| Previous | 199869 Revisions | Next |
| r25361 Tuesday 17th September, 2013 at 06:47:03 UTC by Miodrag Milanović |
|---|
| Cleanups and version bump |
| [hash] | a800_flop.xml amigaocs_flop.xml apple2.xml c64_cart.xml c64_flop.xml copera.xml famicom_cass.xml ibm5140.xml ibm5170.xml megadriv.xml megaduck.xml pc98.xml visicom.xml |
| [src] | version.c |
| [src/emu] | clifront.c divideo.c divideo.h emuopts.c emuopts.h machine.c mame.c memarray.h profiler.h screen.h tilemap.h webengine.c webengine.h |
| [src/emu/cpu] | cpu.mak |
| [src/emu/cpu/cubeqcpu] | cubeqcpu.c |
| [src/emu/cpu/es5510] | es5510.c es5510.h |
| [src/emu/cpu/f8] | f8.c |
| [src/emu/cpu/i8085] | i8085.c |
| [src/emu/cpu/i8089] | i8089.h i8089_channel.c i8089_ops.c |
| [src/emu/cpu/i86] | i186.c i286.c i286.h |
| [src/emu/cpu/i860] | i860.c i860dec.c |
| [src/emu/cpu/i960] | i960.c |
| [src/emu/cpu/jaguar] | jaguar.c |
| [src/emu/cpu/lh5801] | lh5801.c |
| [src/emu/cpu/m37710] | m37710.h |
| [src/emu/cpu/m6800] | m6800.c m6800.h |
| [src/emu/cpu/m68000] | m68k_in.c |
| [src/emu/cpu/mb86233] | mb86233.c |
| [src/emu/cpu/mb88xx] | mb88xx.c mb88xx.h |
| [src/emu/cpu/mc68hc11] | mc68hc11.c |
| [src/emu/cpu/mcs48] | mcs48.c mcs48.h |
| [src/emu/cpu/mcs51] | mcs51.c |
| [src/emu/cpu/minx] | minx.c minx.h |
| [src/emu/cpu/mips] | mips3drc.c |
| [src/emu/cpu/mn10200] | mn10200.c |
| [src/emu/cpu/nec] | v25.c |
| [src/emu/cpu/pic16c5x] | pic16c5x.c |
| [src/emu/cpu/pic16c62x] | pic16c62x.c pic16c62x.h |
| [src/emu/cpu/pps4] | pps4.c |
| [src/emu/cpu/psx] | rcnt.h |
| [src/emu/cpu/rsp] | rspdrc.c |
| [src/emu/cpu/s2650] | s2650.c |
| [src/emu/cpu/sh2] | sh2comn.c sh2comn.h sh2fe.c |
| [src/emu/cpu/tlcs900] | tlcs900.c |
| [src/emu/cpu/tms32082] | dis_mp.c dis_pp.c mp_ops.c tms32082.c tms32082.h |
| [src/emu/cpu/tms34010] | tms34010.c tms34010.h |
| [src/emu/cpu/tms9900] | 99xxcore.h |
| [src/emu/debug] | debugcmd.c debugcpu.c debugcpu.h dvwpoints.c |
| [src/emu/machine] | 40105.c 40105.h 74148.c 74153.c 74153.h 74181.h aicartc.c aicartc.h atahle.c ataintf.c eeprom.c eeprom.h eeprompar.c eeprompar.h eepromser.c eepromser.h generic.c mb87078.h s2636.c s2636.h smc91c9x.h wd_fdc.c |
| [src/emu/sound] | aica.c cdp1864.h esqpump.c esqpump.h multipcm.h okim6376.h s14001a.h sound.mak sp0250.c sp0250.h t6721a.h tms5220.c upd7752.c upd7752.h |
| [src/emu/video] | 315_5124.h dl1416.c hd63484.h huc6260.c huc6261.c i8275.h i8275x.h polynew.h v9938.h |
| [src/lib/formats] | cpis_dsk.c g64_dsk.c |
| [src/lib/web] | mongoose.c mongoose.h |
| [src/lib/web/json] | config.h features.h forwards.h json_batchallocator.h json_tool.h reader.h value.h writer.h |
| [src/lib/zlib] | adler32.c compress.c crc32.c crc32.h deflate.c deflate.h gzclose.c gzguts.h gzlib.c gzread.c gzwrite.c infback.c inffast.c inffixed.h inflate.c inflate.h inftrees.c inftrees.h trees.c trees.h uncompr.c zconf.h zlib.h zutil.c zutil.h |
| [src/mame] | mame.lst |
| [src/mame/audio] | decobsmt.h exidy.c exidy.h exidy440.c galaxian.c leland.c segam1audio.c seibu.c seibu.h t5182.c t5182.h taito_en.c taito_en.h taitosnd.c targ.c |
| [src/mame/drivers] | 20pacgal.c 3x3puzzl.c arcadecl.c atarig42.c atarigt.c atarigx2.c atarisy1.c atarisy2.c badlands.c batman.c berzerk.c bfm_sc1.c blstroid.c cabal.c cave.c cdi.c crystal.c cupidon.c cyberbal.c dambustr.c dblewing.c ddealer.c ddragon.c de_3.c de_3b.c eprom.c exprraid.c firebeat.c freekick.c galaxia.c galaxold.c galpani2.c galpani3.c galpanic.c gticlub.c harddriv.c klax.c ksys573.c laserbas.c malzak.c maygay1b.c mjkjidai.c mlanding.c model2.c mpu5hw.c mustache.c namcond1.c namcos22.c naomi.c nmk16.c offtwall.c panicr.c polepos.c r2dx_v33.c raiden2.c rampart.c relief.c renegade.c sandscrp.c seabattl.c sfbonus.c shanghai.c skimaxx.c skullxbo.c snk68.c stfight.c taito_b.c taito_f3.c taito_x.c taitoair.c taitotx.c taitotz.c tapatune.c thunderj.c toaplan2.c toobin.c topspeed.c trvmadns.c tumbleb.c vamphalf.c vegas.c vicdual.c vindictr.c xybots.c |
| [src/mame/includes] | amiga.h arcadecl.h atarisy1.h cabal.h carpolo.h cd32.h darkmist.h ddragon3.h deadang.h dynduke.h exidy.h exprraid.h galaxia.h gauntlet.h harddriv.h klax.h macrossp.h micro3d.h mjkjidai.h model1.h model2.h mustache.h namcos22.h pgm.h raiden2.h segas32.h snes.h snk6502.h stfight.h taito_b.h taito_x.h toki.h topspeed.h vicdual.h wolfpack.h xybots.h zac2650.h |
| [src/mame/machine] | atarigen.c atarigen.h cd32.c deco104.c deco146.c decocass_tape.h decopincpu.c gaelco3d.c gaelco3d.h maple-dc.c megavdp.c namco62.h naomi.c neoprot.c nmk004.c nmk004.h pgmprot_igs025_igs028.c pgmprot_igs027a_type1.c pgmprot_igs027a_type2.c stfight.c |
| [src/mame/video] | 8080bw.c atarimo.c atarimo.h atarirle.c atarirle.h bfm_adr2.c bfm_adr2.h bfm_dm01.c bfm_dm01.h cave.c ddragon3.c deco16ic.c deco16ic.h gticlub.c k001005.c k001005.h k037122.h kaneko_spr.c mcd212.c namcos2.c namcos22.c powervr2.c powervr2.h segaic16.c segaic16.h snes.c tia.c tia.h toobin.c vrender0.c vrender0.h ygv608.c ygv608.h |
| [src/mess] | mess.lst |
| [src/mess/drivers] | a7800.c abc1600.c apple2.c apricot.c cat.c cosmicos.c dccons.c dsb46.c esq5505.c kaypro.c kyocera.c lola8a.c mac.c megadriv.c mtx.c octopus.c onyx.c pc9801.c rainbow.c sbc6510.c segapico.c studio2.c supracan.c v1050.c zaurus.c |
| [src/mess/includes] | aim65.h amstr_pc.h dccons.h md_cons.h osi.h rmnimbus.h studio2.h |
| [src/mess/layout] | rainbow.lay |
| [src/mess/machine] | 64h156.c a2applicard.c abc1600mac.c abc1600mac.h c2040.c c64_nl10.h comx_fd.c dccons.c e05a03.c e05a03.h hardbox.c hardbox.h isa_wd1002a_wx1.c isa_xtide.c mac.c mackbd.c mackbd.h micropolis.c micropolis.h mpu401.c mpu401.h pc_lpt.h rmnimbus.c |
| [src/mess/machine/c64] | magic_voice.c magic_voice.h music64.h |
| [src/mess/machine/ti99] | spchsyn.c videowrp.c |
| [src/mess/video] | 733_asr.h 911_vdt.h abc1600.c abc1600.h cirrus.h gb_lcd.h k1ge.h nubus_m2video.c pds30_procolor816.c vtvideo.c |
| [src/osd] | osdcomm.h |
| [src/osd/portmedia] | pmmidi.c |
| [src/osd/sdl] | debugqtbreakpointswindow.c |
| [src/osd/windows] | d3dhlsl.h d3dintf.h drawd3d.h winmain.c winmain.h winptty.c |
| [src/tools] | jedutil.c |
| r25360 | r25361 | |
|---|---|---|
| 193 | 193 | </dataarea> |
| 194 | 194 | </part> |
| 195 | 195 | </software> |
| 196 | ||
| 196 | ||
| 197 | 197 | <software name="2ndspace"> |
| 198 | 198 | <description>2nd Space</description> |
| 199 | 199 | <year>1993</year> |
| r25360 | r25361 | |
| 206 | 206 | </dataarea> |
| 207 | 207 | </part> |
| 208 | 208 | </software> |
| 209 | ||
| 209 | ||
| 210 | 210 | <software name="trapturn"> |
| 211 | 211 | <description>Trap & Turn</description> |
| 212 | 212 | <year>1993</year> |
| r25360 | r25361 | |
| 219 | 219 | </dataarea> |
| 220 | 220 | </part> |
| 221 | 221 | </software> |
| 222 | ||
| 222 | ||
| 223 | 223 | <software name="bombdisp"> |
| 224 | 224 | <description>Bomb Disposer</description> |
| 225 | 225 | <year>1993</year> |
| r25360 | r25361 | |
| 232 | 232 | </dataarea> |
| 233 | 233 | </part> |
| 234 | 234 | </software> |
| 235 | ||
| 235 | ||
| 236 | 236 | <software name="mmaze"> |
| 237 | 237 | <description>Magic Maze</description> |
| 238 | 238 | <year>1993</year> |
| r25360 | r25361 | |
| 245 | 245 | </dataarea> |
| 246 | 246 | </part> |
| 247 | 247 | </software> |
| 248 | ||
| 248 | ||
| 249 | 249 | <software name="vex"> |
| 250 | 250 | <description>Vex</description> |
| 251 | 251 | <year>1993</year> |
| r25360 | r25361 | |
|---|---|---|
| 2 | 2 | <!DOCTYPE softwarelist SYSTEM "softwarelist.dtd"> |
| 3 | 3 | <!-- |
| 4 | 4 | |
| 5 | Atari 400 / 800 floppies | |
| 6 | (skeleton list) | |
| 7 | ||
| 8 | note: many 'original' floppy images are in .atx format, whereas cracked / unprotected ones are .atr format | |
| 9 | .atx is unsupported, although apparently has been reverse engineered (insert info link here) | |
| 10 | There are also images in .xex format? | |
| 5 | Atari 400 / 800 floppies | |
| 6 | (skeleton list) | |
| 11 | 7 | |
| 8 | note: many 'original' floppy images are in .atx format, whereas cracked / unprotected ones are .atr format | |
| 9 | .atx is unsupported, although apparently has been reverse engineered (insert info link here) | |
| 10 | There are also images in .xex format? | |
| 11 | ||
| 12 | 12 | --> |
| 13 | 13 | |
| 14 | 14 | <softwarelist name="a800_flop" description="Atari 400 / 800 floppy disks"> |
| r25360 | r25361 | |
| 23 | 23 | </dataarea> |
| 24 | 24 | </part> |
| 25 | 25 | </software> |
| 26 | ||
| 27 | ||
| 26 | ||
| 27 | ||
| 28 | 28 | </softwarelist> |
| r25360 | r25361 | |
|---|---|---|
| 20935 | 20935 | <dataarea name="flop" size="1049612"> |
| 20936 | 20936 | <rom name="hugo - pa nye eventyr 2 (denmark) (disk 1 of 6).ipf" size="1049612" crc="47ebcd60" sha1="e7689d9fab1d1eabb204121633ad0fad87100e86" offset="0"/> |
| 20937 | 20937 | </dataarea> |
| 20938 | </part> | |
| 20938 | </part> | |
| 20939 | 20939 | <part name="flop2" interface="floppy_3_5"> |
| 20940 | 20940 | <feature name="part_id" value="Disk 2" /> |
| 20941 | 20941 | <dataarea name="flop" size="1049612"> |
| r25360 | r25361 | |
|---|---|---|
| 13 | 13 | <description>Advanced Diagnostics for the IBM AT (v2.07)</description> |
| 14 | 14 | <year>1985</year> |
| 15 | 15 | <publisher>IBM</publisher> |
| 16 | ||
| 16 | ||
| 17 | 17 | <part name="flop1" interface="floppy_5_25"> |
| 18 | 18 | <dataarea name="flop" size="368640"> |
| 19 | 19 | <rom name="atad_207.img" size="368640" crc="43d0783b" sha1="63a48f7dd92382356222ed2030cd4b900d09de3d" offset="0" /> |
| r25360 | r25361 | |
|---|---|---|
| 52 | 52 | </dataarea> |
| 53 | 53 | </part> |
| 54 | 54 | </software> |
| 55 | ||
| 55 | ||
| 56 | 56 | </softwarelist> |
| r25360 | r25361 | |
|---|---|---|
| 2 | 2 | <!DOCTYPE softwarelist SYSTEM "softwarelist.dtd"> |
| 3 | 3 | <softwarelist name="famicom_cass" description="Nintendo Famicom Family BASIC cassettes"> |
| 4 | 4 | |
| 5 | <!-- | |
| 5 | <!-- | |
| 6 | 6 | |
| 7 | 7 | This list is a bit peculiar, since it contains cassette images obtained on a FC |
| 8 | 8 | by saving BASIC programs typed in from magazines, books, or homebrew |
| r25360 | r25361 | |
|---|---|---|
| 1085 | 1085 | <rom name="cmk49.d64" size="174848" crc="5ef6645a" sha1="c9afd892731ebd68bc67bd8c6c84cbb1aa5e874d" offset="0" /> |
| 1086 | 1086 | </dataarea> |
| 1087 | 1087 | </part> |
| 1088 | </software> | |
| 1088 | </software> | |
| 1089 | 1089 | |
| 1090 | 1090 | <!-- Test --> |
| 1091 | 1091 |
| r25360 | r25361 | |
|---|---|---|
| 1 | 1 | <?xml version="1.0"?> |
| 2 | 2 | <!DOCTYPE softwarelist SYSTEM "softwarelist.dtd"> |
| 3 | <softwarelist name="pc98" description="NEC PC-9801 disk images"> | |
| 3 | <softwarelist name="pc98" description="NEC PC-9801 disk images"> | |
| 4 | 4 | |
| 5 | 5 | <software name="pc98dosd"> |
| 6 | 6 | <description>PC-98DO+ System Disk</description> |
| r25360 | r25361 | |
| 98 | 98 | <!-- |
| 99 | 99 | PC-98xx NEW (as per 31 July 2013) software list starts here. |
| 100 | 100 | TODO: |
| 101 | - Manually parse the list, add publisher / year where possible, fix floppy order (i.e. if a floppy is labeled opening.fdi or system.fdi is the one | |
| 101 | - Manually parse the list, add publisher / year where possible, fix floppy order (i.e. if a floppy is labeled opening.fdi or system.fdi is the one | |
| 102 | 102 | required at PC-98xx boot), label ALL userX.fdi images as bad dump, test all games and double check support status, fix zipnames (most sucks right now), |
| 103 | 103 | identify anything that has a size different than 1265664 (== 3'5" floppy image), document any unorthodox way for running a given sw. |
| 104 | 104 | |
| r25360 | r25361 | |
| 145 | 145 | <dataarea name="flop" size="1265664"> |
| 146 | 146 | <rom name="2069ad_b.fdi" size="1265664" crc="3e596802" sha1="05633e7847be623f1fdc8e4c4cbaa91dd7ac8a68" offset="0" /> |
| 147 | 147 | </dataarea> |
| 148 | </part> | |
| 148 | </part> | |
| 149 | 149 | <part name="flop3" interface="floppy_5_25"> |
| 150 | 150 | <dataarea name="flop" size="1265664"> |
| 151 | 151 | <rom name="2069ad_c.fdi" size="1265664" crc="25c601a5" sha1="a6b6b7096fedf6a0536fee0b380e976ebd0eb63b" offset="0" /> |
| 152 | 152 | </dataarea> |
| 153 | </part> | |
| 153 | </part> | |
| 154 | 154 | </software> |
| 155 | 155 | |
| 156 | 156 | <software name="31iwayu" supported="yes"> |
| r25360 | r25361 | |
| 162 | 162 | <rom name="disk a.fdi" size="1265664" crc="7131e56e" sha1="2070ebdd0acb1a50d77cc73368b448fe05096a3e" offset="0" /> |
| 163 | 163 | </dataarea> |
| 164 | 164 | </part> |
| 165 | ||
| 165 | ||
| 166 | 166 | <part name="flop2" interface="floppy_5_25"> |
| 167 | 167 | <dataarea name="flop" size="1265664"> |
| 168 | 168 | <rom name="disk b.fdi" size="1265664" crc="54ed018b" sha1="69aaf92e5545a26fe62e4acd5334249173b0e06b" offset="0" /> |
| r25360 | r25361 | |
| 209 | 209 | </dataarea> |
| 210 | 210 | </part> |
| 211 | 211 | <!-- |
| 212 | ||
| 212 | Note: all of these are expansions (and have no clue about how to load them either) | |
| 213 | 213 | --> |
| 214 | 214 | <part name="flop2" interface="floppy_5_25"> |
| 215 | 215 | <dataarea name="flop" size="1265664"> |
| r25360 | r25361 | |
| 833 | 833 | |
| 834 | 834 | <software name="add_pdrk"> |
| 835 | 835 | <description>AD&D Pools of Darkness</description> |
| 836 | <year>19??</year> | |
| 837 | <publisher><unknown></publisher> | |
| 838 | <part name="flop1" interface="floppy_5_25"> | |
| 839 | <dataarea name="flop" size="1265664"> | |
| 840 | <rom name="diska.fdi" size="1265664" crc="a40becba" sha1="3c65e5ab1f95d5f9863681c472b8c73927e0a2c2" offset="0" /> | |
| 841 | </dataarea> | |
| 842 | </part> | |
| 836 | <year>19??</year> | |
| 837 | <publisher><unknown></publisher> | |
| 838 | <part name="flop1" interface="floppy_5_25"> | |
| 839 | <dataarea name="flop" size="1265664"> | |
| 840 | <rom name="diska.fdi" size="1265664" crc="a40becba" sha1="3c65e5ab1f95d5f9863681c472b8c73927e0a2c2" offset="0" /> | |
| 841 | </dataarea> | |
| 842 | </part> | |
| 843 | 843 | <part name="flop2" interface="floppy_5_25"> |
| 844 | <dataarea name="flop" size="1265664"> | |
| 845 | <rom name="diskb.fdi" size="1265664" crc="2fb75bcb" sha1="78df14162d4fbd9e6c8f6a67e00d3aed3dd02bc7" offset="0" /> | |
| 846 | </dataarea> | |
| 847 | </part> | |
| 844 | <dataarea name="flop" size="1265664"> | |
| 845 | <rom name="diskb.fdi" size="1265664" crc="2fb75bcb" sha1="78df14162d4fbd9e6c8f6a67e00d3aed3dd02bc7" offset="0" /> | |
| 846 | </dataarea> | |
| 847 | </part> | |
| 848 | 848 | <part name="flop3" interface="floppy_5_25"> |
| 849 | <dataarea name="flop" size="1265664"> | |
| 850 | <rom name="opening.fdi" size="1265664" crc="11cf2229" sha1="abf3bed693797d9bfecb1b7dc42eadcfb8a14641" offset="0" /> | |
| 851 | </dataarea> | |
| 852 | </part> | |
| 853 | </software> | |
| 849 | <dataarea name="flop" size="1265664"> | |
| 850 | <rom name="opening.fdi" size="1265664" crc="11cf2229" sha1="abf3bed693797d9bfecb1b7dc42eadcfb8a14641" offset="0" /> | |
| 851 | </dataarea> | |
| 852 | </part> | |
| 853 | </software> | |
| 854 | 854 | |
| 855 | 855 | <software name="add_ssil" supported="no"> |
| 856 | 856 | <description>AD&D Secret of the Silver Blades</description> |
| r25360 | r25361 | |
| 882 | 882 | <rom name="user.d88" size="0x138fb0" crc="efd89d91" sha1="c243ec20af65ea9f612926c2c8ce868750a076e4" offset="0" status="baddump" /> |
| 883 | 883 | </dataarea> |
| 884 | 884 | </part> |
| 885 | </software> | |
| 885 | </software> | |
| 886 | 886 | |
| 887 | 887 | <software name="advanp2p"> |
| 888 | 888 | <description>Advanced Power Dolls 2 Premium Disk</description> |
| r25360 | r25361 | |
| 912 | 912 | </part> |
| 913 | 913 | <!-- hacked (and working since it's 2hd floppy) set, not going to be supported however |
| 914 | 914 | <part name="flop3" interface="floppy_5_25"> |
| 915 | <dataarea name="flop" size="0x1093f0"> | |
| 916 | <rom name="adventureland 2hd.d88" size="0x1093f0" crc="dfe46669" sha1="ee0e6fae3553f8b60d515ba5c0bfdbe56cb7df16" offset="0" /> | |
| 917 | </dataarea> | |
| 915 | <dataarea name="flop" size="0x1093f0"> | |
| 916 | <rom name="adventureland 2hd.d88" size="0x1093f0" crc="dfe46669" sha1="ee0e6fae3553f8b60d515ba5c0bfdbe56cb7df16" offset="0" /> | |
| 917 | </dataarea> | |
| 918 | 918 | </part> |
| 919 | 919 | --> |
| 920 | 920 | </software> |
| r25360 | r25361 | |
| 1645 | 1645 | </part> |
| 1646 | 1646 | </software> |
| 1647 | 1647 | <!-- |
| 1648 | <software name="applec4"> | |
| 1649 | <description> Apple Club - Data Shuu #04 - Tonari no Oneesan Hen</description> | |
| 1650 | <year>19??</year> | |
| 1651 | <publisher><unknown></publisher> | |
| 1652 | <part name="flop1" interface="floppy_5_25"> | |
| 1653 | <dataarea name="flop" size="1265664"> | |
| 1654 | <rom name="?pc98????????1 ????#4.fdi" size="1265664" crc=" ***" sha1="20e87b43 ?CRC32*Apple Club 1\aplclub1.FD" offset="0" /> | |
| 1655 | </dataarea> | |
| 1656 | </part> | |
| 1657 | </software> | |
| 1648 | <software name="applec4"> | |
| 1649 | <description> Apple Club - Data Shuu #04 - Tonari no Oneesan Hen</description> | |
| 1650 | <year>19??</year> | |
| 1651 | <publisher><unknown></publisher> | |
| 1652 | <part name="flop1" interface="floppy_5_25"> | |
| 1653 | <dataarea name="flop" size="1265664"> | |
| 1654 | <rom name="?pc98????????1 ????#4.fdi" size="1265664" crc=" ***" sha1="20e87b43 ?CRC32*Apple Club 1\aplclub1.FD" offset="0" /> | |
| 1655 | </dataarea> | |
| 1656 | </part> | |
| 1657 | </software> | |
| 1658 | 1658 | --> |
| 1659 | 1659 | <software name="applecl"> |
| 1660 | 1660 | <description>Apple Club 1 - Kinjirareta Asobi Series</description> |
| r25360 | r25361 | |
| 2041 | 2041 | </dataarea> |
| 2042 | 2042 | </part> |
| 2043 | 2043 | </software> |
| 2044 | ||
| 2044 | ||
| 2045 | 2045 | <software name="asokono"> |
| 2046 | 2046 | <description>Asoko no Koufuku - Yamamoto-san-chi no Baai ni Okeru Asoko no Fukou ni Tsuite</description> |
| 2047 | 2047 | <year>19??</year> |
| r25360 | r25361 | |
| 2638 | 2638 | </dataarea> |
| 2639 | 2639 | </part> |
| 2640 | 2640 | </software> |
| 2641 | ||
| 2641 | ||
| 2642 | 2642 | <software name="bodyins"> |
| 2643 | 2643 | <description>Body Inspection in Belloncho</description> |
| 2644 | 2644 | <year>19??</year> |
| r25360 | r25361 | |
| 2664 | 2664 | <rom name="bokosuka.d88" size="0x10f760" crc="d5da4869" sha1="1fd6124180be8f20acd188702e3b9f9c2d128428" offset="0" /> |
| 2665 | 2665 | </dataarea> |
| 2666 | 2666 | </part> |
| 2667 | </software> | |
| 2667 | </software> | |
| 2668 | 2668 | |
| 2669 | 2669 | <software name="bomberq"> |
| 2670 | 2670 | <description>Bomber Quest</description> |
| r25360 | r25361 | |
| 3093 | 3093 | </dataarea> |
| 3094 | 3094 | </part> |
| 3095 | 3095 | </software> |
| 3096 | ||
| 3096 | ||
| 3097 | 3097 | <software name="burningd"> |
| 3098 | 3098 | <description>Burning Dragon</description> |
| 3099 | 3099 | <year>19??</year> |
| r25360 | r25361 | |
| 3257 | 3257 | </dataarea> |
| 3258 | 3258 | </part> |
| 3259 | 3259 | </software> |
| 3260 | ||
| 3260 | ||
| 3261 | 3261 | <software name="carata" cloneof="carat"> |
| 3262 | 3262 | <description>Carat - Magical Blocks(another)</description> |
| 3263 | 3263 | <year>19??</year> |
| r25360 | r25361 | |
| 4275 | 4275 | </part> |
| 4276 | 4276 | </software> |
| 4277 | 4277 | |
| 4278 | <!-- | |
| 4278 | <!-- | |
| 4279 | 4279 | Presumably copy protection floppy, to be used with CD-Rom |
| 4280 | 4280 | --> |
| 4281 | 4281 | <software name="debut"> |
| r25360 | r25361 | |
| 5098 | 5098 | </part> |
| 5099 | 5099 | </software> |
| 5100 | 5100 | |
| 5101 | ||
| 5101 | ||
| 5102 | 5102 | <software name="dragone"> |
| 5103 | 5103 | <description>Dragon Egg</description> |
| 5104 | 5104 | <year>19??</year> |
| r25360 | r25361 | |
| 5527 | 5527 | |
| 5528 | 5528 | <!-- |
| 5529 | 5529 | TODO: missing install disks |
| 5530 | <software name="eveber"> | |
| 5531 | <description>Eve - Burst Error</description> | |
| 5532 | <year>19??</year> | |
| 5533 | <publisher><unknown></publisher> | |
| 5534 | <part name="flop1" interface="floppy_5_25"> | |
| 5535 | <dataarea name="flop" size="1265664"> | |
| 5536 | <rom name="dos62.fdi" size="1265664" crc="678b88a7" sha1="480dee4a4df0c588416b0895057caeba862eea7f" offset="0" /> | |
| 5537 | </dataarea> | |
| 5538 | </part> | |
| 5539 | </software> | |
| 5530 | <software name="eveber"> | |
| 5531 | <description>Eve - Burst Error</description> | |
| 5532 | <year>19??</year> | |
| 5533 | <publisher><unknown></publisher> | |
| 5534 | <part name="flop1" interface="floppy_5_25"> | |
| 5535 | <dataarea name="flop" size="1265664"> | |
| 5536 | <rom name="dos62.fdi" size="1265664" crc="678b88a7" sha1="480dee4a4df0c588416b0895057caeba862eea7f" offset="0" /> | |
| 5537 | </dataarea> | |
| 5538 | </part> | |
| 5539 | </software> | |
| 5540 | 5540 | --> |
| 5541 | 5541 | |
| 5542 | 5542 | <software name="f14fd"> |
| r25360 | r25361 | |
| 5873 | 5873 | |
| 5874 | 5874 | <!-- same as all bishoujo extra disk 2 --> |
| 5875 | 5875 | <!-- |
| 5876 | <software name="floppyb2"> | |
| 5877 | <description>Floppy Bunko 17 - All Bishoujo Art Graphics Vol. 2</description> | |
| 5878 | <year>19??</year> | |
| 5879 | <publisher><unknown></publisher> | |
| 5880 | <part name="flop1" interface="floppy_5_25"> | |
| 5881 | <dataarea name="flop" size="1265664"> | |
| 5882 | <rom name="disk_2.fdi" size="1265664" crc="ee12585b" sha1="941abd888e3ce84c072a28f4cd73b15cb6c8945b" offset="0" /> | |
| 5883 | </dataarea> | |
| 5884 | </part> | |
| 5885 | </software> | |
| 5876 | <software name="floppyb2"> | |
| 5877 | <description>Floppy Bunko 17 - All Bishoujo Art Graphics Vol. 2</description> | |
| 5878 | <year>19??</year> | |
| 5879 | <publisher><unknown></publisher> | |
| 5880 | <part name="flop1" interface="floppy_5_25"> | |
| 5881 | <dataarea name="flop" size="1265664"> | |
| 5882 | <rom name="disk_2.fdi" size="1265664" crc="ee12585b" sha1="941abd888e3ce84c072a28f4cd73b15cb6c8945b" offset="0" /> | |
| 5883 | </dataarea> | |
| 5884 | </part> | |
| 5885 | </software> | |
| 5886 | 5886 | --> |
| 5887 | 5887 | |
| 5888 | 5888 | <!-- same as all bishoujo extra disk 3 --> |
| 5889 | 5889 | <!-- |
| 5890 | <software name="floppyb3"> | |
| 5891 | <description>Floppy Bunko 20 - All Bishoujo Art Graphics Vol. 3</description> | |
| 5892 | <year>19??</year> | |
| 5893 | <publisher><unknown></publisher> | |
| 5894 | <part name="flop1" interface="floppy_5_25"> | |
| 5895 | <dataarea name="flop" size="1265664"> | |
| 5896 | <rom name="disk_3.fdi" size="1265664" crc="30ae9567" sha1="e46a1cd8fa82a99a497048001b2e6d0268c4a5d6" offset="0" /> | |
| 5897 | </dataarea> | |
| 5898 | </part> | |
| 5899 | </software> | |
| 5890 | <software name="floppyb3"> | |
| 5891 | <description>Floppy Bunko 20 - All Bishoujo Art Graphics Vol. 3</description> | |
| 5892 | <year>19??</year> | |
| 5893 | <publisher><unknown></publisher> | |
| 5894 | <part name="flop1" interface="floppy_5_25"> | |
| 5895 | <dataarea name="flop" size="1265664"> | |
| 5896 | <rom name="disk_3.fdi" size="1265664" crc="30ae9567" sha1="e46a1cd8fa82a99a497048001b2e6d0268c4a5d6" offset="0" /> | |
| 5897 | </dataarea> | |
| 5898 | </part> | |
| 5899 | </software> | |
| 5900 | 5900 | --> |
| 5901 | 5901 | |
| 5902 | 5902 | <software name="foxy"> |
| r25360 | r25361 | |
| 6429 | 6429 | <!-- |
| 6430 | 6430 | Fake disk? |
| 6431 | 6431 | |
| 6432 | <software name="golflin"> | |
| 6433 | <description>Golf Links 386 Pro</description> | |
| 6434 | <year>19??</year> | |
| 6435 | <publisher><unknown></publisher> | |
| 6436 | <part name="flop1" interface="floppy_5_25"> | |
| 6437 | <dataarea name="flop" size="1265664"> | |
| 6438 | <rom name="golf links 386 pro anex86 cd & hd boot disk.fdi" size="1265664" crc="05559a9e" sha1="77510219ec879af55a90da092e268c5fa4b0257c" offset="0" /> | |
| 6439 | </dataarea> | |
| 6440 | </part> | |
| 6441 | </software> | |
| 6432 | <software name="golflin"> | |
| 6433 | <description>Golf Links 386 Pro</description> | |
| 6434 | <year>19??</year> | |
| 6435 | <publisher><unknown></publisher> | |
| 6436 | <part name="flop1" interface="floppy_5_25"> | |
| 6437 | <dataarea name="flop" size="1265664"> | |
| 6438 | <rom name="golf links 386 pro anex86 cd & hd boot disk.fdi" size="1265664" crc="05559a9e" sha1="77510219ec879af55a90da092e268c5fa4b0257c" offset="0" /> | |
| 6439 | </dataarea> | |
| 6440 | </part> | |
| 6441 | </software> | |
| 6442 | 6442 | --> |
| 6443 | 6443 | <software name="golflpr"> |
| 6444 | 6444 | <description>Golf Links Champion Course Pinehurst Resort and Country Ciub</description> |
| r25360 | r25361 | |
| 6814 | 6814 | </software> |
| 6815 | 6815 | |
| 6816 | 6816 | <!-- |
| 6817 | Game is named "image", with lowercase i on title screen | |
| 6817 | Game is named "image", with lowercase i on title screen | |
| 6818 | 6818 | --> |
| 6819 | 6819 | <software name="image"> |
| 6820 | 6820 | <description>image</description> |
| r25360 | r25361 | |
| 7310 | 7310 | |
| 7311 | 7311 | <!-- |
| 7312 | 7312 | TODO: other two disks, in .nfd format |
| 7313 | <software name="kawaisou"> | |
| 7314 | <description>Kawaisou Monogatari</description> | |
| 7315 | <year>19??</year> | |
| 7316 | <publisher><unknown></publisher> | |
| 7317 | <part name="flop1" interface="floppy_5_25"> | |
| 7318 | <dataarea name="flop" size="1265664"> | |
| 7319 | <rom name="user.fdi" size="1265664" crc="6c424c81" sha1="5feb465c5178534a575b555eeeabacae36b9f650" offset="0" status="baddump" /> | |
| 7320 | </dataarea> | |
| 7321 | </part> | |
| 7322 | </software> | |
| 7313 | <software name="kawaisou"> | |
| 7314 | <description>Kawaisou Monogatari</description> | |
| 7315 | <year>19??</year> | |
| 7316 | <publisher><unknown></publisher> | |
| 7317 | <part name="flop1" interface="floppy_5_25"> | |
| 7318 | <dataarea name="flop" size="1265664"> | |
| 7319 | <rom name="user.fdi" size="1265664" crc="6c424c81" sha1="5feb465c5178534a575b555eeeabacae36b9f650" offset="0" status="baddump" /> | |
| 7320 | </dataarea> | |
| 7321 | </part> | |
| 7322 | </software> | |
| 7323 | 7323 | --> |
| 7324 | 7324 | <software name="kerakera"> |
| 7325 | 7325 | <description>Kerakera-sei</description> |
| r25360 | r25361 | |
| 8279 | 8279 | </dataarea> |
| 8280 | 8280 | </part> |
| 8281 | 8281 | </software> |
| 8282 | ||
| 8282 | ||
| 8283 | 8283 | <software name="madouars"> |
| 8284 | 8284 | <description>Madou Monogatari A-R-S</description> |
| 8285 | 8285 | <year>19??</year> |
| r25360 | r25361 | |
| 8465 | 8465 | </software> |
| 8466 | 8466 | |
| 8467 | 8467 | <!-- TODO: another .nfd floppy used |
| 8468 | <software name="mtaikai"> | |
| 8469 | <description>Mahjong Taikai</description> | |
| 8470 | <year>19??</year> | |
| 8471 | <publisher><unknown></publisher> | |
| 8472 | <part name="flop1" interface="floppy_5_25"> | |
| 8473 | <dataarea name="flop" size="1265664"> | |
| 8474 | <rom name="user.fdi" size="1265664" crc="fca4122d" sha1="6797330e0237af84f1f4f112704034281834c97b" offset="0" status="baddump" /> | |
| 8475 | </dataarea> | |
| 8476 | </part> | |
| 8477 | </software> | |
| 8468 | <software name="mtaikai"> | |
| 8469 | <description>Mahjong Taikai</description> | |
| 8470 | <year>19??</year> | |
| 8471 | <publisher><unknown></publisher> | |
| 8472 | <part name="flop1" interface="floppy_5_25"> | |
| 8473 | <dataarea name="flop" size="1265664"> | |
| 8474 | <rom name="user.fdi" size="1265664" crc="fca4122d" sha1="6797330e0237af84f1f4f112704034281834c97b" offset="0" status="baddump" /> | |
| 8475 | </dataarea> | |
| 8476 | </part> | |
| 8477 | </software> | |
| 8478 | 8478 | --> |
| 8479 | 8479 | <software name="mahoush"> |
| 8480 | 8480 | <description>Mahou Shoujo Rina</description> |
| r25360 | r25361 | |
| 8736 | 8736 | </software> |
| 8737 | 8737 | |
| 8738 | 8738 | <!-- same as disk 02 fugasel1 |
| 8739 | <software name="mazeque"> | |
| 8740 | <description>Maze Quest</description> | |
| 8741 | <year>19??</year> | |
| 8742 | <publisher><unknown></publisher> | |
| 8743 | <part name="flop1" interface="floppy_5_25"> | |
| 8744 | <dataarea name="flop" size="1265664"> | |
| 8745 | <rom name="maze quest.fdi" size="1265664" crc="3949e01a" sha1="9ee3c3dac883036375c69192fd98af11695ffea8" offset="0" /> | |
| 8746 | </dataarea> | |
| 8747 | </part> | |
| 8748 | </software> | |
| 8739 | <software name="mazeque"> | |
| 8740 | <description>Maze Quest</description> | |
| 8741 | <year>19??</year> | |
| 8742 | <publisher><unknown></publisher> | |
| 8743 | <part name="flop1" interface="floppy_5_25"> | |
| 8744 | <dataarea name="flop" size="1265664"> | |
| 8745 | <rom name="maze quest.fdi" size="1265664" crc="3949e01a" sha1="9ee3c3dac883036375c69192fd98af11695ffea8" offset="0" /> | |
| 8746 | </dataarea> | |
| 8747 | </part> | |
| 8748 | </software> | |
| 8749 | 8749 | --> |
| 8750 | 8750 | |
| 8751 | 8751 | <software name="meikyuu"> |
| r25360 | r25361 | |
| 9072 | 9072 | |
| 9073 | 9073 | <!-- |
| 9074 | 9074 | Omake disk? |
| 9075 | <software name="mime"> | |
| 9076 | <description>Mime</description> | |
| 9077 | <year>19??</year> | |
| 9078 | <publisher><unknown></publisher> | |
| 9079 | <part name="flop1" interface="floppy_5_25"> | |
| 9080 | <dataarea name="flop" size="1265664"> | |
| 9081 | <rom name="special.fdi" size="1265664" crc="7a3b8749" sha1="2ed561501500af290bd09e09e523d934c9ba7b5c" offset="0" /> | |
| 9082 | </dataarea> | |
| 9083 | </part> | |
| 9084 | </software> | |
| 9075 | <software name="mime"> | |
| 9076 | <description>Mime</description> | |
| 9077 | <year>19??</year> | |
| 9078 | <publisher><unknown></publisher> | |
| 9079 | <part name="flop1" interface="floppy_5_25"> | |
| 9080 | <dataarea name="flop" size="1265664"> | |
| 9081 | <rom name="special.fdi" size="1265664" crc="7a3b8749" sha1="2ed561501500af290bd09e09e523d934c9ba7b5c" offset="0" /> | |
| 9082 | </dataarea> | |
| 9083 | </part> | |
| 9084 | </software> | |
| 9085 | 9085 | --> |
| 9086 | 9086 | |
| 9087 | 9087 | <software name="mink01"> |
| r25360 | r25361 | |
| 9222 | 9222 | </part> |
| 9223 | 9223 | </software> |
| 9224 | 9224 | |
| 9225 | <!-- | |
| 9225 | <!-- | |
| 9226 | 9226 | Requires MS-DOS 5.00H plus an unknown procedure (HDD install?) |
| 9227 | 9227 | --> |
| 9228 | 9228 | <software name="gundamao" supported="no"> |
| r25360 | r25361 | |
| 9753 | 9753 | </part> |
| 9754 | 9754 | </software> |
| 9755 | 9755 | |
| 9756 | <!-- | |
| 9756 | <!-- | |
| 9757 | 9757 | Other three disks, in nfd format |
| 9758 | <software name="n88bas61"> | |
| 9759 | <description>N88 BASIC v6.1</description> | |
| 9760 | <year>19??</year> | |
| 9761 | <publisher><unknown></publisher> | |
| 9762 | <part name="flop1" interface="floppy_5_25"> | |
| 9763 | <dataarea name="flop" size="1265664"> | |
| 9764 | <rom name="rx_train.fdi" size="1265664" crc="607b85f8" sha1="0d2fdf6f0550e50127b27b42b470ba25b305239c" offset="0" /> | |
| 9765 | </dataarea> | |
| 9766 | </part> | |
| 9767 | </software> | |
| 9758 | <software name="n88bas61"> | |
| 9759 | <description>N88 BASIC v6.1</description> | |
| 9760 | <year>19??</year> | |
| 9761 | <publisher><unknown></publisher> | |
| 9762 | <part name="flop1" interface="floppy_5_25"> | |
| 9763 | <dataarea name="flop" size="1265664"> | |
| 9764 | <rom name="rx_train.fdi" size="1265664" crc="607b85f8" sha1="0d2fdf6f0550e50127b27b42b470ba25b305239c" offset="0" /> | |
| 9765 | </dataarea> | |
| 9766 | </part> | |
| 9767 | </software> | |
| 9768 | 9768 | --> |
| 9769 | 9769 | |
| 9770 | 9770 | <software name="nadiamw"> |
| r25360 | r25361 | |
| 9780 | 9780 | |
| 9781 | 9781 | <!-- |
| 9782 | 9782 | other two disks |
| 9783 | <software name="narumah"> | |
| 9784 | <description>Naru Mahjong</description> | |
| 9785 | <year>19??</year> | |
| 9786 | <publisher><unknown></publisher> | |
| 9787 | <part name="flop1" interface="floppy_5_25"> | |
| 9788 | <dataarea name="flop" size="1265664"> | |
| 9789 | <rom name="disk01.fdi" size="1265664" crc="d2db97c6" sha1="06910b3812d6efbac4f0b6adb9767397f2b590d7" offset="0" /> | |
| 9790 | </dataarea> | |
| 9791 | </part> | |
| 9792 | </software> | |
| 9783 | <software name="narumah"> | |
| 9784 | <description>Naru Mahjong</description> | |
| 9785 | <year>19??</year> | |
| 9786 | <publisher><unknown></publisher> | |
| 9787 | <part name="flop1" interface="floppy_5_25"> | |
| 9788 | <dataarea name="flop" size="1265664"> | |
| 9789 | <rom name="disk01.fdi" size="1265664" crc="d2db97c6" sha1="06910b3812d6efbac4f0b6adb9767397f2b590d7" offset="0" /> | |
| 9790 | </dataarea> | |
| 9791 | </part> | |
| 9792 | </software> | |
| 9793 | 9793 | --> |
| 9794 | 9794 | |
| 9795 | 9795 | <software name="natsudam"> |
| r25360 | r25361 | |
| 9834 | 9834 | </dataarea> |
| 9835 | 9835 | </part> |
| 9836 | 9836 | </software> |
| 9837 | ||
| 9837 | ||
| 9838 | 9838 | <software name="nazopds7"> |
| 9839 | 9839 | <description>Nazo Puyo (off DS7)</description> |
| 9840 | 9840 | <year>19??</year> |
| r25360 | r25361 | |
| 12152 | 12152 | </part> |
| 12153 | 12153 | </software> |
| 12154 | 12154 | <!-- |
| 12155 | <software name="rougeno"> | |
| 12156 | <description>Rouge no Densetsu (hdi)</description> | |
| 12157 | <year>19??</year> | |
| 12158 | <publisher><unknown></publisher> | |
| 12159 | <part name="flop1" interface="floppy_5_25"> | |
| 12160 | <dataarea name="flop" size="1265664"> | |
| 12161 | <rom name="kidou.fdi" size="1265664" crc="e0b52ce7" sha1="00ed12fdff1986986e347343d9176f6205d5d87c" offset="0" /> | |
| 12162 | </dataarea> | |
| 12163 | </part> | |
| 12164 | </software> | |
| 12155 | <software name="rougeno"> | |
| 12156 | <description>Rouge no Densetsu (hdi)</description> | |
| 12157 | <year>19??</year> | |
| 12158 | <publisher><unknown></publisher> | |
| 12159 | <part name="flop1" interface="floppy_5_25"> | |
| 12160 | <dataarea name="flop" size="1265664"> | |
| 12161 | <rom name="kidou.fdi" size="1265664" crc="e0b52ce7" sha1="00ed12fdff1986986e347343d9176f6205d5d87c" offset="0" /> | |
| 12162 | </dataarea> | |
| 12163 | </part> | |
| 12164 | </software> | |
| 12165 | 12165 | --> |
| 12166 | 12166 | <software name="roundwar"> |
| 12167 | 12167 | <description>Round Warrior</description> |
| r25360 | r25361 | |
| 12763 | 12763 | |
| 12764 | 12764 | <!-- |
| 12765 | 12765 | Same as Police Quest 2 - Quest for Glory stand-alone disks |
| 12766 | <software name="sierradp"> | |
| 12767 | <description>Sierra 3D AVG Double Pack - Quest for Glory & Police Quest 2</description> | |
| 12768 | <year>19??</year> | |
| 12769 | <publisher><unknown></publisher> | |
| 12770 | <part name="flop1" interface="floppy_5_25"> | |
| 12771 | <dataarea name="flop" size="1265664"> | |
| 12772 | <rom name="police quest ii disk 01.fdi" size="1265664" crc="18f51678" sha1="49b137412230d20df0dec0c1236866003a3f1f15" offset="0" /> | |
| 12773 | </dataarea> | |
| 12774 | </part> | |
| 12775 | <part name="flop1" interface="floppy_5_25"> | |
| 12776 | <dataarea name="flop" size="1265664"> | |
| 12777 | <rom name="police quest ii disk 02.fdi" size="1265664" crc="3fd79ed8" sha1="6893264fd7ecdbf8ceb14d2e62d76bb548fb344e" offset="0" /> | |
| 12778 | </dataarea> | |
| 12779 | </part> | |
| 12780 | <part name="flop1" interface="floppy_5_25"> | |
| 12781 | <dataarea name="flop" size="1265664"> | |
| 12782 | <rom name="police quest ii disk 03.fdi" size="1265664" crc="4c6f0d6a" sha1="442e4f2074087b5d8401f808153a12ffef9a6e7c" offset="0" /> | |
| 12783 | </dataarea> | |
| 12784 | </part> | |
| 12785 | <part name="flop1" interface="floppy_5_25"> | |
| 12786 | <dataarea name="flop" size="1265664"> | |
| 12787 | <rom name="quest for glory disk 01.fdi" size="1265664" crc="695c079e" sha1="93195094944af1d88338c4a2ce82f9188a7f3898" offset="0" /> | |
| 12788 | </dataarea> | |
| 12789 | </part> | |
| 12790 | <part name="flop1" interface="floppy_5_25"> | |
| 12791 | <dataarea name="flop" size="1265664"> | |
| 12792 | <rom name="quest for glory disk 02.fdi" size="1265664" crc="b8cdbf73" sha1="d6048c691963d159ce29c9e90b0f33a60e71c29d" offset="0" /> | |
| 12793 | </dataarea> | |
| 12794 | </part> | |
| 12795 | <part name="flop1" interface="floppy_5_25"> | |
| 12796 | <dataarea name="flop" size="1265664"> | |
| 12797 | <rom name="quest for glory disk 03.fdi" size="1265664" crc="10f50bfa" sha1="7aab2821b8a18ef3ec4811d6c8e50767f96f0108" offset="0" /> | |
| 12798 | </dataarea> | |
| 12799 | </part> | |
| 12800 | </software> | |
| 12766 | <software name="sierradp"> | |
| 12767 | <description>Sierra 3D AVG Double Pack - Quest for Glory & Police Quest 2</description> | |
| 12768 | <year>19??</year> | |
| 12769 | <publisher><unknown></publisher> | |
| 12770 | <part name="flop1" interface="floppy_5_25"> | |
| 12771 | <dataarea name="flop" size="1265664"> | |
| 12772 | <rom name="police quest ii disk 01.fdi" size="1265664" crc="18f51678" sha1="49b137412230d20df0dec0c1236866003a3f1f15" offset="0" /> | |
| 12773 | </dataarea> | |
| 12774 | </part> | |
| 12775 | <part name="flop1" interface="floppy_5_25"> | |
| 12776 | <dataarea name="flop" size="1265664"> | |
| 12777 | <rom name="police quest ii disk 02.fdi" size="1265664" crc="3fd79ed8" sha1="6893264fd7ecdbf8ceb14d2e62d76bb548fb344e" offset="0" /> | |
| 12778 | </dataarea> | |
| 12779 | </part> | |
| 12780 | <part name="flop1" interface="floppy_5_25"> | |
| 12781 | <dataarea name="flop" size="1265664"> | |
| 12782 | <rom name="police quest ii disk 03.fdi" size="1265664" crc="4c6f0d6a" sha1="442e4f2074087b5d8401f808153a12ffef9a6e7c" offset="0" /> | |
| 12783 | </dataarea> | |
| 12784 | </part> | |
| 12785 | <part name="flop1" interface="floppy_5_25"> | |
| 12786 | <dataarea name="flop" size="1265664"> | |
| 12787 | <rom name="quest for glory disk 01.fdi" size="1265664" crc="695c079e" sha1="93195094944af1d88338c4a2ce82f9188a7f3898" offset="0" /> | |
| 12788 | </dataarea> | |
| 12789 | </part> | |
| 12790 | <part name="flop1" interface="floppy_5_25"> | |
| 12791 | <dataarea name="flop" size="1265664"> | |
| 12792 | <rom name="quest for glory disk 02.fdi" size="1265664" crc="b8cdbf73" sha1="d6048c691963d159ce29c9e90b0f33a60e71c29d" offset="0" /> | |
| 12793 | </dataarea> | |
| 12794 | </part> | |
| 12795 | <part name="flop1" interface="floppy_5_25"> | |
| 12796 | <dataarea name="flop" size="1265664"> | |
| 12797 | <rom name="quest for glory disk 03.fdi" size="1265664" crc="10f50bfa" sha1="7aab2821b8a18ef3ec4811d6c8e50767f96f0108" offset="0" /> | |
| 12798 | </dataarea> | |
| 12799 | </part> | |
| 12800 | </software> | |
| 12801 | 12801 | --> |
| 12802 | 12802 | |
| 12803 | 12803 | <software name="simcity"> |
| r25360 | r25361 | |
| 14988 | 14988 | </dataarea> |
| 14989 | 14989 | </part> |
| 14990 | 14990 | </software> |
| 14991 | ||
| 14991 | ||
| 14992 | 14992 | <software name="vg2"> |
| 14993 | 14993 | <description>Variable Geo 2 - The Bout of Cabalistic Goddess</description> |
| 14994 | 14994 | <year>19??</year> |
| r25360 | r25361 | |
| 16508 | 16508 | </dataarea> |
| 16509 | 16509 | </part> |
| 16510 | 16510 | </software> |
| 16511 | ||
| 16511 | ||
| 16512 | 16512 | <software name="artemis"> |
| 16513 | 16513 | <description>Artemis</description> |
| 16514 | 16514 | <year>19??</year> |
| r25360 | r25361 | |
|---|---|---|
| 31027 | 31027 | |
| 31028 | 31028 | --> |
| 31029 | 31029 | |
| 31030 | <!-- Software below is test / demo software for the purpose of validating our emulation | |
| 31031 | where possible any information / additional files provided with the software has been included in extra data areas | |
| 31032 | in order to mirror the original release packages and possibly provide useful references | |
| 31033 | ||
| 31034 | If no additional materials are listed then the results of a successful run should be mentioned here for future reference. | |
| 31035 | --> | |
| 31036 | ||
| 31037 | <!-- most effects currently fail --> | |
| 31038 | <!-- titan-overdrivemegademo.zip --> | |
| 31039 | <!-- http://www.pouet.net/prod.php?which=61724 --> | |
| 31030 | <!-- Software below is test / demo software for the purpose of validating our emulation | |
| 31031 | where possible any information / additional files provided with the software has been included in extra data areas | |
| 31032 | in order to mirror the original release packages and possibly provide useful references | |
| 31033 | ||
| 31034 | If no additional materials are listed then the results of a successful run should be mentioned here for future reference. | |
| 31035 | --> | |
| 31036 | ||
| 31037 | <!-- most effects currently fail --> | |
| 31038 | <!-- titan-overdrivemegademo.zip --> | |
| 31039 | <!-- http://www.pouet.net/prod.php?which=61724 --> | |
| 31040 | 31040 | <software name="d_titovr"> |
| 31041 | 31041 | <description>Overdrive (Demo) (Euro)</description> |
| 31042 | 31042 | <year>2013</year> |
| r25360 | r25361 | |
| 31045 | 31045 | <dataarea name="rom" size="0x400000"> |
| 31046 | 31046 | <rom name="titan-overdrivemegademo.bin" size="0x3f01be" crc="3deb19a9" sha1="6085182099d6a9ad2c8242eae263507e42269b66" offset="0x000000" loadflag="load16_word_swap"/> |
| 31047 | 31047 | </dataarea> |
| 31048 | <!-- non-rom extras (should be marked as optional?) --> | |
| 31049 | <dataarea name="misc" size="0x7af9"> | |
| 31048 | <!-- non-rom extras (should be marked as optional?) --> | |
| 31049 | <dataarea name="misc" size="0x7af9"> | |
| 31050 | 31050 | <rom name="titan-overdrivemegademo.nfo" size="0x7af9" crc="d560530a" sha1="f3a130881878e95a1db6e32268e7b1b001965c1a" offset="0x000000"/> |
| 31051 | 31051 | </dataarea> |
| 31052 | <dataarea name="misc2" size="0x13489c0"> | |
| 31053 | <rom name="titan-overdrivemegademo_inlay.pdf" size="0x13489c0" crc="ae55e12d" sha1="620fcba1600563b87543b027c42687da7d876b03" offset="0x000000"/> | |
| 31052 | <dataarea name="misc2" size="0x13489c0"> | |
| 31053 | <rom name="titan-overdrivemegademo_inlay.pdf" size="0x13489c0" crc="ae55e12d" sha1="620fcba1600563b87543b027c42687da7d876b03" offset="0x000000"/> | |
| 31054 | 31054 | </dataarea> |
| 31055 | <dataarea name="misc3" size="0xa68cf"> | |
| 31056 | <rom name="titan-overdrivemegademo_label.pdf" size="0xa68cf" crc="a527c826" sha1="449c945a0ddcbb145c7c92bc01fac543fc1352da" offset="0x000000"/> | |
| 31055 | <dataarea name="misc3" size="0xa68cf"> | |
| 31056 | <rom name="titan-overdrivemegademo_label.pdf" size="0xa68cf" crc="a527c826" sha1="449c945a0ddcbb145c7c92bc01fac543fc1352da" offset="0x000000"/> | |
| 31057 | 31057 | </dataarea> |
| 31058 | <dataarea name="misc4" size="0x1c985d"> | |
| 31059 | <rom name="titan-overdrivemegademo_poster.png" size="0x1c985d" crc="0dfeac10" sha1="cdfd4ff93e199da66cab3ef49d39828f3eb6040c" offset="0x000000"/> | |
| 31060 | </dataarea> | |
| 31058 | <dataarea name="misc4" size="0x1c985d"> | |
| 31059 | <rom name="titan-overdrivemegademo_poster.png" size="0x1c985d" crc="0dfeac10" sha1="cdfd4ff93e199da66cab3ef49d39828f3eb6040c" offset="0x000000"/> | |
| 31060 | </dataarea> | |
| 31061 | 31061 | </part> |
| 31062 | 31062 | </software> |
| 31063 | 31063 |
| r25360 | r25361 | |
|---|---|---|
| 6903 | 6903 | <publisher>Commodore</publisher> |
| 6904 | 6904 | <info name="serial" value="C-64320" /> |
| 6905 | 6905 | <sharedfeat name="compatibility" value="NTSC,PAL"/> |
| 6906 | ||
| 6906 | ||
| 6907 | 6907 | <part name="cart" interface="c64_cart"> |
| 6908 | 6908 | <feature name="game" value="0" /> |
| 6909 | 6909 | <feature name="exrom" value="0" /> |
| 6910 | ||
| 6910 | ||
| 6911 | 6911 | <dataarea name="roml" size="0x4000"> |
| 6912 | 6912 | <rom name="a-bee-c.rom" size="0x4000" crc="5cfe999c" sha1="57202c3829f1d668c445ae7e792ae80245682a99" offset="0" /> |
| 6913 | 6913 | </dataarea> |
| r25360 | r25361 | |
|---|---|---|
| 1 | 1 | <?xml version="1.0"?> |
| 2 | 2 | <!DOCTYPE softwarelist SYSTEM "softwarelist.dtd"> |
| 3 | 3 | |
| 4 | ||
| 4 | <!-- | |
| 5 | 5 | Games for the MIXT BOOK PLAYER COPERA |
| 6 | 6 | |
| 7 | 7 | * メロディランド - Melody Land (Yamaha - 199312xx - MMGS-1) |
| r25360 | r25361 | |
| 16 | 16 | * コペラのちきゅうだいすき - Copera no Chikyuu Daisuki (Yamaha - ???? - MMGS-9) |
| 17 | 17 | * 冒険!メロリン島 - Bouken! Merorin Shima (Yamaha - ???? - MMGS-10) |
| 18 | 18 | |
| 19 | --> | |
| 20 | ||
| 21 | <softwarelist name="copera" description="Yamaha / Sega Copera cartridges"> | |
| 19 | --> | |
| 22 | 20 | |
| 21 | <softwarelist name="copera" description="Yamaha / Sega Copera cartridges"> | |
| 23 | 22 | |
| 23 | ||
| 24 | 24 | <software name="melody"> |
| 25 | 25 | <description>Melody Land</description> |
| 26 | 26 | <year>1993</year> |
| r25360 | r25361 | |
| 68 | 68 | </dataarea> |
| 69 | 69 | </part> |
| 70 | 70 | </software> |
| 71 | ||
| 71 | ||
| 72 | 72 | <software name="outacanv"> |
| 73 | 73 | <description>Outa no Canvas (Jpn)</description> |
| 74 | 74 | <year>1994</year> |
| r25360 | r25361 | |
| 83 | 83 | </dataarea> |
| 84 | 84 | </part> |
| 85 | 85 | </software> |
| 86 | ||
| 87 | <software name="copekono"> | |
| 86 | ||
| 87 | <software name="copekono"> | |
| 88 | 88 | <description>Copera no Kono Otonaani (Jpn)</description> |
| 89 | 89 | <year>1994</year> |
| 90 | 90 | <publisher>Yamaha</publisher> |
| r25360 | r25361 | |
| 98 | 98 | </dataarea> |
| 99 | 99 | </part> |
| 100 | 100 | </software> |
| 101 | ||
| 101 | ||
| 102 | 102 | <software name="mikeatmw"> |
| 103 | 103 | <description>Mike to Asobou Tobidase Milky Way (Jpn)</description> |
| 104 | 104 | <year>1994</year> |
| r25360 | r25361 | |
|---|---|---|
| 8 | 8 | |
| 9 | 9 | CAS-110 Arithmetic Drill (Math Fun & Fun with Numbers) no 算数ドリル |
| 10 | 10 | CAS-130 Sports Fan (Baseball & Sumo Wrestling) yes スポーツファン |
| 11 | CAS-140 Gambler I (Blackjack) no ギャンブラーI | |
| 11 | CAS-140 Gambler I (Blackjack) no ギャンブラーI | |
| 12 | 12 | CAS-141 Gambler II (Slot Machine and Dice) no ギャンブラーII |
| 13 | 13 | CAS-160 Space Command (Space War) no スペースコマンド |
| 14 | 14 | CAS-190 Inspiration (Bagua and Biorhythm) no 霊感 |
| r25360 | r25361 | |
|---|---|---|
| 2766 | 2766 | <software name="breakout"> |
| 2767 | 2767 | <description>Breakout</description> |
| 2768 | 2768 | <year>19??</year> |
| 2769 | <publisher>Apple Computer, Inc.</publisher> | |
| 2769 | <publisher>Apple Computer, Inc.</publisher> <!-- programmed by Steve Wozniak --> | |
| 2770 | 2770 | |
| 2771 | 2771 | <part name="flop11" interface="floppy_5_25"> |
| 2772 | 2772 | <dataarea name="flop1" size="143360"> |
| r25360 | r25361 | |
|---|---|---|
| 112 | 112 | BreakpointsWindow* window = dynamic_cast<BreakpointsWindow*>(widget); |
| 113 | 113 | |
| 114 | 114 | QActionGroup* typeGroup = window->findChild<QActionGroup*>("typegroup"); |
| 115 | ||
| 115 | typeGroup->actions()[m_bwType]->trigger(); | |
| 116 | 116 | } |
| 117 | 117 | |
| 118 | 118 |
| r25360 | r25361 | |
|---|---|---|
| 298 | 298 | PmEvent ev; |
| 299 | 299 | ev.timestamp = 0; // use the current time |
| 300 | 300 | |
| 301 | // | |
| 301 | // printf("write: %02x (%d)\n", data, dev->xmit_cnt); | |
| 302 | 302 | |
| 303 | 303 | if (dev->xmit_cnt >= 4) |
| 304 | 304 | { |
| r25360 | r25361 | |
| 314 | 314 | // if we get a status that isn't sysex, assume it's system common |
| 315 | 315 | if ((data & 0x80) && (data != MIDI_EOX)) |
| 316 | 316 | { |
| 317 | // | |
| 317 | // printf("common during sysex!\n"); | |
| 318 | 318 | ev.message = Pm_Message(data, 0, 0); |
| 319 | 319 | Pm_Write(dev->pmStream, &ev, 1); |
| 320 | 320 | return; |
| r25360 | r25361 | |
| 330 | 330 | dev->xmit_in[0] = dev->xmit_in[1] = dev->xmit_in[2] = dev->xmit_in[3] = 0; |
| 331 | 331 | dev->xmit_cnt = 0; |
| 332 | 332 | |
| 333 | // | |
| 333 | // printf("SysEx packet: %08x\n", ev.message); | |
| 334 | 334 | |
| 335 | 335 | // if this is EOX, kill the running status |
| 336 | 336 | if (data == MIDI_EOX) |
| r25360 | r25361 | |
| 352 | 352 | { |
| 353 | 353 | dev->xmit_in[dev->xmit_cnt++] = dev->last_status; |
| 354 | 354 | dev->xmit_in[dev->xmit_cnt++] = data; |
| 355 | // | |
| 355 | // printf("\trunning status: [%d] = %02x, [%d] = %02x, last_status = %02x\n", dev->xmit_cnt-2, dev->last_status, dev->xmit_cnt-1, data, dev->last_status); | |
| 356 | 356 | } |
| 357 | 357 | else |
| 358 | 358 | { |
| 359 | 359 | dev->xmit_in[dev->xmit_cnt++] = data; |
| 360 | // | |
| 360 | // printf("\tNRS: [%d] = %02x\n", dev->xmit_cnt-1, data); | |
| 361 | 361 | } |
| 362 | 362 | |
| 363 | 363 | if ((dev->xmit_cnt == 1) && (dev->xmit_in[0] == MIDI_SYSEX)) |
| 364 | 364 | { |
| 365 | // | |
| 365 | // printf("Start SysEx!\n"); | |
| 366 | 366 | dev->last_status = MIDI_SYSEX; |
| 367 | 367 | return; |
| 368 | 368 | } |
| 369 | 369 | |
| 370 | 370 | // are we there yet? |
| 371 | // | |
| 371 | // printf("status check: %02x\n", dev->xmit_in[0]); | |
| 372 | 372 | switch ((dev->xmit_in[0]>>4) & 0xf) |
| 373 | 373 | { |
| 374 | 374 | case 0xc: // 2-byte messages |
| r25360 | r25361 | |
|---|---|---|
| 67 | 67 | #define ATTR_CONST __attribute__((const)) |
| 68 | 68 | #define ATTR_FORCE_INLINE __attribute__((always_inline)) |
| 69 | 69 | #define ATTR_NONNULL(...) __attribute__((nonnull(__VA_ARGS__))) |
| 70 | #define ATTR_DEPRECATED | |
| 70 | #define ATTR_DEPRECATED __attribute__((deprecated)) | |
| 71 | 71 | /* not supported in GCC prior to 4.4.x */ |
| 72 | 72 | #if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4) |
| 73 | 73 | #define ATTR_HOT __attribute__((hot)) |
| r25360 | r25361 | |
| 83 | 83 | #else |
| 84 | 84 | #define ATTR_UNUSED |
| 85 | 85 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) |
| 86 | #define ATTR_NORETURN | |
| 86 | #define ATTR_NORETURN __declspec(noreturn) | |
| 87 | 87 | #else |
| 88 | 88 | #define ATTR_NORETURN |
| 89 | 89 | #endif |
| r25360 | r25361 | |
| 93 | 93 | #define ATTR_CONST |
| 94 | 94 | #define ATTR_FORCE_INLINE |
| 95 | 95 | #define ATTR_NONNULL(...) |
| 96 | #define ATTR_DEPRECATED | |
| 96 | #define ATTR_DEPRECATED __declspec(deprecated) | |
| 97 | 97 | #define ATTR_HOT |
| 98 | 98 | #define ATTR_COLD |
| 99 | 99 | #define UNEXPECTED(exp) (exp) |
| r25360 | r25361 | |
|---|---|---|
| 66 | 66 | #define WINOPTION_WINDOW "window" |
| 67 | 67 | #define WINOPTION_MAXIMIZE "maximize" |
| 68 | 68 | #define WINOPTION_KEEPASPECT "keepaspect" |
| 69 | #define WINOPTION_UNEVENSTRETCH | |
| 69 | #define WINOPTION_UNEVENSTRETCH "unevenstretch" | |
| 70 | 70 | #define WINOPTION_PRESCALE "prescale" |
| 71 | 71 | #define WINOPTION_WAITVSYNC "waitvsync" |
| 72 | 72 | #define WINOPTION_SYNCREFRESH "syncrefresh" |
| r25360 | r25361 | |
|---|---|---|
| 177 | 177 | // Setters / getters |
| 178 | 178 | int get_adapter() { return m_adapter; } |
| 179 | 179 | int get_width() { return m_width; } |
| 180 | vec2f | |
| 180 | vec2f get_dims() { return vec2f(m_width, m_height); } | |
| 181 | 181 | int get_height() { return m_height; } |
| 182 | 182 | int get_refresh() { return m_refresh; } |
| 183 | 183 |
| r25360 | r25361 | |
|---|---|---|
| 245 | 245 | void * d3dobj; |
| 246 | 246 | HINSTANCE dllhandle; |
| 247 | 247 | bool post_fx_available; |
| 248 | HINSTANCE | |
| 248 | HINSTANCE libhandle; | |
| 249 | 249 | |
| 250 | 250 | // interface pointers |
| 251 | 251 | interface d3d; |
| r25360 | r25361 | |
|---|---|---|
| 55 | 55 | |
| 56 | 56 | namespace d3d |
| 57 | 57 | { |
| 58 | ||
| 59 | 58 | class effect; |
| 60 | 59 | class shaders; |
| 61 | 60 | |
| r25360 | r25361 | |
| 133 | 132 | |
| 134 | 133 | uniform(effect *shader, const char *name, uniform_type type, int id); |
| 135 | 134 | |
| 136 | void set_next(uniform *next); | |
| 137 | uniform * get_next() { return m_next; } | |
| 135 | void set_next(uniform *next); | |
| 136 | uniform * get_next() { return m_next; } | |
| 138 | 137 | |
| 139 | void set(float x, float y, float z, float w); | |
| 140 | void set(float x, float y, float z); | |
| 141 | void set(float x, float y); | |
| 142 | void set(float x); | |
| 143 | void set(int x); | |
| 144 | void set(matrix *mat); | |
| 145 | void set(texture *tex); | |
| 138 | void set(float x, float y, float z, float w); | |
| 139 | void set(float x, float y, float z); | |
| 140 | void set(float x, float y); | |
| 141 | void set(float x); | |
| 142 | void set(int x); | |
| 143 | void set(matrix *mat); | |
| 144 | void set(texture *tex); | |
| 146 | 145 | |
| 147 | void upload(); | |
| 148 | void update(); | |
| 146 | void upload(); | |
| 147 | void update(); | |
| 149 | 148 | |
| 150 | 149 | protected: |
| 151 | uniform | |
| 150 | uniform *m_next; | |
| 152 | 151 | |
| 153 | float m_vec[4]; | |
| 154 | int m_ival; | |
| 155 | matrix *m_mval; | |
| 156 | texture *m_texture; | |
| 157 | int m_count; | |
| 158 | uniform_type m_type; | |
| 159 | int m_id; | |
| 152 | float m_vec[4]; | |
| 153 | int m_ival; | |
| 154 | matrix *m_mval; | |
| 155 | texture *m_texture; | |
| 156 | int m_count; | |
| 157 | uniform_type m_type; | |
| 158 | int m_id; | |
| 160 | 159 | |
| 161 | effect *m_shader; | |
| 162 | D3DXHANDLE m_handle; | |
| 160 | effect *m_shader; | |
| 161 | D3DXHANDLE m_handle; | |
| 163 | 162 | }; |
| 164 | 163 | |
| 165 | 164 | class effect |
| r25360 | r25361 | |
| 170 | 169 | effect(shaders *shadersys, device *dev, const char *name, const char *path); |
| 171 | 170 | ~effect(); |
| 172 | 171 | |
| 173 | void begin(UINT *passes, DWORD flags); | |
| 174 | void begin_pass(UINT pass); | |
| 172 | void begin(UINT *passes, DWORD flags); | |
| 173 | void begin_pass(UINT pass); | |
| 175 | 174 | |
| 176 | void end(); | |
| 177 | void end_pass(); | |
| 175 | void end(); | |
| 176 | void end_pass(); | |
| 178 | 177 | |
| 179 | void | |
| 178 | void set_technique(const char *name); | |
| 180 | 179 | |
| 181 | void set_vector(D3DXHANDLE param, int count, float *vector); | |
| 182 | void set_float(D3DXHANDLE param, float value); | |
| 183 | void set_int(D3DXHANDLE param, int value); | |
| 184 | void set_matrix(D3DXHANDLE param, matrix *matrix); | |
| 185 | void set_texture(D3DXHANDLE param, texture *tex); | |
| 180 | void set_vector(D3DXHANDLE param, int count, float *vector); | |
| 181 | void set_float(D3DXHANDLE param, float value); | |
| 182 | void set_int(D3DXHANDLE param, int value); | |
| 183 | void set_matrix(D3DXHANDLE param, matrix *matrix); | |
| 184 | void set_texture(D3DXHANDLE param, texture *tex); | |
| 186 | 185 | |
| 187 | void add_uniform(const char *name, uniform::uniform_type type, int id); | |
| 188 | void update_uniforms(); | |
| 186 | void add_uniform(const char *name, uniform::uniform_type type, int id); | |
| 187 | void update_uniforms(); | |
| 189 | 188 | |
| 190 | D3DXHANDLE | |
| 189 | D3DXHANDLE get_parameter(D3DXHANDLE param, const char *name); | |
| 191 | 190 | |
| 192 | ULONG | |
| 191 | ULONG release(); | |
| 193 | 192 | |
| 194 | shaders* | |
| 193 | shaders* get_shaders() { return m_shaders; } | |
| 195 | 194 | |
| 196 | bool | |
| 195 | bool is_valid() { return m_valid; } | |
| 197 | 196 | |
| 198 | 197 | private: |
| 199 | uniform *m_uniform_head; | |
| 200 | uniform *m_uniform_tail; | |
| 198 | uniform *m_uniform_head; | |
| 199 | uniform *m_uniform_tail; | |
| 201 | 200 | ID3DXEffect *m_effect; |
| 202 | shaders | |
| 201 | shaders *m_shaders; | |
| 203 | 202 | |
| 204 | bool | |
| 203 | bool m_valid; | |
| 205 | 204 | }; |
| 206 | 205 | |
| 207 | 206 | class render_target; |
| r25360 | r25361 | |
| 358 | 357 | void remove_cache_target(cache_target *cache); |
| 359 | 358 | |
| 360 | 359 | // Shader passes |
| 361 | void ntsc_pass(render_target *rt, vec2f &texsize, vec2f &delta); | |
| 362 | void color_convolution_pass(render_target *rt, vec2f &texsize, vec2f &sourcedims); | |
| 363 | void prescale_pass(render_target *rt, vec2f &texsize, vec2f &sourcedims); | |
| 364 | void deconverge_pass(render_target *rt, vec2f &texsize, vec2f &delta, vec2f &sourcedims); | |
| 365 | void defocus_pass(render_target *rt, vec2f &texsize); | |
| 366 | void phosphor_pass(render_target *rt, cache_target *ct, vec2f &texsize, bool focus_enable); | |
| 367 | void screen_post_pass(render_target *rt, vec2f &texsize, vec2f &delta, vec2f &sourcedims, poly_info *poly, int vertnum); | |
| 368 | void avi_post_pass(render_target *rt, vec2f &texsize, vec2f &delta, vec2f &sourcedims, poly_info *poly, int vertnum); | |
| 369 | void raster_bloom_pass(render_target *rt, vec2f &texsize, vec2f &delta, poly_info *poly, int vertnum); | |
| 360 | void ntsc_pass(render_target *rt, vec2f &texsize, vec2f &delta); | |
| 361 | void color_convolution_pass(render_target *rt, vec2f &texsize, vec2f &sourcedims); | |
| 362 | void prescale_pass(render_target *rt, vec2f &texsize, vec2f &sourcedims); | |
| 363 | void deconverge_pass(render_target *rt, vec2f &texsize, vec2f &delta, vec2f &sourcedims); | |
| 364 | void defocus_pass(render_target *rt, vec2f &texsize); | |
| 365 | void phosphor_pass(render_target *rt, cache_target *ct, vec2f &texsize, bool focus_enable); | |
| 366 | void screen_post_pass(render_target *rt, vec2f &texsize, vec2f &delta, vec2f &sourcedims, poly_info *poly, int vertnum); | |
| 367 | void avi_post_pass(render_target *rt, vec2f &texsize, vec2f &delta, vec2f &sourcedims, poly_info *poly, int vertnum); | |
| 368 | void raster_bloom_pass(render_target *rt, vec2f &texsize, vec2f &delta, poly_info *poly, int vertnum); | |
| 370 | 369 | |
| 371 | 370 | base * d3dintf; // D3D interface |
| 372 | 371 | win_window_info * window; // D3D window info |
| r25360 | r25361 | |
| 434 | 433 | effect * vector_effect; // pointer to the vector-effect object |
| 435 | 434 | vertex * fsfx_vertices; // pointer to our full-screen-quad object |
| 436 | 435 | |
| 437 | texture_info * curr_texture; | |
| 438 | bool phosphor_passthrough; | |
| 439 | float target_size[2]; | |
| 436 | texture_info * curr_texture; | |
| 437 | bool phosphor_passthrough; | |
| 438 | float target_size[2]; | |
| 440 | 439 | |
| 441 | 440 | public: |
| 442 | 441 | render_target * targethead; |
| r25360 | r25361 | |
|---|---|---|
| 18 | 18 | return FILERR_OUT_OF_MEMORY; |
| 19 | 19 | |
| 20 | 20 | pipe = CreateNamedPipe(t_name, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_NOWAIT, 1, 32, 32, 0, NULL); |
| 21 | ||
| 21 | ||
| 22 | 22 | osd_free(t_name); |
| 23 | ||
| 23 | ||
| 24 | 24 | if(pipe == INVALID_HANDLE_VALUE) |
| 25 | 25 | return FILERR_ACCESS_DENIED; |
| 26 | 26 |
| r25360 | r25361 | |
|---|---|---|
| 318 | 318 | { WINOPTION_WINDOW ";w", "0", OPTION_BOOLEAN, "enable window mode; otherwise, full screen mode is assumed" }, |
| 319 | 319 | { WINOPTION_MAXIMIZE ";max", "1", OPTION_BOOLEAN, "default to maximized windows; otherwise, windows will be minimized" }, |
| 320 | 320 | { WINOPTION_KEEPASPECT ";ka", "1", OPTION_BOOLEAN, "constrain to the proper aspect ratio" }, |
| 321 | { WINOPTION_UNEVENSTRETCH ";ues", | |
| 321 | { WINOPTION_UNEVENSTRETCH ";ues", "1", OPTION_BOOLEAN, "allow non-integer stretch factors" }, | |
| 322 | 322 | { WINOPTION_PRESCALE, "1", OPTION_INTEGER, "scale screen rendering by this amount in software" }, |
| 323 | 323 | { WINOPTION_WAITVSYNC ";vs", "0", OPTION_BOOLEAN, "enable waiting for the start of VBLANK before flipping screens; reduces tearing effects" }, |
| 324 | 324 | { WINOPTION_SYNCREFRESH ";srf", "0", OPTION_BOOLEAN, "enable using the start of VBLANK for throttling instead of the game time" }, |
| r25360 | r25361 | |
|---|---|---|
| 38 | 38 | ***************************************************************************/ |
| 39 | 39 | |
| 40 | 40 | extern const char build_version[]; |
| 41 | const char build_version[] = "0.1 | |
| 41 | const char build_version[] = "0.150 ("__DATE__")"; |
| r25360 | r25361 | |
|---|---|---|
| 196 | 196 | ***************************************************************************/ |
| 197 | 197 | |
| 198 | 198 | #define HEADER_LENGTH 0x2ac // standard length for 84 half tracks |
| 199 | #define MAX_HEADS | |
| 199 | #define MAX_HEADS 2 | |
| 200 | 200 | #define MAX_TRACKS 84 |
| 201 | 201 | |
| 202 | 202 | /*************************************************************************** |
| r25360 | r25361 | |
| 206 | 206 | struct g64dsk_tag |
| 207 | 207 | { |
| 208 | 208 | int version; |
| 209 | int heads; // number of physical heads | |
| 210 | int tracks; // number of physical tracks | |
| 211 | UINT16 track_size[MAX_HEADS][MAX_TRACKS]; // size of each track | |
| 212 | UINT32 track_offset[MAX_HEADS][MAX_TRACKS]; // offset within data for each track | |
| 213 | UINT32 speed_zone_offset[MAX_HEADS][MAX_TRACKS]; // offset within data for each track | |
| 209 | int heads; // number of physical heads | |
| 210 | int tracks; // number of physical tracks | |
| 211 | UINT16 track_size[MAX_HEADS][MAX_TRACKS]; // size of each track | |
| 212 | UINT32 track_offset[MAX_HEADS][MAX_TRACKS]; // offset within data for each track | |
| 213 | UINT32 speed_zone_offset[MAX_HEADS][MAX_TRACKS]; // offset within data for each track | |
| 214 | 214 | }; |
| 215 | 215 | |
| 216 | 216 | /*************************************************************************** |
| r25360 | r25361 | |
| 466 | 466 | for (int i = 0; i < tag->tracks; i++) |
| 467 | 467 | { |
| 468 | 468 | tag->speed_zone_offset[head][i] = pick_integer_le(header, pos, 4); |
| 469 | ||
| 469 | ||
| 470 | 470 | if (tag->speed_zone_offset[head][i] >= 4) |
| 471 | 471 | { |
| 472 | 472 | tag->speed_zone_offset[head][i] += start_pos; |
| r25360 | r25361 | |
|---|---|---|
| 184 | 184 | }; |
| 185 | 185 | |
| 186 | 186 | const floppy_format_type FLOPPY_CPIS_FORMAT = &floppy_image_format_creator<cpis_format>; |
| 187 |
| r25360 | r25361 | |
|---|---|---|
| 34 | 34 | |
| 35 | 35 | // This structure contains information about the HTTP request. |
| 36 | 36 | struct mg_request_info { |
| 37 | const char *request_method; // "GET", "POST", etc | |
| 38 | const char *uri; // URL-decoded URI | |
| 39 | const char *http_version; // E.g. "1.0", "1.1" | |
| 40 | const char *query_string; // URL part after '?', not including '?', or NULL | |
| 41 | const char *remote_user; // Authenticated user, or NULL if no auth used | |
| 42 | long remote_ip; // Client's IP address | |
| 43 | int remote_port; // Client's port | |
| 44 | int is_ssl; // 1 if SSL-ed, 0 if not | |
| 45 | void *user_data; // User data pointer passed to mg_start() | |
| 37 | const char *request_method; // "GET", "POST", etc | |
| 38 | const char *uri; // URL-decoded URI | |
| 39 | const char *http_version; // E.g. "1.0", "1.1" | |
| 40 | const char *query_string; // URL part after '?', not including '?', or NULL | |
| 41 | const char *remote_user; // Authenticated user, or NULL if no auth used | |
| 42 | long remote_ip; // Client's IP address | |
| 43 | int remote_port; // Client's port | |
| 44 | int is_ssl; // 1 if SSL-ed, 0 if not | |
| 45 | void *user_data; // User data pointer passed to mg_start() | |
| 46 | 46 | |
| 47 | int num_headers; // Number of HTTP headers | |
| 48 | struct mg_header { | |
| 49 | const char *name; // HTTP header name | |
| 50 | const char *value; // HTTP header value | |
| 51 | } http_headers[64]; // Maximum 64 headers | |
| 47 | int num_headers; // Number of HTTP headers | |
| 48 | struct mg_header { | |
| 49 | const char *name; // HTTP header name | |
| 50 | const char *value; // HTTP header value | |
| 51 | } http_headers[64]; // Maximum 64 headers | |
| 52 | 52 | }; |
| 53 | 53 | |
| 54 | 54 | |
| r25360 | r25361 | |
| 56 | 56 | // which callbacks to invoke. For detailed description, see |
| 57 | 57 | // https://github.com/valenok/mongoose/blob/master/UserManual.md |
| 58 | 58 | struct mg_callbacks { |
| 59 | // Called when mongoose has received new HTTP request. | |
| 60 | // If callback returns non-zero, | |
| 61 | // callback must process the request by sending valid HTTP headers and body, | |
| 62 | // and mongoose will not do any further processing. | |
| 63 | // If callback returns 0, mongoose processes the request itself. In this case, | |
| 64 | // callback must not send any data to the client. | |
| 65 | int (*begin_request)(struct mg_connection *); | |
| 59 | // Called when mongoose has received new HTTP request. | |
| 60 | // If callback returns non-zero, | |
| 61 | // callback must process the request by sending valid HTTP headers and body, | |
| 62 | // and mongoose will not do any further processing. | |
| 63 | // If callback returns 0, mongoose processes the request itself. In this case, | |
| 64 | // callback must not send any data to the client. | |
| 65 | int (*begin_request)(struct mg_connection *); | |
| 66 | 66 | |
| 67 | // Called when mongoose has finished processing request. | |
| 68 | void (*end_request)(const struct mg_connection *, int reply_status_code); | |
| 67 | // Called when mongoose has finished processing request. | |
| 68 | void (*end_request)(const struct mg_connection *, int reply_status_code); | |
| 69 | 69 | |
| 70 | // Called when mongoose is about to log a message. If callback returns | |
| 71 | // non-zero, mongoose does not log anything. | |
| 72 | int (*log_message)(const struct mg_connection *, const char *message); | |
| 70 | // Called when mongoose is about to log a message. If callback returns | |
| 71 | // non-zero, mongoose does not log anything. | |
| 72 | int (*log_message)(const struct mg_connection *, const char *message); | |
| 73 | 73 | |
| 74 | // Called when mongoose initializes SSL library. | |
| 75 | int (*init_ssl)(void *ssl_context, void *user_data); | |
| 74 | // Called when mongoose initializes SSL library. | |
| 75 | int (*init_ssl)(void *ssl_context, void *user_data); | |
| 76 | 76 | |
| 77 | // Called when websocket request is received, before websocket handshake. | |
| 78 | // If callback returns 0, mongoose proceeds with handshake, otherwise | |
| 79 | // cinnection is closed immediately. | |
| 80 | int (*websocket_connect)(const struct mg_connection *); | |
| 77 | // Called when websocket request is received, before websocket handshake. | |
| 78 | // If callback returns 0, mongoose proceeds with handshake, otherwise | |
| 79 | // cinnection is closed immediately. | |
| 80 | int (*websocket_connect)(const struct mg_connection *); | |
| 81 | 81 | |
| 82 | // Called when websocket handshake is successfully completed, and | |
| 83 | // connection is ready for data exchange. | |
| 84 | void (*websocket_ready)(struct mg_connection *); | |
| 82 | // Called when websocket handshake is successfully completed, and | |
| 83 | // connection is ready for data exchange. | |
| 84 | void (*websocket_ready)(struct mg_connection *); | |
| 85 | 85 | |
| 86 | // Called when data frame has been received from the client. | |
| 87 | // Parameters: | |
| 88 | // bits: first byte of the websocket frame, see websocket RFC at | |
| 89 | // http://tools.ietf.org/html/rfc6455, section 5.2 | |
| 90 | // data, data_len: payload, with mask (if any) already applied. | |
| 91 | // Return value: | |
| 92 | // non-0: keep this websocket connection opened. | |
| 93 | // 0: close this websocket connection. | |
| 94 | int (*websocket_data)(struct mg_connection *, int bits, | |
| 95 | char *data, size_t data_len); | |
| 86 | // Called when data frame has been received from the client. | |
| 87 | // Parameters: | |
| 88 | // bits: first byte of the websocket frame, see websocket RFC at | |
| 89 | // http://tools.ietf.org/html/rfc6455, section 5.2 | |
| 90 | // data, data_len: payload, with mask (if any) already applied. | |
| 91 | // Return value: | |
| 92 | // non-0: keep this websocket connection opened. | |
| 93 | // 0: close this websocket connection. | |
| 94 | int (*websocket_data)(struct mg_connection *, int bits, | |
| 95 | char *data, size_t data_len); | |
| 96 | 96 | |
| 97 | // Called when mongoose tries to open a file. Used to intercept file open | |
| 98 | // calls, and serve file data from memory instead. | |
| 99 | // Parameters: | |
| 100 | // path: Full path to the file to open. | |
| 101 | // data_len: Placeholder for the file size, if file is served from memory. | |
| 102 | // Return value: | |
| 103 | // NULL: do not serve file from memory, proceed with normal file open. | |
| 104 | // non-NULL: pointer to the file contents in memory. data_len must be | |
| 105 | // initilized with the size of the memory block. | |
| 106 | const char * (*open_file)(const struct mg_connection *, | |
| 107 | const char *path, size_t *data_len); | |
| 97 | // Called when mongoose tries to open a file. Used to intercept file open | |
| 98 | // calls, and serve file data from memory instead. | |
| 99 | // Parameters: | |
| 100 | // path: Full path to the file to open. | |
| 101 | // data_len: Placeholder for the file size, if file is served from memory. | |
| 102 | // Return value: | |
| 103 | // NULL: do not serve file from memory, proceed with normal file open. | |
| 104 | // non-NULL: pointer to the file contents in memory. data_len must be | |
| 105 | // initilized with the size of the memory block. | |
| 106 | const char * (*open_file)(const struct mg_connection *, | |
| 107 | const char *path, size_t *data_len); | |
| 108 | 108 | |
| 109 | // Called when mongoose is about to serve Lua server page (.lp file), if | |
| 110 | // Lua support is enabled. | |
| 111 | // Parameters: | |
| 112 | // lua_context: "lua_State *" pointer. | |
| 113 | void (*init_lua)(struct mg_connection *, void *lua_context); | |
| 109 | // Called when mongoose is about to serve Lua server page (.lp file), if | |
| 110 | // Lua support is enabled. | |
| 111 | // Parameters: | |
| 112 | // lua_context: "lua_State *" pointer. | |
| 113 | void (*init_lua)(struct mg_connection *, void *lua_context); | |
| 114 | 114 | |
| 115 | // Called when mongoose has uploaded a file to a temporary directory as a | |
| 116 | // result of mg_upload() call. | |
| 117 | // Parameters: | |
| 118 | // file_file: full path name to the uploaded file. | |
| 119 | void (*upload)(struct mg_connection *, const char *file_name); | |
| 115 | // Called when mongoose has uploaded a file to a temporary directory as a | |
| 116 | // result of mg_upload() call. | |
| 117 | // Parameters: | |
| 118 | // file_file: full path name to the uploaded file. | |
| 119 | void (*upload)(struct mg_connection *, const char *file_name); | |
| 120 | 120 | |
| 121 | // Called when mongoose is about to send HTTP error to the client. | |
| 122 | // Implementing this callback allows to create custom error pages. | |
| 123 | // Parameters: | |
| 124 | // status: HTTP error status code. | |
| 125 | int (*http_error)(struct mg_connection *, int status); | |
| 121 | // Called when mongoose is about to send HTTP error to the client. | |
| 122 | // Implementing this callback allows to create custom error pages. | |
| 123 | // Parameters: | |
| 124 | // status: HTTP error status code. | |
| 125 | int (*http_error)(struct mg_connection *, int status); | |
| 126 | 126 | }; |
| 127 | 127 | |
| 128 | 128 | // Start web server. |
| r25360 | r25361 | |
| 151 | 151 | // Return: |
| 152 | 152 | // web server context, or NULL on error. |
| 153 | 153 | struct mg_context *mg_start(const struct mg_callbacks *callbacks, |
| 154 | void *user_data, | |
| 155 | const char **configuration_options); | |
| 154 | void *user_data, | |
| 155 | const char **configuration_options); | |
| 156 | 156 | |
| 157 | 157 | |
| 158 | 158 | // Stop the web server. |
| r25360 | r25361 | |
| 191 | 191 | // Return: |
| 192 | 192 | // 1 on success, 0 on error. |
| 193 | 193 | int mg_modify_passwords_file(const char *passwords_file_name, |
| 194 | const char *domain, | |
| 195 | const char *user, | |
| 196 | const char *password); | |
| 194 | const char *domain, | |
| 195 | const char *user, | |
| 196 | const char *password); | |
| 197 | 197 | |
| 198 | 198 | |
| 199 | 199 | // Return information associated with the request. |
| r25360 | r25361 | |
| 217 | 217 | // -1 on error |
| 218 | 218 | // >0 number of bytes written on success |
| 219 | 219 | int mg_websocket_write(struct mg_connection* conn, int opcode, |
| 220 | ||
| 220 | const char *data, size_t data_len); | |
| 221 | 221 | |
| 222 | 222 | // Opcodes, from http://tools.ietf.org/html/rfc6455 |
| 223 | 223 | enum { |
| 224 | WEBSOCKET_OPCODE_CONTINUATION = 0x0, | |
| 225 | WEBSOCKET_OPCODE_TEXT = 0x1, | |
| 226 | WEBSOCKET_OPCODE_BINARY = 0x2, | |
| 227 | WEBSOCKET_OPCODE_CONNECTION_CLOSE = 0x8, | |
| 228 | WEBSOCKET_OPCODE_PING = 0x9, | |
| 229 | WEBSOCKET_OPCODE_PONG = 0xa | |
| 224 | WEBSOCKET_OPCODE_CONTINUATION = 0x0, | |
| 225 | WEBSOCKET_OPCODE_TEXT = 0x1, | |
| 226 | WEBSOCKET_OPCODE_BINARY = 0x2, | |
| 227 | WEBSOCKET_OPCODE_CONNECTION_CLOSE = 0x8, | |
| 228 | WEBSOCKET_OPCODE_PING = 0x9, | |
| 229 | WEBSOCKET_OPCODE_PONG = 0xa | |
| 230 | 230 | }; |
| 231 | 231 | |
| 232 | 232 | |
| r25360 | r25361 | |
| 253 | 253 | // |
| 254 | 254 | // Works exactly like mg_write(), but allows to do message formatting. |
| 255 | 255 | int mg_printf(struct mg_connection *, |
| 256 | ||
| 256 | PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(2, 3); | |
| 257 | 257 | |
| 258 | 258 | |
| 259 | 259 | // Send contents of the entire file together with HTTP headers. |
| r25360 | r25361 | |
| 296 | 296 | // Destination buffer is guaranteed to be '\0' - terminated if it is not |
| 297 | 297 | // NULL or zero length. |
| 298 | 298 | int mg_get_var(const char *data, size_t data_len, |
| 299 | ||
| 299 | const char *var_name, char *dst, size_t dst_len); | |
| 300 | 300 | |
| 301 | 301 | // Fetch value of certain cookie variable into the destination buffer. |
| 302 | 302 | // |
| r25360 | r25361 | |
| 312 | 312 | // -2 (destination buffer is NULL, zero length or too small to hold the |
| 313 | 313 | // value). |
| 314 | 314 | int mg_get_cookie(const char *cookie, const char *var_name, |
| 315 | ||
| 315 | char *buf, size_t buf_len); | |
| 316 | 316 | |
| 317 | 317 | |
| 318 | 318 | // Download data from the remote web server. |
| r25360 | r25361 | |
| 330 | 330 | // conn = mg_download("google.com", 80, 0, ebuf, sizeof(ebuf), |
| 331 | 331 | // "%s", "GET / HTTP/1.0\r\nHost: google.com\r\n\r\n"); |
| 332 | 332 | struct mg_connection *mg_download(const char *host, int port, int use_ssl, |
| 333 | char *error_buffer, size_t error_buffer_size, | |
| 334 | PRINTF_FORMAT_STRING(const char *request_fmt), | |
| 335 | ...) PRINTF_ARGS(6, 7); | |
| 333 | char *error_buffer, size_t error_buffer_size, | |
| 334 | PRINTF_FORMAT_STRING(const char *request_fmt), | |
| 335 | ...) PRINTF_ARGS(6, 7); | |
| 336 | 336 | |
| 337 | 337 | |
| 338 | 338 | // Close the connection opened by mg_download(). |
| r25360 | r25361 | |
| 366 | 366 | // http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt |
| 367 | 367 | // Return: length of the decoded data, or -1 if dst buffer is too small. |
| 368 | 368 | int mg_url_decode(const char *src, int src_len, char *dst, |
| 369 | ||
| 369 | int dst_len, int is_form_url_encoded); | |
| 370 | 370 | |
| 371 | 371 | // MD5 hash given strings. |
| 372 | 372 | // Buffer 'buf' must be 33 bytes long. Varargs is a NULL terminated list of |
| r25360 | r25361 | |
|---|---|---|
| 100 | 100 | #endif // _WIN32_WCE |
| 101 | 101 | |
| 102 | 102 | #define MAKEUQUAD(lo, hi) ((uint64_t)(((uint32_t)(lo)) | \ |
| 103 | ||
| 103 | ((uint64_t)((uint32_t)(hi))) << 32)) | |
| 104 | 104 | #define RATE_DIFF 10000000 // 100 nsecs |
| 105 | 105 | #define EPOCH_DIFF MAKEUQUAD(0xd53e8000, 0x019db1de) |
| 106 | 106 | #define SYS2UNIX_TIME(lo, hi) \ |
| 107 | ||
| 107 | (time_t) ((MAKEUQUAD((lo), (hi)) - EPOCH_DIFF) / RATE_DIFF) | |
| 108 | 108 | |
| 109 | 109 | // Visual Studio 6 does not know __func__ or __FUNCTION__ |
| 110 | 110 | // The rest of MS compilers use __FUNCTION__, not C99 __func__ |
| r25360 | r25361 | |
| 192 | 192 | |
| 193 | 193 | // POSIX dirent interface |
| 194 | 194 | struct dirent { |
| 195 | ||
| 195 | char d_name[PATH_MAX]; | |
| 196 | 196 | }; |
| 197 | 197 | |
| 198 | 198 | typedef struct DIR { |
| 199 | HANDLE handle; | |
| 200 | WIN32_FIND_DATAW info; | |
| 201 | struct dirent result; | |
| 199 | HANDLE handle; | |
| 200 | WIN32_FIND_DATAW info; | |
| 201 | struct dirent result; | |
| 202 | 202 | } DIR; |
| 203 | 203 | |
| 204 | 204 | #ifndef HAVE_POLL |
| 205 | 205 | struct pollfd { |
| 206 | int fd; | |
| 207 | short events; | |
| 208 | short revents; | |
| 206 | int fd; | |
| 207 | short events; | |
| 208 | short revents; | |
| 209 | 209 | }; |
| 210 | 210 | #define POLLIN 1 |
| 211 | 211 | #endif |
| r25360 | r25361 | |
| 274 | 274 | static CRITICAL_SECTION global_log_file_lock; |
| 275 | 275 | #if !defined(NO_SSL) |
| 276 | 276 | static pthread_t pthread_self(void) { |
| 277 | ||
| 277 | return GetCurrentThreadId(); | |
| 278 | 278 | } |
| 279 | 279 | #endif |
| 280 | 280 | #endif // _WIN32 |
| r25360 | r25361 | |
| 285 | 285 | #else |
| 286 | 286 | #if defined(DEBUG) |
| 287 | 287 | #define DEBUG_TRACE(x) do { \ |
| 288 | flockfile(stdout); \ | |
| 289 | printf("*** %lu.%p.%s.%d: ", \ | |
| 290 | (unsigned long) time(NULL), (void *) pthread_self(), \ | |
| 291 | __func__, __LINE__); \ | |
| 292 | printf x; \ | |
| 293 | putchar('\n'); \ | |
| 294 | fflush(stdout); \ | |
| 295 | funlockfile(stdout); \ | |
| 288 | flockfile(stdout); \ | |
| 289 | printf("*** %lu.%p.%s.%d: ", \ | |
| 290 | (unsigned long) time(NULL), (void *) pthread_self(), \ | |
| 291 | __func__, __LINE__); \ | |
| 292 | printf x; \ | |
| 293 | putchar('\n'); \ | |
| 294 | fflush(stdout); \ | |
| 295 | funlockfile(stdout); \ | |
| 296 | 296 | } while (0) |
| 297 | 297 | #else |
| 298 | 298 | #define DEBUG_TRACE(x) |
| r25360 | r25361 | |
| 331 | 331 | typedef struct ssl_ctx_st SSL_CTX; |
| 332 | 332 | |
| 333 | 333 | struct ssl_func { |
| 334 | const char *name; // SSL function name | |
| 335 | void (*ptr)(void); // Function pointer | |
| 334 | const char *name; // SSL function name | |
| 335 | void (*ptr)(void); // Function pointer | |
| 336 | 336 | }; |
| 337 | 337 | |
| 338 | 338 | #define SSL_free (* (void (*)(SSL *)) ssl_sw[0].ptr) |
| r25360 | r25361 | |
| 347 | 347 | #define SSLv23_server_method (* (SSL_METHOD * (*)(void)) ssl_sw[9].ptr) |
| 348 | 348 | #define SSL_library_init (* (int (*)(void)) ssl_sw[10].ptr) |
| 349 | 349 | #define SSL_CTX_use_PrivateKey_file (* (int (*)(SSL_CTX *, \ |
| 350 | ||
| 350 | const char *, int)) ssl_sw[11].ptr) | |
| 351 | 351 | #define SSL_CTX_use_certificate_file (* (int (*)(SSL_CTX *, \ |
| 352 | ||
| 352 | const char *, int)) ssl_sw[12].ptr) | |
| 353 | 353 | #define SSL_CTX_set_default_passwd_cb \ |
| 354 | ||
| 354 | (* (void (*)(SSL_CTX *, mg_callback_t)) ssl_sw[13].ptr) | |
| 355 | 355 | #define SSL_CTX_free (* (void (*)(SSL_CTX *)) ssl_sw[14].ptr) |
| 356 | 356 | #define SSL_load_error_strings (* (void (*)(void)) ssl_sw[15].ptr) |
| 357 | 357 | #define SSL_CTX_use_certificate_chain_file \ |
| 358 | ||
| 358 | (* (int (*)(SSL_CTX *, const char *)) ssl_sw[16].ptr) | |
| 359 | 359 | #define SSLv23_client_method (* (SSL_METHOD * (*)(void)) ssl_sw[17].ptr) |
| 360 | 360 | #define SSL_pending (* (int (*)(SSL *)) ssl_sw[18].ptr) |
| 361 | 361 | #define SSL_CTX_set_verify (* (void (*)(SSL_CTX *, int, int)) ssl_sw[19].ptr) |
| r25360 | r25361 | |
| 363 | 363 | |
| 364 | 364 | #define CRYPTO_num_locks (* (int (*)(void)) crypto_sw[0].ptr) |
| 365 | 365 | #define CRYPTO_set_locking_callback \ |
| 366 | ||
| 366 | (* (void (*)(void (*)(int, int, const char *, int))) crypto_sw[1].ptr) | |
| 367 | 367 | #define CRYPTO_set_id_callback \ |
| 368 | ||
| 368 | (* (void (*)(unsigned long (*)(void))) crypto_sw[2].ptr) | |
| 369 | 369 | #define ERR_get_error (* (unsigned long (*)(void)) crypto_sw[3].ptr) |
| 370 | 370 | #define ERR_error_string (* (char * (*)(unsigned long,char *)) crypto_sw[4].ptr) |
| 371 | 371 | |
| r25360 | r25361 | |
| 374 | 374 | // of respective functions. The macros above (like SSL_connect()) are really |
| 375 | 375 | // just calling these functions indirectly via the pointer. |
| 376 | 376 | static struct ssl_func ssl_sw[] = { |
| 377 | {"SSL_free", NULL}, | |
| 378 | {"SSL_accept", NULL}, | |
| 379 | {"SSL_connect", NULL}, | |
| 380 | {"SSL_read", NULL}, | |
| 381 | {"SSL_write", NULL}, | |
| 382 | {"SSL_get_error", NULL}, | |
| 383 | {"SSL_set_fd", NULL}, | |
| 384 | {"SSL_new", NULL}, | |
| 385 | {"SSL_CTX_new", NULL}, | |
| 386 | {"SSLv23_server_method", NULL}, | |
| 387 | {"SSL_library_init", NULL}, | |
| 388 | {"SSL_CTX_use_PrivateKey_file", NULL}, | |
| 389 | {"SSL_CTX_use_certificate_file",NULL}, | |
| 390 | {"SSL_CTX_set_default_passwd_cb",NULL}, | |
| 391 | {"SSL_CTX_free", NULL}, | |
| 392 | {"SSL_load_error_strings", NULL}, | |
| 393 | {"SSL_CTX_use_certificate_chain_file", NULL}, | |
| 394 | {"SSLv23_client_method", NULL}, | |
| 395 | {"SSL_pending", NULL}, | |
| 396 | {"SSL_CTX_set_verify", NULL}, | |
| 397 | {"SSL_shutdown", NULL}, | |
| 398 | {NULL, NULL} | |
| 377 | {"SSL_free", NULL}, | |
| 378 | {"SSL_accept", NULL}, | |
| 379 | {"SSL_connect", NULL}, | |
| 380 | {"SSL_read", NULL}, | |
| 381 | {"SSL_write", NULL}, | |
| 382 | {"SSL_get_error", NULL}, | |
| 383 | {"SSL_set_fd", NULL}, | |
| 384 | {"SSL_new", NULL}, | |
| 385 | {"SSL_CTX_new", NULL}, | |
| 386 | {"SSLv23_server_method", NULL}, | |
| 387 | {"SSL_library_init", NULL}, | |
| 388 | {"SSL_CTX_use_PrivateKey_file", NULL}, | |
| 389 | {"SSL_CTX_use_certificate_file",NULL}, | |
| 390 | {"SSL_CTX_set_default_passwd_cb",NULL}, | |
| 391 | {"SSL_CTX_free", NULL}, | |
| 392 | {"SSL_load_error_strings", NULL}, | |
| 393 | {"SSL_CTX_use_certificate_chain_file", NULL}, | |
| 394 | {"SSLv23_client_method", NULL}, | |
| 395 | {"SSL_pending", NULL}, | |
| 396 | {"SSL_CTX_set_verify", NULL}, | |
| 397 | {"SSL_shutdown", NULL}, | |
| 398 | {NULL, NULL} | |
| 399 | 399 | }; |
| 400 | 400 | |
| 401 | 401 | // Similar array as ssl_sw. These functions could be located in different lib. |
| 402 | 402 | #if !defined(NO_SSL) |
| 403 | 403 | static struct ssl_func crypto_sw[] = { |
| 404 | {"CRYPTO_num_locks", NULL}, | |
| 405 | {"CRYPTO_set_locking_callback", NULL}, | |
| 406 | {"CRYPTO_set_id_callback", NULL}, | |
| 407 | {"ERR_get_error", NULL}, | |
| 408 | {"ERR_error_string", NULL}, | |
| 409 | {NULL, NULL} | |
| 404 | {"CRYPTO_num_locks", NULL}, | |
| 405 | {"CRYPTO_set_locking_callback", NULL}, | |
| 406 | {"CRYPTO_set_id_callback", NULL}, | |
| 407 | {"ERR_get_error", NULL}, | |
| 408 | {"ERR_error_string", NULL}, | |
| 409 | {NULL, NULL} | |
| 410 | 410 | }; |
| 411 | 411 | #endif // NO_SSL |
| 412 | 412 | #endif // NO_SSL_DL |
| 413 | 413 | |
| 414 | 414 | static const char *month_names[] = { |
| 415 | "Jan", "Feb", "Mar", "Apr", "May", "Jun", | |
| 416 | "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" | |
| 415 | "Jan", "Feb", "Mar", "Apr", "May", "Jun", | |
| 416 | "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" | |
| 417 | 417 | }; |
| 418 | 418 | |
| 419 | 419 | // Unified socket address. For IPv6 support, add IPv6 address structure |
| 420 | 420 | // in the union u. |
| 421 | 421 | union usa { |
| 422 | struct sockaddr sa; | |
| 423 | struct sockaddr_in sin; | |
| 422 | struct sockaddr sa; | |
| 423 | struct sockaddr_in sin; | |
| 424 | 424 | #if defined(USE_IPV6) |
| 425 | ||
| 425 | struct sockaddr_in6 sin6; | |
| 426 | 426 | #endif |
| 427 | 427 | }; |
| 428 | 428 | |
| 429 | 429 | // Describes a string (chunk of memory). |
| 430 | 430 | struct vec { |
| 431 | const char *ptr; | |
| 432 | size_t len; | |
| 431 | const char *ptr; | |
| 432 | size_t len; | |
| 433 | 433 | }; |
| 434 | 434 | |
| 435 | 435 | struct file { |
| 436 | int is_directory; | |
| 437 | time_t modification_time; | |
| 438 | int64_t size; | |
| 439 | FILE *fp; | |
| 440 | const char *membuf; // Non-NULL if file data is in memory | |
| 441 | // set to 1 if the content is gzipped | |
| 442 | // in which case we need a content-encoding: gzip header | |
| 443 | int gzipped; | |
| 436 | int is_directory; | |
| 437 | time_t modification_time; | |
| 438 | int64_t size; | |
| 439 | FILE *fp; | |
| 440 | const char *membuf; // Non-NULL if file data is in memory | |
| 441 | // set to 1 if the content is gzipped | |
| 442 | // in which case we need a content-encoding: gzip header | |
| 443 | int gzipped; | |
| 444 | 444 | }; |
| 445 | 445 | #define STRUCT_FILE_INITIALIZER {0, 0, 0, NULL, NULL, 0} |
| 446 | 446 | |
| 447 | 447 | // Describes listening socket, or socket which was accept()-ed by the master |
| 448 | 448 | // thread and queued for future handling by the worker thread. |
| 449 | 449 | struct socket { |
| 450 | SOCKET sock; // Listening socket | |
| 451 | union usa lsa; // Local socket address | |
| 452 | union usa rsa; // Remote socket address | |
| 453 | unsigned is_ssl:1; // Is port SSL-ed | |
| 454 | unsigned ssl_redir:1; // Is port supposed to redirect everything to SSL port | |
| 450 | SOCKET sock; // Listening socket | |
| 451 | union usa lsa; // Local socket address | |
| 452 | union usa rsa; // Remote socket address | |
| 453 | unsigned is_ssl:1; // Is port SSL-ed | |
| 454 | unsigned ssl_redir:1; // Is port supposed to redirect everything to SSL port | |
| 455 | 455 | }; |
| 456 | 456 | |
| 457 | 457 | // NOTE(lsm): this enum shoulds be in sync with the config_options below. |
| 458 | 458 | enum { |
| 459 | CGI_EXTENSIONS, CGI_ENVIRONMENT, PUT_DELETE_PASSWORDS_FILE, CGI_INTERPRETER, | |
| 460 | PROTECT_URI, AUTHENTICATION_DOMAIN, SSI_EXTENSIONS, THROTTLE, | |
| 461 | ACCESS_LOG_FILE, ENABLE_DIRECTORY_LISTING, ERROR_LOG_FILE, | |
| 462 | GLOBAL_PASSWORDS_FILE, INDEX_FILES, ENABLE_KEEP_ALIVE, ACCESS_CONTROL_LIST, | |
| 463 | EXTRA_MIME_TYPES, LISTENING_PORTS, DOCUMENT_ROOT, SSL_CERTIFICATE, | |
| 464 | NUM_THREADS, RUN_AS_USER, REWRITE, HIDE_FILES, REQUEST_TIMEOUT, | |
| 465 | NUM_OPTIONS | |
| 459 | CGI_EXTENSIONS, CGI_ENVIRONMENT, PUT_DELETE_PASSWORDS_FILE, CGI_INTERPRETER, | |
| 460 | PROTECT_URI, AUTHENTICATION_DOMAIN, SSI_EXTENSIONS, THROTTLE, | |
| 461 | ACCESS_LOG_FILE, ENABLE_DIRECTORY_LISTING, ERROR_LOG_FILE, | |
| 462 | GLOBAL_PASSWORDS_FILE, INDEX_FILES, ENABLE_KEEP_ALIVE, ACCESS_CONTROL_LIST, | |
| 463 | EXTRA_MIME_TYPES, LISTENING_PORTS, DOCUMENT_ROOT, SSL_CERTIFICATE, | |
| 464 | NUM_THREADS, RUN_AS_USER, REWRITE, HIDE_FILES, REQUEST_TIMEOUT, | |
| 465 | NUM_OPTIONS | |
| 466 | 466 | }; |
| 467 | 467 | |
| 468 | 468 | static const char *config_options[] = { |
| 469 | "cgi_pattern", "**.cgi$|**.pl$|**.php$", | |
| 470 | "cgi_environment", NULL, | |
| 471 | "put_delete_auth_file", NULL, | |
| 472 | "cgi_interpreter", NULL, | |
| 473 | "protect_uri", NULL, | |
| 474 | "authentication_domain", "mydomain.com", | |
| 475 | "ssi_pattern", "**.shtml$|**.shtm$", | |
| 476 | "throttle", NULL, | |
| 477 | "access_log_file", NULL, | |
| 478 | "enable_directory_listing", "yes", | |
| 479 | "error_log_file", NULL, | |
| 480 | "global_auth_file", NULL, | |
| 481 | "index_files", | |
| 482 | "index.html,index.htm,index.cgi,index.shtml,index.php,index.lp", | |
| 483 | "enable_keep_alive", "no", | |
| 484 | "access_control_list", NULL, | |
| 485 | "extra_mime_types", NULL, | |
| 486 | "listening_ports", "8080", | |
| 487 | "document_root", ".", | |
| 488 | "ssl_certificate", NULL, | |
| 489 | "num_threads", "50", | |
| 490 | "run_as_user", NULL, | |
| 491 | "url_rewrite_patterns", NULL, | |
| 492 | "hide_files_patterns", NULL, | |
| 493 | "request_timeout_ms", "30000", | |
| 494 | NULL | |
| 469 | "cgi_pattern", "**.cgi$|**.pl$|**.php$", | |
| 470 | "cgi_environment", NULL, | |
| 471 | "put_delete_auth_file", NULL, | |
| 472 | "cgi_interpreter", NULL, | |
| 473 | "protect_uri", NULL, | |
| 474 | "authentication_domain", "mydomain.com", | |
| 475 | "ssi_pattern", "**.shtml$|**.shtm$", | |
| 476 | "throttle", NULL, | |
| 477 | "access_log_file", NULL, | |
| 478 | "enable_directory_listing", "yes", | |
| 479 | "error_log_file", NULL, | |
| 480 | "global_auth_file", NULL, | |
| 481 | "index_files", | |
| 482 | "index.html,index.htm,index.cgi,index.shtml,index.php,index.lp", | |
| 483 | "enable_keep_alive", "no", | |
| 484 | "access_control_list", NULL, | |
| 485 | "extra_mime_types", NULL, | |
| 486 | "listening_ports", "8080", | |
| 487 | "document_root", ".", | |
| 488 | "ssl_certificate", NULL, | |
| 489 | "num_threads", "50", | |
| 490 | "run_as_user", NULL, | |
| 491 | "url_rewrite_patterns", NULL, | |
| 492 | "hide_files_patterns", NULL, | |
| 493 | "request_timeout_ms", "30000", | |
| 494 | NULL | |
| 495 | 495 | }; |
| 496 | 496 | |
| 497 | 497 | struct mg_context { |
| 498 | volatile int stop_flag; // Should we stop event loop | |
| 499 | SSL_CTX *ssl_ctx; // SSL context | |
| 500 | char *config[NUM_OPTIONS]; // Mongoose configuration parameters | |
| 501 | struct mg_callbacks callbacks; // User-defined callback function | |
| 502 | void *user_data; // User-defined data | |
| 498 | volatile int stop_flag; // Should we stop event loop | |
| 499 | SSL_CTX *ssl_ctx; // SSL context | |
| 500 | char *config[NUM_OPTIONS]; // Mongoose configuration parameters | |
| 501 | struct mg_callbacks callbacks; // User-defined callback function | |
| 502 | void *user_data; // User-defined data | |
| 503 | 503 | |
| 504 | struct socket *listening_sockets; | |
| 505 | int num_listening_sockets; | |
| 504 | struct socket *listening_sockets; | |
| 505 | int num_listening_sockets; | |
| 506 | 506 | |
| 507 | volatile int num_threads; // Number of threads | |
| 508 | pthread_mutex_t mutex; // Protects (max|num)_threads | |
| 509 | pthread_cond_t cond; // Condvar for tracking workers terminations | |
| 507 | volatile int num_threads; // Number of threads | |
| 508 | pthread_mutex_t mutex; // Protects (max|num)_threads | |
| 509 | pthread_cond_t cond; // Condvar for tracking workers terminations | |
| 510 | 510 | |
| 511 | struct socket queue[20]; // Accepted sockets | |
| 512 | volatile int sq_head; // Head of the socket queue | |
| 513 | volatile int sq_tail; // Tail of the socket queue | |
| 514 | pthread_cond_t sq_full; // Signaled when socket is produced | |
| 515 | pthread_cond_t sq_empty; // Signaled when socket is consumed | |
| 511 | struct socket queue[20]; // Accepted sockets | |
| 512 | volatile int sq_head; // Head of the socket queue | |
| 513 | volatile int sq_tail; // Tail of the socket queue | |
| 514 | pthread_cond_t sq_full; // Signaled when socket is produced | |
| 515 | pthread_cond_t sq_empty; // Signaled when socket is consumed | |
| 516 | 516 | }; |
| 517 | 517 | |
| 518 | 518 | struct mg_connection { |
| 519 | struct mg_request_info request_info; | |
| 520 | struct mg_context *ctx; | |
| 521 | SSL *ssl; // SSL descriptor | |
| 522 | SSL_CTX *client_ssl_ctx; // SSL context for client connections | |
| 523 | struct socket client; // Connected client | |
| 524 | time_t birth_time; // Time when request was received | |
| 525 | int64_t num_bytes_sent; // Total bytes sent to client | |
| 526 | int64_t content_len; // Content-Length header value | |
| 527 | int64_t consumed_content; // How many bytes of content have been read | |
| 528 | char *buf; // Buffer for received data | |
| 529 | char *path_info; // PATH_INFO part of the URL | |
| 530 | int must_close; // 1 if connection must be closed | |
| 531 | int buf_size; // Buffer size | |
| 532 | int request_len; // Size of the request + headers in a buffer | |
| 533 | int data_len; // Total size of data in a buffer | |
| 534 | int status_code; // HTTP reply status code, e.g. 200 | |
| 535 | int throttle; // Throttling, bytes/sec. <= 0 means no throttle | |
| 536 | time_t last_throttle_time; // Last time throttled data was sent | |
| 537 | int64_t last_throttle_bytes;// Bytes sent this second | |
| 519 | struct mg_request_info request_info; | |
| 520 | struct mg_context *ctx; | |
| 521 | SSL *ssl; // SSL descriptor | |
| 522 | SSL_CTX *client_ssl_ctx; // SSL context for client connections | |
| 523 | struct socket client; // Connected client | |
| 524 | time_t birth_time; // Time when request was received | |
| 525 | int64_t num_bytes_sent; // Total bytes sent to client | |
| 526 | int64_t content_len; // Content-Length header value | |
| 527 | int64_t consumed_content; // How many bytes of content have been read | |
| 528 | char *buf; // Buffer for received data | |
| 529 | char *path_info; // PATH_INFO part of the URL | |
| 530 | int must_close; // 1 if connection must be closed | |
| 531 | int buf_size; // Buffer size | |
| 532 | int request_len; // Size of the request + headers in a buffer | |
| 533 | int data_len; // Total size of data in a buffer | |
| 534 | int status_code; // HTTP reply status code, e.g. 200 | |
| 535 | int throttle; // Throttling, bytes/sec. <= 0 means no throttle | |
| 536 | time_t last_throttle_time; // Last time throttled data was sent | |
| 537 | int64_t last_throttle_bytes;// Bytes sent this second | |
| 538 | 538 | }; |
| 539 | 539 | |
| 540 | 540 | // Directory entry |
| 541 | 541 | struct de { |
| 542 | struct mg_connection *conn; | |
| 543 | char *file_name; | |
| 544 | struct file file; | |
| 542 | struct mg_connection *conn; | |
| 543 | char *file_name; | |
| 544 | struct file file; | |
| 545 | 545 | }; |
| 546 | 546 | |
| 547 | 547 | const char **mg_get_valid_option_names(void) { |
| 548 | ||
| 548 | return config_options; | |
| 549 | 549 | } |
| 550 | 550 | |
| 551 | 551 | static int is_file_in_memory(struct mg_connection *conn, const char *path, |
| 552 | struct file *filep) { | |
| 553 | size_t size = 0; | |
| 554 | if ((filep->membuf = conn->ctx->callbacks.open_file == NULL ? NULL : | |
| 555 | conn->ctx->callbacks.open_file(conn, path, &size)) != NULL) { | |
| 556 | // NOTE: override filep->size only on success. Otherwise, it might break | |
| 557 | // constructs like if (!mg_stat() || !mg_fopen()) ... | |
| 558 | filep->size = size; | |
| 559 | } | |
| 560 | return filep->membuf != NULL; | |
| 552 | struct file *filep) { | |
| 553 | size_t size = 0; | |
| 554 | if ((filep->membuf = conn->ctx->callbacks.open_file == NULL ? NULL : | |
| 555 | conn->ctx->callbacks.open_file(conn, path, &size)) != NULL) { | |
| 556 | // NOTE: override filep->size only on success. Otherwise, it might break | |
| 557 | // constructs like if (!mg_stat() || !mg_fopen()) ... | |
| 558 | filep->size = size; | |
| 559 | } | |
| 560 | return filep->membuf != NULL; | |
| 561 | 561 | } |
| 562 | 562 | |
| 563 | 563 | static int is_file_opened(const struct file *filep) { |
| 564 | ||
| 564 | return filep->membuf != NULL || filep->fp != NULL; | |
| 565 | 565 | } |
| 566 | 566 | |
| 567 | 567 | static int mg_fopen(struct mg_connection *conn, const char *path, |
| 568 | const char *mode, struct file *filep) { | |
| 569 | if (!is_file_in_memory(conn, path, filep)) { | |
| 568 | const char *mode, struct file *filep) { | |
| 569 | if (!is_file_in_memory(conn, path, filep)) { | |
| 570 | 570 | #ifdef _WIN32 |
| 571 | wchar_t wbuf[PATH_MAX], wmode[20]; | |
| 572 | to_unicode(path, wbuf, ARRAY_SIZE(wbuf)); | |
| 573 | MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, ARRAY_SIZE(wmode)); | |
| 574 | filep->fp = _wfopen(wbuf, wmode); | |
| 571 | wchar_t wbuf[PATH_MAX], wmode[20]; | |
| 572 | to_unicode(path, wbuf, ARRAY_SIZE(wbuf)); | |
| 573 | MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, ARRAY_SIZE(wmode)); | |
| 574 | filep->fp = _wfopen(wbuf, wmode); | |
| 575 | 575 | #else |
| 576 | ||
| 576 | filep->fp = fopen(path, mode); | |
| 577 | 577 | #endif |
| 578 | ||
| 578 | } | |
| 579 | 579 | |
| 580 | ||
| 580 | return is_file_opened(filep); | |
| 581 | 581 | } |
| 582 | 582 | |
| 583 | 583 | static void mg_fclose(struct file *filep) { |
| 584 | if (filep != NULL && filep->fp != NULL) { | |
| 585 | fclose(filep->fp); | |
| 586 | } | |
| 584 | if (filep != NULL && filep->fp != NULL) { | |
| 585 | fclose(filep->fp); | |
| 586 | } | |
| 587 | 587 | } |
| 588 | 588 | |
| 589 | 589 | static int get_option_index(const char *name) { |
| 590 | ||
| 590 | int i; | |
| 591 | 591 | |
| 592 | for (i = 0; config_options[i * 2] != NULL; i++) { | |
| 593 | if (strcmp(config_options[i * 2], name) == 0) { | |
| 594 | return i; | |
| 595 | } | |
| 596 | } | |
| 597 | return -1; | |
| 592 | for (i = 0; config_options[i * 2] != NULL; i++) { | |
| 593 | if (strcmp(config_options[i * 2], name) == 0) { | |
| 594 | return i; | |
| 595 | } | |
| 596 | } | |
| 597 | return -1; | |
| 598 | 598 | } |
| 599 | 599 | |
| 600 | 600 | const char *mg_get_option(const struct mg_context *ctx, const char *name) { |
| 601 | int i; | |
| 602 | if ((i = get_option_index(name)) == -1) { | |
| 603 | return NULL; | |
| 604 | } else if (ctx->config[i] == NULL) { | |
| 605 | return ""; | |
| 606 | } else { | |
| 607 | return ctx->config[i]; | |
| 608 | } | |
| 601 | int i; | |
| 602 | if ((i = get_option_index(name)) == -1) { | |
| 603 | return NULL; | |
| 604 | } else if (ctx->config[i] == NULL) { | |
| 605 | return ""; | |
| 606 | } else { | |
| 607 | return ctx->config[i]; | |
| 608 | } | |
| 609 | 609 | } |
| 610 | 610 | |
| 611 | 611 | static void sockaddr_to_string(char *buf, size_t len, |
| 612 | const union usa *usa) { | |
| 613 | buf[0] = '\0'; | |
| 612 | const union usa *usa) { | |
| 613 | buf[0] = '\0'; | |
| 614 | 614 | #if defined(USE_IPV6) |
| 615 | inet_ntop(usa->sa.sa_family, usa->sa.sa_family == AF_INET ? | |
| 616 | (void *) &usa->sin.sin_addr : | |
| 617 | (void *) &usa->sin6.sin6_addr, buf, len); | |
| 615 | inet_ntop(usa->sa.sa_family, usa->sa.sa_family == AF_INET ? | |
| 616 | (void *) &usa->sin.sin_addr : | |
| 617 | (void *) &usa->sin6.sin6_addr, buf, len); | |
| 618 | 618 | #elif defined(_WIN32) |
| 619 | // Only Windoze Vista (and newer) have inet_ntop() | |
| 620 | strncpy(buf, inet_ntoa(usa->sin.sin_addr), len); | |
| 619 | // Only Windoze Vista (and newer) have inet_ntop() | |
| 620 | strncpy(buf, inet_ntoa(usa->sin.sin_addr), len); | |
| 621 | 621 | #else |
| 622 | ||
| 622 | inet_ntop(usa->sa.sa_family, (void *) &usa->sin.sin_addr, buf, len); | |
| 623 | 623 | #endif |
| 624 | 624 | } |
| 625 | 625 | |
| 626 | 626 | static void cry(struct mg_connection *conn, |
| 627 | ||
| 627 | PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(2, 3); | |
| 628 | 628 | |
| 629 | 629 | // Print error message to the opened error log stream. |
| 630 | 630 | static void cry(struct mg_connection *conn, const char *fmt, ...) { |
| 631 | char buf[MG_BUF_LEN], src_addr[IP_ADDR_STR_LEN]; | |
| 632 | va_list ap; | |
| 633 | FILE *fp; | |
| 634 | time_t timestamp; | |
| 631 | char buf[MG_BUF_LEN], src_addr[IP_ADDR_STR_LEN]; | |
| 632 | va_list ap; | |
| 633 | FILE *fp; | |
| 634 | time_t timestamp; | |
| 635 | 635 | |
| 636 | va_start(ap, fmt); | |
| 637 | (void) vsnprintf(buf, sizeof(buf), fmt, ap); | |
| 638 | va_end(ap); | |
| 636 | va_start(ap, fmt); | |
| 637 | (void) vsnprintf(buf, sizeof(buf), fmt, ap); | |
| 638 | va_end(ap); | |
| 639 | 639 | |
| 640 | // Do not lock when getting the callback value, here and below. | |
| 641 | // I suppose this is fine, since function cannot disappear in the | |
| 642 | // same way string option can. | |
| 643 | if (conn->ctx->callbacks.log_message == NULL || | |
| 644 | conn->ctx->callbacks.log_message(conn, buf) == 0) { | |
| 645 | fp = conn->ctx == NULL || conn->ctx->config[ERROR_LOG_FILE] == NULL ? NULL : | |
| 646 | fopen(conn->ctx->config[ERROR_LOG_FILE], "a+"); | |
| 640 | // Do not lock when getting the callback value, here and below. | |
| 641 | // I suppose this is fine, since function cannot disappear in the | |
| 642 | // same way string option can. | |
| 643 | if (conn->ctx->callbacks.log_message == NULL || | |
| 644 | conn->ctx->callbacks.log_message(conn, buf) == 0) { | |
| 645 | fp = conn->ctx == NULL || conn->ctx->config[ERROR_LOG_FILE] == NULL ? NULL : | |
| 646 | fopen(conn->ctx->config[ERROR_LOG_FILE], "a+"); | |
| 647 | 647 | |
| 648 | if (fp != NULL) { | |
| 649 | flockfile(fp); | |
| 650 | timestamp = time(NULL); | |
| 648 | if (fp != NULL) { | |
| 649 | flockfile(fp); | |
| 650 | timestamp = time(NULL); | |
| 651 | 651 | |
| 652 | sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa); | |
| 653 | fprintf(fp, "[%010lu] [error] [client %s] ", (unsigned long) timestamp, | |
| 654 | src_addr); | |
| 652 | sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa); | |
| 653 | fprintf(fp, "[%010lu] [error] [client %s] ", (unsigned long) timestamp, | |
| 654 | src_addr); | |
| 655 | 655 | |
| 656 | if (conn->request_info.request_method != NULL) { | |
| 657 | fprintf(fp, "%s %s: ", conn->request_info.request_method, | |
| 658 | conn->request_info.uri); | |
| 659 | } | |
| 656 | if (conn->request_info.request_method != NULL) { | |
| 657 | fprintf(fp, "%s %s: ", conn->request_info.request_method, | |
| 658 | conn->request_info.uri); | |
| 659 | } | |
| 660 | 660 | |
| 661 | fprintf(fp, "%s", buf); | |
| 662 | fputc('\n', fp); | |
| 663 | funlockfile(fp); | |
| 664 | fclose(fp); | |
| 665 | } | |
| 666 | } | |
| 661 | fprintf(fp, "%s", buf); | |
| 662 | fputc('\n', fp); | |
| 663 | funlockfile(fp); | |
| 664 | fclose(fp); | |
| 665 | } | |
| 666 | } | |
| 667 | 667 | } |
| 668 | 668 | |
| 669 | 669 | // Return fake connection structure. Used for logging, if connection |
| 670 | 670 | // is not applicable at the moment of logging. |
| 671 | 671 | static struct mg_connection *fc(struct mg_context *ctx) { |
| 672 | static struct mg_connection fake_connection; | |
| 673 | fake_connection.ctx = ctx; | |
| 674 | return &fake_connection; | |
| 672 | static struct mg_connection fake_connection; | |
| 673 | fake_connection.ctx = ctx; | |
| 674 | return &fake_connection; | |
| 675 | 675 | } |
| 676 | 676 | |
| 677 | 677 | const char *mg_version(void) { |
| 678 | ||
| 678 | return MONGOOSE_VERSION; | |
| 679 | 679 | } |
| 680 | 680 | |
| 681 | 681 | struct mg_request_info *mg_get_request_info(struct mg_connection *conn) { |
| 682 | ||
| 682 | return &conn->request_info; | |
| 683 | 683 | } |
| 684 | 684 | |
| 685 | 685 | static void mg_strlcpy(register char *dst, register const char *src, size_t n) { |
| 686 | for (; *src != '\0' && n > 1; n--) { | |
| 687 | *dst++ = *src++; | |
| 688 | } | |
| 689 | *dst = '\0'; | |
| 686 | for (; *src != '\0' && n > 1; n--) { | |
| 687 | *dst++ = *src++; | |
| 688 | } | |
| 689 | *dst = '\0'; | |
| 690 | 690 | } |
| 691 | 691 | |
| 692 | 692 | static int lowercase(const char *s) { |
| 693 | ||
| 693 | return tolower(* (const unsigned char *) s); | |
| 694 | 694 | } |
| 695 | 695 | |
| 696 | 696 | static int mg_strncasecmp(const char *s1, const char *s2, size_t len) { |
| 697 | ||
| 697 | int diff = 0; | |
| 698 | 698 | |
| 699 | if (len > 0) | |
| 700 | do { | |
| 701 | diff = lowercase(s1++) - lowercase(s2++); | |
| 702 | } while (diff == 0 && s1[-1] != '\0' && --len > 0); | |
| 699 | if (len > 0) | |
| 700 | do { | |
| 701 | diff = lowercase(s1++) - lowercase(s2++); | |
| 702 | } while (diff == 0 && s1[-1] != '\0' && --len > 0); | |
| 703 | 703 | |
| 704 | ||
| 704 | return diff; | |
| 705 | 705 | } |
| 706 | 706 | |
| 707 | 707 | static int mg_strcasecmp(const char *s1, const char *s2) { |
| 708 | ||
| 708 | int diff; | |
| 709 | 709 | |
| 710 | do { | |
| 711 | diff = lowercase(s1++) - lowercase(s2++); | |
| 712 | } while (diff == 0 && s1[-1] != '\0'); | |
| 710 | do { | |
| 711 | diff = lowercase(s1++) - lowercase(s2++); | |
| 712 | } while (diff == 0 && s1[-1] != '\0'); | |
| 713 | 713 | |
| 714 | ||
| 714 | return diff; | |
| 715 | 715 | } |
| 716 | 716 | |
| 717 | 717 | static char * mg_strndup(const char *ptr, size_t len) { |
| 718 | ||
| 718 | char *p; | |
| 719 | 719 | |
| 720 | if ((p = (char *) malloc(len + 1)) != NULL) { | |
| 721 | mg_strlcpy(p, ptr, len + 1); | |
| 722 | } | |
| 720 | if ((p = (char *) malloc(len + 1)) != NULL) { | |
| 721 | mg_strlcpy(p, ptr, len + 1); | |
| 722 | } | |
| 723 | 723 | |
| 724 | ||
| 724 | return p; | |
| 725 | 725 | } |
| 726 | 726 | |
| 727 | 727 | static char * mg_strdup(const char *str) { |
| 728 | ||
| 728 | return mg_strndup(str, strlen(str)); | |
| 729 | 729 | } |
| 730 | 730 | |
| 731 | 731 | static const char *mg_strcasestr(const char *big_str, const char *small_str) { |
| 732 | ||
| 732 | int i, big_len = strlen(big_str), small_len = strlen(small_str); | |
| 733 | 733 | |
| 734 | for (i = 0; i <= big_len - small_len; i++) { | |
| 735 | if (mg_strncasecmp(big_str + i, small_str, small_len) == 0) { | |
| 736 | return big_str + i; | |
| 737 | } | |
| 738 | } | |
| 734 | for (i = 0; i <= big_len - small_len; i++) { | |
| 735 | if (mg_strncasecmp(big_str + i, small_str, small_len) == 0) { | |
| 736 | return big_str + i; | |
| 737 | } | |
| 738 | } | |
| 739 | 739 | |
| 740 | ||
| 740 | return NULL; | |
| 741 | 741 | } |
| 742 | 742 | |
| 743 | 743 | // Like snprintf(), but never returns negative value, or a value |
| r25360 | r25361 | |
| 745 | 745 | // Thanks to Adam Zeldis to pointing snprintf()-caused vulnerability |
| 746 | 746 | // in his audit report. |
| 747 | 747 | static int mg_vsnprintf(struct mg_connection *conn, char *buf, size_t buflen, |
| 748 | const char *fmt, va_list ap) { | |
| 749 | int n; | |
| 748 | const char *fmt, va_list ap) { | |
| 749 | int n; | |
| 750 | 750 | |
| 751 | if (buflen == 0) | |
| 752 | return 0; | |
| 751 | if (buflen == 0) | |
| 752 | return 0; | |
| 753 | 753 | |
| 754 | ||
| 754 | n = vsnprintf(buf, buflen, fmt, ap); | |
| 755 | 755 | |
| 756 | if (n < 0) { | |
| 757 | cry(conn, "vsnprintf error"); | |
| 758 | n = 0; | |
| 759 | } else if (n >= (int) buflen) { | |
| 760 | cry(conn, "truncating vsnprintf buffer: [%.*s]", | |
| 761 | n > 200 ? 200 : n, buf); | |
| 762 | n = (int) buflen - 1; | |
| 763 | } | |
| 764 | buf[n] = '\0'; | |
| 756 | if (n < 0) { | |
| 757 | cry(conn, "vsnprintf error"); | |
| 758 | n = 0; | |
| 759 | } else if (n >= (int) buflen) { | |
| 760 | cry(conn, "truncating vsnprintf buffer: [%.*s]", | |
| 761 | n > 200 ? 200 : n, buf); | |
| 762 | n = (int) buflen - 1; | |
| 763 | } | |
| 764 | buf[n] = '\0'; | |
| 765 | 765 | |
| 766 | ||
| 766 | return n; | |
| 767 | 767 | } |
| 768 | 768 | |
| 769 | 769 | static int mg_snprintf(struct mg_connection *conn, char *buf, size_t buflen, |
| 770 | PRINTF_FORMAT_STRING(const char *fmt), ...) | |
| 771 | PRINTF_ARGS(4, 5); | |
| 770 | PRINTF_FORMAT_STRING(const char *fmt), ...) | |
| 771 | PRINTF_ARGS(4, 5); | |
| 772 | 772 | |
| 773 | 773 | static int mg_snprintf(struct mg_connection *conn, char *buf, size_t buflen, |
| 774 | const char *fmt, ...) { | |
| 775 | va_list ap; | |
| 776 | int n; | |
| 774 | const char *fmt, ...) { | |
| 775 | va_list ap; | |
| 776 | int n; | |
| 777 | 777 | |
| 778 | va_start(ap, fmt); | |
| 779 | n = mg_vsnprintf(conn, buf, buflen, fmt, ap); | |
| 780 | va_end(ap); | |
| 778 | va_start(ap, fmt); | |
| 779 | n = mg_vsnprintf(conn, buf, buflen, fmt, ap); | |
| 780 | va_end(ap); | |
| 781 | 781 | |
| 782 | ||
| 782 | return n; | |
| 783 | 783 | } |
| 784 | 784 | |
| 785 | 785 | // Skip the characters until one of the delimiters characters found. |
| r25360 | r25361 | |
| 787 | 787 | // Advance pointer to buffer to the next word. Return found 0-terminated word. |
| 788 | 788 | // Delimiters can be quoted with quotechar. |
| 789 | 789 | static char *skip_quoted(char **buf, const char *delimiters, |
| 790 | const char *whitespace, char quotechar) { | |
| 791 | char *p, *begin_word, *end_word, *end_whitespace; | |
| 790 | const char *whitespace, char quotechar) { | |
| 791 | char *p, *begin_word, *end_word, *end_whitespace; | |
| 792 | 792 | |
| 793 | begin_word = *buf; | |
| 794 | end_word = begin_word + strcspn(begin_word, delimiters); | |
| 793 | begin_word = *buf; | |
| 794 | end_word = begin_word + strcspn(begin_word, delimiters); | |
| 795 | 795 | |
| 796 | // Check for quotechar | |
| 797 | if (end_word > begin_word) { | |
| 798 | p = end_word - 1; | |
| 799 | while (*p == quotechar) { | |
| 800 | // If there is anything beyond end_word, copy it | |
| 801 | if (*end_word == '\0') { | |
| 802 | *p = '\0'; | |
| 803 | break; | |
| 804 | } else { | |
| 805 | size_t end_off = strcspn(end_word + 1, delimiters); | |
| 806 | memmove (p, end_word, end_off + 1); | |
| 807 | p += end_off; // p must correspond to end_word - 1 | |
| 808 | end_word += end_off + 1; | |
| 809 | } | |
| 810 | } | |
| 811 | for (p++; p < end_word; p++) { | |
| 812 | *p = '\0'; | |
| 813 | } | |
| 814 | } | |
| 796 | // Check for quotechar | |
| 797 | if (end_word > begin_word) { | |
| 798 | p = end_word - 1; | |
| 799 | while (*p == quotechar) { | |
| 800 | // If there is anything beyond end_word, copy it | |
| 801 | if (*end_word == '\0') { | |
| 802 | *p = '\0'; | |
| 803 | break; | |
| 804 | } else { | |
| 805 | size_t end_off = strcspn(end_word + 1, delimiters); | |
| 806 | memmove (p, end_word, end_off + 1); | |
| 807 | p += end_off; // p must correspond to end_word - 1 | |
| 808 | end_word += end_off + 1; | |
| 809 | } | |
| 810 | } | |
| 811 | for (p++; p < end_word; p++) { | |
| 812 | *p = '\0'; | |
| 813 | } | |
| 814 | } | |
| 815 | 815 | |
| 816 | if (*end_word == '\0') { | |
| 817 | *buf = end_word; | |
| 818 | } else { | |
| 819 | end_whitespace = end_word + 1 + strspn(end_word + 1, whitespace); | |
| 816 | if (*end_word == '\0') { | |
| 817 | *buf = end_word; | |
| 818 | } else { | |
| 819 | end_whitespace = end_word + 1 + strspn(end_word + 1, whitespace); | |
| 820 | 820 | |
| 821 | for (p = end_word; p < end_whitespace; p++) { | |
| 822 | *p = '\0'; | |
| 823 | } | |
| 821 | for (p = end_word; p < end_whitespace; p++) { | |
| 822 | *p = '\0'; | |
| 823 | } | |
| 824 | 824 | |
| 825 | *buf = end_whitespace; | |
| 826 | } | |
| 825 | *buf = end_whitespace; | |
| 826 | } | |
| 827 | 827 | |
| 828 | ||
| 828 | return begin_word; | |
| 829 | 829 | } |
| 830 | 830 | |
| 831 | 831 | // Simplified version of skip_quoted without quote char |
| 832 | 832 | // and whitespace == delimiters |
| 833 | 833 | static char *skip(char **buf, const char *delimiters) { |
| 834 | ||
| 834 | return skip_quoted(buf, delimiters, delimiters, 0); | |
| 835 | 835 | } |
| 836 | 836 | |
| 837 | 837 | |
| 838 | 838 | // Return HTTP header value, or NULL if not found. |
| 839 | 839 | static const char *get_header(const struct mg_request_info *ri, |
| 840 | const char *name) { | |
| 841 | int i; | |
| 840 | const char *name) { | |
| 841 | int i; | |
| 842 | 842 | |
| 843 | for (i = 0; i < ri->num_headers; i++) | |
| 844 | if (!mg_strcasecmp(name, ri->http_headers[i].name)) | |
| 845 | return ri->http_headers[i].value; | |
| 843 | for (i = 0; i < ri->num_headers; i++) | |
| 844 | if (!mg_strcasecmp(name, ri->http_headers[i].name)) | |
| 845 | return ri->http_headers[i].value; | |
| 846 | 846 | |
| 847 | ||
| 847 | return NULL; | |
| 848 | 848 | } |
| 849 | 849 | |
| 850 | 850 | const char *mg_get_header(const struct mg_connection *conn, const char *name) { |
| 851 | ||
| 851 | return get_header(&conn->request_info, name); | |
| 852 | 852 | } |
| 853 | 853 | |
| 854 | 854 | // A helper function for traversing a comma separated list of values. |
| r25360 | r25361 | |
| 858 | 858 | // vector is initialized to point to the "y" part, and val vector length |
| 859 | 859 | // is adjusted to point only to "x". |
| 860 | 860 | static const char *next_option(const char *list, struct vec *val, |
| 861 | struct vec *eq_val) { | |
| 862 | if (list == NULL || *list == '\0') { | |
| 863 | // End of the list | |
| 864 | list = NULL; | |
| 865 | } else { | |
| 866 | val->ptr = list; | |
| 867 | if ((list = strchr(val->ptr, ',')) != NULL) { | |
| 868 | // Comma found. Store length and shift the list ptr | |
| 869 | val->len = list - val->ptr; | |
| 870 | list++; | |
| 871 | } else { | |
| 872 | // This value is the last one | |
| 873 | list = val->ptr + strlen(val->ptr); | |
| 874 | val->len = list - val->ptr; | |
| 875 | } | |
| 861 | struct vec *eq_val) { | |
| 862 | if (list == NULL || *list == '\0') { | |
| 863 | // End of the list | |
| 864 | list = NULL; | |
| 865 | } else { | |
| 866 | val->ptr = list; | |
| 867 | if ((list = strchr(val->ptr, ',')) != NULL) { | |
| 868 | // Comma found. Store length and shift the list ptr | |
| 869 | val->len = list - val->ptr; | |
| 870 | list++; | |
| 871 | } else { | |
| 872 | // This value is the last one | |
| 873 | list = val->ptr + strlen(val->ptr); | |
| 874 | val->len = list - val->ptr; | |
| 875 | } | |
| 876 | 876 | |
| 877 | if (eq_val != NULL) { | |
| 878 | // Value has form "x=y", adjust pointers and lengths | |
| 879 | // so that val points to "x", and eq_val points to "y". | |
| 880 | eq_val->len = 0; | |
| 881 | eq_val->ptr = (const char *) memchr(val->ptr, '=', val->len); | |
| 882 | if (eq_val->ptr != NULL) { | |
| 883 | eq_val->ptr++; // Skip over '=' character | |
| 884 | eq_val->len = val->ptr + val->len - eq_val->ptr; | |
| 885 | val->len = (eq_val->ptr - val->ptr) - 1; | |
| 886 | } | |
| 887 | } | |
| 888 | } | |
| 877 | if (eq_val != NULL) { | |
| 878 | // Value has form "x=y", adjust pointers and lengths | |
| 879 | // so that val points to "x", and eq_val points to "y". | |
| 880 | eq_val->len = 0; | |
| 881 | eq_val->ptr = (const char *) memchr(val->ptr, '=', val->len); | |
| 882 | if (eq_val->ptr != NULL) { | |
| 883 | eq_val->ptr++; // Skip over '=' character | |
| 884 | eq_val->len = val->ptr + val->len - eq_val->ptr; | |
| 885 | val->len = (eq_val->ptr - val->ptr) - 1; | |
| 886 | } | |
| 887 | } | |
| 888 | } | |
| 889 | 889 | |
| 890 | ||
| 890 | return list; | |
| 891 | 891 | } |
| 892 | 892 | |
| 893 | 893 | static int match_prefix(const char *pattern, int pattern_len, const char *str) { |
| 894 | const char *or_str; | |
| 895 | int i, j, len, res; | |
| 894 | const char *or_str; | |
| 895 | int i, j, len, res; | |
| 896 | 896 | |
| 897 | if ((or_str = (const char *) memchr(pattern, '|', pattern_len)) != NULL) { | |
| 898 | res = match_prefix(pattern, or_str - pattern, str); | |
| 899 | return res > 0 ? res : | |
| 900 | match_prefix(or_str + 1, (pattern + pattern_len) - (or_str + 1), str); | |
| 901 | } | |
| 897 | if ((or_str = (const char *) memchr(pattern, '|', pattern_len)) != NULL) { | |
| 898 | res = match_prefix(pattern, or_str - pattern, str); | |
| 899 | return res > 0 ? res : | |
| 900 | match_prefix(or_str + 1, (pattern + pattern_len) - (or_str + 1), str); | |
| 901 | } | |
| 902 | 902 | |
| 903 | i = j = 0; | |
| 904 | res = -1; | |
| 905 | for (; i < pattern_len; i++, j++) { | |
| 906 | if (pattern[i] == '?' && str[j] != '\0') { | |
| 907 | continue; | |
| 908 | } else if (pattern[i] == '$') { | |
| 909 | return str[j] == '\0' ? j : -1; | |
| 910 | } else if (pattern[i] == '*') { | |
| 911 | i++; | |
| 912 | if (pattern[i] == '*') { | |
| 913 | i++; | |
| 914 | len = (int) strlen(str + j); | |
| 915 | } else { | |
| 916 | len = (int) strcspn(str + j, "/"); | |
| 917 | } | |
| 918 | if (i == pattern_len) { | |
| 919 | return j + len; | |
| 920 | } | |
| 921 | do { | |
| 922 | res = match_prefix(pattern + i, pattern_len - i, str + j + len); | |
| 923 | } while (res == -1 && len-- > 0); | |
| 924 | return res == -1 ? -1 : j + res + len; | |
| 925 | } else if (pattern[i] != str[j]) { | |
| 926 | return -1; | |
| 927 | } | |
| 928 | } | |
| 929 | return j; | |
| 903 | i = j = 0; | |
| 904 | res = -1; | |
| 905 | for (; i < pattern_len; i++, j++) { | |
| 906 | if (pattern[i] == '?' && str[j] != '\0') { | |
| 907 | continue; | |
| 908 | } else if (pattern[i] == '$') { | |
| 909 | return str[j] == '\0' ? j : -1; | |
| 910 | } else if (pattern[i] == '*') { | |
| 911 | i++; | |
| 912 | if (pattern[i] == '*') { | |
| 913 | i++; | |
| 914 | len = (int) strlen(str + j); | |
| 915 | } else { | |
| 916 | len = (int) strcspn(str + j, "/"); | |
| 917 | } | |
| 918 | if (i == pattern_len) { | |
| 919 | return j + len; | |
| 920 | } | |
| 921 | do { | |
| 922 | res = match_prefix(pattern + i, pattern_len - i, str + j + len); | |
| 923 | } while (res == -1 && len-- > 0); | |
| 924 | return res == -1 ? -1 : j + res + len; | |
| 925 | } else if (pattern[i] != str[j]) { | |
| 926 | return -1; | |
| 927 | } | |
| 928 | } | |
| 929 | return j; | |
| 930 | 930 | } |
| 931 | 931 | |
| 932 | 932 | // HTTP 1.1 assumes keep alive if "Connection:" header is not set |
| 933 | 933 | // This function must tolerate situations when connection info is not |
| 934 | 934 | // set up, for example if request parsing failed. |
| 935 | 935 | static int should_keep_alive(const struct mg_connection *conn) { |
| 936 | const char *http_version = conn->request_info.http_version; | |
| 937 | const char *header = mg_get_header(conn, "Connection"); | |
| 938 | if (conn->must_close || | |
| 939 | conn->status_code == 401 || | |
| 940 | mg_strcasecmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes") != 0 || | |
| 941 | (header != NULL && mg_strcasecmp(header, "keep-alive") != 0) || | |
| 942 | (header == NULL && http_version && strcmp(http_version, "1.1"))) { | |
| 943 | return 0; | |
| 944 | } | |
| 945 | return 1; | |
| 936 | const char *http_version = conn->request_info.http_version; | |
| 937 | const char *header = mg_get_header(conn, "Connection"); | |
| 938 | if (conn->must_close || | |
| 939 | conn->status_code == 401 || | |
| 940 | mg_strcasecmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes") != 0 || | |
| 941 | (header != NULL && mg_strcasecmp(header, "keep-alive") != 0) || | |
| 942 | (header == NULL && http_version && strcmp(http_version, "1.1"))) { | |
| 943 | return 0; | |
| 944 | } | |
| 945 | return 1; | |
| 946 | 946 | } |
| 947 | 947 | |
| 948 | 948 | static const char *suggest_connection_header(const struct mg_connection *conn) { |
| 949 | ||
| 949 | return should_keep_alive(conn) ? "keep-alive" : "close"; | |
| 950 | 950 | } |
| 951 | 951 | |
| 952 | 952 | static void send_http_error(struct mg_connection *, int, const char *, |
| 953 | PRINTF_FORMAT_STRING(const char *fmt), ...) | |
| 954 | PRINTF_ARGS(4, 5); | |
| 953 | PRINTF_FORMAT_STRING(const char *fmt), ...) | |
| 954 | PRINTF_ARGS(4, 5); | |
| 955 | 955 | |
| 956 | 956 | |
| 957 | 957 | static void send_http_error(struct mg_connection *conn, int status, |
| 958 | const char *reason, const char *fmt, ...) { | |
| 959 | char buf[MG_BUF_LEN]; | |
| 960 | va_list ap; | |
| 961 | int len = 0; | |
| 958 | const char *reason, const char *fmt, ...) { | |
| 959 | char buf[MG_BUF_LEN]; | |
| 960 | va_list ap; | |
| 961 | int len = 0; | |
| 962 | 962 | |
| 963 | conn->status_code = status; | |
| 964 | if (conn->ctx->callbacks.http_error == NULL || | |
| 965 | conn->ctx->callbacks.http_error(conn, status)) { | |
| 966 | buf[0] = '\0'; | |
| 963 | conn->status_code = status; | |
| 964 | if (conn->ctx->callbacks.http_error == NULL || | |
| 965 | conn->ctx->callbacks.http_error(conn, status)) { | |
| 966 | buf[0] = '\0'; | |
| 967 | 967 | |
| 968 | // Errors 1xx, 204 and 304 MUST NOT send a body | |
| 969 | if (status > 199 && status != 204 && status != 304) { | |
| 970 | len = mg_snprintf(conn, buf, sizeof(buf), "Error %d: %s", status, reason); | |
| 971 | buf[len++] = '\n'; | |
| 968 | // Errors 1xx, 204 and 304 MUST NOT send a body | |
| 969 | if (status > 199 && status != 204 && status != 304) { | |
| 970 | len = mg_snprintf(conn, buf, sizeof(buf), "Error %d: %s", status, reason); | |
| 971 | buf[len++] = '\n'; | |
| 972 | 972 | |
| 973 | va_start(ap, fmt); | |
| 974 | len += mg_vsnprintf(conn, buf + len, sizeof(buf) - len, fmt, ap); | |
| 975 | va_end(ap); | |
| 976 | } | |
| 977 | DEBUG_TRACE(("[%s]", buf)); | |
| 973 | va_start(ap, fmt); | |
| 974 | len += mg_vsnprintf(conn, buf + len, sizeof(buf) - len, fmt, ap); | |
| 975 | va_end(ap); | |
| 976 | } | |
| 977 | DEBUG_TRACE(("[%s]", buf)); | |
| 978 | 978 | |
| 979 | mg_printf(conn, "HTTP/1.1 %d %s\r\n" | |
| 980 | "Content-Length: %d\r\n" | |
| 981 | "Connection: %s\r\n\r\n", status, reason, len, | |
| 982 | suggest_connection_header(conn)); | |
| 983 | conn->num_bytes_sent += mg_printf(conn, "%s", buf); | |
| 984 | } | |
| 979 | mg_printf(conn, "HTTP/1.1 %d %s\r\n" | |
| 980 | "Content-Length: %d\r\n" | |
| 981 | "Connection: %s\r\n\r\n", status, reason, len, | |
| 982 | suggest_connection_header(conn)); | |
| 983 | conn->num_bytes_sent += mg_printf(conn, "%s", buf); | |
| 984 | } | |
| 985 | 985 | } |
| 986 | 986 | |
| 987 | 987 | #if defined(_WIN32) && !defined(__SYMBIAN32__) |
| 988 | 988 | static int pthread_mutex_init(pthread_mutex_t *mutex, void *unused) { |
| 989 | (void) unused; | |
| 990 | *mutex = CreateMutex(NULL, FALSE, NULL); | |
| 991 | return *mutex == NULL ? -1 : 0; | |
| 989 | (void) unused; | |
| 990 | *mutex = CreateMutex(NULL, FALSE, NULL); | |
| 991 | return *mutex == NULL ? -1 : 0; | |
| 992 | 992 | } |
| 993 | 993 | |
| 994 | 994 | static int pthread_mutex_destroy(pthread_mutex_t *mutex) { |
| 995 | ||
| 995 | return CloseHandle(*mutex) == 0 ? -1 : 0; | |
| 996 | 996 | } |
| 997 | 997 | |
| 998 | 998 | static int pthread_mutex_lock(pthread_mutex_t *mutex) { |
| 999 | ||
| 999 | return WaitForSingleObject(*mutex, INFINITE) == WAIT_OBJECT_0? 0 : -1; | |
| 1000 | 1000 | } |
| 1001 | 1001 | |
| 1002 | 1002 | static int pthread_mutex_unlock(pthread_mutex_t *mutex) { |
| 1003 | ||
| 1003 | return ReleaseMutex(*mutex) == 0 ? -1 : 0; | |
| 1004 | 1004 | } |
| 1005 | 1005 | |
| 1006 | 1006 | static int pthread_cond_init(pthread_cond_t *cv, const void *unused) { |
| 1007 | (void) unused; | |
| 1008 | cv->signal = CreateEvent(NULL, FALSE, FALSE, NULL); | |
| 1009 | cv->broadcast = CreateEvent(NULL, TRUE, FALSE, NULL); | |
| 1010 | return cv->signal != NULL && cv->broadcast != NULL ? 0 : -1; | |
| 1007 | (void) unused; | |
| 1008 | cv->signal = CreateEvent(NULL, FALSE, FALSE, NULL); | |
| 1009 | cv->broadcast = CreateEvent(NULL, TRUE, FALSE, NULL); | |
| 1010 | return cv->signal != NULL && cv->broadcast != NULL ? 0 : -1; | |
| 1011 | 1011 | } |
| 1012 | 1012 | |
| 1013 | 1013 | static int pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mutex) { |
| 1014 | HANDLE handles[] = {cv->signal, cv->broadcast}; | |
| 1015 | ReleaseMutex(*mutex); | |
| 1016 | WaitForMultipleObjects(2, handles, FALSE, INFINITE); | |
| 1017 | return WaitForSingleObject(*mutex, INFINITE) == WAIT_OBJECT_0? 0 : -1; | |
| 1014 | HANDLE handles[] = {cv->signal, cv->broadcast}; | |
| 1015 | ReleaseMutex(*mutex); | |
| 1016 | WaitForMultipleObjects(2, handles, FALSE, INFINITE); | |
| 1017 | return WaitForSingleObject(*mutex, INFINITE) == WAIT_OBJECT_0? 0 : -1; | |
| 1018 | 1018 | } |
| 1019 | 1019 | |
| 1020 | 1020 | static int pthread_cond_signal(pthread_cond_t *cv) { |
| 1021 | ||
| 1021 | return SetEvent(cv->signal) == 0 ? -1 : 0; | |
| 1022 | 1022 | } |
| 1023 | 1023 | |
| 1024 | 1024 | static int pthread_cond_broadcast(pthread_cond_t *cv) { |
| 1025 | // Implementation with PulseEvent() has race condition, see | |
| 1026 | // http://www.cs.wustl.edu/~schmidt/win32-cv-1.html | |
| 1027 | return PulseEvent(cv->broadcast) == 0 ? -1 : 0; | |
| 1025 | // Implementation with PulseEvent() has race condition, see | |
| 1026 | // http://www.cs.wustl.edu/~schmidt/win32-cv-1.html | |
| 1027 | return PulseEvent(cv->broadcast) == 0 ? -1 : 0; | |
| 1028 | 1028 | } |
| 1029 | 1029 | |
| 1030 | 1030 | static int pthread_cond_destroy(pthread_cond_t *cv) { |
| 1031 | ||
| 1031 | return CloseHandle(cv->signal) && CloseHandle(cv->broadcast) ? 0 : -1; | |
| 1032 | 1032 | } |
| 1033 | 1033 | |
| 1034 | 1034 | // For Windows, change all slashes to backslashes in path names. |
| 1035 | 1035 | static void change_slashes_to_backslashes(char *path) { |
| 1036 | ||
| 1036 | int i; | |
| 1037 | 1037 | |
| 1038 | for (i = 0; path[i] != '\0'; i++) { | |
| 1039 | if (path[i] == '/') | |
| 1040 | path[i] = '\\'; | |
| 1041 | // i > 0 check is to preserve UNC paths, like \\server\file.txt | |
| 1042 | if (path[i] == '\\' && i > 0) | |
| 1043 | while (path[i + 1] == '\\' || path[i + 1] == '/') | |
| 1044 | (void) memmove(path + i + 1, | |
| 1045 | path + i + 2, strlen(path + i + 1)); | |
| 1046 | } | |
| 1038 | for (i = 0; path[i] != '\0'; i++) { | |
| 1039 | if (path[i] == '/') | |
| 1040 | path[i] = '\\'; | |
| 1041 | // i > 0 check is to preserve UNC paths, like \\server\file.txt | |
| 1042 | if (path[i] == '\\' && i > 0) | |
| 1043 | while (path[i + 1] == '\\' || path[i + 1] == '/') | |
| 1044 | (void) memmove(path + i + 1, | |
| 1045 | path + i + 2, strlen(path + i + 1)); | |
| 1046 | } | |
| 1047 | 1047 | } |
| 1048 | 1048 | |
| 1049 | 1049 | // Encode 'path' which is assumed UTF-8 string, into UNICODE string. |
| 1050 | 1050 | // wbuf and wbuf_len is a target buffer and its length. |
| 1051 | 1051 | static void to_unicode(const char *path, wchar_t *wbuf, size_t wbuf_len) { |
| 1052 | ||
| 1052 | char buf[PATH_MAX], buf2[PATH_MAX]; | |
| 1053 | 1053 | |
| 1054 | mg_strlcpy(buf, path, sizeof(buf)); | |
| 1055 | change_slashes_to_backslashes(buf); | |
| 1054 | mg_strlcpy(buf, path, sizeof(buf)); | |
| 1055 | change_slashes_to_backslashes(buf); | |
| 1056 | 1056 | |
| 1057 | // Convert to Unicode and back. If doubly-converted string does not | |
| 1058 | // match the original, something is fishy, reject. | |
| 1059 | memset(wbuf, 0, wbuf_len * sizeof(wchar_t)); | |
| 1060 | MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int) wbuf_len); | |
| 1061 | WideCharToMultiByte(CP_UTF8, 0, wbuf, (int) wbuf_len, buf2, sizeof(buf2), | |
| 1062 | NULL, NULL); | |
| 1063 | if (strcmp(buf, buf2) != 0) { | |
| 1064 | wbuf[0] = L'\0'; | |
| 1065 | } | |
| 1057 | // Convert to Unicode and back. If doubly-converted string does not | |
| 1058 | // match the original, something is fishy, reject. | |
| 1059 | memset(wbuf, 0, wbuf_len * sizeof(wchar_t)); | |
| 1060 | MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int) wbuf_len); | |
| 1061 | WideCharToMultiByte(CP_UTF8, 0, wbuf, (int) wbuf_len, buf2, sizeof(buf2), | |
| 1062 | NULL, NULL); | |
| 1063 | if (strcmp(buf, buf2) != 0) { | |
| 1064 | wbuf[0] = L'\0'; | |
| 1065 | } | |
| 1066 | 1066 | } |
| 1067 | 1067 | |
| 1068 | 1068 | #if defined(_WIN32_WCE) |
| 1069 | 1069 | static time_t time(time_t *ptime) { |
| 1070 | time_t t; | |
| 1071 | SYSTEMTIME st; | |
| 1072 | FILETIME ft; | |
| 1070 | time_t t; | |
| 1071 | SYSTEMTIME st; | |
| 1072 | FILETIME ft; | |
| 1073 | 1073 | |
| 1074 | GetSystemTime(&st); | |
| 1075 | SystemTimeToFileTime(&st, &ft); | |
| 1076 | t = SYS2UNIX_TIME(ft.dwLowDateTime, ft.dwHighDateTime); | |
| 1074 | GetSystemTime(&st); | |
| 1075 | SystemTimeToFileTime(&st, &ft); | |
| 1076 | t = SYS2UNIX_TIME(ft.dwLowDateTime, ft.dwHighDateTime); | |
| 1077 | 1077 | |
| 1078 | if (ptime != NULL) { | |
| 1079 | *ptime = t; | |
| 1080 | } | |
| 1078 | if (ptime != NULL) { | |
| 1079 | *ptime = t; | |
| 1080 | } | |
| 1081 | 1081 | |
| 1082 | ||
| 1082 | return t; | |
| 1083 | 1083 | } |
| 1084 | 1084 | |
| 1085 | 1085 | static struct tm *localtime(const time_t *ptime, struct tm *ptm) { |
| 1086 | int64_t t = ((int64_t) *ptime) * RATE_DIFF + EPOCH_DIFF; | |
| 1087 | FILETIME ft, lft; | |
| 1088 | SYSTEMTIME st; | |
| 1089 | TIME_ZONE_INFORMATION tzinfo; | |
| 1086 | int64_t t = ((int64_t) *ptime) * RATE_DIFF + EPOCH_DIFF; | |
| 1087 | FILETIME ft, lft; | |
| 1088 | SYSTEMTIME st; | |
| 1089 | TIME_ZONE_INFORMATION tzinfo; | |
| 1090 | 1090 | |
| 1091 | if (ptm == NULL) { | |
| 1092 | return NULL; | |
| 1093 | } | |
| 1091 | if (ptm == NULL) { | |
| 1092 | return NULL; | |
| 1093 | } | |
| 1094 | 1094 | |
| 1095 | * (int64_t *) &ft = t; | |
| 1096 | FileTimeToLocalFileTime(&ft, &lft); | |
| 1097 | FileTimeToSystemTime(&lft, &st); | |
| 1098 | ptm->tm_year = st.wYear - 1900; | |
| 1099 | ptm->tm_mon = st.wMonth - 1; | |
| 1100 | ptm->tm_wday = st.wDayOfWeek; | |
| 1101 | ptm->tm_mday = st.wDay; | |
| 1102 | ptm->tm_hour = st.wHour; | |
| 1103 | ptm->tm_min = st.wMinute; | |
| 1104 | ptm->tm_sec = st.wSecond; | |
| 1105 | ptm->tm_yday = 0; // hope nobody uses this | |
| 1106 | ptm->tm_isdst = | |
| 1107 | GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_DAYLIGHT ? 1 : 0; | |
| 1095 | * (int64_t *) &ft = t; | |
| 1096 | FileTimeToLocalFileTime(&ft, &lft); | |
| 1097 | FileTimeToSystemTime(&lft, &st); | |
| 1098 | ptm->tm_year = st.wYear - 1900; | |
| 1099 | ptm->tm_mon = st.wMonth - 1; | |
| 1100 | ptm->tm_wday = st.wDayOfWeek; | |
| 1101 | ptm->tm_mday = st.wDay; | |
| 1102 | ptm->tm_hour = st.wHour; | |
| 1103 | ptm->tm_min = st.wMinute; | |
| 1104 | ptm->tm_sec = st.wSecond; | |
| 1105 | ptm->tm_yday = 0; // hope nobody uses this | |
| 1106 | ptm->tm_isdst = | |
| 1107 | GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_DAYLIGHT ? 1 : 0; | |
| 1108 | 1108 | |
| 1109 | ||
| 1109 | return ptm; | |
| 1110 | 1110 | } |
| 1111 | 1111 | |
| 1112 | 1112 | static struct tm *gmtime(const time_t *ptime, struct tm *ptm) { |
| 1113 | // FIXME(lsm): fix this. | |
| 1114 | return localtime(ptime, ptm); | |
| 1113 | // FIXME(lsm): fix this. | |
| 1114 | return localtime(ptime, ptm); | |
| 1115 | 1115 | } |
| 1116 | 1116 | |
| 1117 | 1117 | static size_t strftime(char *dst, size_t dst_size, const char *fmt, |
| 1118 | const struct tm *tm) { | |
| 1119 | (void) snprintf(dst, dst_size, "implement strftime() for WinCE"); | |
| 1120 | return 0; | |
| 1118 | const struct tm *tm) { | |
| 1119 | (void) snprintf(dst, dst_size, "implement strftime() for WinCE"); | |
| 1120 | return 0; | |
| 1121 | 1121 | } |
| 1122 | 1122 | #endif |
| 1123 | 1123 | |
| r25360 | r25361 | |
| 1126 | 1126 | // "a.cgi", despite one would expect an error back. |
| 1127 | 1127 | // This function returns non-0 if path ends with some garbage. |
| 1128 | 1128 | static int path_cannot_disclose_cgi(const char *path) { |
| 1129 | static const char *allowed_last_characters = "_-"; | |
| 1130 | int last = path[strlen(path) - 1]; | |
| 1131 | return isalnum(last) || strchr(allowed_last_characters, last) != NULL; | |
| 1129 | static const char *allowed_last_characters = "_-"; | |
| 1130 | int last = path[strlen(path) - 1]; | |
| 1131 | return isalnum(last) || strchr(allowed_last_characters, last) != NULL; | |
| 1132 | 1132 | } |
| 1133 | 1133 | |
| 1134 | 1134 | static int mg_stat(struct mg_connection *conn, const char *path, |
| 1135 | struct file *filep) { | |
| 1136 | wchar_t wbuf[PATH_MAX]; | |
| 1137 | WIN32_FILE_ATTRIBUTE_DATA info; | |
| 1135 | struct file *filep) { | |
| 1136 | wchar_t wbuf[PATH_MAX]; | |
| 1137 | WIN32_FILE_ATTRIBUTE_DATA info; | |
| 1138 | 1138 | |
| 1139 | if (!is_file_in_memory(conn, path, filep)) { | |
| 1140 | to_unicode(path, wbuf, ARRAY_SIZE(wbuf)); | |
| 1141 | if (GetFileAttributesExW(wbuf, GetFileExInfoStandard, &info) != 0) { | |
| 1142 | filep->size = MAKEUQUAD(info.nFileSizeLow, info.nFileSizeHigh); | |
| 1143 | filep->modification_time = SYS2UNIX_TIME( | |
| 1144 | info.ftLastWriteTime.dwLowDateTime, | |
| 1145 | info.ftLastWriteTime.dwHighDateTime); | |
| 1146 | filep->is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; | |
| 1147 | // If file name is fishy, reset the file structure and return error. | |
| 1148 | // Note it is important to reset, not just return the error, cause | |
| 1149 | // functions like is_file_opened() check the struct. | |
| 1150 | if (!filep->is_directory && !path_cannot_disclose_cgi(path)) { | |
| 1151 | memset(filep, 0, sizeof(*filep)); | |
| 1152 | } | |
| 1153 | } | |
| 1154 | } | |
| 1139 | if (!is_file_in_memory(conn, path, filep)) { | |
| 1140 | to_unicode(path, wbuf, ARRAY_SIZE(wbuf)); | |
| 1141 | if (GetFileAttributesExW(wbuf, GetFileExInfoStandard, &info) != 0) { | |
| 1142 | filep->size = MAKEUQUAD(info.nFileSizeLow, info.nFileSizeHigh); | |
| 1143 | filep->modification_time = SYS2UNIX_TIME( | |
| 1144 | info.ftLastWriteTime.dwLowDateTime, | |
| 1145 | info.ftLastWriteTime.dwHighDateTime); | |
| 1146 | filep->is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; | |
| 1147 | // If file name is fishy, reset the file structure and return error. | |
| 1148 | // Note it is important to reset, not just return the error, cause | |
| 1149 | // functions like is_file_opened() check the struct. | |
| 1150 | if (!filep->is_directory && !path_cannot_disclose_cgi(path)) { | |
| 1151 | memset(filep, 0, sizeof(*filep)); | |
| 1152 | } | |
| 1153 | } | |
| 1154 | } | |
| 1155 | 1155 | |
| 1156 | ||
| 1156 | return filep->membuf != NULL || filep->modification_time != 0; | |
| 1157 | 1157 | } |
| 1158 | 1158 | |
| 1159 | 1159 | static int mg_remove(const char *path) { |
| 1160 | wchar_t wbuf[PATH_MAX]; | |
| 1161 | to_unicode(path, wbuf, ARRAY_SIZE(wbuf)); | |
| 1162 | return DeleteFileW(wbuf) ? 0 : -1; | |
| 1160 | wchar_t wbuf[PATH_MAX]; | |
| 1161 | to_unicode(path, wbuf, ARRAY_SIZE(wbuf)); | |
| 1162 | return DeleteFileW(wbuf) ? 0 : -1; | |
| 1163 | 1163 | } |
| 1164 | 1164 | |
| 1165 | 1165 | static int mg_mkdir(const char *path, int mode) { |
| 1166 | char buf[PATH_MAX]; | |
| 1167 | wchar_t wbuf[PATH_MAX]; | |
| 1166 | char buf[PATH_MAX]; | |
| 1167 | wchar_t wbuf[PATH_MAX]; | |
| 1168 | 1168 | |
| 1169 | (void) mode; | |
| 1170 | mg_strlcpy(buf, path, sizeof(buf)); | |
| 1171 | change_slashes_to_backslashes(buf); | |
| 1169 | (void) mode; | |
| 1170 | mg_strlcpy(buf, path, sizeof(buf)); | |
| 1171 | change_slashes_to_backslashes(buf); | |
| 1172 | 1172 | |
| 1173 | ||
| 1173 | (void) MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, ARRAY_SIZE(wbuf)); | |
| 1174 | 1174 | |
| 1175 | ||
| 1175 | return CreateDirectoryW(wbuf, NULL) ? 0 : -1; | |
| 1176 | 1176 | } |
| 1177 | 1177 | |
| 1178 | 1178 | // Implementation of POSIX opendir/closedir/readdir for Windows. |
| 1179 | 1179 | static DIR * opendir(const char *name) { |
| 1180 | DIR *dir = NULL; | |
| 1181 | wchar_t wpath[PATH_MAX]; | |
| 1182 | DWORD attrs; | |
| 1180 | DIR *dir = NULL; | |
| 1181 | wchar_t wpath[PATH_MAX]; | |
| 1182 | DWORD attrs; | |
| 1183 | 1183 | |
| 1184 | if (name == NULL) { | |
| 1185 | SetLastError(ERROR_BAD_ARGUMENTS); | |
| 1186 | } else if ((dir = (DIR *) malloc(sizeof(*dir))) == NULL) { | |
| 1187 | SetLastError(ERROR_NOT_ENOUGH_MEMORY); | |
| 1188 | } else { | |
| 1189 | to_unicode(name, wpath, ARRAY_SIZE(wpath)); | |
| 1190 | attrs = GetFileAttributesW(wpath); | |
| 1191 | if (attrs != 0xFFFFFFFF && | |
| 1192 | ((attrs & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)) { | |
| 1193 | (void) wcscat(wpath, L"\\*"); | |
| 1194 | dir->handle = FindFirstFileW(wpath, &dir->info); | |
| 1195 | dir->result.d_name[0] = '\0'; | |
| 1196 | } else { | |
| 1197 | free(dir); | |
| 1198 | dir = NULL; | |
| 1199 | } | |
| 1200 | } | |
| 1184 | if (name == NULL) { | |
| 1185 | SetLastError(ERROR_BAD_ARGUMENTS); | |
| 1186 | } else if ((dir = (DIR *) malloc(sizeof(*dir))) == NULL) { | |
| 1187 | SetLastError(ERROR_NOT_ENOUGH_MEMORY); | |
| 1188 | } else { | |
| 1189 | to_unicode(name, wpath, ARRAY_SIZE(wpath)); | |
| 1190 | attrs = GetFileAttributesW(wpath); | |
| 1191 | if (attrs != 0xFFFFFFFF && | |
| 1192 | ((attrs & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)) { | |
| 1193 | (void) wcscat(wpath, L"\\*"); | |
| 1194 | dir->handle = FindFirstFileW(wpath, &dir->info); | |
| 1195 | dir->result.d_name[0] = '\0'; | |
| 1196 | } else { | |
| 1197 | free(dir); | |
| 1198 | dir = NULL; | |
| 1199 | } | |
| 1200 | } | |
| 1201 | 1201 | |
| 1202 | ||
| 1202 | return dir; | |
| 1203 | 1203 | } |
| 1204 | 1204 | |
| 1205 | 1205 | static int closedir(DIR *dir) { |
| 1206 | ||
| 1206 | int result = 0; | |
| 1207 | 1207 | |
| 1208 | if (dir != NULL) { | |
| 1209 | if (dir->handle != INVALID_HANDLE_VALUE) | |
| 1210 | result = FindClose(dir->handle) ? 0 : -1; | |
| 1208 | if (dir != NULL) { | |
| 1209 | if (dir->handle != INVALID_HANDLE_VALUE) | |
| 1210 | result = FindClose(dir->handle) ? 0 : -1; | |
| 1211 | 1211 | |
| 1212 | free(dir); | |
| 1213 | } else { | |
| 1214 | result = -1; | |
| 1215 | SetLastError(ERROR_BAD_ARGUMENTS); | |
| 1216 | } | |
| 1212 | free(dir); | |
| 1213 | } else { | |
| 1214 | result = -1; | |
| 1215 | SetLastError(ERROR_BAD_ARGUMENTS); | |
| 1216 | } | |
| 1217 | 1217 | |
| 1218 | ||
| 1218 | return result; | |
| 1219 | 1219 | } |
| 1220 | 1220 | |
| 1221 | 1221 | static struct dirent *readdir(DIR *dir) { |
| 1222 | ||
| 1222 | struct dirent *result = 0; | |
| 1223 | 1223 | |
| 1224 | if (dir) { | |
| 1225 | if (dir->handle != INVALID_HANDLE_VALUE) { | |
| 1226 | result = &dir->result; | |
| 1227 | (void) WideCharToMultiByte(CP_UTF8, 0, | |
| 1228 | dir->info.cFileName, -1, result->d_name, | |
| 1229 | sizeof(result->d_name), NULL, NULL); | |
| 1224 | if (dir) { | |
| 1225 | if (dir->handle != INVALID_HANDLE_VALUE) { | |
| 1226 | result = &dir->result; | |
| 1227 | (void) WideCharToMultiByte(CP_UTF8, 0, | |
| 1228 | dir->info.cFileName, -1, result->d_name, | |
| 1229 | sizeof(result->d_name), NULL, NULL); | |
| 1230 | 1230 | |
| 1231 | if (!FindNextFileW(dir->handle, &dir->info)) { | |
| 1232 | (void) FindClose(dir->handle); | |
| 1233 | dir->handle = INVALID_HANDLE_VALUE; | |
| 1234 | } | |
| 1231 | if (!FindNextFileW(dir->handle, &dir->info)) { | |
| 1232 | (void) FindClose(dir->handle); | |
| 1233 | dir->handle = INVALID_HANDLE_VALUE; | |
| 1234 | } | |
| 1235 | 1235 | |
| 1236 | } else { | |
| 1237 | SetLastError(ERROR_FILE_NOT_FOUND); | |
| 1238 | } | |
| 1239 | } else { | |
| 1240 | SetLastError(ERROR_BAD_ARGUMENTS); | |
| 1241 | } | |
| 1236 | } else { | |
| 1237 | SetLastError(ERROR_FILE_NOT_FOUND); | |
| 1238 | } | |
| 1239 | } else { | |
| 1240 | SetLastError(ERROR_BAD_ARGUMENTS); | |
| 1241 | } | |
| 1242 | 1242 | |
| 1243 | ||
| 1243 | return result; | |
| 1244 | 1244 | } |
| 1245 | 1245 | |
| 1246 | 1246 | #ifndef HAVE_POLL |
| 1247 | 1247 | static int poll(struct pollfd *pfd, int n, int milliseconds) { |
| 1248 | struct timeval tv; | |
| 1249 | fd_set set; | |
| 1250 | int i, result, maxfd = 0; | |
| 1248 | struct timeval tv; | |
| 1249 | fd_set set; | |
| 1250 | int i, result, maxfd = 0; | |
| 1251 | 1251 | |
| 1252 | tv.tv_sec = milliseconds / 1000; | |
| 1253 | tv.tv_usec = (milliseconds % 1000) * 1000; | |
| 1254 | FD_ZERO(&set); | |
| 1252 | tv.tv_sec = milliseconds / 1000; | |
| 1253 | tv.tv_usec = (milliseconds % 1000) * 1000; | |
| 1254 | FD_ZERO(&set); | |
| 1255 | 1255 | |
| 1256 | for (i = 0; i < n; i++) { | |
| 1257 | FD_SET((SOCKET) pfd[i].fd, &set); | |
| 1258 | pfd[i].revents = 0; | |
| 1256 | for (i = 0; i < n; i++) { | |
| 1257 | FD_SET((SOCKET) pfd[i].fd, &set); | |
| 1258 | pfd[i].revents = 0; | |
| 1259 | 1259 | |
| 1260 | if (pfd[i].fd > maxfd) { | |
| 1261 | maxfd = pfd[i].fd; | |
| 1262 | } | |
| 1263 | } | |
| 1260 | if (pfd[i].fd > maxfd) { | |
| 1261 | maxfd = pfd[i].fd; | |
| 1262 | } | |
| 1263 | } | |
| 1264 | 1264 | |
| 1265 | if ((result = select(maxfd + 1, &set, NULL, NULL, &tv)) > 0) { | |
| 1266 | for (i = 0; i < n; i++) { | |
| 1267 | if (FD_ISSET(pfd[i].fd, &set)) { | |
| 1268 | pfd[i].revents = POLLIN; | |
| 1269 | } | |
| 1270 | } | |
| 1271 | } | |
| 1265 | if ((result = select(maxfd + 1, &set, NULL, NULL, &tv)) > 0) { | |
| 1266 | for (i = 0; i < n; i++) { | |
| 1267 | if (FD_ISSET(pfd[i].fd, &set)) { | |
| 1268 | pfd[i].revents = POLLIN; | |
| 1269 | } | |
| 1270 | } | |
| 1271 | } | |
| 1272 | 1272 | |
| 1273 | ||
| 1273 | return result; | |
| 1274 | 1274 | } |
| 1275 | 1275 | #endif // HAVE_POLL |
| 1276 | 1276 | |
| 1277 | 1277 | #define set_close_on_exec(x) // No FD_CLOEXEC on Windows |
| 1278 | 1278 | |
| 1279 | 1279 | int mg_start_thread(mg_thread_func_t f, void *p) { |
| 1280 | ||
| 1280 | return (long)_beginthread((void (__cdecl *)(void *)) f, 0, p) == -1L ? -1 : 0; | |
| 1281 | 1281 | } |
| 1282 | 1282 | |
| 1283 | 1283 | #if !defined(NO_SSL) |
| 1284 | 1284 | static HANDLE dlopen(const char *dll_name, int flags) { |
| 1285 | wchar_t wbuf[PATH_MAX]; | |
| 1286 | (void) flags; | |
| 1287 | to_unicode(dll_name, wbuf, ARRAY_SIZE(wbuf)); | |
| 1288 | return LoadLibraryW(wbuf); | |
| 1285 | wchar_t wbuf[PATH_MAX]; | |
| 1286 | (void) flags; | |
| 1287 | to_unicode(dll_name, wbuf, ARRAY_SIZE(wbuf)); | |
| 1288 | return LoadLibraryW(wbuf); | |
| 1289 | 1289 | } |
| 1290 | 1290 | #endif |
| 1291 | 1291 | #if !defined(NO_CGI) |
| 1292 | 1292 | #define SIGKILL 0 |
| 1293 | 1293 | static int kill(pid_t pid, int sig_num) { |
| 1294 | (void) TerminateProcess(pid, sig_num); | |
| 1295 | (void) CloseHandle(pid); | |
| 1296 | return 0; | |
| 1294 | (void) TerminateProcess(pid, sig_num); | |
| 1295 | (void) CloseHandle(pid); | |
| 1296 | return 0; | |
| 1297 | 1297 | } |
| 1298 | 1298 | |
| 1299 | 1299 | static void trim_trailing_whitespaces(char *s) { |
| 1300 | char *e = s + strlen(s) - 1; | |
| 1301 | while (e > s && isspace(* (unsigned char *) e)) { | |
| 1302 | *e-- = '\0'; | |
| 1303 | } | |
| 1300 | char *e = s + strlen(s) - 1; | |
| 1301 | while (e > s && isspace(* (unsigned char *) e)) { | |
| 1302 | *e-- = '\0'; | |
| 1303 | } | |
| 1304 | 1304 | } |
| 1305 | 1305 | |
| 1306 | 1306 | static pid_t spawn_process(struct mg_connection *conn, const char *prog, |
| 1307 | char *envblk, char *envp[], int fd_stdin, | |
| 1308 | int fd_stdout, const char *dir) { | |
| 1309 | HANDLE me; | |
| 1310 | char *p, *interp, full_interp[PATH_MAX], full_dir[PATH_MAX], | |
| 1311 | cmdline[PATH_MAX], buf[PATH_MAX]; | |
| 1312 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 1313 | STARTUPINFOA si; | |
| 1314 | PROCESS_INFORMATION pi = { 0 }; | |
| 1307 | char *envblk, char *envp[], int fd_stdin, | |
| 1308 | int fd_stdout, const char *dir) { | |
| 1309 | HANDLE me; | |
| 1310 | char *p, *interp, full_interp[PATH_MAX], full_dir[PATH_MAX], | |
| 1311 | cmdline[PATH_MAX], buf[PATH_MAX]; | |
| 1312 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 1313 | STARTUPINFOA si; | |
| 1314 | PROCESS_INFORMATION pi = { 0 }; | |
| 1315 | 1315 | |
| 1316 | ||
| 1316 | (void) envp; | |
| 1317 | 1317 | |
| 1318 | memset(&si, 0, sizeof(si)); | |
| 1319 | si.cb = sizeof(si); | |
| 1318 | memset(&si, 0, sizeof(si)); | |
| 1319 | si.cb = sizeof(si); | |
| 1320 | 1320 | |
| 1321 | // TODO(lsm): redirect CGI errors to the error log file | |
| 1322 | si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; | |
| 1323 | si.wShowWindow = SW_HIDE; | |
| 1321 | // TODO(lsm): redirect CGI errors to the error log file | |
| 1322 | si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; | |
| 1323 | si.wShowWindow = SW_HIDE; | |
| 1324 | 1324 | |
| 1325 | me = GetCurrentProcess(); | |
| 1326 | DuplicateHandle(me, (HANDLE) _get_osfhandle(fd_stdin), me, | |
| 1327 | &si.hStdInput, 0, TRUE, DUPLICATE_SAME_ACCESS); | |
| 1328 | DuplicateHandle(me, (HANDLE) _get_osfhandle(fd_stdout), me, | |
| 1329 | &si.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS); | |
| 1325 | me = GetCurrentProcess(); | |
| 1326 | DuplicateHandle(me, (HANDLE) _get_osfhandle(fd_stdin), me, | |
| 1327 | &si.hStdInput, 0, TRUE, DUPLICATE_SAME_ACCESS); | |
| 1328 | DuplicateHandle(me, (HANDLE) _get_osfhandle(fd_stdout), me, | |
| 1329 | &si.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS); | |
| 1330 | 1330 | |
| 1331 | // If CGI file is a script, try to read the interpreter line | |
| 1332 | interp = conn->ctx->config[CGI_INTERPRETER]; | |
| 1333 | if (interp == NULL) { | |
| 1334 | buf[0] = buf[1] = '\0'; | |
| 1331 | // If CGI file is a script, try to read the interpreter line | |
| 1332 | interp = conn->ctx->config[CGI_INTERPRETER]; | |
| 1333 | if (interp == NULL) { | |
| 1334 | buf[0] = buf[1] = '\0'; | |
| 1335 | 1335 | |
| 1336 | // Read the first line of the script into the buffer | |
| 1337 | snprintf(cmdline, sizeof(cmdline), "%s%c%s", dir, '/', prog); | |
| 1338 | if (mg_fopen(conn, cmdline, "r", &file)) { | |
| 1339 | p = (char *) file.membuf; | |
| 1340 | mg_fgets(buf, sizeof(buf), &file, &p); | |
| 1341 | mg_fclose(&file); | |
| 1342 | buf[sizeof(buf) - 1] = '\0'; | |
| 1343 | } | |
| 1336 | // Read the first line of the script into the buffer | |
| 1337 | snprintf(cmdline, sizeof(cmdline), "%s%c%s", dir, '/', prog); | |
| 1338 | if (mg_fopen(conn, cmdline, "r", &file)) { | |
| 1339 | p = (char *) file.membuf; | |
| 1340 | mg_fgets(buf, sizeof(buf), &file, &p); | |
| 1341 | mg_fclose(&file); | |
| 1342 | buf[sizeof(buf) - 1] = '\0'; | |
| 1343 | } | |
| 1344 | 1344 | |
| 1345 | if (buf[0] == '#' && buf[1] == '!') { | |
| 1346 | trim_trailing_whitespaces(buf + 2); | |
| 1347 | } else { | |
| 1348 | buf[2] = '\0'; | |
| 1349 | } | |
| 1350 | interp = buf + 2; | |
| 1351 | } | |
| 1345 | if (buf[0] == '#' && buf[1] == '!') { | |
| 1346 | trim_trailing_whitespaces(buf + 2); | |
| 1347 | } else { | |
| 1348 | buf[2] = '\0'; | |
| 1349 | } | |
| 1350 | interp = buf + 2; | |
| 1351 | } | |
| 1352 | 1352 | |
| 1353 | if (interp[0] != '\0') { | |
| 1354 | GetFullPathNameA(interp, sizeof(full_interp), full_interp, NULL); | |
| 1355 | interp = full_interp; | |
| 1356 | } | |
| 1357 | GetFullPathNameA(dir, sizeof(full_dir), full_dir, NULL); | |
| 1353 | if (interp[0] != '\0') { | |
| 1354 | GetFullPathNameA(interp, sizeof(full_interp), full_interp, NULL); | |
| 1355 | interp = full_interp; | |
| 1356 | } | |
| 1357 | GetFullPathNameA(dir, sizeof(full_dir), full_dir, NULL); | |
| 1358 | 1358 | |
| 1359 | mg_snprintf(conn, cmdline, sizeof(cmdline), "%s%s%s\\%s", | |
| 1360 | interp, interp[0] == '\0' ? "" : " ", full_dir, prog); | |
| 1359 | mg_snprintf(conn, cmdline, sizeof(cmdline), "%s%s%s\\%s", | |
| 1360 | interp, interp[0] == '\0' ? "" : " ", full_dir, prog); | |
| 1361 | 1361 | |
| 1362 | DEBUG_TRACE(("Running [%s]", cmdline)); | |
| 1363 | if (CreateProcessA(NULL, cmdline, NULL, NULL, TRUE, | |
| 1364 | CREATE_NEW_PROCESS_GROUP, envblk, NULL, &si, &pi) == 0) { | |
| 1365 | cry(conn, "%s: CreateProcess(%s): %ld", | |
| 1366 | __func__, cmdline, ERRNO); | |
| 1367 | pi.hProcess = (pid_t) -1; | |
| 1368 | } | |
| 1362 | DEBUG_TRACE(("Running [%s]", cmdline)); | |
| 1363 | if (CreateProcessA(NULL, cmdline, NULL, NULL, TRUE, | |
| 1364 | CREATE_NEW_PROCESS_GROUP, envblk, NULL, &si, &pi) == 0) { | |
| 1365 | cry(conn, "%s: CreateProcess(%s): %ld", | |
| 1366 | __func__, cmdline, ERRNO); | |
| 1367 | pi.hProcess = (pid_t) -1; | |
| 1368 | } | |
| 1369 | 1369 | |
| 1370 | // Always close these to prevent handle leakage. | |
| 1371 | (void) close(fd_stdin); | |
| 1372 | (void) close(fd_stdout); | |
| 1370 | // Always close these to prevent handle leakage. | |
| 1371 | (void) close(fd_stdin); | |
| 1372 | (void) close(fd_stdout); | |
| 1373 | 1373 | |
| 1374 | (void) CloseHandle(si.hStdOutput); | |
| 1375 | (void) CloseHandle(si.hStdInput); | |
| 1376 | (void) CloseHandle(pi.hThread); | |
| 1374 | (void) CloseHandle(si.hStdOutput); | |
| 1375 | (void) CloseHandle(si.hStdInput); | |
| 1376 | (void) CloseHandle(pi.hThread); | |
| 1377 | 1377 | |
| 1378 | ||
| 1378 | return (pid_t) pi.hProcess; | |
| 1379 | 1379 | } |
| 1380 | 1380 | #endif // !NO_CGI |
| 1381 | 1381 | |
| 1382 | 1382 | static int set_non_blocking_mode(SOCKET sock) { |
| 1383 | unsigned long on = 1; | |
| 1384 | return ioctlsocket(sock, FIONBIO, &on); | |
| 1383 | unsigned long on = 1; | |
| 1384 | return ioctlsocket(sock, FIONBIO, &on); | |
| 1385 | 1385 | } |
| 1386 | 1386 | |
| 1387 | 1387 | #else |
| 1388 | 1388 | static int mg_stat(struct mg_connection *conn, const char *path, |
| 1389 | struct file *filep) { | |
| 1390 | struct stat st; | |
| 1389 | struct file *filep) { | |
| 1390 | struct stat st; | |
| 1391 | 1391 | |
| 1392 | if (!is_file_in_memory(conn, path, filep) && !stat(path, &st)) { | |
| 1393 | filep->size = st.st_size; | |
| 1394 | filep->modification_time = st.st_mtime; | |
| 1395 | filep->is_directory = S_ISDIR(st.st_mode); | |
| 1396 | } else { | |
| 1397 | filep->modification_time = (time_t) 0; | |
| 1398 | } | |
| 1392 | if (!is_file_in_memory(conn, path, filep) && !stat(path, &st)) { | |
| 1393 | filep->size = st.st_size; | |
| 1394 | filep->modification_time = st.st_mtime; | |
| 1395 | filep->is_directory = S_ISDIR(st.st_mode); | |
| 1396 | } else { | |
| 1397 | filep->modification_time = (time_t) 0; | |
| 1398 | } | |
| 1399 | 1399 | |
| 1400 | ||
| 1400 | return filep->membuf != NULL || filep->modification_time != (time_t) 0; | |
| 1401 | 1401 | } |
| 1402 | 1402 | |
| 1403 | 1403 | static void set_close_on_exec(int fd) { |
| 1404 | ||
| 1404 | fcntl(fd, F_SETFD, FD_CLOEXEC); | |
| 1405 | 1405 | } |
| 1406 | 1406 | |
| 1407 | 1407 | int mg_start_thread(mg_thread_func_t func, void *param) { |
| 1408 | pthread_t thread_id; | |
| 1409 | pthread_attr_t attr; | |
| 1410 | int result; | |
| 1408 | pthread_t thread_id; | |
| 1409 | pthread_attr_t attr; | |
| 1410 | int result; | |
| 1411 | 1411 | |
| 1412 | (void) pthread_attr_init(&attr); | |
| 1413 | (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); | |
| 1414 | // TODO(lsm): figure out why mongoose dies on Linux if next line is enabled | |
| 1415 | // (void) pthread_attr_setstacksize(&attr, sizeof(struct mg_connection) * 5); | |
| 1412 | (void) pthread_attr_init(&attr); | |
| 1413 | (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); | |
| 1414 | // TODO(lsm): figure out why mongoose dies on Linux if next line is enabled | |
| 1415 | // (void) pthread_attr_setstacksize(&attr, sizeof(struct mg_connection) * 5); | |
| 1416 | 1416 | |
| 1417 | result = pthread_create(&thread_id, &attr, func, param); | |
| 1418 | pthread_attr_destroy(&attr); | |
| 1417 | result = pthread_create(&thread_id, &attr, func, param); | |
| 1418 | pthread_attr_destroy(&attr); | |
| 1419 | 1419 | |
| 1420 | ||
| 1420 | return result; | |
| 1421 | 1421 | } |
| 1422 | 1422 | |
| 1423 | 1423 | #ifndef NO_CGI |
| 1424 | 1424 | static pid_t spawn_process(struct mg_connection *conn, const char *prog, |
| 1425 | char *envblk, char *envp[], int fd_stdin, | |
| 1426 | int fd_stdout, const char *dir) { | |
| 1427 | pid_t pid; | |
| 1428 | const char *interp; | |
| 1425 | char *envblk, char *envp[], int fd_stdin, | |
| 1426 | int fd_stdout, const char *dir) { | |
| 1427 | pid_t pid; | |
| 1428 | const char *interp; | |
| 1429 | 1429 | |
| 1430 | ||
| 1430 | (void) envblk; | |
| 1431 | 1431 | |
| 1432 | if ((pid = fork()) == -1) { | |
| 1433 | // Parent | |
| 1434 | send_http_error(conn, 500, http_500_error, "fork(): %s", strerror(ERRNO)); | |
| 1435 | } else if (pid == 0) { | |
| 1436 | // Child | |
| 1437 | if (chdir(dir) != 0) { | |
| 1438 | cry(conn, "%s: chdir(%s): %s", __func__, dir, strerror(ERRNO)); | |
| 1439 | } else if (dup2(fd_stdin, 0) == -1) { | |
| 1440 | cry(conn, "%s: dup2(%d, 0): %s", __func__, fd_stdin, strerror(ERRNO)); | |
| 1441 | } else if (dup2(fd_stdout, 1) == -1) { | |
| 1442 | cry(conn, "%s: dup2(%d, 1): %s", __func__, fd_stdout, strerror(ERRNO)); | |
| 1443 | } else { | |
| 1444 | // Not redirecting stderr to stdout, to avoid output being littered | |
| 1445 | // with the error messages. | |
| 1446 | (void) close(fd_stdin); | |
| 1447 | (void) close(fd_stdout); | |
| 1432 | if ((pid = fork()) == -1) { | |
| 1433 | // Parent | |
| 1434 | send_http_error(conn, 500, http_500_error, "fork(): %s", strerror(ERRNO)); | |
| 1435 | } else if (pid == 0) { | |
| 1436 | // Child | |
| 1437 | if (chdir(dir) != 0) { | |
| 1438 | cry(conn, "%s: chdir(%s): %s", __func__, dir, strerror(ERRNO)); | |
| 1439 | } else if (dup2(fd_stdin, 0) == -1) { | |
| 1440 | cry(conn, "%s: dup2(%d, 0): %s", __func__, fd_stdin, strerror(ERRNO)); | |
| 1441 | } else if (dup2(fd_stdout, 1) == -1) { | |
| 1442 | cry(conn, "%s: dup2(%d, 1): %s", __func__, fd_stdout, strerror(ERRNO)); | |
| 1443 | } else { | |
| 1444 | // Not redirecting stderr to stdout, to avoid output being littered | |
| 1445 | // with the error messages. | |
| 1446 | (void) close(fd_stdin); | |
| 1447 | (void) close(fd_stdout); | |
| 1448 | 1448 | |
| 1449 | // After exec, all signal handlers are restored to their default values, | |
| 1450 | // with one exception of SIGCHLD. According to POSIX.1-2001 and Linux's | |
| 1451 | // implementation, SIGCHLD's handler will leave unchanged after exec | |
| 1452 | // if it was set to be ignored. Restore it to default action. | |
| 1453 | signal(SIGCHLD, SIG_DFL); | |
| 1449 | // After exec, all signal handlers are restored to their default values, | |
| 1450 | // with one exception of SIGCHLD. According to POSIX.1-2001 and Linux's | |
| 1451 | // implementation, SIGCHLD's handler will leave unchanged after exec | |
| 1452 | // if it was set to be ignored. Restore it to default action. | |
| 1453 | signal(SIGCHLD, SIG_DFL); | |
| 1454 | 1454 | |
| 1455 | interp = conn->ctx->config[CGI_INTERPRETER]; | |
| 1456 | if (interp == NULL) { | |
| 1457 | (void) execle(prog, prog, NULL, envp); | |
| 1458 | cry(conn, "%s: execle(%s): %s", __func__, prog, strerror(ERRNO)); | |
| 1459 | } else { | |
| 1460 | (void) execle(interp, interp, prog, NULL, envp); | |
| 1461 | cry(conn, "%s: execle(%s %s): %s", __func__, interp, prog, | |
| 1462 | strerror(ERRNO)); | |
| 1463 | } | |
| 1464 | } | |
| 1465 | exit(EXIT_FAILURE); | |
| 1466 | } | |
| 1455 | interp = conn->ctx->config[CGI_INTERPRETER]; | |
| 1456 | if (interp == NULL) { | |
| 1457 | (void) execle(prog, prog, NULL, envp); | |
| 1458 | cry(conn, "%s: execle(%s): %s", __func__, prog, strerror(ERRNO)); | |
| 1459 | } else { | |
| 1460 | (void) execle(interp, interp, prog, NULL, envp); | |
| 1461 | cry(conn, "%s: execle(%s %s): %s", __func__, interp, prog, | |
| 1462 | strerror(ERRNO)); | |
| 1463 | } | |
| 1464 | } | |
| 1465 | exit(EXIT_FAILURE); | |
| 1466 | } | |
| 1467 | 1467 | |
| 1468 | // Parent. Close stdio descriptors | |
| 1469 | (void) close(fd_stdin); | |
| 1470 | (void) close(fd_stdout); | |
| 1468 | // Parent. Close stdio descriptors | |
| 1469 | (void) close(fd_stdin); | |
| 1470 | (void) close(fd_stdout); | |
| 1471 | 1471 | |
| 1472 | ||
| 1472 | return pid; | |
| 1473 | 1473 | } |
| 1474 | 1474 | #endif // !NO_CGI |
| 1475 | 1475 | |
| 1476 | 1476 | static int set_non_blocking_mode(SOCKET sock) { |
| 1477 | ||
| 1477 | int flags; | |
| 1478 | 1478 | |
| 1479 | flags = fcntl(sock, F_GETFL, 0); | |
| 1480 | (void) fcntl(sock, F_SETFL, flags | O_NONBLOCK); | |
| 1479 | flags = fcntl(sock, F_GETFL, 0); | |
| 1480 | (void) fcntl(sock, F_SETFL, flags | O_NONBLOCK); | |
| 1481 | 1481 | |
| 1482 | ||
| 1482 | return 0; | |
| 1483 | 1483 | } |
| 1484 | 1484 | #endif // _WIN32 |
| 1485 | 1485 | |
| 1486 | 1486 | // Write data to the IO channel - opened file descriptor, socket or SSL |
| 1487 | 1487 | // descriptor. Return number of bytes written. |
| 1488 | 1488 | static int64_t push(FILE *fp, SOCKET sock, SSL *ssl, const char *buf, |
| 1489 | int64_t len) { | |
| 1490 | int64_t sent; | |
| 1491 | int n, k; | |
| 1489 | int64_t len) { | |
| 1490 | int64_t sent; | |
| 1491 | int n, k; | |
| 1492 | 1492 | |
| 1493 | (void) ssl; // Get rid of warning | |
| 1494 | sent = 0; | |
| 1495 | while (sent < len) { | |
| 1493 | (void) ssl; // Get rid of warning | |
| 1494 | sent = 0; | |
| 1495 | while (sent < len) { | |
| 1496 | // How many bytes we send in this iteration | |
| 1497 | k = len - sent > INT_MAX ? INT_MAX : (int) (len - sent); | |
| 1496 | 1498 | |
| 1497 | // How many bytes we send in this iteration | |
| 1498 | k = len - sent > INT_MAX ? INT_MAX : (int) (len - sent); | |
| 1499 | ||
| 1500 | 1499 | #ifndef NO_SSL |
| 1501 | if (ssl != NULL) { | |
| 1502 | n = SSL_write(ssl, buf + sent, k); | |
| 1503 | } else | |
| 1500 | if (ssl != NULL) { | |
| 1501 | n = SSL_write(ssl, buf + sent, k); | |
| 1502 | } else | |
| 1504 | 1503 | #endif |
| 1505 | if (fp != NULL) { | |
| 1506 | n = (int) fwrite(buf + sent, 1, (size_t) k, fp); | |
| 1507 | if (ferror(fp)) | |
| 1508 | n = -1; | |
| 1509 | } else { | |
| 1510 | n = send(sock, buf + sent, (size_t) k, MSG_NOSIGNAL); | |
| 1511 | } | |
| 1504 | if (fp != NULL) { | |
| 1505 | n = (int) fwrite(buf + sent, 1, (size_t) k, fp); | |
| 1506 | if (ferror(fp)) | |
| 1507 | n = -1; | |
| 1508 | } else { | |
| 1509 | n = send(sock, buf + sent, (size_t) k, MSG_NOSIGNAL); | |
| 1510 | } | |
| 1512 | 1511 | |
| 1513 | if (n <= 0) | |
| 1514 | break; | |
| 1512 | if (n <= 0) | |
| 1513 | break; | |
| 1515 | 1514 | |
| 1516 | sent += n; | |
| 1517 | } | |
| 1515 | sent += n; | |
| 1516 | } | |
| 1518 | 1517 | |
| 1519 | ||
| 1518 | return sent; | |
| 1520 | 1519 | } |
| 1521 | 1520 | |
| 1522 | 1521 | // Read from IO channel - opened file descriptor, socket, or SSL descriptor. |
| 1523 | 1522 | // Return negative value on error, or number of bytes read on success. |
| 1524 | 1523 | static int pull(FILE *fp, struct mg_connection *conn, char *buf, int len) { |
| 1525 | ||
| 1524 | int nread; | |
| 1526 | 1525 | |
| 1527 | if (fp != NULL) { | |
| 1528 | // Use read() instead of fread(), because if we're reading from the CGI | |
| 1529 | // pipe, fread() may block until IO buffer is filled up. We cannot afford | |
| 1530 | // to block and must pass all read bytes immediately to the client. | |
| 1531 | nread = read(fileno(fp), buf, (size_t) len); | |
| 1526 | if (fp != NULL) { | |
| 1527 | // Use read() instead of fread(), because if we're reading from the CGI | |
| 1528 | // pipe, fread() may block until IO buffer is filled up. We cannot afford | |
| 1529 | // to block and must pass all read bytes immediately to the client. | |
| 1530 | nread = read(fileno(fp), buf, (size_t) len); | |
| 1532 | 1531 | #ifndef NO_SSL |
| 1533 | } else if (conn->ssl != NULL) { | |
| 1534 | nread = SSL_read(conn->ssl, buf, len); | |
| 1532 | } else if (conn->ssl != NULL) { | |
| 1533 | nread = SSL_read(conn->ssl, buf, len); | |
| 1535 | 1534 | #endif |
| 1536 | } else { | |
| 1537 | nread = recv(conn->client.sock, buf, (size_t) len, 0); | |
| 1538 | } | |
| 1535 | } else { | |
| 1536 | nread = recv(conn->client.sock, buf, (size_t) len, 0); | |
| 1537 | } | |
| 1539 | 1538 | |
| 1540 | ||
| 1539 | return conn->ctx->stop_flag ? -1 : nread; | |
| 1541 | 1540 | } |
| 1542 | 1541 | |
| 1543 | 1542 | static int pull_all(FILE *fp, struct mg_connection *conn, char *buf, int len) { |
| 1544 | ||
| 1543 | int n, nread = 0; | |
| 1545 | 1544 | |
| 1546 | while (len > 0) { | |
| 1547 | n = pull(fp, conn, buf + nread, len); | |
| 1548 | if (n < 0) { | |
| 1549 | nread = n; // Propagate the error | |
| 1550 | break; | |
| 1551 | } else if (n == 0) { | |
| 1552 | break; // No more data to read | |
| 1553 | } else { | |
| 1554 | conn->consumed_content += n; | |
| 1555 | nread += n; | |
| 1556 | len -= n; | |
| 1557 | } | |
| 1558 | } | |
| 1545 | while (len > 0) { | |
| 1546 | n = pull(fp, conn, buf + nread, len); | |
| 1547 | if (n < 0) { | |
| 1548 | nread = n; // Propagate the error | |
| 1549 | break; | |
| 1550 | } else if (n == 0) { | |
| 1551 | break; // No more data to read | |
| 1552 | } else { | |
| 1553 | conn->consumed_content += n; | |
| 1554 | nread += n; | |
| 1555 | len -= n; | |
| 1556 | } | |
| 1557 | } | |
| 1559 | 1558 | |
| 1560 | ||
| 1559 | return nread; | |
| 1561 | 1560 | } |
| 1562 | 1561 | |
| 1563 | 1562 | int mg_read(struct mg_connection *conn, void *buf, size_t len) { |
| 1564 | int n, buffered_len, nread; | |
| 1565 | const char *body; | |
| 1563 | int n, buffered_len, nread; | |
| 1564 | const char *body; | |
| 1566 | 1565 | |
| 1567 | // If Content-Length is not set, read until socket is closed | |
| 1568 | if (conn->consumed_content == 0 && conn->content_len == 0) { | |
| 1569 | conn->content_len = INT64_MAX; | |
| 1570 | conn->must_close = 1; | |
| 1571 | } | |
| 1566 | // If Content-Length is not set, read until socket is closed | |
| 1567 | if (conn->consumed_content == 0 && conn->content_len == 0) { | |
| 1568 | conn->content_len = INT64_MAX; | |
| 1569 | conn->must_close = 1; | |
| 1570 | } | |
| 1572 | 1571 | |
| 1573 | nread = 0; | |
| 1574 | if (conn->consumed_content < conn->content_len) { | |
| 1575 | // Adjust number of bytes to read. | |
| 1576 | int64_t to_read = conn->content_len - conn->consumed_content; | |
| 1577 | if (to_read < (int64_t) len) { | |
| 1578 | len = (size_t) to_read; | |
| 1579 | } | |
| 1572 | nread = 0; | |
| 1573 | if (conn->consumed_content < conn->content_len) { | |
| 1574 | // Adjust number of bytes to read. | |
| 1575 | int64_t to_read = conn->content_len - conn->consumed_content; | |
| 1576 | if (to_read < (int64_t) len) { | |
| 1577 | len = (size_t) to_read; | |
| 1578 | } | |
| 1580 | 1579 | |
| 1581 | // Return buffered data | |
| 1582 | body = conn->buf + conn->request_len + conn->consumed_content; | |
| 1583 | buffered_len = &conn->buf[conn->data_len] - body; | |
| 1584 | if (buffered_len > 0) { | |
| 1585 | if (len < (size_t) buffered_len) { | |
| 1586 | buffered_len = (int) len; | |
| 1587 | } | |
| 1588 | memcpy(buf, body, (size_t) buffered_len); | |
| 1589 | len -= buffered_len; | |
| 1590 | conn->consumed_content += buffered_len; | |
| 1591 | nread += buffered_len; | |
| 1592 | buf = (char *) buf + buffered_len; | |
| 1593 | } | |
| 1580 | // Return buffered data | |
| 1581 | body = conn->buf + conn->request_len + conn->consumed_content; | |
| 1582 | buffered_len = &conn->buf[conn->data_len] - body; | |
| 1583 | if (buffered_len > 0) { | |
| 1584 | if (len < (size_t) buffered_len) { | |
| 1585 | buffered_len = (int) len; | |
| 1586 | } | |
| 1587 | memcpy(buf, body, (size_t) buffered_len); | |
| 1588 | len -= buffered_len; | |
| 1589 | conn->consumed_content += buffered_len; | |
| 1590 | nread += buffered_len; | |
| 1591 | buf = (char *) buf + buffered_len; | |
| 1592 | } | |
| 1594 | 1593 | |
| 1595 | // We have returned all buffered data. Read new data from the remote socket. | |
| 1596 | n = pull_all(NULL, conn, (char *) buf, (int) len); | |
| 1597 | nread = n >= 0 ? nread + n : n; | |
| 1598 | } | |
| 1599 | return nread; | |
| 1594 | // We have returned all buffered data. Read new data from the remote socket. | |
| 1595 | n = pull_all(NULL, conn, (char *) buf, (int) len); | |
| 1596 | nread = n >= 0 ? nread + n : n; | |
| 1597 | } | |
| 1598 | return nread; | |
| 1600 | 1599 | } |
| 1601 | 1600 | |
| 1602 | 1601 | int mg_write(struct mg_connection *conn, const void *buf, size_t len) { |
| 1603 | time_t now; | |
| 1604 | int64_t n, total, allowed; | |
| 1602 | time_t now; | |
| 1603 | int64_t n, total, allowed; | |
| 1605 | 1604 | |
| 1606 | if (conn->throttle > 0) { | |
| 1607 | if ((now = time(NULL)) != conn->last_throttle_time) { | |
| 1608 | conn->last_throttle_time = now; | |
| 1609 | conn->last_throttle_bytes = 0; | |
| 1610 | } | |
| 1611 | allowed = conn->throttle - conn->last_throttle_bytes; | |
| 1612 | if (allowed > (int64_t) len) { | |
| 1613 | allowed = len; | |
| 1614 | } | |
| 1615 | if ((total = push(NULL, conn->client.sock, conn->ssl, (const char *) buf, | |
| 1616 | (int64_t) allowed)) == allowed) { | |
| 1617 | buf = (char *) buf + total; | |
| 1618 | conn->last_throttle_bytes += total; | |
| 1619 | while (total < (int64_t) len && conn->ctx->stop_flag == 0) { | |
| 1620 | allowed = conn->throttle > (int64_t) len - total ? | |
| 1621 | (int64_t) len - total : conn->throttle; | |
| 1622 | if ((n = push(NULL, conn->client.sock, conn->ssl, (const char *) buf, | |
| 1623 | (int64_t) allowed)) != allowed) { | |
| 1624 | break; | |
| 1625 | } | |
| 1626 | sleep(1); | |
| 1627 | conn->last_throttle_bytes = allowed; | |
| 1628 | conn->last_throttle_time = time(NULL); | |
| 1629 | buf = (char *) buf + n; | |
| 1630 | total += n; | |
| 1631 | } | |
| 1632 | } | |
| 1633 | } else { | |
| 1634 | total = push(NULL, conn->client.sock, conn->ssl, (const char *) buf, | |
| 1635 | (int64_t) len); | |
| 1636 | } | |
| 1637 | return (int) total; | |
| 1605 | if (conn->throttle > 0) { | |
| 1606 | if ((now = time(NULL)) != conn->last_throttle_time) { | |
| 1607 | conn->last_throttle_time = now; | |
| 1608 | conn->last_throttle_bytes = 0; | |
| 1609 | } | |
| 1610 | allowed = conn->throttle - conn->last_throttle_bytes; | |
| 1611 | if (allowed > (int64_t) len) { | |
| 1612 | allowed = len; | |
| 1613 | } | |
| 1614 | if ((total = push(NULL, conn->client.sock, conn->ssl, (const char *) buf, | |
| 1615 | (int64_t) allowed)) == allowed) { | |
| 1616 | buf = (char *) buf + total; | |
| 1617 | conn->last_throttle_bytes += total; | |
| 1618 | while (total < (int64_t) len && conn->ctx->stop_flag == 0) { | |
| 1619 | allowed = conn->throttle > (int64_t) len - total ? | |
| 1620 | (int64_t) len - total : conn->throttle; | |
| 1621 | if ((n = push(NULL, conn->client.sock, conn->ssl, (const char *) buf, | |
| 1622 | (int64_t) allowed)) != allowed) { | |
| 1623 | break; | |
| 1624 | } | |
| 1625 | sleep(1); | |
| 1626 | conn->last_throttle_bytes = allowed; | |
| 1627 | conn->last_throttle_time = time(NULL); | |
| 1628 | buf = (char *) buf + n; | |
| 1629 | total += n; | |
| 1630 | } | |
| 1631 | } | |
| 1632 | } else { | |
| 1633 | total = push(NULL, conn->client.sock, conn->ssl, (const char *) buf, | |
| 1634 | (int64_t) len); | |
| 1635 | } | |
| 1636 | return (int) total; | |
| 1638 | 1637 | } |
| 1639 | 1638 | |
| 1640 | 1639 | // Print message to buffer. If buffer is large enough to hold the message, |
| 1641 | 1640 | // return buffer. If buffer is to small, allocate large enough buffer on heap, |
| 1642 | 1641 | // and return allocated buffer. |
| 1643 | 1642 | static int alloc_vprintf(char **buf, size_t size, const char *fmt, va_list ap) { |
| 1644 | va_list ap_copy; | |
| 1645 | int len; | |
| 1643 | va_list ap_copy; | |
| 1644 | int len; | |
| 1646 | 1645 | |
| 1647 | // Windows is not standard-compliant, and vsnprintf() returns -1 if | |
| 1648 | // buffer is too small. Also, older versions of msvcrt.dll do not have | |
| 1649 | // _vscprintf(). However, if size is 0, vsnprintf() behaves correctly. | |
| 1650 | // Therefore, we make two passes: on first pass, get required message length. | |
| 1651 | // On second pass, actually print the message. | |
| 1652 | va_copy(ap_copy, ap); | |
| 1653 | len = vsnprintf(NULL, 0, fmt, ap_copy); | |
| 1646 | // Windows is not standard-compliant, and vsnprintf() returns -1 if | |
| 1647 | // buffer is too small. Also, older versions of msvcrt.dll do not have | |
| 1648 | // _vscprintf(). However, if size is 0, vsnprintf() behaves correctly. | |
| 1649 | // Therefore, we make two passes: on first pass, get required message length. | |
| 1650 | // On second pass, actually print the message. | |
| 1651 | va_copy(ap_copy, ap); | |
| 1652 | len = vsnprintf(NULL, 0, fmt, ap_copy); | |
| 1654 | 1653 | |
| 1655 | if (len > (int) size && | |
| 1656 | (size = len + 1) > 0 && | |
| 1657 | (*buf = (char *) malloc(size)) == NULL) { | |
| 1658 | len = -1; // Allocation failed, mark failure | |
| 1659 | } else { | |
| 1660 | va_copy(ap_copy, ap); | |
| 1661 | vsnprintf(*buf, size, fmt, ap_copy); | |
| 1662 | } | |
| 1654 | if (len > (int) size && | |
| 1655 | (size = len + 1) > 0 && | |
| 1656 | (*buf = (char *) malloc(size)) == NULL) { | |
| 1657 | len = -1; // Allocation failed, mark failure | |
| 1658 | } else { | |
| 1659 | va_copy(ap_copy, ap); | |
| 1660 | vsnprintf(*buf, size, fmt, ap_copy); | |
| 1661 | } | |
| 1663 | 1662 | |
| 1664 | ||
| 1663 | return len; | |
| 1665 | 1664 | } |
| 1666 | 1665 | |
| 1667 | 1666 | int mg_vprintf(struct mg_connection *conn, const char *fmt, va_list ap) { |
| 1668 | char mem[MG_BUF_LEN], *buf = mem; | |
| 1669 | int len; | |
| 1667 | char mem[MG_BUF_LEN], *buf = mem; | |
| 1668 | int len; | |
| 1670 | 1669 | |
| 1671 | if ((len = alloc_vprintf(&buf, sizeof(mem), fmt, ap)) > 0) { | |
| 1672 | len = mg_write(conn, buf, (size_t) len); | |
| 1673 | } | |
| 1674 | if (buf != mem && buf != NULL) { | |
| 1675 | free(buf); | |
| 1676 | } | |
| 1670 | if ((len = alloc_vprintf(&buf, sizeof(mem), fmt, ap)) > 0) { | |
| 1671 | len = mg_write(conn, buf, (size_t) len); | |
| 1672 | } | |
| 1673 | if (buf != mem && buf != NULL) { | |
| 1674 | free(buf); | |
| 1675 | } | |
| 1677 | 1676 | |
| 1678 | ||
| 1677 | return len; | |
| 1679 | 1678 | } |
| 1680 | 1679 | |
| 1681 | 1680 | int mg_printf(struct mg_connection *conn, const char *fmt, ...) { |
| 1682 | va_list ap; | |
| 1683 | va_start(ap, fmt); | |
| 1684 | return mg_vprintf(conn, fmt, ap); | |
| 1681 | va_list ap; | |
| 1682 | va_start(ap, fmt); | |
| 1683 | return mg_vprintf(conn, fmt, ap); | |
| 1685 | 1684 | } |
| 1686 | 1685 | |
| 1687 | 1686 | int mg_url_decode(const char *src, int src_len, char *dst, |
| 1688 | int dst_len, int is_form_url_encoded) { | |
| 1689 | int i, j, a, b; | |
| 1687 | int dst_len, int is_form_url_encoded) { | |
| 1688 | int i, j, a, b; | |
| 1690 | 1689 | #define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W') |
| 1691 | 1690 | |
| 1692 | for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++) { | |
| 1693 | if (src[i] == '%' && i < src_len - 2 && | |
| 1694 | isxdigit(* (const unsigned char *) (src + i + 1)) && | |
| 1695 | isxdigit(* (const unsigned char *) (src + i + 2))) { | |
| 1696 | a = tolower(* (const unsigned char *) (src + i + 1)); | |
| 1697 | b = tolower(* (const unsigned char *) (src + i + 2)); | |
| 1698 | dst[j] = (char) ((HEXTOI(a) << 4) | HEXTOI(b)); | |
| 1699 | i += 2; | |
| 1700 | } else if (is_form_url_encoded && src[i] == '+') { | |
| 1701 | dst[j] = ' '; | |
| 1702 | } else { | |
| 1703 | dst[j] = src[i]; | |
| 1704 | } | |
| 1705 | } | |
| 1691 | for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++) { | |
| 1692 | if (src[i] == '%' && i < src_len - 2 && | |
| 1693 | isxdigit(* (const unsigned char *) (src + i + 1)) && | |
| 1694 | isxdigit(* (const unsigned char *) (src + i + 2))) { | |
| 1695 | a = tolower(* (const unsigned char *) (src + i + 1)); | |
| 1696 | b = tolower(* (const unsigned char *) (src + i + 2)); | |
| 1697 | dst[j] = (char) ((HEXTOI(a) << 4) | HEXTOI(b)); | |
| 1698 | i += 2; | |
| 1699 | } else if (is_form_url_encoded && src[i] == '+') { | |
| 1700 | dst[j] = ' '; | |
| 1701 | } else { | |
| 1702 | dst[j] = src[i]; | |
| 1703 | } | |
| 1704 | } | |
| 1706 | 1705 | |
| 1707 | ||
| 1706 | dst[j] = '\0'; // Null-terminate the destination | |
| 1708 | 1707 | |
| 1709 | ||
| 1708 | return i >= src_len ? j : -1; | |
| 1710 | 1709 | } |
| 1711 | 1710 | |
| 1712 | 1711 | int mg_get_var(const char *data, size_t data_len, const char *name, |
| 1713 | char *dst, size_t dst_len) { | |
| 1714 | const char *p, *e, *s; | |
| 1715 | size_t name_len; | |
| 1716 | int len; | |
| 1712 | char *dst, size_t dst_len) { | |
| 1713 | const char *p, *e, *s; | |
| 1714 | size_t name_len; | |
| 1715 | int len; | |
| 1717 | 1716 | |
| 1718 | if (dst == NULL || dst_len == 0) { | |
| 1719 | len = -2; | |
| 1720 | } else if (data == NULL || name == NULL || data_len == 0) { | |
| 1721 | len = -1; | |
| 1722 | dst[0] = '\0'; | |
| 1723 | } else { | |
| 1724 | name_len = strlen(name); | |
| 1725 | e = data + data_len; | |
| 1726 | len = -1; | |
| 1727 | dst[0] = '\0'; | |
| 1717 | if (dst == NULL || dst_len == 0) { | |
| 1718 | len = -2; | |
| 1719 | } else if (data == NULL || name == NULL || data_len == 0) { | |
| 1720 | len = -1; | |
| 1721 | dst[0] = '\0'; | |
| 1722 | } else { | |
| 1723 | name_len = strlen(name); | |
| 1724 | e = data + data_len; | |
| 1725 | len = -1; | |
| 1726 | dst[0] = '\0'; | |
| 1728 | 1727 | |
| 1729 | // data is "var1=val1&var2=val2...". Find variable first | |
| 1730 | for (p = data; p + name_len < e; p++) { | |
| 1731 | if ((p == data || p[-1] == '&') && p[name_len] == '=' && | |
| 1732 | !mg_strncasecmp(name, p, name_len)) { | |
| 1728 | // data is "var1=val1&var2=val2...". Find variable first | |
| 1729 | for (p = data; p + name_len < e; p++) { | |
| 1730 | if ((p == data || p[-1] == '&') && p[name_len] == '=' && | |
| 1731 | !mg_strncasecmp(name, p, name_len)) { | |
| 1732 | // Point p to variable value | |
| 1733 | p += name_len + 1; | |
| 1733 | 1734 | |
| 1734 | // Point p to variable value | |
| 1735 | p += name_len + 1; | |
| 1735 | // Point s to the end of the value | |
| 1736 | s = (const char *) memchr(p, '&', (size_t)(e - p)); | |
| 1737 | if (s == NULL) { | |
| 1738 | s = e; | |
| 1739 | } | |
| 1740 | assert(s >= p); | |
| 1736 | 1741 | |
| 1737 | // Point s to the end of the value | |
| 1738 | s = (const char *) memchr(p, '&', (size_t)(e - p)); | |
| 1739 | if (s == NULL) { | |
| 1740 | s = e; | |
| 1741 | } | |
| 1742 | assert(s >= p); | |
| 1742 | // Decode variable into destination buffer | |
| 1743 | len = mg_url_decode(p, (size_t)(s - p), dst, dst_len, 1); | |
| 1743 | 1744 | |
| 1744 | // Decode variable into destination buffer | |
| 1745 | len = mg_url_decode(p, (size_t)(s - p), dst, dst_len, 1); | |
| 1745 | // Redirect error code from -1 to -2 (destination buffer too small). | |
| 1746 | if (len == -1) { | |
| 1747 | len = -2; | |
| 1748 | } | |
| 1749 | break; | |
| 1750 | } | |
| 1751 | } | |
| 1752 | } | |
| 1746 | 1753 | |
| 1747 | // Redirect error code from -1 to -2 (destination buffer too small). | |
| 1748 | if (len == -1) { | |
| 1749 | len = -2; | |
| 1750 | } | |
| 1751 | break; | |
| 1752 | } | |
| 1753 | } | |
| 1754 | } | |
| 1755 | ||
| 1756 | return len; | |
| 1754 | return len; | |
| 1757 | 1755 | } |
| 1758 | 1756 | |
| 1759 | 1757 | int mg_get_cookie(const char *cookie_header, const char *var_name, |
| 1760 | char *dst, size_t dst_size) { | |
| 1761 | const char *s, *p, *end; | |
| 1762 | int name_len, len = -1; | |
| 1758 | char *dst, size_t dst_size) { | |
| 1759 | const char *s, *p, *end; | |
| 1760 | int name_len, len = -1; | |
| 1763 | 1761 | |
| 1764 | if (dst == NULL || dst_size == 0) { | |
| 1765 | len = -2; | |
| 1766 | } else if (var_name == NULL || (s = cookie_header) == NULL) { | |
| 1767 | len = -1; | |
| 1768 | dst[0] = '\0'; | |
| 1769 | } else { | |
| 1770 | name_len = (int) strlen(var_name); | |
| 1771 | end = s + strlen(s); | |
| 1772 | dst[0] = '\0'; | |
| 1762 | if (dst == NULL || dst_size == 0) { | |
| 1763 | len = -2; | |
| 1764 | } else if (var_name == NULL || (s = cookie_header) == NULL) { | |
| 1765 | len = -1; | |
| 1766 | dst[0] = '\0'; | |
| 1767 | } else { | |
| 1768 | name_len = (int) strlen(var_name); | |
| 1769 | end = s + strlen(s); | |
| 1770 | dst[0] = '\0'; | |
| 1773 | 1771 | |
| 1774 | for (; (s = mg_strcasestr(s, var_name)) != NULL; s += name_len) { | |
| 1775 | if (s[name_len] == '=') { | |
| 1776 | s += name_len + 1; | |
| 1777 | if ((p = strchr(s, ' ')) == NULL) | |
| 1778 | p = end; | |
| 1779 | if (p[-1] == ';') | |
| 1780 | p--; | |
| 1781 | if (*s == '"' && p[-1] == '"' && p > s + 1) { | |
| 1782 | s++; | |
| 1783 | p--; | |
| 1784 | } | |
| 1785 | if ((size_t) (p - s) < dst_size) { | |
| 1786 | len = p - s; | |
| 1787 | mg_strlcpy(dst, s, (size_t) len + 1); | |
| 1788 | } else { | |
| 1789 | len = -3; | |
| 1790 | } | |
| 1791 | break; | |
| 1792 | } | |
| 1793 | } | |
| 1794 | } | |
| 1795 | return len; | |
| 1772 | for (; (s = mg_strcasestr(s, var_name)) != NULL; s += name_len) { | |
| 1773 | if (s[name_len] == '=') { | |
| 1774 | s += name_len + 1; | |
| 1775 | if ((p = strchr(s, ' ')) == NULL) | |
| 1776 | p = end; | |
| 1777 | if (p[-1] == ';') | |
| 1778 | p--; | |
| 1779 | if (*s == '"' && p[-1] == '"' && p > s + 1) { | |
| 1780 | s++; | |
| 1781 | p--; | |
| 1782 | } | |
| 1783 | if ((size_t) (p - s) < dst_size) { | |
| 1784 | len = p - s; | |
| 1785 | mg_strlcpy(dst, s, (size_t) len + 1); | |
| 1786 | } else { | |
| 1787 | len = -3; | |
| 1788 | } | |
| 1789 | break; | |
| 1790 | } | |
| 1791 | } | |
| 1792 | } | |
| 1793 | return len; | |
| 1796 | 1794 | } |
| 1797 | 1795 | |
| 1798 | 1796 | static void convert_uri_to_file_name(struct mg_connection *conn, char *buf, |
| 1799 | size_t buf_len, struct file *filep) { | |
| 1800 | struct vec a, b; | |
| 1801 | const char *rewrite, *uri = conn->request_info.uri; | |
| 1802 | char *p; | |
| 1803 | int match_len; | |
| 1804 | char gz_path[PATH_MAX]; | |
| 1805 | char const* accept_encoding; | |
| 1797 | size_t buf_len, struct file *filep) { | |
| 1798 | struct vec a, b; | |
| 1799 | const char *rewrite, *uri = conn->request_info.uri; | |
| 1800 | char *p; | |
| 1801 | int match_len; | |
| 1802 | char gz_path[PATH_MAX]; | |
| 1803 | char const* accept_encoding; | |
| 1806 | 1804 | |
| 1807 | // Using buf_len - 1 because memmove() for PATH_INFO may shift part | |
| 1808 | // of the path one byte on the right. | |
| 1809 | mg_snprintf(conn, buf, buf_len - 1, "%s%s", conn->ctx->config[DOCUMENT_ROOT], | |
| 1810 | uri); | |
| 1805 | // Using buf_len - 1 because memmove() for PATH_INFO may shift part | |
| 1806 | // of the path one byte on the right. | |
| 1807 | mg_snprintf(conn, buf, buf_len - 1, "%s%s", conn->ctx->config[DOCUMENT_ROOT], | |
| 1808 | uri); | |
| 1811 | 1809 | |
| 1812 | rewrite = conn->ctx->config[REWRITE]; | |
| 1813 | while ((rewrite = next_option(rewrite, &a, &b)) != NULL) { | |
| 1814 | if ((match_len = match_prefix(a.ptr, a.len, uri)) > 0) { | |
| 1815 | mg_snprintf(conn, buf, buf_len - 1, "%.*s%s", (int) b.len, b.ptr, | |
| 1816 | uri + match_len); | |
| 1817 | break; | |
| 1818 | } | |
| 1819 | } | |
| 1810 | rewrite = conn->ctx->config[REWRITE]; | |
| 1811 | while ((rewrite = next_option(rewrite, &a, &b)) != NULL) { | |
| 1812 | if ((match_len = match_prefix(a.ptr, a.len, uri)) > 0) { | |
| 1813 | mg_snprintf(conn, buf, buf_len - 1, "%.*s%s", (int) b.len, b.ptr, | |
| 1814 | uri + match_len); | |
| 1815 | break; | |
| 1816 | } | |
| 1817 | } | |
| 1820 | 1818 | |
| 1821 | ||
| 1819 | if (mg_stat(conn, buf, filep)) return; | |
| 1822 | 1820 | |
| 1823 | // if we can't find the actual file, look for the file | |
| 1824 | // with the same name but a .gz extension. If we find it, | |
| 1825 | // use that and set the gzipped flag in the file struct | |
| 1826 | // to indicate that the response need to have the content- | |
| 1827 | // encoding: gzip header | |
| 1828 | // we can only do this if the browser declares support | |
| 1829 | if ((accept_encoding = mg_get_header(conn, "Accept-Encoding")) != NULL) { | |
| 1830 | if (strstr(accept_encoding,"gzip") != NULL) { | |
| 1831 | snprintf(gz_path, sizeof(gz_path), "%s.gz", buf); | |
| 1832 | if (mg_stat(conn, gz_path, filep)) { | |
| 1833 | filep->gzipped = 1; | |
| 1834 | return; | |
| 1835 | } | |
| 1836 | } | |
| 1837 | } | |
| 1821 | // if we can't find the actual file, look for the file | |
| 1822 | // with the same name but a .gz extension. If we find it, | |
| 1823 | // use that and set the gzipped flag in the file struct | |
| 1824 | // to indicate that the response need to have the content- | |
| 1825 | // encoding: gzip header | |
| 1826 | // we can only do this if the browser declares support | |
| 1827 | if ((accept_encoding = mg_get_header(conn, "Accept-Encoding")) != NULL) { | |
| 1828 | if (strstr(accept_encoding,"gzip") != NULL) { | |
| 1829 | snprintf(gz_path, sizeof(gz_path), "%s.gz", buf); | |
| 1830 | if (mg_stat(conn, gz_path, filep)) { | |
| 1831 | filep->gzipped = 1; | |
| 1832 | return; | |
| 1833 | } | |
| 1834 | } | |
| 1835 | } | |
| 1838 | 1836 | |
| 1839 | // Support PATH_INFO for CGI scripts. | |
| 1840 | for (p = buf + strlen(buf); p > buf + 1; p--) { | |
| 1841 | if (*p == '/') { | |
| 1842 | *p = '\0'; | |
| 1843 | if (match_prefix(conn->ctx->config[CGI_EXTENSIONS], | |
| 1844 | strlen(conn->ctx->config[CGI_EXTENSIONS]), buf) > 0 && | |
| 1845 | mg_stat(conn, buf, filep)) { | |
| 1846 | // Shift PATH_INFO block one character right, e.g. | |
| 1847 | // "/x.cgi/foo/bar\x00" => "/x.cgi\x00/foo/bar\x00" | |
| 1848 | // conn->path_info is pointing to the local variable "path" declared | |
| 1849 | // in handle_request(), so PATH_INFO is not valid after | |
| 1850 | // handle_request returns. | |
| 1851 | conn->path_info = p + 1; | |
| 1852 | memmove(p + 2, p + 1, strlen(p + 1) + 1); // +1 is for trailing \0 | |
| 1853 | p[1] = '/'; | |
| 1854 | break; | |
| 1855 | } else { | |
| 1856 | *p = '/'; | |
| 1857 | } | |
| 1858 | } | |
| 1859 | } | |
| 1837 | // Support PATH_INFO for CGI scripts. | |
| 1838 | for (p = buf + strlen(buf); p > buf + 1; p--) { | |
| 1839 | if (*p == '/') { | |
| 1840 | *p = '\0'; | |
| 1841 | if (match_prefix(conn->ctx->config[CGI_EXTENSIONS], | |
| 1842 | strlen(conn->ctx->config[CGI_EXTENSIONS]), buf) > 0 && | |
| 1843 | mg_stat(conn, buf, filep)) { | |
| 1844 | // Shift PATH_INFO block one character right, e.g. | |
| 1845 | // "/x.cgi/foo/bar\x00" => "/x.cgi\x00/foo/bar\x00" | |
| 1846 | // conn->path_info is pointing to the local variable "path" declared | |
| 1847 | // in handle_request(), so PATH_INFO is not valid after | |
| 1848 | // handle_request returns. | |
| 1849 | conn->path_info = p + 1; | |
| 1850 | memmove(p + 2, p + 1, strlen(p + 1) + 1); // +1 is for trailing \0 | |
| 1851 | p[1] = '/'; | |
| 1852 | break; | |
| 1853 | } else { | |
| 1854 | *p = '/'; | |
| 1855 | } | |
| 1856 | } | |
| 1857 | } | |
| 1860 | 1858 | } |
| 1861 | 1859 | |
| 1862 | 1860 | // Check whether full request is buffered. Return: |
| r25360 | r25361 | |
| 1864 | 1862 | // 0 if request is not yet fully buffered |
| 1865 | 1863 | // >0 actual request length, including last \r\n\r\n |
| 1866 | 1864 | static int get_request_len(const char *buf, int buflen) { |
| 1867 | const char *s, *e; | |
| 1868 | int len = 0; | |
| 1865 | const char *s, *e; | |
| 1866 | int len = 0; | |
| 1869 | 1867 | |
| 1870 | for (s = buf, e = s + buflen - 1; len <= 0 && s < e; s++) | |
| 1871 | // Control characters are not allowed but >=128 is. | |
| 1872 | if (!isprint(* (const unsigned char *) s) && *s != '\r' && | |
| 1873 | *s != '\n' && * (const unsigned char *) s < 128) { | |
| 1874 | len = -1; | |
| 1875 | break; // [i_a] abort scan as soon as one malformed character is found; | |
| 1876 | // don't let subsequent \r\n\r\n win us over anyhow | |
| 1877 | } else if (s[0] == '\n' && s[1] == '\n') { | |
| 1878 | len = (int) (s - buf) + 2; | |
| 1879 | } else if (s[0] == '\n' && &s[1] < e && | |
| 1880 | s[1] == '\r' && s[2] == '\n') { | |
| 1881 | len = (int) (s - buf) + 3; | |
| 1882 | } | |
| 1868 | for (s = buf, e = s + buflen - 1; len <= 0 && s < e; s++) | |
| 1869 | // Control characters are not allowed but >=128 is. | |
| 1870 | if (!isprint(* (const unsigned char *) s) && *s != '\r' && | |
| 1871 | *s != '\n' && * (const unsigned char *) s < 128) { | |
| 1872 | len = -1; | |
| 1873 | break; // [i_a] abort scan as soon as one malformed character is found; | |
| 1874 | // don't let subsequent \r\n\r\n win us over anyhow | |
| 1875 | } else if (s[0] == '\n' && s[1] == '\n') { | |
| 1876 | len = (int) (s - buf) + 2; | |
| 1877 | } else if (s[0] == '\n' && &s[1] < e && | |
| 1878 | s[1] == '\r' && s[2] == '\n') { | |
| 1879 | len = (int) (s - buf) + 3; | |
| 1880 | } | |
| 1883 | 1881 | |
| 1884 | ||
| 1882 | return len; | |
| 1885 | 1883 | } |
| 1886 | 1884 | |
| 1887 | 1885 | // Convert month to the month number. Return -1 on error, or month number |
| 1888 | 1886 | static int get_month_index(const char *s) { |
| 1889 | ||
| 1887 | size_t i; | |
| 1890 | 1888 | |
| 1891 | for (i = 0; i < ARRAY_SIZE(month_names); i++) | |
| 1892 | if (!strcmp(s, month_names[i])) | |
| 1893 | return (int) i; | |
| 1889 | for (i = 0; i < ARRAY_SIZE(month_names); i++) | |
| 1890 | if (!strcmp(s, month_names[i])) | |
| 1891 | return (int) i; | |
| 1894 | 1892 | |
| 1895 | ||
| 1893 | return -1; | |
| 1896 | 1894 | } |
| 1897 | 1895 | |
| 1898 | 1896 | static int num_leap_years(int year) { |
| 1899 | ||
| 1897 | return year / 4 - year / 100 + year / 400; | |
| 1900 | 1898 | } |
| 1901 | 1899 | |
| 1902 | 1900 | // Parse UTC date-time string, and return the corresponding time_t value. |
| 1903 | 1901 | static time_t parse_date_string(const char *datetime) { |
| 1904 | static const unsigned short days_before_month[] = { | |
| 1905 | 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 | |
| 1906 | }; | |
| 1907 | char month_str[32]; | |
| 1908 | int second, minute, hour, day, month, year, leap_days, days; | |
| 1909 | time_t result = (time_t) 0; | |
| 1902 | static const unsigned short days_before_month[] = { | |
| 1903 | 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 | |
| 1904 | }; | |
| 1905 | char month_str[32]; | |
| 1906 | int second, minute, hour, day, month, year, leap_days, days; | |
| 1907 | time_t result = (time_t) 0; | |
| 1910 | 1908 | |
| 1911 | if (((sscanf(datetime, "%d/%3s/%d %d:%d:%d", | |
| 1912 | &day, month_str, &year, &hour, &minute, &second) == 6) || | |
| 1913 | (sscanf(datetime, "%d %3s %d %d:%d:%d", | |
| 1914 | &day, month_str, &year, &hour, &minute, &second) == 6) || | |
| 1915 | (sscanf(datetime, "%*3s, %d %3s %d %d:%d:%d", | |
| 1916 | &day, month_str, &year, &hour, &minute, &second) == 6) || | |
| 1917 | (sscanf(datetime, "%d-%3s-%d %d:%d:%d", | |
| 1918 | &day, month_str, &year, &hour, &minute, &second) == 6)) && | |
| 1919 | year > 1970 && | |
| 1920 | (month = get_month_index(month_str)) != -1) { | |
| 1921 | leap_days = num_leap_years(year) - num_leap_years(1970); | |
| 1922 | year -= 1970; | |
| 1923 | days = year * 365 + days_before_month[month] + (day - 1) + leap_days; | |
| 1924 | result = days * 24 * 3600 + hour * 3600 + minute * 60 + second; | |
| 1925 | } | |
| 1909 | if (((sscanf(datetime, "%d/%3s/%d %d:%d:%d", | |
| 1910 | &day, month_str, &year, &hour, &minute, &second) == 6) || | |
| 1911 | (sscanf(datetime, "%d %3s %d %d:%d:%d", | |
| 1912 | &day, month_str, &year, &hour, &minute, &second) == 6) || | |
| 1913 | (sscanf(datetime, "%*3s, %d %3s %d %d:%d:%d", | |
| 1914 | &day, month_str, &year, &hour, &minute, &second) == 6) || | |
| 1915 | (sscanf(datetime, "%d-%3s-%d %d:%d:%d", | |
| 1916 | &day, month_str, &year, &hour, &minute, &second) == 6)) && | |
| 1917 | year > 1970 && | |
| 1918 | (month = get_month_index(month_str)) != -1) { | |
| 1919 | leap_days = num_leap_years(year) - num_leap_years(1970); | |
| 1920 | year -= 1970; | |
| 1921 | days = year * 365 + days_before_month[month] + (day - 1) + leap_days; | |
| 1922 | result = days * 24 * 3600 + hour * 3600 + minute * 60 + second; | |
| 1923 | } | |
| 1926 | 1924 | |
| 1927 | ||
| 1925 | return result; | |
| 1928 | 1926 | } |
| 1929 | 1927 | |
| 1930 | 1928 | // Protect against directory disclosure attack by removing '..', |
| 1931 | 1929 | // excessive '/' and '\' characters |
| 1932 | 1930 | static void remove_double_dots_and_double_slashes(char *s) { |
| 1933 | ||
| 1931 | char *p = s; | |
| 1934 | 1932 | |
| 1935 | while (*s != '\0') { | |
| 1936 | *p++ = *s++; | |
| 1937 | if (s[-1] == '/' || s[-1] == '\\') { | |
| 1938 | // Skip all following slashes, backslashes and double-dots | |
| 1939 | while (s[0] != '\0') { | |
| 1940 | if (s[0] == '/' || s[0] == '\\') { | |
| 1941 | s++; | |
| 1942 | } else if (s[0] == '.' && s[1] == '.') { | |
| 1943 | s += 2; | |
| 1944 | } else { | |
| 1945 | break; | |
| 1946 | } | |
| 1947 | } | |
| 1948 | } | |
| 1949 | } | |
| 1950 | *p = '\0'; | |
| 1933 | while (*s != '\0') { | |
| 1934 | *p++ = *s++; | |
| 1935 | if (s[-1] == '/' || s[-1] == '\\') { | |
| 1936 | // Skip all following slashes, backslashes and double-dots | |
| 1937 | while (s[0] != '\0') { | |
| 1938 | if (s[0] == '/' || s[0] == '\\') { | |
| 1939 | s++; | |
| 1940 | } else if (s[0] == '.' && s[1] == '.') { | |
| 1941 | s += 2; | |
| 1942 | } else { | |
| 1943 | break; | |
| 1944 | } | |
| 1945 | } | |
| 1946 | } | |
| 1947 | } | |
| 1948 | *p = '\0'; | |
| 1951 | 1949 | } |
| 1952 | 1950 | |
| 1953 | 1951 | static const struct { |
| 1954 | const char *extension; | |
| 1955 | size_t ext_len; | |
| 1956 | const char *mime_type; | |
| 1952 | const char *extension; | |
| 1953 | size_t ext_len; | |
| 1954 | const char *mime_type; | |
| 1957 | 1955 | } builtin_mime_types[] = { |
| 1958 | {".html", 5, "text/html"}, | |
| 1959 | {".htm", 4, "text/html"}, | |
| 1960 | {".shtm", 5, "text/html"}, | |
| 1961 | {".shtml", 6, "text/html"}, | |
| 1962 | {".css", 4, "text/css"}, | |
| 1963 | {".js", 3, "application/x-javascript"}, | |
| 1964 | {".ico", 4, "image/x-icon"}, | |
| 1965 | {".gif", 4, "image/gif"}, | |
| 1966 | {".jpg", 4, "image/jpeg"}, | |
| 1967 | {".jpeg", 5, "image/jpeg"}, | |
| 1968 | {".png", 4, "image/png"}, | |
| 1969 | {".svg", 4, "image/svg+xml"}, | |
| 1970 | {".txt", 4, "text/plain"}, | |
| 1971 | {".torrent", 8, "application/x-bittorrent"}, | |
| 1972 | {".wav", 4, "audio/x-wav"}, | |
| 1973 | {".mp3", 4, "audio/x-mp3"}, | |
| 1974 | {".mid", 4, "audio/mid"}, | |
| 1975 | {".m3u", 4, "audio/x-mpegurl"}, | |
| 1976 | {".ogg", 4, "audio/ogg"}, | |
| 1977 | {".ram", 4, "audio/x-pn-realaudio"}, | |
| 1978 | {".xml", 4, "text/xml"}, | |
| 1979 | {".json", 5, "text/json"}, | |
| 1980 | {".xslt", 5, "application/xml"}, | |
| 1981 | {".xsl", 4, "application/xml"}, | |
| 1982 | {".ra", 3, "audio/x-pn-realaudio"}, | |
| 1983 | {".doc", 4, "application/msword"}, | |
| 1984 | {".exe", 4, "application/octet-stream"}, | |
| 1985 | {".zip", 4, "application/x-zip-compressed"}, | |
| 1986 | {".xls", 4, "application/excel"}, | |
| 1987 | {".tgz", 4, "application/x-tar-gz"}, | |
| 1988 | {".tar", 4, "application/x-tar"}, | |
| 1989 | {".gz", 3, "application/x-gunzip"}, | |
| 1990 | {".arj", 4, "application/x-arj-compressed"}, | |
| 1991 | {".rar", 4, "application/x-arj-compressed"}, | |
| 1992 | {".rtf", 4, "application/rtf"}, | |
| 1993 | {".pdf", 4, "application/pdf"}, | |
| 1994 | {".swf", 4, "application/x-shockwave-flash"}, | |
| 1995 | {".mpg", 4, "video/mpeg"}, | |
| 1996 | {".webm", 5, "video/webm"}, | |
| 1997 | {".mpeg", 5, "video/mpeg"}, | |
| 1998 | {".mov", 4, "video/quicktime"}, | |
| 1999 | {".mp4", 4, "video/mp4"}, | |
| 2000 | {".m4v", 4, "video/x-m4v"}, | |
| 2001 | {".asf", 4, "video/x-ms-asf"}, | |
| 2002 | {".avi", 4, "video/x-msvideo"}, | |
| 2003 | {".bmp", 4, "image/bmp"}, | |
| 2004 | {".ttf", 4, "application/x-font-ttf"}, | |
| 2005 | {NULL, 0, NULL} | |
| 1956 | {".html", 5, "text/html"}, | |
| 1957 | {".htm", 4, "text/html"}, | |
| 1958 | {".shtm", 5, "text/html"}, | |
| 1959 | {".shtml", 6, "text/html"}, | |
| 1960 | {".css", 4, "text/css"}, | |
| 1961 | {".js", 3, "application/x-javascript"}, | |
| 1962 | {".ico", 4, "image/x-icon"}, | |
| 1963 | {".gif", 4, "image/gif"}, | |
| 1964 | {".jpg", 4, "image/jpeg"}, | |
| 1965 | {".jpeg", 5, "image/jpeg"}, | |
| 1966 | {".png", 4, "image/png"}, | |
| 1967 | {".svg", 4, "image/svg+xml"}, | |
| 1968 | {".txt", 4, "text/plain"}, | |
| 1969 | {".torrent", 8, "application/x-bittorrent"}, | |
| 1970 | {".wav", 4, "audio/x-wav"}, | |
| 1971 | {".mp3", 4, "audio/x-mp3"}, | |
| 1972 | {".mid", 4, "audio/mid"}, | |
| 1973 | {".m3u", 4, "audio/x-mpegurl"}, | |
| 1974 | {".ogg", 4, "audio/ogg"}, | |
| 1975 | {".ram", 4, "audio/x-pn-realaudio"}, | |
| 1976 | {".xml", 4, "text/xml"}, | |
| 1977 | {".json", 5, "text/json"}, | |
| 1978 | {".xslt", 5, "application/xml"}, | |
| 1979 | {".xsl", 4, "application/xml"}, | |
| 1980 | {".ra", 3, "audio/x-pn-realaudio"}, | |
| 1981 | {".doc", 4, "application/msword"}, | |
| 1982 | {".exe", 4, "application/octet-stream"}, | |
| 1983 | {".zip", 4, "application/x-zip-compressed"}, | |
| 1984 | {".xls", 4, "application/excel"}, | |
| 1985 | {".tgz", 4, "application/x-tar-gz"}, | |
| 1986 | {".tar", 4, "application/x-tar"}, | |
| 1987 | {".gz", 3, "application/x-gunzip"}, | |
| 1988 | {".arj", 4, "application/x-arj-compressed"}, | |
| 1989 | {".rar", 4, "application/x-arj-compressed"}, | |
| 1990 | {".rtf", 4, "application/rtf"}, | |
| 1991 | {".pdf", 4, "application/pdf"}, | |
| 1992 | {".swf", 4, "application/x-shockwave-flash"}, | |
| 1993 | {".mpg", 4, "video/mpeg"}, | |
| 1994 | {".webm", 5, "video/webm"}, | |
| 1995 | {".mpeg", 5, "video/mpeg"}, | |
| 1996 | {".mov", 4, "video/quicktime"}, | |
| 1997 | {".mp4", 4, "video/mp4"}, | |
| 1998 | {".m4v", 4, "video/x-m4v"}, | |
| 1999 | {".asf", 4, "video/x-ms-asf"}, | |
| 2000 | {".avi", 4, "video/x-msvideo"}, | |
| 2001 | {".bmp", 4, "image/bmp"}, | |
| 2002 | {".ttf", 4, "application/x-font-ttf"}, | |
| 2003 | {NULL, 0, NULL} | |
| 2006 | 2004 | }; |
| 2007 | 2005 | |
| 2008 | 2006 | const char *mg_get_builtin_mime_type(const char *path) { |
| 2009 | const char *ext; | |
| 2010 | size_t i, path_len; | |
| 2007 | const char *ext; | |
| 2008 | size_t i, path_len; | |
| 2011 | 2009 | |
| 2012 | ||
| 2010 | path_len = strlen(path); | |
| 2013 | 2011 | |
| 2014 | for (i = 0; builtin_mime_types[i].extension != NULL; i++) { | |
| 2015 | ext = path + (path_len - builtin_mime_types[i].ext_len); | |
| 2016 | if (path_len > builtin_mime_types[i].ext_len && | |
| 2017 | mg_strcasecmp(ext, builtin_mime_types[i].extension) == 0) { | |
| 2018 | return builtin_mime_types[i].mime_type; | |
| 2019 | } | |
| 2020 | } | |
| 2012 | for (i = 0; builtin_mime_types[i].extension != NULL; i++) { | |
| 2013 | ext = path + (path_len - builtin_mime_types[i].ext_len); | |
| 2014 | if (path_len > builtin_mime_types[i].ext_len && | |
| 2015 | mg_strcasecmp(ext, builtin_mime_types[i].extension) == 0) { | |
| 2016 | return builtin_mime_types[i].mime_type; | |
| 2017 | } | |
| 2018 | } | |
| 2021 | 2019 | |
| 2022 | ||
| 2020 | return "text/plain"; | |
| 2023 | 2021 | } |
| 2024 | 2022 | |
| 2025 | 2023 | // Look at the "path" extension and figure what mime type it has. |
| 2026 | 2024 | // Store mime type in the vector. |
| 2027 | 2025 | static void get_mime_type(struct mg_context *ctx, const char *path, |
| 2028 | struct vec *vec) { | |
| 2029 | struct vec ext_vec, mime_vec; | |
| 2030 | const char *list, *ext; | |
| 2031 | size_t path_len; | |
| 2026 | struct vec *vec) { | |
| 2027 | struct vec ext_vec, mime_vec; | |
| 2028 | const char *list, *ext; | |
| 2029 | size_t path_len; | |
| 2032 | 2030 | |
| 2033 | ||
| 2031 | path_len = strlen(path); | |
| 2034 | 2032 | |
| 2035 | // Scan user-defined mime types first, in case user wants to | |
| 2036 | // override default mime types. | |
| 2037 | list = ctx->config[EXTRA_MIME_TYPES]; | |
| 2038 | while ((list = next_option(list, &ext_vec, &mime_vec)) != NULL) { | |
| 2039 | // ext now points to the path suffix | |
| 2040 | ext = path + path_len - ext_vec.len; | |
| 2041 | if (mg_strncasecmp(ext, ext_vec.ptr, ext_vec.len) == 0) { | |
| 2042 | *vec = mime_vec; | |
| 2043 | return; | |
| 2044 | } | |
| 2045 | } | |
| 2033 | // Scan user-defined mime types first, in case user wants to | |
| 2034 | // override default mime types. | |
| 2035 | list = ctx->config[EXTRA_MIME_TYPES]; | |
| 2036 | while ((list = next_option(list, &ext_vec, &mime_vec)) != NULL) { | |
| 2037 | // ext now points to the path suffix | |
| 2038 | ext = path + path_len - ext_vec.len; | |
| 2039 | if (mg_strncasecmp(ext, ext_vec.ptr, ext_vec.len) == 0) { | |
| 2040 | *vec = mime_vec; | |
| 2041 | return; | |
| 2042 | } | |
| 2043 | } | |
| 2046 | 2044 | |
| 2047 | vec->ptr = mg_get_builtin_mime_type(path); | |
| 2048 | vec->len = strlen(vec->ptr); | |
| 2045 | vec->ptr = mg_get_builtin_mime_type(path); | |
| 2046 | vec->len = strlen(vec->ptr); | |
| 2049 | 2047 | } |
| 2050 | 2048 | |
| 2051 | 2049 | static int is_big_endian(void) { |
| 2052 | static const int n = 1; | |
| 2053 | return ((char *) &n)[0] == 0; | |
| 2050 | static const int n = 1; | |
| 2051 | return ((char *) &n)[0] == 0; | |
| 2054 | 2052 | } |
| 2055 | 2053 | |
| 2056 | 2054 | #ifndef HAVE_MD5 |
| 2057 | 2055 | typedef struct MD5Context { |
| 2058 | uint32_t buf[4]; | |
| 2059 | uint32_t bits[2]; | |
| 2060 | unsigned char in[64]; | |
| 2056 | uint32_t buf[4]; | |
| 2057 | uint32_t bits[2]; | |
| 2058 | unsigned char in[64]; | |
| 2061 | 2059 | } MD5_CTX; |
| 2062 | 2060 | |
| 2063 | 2061 | static void byteReverse(unsigned char *buf, unsigned longs) { |
| 2064 | ||
| 2062 | uint32_t t; | |
| 2065 | 2063 | |
| 2066 | // Forrest: MD5 expect LITTLE_ENDIAN, swap if BIG_ENDIAN | |
| 2067 | if (is_big_endian()) { | |
| 2068 | do { | |
| 2069 | t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 | | |
| 2070 | ((unsigned) buf[1] << 8 | buf[0]); | |
| 2071 | * (uint32_t *) buf = t; | |
| 2072 | buf += 4; | |
| 2073 | } while (--longs); | |
| 2074 | } | |
| 2064 | // Forrest: MD5 expect LITTLE_ENDIAN, swap if BIG_ENDIAN | |
| 2065 | if (is_big_endian()) { | |
| 2066 | do { | |
| 2067 | t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 | | |
| 2068 | ((unsigned) buf[1] << 8 | buf[0]); | |
| 2069 | * (uint32_t *) buf = t; | |
| 2070 | buf += 4; | |
| 2071 | } while (--longs); | |
| 2072 | } | |
| 2075 | 2073 | } |
| 2076 | 2074 | |
| 2077 | 2075 | #define F1(x, y, z) (z ^ (x & (y ^ z))) |
| r25360 | r25361 | |
| 2080 | 2078 | #define F4(x, y, z) (y ^ (x | ~z)) |
| 2081 | 2079 | |
| 2082 | 2080 | #define MD5STEP(f, w, x, y, z, data, s) \ |
| 2083 | ||
| 2081 | ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) | |
| 2084 | 2082 | |
| 2085 | 2083 | // Start MD5 accumulation. Set bit count to 0 and buffer to mysterious |
| 2086 | 2084 | // initialization constants. |
| 2087 | 2085 | static void MD5Init(MD5_CTX *ctx) { |
| 2088 | ctx->buf[0] = 0x67452301; | |
| 2089 | ctx->buf[1] = 0xefcdab89; | |
| 2090 | ctx->buf[2] = 0x98badcfe; | |
| 2091 | ctx->buf[3] = 0x10325476; | |
| 2086 | ctx->buf[0] = 0x67452301; | |
| 2087 | ctx->buf[1] = 0xefcdab89; | |
| 2088 | ctx->buf[2] = 0x98badcfe; | |
| 2089 | ctx->buf[3] = 0x10325476; | |
| 2092 | 2090 | |
| 2093 | ctx->bits[0] = 0; | |
| 2094 | ctx->bits[1] = 0; | |
| 2091 | ctx->bits[0] = 0; | |
| 2092 | ctx->bits[1] = 0; | |
| 2095 | 2093 | } |
| 2096 | 2094 | |
| 2097 | 2095 | static void MD5Transform(uint32_t buf[4], uint32_t const in[16]) { |
| 2098 | ||
| 2096 | register uint32_t a, b, c, d; | |
| 2099 | 2097 | |
| 2100 | a = buf[0]; | |
| 2101 | b = buf[1]; | |
| 2102 | c = buf[2]; | |
| 2103 | d = buf[3]; | |
| 2098 | a = buf[0]; | |
| 2099 | b = buf[1]; | |
| 2100 | c = buf[2]; | |
| 2101 | d = buf[3]; | |
| 2104 | 2102 | |
| 2105 | MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); | |
| 2106 | MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); | |
| 2107 | MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); | |
| 2108 | MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); | |
| 2109 | MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); | |
| 2110 | MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); | |
| 2111 | MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); | |
| 2112 | MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); | |
| 2113 | MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); | |
| 2114 | MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); | |
| 2115 | MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); | |
| 2116 | MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); | |
| 2117 | MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); | |
| 2118 | MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); | |
| 2119 | MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); | |
| 2120 | MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); | |
| 2103 | MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); | |
| 2104 | MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); | |
| 2105 | MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); | |
| 2106 | MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); | |
| 2107 | MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); | |
| 2108 | MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); | |
| 2109 | MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); | |
| 2110 | MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); | |
| 2111 | MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); | |
| 2112 | MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); | |
| 2113 | MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); | |
| 2114 | MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); | |
| 2115 | MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); | |
| 2116 | MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); | |
| 2117 | MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); | |
| 2118 | MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); | |
| 2121 | 2119 | |
| 2122 | MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); | |
| 2123 | MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); | |
| 2124 | MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); | |
| 2125 | MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); | |
| 2126 | MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); | |
| 2127 | MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); | |
| 2128 | MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); | |
| 2129 | MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); | |
| 2130 | MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); | |
| 2131 | MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); | |
| 2132 | MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); | |
| 2133 | MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); | |
| 2134 | MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); | |
| 2135 | MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); | |
| 2136 | MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); | |
| 2137 | MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); | |
| 2120 | MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); | |
| 2121 | MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); | |
| 2122 | MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); | |
| 2123 | MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); | |
| 2124 | MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); | |
| 2125 | MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); | |
| 2126 | MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); | |
| 2127 | MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); | |
| 2128 | MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); | |
| 2129 | MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); | |
| 2130 | MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); | |
| 2131 | MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); | |
| 2132 | MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); | |
| 2133 | MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); | |
| 2134 | MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); | |
| 2135 | MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); | |
| 2138 | 2136 | |
| 2139 | MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); | |
| 2140 | MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); | |
| 2141 | MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); | |
| 2142 | MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); | |
| 2143 | MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); | |
| 2144 | MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); | |
| 2145 | MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); | |
| 2146 | MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); | |
| 2147 | MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); | |
| 2148 | MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); | |
| 2149 | MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); | |
| 2150 | MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); | |
| 2151 | MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); | |
| 2152 | MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); | |
| 2153 | MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); | |
| 2154 | MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); | |
| 2137 | MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); | |
| 2138 | MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); | |
| 2139 | MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); | |
| 2140 | MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); | |
| 2141 | MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); | |
| 2142 | MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); | |
| 2143 | MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); | |
| 2144 | MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); | |
| 2145 | MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); | |
| 2146 | MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); | |
| 2147 | MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); | |
| 2148 | MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); | |
| 2149 | MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); | |
| 2150 | MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); | |
| 2151 | MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); | |
| 2152 | MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); | |
| 2155 | 2153 | |
| 2156 | MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); | |
| 2157 | MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); | |
| 2158 | MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); | |
| 2159 | MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); | |
| 2160 | MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); | |
| 2161 | MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); | |
| 2162 | MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); | |
| 2163 | MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); | |
| 2164 | MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); | |
| 2165 | MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); | |
| 2166 | MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); | |
| 2167 | MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); | |
| 2168 | MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); | |
| 2169 | MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); | |
| 2170 | MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); | |
| 2171 | MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); | |
| 2154 | MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); | |
| 2155 | MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); | |
| 2156 | MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); | |
| 2157 | MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); | |
| 2158 | MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); | |
| 2159 | MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); | |
| 2160 | MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); | |
| 2161 | MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); | |
| 2162 | MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); | |
| 2163 | MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); | |
| 2164 | MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); | |
| 2165 | MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); | |
| 2166 | MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); | |
| 2167 | MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); | |
| 2168 | MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); | |
| 2169 | MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); | |
| 2172 | 2170 | |
| 2173 | buf[0] += a; | |
| 2174 | buf[1] += b; | |
| 2175 | buf[2] += c; | |
| 2176 | buf[3] += d; | |
| 2171 | buf[0] += a; | |
| 2172 | buf[1] += b; | |
| 2173 | buf[2] += c; | |
| 2174 | buf[3] += d; | |
| 2177 | 2175 | } |
| 2178 | 2176 | |
| 2179 | 2177 | static void MD5Update(MD5_CTX *ctx, unsigned char const *buf, unsigned len) { |
| 2180 | ||
| 2178 | uint32_t t; | |
| 2181 | 2179 | |
| 2182 | t = ctx->bits[0]; | |
| 2183 | if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) | |
| 2184 | ctx->bits[1]++; | |
| 2185 | ctx->bits[1] += len >> 29; | |
| 2180 | t = ctx->bits[0]; | |
| 2181 | if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) | |
| 2182 | ctx->bits[1]++; | |
| 2183 | ctx->bits[1] += len >> 29; | |
| 2186 | 2184 | |
| 2187 | ||
| 2185 | t = (t >> 3) & 0x3f; | |
| 2188 | 2186 | |
| 2189 | if (t) { | |
| 2190 | unsigned char *p = (unsigned char *) ctx->in + t; | |
| 2187 | if (t) { | |
| 2188 | unsigned char *p = (unsigned char *) ctx->in + t; | |
| 2191 | 2189 | |
| 2192 | t = 64 - t; | |
| 2193 | if (len < t) { | |
| 2194 | memcpy(p, buf, len); | |
| 2195 | return; | |
| 2196 | } | |
| 2197 | memcpy(p, buf, t); | |
| 2198 | byteReverse(ctx->in, 16); | |
| 2199 | MD5Transform(ctx->buf, (uint32_t *) ctx->in); | |
| 2200 | buf += t; | |
| 2201 | len -= t; | |
| 2202 | } | |
| 2190 | t = 64 - t; | |
| 2191 | if (len < t) { | |
| 2192 | memcpy(p, buf, len); | |
| 2193 | return; | |
| 2194 | } | |
| 2195 | memcpy(p, buf, t); | |
| 2196 | byteReverse(ctx->in, 16); | |
| 2197 | MD5Transform(ctx->buf, (uint32_t *) ctx->in); | |
| 2198 | buf += t; | |
| 2199 | len -= t; | |
| 2200 | } | |
| 2203 | 2201 | |
| 2204 | while (len >= 64) { | |
| 2205 | memcpy(ctx->in, buf, 64); | |
| 2206 | byteReverse(ctx->in, 16); | |
| 2207 | MD5Transform(ctx->buf, (uint32_t *) ctx->in); | |
| 2208 | buf += 64; | |
| 2209 | len -= 64; | |
| 2210 | } | |
| 2202 | while (len >= 64) { | |
| 2203 | memcpy(ctx->in, buf, 64); | |
| 2204 | byteReverse(ctx->in, 16); | |
| 2205 | MD5Transform(ctx->buf, (uint32_t *) ctx->in); | |
| 2206 | buf += 64; | |
| 2207 | len -= 64; | |
| 2208 | } | |
| 2211 | 2209 | |
| 2212 | ||
| 2210 | memcpy(ctx->in, buf, len); | |
| 2213 | 2211 | } |
| 2214 | 2212 | |
| 2215 | 2213 | static void MD5Final(unsigned char digest[16], MD5_CTX *ctx) { |
| 2216 | unsigned count; | |
| 2217 | unsigned char *p; | |
| 2218 | uint32_t *a; | |
| 2214 | unsigned count; | |
| 2215 | unsigned char *p; | |
| 2216 | uint32_t *a; | |
| 2219 | 2217 | |
| 2220 | ||
| 2218 | count = (ctx->bits[0] >> 3) & 0x3F; | |
| 2221 | 2219 | |
| 2222 | p = ctx->in + count; | |
| 2223 | *p++ = 0x80; | |
| 2224 | count = 64 - 1 - count; | |
| 2225 | if (count < 8) { | |
| 2226 | memset(p, 0, count); | |
| 2227 | byteReverse(ctx->in, 16); | |
| 2228 | MD5Transform(ctx->buf, (uint32_t *) ctx->in); | |
| 2229 | memset(ctx->in, 0, 56); | |
| 2230 | } else { | |
| 2231 | memset(p, 0, count - 8); | |
| 2232 | } | |
| 2233 | byteReverse(ctx->in, 14); | |
| 2220 | p = ctx->in + count; | |
| 2221 | *p++ = 0x80; | |
| 2222 | count = 64 - 1 - count; | |
| 2223 | if (count < 8) { | |
| 2224 | memset(p, 0, count); | |
| 2225 | byteReverse(ctx->in, 16); | |
| 2226 | MD5Transform(ctx->buf, (uint32_t *) ctx->in); | |
| 2227 | memset(ctx->in, 0, 56); | |
| 2228 | } else { | |
| 2229 | memset(p, 0, count - 8); | |
| 2230 | } | |
| 2231 | byteReverse(ctx->in, 14); | |
| 2234 | 2232 | |
| 2235 | a = (uint32_t *)ctx->in; | |
| 2236 | a[14] = ctx->bits[0]; | |
| 2237 | a[15] = ctx->bits[1]; | |
| 2233 | a = (uint32_t *)ctx->in; | |
| 2234 | a[14] = ctx->bits[0]; | |
| 2235 | a[15] = ctx->bits[1]; | |
| 2238 | 2236 | |
| 2239 | MD5Transform(ctx->buf, (uint32_t *) ctx->in); | |
| 2240 | byteReverse((unsigned char *) ctx->buf, 4); | |
| 2241 | memcpy(digest, ctx->buf, 16); | |
| 2242 | memset((char *) ctx, 0, sizeof(*ctx)); | |
| 2237 | MD5Transform(ctx->buf, (uint32_t *) ctx->in); | |
| 2238 | byteReverse((unsigned char *) ctx->buf, 4); | |
| 2239 | memcpy(digest, ctx->buf, 16); | |
| 2240 | memset((char *) ctx, 0, sizeof(*ctx)); | |
| 2243 | 2241 | } |
| 2244 | 2242 | #endif // !HAVE_MD5 |
| 2245 | 2243 | |
| 2246 | 2244 | // Stringify binary data. Output buffer must be twice as big as input, |
| 2247 | 2245 | // because each byte takes 2 bytes in string representation |
| 2248 | 2246 | static void bin2str(char *to, const unsigned char *p, size_t len) { |
| 2249 | ||
| 2247 | static const char *hex = "0123456789abcdef"; | |
| 2250 | 2248 | |
| 2251 | for (; len--; p++) { | |
| 2252 | *to++ = hex[p[0] >> 4]; | |
| 2253 | *to++ = hex[p[0] & 0x0f]; | |
| 2254 | } | |
| 2255 | *to = '\0'; | |
| 2249 | for (; len--; p++) { | |
| 2250 | *to++ = hex[p[0] >> 4]; | |
| 2251 | *to++ = hex[p[0] & 0x0f]; | |
| 2252 | } | |
| 2253 | *to = '\0'; | |
| 2256 | 2254 | } |
| 2257 | 2255 | |
| 2258 | 2256 | // Return stringified MD5 hash for list of strings. Buffer must be 33 bytes. |
| 2259 | 2257 | char *mg_md5(char buf[33], ...) { |
| 2260 | unsigned char hash[16]; | |
| 2261 | const char *p; | |
| 2262 | va_list ap; | |
| 2263 | MD5_CTX ctx; | |
| 2258 | unsigned char hash[16]; | |
| 2259 | const char *p; | |
| 2260 | va_list ap; | |
| 2261 | MD5_CTX ctx; | |
| 2264 | 2262 | |
| 2265 | ||
| 2263 | MD5Init(&ctx); | |
| 2266 | 2264 | |
| 2267 | va_start(ap, buf); | |
| 2268 | while ((p = va_arg(ap, const char *)) != NULL) { | |
| 2269 | MD5Update(&ctx, (const unsigned char *) p, (unsigned) strlen(p)); | |
| 2270 | } | |
| 2271 | va_end(ap); | |
| 2265 | va_start(ap, buf); | |
| 2266 | while ((p = va_arg(ap, const char *)) != NULL) { | |
| 2267 | MD5Update(&ctx, (const unsigned char *) p, (unsigned) strlen(p)); | |
| 2268 | } | |
| 2269 | va_end(ap); | |
| 2272 | 2270 | |
| 2273 | MD5Final(hash, &ctx); | |
| 2274 | bin2str(buf, hash, sizeof(hash)); | |
| 2275 | return buf; | |
| 2271 | MD5Final(hash, &ctx); | |
| 2272 | bin2str(buf, hash, sizeof(hash)); | |
| 2273 | return buf; | |
| 2276 | 2274 | } |
| 2277 | 2275 | |
| 2278 | 2276 | // Check the user's password, return 1 if OK |
| 2279 | 2277 | static int check_password(const char *method, const char *ha1, const char *uri, |
| 2280 | const char *nonce, const char *nc, const char *cnonce, | |
| 2281 | const char *qop, const char *response) { | |
| 2282 | char ha2[32 + 1], expected_response[32 + 1]; | |
| 2278 | const char *nonce, const char *nc, const char *cnonce, | |
| 2279 | const char *qop, const char *response) { | |
| 2280 | char ha2[32 + 1], expected_response[32 + 1]; | |
| 2283 | 2281 | |
| 2284 | // Some of the parameters may be NULL | |
| 2285 | if (method == NULL || nonce == NULL || nc == NULL || cnonce == NULL || | |
| 2286 | qop == NULL || response == NULL) { | |
| 2287 | return 0; | |
| 2288 | } | |
| 2282 | // Some of the parameters may be NULL | |
| 2283 | if (method == NULL || nonce == NULL || nc == NULL || cnonce == NULL || | |
| 2284 | qop == NULL || response == NULL) { | |
| 2285 | return 0; | |
| 2286 | } | |
| 2289 | 2287 | |
| 2290 | // NOTE(lsm): due to a bug in MSIE, we do not compare the URI | |
| 2291 | // TODO(lsm): check for authentication timeout | |
| 2292 | if (// strcmp(dig->uri, c->ouri) != 0 || | |
| 2293 | strlen(response) != 32 | |
| 2294 | // || now - strtoul(dig->nonce, NULL, 10) > 3600 | |
| 2295 | ) { | |
| 2296 | return 0; | |
| 2297 | } | |
| 2288 | // NOTE(lsm): due to a bug in MSIE, we do not compare the URI | |
| 2289 | // TODO(lsm): check for authentication timeout | |
| 2290 | if (// strcmp(dig->uri, c->ouri) != 0 || | |
| 2291 | strlen(response) != 32 | |
| 2292 | // || now - strtoul(dig->nonce, NULL, 10) > 3600 | |
| 2293 | ) { | |
| 2294 | return 0; | |
| 2295 | } | |
| 2298 | 2296 | |
| 2299 | mg_md5(ha2, method, ":", uri, NULL); | |
| 2300 | mg_md5(expected_response, ha1, ":", nonce, ":", nc, | |
| 2301 | ":", cnonce, ":", qop, ":", ha2, NULL); | |
| 2297 | mg_md5(ha2, method, ":", uri, NULL); | |
| 2298 | mg_md5(expected_response, ha1, ":", nonce, ":", nc, | |
| 2299 | ":", cnonce, ":", qop, ":", ha2, NULL); | |
| 2302 | 2300 | |
| 2303 | ||
| 2301 | return mg_strcasecmp(response, expected_response) == 0; | |
| 2304 | 2302 | } |
| 2305 | 2303 | |
| 2306 | 2304 | // Use the global passwords file, if specified by auth_gpass option, |
| 2307 | 2305 | // or search for .htpasswd in the requested directory. |
| 2308 | 2306 | static void open_auth_file(struct mg_connection *conn, const char *path, |
| 2309 | struct file *filep) { | |
| 2310 | char name[PATH_MAX]; | |
| 2311 | const char *p, *e, *gpass = conn->ctx->config[GLOBAL_PASSWORDS_FILE]; | |
| 2312 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 2307 | struct file *filep) { | |
| 2308 | char name[PATH_MAX]; | |
| 2309 | const char *p, *e, *gpass = conn->ctx->config[GLOBAL_PASSWORDS_FILE]; | |
| 2310 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 2313 | 2311 | |
| 2314 | if (gpass != NULL) { | |
| 2315 | // Use global passwords file | |
| 2316 | if (!mg_fopen(conn, gpass, "r", filep)) { | |
| 2317 | cry(conn, "fopen(%s): %s", gpass, strerror(ERRNO)); | |
| 2318 | } | |
| 2319 | // Important: using local struct file to test path for is_directory flag. | |
| 2320 | // If filep is used, mg_stat() makes it appear as if auth file was opened. | |
| 2321 | } else if (mg_stat(conn, path, &file) && file.is_directory) { | |
| 2322 | mg_snprintf(conn, name, sizeof(name), "%s%c%s", | |
| 2323 | path, '/', PASSWORDS_FILE_NAME); | |
| 2324 | mg_fopen(conn, name, "r", filep); | |
| 2325 | } else { | |
| 2326 | // Try to find .htpasswd in requested directory. | |
| 2327 | for (p = path, e = p + strlen(p) - 1; e > p; e--) | |
| 2328 | if (e[0] == '/') | |
| 2329 | break; | |
| 2330 | mg_snprintf(conn, name, sizeof(name), "%.*s%c%s", | |
| 2331 | (int) (e - p), p, '/', PASSWORDS_FILE_NAME); | |
| 2332 | mg_fopen(conn, name, "r", filep); | |
| 2333 | } | |
| 2312 | if (gpass != NULL) { | |
| 2313 | // Use global passwords file | |
| 2314 | if (!mg_fopen(conn, gpass, "r", filep)) { | |
| 2315 | cry(conn, "fopen(%s): %s", gpass, strerror(ERRNO)); | |
| 2316 | } | |
| 2317 | // Important: using local struct file to test path for is_directory flag. | |
| 2318 | // If filep is used, mg_stat() makes it appear as if auth file was opened. | |
| 2319 | } else if (mg_stat(conn, path, &file) && file.is_directory) { | |
| 2320 | mg_snprintf(conn, name, sizeof(name), "%s%c%s", | |
| 2321 | path, '/', PASSWORDS_FILE_NAME); | |
| 2322 | mg_fopen(conn, name, "r", filep); | |
| 2323 | } else { | |
| 2324 | // Try to find .htpasswd in requested directory. | |
| 2325 | for (p = path, e = p + strlen(p) - 1; e > p; e--) | |
| 2326 | if (e[0] == '/') | |
| 2327 | break; | |
| 2328 | mg_snprintf(conn, name, sizeof(name), "%.*s%c%s", | |
| 2329 | (int) (e - p), p, '/', PASSWORDS_FILE_NAME); | |
| 2330 | mg_fopen(conn, name, "r", filep); | |
| 2331 | } | |
| 2334 | 2332 | } |
| 2335 | 2333 | |
| 2336 | 2334 | // Parsed Authorization header |
| 2337 | 2335 | struct ah { |
| 2338 | ||
| 2336 | char *user, *uri, *cnonce, *response, *qop, *nc, *nonce; | |
| 2339 | 2337 | }; |
| 2340 | 2338 | |
| 2341 | 2339 | // Return 1 on success. Always initializes the ah structure. |
| 2342 | 2340 | static int parse_auth_header(struct mg_connection *conn, char *buf, |
| 2343 | size_t buf_size, struct ah *ah) { | |
| 2344 | char *name, *value, *s; | |
| 2345 | const char *auth_header; | |
| 2341 | size_t buf_size, struct ah *ah) { | |
| 2342 | char *name, *value, *s; | |
| 2343 | const char *auth_header; | |
| 2346 | 2344 | |
| 2347 | (void) memset(ah, 0, sizeof(*ah)); | |
| 2348 | if ((auth_header = mg_get_header(conn, "Authorization")) == NULL || | |
| 2349 | mg_strncasecmp(auth_header, "Digest ", 7) != 0) { | |
| 2350 | return 0; | |
| 2351 | } | |
| 2345 | (void) memset(ah, 0, sizeof(*ah)); | |
| 2346 | if ((auth_header = mg_get_header(conn, "Authorization")) == NULL || | |
| 2347 | mg_strncasecmp(auth_header, "Digest ", 7) != 0) { | |
| 2348 | return 0; | |
| 2349 | } | |
| 2352 | 2350 | |
| 2353 | // Make modifiable copy of the auth header | |
| 2354 | (void) mg_strlcpy(buf, auth_header + 7, buf_size); | |
| 2355 | s = buf; | |
| 2351 | // Make modifiable copy of the auth header | |
| 2352 | (void) mg_strlcpy(buf, auth_header + 7, buf_size); | |
| 2353 | s = buf; | |
| 2356 | 2354 | |
| 2357 | // Parse authorization header | |
| 2358 | for (;;) { | |
| 2359 | // Gobble initial spaces | |
| 2360 | while (isspace(* (unsigned char *) s)) { | |
| 2361 | s++; | |
| 2362 | } | |
| 2363 | name = skip_quoted(&s, "=", " ", 0); | |
| 2364 | // Value is either quote-delimited, or ends at first comma or space. | |
| 2365 | if (s[0] == '\"') { | |
| 2366 | s++; | |
| 2367 | value = skip_quoted(&s, "\"", " ", '\\'); | |
| 2368 | if (s[0] == ',') { | |
| 2369 | s++; | |
| 2370 | } | |
| 2371 | } else { | |
| 2372 | value = skip_quoted(&s, ", ", " ", 0); // IE uses commas, FF uses spaces | |
| 2373 | } | |
| 2374 | if (*name == '\0') { | |
| 2375 | break; | |
| 2376 | } | |
| 2355 | // Parse authorization header | |
| 2356 | for (;;) { | |
| 2357 | // Gobble initial spaces | |
| 2358 | while (isspace(* (unsigned char *) s)) { | |
| 2359 | s++; | |
| 2360 | } | |
| 2361 | name = skip_quoted(&s, "=", " ", 0); | |
| 2362 | // Value is either quote-delimited, or ends at first comma or space. | |
| 2363 | if (s[0] == '\"') { | |
| 2364 | s++; | |
| 2365 | value = skip_quoted(&s, "\"", " ", '\\'); | |
| 2366 | if (s[0] == ',') { | |
| 2367 | s++; | |
| 2368 | } | |
| 2369 | } else { | |
| 2370 | value = skip_quoted(&s, ", ", " ", 0); // IE uses commas, FF uses spaces | |
| 2371 | } | |
| 2372 | if (*name == '\0') { | |
| 2373 | break; | |
| 2374 | } | |
| 2377 | 2375 | |
| 2378 | if (!strcmp(name, "username")) { | |
| 2379 | ah->user = value; | |
| 2380 | } else if (!strcmp(name, "cnonce")) { | |
| 2381 | ah->cnonce = value; | |
| 2382 | } else if (!strcmp(name, "response")) { | |
| 2383 | ah->response = value; | |
| 2384 | } else if (!strcmp(name, "uri")) { | |
| 2385 | ah->uri = value; | |
| 2386 | } else if (!strcmp(name, "qop")) { | |
| 2387 | ah->qop = value; | |
| 2388 | } else if (!strcmp(name, "nc")) { | |
| 2389 | ah->nc = value; | |
| 2390 | } else if (!strcmp(name, "nonce")) { | |
| 2391 | ah->nonce = value; | |
| 2392 | } | |
| 2393 | } | |
| 2376 | if (!strcmp(name, "username")) { | |
| 2377 | ah->user = value; | |
| 2378 | } else if (!strcmp(name, "cnonce")) { | |
| 2379 | ah->cnonce = value; | |
| 2380 | } else if (!strcmp(name, "response")) { | |
| 2381 | ah->response = value; | |
| 2382 | } else if (!strcmp(name, "uri")) { | |
| 2383 | ah->uri = value; | |
| 2384 | } else if (!strcmp(name, "qop")) { | |
| 2385 | ah->qop = value; | |
| 2386 | } else if (!strcmp(name, "nc")) { | |
| 2387 | ah->nc = value; | |
| 2388 | } else if (!strcmp(name, "nonce")) { | |
| 2389 | ah->nonce = value; | |
| 2390 | } | |
| 2391 | } | |
| 2394 | 2392 | |
| 2395 | // CGI needs it as REMOTE_USER | |
| 2396 | if (ah->user != NULL) { | |
| 2397 | conn->request_info.remote_user = mg_strdup(ah->user); | |
| 2398 | } else { | |
| 2399 | return 0; | |
| 2400 | } | |
| 2393 | // CGI needs it as REMOTE_USER | |
| 2394 | if (ah->user != NULL) { | |
| 2395 | conn->request_info.remote_user = mg_strdup(ah->user); | |
| 2396 | } else { | |
| 2397 | return 0; | |
| 2398 | } | |
| 2401 | 2399 | |
| 2402 | ||
| 2400 | return 1; | |
| 2403 | 2401 | } |
| 2404 | 2402 | |
| 2405 | 2403 | static char *mg_fgets(char *buf, size_t size, struct file *filep, char **p) { |
| 2406 | char *eof; | |
| 2407 | size_t len; | |
| 2404 | char *eof; | |
| 2405 | size_t len; | |
| 2408 | 2406 | |
| 2409 | if (filep->membuf != NULL && *p != NULL) { | |
| 2410 | eof = (char*)memchr(*p, '\n', &filep->membuf[filep->size] - *p); | |
| 2411 | len = (size_t) (eof - *p) > size - 1 ? size - 1 : (size_t) (eof - *p); | |
| 2412 | memcpy(buf, *p, len); | |
| 2413 | buf[len] = '\0'; | |
| 2414 | *p = eof; | |
| 2415 | return eof; | |
| 2416 | } else if (filep->fp != NULL) { | |
| 2417 | return fgets(buf, size, filep->fp); | |
| 2418 | } else { | |
| 2419 | return NULL; | |
| 2420 | } | |
| 2407 | if (filep->membuf != NULL && *p != NULL) { | |
| 2408 | eof = (char*)memchr(*p, '\n', &filep->membuf[filep->size] - *p); | |
| 2409 | len = (size_t) (eof - *p) > size - 1 ? size - 1 : (size_t) (eof - *p); | |
| 2410 | memcpy(buf, *p, len); | |
| 2411 | buf[len] = '\0'; | |
| 2412 | *p = eof; | |
| 2413 | return eof; | |
| 2414 | } else if (filep->fp != NULL) { | |
| 2415 | return fgets(buf, size, filep->fp); | |
| 2416 | } else { | |
| 2417 | return NULL; | |
| 2418 | } | |
| 2421 | 2419 | } |
| 2422 | 2420 | |
| 2423 | 2421 | // Authorize against the opened passwords file. Return 1 if authorized. |
| 2424 | 2422 | static int authorize(struct mg_connection *conn, struct file *filep) { |
| 2425 | struct ah ah; | |
| 2426 | char line[256], f_user[256], ha1[256], f_domain[256], buf[MG_BUF_LEN], *p; | |
| 2423 | struct ah ah; | |
| 2424 | char line[256], f_user[256], ha1[256], f_domain[256], buf[MG_BUF_LEN], *p; | |
| 2427 | 2425 | |
| 2428 | if (!parse_auth_header(conn, buf, sizeof(buf), &ah)) { | |
| 2429 | return 0; | |
| 2430 | } | |
| 2426 | if (!parse_auth_header(conn, buf, sizeof(buf), &ah)) { | |
| 2427 | return 0; | |
| 2428 | } | |
| 2431 | 2429 | |
| 2432 | // Loop over passwords file | |
| 2433 | p = (char *) filep->membuf; | |
| 2434 | while (mg_fgets(line, sizeof(line), filep, &p) != NULL) { | |
| 2435 | if (sscanf(line, "%[^:]:%[^:]:%s", f_user, f_domain, ha1) != 3) { | |
| 2436 | continue; | |
| 2437 | } | |
| 2430 | // Loop over passwords file | |
| 2431 | p = (char *) filep->membuf; | |
| 2432 | while (mg_fgets(line, sizeof(line), filep, &p) != NULL) { | |
| 2433 | if (sscanf(line, "%[^:]:%[^:]:%s", f_user, f_domain, ha1) != 3) { | |
| 2434 | continue; | |
| 2435 | } | |
| 2438 | 2436 | |
| 2439 | if (!strcmp(ah.user, f_user) && | |
| 2440 | !strcmp(conn->ctx->config[AUTHENTICATION_DOMAIN], f_domain)) | |
| 2441 | return check_password(conn->request_info.request_method, ha1, ah.uri, | |
| 2442 | ah.nonce, ah.nc, ah.cnonce, ah.qop, ah.response); | |
| 2443 | } | |
| 2437 | if (!strcmp(ah.user, f_user) && | |
| 2438 | !strcmp(conn->ctx->config[AUTHENTICATION_DOMAIN], f_domain)) | |
| 2439 | return check_password(conn->request_info.request_method, ha1, ah.uri, | |
| 2440 | ah.nonce, ah.nc, ah.cnonce, ah.qop, ah.response); | |
| 2441 | } | |
| 2444 | 2442 | |
| 2445 | ||
| 2443 | return 0; | |
| 2446 | 2444 | } |
| 2447 | 2445 | |
| 2448 | 2446 | // Return 1 if request is authorised, 0 otherwise. |
| 2449 | 2447 | static int check_authorization(struct mg_connection *conn, const char *path) { |
| 2450 | char fname[PATH_MAX]; | |
| 2451 | struct vec uri_vec, filename_vec; | |
| 2452 | const char *list; | |
| 2453 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 2454 | int authorized = 1; | |
| 2448 | char fname[PATH_MAX]; | |
| 2449 | struct vec uri_vec, filename_vec; | |
| 2450 | const char *list; | |
| 2451 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 2452 | int authorized = 1; | |
| 2455 | 2453 | |
| 2456 | list = conn->ctx->config[PROTECT_URI]; | |
| 2457 | while ((list = next_option(list, &uri_vec, &filename_vec)) != NULL) { | |
| 2458 | if (!memcmp(conn->request_info.uri, uri_vec.ptr, uri_vec.len)) { | |
| 2459 | mg_snprintf(conn, fname, sizeof(fname), "%.*s", | |
| 2460 | (int) filename_vec.len, filename_vec.ptr); | |
| 2461 | if (!mg_fopen(conn, fname, "r", &file)) { | |
| 2462 | cry(conn, "%s: cannot open %s: %s", __func__, fname, strerror(errno)); | |
| 2463 | } | |
| 2464 | break; | |
| 2465 | } | |
| 2466 | } | |
| 2454 | list = conn->ctx->config[PROTECT_URI]; | |
| 2455 | while ((list = next_option(list, &uri_vec, &filename_vec)) != NULL) { | |
| 2456 | if (!memcmp(conn->request_info.uri, uri_vec.ptr, uri_vec.len)) { | |
| 2457 | mg_snprintf(conn, fname, sizeof(fname), "%.*s", | |
| 2458 | (int) filename_vec.len, filename_vec.ptr); | |
| 2459 | if (!mg_fopen(conn, fname, "r", &file)) { | |
| 2460 | cry(conn, "%s: cannot open %s: %s", __func__, fname, strerror(errno)); | |
| 2461 | } | |
| 2462 | break; | |
| 2463 | } | |
| 2464 | } | |
| 2467 | 2465 | |
| 2468 | if (!is_file_opened(&file)) { | |
| 2469 | open_auth_file(conn, path, &file); | |
| 2470 | } | |
| 2466 | if (!is_file_opened(&file)) { | |
| 2467 | open_auth_file(conn, path, &file); | |
| 2468 | } | |
| 2471 | 2469 | |
| 2472 | if (is_file_opened(&file)) { | |
| 2473 | authorized = authorize(conn, &file); | |
| 2474 | mg_fclose(&file); | |
| 2475 | } | |
| 2470 | if (is_file_opened(&file)) { | |
| 2471 | authorized = authorize(conn, &file); | |
| 2472 | mg_fclose(&file); | |
| 2473 | } | |
| 2476 | 2474 | |
| 2477 | ||
| 2475 | return authorized; | |
| 2478 | 2476 | } |
| 2479 | 2477 | |
| 2480 | 2478 | static void send_authorization_request(struct mg_connection *conn) { |
| 2481 | conn->status_code = 401; | |
| 2482 | mg_printf(conn, | |
| 2483 | "HTTP/1.1 401 Unauthorized\r\n" | |
| 2484 | "Content-Length: 0\r\n" | |
| 2485 | "WWW-Authenticate: Digest qop=\"auth\", " | |
| 2486 | "realm=\"%s\", nonce=\"%lu\"\r\n\r\n", | |
| 2487 | conn->ctx->config[AUTHENTICATION_DOMAIN], | |
| 2488 | (unsigned long) time(NULL)); | |
| 2479 | conn->status_code = 401; | |
| 2480 | mg_printf(conn, | |
| 2481 | "HTTP/1.1 401 Unauthorized\r\n" | |
| 2482 | "Content-Length: 0\r\n" | |
| 2483 | "WWW-Authenticate: Digest qop=\"auth\", " | |
| 2484 | "realm=\"%s\", nonce=\"%lu\"\r\n\r\n", | |
| 2485 | conn->ctx->config[AUTHENTICATION_DOMAIN], | |
| 2486 | (unsigned long) time(NULL)); | |
| 2489 | 2487 | } |
| 2490 | 2488 | |
| 2491 | 2489 | static int is_authorized_for_put(struct mg_connection *conn) { |
| 2492 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 2493 | const char *passfile = conn->ctx->config[PUT_DELETE_PASSWORDS_FILE]; | |
| 2494 | int ret = 0; | |
| 2490 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 2491 | const char *passfile = conn->ctx->config[PUT_DELETE_PASSWORDS_FILE]; | |
| 2492 | int ret = 0; | |
| 2495 | 2493 | |
| 2496 | if (passfile != NULL && mg_fopen(conn, passfile, "r", &file)) { | |
| 2497 | ret = authorize(conn, &file); | |
| 2498 | mg_fclose(&file); | |
| 2499 | } | |
| 2494 | if (passfile != NULL && mg_fopen(conn, passfile, "r", &file)) { | |
| 2495 | ret = authorize(conn, &file); | |
| 2496 | mg_fclose(&file); | |
| 2497 | } | |
| 2500 | 2498 | |
| 2501 | ||
| 2499 | return ret; | |
| 2502 | 2500 | } |
| 2503 | 2501 | |
| 2504 | 2502 | int mg_modify_passwords_file(const char *fname, const char *domain, |
| 2505 | const char *user, const char *pass) { | |
| 2506 | int found; | |
| 2507 | char line[512], u[512], d[512], ha1[33], tmp[PATH_MAX]; | |
| 2508 | FILE *fp, *fp2; | |
| 2503 | const char *user, const char *pass) { | |
| 2504 | int found; | |
| 2505 | char line[512], u[512], d[512], ha1[33], tmp[PATH_MAX]; | |
| 2506 | FILE *fp, *fp2; | |
| 2509 | 2507 | |
| 2510 | found = 0; | |
| 2511 | fp = fp2 = NULL; | |
| 2508 | found = 0; | |
| 2509 | fp = fp2 = NULL; | |
| 2512 | 2510 | |
| 2513 | // Regard empty password as no password - remove user record. | |
| 2514 | if (pass != NULL && pass[0] == '\0') { | |
| 2515 | pass = NULL; | |
| 2516 | } | |
| 2511 | // Regard empty password as no password - remove user record. | |
| 2512 | if (pass != NULL && pass[0] == '\0') { | |
| 2513 | pass = NULL; | |
| 2514 | } | |
| 2517 | 2515 | |
| 2518 | ||
| 2516 | (void) snprintf(tmp, sizeof(tmp), "%s.tmp", fname); | |
| 2519 | 2517 | |
| 2520 | // Create the file if does not exist | |
| 2521 | if ((fp = fopen(fname, "a+")) != NULL) { | |
| 2522 | (void) fclose(fp); | |
| 2523 | } | |
| 2518 | // Create the file if does not exist | |
| 2519 | if ((fp = fopen(fname, "a+")) != NULL) { | |
| 2520 | (void) fclose(fp); | |
| 2521 | } | |
| 2524 | 2522 | |
| 2525 | // Open the given file and temporary file | |
| 2526 | if ((fp = fopen(fname, "r")) == NULL) { | |
| 2527 | return 0; | |
| 2528 | } else if ((fp2 = fopen(tmp, "w+")) == NULL) { | |
| 2529 | fclose(fp); | |
| 2530 | return 0; | |
| 2531 | } | |
| 2523 | // Open the given file and temporary file | |
| 2524 | if ((fp = fopen(fname, "r")) == NULL) { | |
| 2525 | return 0; | |
| 2526 | } else if ((fp2 = fopen(tmp, "w+")) == NULL) { | |
| 2527 | fclose(fp); | |
| 2528 | return 0; | |
| 2529 | } | |
| 2532 | 2530 | |
| 2533 | // Copy the stuff to temporary file | |
| 2534 | while (fgets(line, sizeof(line), fp) != NULL) { | |
| 2535 | if (sscanf(line, "%[^:]:%[^:]:%*s", u, d) != 2) { | |
| 2536 | continue; | |
| 2537 | } | |
| 2531 | // Copy the stuff to temporary file | |
| 2532 | while (fgets(line, sizeof(line), fp) != NULL) { | |
| 2533 | if (sscanf(line, "%[^:]:%[^:]:%*s", u, d) != 2) { | |
| 2534 | continue; | |
| 2535 | } | |
| 2538 | 2536 | |
| 2539 | if (!strcmp(u, user) && !strcmp(d, domain)) { | |
| 2540 | found++; | |
| 2541 | if (pass != NULL) { | |
| 2542 | mg_md5(ha1, user, ":", domain, ":", pass, NULL); | |
| 2543 | fprintf(fp2, "%s:%s:%s\n", user, domain, ha1); | |
| 2544 | } | |
| 2545 | } else { | |
| 2546 | fprintf(fp2, "%s", line); | |
| 2547 | } | |
| 2548 | } | |
| 2537 | if (!strcmp(u, user) && !strcmp(d, domain)) { | |
| 2538 | found++; | |
| 2539 | if (pass != NULL) { | |
| 2540 | mg_md5(ha1, user, ":", domain, ":", pass, NULL); | |
| 2541 | fprintf(fp2, "%s:%s:%s\n", user, domain, ha1); | |
| 2542 | } | |
| 2543 | } else { | |
| 2544 | fprintf(fp2, "%s", line); | |
| 2545 | } | |
| 2546 | } | |
| 2549 | 2547 | |
| 2550 | // If new user, just add it | |
| 2551 | if (!found && pass != NULL) { | |
| 2552 | mg_md5(ha1, user, ":", domain, ":", pass, NULL); | |
| 2553 | fprintf(fp2, "%s:%s:%s\n", user, domain, ha1); | |
| 2554 | } | |
| 2548 | // If new user, just add it | |
| 2549 | if (!found && pass != NULL) { | |
| 2550 | mg_md5(ha1, user, ":", domain, ":", pass, NULL); | |
| 2551 | fprintf(fp2, "%s:%s:%s\n", user, domain, ha1); | |
| 2552 | } | |
| 2555 | 2553 | |
| 2556 | // Close files | |
| 2557 | fclose(fp); | |
| 2558 | fclose(fp2); | |
| 2554 | // Close files | |
| 2555 | fclose(fp); | |
| 2556 | fclose(fp2); | |
| 2559 | 2557 | |
| 2560 | // Put the temp file in place of real file | |
| 2561 | remove(fname); | |
| 2562 | rename(tmp, fname); | |
| 2558 | // Put the temp file in place of real file | |
| 2559 | remove(fname); | |
| 2560 | rename(tmp, fname); | |
| 2563 | 2561 | |
| 2564 | ||
| 2562 | return 1; | |
| 2565 | 2563 | } |
| 2566 | 2564 | |
| 2567 | 2565 | static int conn2(const char *host, int port, int use_ssl, |
| 2568 | char *ebuf, size_t ebuf_len) { | |
| 2569 | struct sockaddr_in sin; | |
| 2570 | struct hostent *he; | |
| 2571 | SOCKET sock = INVALID_SOCKET; | |
| 2566 | char *ebuf, size_t ebuf_len) { | |
| 2567 | struct sockaddr_in sin; | |
| 2568 | struct hostent *he; | |
| 2569 | SOCKET sock = INVALID_SOCKET; | |
| 2572 | 2570 | |
| 2573 | if (host == NULL) { | |
| 2574 | snprintf(ebuf, ebuf_len, "%s", "NULL host"); | |
| 2575 | } else if (use_ssl && SSLv23_client_method == NULL) { | |
| 2576 | snprintf(ebuf, ebuf_len, "%s", "SSL is not initialized"); | |
| 2577 | // TODO(lsm): use something threadsafe instead of gethostbyname() | |
| 2578 | } else if ((he = gethostbyname(host)) == NULL) { | |
| 2579 | snprintf(ebuf, ebuf_len, "gethostbyname(%s): %s", host, strerror(ERRNO)); | |
| 2580 | } else if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { | |
| 2581 | snprintf(ebuf, ebuf_len, "socket(): %s", strerror(ERRNO)); | |
| 2582 | } else { | |
| 2583 | sin.sin_family = AF_INET; | |
| 2584 | sin.sin_port = htons((uint16_t) port); | |
| 2585 | sin.sin_addr = * (struct in_addr *) he->h_addr_list[0]; | |
| 2586 | if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) != 0) { | |
| 2587 | snprintf(ebuf, ebuf_len, "connect(%s:%d): %s", | |
| 2588 | host, port, strerror(ERRNO)); | |
| 2589 | closesocket(sock); | |
| 2590 | sock = INVALID_SOCKET; | |
| 2591 | } | |
| 2592 | } | |
| 2593 | return sock; | |
| 2571 | if (host == NULL) { | |
| 2572 | snprintf(ebuf, ebuf_len, "%s", "NULL host"); | |
| 2573 | } else if (use_ssl && SSLv23_client_method == NULL) { | |
| 2574 | snprintf(ebuf, ebuf_len, "%s", "SSL is not initialized"); | |
| 2575 | // TODO(lsm): use something threadsafe instead of gethostbyname() | |
| 2576 | } else if ((he = gethostbyname(host)) == NULL) { | |
| 2577 | snprintf(ebuf, ebuf_len, "gethostbyname(%s): %s", host, strerror(ERRNO)); | |
| 2578 | } else if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { | |
| 2579 | snprintf(ebuf, ebuf_len, "socket(): %s", strerror(ERRNO)); | |
| 2580 | } else { | |
| 2581 | sin.sin_family = AF_INET; | |
| 2582 | sin.sin_port = htons((uint16_t) port); | |
| 2583 | sin.sin_addr = * (struct in_addr *) he->h_addr_list[0]; | |
| 2584 | if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) != 0) { | |
| 2585 | snprintf(ebuf, ebuf_len, "connect(%s:%d): %s", | |
| 2586 | host, port, strerror(ERRNO)); | |
| 2587 | closesocket(sock); | |
| 2588 | sock = INVALID_SOCKET; | |
| 2589 | } | |
| 2590 | } | |
| 2591 | return sock; | |
| 2594 | 2592 | } |
| 2595 | 2593 | |
| 2596 | 2594 | |
| 2597 | 2595 | |
| 2598 | 2596 | void mg_url_encode(const char *src, char *dst, size_t dst_len) { |
| 2599 | static const char *dont_escape = "._-$,;~()"; | |
| 2600 | static const char *hex = "0123456789abcdef"; | |
| 2601 | const char *end = dst + dst_len - 1; | |
| 2597 | static const char *dont_escape = "._-$,;~()"; | |
| 2598 | static const char *hex = "0123456789abcdef"; | |
| 2599 | const char *end = dst + dst_len - 1; | |
| 2602 | 2600 | |
| 2603 | for (; *src != '\0' && dst < end; src++, dst++) { | |
| 2604 | if (isalnum(*(const unsigned char *) src) || | |
| 2605 | strchr(dont_escape, * (const unsigned char *) src) != NULL) { | |
| 2606 | *dst = *src; | |
| 2607 | } else if (dst + 2 < end) { | |
| 2608 | dst[0] = '%'; | |
| 2609 | dst[1] = hex[(* (const unsigned char *) src) >> 4]; | |
| 2610 | dst[2] = hex[(* (const unsigned char *) src) & 0xf]; | |
| 2611 | dst += 2; | |
| 2612 | } | |
| 2613 | } | |
| 2601 | for (; *src != '\0' && dst < end; src++, dst++) { | |
| 2602 | if (isalnum(*(const unsigned char *) src) || | |
| 2603 | strchr(dont_escape, * (const unsigned char *) src) != NULL) { | |
| 2604 | *dst = *src; | |
| 2605 | } else if (dst + 2 < end) { | |
| 2606 | dst[0] = '%'; | |
| 2607 | dst[1] = hex[(* (const unsigned char *) src) >> 4]; | |
| 2608 | dst[2] = hex[(* (const unsigned char *) src) & 0xf]; | |
| 2609 | dst += 2; | |
| 2610 | } | |
| 2611 | } | |
| 2614 | 2612 | |
| 2615 | ||
| 2613 | *dst = '\0'; | |
| 2616 | 2614 | } |
| 2617 | 2615 | |
| 2618 | 2616 | static void print_dir_entry(struct de *de) { |
| 2619 | ||
| 2617 | char size[64], mod[64], href[PATH_MAX]; | |
| 2620 | 2618 | |
| 2621 | if (de->file.is_directory) { | |
| 2622 | mg_snprintf(de->conn, size, sizeof(size), "%s", "[DIRECTORY]"); | |
| 2623 | } else { | |
| 2624 | // We use (signed) cast below because MSVC 6 compiler cannot | |
| 2625 | // convert unsigned __int64 to double. Sigh. | |
| 2626 | if (de->file.size < 1024) { | |
| 2627 | mg_snprintf(de->conn, size, sizeof(size), "%d", (int) de->file.size); | |
| 2628 | } else if (de->file.size < 0x100000) { | |
| 2629 | mg_snprintf(de->conn, size, sizeof(size), | |
| 2630 | "%.1fk", (double) de->file.size / 1024.0); | |
| 2631 | } else if (de->file.size < 0x40000000) { | |
| 2632 | mg_snprintf(de->conn, size, sizeof(size), | |
| 2633 | "%.1fM", (double) de->file.size / 1048576); | |
| 2634 | } else { | |
| 2635 | mg_snprintf(de->conn, size, sizeof(size), | |
| 2636 | "%.1fG", (double) de->file.size / 1073741824); | |
| 2637 | } | |
| 2638 | } | |
| 2639 | strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", | |
| 2640 | localtime(&de->file.modification_time)); | |
| 2641 | mg_url_encode(de->file_name, href, sizeof(href)); | |
| 2642 | de->conn->num_bytes_sent += mg_printf(de->conn, | |
| 2643 | "<tr><td><a href=\"%s%s%s\">%s%s</a></td>" | |
| 2644 | "<td> %s</td><td> %s</td></tr>\n", | |
| 2645 | de->conn->request_info.uri, href, de->file.is_directory ? "/" : "", | |
| 2646 | de->file_name, de->file.is_directory ? "/" : "", mod, size); | |
| 2619 | if (de->file.is_directory) { | |
| 2620 | mg_snprintf(de->conn, size, sizeof(size), "%s", "[DIRECTORY]"); | |
| 2621 | } else { | |
| 2622 | // We use (signed) cast below because MSVC 6 compiler cannot | |
| 2623 | // convert unsigned __int64 to double. Sigh. | |
| 2624 | if (de->file.size < 1024) { | |
| 2625 | mg_snprintf(de->conn, size, sizeof(size), "%d", (int) de->file.size); | |
| 2626 | } else if (de->file.size < 0x100000) { | |
| 2627 | mg_snprintf(de->conn, size, sizeof(size), | |
| 2628 | "%.1fk", (double) de->file.size / 1024.0); | |
| 2629 | } else if (de->file.size < 0x40000000) { | |
| 2630 | mg_snprintf(de->conn, size, sizeof(size), | |
| 2631 | "%.1fM", (double) de->file.size / 1048576); | |
| 2632 | } else { | |
| 2633 | mg_snprintf(de->conn, size, sizeof(size), | |
| 2634 | "%.1fG", (double) de->file.size / 1073741824); | |
| 2635 | } | |
| 2636 | } | |
| 2637 | strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", | |
| 2638 | localtime(&de->file.modification_time)); | |
| 2639 | mg_url_encode(de->file_name, href, sizeof(href)); | |
| 2640 | de->conn->num_bytes_sent += mg_printf(de->conn, | |
| 2641 | "<tr><td><a href=\"%s%s%s\">%s%s</a></td>" | |
| 2642 | "<td> %s</td><td> %s</td></tr>\n", | |
| 2643 | de->conn->request_info.uri, href, de->file.is_directory ? "/" : "", | |
| 2644 | de->file_name, de->file.is_directory ? "/" : "", mod, size); | |
| 2647 | 2645 | } |
| 2648 | 2646 | |
| 2649 | 2647 | // This function is called from send_directory() and used for |
| r25360 | r25361 | |
| 2651 | 2649 | // On windows, __cdecl specification is needed in case if project is built |
| 2652 | 2650 | // with __stdcall convention. qsort always requires __cdels callback. |
| 2653 | 2651 | static int WINCDECL compare_dir_entries(const void *p1, const void *p2) { |
| 2654 | const struct de *a = (const struct de *) p1, *b = (const struct de *) p2; | |
| 2655 | const char *query_string = a->conn->request_info.query_string; | |
| 2656 | int cmp_result = 0; | |
| 2652 | const struct de *a = (const struct de *) p1, *b = (const struct de *) p2; | |
| 2653 | const char *query_string = a->conn->request_info.query_string; | |
| 2654 | int cmp_result = 0; | |
| 2657 | 2655 | |
| 2658 | if (query_string == NULL) { | |
| 2659 | query_string = "na"; | |
| 2660 | } | |
| 2656 | if (query_string == NULL) { | |
| 2657 | query_string = "na"; | |
| 2658 | } | |
| 2661 | 2659 | |
| 2662 | if (a->file.is_directory && !b->file.is_directory) { | |
| 2663 | return -1; // Always put directories on top | |
| 2664 | } else if (!a->file.is_directory && b->file.is_directory) { | |
| 2665 | return 1; // Always put directories on top | |
| 2666 | } else if (*query_string == 'n') { | |
| 2667 | cmp_result = strcmp(a->file_name, b->file_name); | |
| 2668 | } else if (*query_string == 's') { | |
| 2669 | cmp_result = a->file.size == b->file.size ? 0 : | |
| 2670 | a->file.size > b->file.size ? 1 : -1; | |
| 2671 | } else if (*query_string == 'd') { | |
| 2672 | cmp_result = a->file.modification_time == b->file.modification_time ? 0 : | |
| 2673 | a->file.modification_time > b->file.modification_time ? 1 : -1; | |
| 2674 | } | |
| 2660 | if (a->file.is_directory && !b->file.is_directory) { | |
| 2661 | return -1; // Always put directories on top | |
| 2662 | } else if (!a->file.is_directory && b->file.is_directory) { | |
| 2663 | return 1; // Always put directories on top | |
| 2664 | } else if (*query_string == 'n') { | |
| 2665 | cmp_result = strcmp(a->file_name, b->file_name); | |
| 2666 | } else if (*query_string == 's') { | |
| 2667 | cmp_result = a->file.size == b->file.size ? 0 : | |
| 2668 | a->file.size > b->file.size ? 1 : -1; | |
| 2669 | } else if (*query_string == 'd') { | |
| 2670 | cmp_result = a->file.modification_time == b->file.modification_time ? 0 : | |
| 2671 | a->file.modification_time > b->file.modification_time ? 1 : -1; | |
| 2672 | } | |
| 2675 | 2673 | |
| 2676 | ||
| 2674 | return query_string[1] == 'd' ? -cmp_result : cmp_result; | |
| 2677 | 2675 | } |
| 2678 | 2676 | |
| 2679 | 2677 | static int must_hide_file(struct mg_connection *conn, const char *path) { |
| 2680 | const char *pw_pattern = "**" PASSWORDS_FILE_NAME "$"; | |
| 2681 | const char *pattern = conn->ctx->config[HIDE_FILES]; | |
| 2682 | return match_prefix(pw_pattern, strlen(pw_pattern), path) > 0 || | |
| 2683 | (pattern != NULL && match_prefix(pattern, strlen(pattern), path) > 0); | |
| 2678 | const char *pw_pattern = "**" PASSWORDS_FILE_NAME "$"; | |
| 2679 | const char *pattern = conn->ctx->config[HIDE_FILES]; | |
| 2680 | return match_prefix(pw_pattern, strlen(pw_pattern), path) > 0 || | |
| 2681 | (pattern != NULL && match_prefix(pattern, strlen(pattern), path) > 0); | |
| 2684 | 2682 | } |
| 2685 | 2683 | |
| 2686 | 2684 | static int scan_directory(struct mg_connection *conn, const char *dir, |
| 2687 | void *data, void (*cb)(struct de *, void *)) { | |
| 2688 | char path[PATH_MAX]; | |
| 2689 | struct dirent *dp; | |
| 2690 | DIR *dirp; | |
| 2691 | struct de de; | |
| 2685 | void *data, void (*cb)(struct de *, void *)) { | |
| 2686 | char path[PATH_MAX]; | |
| 2687 | struct dirent *dp; | |
| 2688 | DIR *dirp; | |
| 2689 | struct de de; | |
| 2692 | 2690 | |
| 2693 | if ((dirp = opendir(dir)) == NULL) { | |
| 2694 | return 0; | |
| 2695 | } else { | |
| 2696 | de.conn = conn; | |
| 2691 | if ((dirp = opendir(dir)) == NULL) { | |
| 2692 | return 0; | |
| 2693 | } else { | |
| 2694 | de.conn = conn; | |
| 2697 | 2695 | |
| 2698 | while ((dp = readdir(dirp)) != NULL) { | |
| 2699 | // Do not show current dir and hidden files | |
| 2700 | if (!strcmp(dp->d_name, ".") || | |
| 2701 | !strcmp(dp->d_name, "..") || | |
| 2702 | must_hide_file(conn, dp->d_name)) { | |
| 2703 | continue; | |
| 2704 | } | |
| 2696 | while ((dp = readdir(dirp)) != NULL) { | |
| 2697 | // Do not show current dir and hidden files | |
| 2698 | if (!strcmp(dp->d_name, ".") || | |
| 2699 | !strcmp(dp->d_name, "..") || | |
| 2700 | must_hide_file(conn, dp->d_name)) { | |
| 2701 | continue; | |
| 2702 | } | |
| 2705 | 2703 | |
| 2706 | ||
| 2704 | mg_snprintf(conn, path, sizeof(path), "%s%c%s", dir, '/', dp->d_name); | |
| 2707 | 2705 | |
| 2708 | // If we don't memset stat structure to zero, mtime will have | |
| 2709 | // garbage and strftime() will segfault later on in | |
| 2710 | // print_dir_entry(). memset is required only if mg_stat() | |
| 2711 | // fails. For more details, see | |
| 2712 | // http://code.google.com/p/mongoose/issues/detail?id=79 | |
| 2713 | memset(&de.file, 0, sizeof(de.file)); | |
| 2714 | mg_stat(conn, path, &de.file); | |
| 2706 | // If we don't memset stat structure to zero, mtime will have | |
| 2707 | // garbage and strftime() will segfault later on in | |
| 2708 | // print_dir_entry(). memset is required only if mg_stat() | |
| 2709 | // fails. For more details, see | |
| 2710 | // http://code.google.com/p/mongoose/issues/detail?id=79 | |
| 2711 | memset(&de.file, 0, sizeof(de.file)); | |
| 2712 | mg_stat(conn, path, &de.file); | |
| 2715 | 2713 | |
| 2716 | de.file_name = dp->d_name; | |
| 2717 | cb(&de, data); | |
| 2718 | } | |
| 2719 | (void) closedir(dirp); | |
| 2720 | } | |
| 2721 | return 1; | |
| 2714 | de.file_name = dp->d_name; | |
| 2715 | cb(&de, data); | |
| 2716 | } | |
| 2717 | (void) closedir(dirp); | |
| 2718 | } | |
| 2719 | return 1; | |
| 2722 | 2720 | } |
| 2723 | 2721 | |
| 2724 | 2722 | static int remove_directory(struct mg_connection *conn, const char *dir) { |
| 2725 | char path[PATH_MAX]; | |
| 2726 | struct dirent *dp; | |
| 2727 | DIR *dirp; | |
| 2728 | struct de de; | |
| 2723 | char path[PATH_MAX]; | |
| 2724 | struct dirent *dp; | |
| 2725 | DIR *dirp; | |
| 2726 | struct de de; | |
| 2729 | 2727 | |
| 2730 | if ((dirp = opendir(dir)) == NULL) { | |
| 2731 | return 0; | |
| 2732 | } else { | |
| 2733 | de.conn = conn; | |
| 2728 | if ((dirp = opendir(dir)) == NULL) { | |
| 2729 | return 0; | |
| 2730 | } else { | |
| 2731 | de.conn = conn; | |
| 2734 | 2732 | |
| 2735 | while ((dp = readdir(dirp)) != NULL) { | |
| 2736 | // Do not show current dir (but show hidden files as they will also be removed) | |
| 2737 | if (!strcmp(dp->d_name, ".") || | |
| 2738 | !strcmp(dp->d_name, "..")) { | |
| 2739 | continue; | |
| 2740 | } | |
| 2733 | while ((dp = readdir(dirp)) != NULL) { | |
| 2734 | // Do not show current dir (but show hidden files as they will also be removed) | |
| 2735 | if (!strcmp(dp->d_name, ".") || | |
| 2736 | !strcmp(dp->d_name, "..")) { | |
| 2737 | continue; | |
| 2738 | } | |
| 2741 | 2739 | |
| 2742 | ||
| 2740 | mg_snprintf(conn, path, sizeof(path), "%s%c%s", dir, '/', dp->d_name); | |
| 2743 | 2741 | |
| 2744 | // If we don't memset stat structure to zero, mtime will have | |
| 2745 | // garbage and strftime() will segfault later on in | |
| 2746 | // print_dir_entry(). memset is required only if mg_stat() | |
| 2747 | // fails. For more details, see | |
| 2748 | // http://code.google.com/p/mongoose/issues/detail?id=79 | |
| 2749 | memset(&de.file, 0, sizeof(de.file)); | |
| 2750 | mg_stat(conn, path, &de.file); | |
| 2751 | if(de.file.modification_time) { | |
| 2752 | if(de.file.is_directory) { | |
| 2753 | remove_directory(conn, path); | |
| 2754 | } else { | |
| 2755 | mg_remove(path); | |
| 2756 | } | |
| 2757 | } | |
| 2742 | // If we don't memset stat structure to zero, mtime will have | |
| 2743 | // garbage and strftime() will segfault later on in | |
| 2744 | // print_dir_entry(). memset is required only if mg_stat() | |
| 2745 | // fails. For more details, see | |
| 2746 | // http://code.google.com/p/mongoose/issues/detail?id=79 | |
| 2747 | memset(&de.file, 0, sizeof(de.file)); | |
| 2748 | mg_stat(conn, path, &de.file); | |
| 2749 | if(de.file.modification_time) { | |
| 2750 | if(de.file.is_directory) { | |
| 2751 | remove_directory(conn, path); | |
| 2752 | } else { | |
| 2753 | mg_remove(path); | |
| 2754 | } | |
| 2755 | } | |
| 2758 | 2756 | |
| 2759 | } | |
| 2760 | (void) closedir(dirp); | |
| 2757 | } | |
| 2758 | (void) closedir(dirp); | |
| 2761 | 2759 | |
| 2762 | rmdir(dir); | |
| 2763 | } | |
| 2760 | rmdir(dir); | |
| 2761 | } | |
| 2764 | 2762 | |
| 2765 | ||
| 2763 | return 1; | |
| 2766 | 2764 | } |
| 2767 | 2765 | |
| 2768 | 2766 | struct dir_scan_data { |
| 2769 | struct de *entries; | |
| 2770 | int num_entries; | |
| 2771 | int arr_size; | |
| 2767 | struct de *entries; | |
| 2768 | int num_entries; | |
| 2769 | int arr_size; | |
| 2772 | 2770 | }; |
| 2773 | 2771 | |
| 2774 | 2772 | // Behaves like realloc(), but frees original pointer on failure |
| 2775 | 2773 | static void *realloc2(void *ptr, size_t size) { |
| 2776 | void *new_ptr = realloc(ptr, size); | |
| 2777 | if (new_ptr == NULL) { | |
| 2778 | free(ptr); | |
| 2779 | } | |
| 2780 | return new_ptr; | |
| 2774 | void *new_ptr = realloc(ptr, size); | |
| 2775 | if (new_ptr == NULL) { | |
| 2776 | free(ptr); | |
| 2777 | } | |
| 2778 | return new_ptr; | |
| 2781 | 2779 | } |
| 2782 | 2780 | |
| 2783 | 2781 | static void dir_scan_callback(struct de *de, void *data) { |
| 2784 | ||
| 2782 | struct dir_scan_data *dsd = (struct dir_scan_data *) data; | |
| 2785 | 2783 | |
| 2786 | if (dsd->entries == NULL || dsd->num_entries >= dsd->arr_size) { | |
| 2787 | dsd->arr_size *= 2; | |
| 2788 | dsd->entries = (struct de *) realloc2(dsd->entries, dsd->arr_size * | |
| 2789 | sizeof(dsd->entries[0])); | |
| 2790 | } | |
| 2791 | if (dsd->entries == NULL) { | |
| 2792 | // TODO(lsm): propagate an error to the caller | |
| 2793 | dsd->num_entries = 0; | |
| 2794 | } else { | |
| 2795 | dsd->entries[dsd->num_entries].file_name = mg_strdup(de->file_name); | |
| 2796 | dsd->entries[dsd->num_entries].file = de->file; | |
| 2797 | dsd->entries[dsd->num_entries].conn = de->conn; | |
| 2798 | dsd->num_entries++; | |
| 2799 | } | |
| 2784 | if (dsd->entries == NULL || dsd->num_entries >= dsd->arr_size) { | |
| 2785 | dsd->arr_size *= 2; | |
| 2786 | dsd->entries = (struct de *) realloc2(dsd->entries, dsd->arr_size * | |
| 2787 | sizeof(dsd->entries[0])); | |
| 2788 | } | |
| 2789 | if (dsd->entries == NULL) { | |
| 2790 | // TODO(lsm): propagate an error to the caller | |
| 2791 | dsd->num_entries = 0; | |
| 2792 | } else { | |
| 2793 | dsd->entries[dsd->num_entries].file_name = mg_strdup(de->file_name); | |
| 2794 | dsd->entries[dsd->num_entries].file = de->file; | |
| 2795 | dsd->entries[dsd->num_entries].conn = de->conn; | |
| 2796 | dsd->num_entries++; | |
| 2797 | } | |
| 2800 | 2798 | } |
| 2801 | 2799 | |
| 2802 | 2800 | static void handle_directory_request(struct mg_connection *conn, |
| 2803 | const char *dir) { | |
| 2804 | int i, sort_direction; | |
| 2805 | struct dir_scan_data data = { NULL, 0, 128 }; | |
| 2801 | const char *dir) { | |
| 2802 | int i, sort_direction; | |
| 2803 | struct dir_scan_data data = { NULL, 0, 128 }; | |
| 2806 | 2804 | |
| 2807 | if (!scan_directory(conn, dir, &data, dir_scan_callback)) { | |
| 2808 | send_http_error(conn, 500, "Cannot open directory", | |
| 2809 | "Error: opendir(%s): %s", dir, strerror(ERRNO)); | |
| 2810 | return; | |
| 2811 | } | |
| 2805 | if (!scan_directory(conn, dir, &data, dir_scan_callback)) { | |
| 2806 | send_http_error(conn, 500, "Cannot open directory", | |
| 2807 | "Error: opendir(%s): %s", dir, strerror(ERRNO)); | |
| 2808 | return; | |
| 2809 | } | |
| 2812 | 2810 | |
| 2813 | sort_direction = conn->request_info.query_string != NULL && | |
| 2814 | conn->request_info.query_string[1] == 'd' ? 'a' : 'd'; | |
| 2811 | sort_direction = conn->request_info.query_string != NULL && | |
| 2812 | conn->request_info.query_string[1] == 'd' ? 'a' : 'd'; | |
| 2815 | 2813 | |
| 2816 | conn->must_close = 1; | |
| 2817 | mg_printf(conn, "%s", | |
| 2818 | "HTTP/1.1 200 OK\r\n" | |
| 2819 | "Connection: close\r\n" | |
| 2820 | "Content-Type: text/html; charset=utf-8\r\n\r\n"); | |
| 2814 | conn->must_close = 1; | |
| 2815 | mg_printf(conn, "%s", | |
| 2816 | "HTTP/1.1 200 OK\r\n" | |
| 2817 | "Connection: close\r\n" | |
| 2818 | "Content-Type: text/html; charset=utf-8\r\n\r\n"); | |
| 2821 | 2819 | |
| 2822 | conn->num_bytes_sent += mg_printf(conn, | |
| 2823 | "<html><head><title>Index of %s</title>" | |
| 2824 | "<style>th {text-align: left;}</style></head>" | |
| 2825 | "<body><h1>Index of %s</h1><pre><table cellpadding=\"0\">" | |
| 2826 | "<tr><th><a href=\"?n%c\">Name</a></th>" | |
| 2827 | "<th><a href=\"?d%c\">Modified</a></th>" | |
| 2828 | "<th><a href=\"?s%c\">Size</a></th></tr>" | |
| 2829 | "<tr><td colspan=\"3\"><hr></td></tr>", | |
| 2830 | conn->request_info.uri, conn->request_info.uri, | |
| 2831 | sort_direction, sort_direction, sort_direction); | |
| 2820 | conn->num_bytes_sent += mg_printf(conn, | |
| 2821 | "<html><head><title>Index of %s</title>" | |
| 2822 | "<style>th {text-align: left;}</style></head>" | |
| 2823 | "<body><h1>Index of %s</h1><pre><table cellpadding=\"0\">" | |
| 2824 | "<tr><th><a href=\"?n%c\">Name</a></th>" | |
| 2825 | "<th><a href=\"?d%c\">Modified</a></th>" | |
| 2826 | "<th><a href=\"?s%c\">Size</a></th></tr>" | |
| 2827 | "<tr><td colspan=\"3\"><hr></td></tr>", | |
| 2828 | conn->request_info.uri, conn->request_info.uri, | |
| 2829 | sort_direction, sort_direction, sort_direction); | |
| 2832 | 2830 | |
| 2833 | // Print first entry - link to a parent directory | |
| 2834 | conn->num_bytes_sent += mg_printf(conn, | |
| 2835 | "<tr><td><a href=\"%s%s\">%s</a></td>" | |
| 2836 | "<td> %s</td><td> %s</td></tr>\n", | |
| 2837 | conn->request_info.uri, "..", "Parent directory", "-", "-"); | |
| 2831 | // Print first entry - link to a parent directory | |
| 2832 | conn->num_bytes_sent += mg_printf(conn, | |
| 2833 | "<tr><td><a href=\"%s%s\">%s</a></td>" | |
| 2834 | "<td> %s</td><td> %s</td></tr>\n", | |
| 2835 | conn->request_info.uri, "..", "Parent directory", "-", "-"); | |
| 2838 | 2836 | |
| 2839 | // Sort and print directory entries | |
| 2840 | qsort(data.entries, (size_t) data.num_entries, sizeof(data.entries[0]), | |
| 2841 | compare_dir_entries); | |
| 2842 | for (i = 0; i < data.num_entries; i++) { | |
| 2843 | print_dir_entry(&data.entries[i]); | |
| 2844 | free(data.entries[i].file_name); | |
| 2845 | } | |
| 2846 | free(data.entries); | |
| 2837 | // Sort and print directory entries | |
| 2838 | qsort(data.entries, (size_t) data.num_entries, sizeof(data.entries[0]), | |
| 2839 | compare_dir_entries); | |
| 2840 | for (i = 0; i < data.num_entries; i++) { | |
| 2841 | print_dir_entry(&data.entries[i]); | |
| 2842 | free(data.entries[i].file_name); | |
| 2843 | } | |
| 2844 | free(data.entries); | |
| 2847 | 2845 | |
| 2848 | conn->num_bytes_sent += mg_printf(conn, "%s", "</table></body></html>"); | |
| 2849 | conn->status_code = 200; | |
| 2846 | conn->num_bytes_sent += mg_printf(conn, "%s", "</table></body></html>"); | |
| 2847 | conn->status_code = 200; | |
| 2850 | 2848 | } |
| 2851 | 2849 | |
| 2852 | 2850 | // Send len bytes from the opened file to the client. |
| 2853 | 2851 | static void send_file_data(struct mg_connection *conn, struct file *filep, |
| 2854 | int64_t offset, int64_t len) { | |
| 2855 | char buf[MG_BUF_LEN]; | |
| 2856 | int to_read, num_read, num_written; | |
| 2852 | int64_t offset, int64_t len) { | |
| 2853 | char buf[MG_BUF_LEN]; | |
| 2854 | int to_read, num_read, num_written; | |
| 2857 | 2855 | |
| 2858 | // Sanity check the offset | |
| 2859 | offset = offset < 0 ? 0 : offset > filep->size ? filep->size : offset; | |
| 2856 | // Sanity check the offset | |
| 2857 | offset = offset < 0 ? 0 : offset > filep->size ? filep->size : offset; | |
| 2860 | 2858 | |
| 2861 | if (len > 0 && filep->membuf != NULL && filep->size > 0) { | |
| 2862 | if (len > filep->size - offset) { | |
| 2863 | len = filep->size - offset; | |
| 2864 | } | |
| 2865 | mg_write(conn, filep->membuf + offset, (size_t) len); | |
| 2866 | } else if (len > 0 && filep->fp != NULL) { | |
| 2867 | fseeko(filep->fp, offset, SEEK_SET); | |
| 2868 | while (len > 0) { | |
| 2869 | // Calculate how much to read from the file in the buffer | |
| 2870 | to_read = sizeof(buf); | |
| 2871 | if ((int64_t) to_read > len) { | |
| 2872 | to_read = (int) len; | |
| 2873 | } | |
| 2859 | if (len > 0 && filep->membuf != NULL && filep->size > 0) { | |
| 2860 | if (len > filep->size - offset) { | |
| 2861 | len = filep->size - offset; | |
| 2862 | } | |
| 2863 | mg_write(conn, filep->membuf + offset, (size_t) len); | |
| 2864 | } else if (len > 0 && filep->fp != NULL) { | |
| 2865 | fseeko(filep->fp, offset, SEEK_SET); | |
| 2866 | while (len > 0) { | |
| 2867 | // Calculate how much to read from the file in the buffer | |
| 2868 | to_read = sizeof(buf); | |
| 2869 | if ((int64_t) to_read > len) { | |
| 2870 | to_read = (int) len; | |
| 2871 | } | |
| 2874 | 2872 | |
| 2875 | // Read from file, exit the loop on error | |
| 2876 | if ((num_read = fread(buf, 1, (size_t) to_read, filep->fp)) <= 0) { | |
| 2877 | break; | |
| 2878 | } | |
| 2873 | // Read from file, exit the loop on error | |
| 2874 | if ((num_read = fread(buf, 1, (size_t) to_read, filep->fp)) <= 0) { | |
| 2875 | break; | |
| 2876 | } | |
| 2879 | 2877 | |
| 2880 | // Send read bytes to the client, exit the loop on error | |
| 2881 | if ((num_written = mg_write(conn, buf, (size_t) num_read)) != num_read) { | |
| 2882 | break; | |
| 2883 | } | |
| 2878 | // Send read bytes to the client, exit the loop on error | |
| 2879 | if ((num_written = mg_write(conn, buf, (size_t) num_read)) != num_read) { | |
| 2880 | break; | |
| 2881 | } | |
| 2884 | 2882 | |
| 2885 | // Both read and were successful, adjust counters | |
| 2886 | conn->num_bytes_sent += num_written; | |
| 2887 | len -= num_written; | |
| 2888 | } | |
| 2889 | } | |
| 2883 | // Both read and were successful, adjust counters | |
| 2884 | conn->num_bytes_sent += num_written; | |
| 2885 | len -= num_written; | |
| 2886 | } | |
| 2887 | } | |
| 2890 | 2888 | } |
| 2891 | 2889 | |
| 2892 | 2890 | static int parse_range_header(const char *header, int64_t *a, int64_t *b) { |
| 2893 | ||
| 2891 | return sscanf(header, "bytes=%" INT64_FMT "-%" INT64_FMT, a, b); | |
| 2894 | 2892 | } |
| 2895 | 2893 | |
| 2896 | 2894 | static void gmt_time_string(char *buf, size_t buf_len, time_t *t) { |
| 2897 | ||
| 2895 | strftime(buf, buf_len, "%a, %d %b %Y %H:%M:%S GMT", gmtime(t)); | |
| 2898 | 2896 | } |
| 2899 | 2897 | |
| 2900 | 2898 | static void construct_etag(char *buf, size_t buf_len, |
| 2901 | const struct file *filep) { | |
| 2902 | snprintf(buf, buf_len, "\"%lx.%" INT64_FMT "\"", | |
| 2903 | (unsigned long) filep->modification_time, filep->size); | |
| 2899 | const struct file *filep) { | |
| 2900 | snprintf(buf, buf_len, "\"%lx.%" INT64_FMT "\"", | |
| 2901 | (unsigned long) filep->modification_time, filep->size); | |
| 2904 | 2902 | } |
| 2905 | 2903 | |
| 2906 | 2904 | static void fclose_on_exec(struct file *filep) { |
| 2907 | ||
| 2905 | if (filep != NULL && filep->fp != NULL) { | |
| 2908 | 2906 | #ifndef _WIN32 |
| 2909 | ||
| 2907 | fcntl(fileno(filep->fp), F_SETFD, FD_CLOEXEC); | |
| 2910 | 2908 | #endif |
| 2911 | ||
| 2909 | } | |
| 2912 | 2910 | } |
| 2913 | 2911 | |
| 2914 | 2912 | static void handle_file_request(struct mg_connection *conn, const char *path, |
| 2915 | struct file *filep) { | |
| 2916 | char date[64], lm[64], etag[64], range[64]; | |
| 2917 | const char *msg = "OK", *hdr; | |
| 2918 | time_t curtime = time(NULL); | |
| 2919 | int64_t cl, r1, r2; | |
| 2920 | struct vec mime_vec; | |
| 2921 | int n; | |
| 2922 | char gz_path[PATH_MAX]; | |
| 2923 | char const* encoding = ""; | |
| 2913 | struct file *filep) { | |
| 2914 | char date[64], lm[64], etag[64], range[64]; | |
| 2915 | const char *msg = "OK", *hdr; | |
| 2916 | time_t curtime = time(NULL); | |
| 2917 | int64_t cl, r1, r2; | |
| 2918 | struct vec mime_vec; | |
| 2919 | int n; | |
| 2920 | char gz_path[PATH_MAX]; | |
| 2921 | char const* encoding = ""; | |
| 2924 | 2922 | |
| 2925 | get_mime_type(conn->ctx, path, &mime_vec); | |
| 2926 | cl = filep->size; | |
| 2927 | conn->status_code = 200; | |
| 2928 | range[0] = '\0'; | |
| 2923 | get_mime_type(conn->ctx, path, &mime_vec); | |
| 2924 | cl = filep->size; | |
| 2925 | conn->status_code = 200; | |
| 2926 | range[0] = '\0'; | |
| 2929 | 2927 | |
| 2930 | // if this file is in fact a pre-gzipped file, rewrite its filename | |
| 2931 | // it's important to rewrite the filename after resolving | |
| 2932 | // the mime type from it, to preserve the actual file's type | |
| 2933 | if (filep->gzipped) { | |
| 2934 | snprintf(gz_path, sizeof(gz_path), "%s.gz", path); | |
| 2935 | path = gz_path; | |
| 2936 | encoding = "Content-Encoding: gzip\r\n"; | |
| 2937 | } | |
| 2928 | // if this file is in fact a pre-gzipped file, rewrite its filename | |
| 2929 | // it's important to rewrite the filename after resolving | |
| 2930 | // the mime type from it, to preserve the actual file's type | |
| 2931 | if (filep->gzipped) { | |
| 2932 | snprintf(gz_path, sizeof(gz_path), "%s.gz", path); | |
| 2933 | path = gz_path; | |
| 2934 | encoding = "Content-Encoding: gzip\r\n"; | |
| 2935 | } | |
| 2938 | 2936 | |
| 2939 | if (!mg_fopen(conn, path, "rb", filep)) { | |
| 2940 | send_http_error(conn, 500, http_500_error, | |
| 2941 | "fopen(%s): %s", path, strerror(ERRNO)); | |
| 2942 | return; | |
| 2943 | } | |
| 2937 | if (!mg_fopen(conn, path, "rb", filep)) { | |
| 2938 | send_http_error(conn, 500, http_500_error, | |
| 2939 | "fopen(%s): %s", path, strerror(ERRNO)); | |
| 2940 | return; | |
| 2941 | } | |
| 2944 | 2942 | |
| 2945 | ||
| 2943 | fclose_on_exec(filep); | |
| 2946 | 2944 | |
| 2947 | // If Range: header specified, act accordingly | |
| 2948 | r1 = r2 = 0; | |
| 2949 | hdr = mg_get_header(conn, "Range"); | |
| 2950 | if (hdr != NULL && (n = parse_range_header(hdr, &r1, &r2)) > 0 && | |
| 2951 | r1 >= 0 && r2 >= 0) { | |
| 2952 | // actually, range requests don't play well with a pre-gzipped | |
| 2953 | // file (since the range is specified in the uncmpressed space) | |
| 2954 | if (filep->gzipped) { | |
| 2955 | send_http_error(conn, 501, "Not Implemented", "range requests in gzipped files are not supported"); | |
| 2956 | return; | |
| 2957 | } | |
| 2958 | conn->status_code = 206; | |
| 2959 | cl = n == 2 ? (r2 > cl ? cl : r2) - r1 + 1: cl - r1; | |
| 2960 | mg_snprintf(conn, range, sizeof(range), | |
| 2961 | "Content-Range: bytes " | |
| 2962 | "%" INT64_FMT "-%" | |
| 2963 | INT64_FMT "/%" INT64_FMT "\r\n", | |
| 2964 | r1, r1 + cl - 1, filep->size); | |
| 2965 | msg = "Partial Content"; | |
| 2966 | } | |
| 2945 | // If Range: header specified, act accordingly | |
| 2946 | r1 = r2 = 0; | |
| 2947 | hdr = mg_get_header(conn, "Range"); | |
| 2948 | if (hdr != NULL && (n = parse_range_header(hdr, &r1, &r2)) > 0 && | |
| 2949 | r1 >= 0 && r2 >= 0) { | |
| 2950 | // actually, range requests don't play well with a pre-gzipped | |
| 2951 | // file (since the range is specified in the uncmpressed space) | |
| 2952 | if (filep->gzipped) { | |
| 2953 | send_http_error(conn, 501, "Not Implemented", "range requests in gzipped files are not supported"); | |
| 2954 | return; | |
| 2955 | } | |
| 2956 | conn->status_code = 206; | |
| 2957 | cl = n == 2 ? (r2 > cl ? cl : r2) - r1 + 1: cl - r1; | |
| 2958 | mg_snprintf(conn, range, sizeof(range), | |
| 2959 | "Content-Range: bytes " | |
| 2960 | "%" INT64_FMT "-%" | |
| 2961 | INT64_FMT "/%" INT64_FMT "\r\n", | |
| 2962 | r1, r1 + cl - 1, filep->size); | |
| 2963 | msg = "Partial Content"; | |
| 2964 | } | |
| 2967 | 2965 | |
| 2968 | // Prepare Etag, Date, Last-Modified headers. Must be in UTC, according to | |
| 2969 | // http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3 | |
| 2970 | gmt_time_string(date, sizeof(date), &curtime); | |
| 2971 | gmt_time_string(lm, sizeof(lm), &filep->modification_time); | |
| 2972 | construct_etag(etag, sizeof(etag), filep); | |
| 2966 | // Prepare Etag, Date, Last-Modified headers. Must be in UTC, according to | |
| 2967 | // http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3 | |
| 2968 | gmt_time_string(date, sizeof(date), &curtime); | |
| 2969 | gmt_time_string(lm, sizeof(lm), &filep->modification_time); | |
| 2970 | construct_etag(etag, sizeof(etag), filep); | |
| 2973 | 2971 | |
| 2974 | (void) mg_printf(conn, | |
| 2975 | "HTTP/1.1 %d %s\r\n" | |
| 2976 | "Date: %s\r\n" | |
| 2977 | "Last-Modified: %s\r\n" | |
| 2978 | "Etag: %s\r\n" | |
| 2979 | "Content-Type: %.*s\r\n" | |
| 2980 | "Content-Length: %" INT64_FMT "\r\n" | |
| 2981 | "Connection: %s\r\n" | |
| 2982 | "Accept-Ranges: bytes\r\n" | |
| 2983 | "%s%s\r\n", | |
| 2984 | conn->status_code, msg, date, lm, etag, (int) mime_vec.len, | |
| 2985 | mime_vec.ptr, cl, suggest_connection_header(conn), range, encoding); | |
| 2972 | (void) mg_printf(conn, | |
| 2973 | "HTTP/1.1 %d %s\r\n" | |
| 2974 | "Date: %s\r\n" | |
| 2975 | "Last-Modified: %s\r\n" | |
| 2976 | "Etag: %s\r\n" | |
| 2977 | "Content-Type: %.*s\r\n" | |
| 2978 | "Content-Length: %" INT64_FMT "\r\n" | |
| 2979 | "Connection: %s\r\n" | |
| 2980 | "Accept-Ranges: bytes\r\n" | |
| 2981 | "%s%s\r\n", | |
| 2982 | conn->status_code, msg, date, lm, etag, (int) mime_vec.len, | |
| 2983 | mime_vec.ptr, cl, suggest_connection_header(conn), range, encoding); | |
| 2986 | 2984 | |
| 2987 | if (strcmp(conn->request_info.request_method, "HEAD") != 0) { | |
| 2988 | send_file_data(conn, filep, r1, cl); | |
| 2989 | } | |
| 2990 | mg_fclose(filep); | |
| 2985 | if (strcmp(conn->request_info.request_method, "HEAD") != 0) { | |
| 2986 | send_file_data(conn, filep, r1, cl); | |
| 2987 | } | |
| 2988 | mg_fclose(filep); | |
| 2991 | 2989 | } |
| 2992 | 2990 | |
| 2993 | 2991 | void mg_send_file(struct mg_connection *conn, const char *path) { |
| 2994 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 2995 | if (mg_stat(conn, path, &file)) { | |
| 2996 | handle_file_request(conn, path, &file); | |
| 2997 | } else { | |
| 2998 | send_http_error(conn, 404, "Not Found", "%s", "File not found"); | |
| 2999 | } | |
| 2992 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 2993 | if (mg_stat(conn, path, &file)) { | |
| 2994 | handle_file_request(conn, path, &file); | |
| 2995 | } else { | |
| 2996 | send_http_error(conn, 404, "Not Found", "%s", "File not found"); | |
| 2997 | } | |
| 3000 | 2998 | } |
| 3001 | 2999 | |
| 3002 | 3000 | |
| 3003 | 3001 | // Parse HTTP headers from the given buffer, advance buffer to the point |
| 3004 | 3002 | // where parsing stopped. |
| 3005 | 3003 | static void parse_http_headers(char **buf, struct mg_request_info *ri) { |
| 3006 | ||
| 3004 | int i; | |
| 3007 | 3005 | |
| 3008 | for (i = 0; i < (int) ARRAY_SIZE(ri->http_headers); i++) { | |
| 3009 | ri->http_headers[i].name = skip_quoted(buf, ":", " ", 0); | |
| 3010 | ri->http_headers[i].value = skip(buf, "\r\n"); | |
| 3011 | if (ri->http_headers[i].name[0] == '\0') | |
| 3012 | break; | |
| 3013 | ri->num_headers = i + 1; | |
| 3014 | } | |
| 3006 | for (i = 0; i < (int) ARRAY_SIZE(ri->http_headers); i++) { | |
| 3007 | ri->http_headers[i].name = skip_quoted(buf, ":", " ", 0); | |
| 3008 | ri->http_headers[i].value = skip(buf, "\r\n"); | |
| 3009 | if (ri->http_headers[i].name[0] == '\0') | |
| 3010 | break; | |
| 3011 | ri->num_headers = i + 1; | |
| 3012 | } | |
| 3015 | 3013 | } |
| 3016 | 3014 | |
| 3017 | 3015 | static int is_valid_http_method(const char *method) { |
| 3018 | return !strcmp(method, "GET") || !strcmp(method, "POST") || | |
| 3019 | !strcmp(method, "HEAD") || !strcmp(method, "CONNECT") || | |
| 3020 | !strcmp(method, "PUT") || !strcmp(method, "DELETE") || | |
| 3021 | !strcmp(method, "OPTIONS") || !strcmp(method, "PROPFIND") | |
| 3022 | || !strcmp(method, "MKCOL") | |
| 3023 | ; | |
| 3016 | return !strcmp(method, "GET") || !strcmp(method, "POST") || | |
| 3017 | !strcmp(method, "HEAD") || !strcmp(method, "CONNECT") || | |
| 3018 | !strcmp(method, "PUT") || !strcmp(method, "DELETE") || | |
| 3019 | !strcmp(method, "OPTIONS") || !strcmp(method, "PROPFIND") | |
| 3020 | || !strcmp(method, "MKCOL") | |
| 3021 | ; | |
| 3024 | 3022 | } |
| 3025 | 3023 | |
| 3026 | 3024 | // Parse HTTP request, fill in mg_request_info structure. |
| 3027 | 3025 | // This function modifies the buffer by NUL-terminating |
| 3028 | 3026 | // HTTP request components, header names and header values. |
| 3029 | 3027 | static int parse_http_message(char *buf, int len, struct mg_request_info *ri) { |
| 3030 | int is_request, request_length = get_request_len(buf, len); | |
| 3031 | if (request_length > 0) { | |
| 3032 | // Reset attributes. DO NOT TOUCH is_ssl, remote_ip, remote_port | |
| 3033 | ri->remote_user = ri->request_method = ri->uri = ri->http_version = NULL; | |
| 3034 | ri->num_headers = 0; | |
| 3028 | int is_request, request_length = get_request_len(buf, len); | |
| 3029 | if (request_length > 0) { | |
| 3030 | // Reset attributes. DO NOT TOUCH is_ssl, remote_ip, remote_port | |
| 3031 | ri->remote_user = ri->request_method = ri->uri = ri->http_version = NULL; | |
| 3032 | ri->num_headers = 0; | |
| 3035 | 3033 | |
| 3036 | ||
| 3034 | buf[request_length - 1] = '\0'; | |
| 3037 | 3035 | |
| 3038 | // RFC says that all initial whitespaces should be ingored | |
| 3039 | while (*buf != '\0' && isspace(* (unsigned char *) buf)) { | |
| 3040 | buf++; | |
| 3041 | } | |
| 3042 | ri->request_method = skip(&buf, " "); | |
| 3043 | ri->uri = skip(&buf, " "); | |
| 3044 | ri->http_version = skip(&buf, "\r\n"); | |
| 3045 | if (((is_request = is_valid_http_method(ri->request_method)) && | |
| 3046 | memcmp(ri->http_version, "HTTP/", 5) != 0) || | |
| 3047 | (!is_request && memcmp(ri->request_method, "HTTP/", 5)) != 0) { | |
| 3048 | request_length = -1; | |
| 3049 | } else { | |
| 3050 | if (is_request) { | |
| 3051 | ri->http_version += 5; | |
| 3052 | } | |
| 3053 | parse_http_headers(&buf, ri); | |
| 3054 | } | |
| 3055 | } | |
| 3056 | return request_length; | |
| 3036 | // RFC says that all initial whitespaces should be ingored | |
| 3037 | while (*buf != '\0' && isspace(* (unsigned char *) buf)) { | |
| 3038 | buf++; | |
| 3039 | } | |
| 3040 | ri->request_method = skip(&buf, " "); | |
| 3041 | ri->uri = skip(&buf, " "); | |
| 3042 | ri->http_version = skip(&buf, "\r\n"); | |
| 3043 | if (((is_request = is_valid_http_method(ri->request_method)) && | |
| 3044 | memcmp(ri->http_version, "HTTP/", 5) != 0) || | |
| 3045 | (!is_request && memcmp(ri->request_method, "HTTP/", 5)) != 0) { | |
| 3046 | request_length = -1; | |
| 3047 | } else { | |
| 3048 | if (is_request) { | |
| 3049 | ri->http_version += 5; | |
| 3050 | } | |
| 3051 | parse_http_headers(&buf, ri); | |
| 3052 | } | |
| 3053 | } | |
| 3054 | return request_length; | |
| 3057 | 3055 | } |
| 3058 | 3056 | |
| 3059 | 3057 | // Keep reading the input (either opened file descriptor fd, or socket sock, |
| r25360 | r25361 | |
| 3062 | 3060 | // have some data. The length of the data is stored in nread. |
| 3063 | 3061 | // Upon every read operation, increase nread by the number of bytes read. |
| 3064 | 3062 | static int read_request(FILE *fp, struct mg_connection *conn, |
| 3065 | char *buf, int bufsiz, int *nread) { | |
| 3066 | int request_len, n = 0; | |
| 3063 | char *buf, int bufsiz, int *nread) { | |
| 3064 | int request_len, n = 0; | |
| 3067 | 3065 | |
| 3068 | request_len = get_request_len(buf, *nread); | |
| 3069 | while (*nread < bufsiz && request_len == 0 && | |
| 3070 | (n = pull(fp, conn, buf + *nread, bufsiz - *nread)) > 0) { | |
| 3071 | *nread += n; | |
| 3072 | assert(*nread <= bufsiz); | |
| 3073 | request_len = get_request_len(buf, *nread); | |
| 3074 | } | |
| 3066 | request_len = get_request_len(buf, *nread); | |
| 3067 | while (*nread < bufsiz && request_len == 0 && | |
| 3068 | (n = pull(fp, conn, buf + *nread, bufsiz - *nread)) > 0) { | |
| 3069 | *nread += n; | |
| 3070 | assert(*nread <= bufsiz); | |
| 3071 | request_len = get_request_len(buf, *nread); | |
| 3072 | } | |
| 3075 | 3073 | |
| 3076 | ||
| 3074 | return request_len <= 0 && n <= 0 ? -1 : request_len; | |
| 3077 | 3075 | } |
| 3078 | 3076 | |
| 3079 | 3077 | // For given directory path, substitute it to valid index file. |
| 3080 | 3078 | // Return 0 if index file has been found, -1 if not found. |
| 3081 | 3079 | // If the file is found, it's stats is returned in stp. |
| 3082 | 3080 | static int substitute_index_file(struct mg_connection *conn, char *path, |
| 3083 | size_t path_len, struct file *filep) { | |
| 3084 | const char *list = conn->ctx->config[INDEX_FILES]; | |
| 3085 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 3086 | struct vec filename_vec; | |
| 3087 | size_t n = strlen(path); | |
| 3088 | int found = 0; | |
| 3081 | size_t path_len, struct file *filep) { | |
| 3082 | const char *list = conn->ctx->config[INDEX_FILES]; | |
| 3083 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 3084 | struct vec filename_vec; | |
| 3085 | size_t n = strlen(path); | |
| 3086 | int found = 0; | |
| 3089 | 3087 | |
| 3090 | // The 'path' given to us points to the directory. Remove all trailing | |
| 3091 | // directory separator characters from the end of the path, and | |
| 3092 | // then append single directory separator character. | |
| 3093 | while (n > 0 && path[n - 1] == '/') { | |
| 3094 | n--; | |
| 3095 | } | |
| 3096 | path[n] = '/'; | |
| 3088 | // The 'path' given to us points to the directory. Remove all trailing | |
| 3089 | // directory separator characters from the end of the path, and | |
| 3090 | // then append single directory separator character. | |
| 3091 | while (n > 0 && path[n - 1] == '/') { | |
| 3092 | n--; | |
| 3093 | } | |
| 3094 | path[n] = '/'; | |
| 3097 | 3095 | |
| 3098 | // Traverse index files list. For each entry, append it to the given | |
| 3099 | // path and see if the file exists. If it exists, break the loop | |
| 3100 | while ((list = next_option(list, &filename_vec, NULL)) != NULL) { | |
| 3096 | // Traverse index files list. For each entry, append it to the given | |
| 3097 | // path and see if the file exists. If it exists, break the loop | |
| 3098 | while ((list = next_option(list, &filename_vec, NULL)) != NULL) { | |
| 3099 | // Ignore too long entries that may overflow path buffer | |
| 3100 | if (filename_vec.len > path_len - (n + 2)) | |
| 3101 | continue; | |
| 3101 | 3102 | |
| 3102 | // Ignore too long entries that may overflow path buffer | |
| 3103 | if (filename_vec.len > path_len - (n + 2)) | |
| 3104 | continue; | |
| 3103 | // Prepare full path to the index file | |
| 3104 | mg_strlcpy(path + n + 1, filename_vec.ptr, filename_vec.len + 1); | |
| 3105 | 3105 | |
| 3106 | // Prepare full path to the index file | |
| 3107 | mg_strlcpy(path + n + 1, filename_vec.ptr, filename_vec.len + 1); | |
| 3106 | // Does it exist? | |
| 3107 | if (mg_stat(conn, path, &file)) { | |
| 3108 | // Yes it does, break the loop | |
| 3109 | *filep = file; | |
| 3110 | found = 1; | |
| 3111 | break; | |
| 3112 | } | |
| 3113 | } | |
| 3108 | 3114 | |
| 3109 | // Does it exist? | |
| 3110 | if (mg_stat(conn, path, &file)) { | |
| 3111 | // Yes it does, break the loop | |
| 3112 | *filep = file; | |
| 3113 | found = 1; | |
| 3114 | break; | |
| 3115 | } | |
| 3116 | } | |
| 3115 | // If no index file exists, restore directory path | |
| 3116 | if (!found) { | |
| 3117 | path[n] = '\0'; | |
| 3118 | } | |
| 3117 | 3119 | |
| 3118 | // If no index file exists, restore directory path | |
| 3119 | if (!found) { | |
| 3120 | path[n] = '\0'; | |
| 3121 | } | |
| 3122 | ||
| 3123 | return found; | |
| 3120 | return found; | |
| 3124 | 3121 | } |
| 3125 | 3122 | |
| 3126 | 3123 | // Return True if we should reply 304 Not Modified. |
| 3127 | 3124 | static int is_not_modified(const struct mg_connection *conn, |
| 3128 | const struct file *filep) { | |
| 3129 | char etag[64]; | |
| 3130 | const char *ims = mg_get_header(conn, "If-Modified-Since"); | |
| 3131 | const char *inm = mg_get_header(conn, "If-None-Match"); | |
| 3132 | construct_etag(etag, sizeof(etag), filep); | |
| 3133 | return (inm != NULL && !mg_strcasecmp(etag, inm)) || | |
| 3134 | (ims != NULL && filep->modification_time <= parse_date_string(ims)); | |
| 3125 | const struct file *filep) { | |
| 3126 | char etag[64]; | |
| 3127 | const char *ims = mg_get_header(conn, "If-Modified-Since"); | |
| 3128 | const char *inm = mg_get_header(conn, "If-None-Match"); | |
| 3129 | construct_etag(etag, sizeof(etag), filep); | |
| 3130 | return (inm != NULL && !mg_strcasecmp(etag, inm)) || | |
| 3131 | (ims != NULL && filep->modification_time <= parse_date_string(ims)); | |
| 3135 | 3132 | } |
| 3136 | 3133 | |
| 3137 | 3134 | static int forward_body_data(struct mg_connection *conn, FILE *fp, |
| 3138 | SOCKET sock, SSL *ssl) { | |
| 3139 | const char *expect, *body; | |
| 3140 | char buf[MG_BUF_LEN]; | |
| 3141 | int to_read, nread, buffered_len, success = 0; | |
| 3135 | SOCKET sock, SSL *ssl) { | |
| 3136 | const char *expect, *body; | |
| 3137 | char buf[MG_BUF_LEN]; | |
| 3138 | int to_read, nread, buffered_len, success = 0; | |
| 3142 | 3139 | |
| 3143 | expect = mg_get_header(conn, "Expect"); | |
| 3144 | assert(fp != NULL); | |
| 3140 | expect = mg_get_header(conn, "Expect"); | |
| 3141 | assert(fp != NULL); | |
| 3145 | 3142 | |
| 3146 | if (conn->content_len == -1) { | |
| 3147 | send_http_error(conn, 411, "Length Required", "%s", ""); | |
| 3148 | } else if (expect != NULL && mg_strcasecmp(expect, "100-continue")) { | |
| 3149 | send_http_error(conn, 417, "Expectation Failed", "%s", ""); | |
| 3150 | } else { | |
| 3151 | if (expect != NULL) { | |
| 3152 | (void) mg_printf(conn, "%s", "HTTP/1.1 100 Continue\r\n\r\n"); | |
| 3153 | } | |
| 3143 | if (conn->content_len == -1) { | |
| 3144 | send_http_error(conn, 411, "Length Required", "%s", ""); | |
| 3145 | } else if (expect != NULL && mg_strcasecmp(expect, "100-continue")) { | |
| 3146 | send_http_error(conn, 417, "Expectation Failed", "%s", ""); | |
| 3147 | } else { | |
| 3148 | if (expect != NULL) { | |
| 3149 | (void) mg_printf(conn, "%s", "HTTP/1.1 100 Continue\r\n\r\n"); | |
| 3150 | } | |
| 3154 | 3151 | |
| 3155 | body = conn->buf + conn->request_len + conn->consumed_content; | |
| 3156 | buffered_len = &conn->buf[conn->data_len] - body; | |
| 3157 | assert(buffered_len >= 0); | |
| 3158 | assert(conn->consumed_content == 0); | |
| 3152 | body = conn->buf + conn->request_len + conn->consumed_content; | |
| 3153 | buffered_len = &conn->buf[conn->data_len] - body; | |
| 3154 | assert(buffered_len >= 0); | |
| 3155 | assert(conn->consumed_content == 0); | |
| 3159 | 3156 | |
| 3160 | if (buffered_len > 0) { | |
| 3161 | if ((int64_t) buffered_len > conn->content_len) { | |
| 3162 | buffered_len = (int) conn->content_len; | |
| 3163 | } | |
| 3164 | push(fp, sock, ssl, body, (int64_t) buffered_len); | |
| 3165 | conn->consumed_content += buffered_len; | |
| 3166 | } | |
| 3157 | if (buffered_len > 0) { | |
| 3158 | if ((int64_t) buffered_len > conn->content_len) { | |
| 3159 | buffered_len = (int) conn->content_len; | |
| 3160 | } | |
| 3161 | push(fp, sock, ssl, body, (int64_t) buffered_len); | |
| 3162 | conn->consumed_content += buffered_len; | |
| 3163 | } | |
| 3167 | 3164 | |
| 3168 | nread = 0; | |
| 3169 | while (conn->consumed_content < conn->content_len) { | |
| 3170 | to_read = sizeof(buf); | |
| 3171 | if ((int64_t) to_read > conn->content_len - conn->consumed_content) { | |
| 3172 | to_read = (int) (conn->content_len - conn->consumed_content); | |
| 3173 | } | |
| 3174 | nread = pull(NULL, conn, buf, to_read); | |
| 3175 | if (nread <= 0 || push(fp, sock, ssl, buf, nread) != nread) { | |
| 3176 | break; | |
| 3177 | } | |
| 3178 | conn->consumed_content += nread; | |
| 3179 | } | |
| 3165 | nread = 0; | |
| 3166 | while (conn->consumed_content < conn->content_len) { | |
| 3167 | to_read = sizeof(buf); | |
| 3168 | if ((int64_t) to_read > conn->content_len - conn->consumed_content) { | |
| 3169 | to_read = (int) (conn->content_len - conn->consumed_content); | |
| 3170 | } | |
| 3171 | nread = pull(NULL, conn, buf, to_read); | |
| 3172 | if (nread <= 0 || push(fp, sock, ssl, buf, nread) != nread) { | |
| 3173 | break; | |
| 3174 | } | |
| 3175 | conn->consumed_content += nread; | |
| 3176 | } | |
| 3180 | 3177 | |
| 3181 | if (conn->consumed_content == conn->content_len) { | |
| 3182 | success = nread >= 0; | |
| 3183 | } | |
| 3178 | if (conn->consumed_content == conn->content_len) { | |
| 3179 | success = nread >= 0; | |
| 3180 | } | |
| 3184 | 3181 | |
| 3185 | // Each error code path in this function must send an error | |
| 3186 | if (!success) { | |
| 3187 | send_http_error(conn, 577, http_500_error, "%s", ""); | |
| 3188 | } | |
| 3189 | } | |
| 3182 | // Each error code path in this function must send an error | |
| 3183 | if (!success) { | |
| 3184 | send_http_error(conn, 577, http_500_error, "%s", ""); | |
| 3185 | } | |
| 3186 | } | |
| 3190 | 3187 | |
| 3191 | ||
| 3188 | return success; | |
| 3192 | 3189 | } |
| 3193 | 3190 | |
| 3194 | 3191 | #if !defined(NO_CGI) |
| r25360 | r25361 | |
| 3201 | 3198 | // We satisfy both worlds: we create an envp array (which is vars), all |
| 3202 | 3199 | // entries are actually pointers inside buf. |
| 3203 | 3200 | struct cgi_env_block { |
| 3204 | struct mg_connection *conn; | |
| 3205 | char buf[CGI_ENVIRONMENT_SIZE]; // Environment buffer | |
| 3206 | int len; // Space taken | |
| 3207 | char *vars[MAX_CGI_ENVIR_VARS]; // char **envp | |
| 3208 | int nvars; // Number of variables | |
| 3201 | struct mg_connection *conn; | |
| 3202 | char buf[CGI_ENVIRONMENT_SIZE]; // Environment buffer | |
| 3203 | int len; // Space taken | |
| 3204 | char *vars[MAX_CGI_ENVIR_VARS]; // char **envp | |
| 3205 | int nvars; // Number of variables | |
| 3209 | 3206 | }; |
| 3210 | 3207 | |
| 3211 | 3208 | static char *addenv(struct cgi_env_block *block, |
| 3212 | PRINTF_FORMAT_STRING(const char *fmt), ...) | |
| 3213 | PRINTF_ARGS(2, 3); | |
| 3209 | PRINTF_FORMAT_STRING(const char *fmt), ...) | |
| 3210 | PRINTF_ARGS(2, 3); | |
| 3214 | 3211 | |
| 3215 | 3212 | // Append VARIABLE=VALUE\0 string to the buffer, and add a respective |
| 3216 | 3213 | // pointer into the vars array. |
| 3217 | 3214 | static char *addenv(struct cgi_env_block *block, const char *fmt, ...) { |
| 3218 | int n, space; | |
| 3219 | char *added; | |
| 3220 | va_list ap; | |
| 3215 | int n, space; | |
| 3216 | char *added; | |
| 3217 | va_list ap; | |
| 3221 | 3218 | |
| 3222 | // Calculate how much space is left in the buffer | |
| 3223 | space = sizeof(block->buf) - block->len - 2; | |
| 3224 | assert(space >= 0); | |
| 3219 | // Calculate how much space is left in the buffer | |
| 3220 | space = sizeof(block->buf) - block->len - 2; | |
| 3221 | assert(space >= 0); | |
| 3225 | 3222 | |
| 3226 | // Make a pointer to the free space int the buffer | |
| 3227 | added = block->buf + block->len; | |
| 3223 | // Make a pointer to the free space int the buffer | |
| 3224 | added = block->buf + block->len; | |
| 3228 | 3225 | |
| 3229 | // Copy VARIABLE=VALUE\0 string into the free space | |
| 3230 | va_start(ap, fmt); | |
| 3231 | n = mg_vsnprintf(block->conn, added, (size_t) space, fmt, ap); | |
| 3232 | va_end(ap); | |
| 3226 | // Copy VARIABLE=VALUE\0 string into the free space | |
| 3227 | va_start(ap, fmt); | |
| 3228 | n = mg_vsnprintf(block->conn, added, (size_t) space, fmt, ap); | |
| 3229 | va_end(ap); | |
| 3233 | 3230 | |
| 3234 | // Make sure we do not overflow buffer and the envp array | |
| 3235 | if (n > 0 && n + 1 < space && | |
| 3236 | block->nvars < (int) ARRAY_SIZE(block->vars) - 2) { | |
| 3237 | // Append a pointer to the added string into the envp array | |
| 3238 | block->vars[block->nvars++] = added; | |
| 3239 | // Bump up used length counter. Include \0 terminator | |
| 3240 | block->len += n + 1; | |
| 3241 | } else { | |
| 3242 | cry(block->conn, "%s: CGI env buffer truncated for [%s]", __func__, fmt); | |
| 3243 | } | |
| 3231 | // Make sure we do not overflow buffer and the envp array | |
| 3232 | if (n > 0 && n + 1 < space && | |
| 3233 | block->nvars < (int) ARRAY_SIZE(block->vars) - 2) { | |
| 3234 | // Append a pointer to the added string into the envp array | |
| 3235 | block->vars[block->nvars++] = added; | |
| 3236 | // Bump up used length counter. Include \0 terminator | |
| 3237 | block->len += n + 1; | |
| 3238 | } else { | |
| 3239 | cry(block->conn, "%s: CGI env buffer truncated for [%s]", __func__, fmt); | |
| 3240 | } | |
| 3244 | 3241 | |
| 3245 | ||
| 3242 | return added; | |
| 3246 | 3243 | } |
| 3247 | 3244 | |
| 3248 | 3245 | static void prepare_cgi_environment(struct mg_connection *conn, |
| 3249 | const char *prog, | |
| 3250 | struct cgi_env_block *blk) { | |
| 3251 | const char *s, *slash; | |
| 3252 | struct vec var_vec; | |
| 3253 | char *p, src_addr[IP_ADDR_STR_LEN]; | |
| 3254 | int i; | |
| 3246 | const char *prog, | |
| 3247 | struct cgi_env_block *blk) { | |
| 3248 | const char *s, *slash; | |
| 3249 | struct vec var_vec; | |
| 3250 | char *p, src_addr[IP_ADDR_STR_LEN]; | |
| 3251 | int i; | |
| 3255 | 3252 | |
| 3256 | blk->len = blk->nvars = 0; | |
| 3257 | blk->conn = conn; | |
| 3258 | sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa); | |
| 3253 | blk->len = blk->nvars = 0; | |
| 3254 | blk->conn = conn; | |
| 3255 | sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa); | |
| 3259 | 3256 | |
| 3260 | addenv(blk, "SERVER_NAME=%s", conn->ctx->config[AUTHENTICATION_DOMAIN]); | |
| 3261 | addenv(blk, "SERVER_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT]); | |
| 3262 | addenv(blk, "DOCUMENT_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT]); | |
| 3257 | addenv(blk, "SERVER_NAME=%s", conn->ctx->config[AUTHENTICATION_DOMAIN]); | |
| 3258 | addenv(blk, "SERVER_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT]); | |
| 3259 | addenv(blk, "DOCUMENT_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT]); | |
| 3263 | 3260 | |
| 3264 | // Prepare the environment block | |
| 3265 | addenv(blk, "%s", "GATEWAY_INTERFACE=CGI/1.1"); | |
| 3266 | addenv(blk, "%s", "SERVER_PROTOCOL=HTTP/1.1"); | |
| 3267 | addenv(blk, "%s", "REDIRECT_STATUS=200"); // For PHP | |
| 3261 | // Prepare the environment block | |
| 3262 | addenv(blk, "%s", "GATEWAY_INTERFACE=CGI/1.1"); | |
| 3263 | addenv(blk, "%s", "SERVER_PROTOCOL=HTTP/1.1"); | |
| 3264 | addenv(blk, "%s", "REDIRECT_STATUS=200"); // For PHP | |
| 3268 | 3265 | |
| 3269 | // TODO(lsm): fix this for IPv6 case | |
| 3270 | addenv(blk, "SERVER_PORT=%d", ntohs(conn->client.lsa.sin.sin_port)); | |
| 3266 | // TODO(lsm): fix this for IPv6 case | |
| 3267 | addenv(blk, "SERVER_PORT=%d", ntohs(conn->client.lsa.sin.sin_port)); | |
| 3271 | 3268 | |
| 3272 | addenv(blk, "REQUEST_METHOD=%s", conn->request_info.request_method); | |
| 3273 | addenv(blk, "REMOTE_ADDR=%s", src_addr); | |
| 3274 | addenv(blk, "REMOTE_PORT=%d", conn->request_info.remote_port); | |
| 3275 | addenv(blk, "REQUEST_URI=%s", conn->request_info.uri); | |
| 3269 | addenv(blk, "REQUEST_METHOD=%s", conn->request_info.request_method); | |
| 3270 | addenv(blk, "REMOTE_ADDR=%s", src_addr); | |
| 3271 | addenv(blk, "REMOTE_PORT=%d", conn->request_info.remote_port); | |
| 3272 | addenv(blk, "REQUEST_URI=%s", conn->request_info.uri); | |
| 3276 | 3273 | |
| 3277 | // SCRIPT_NAME | |
| 3278 | assert(conn->request_info.uri[0] == '/'); | |
| 3279 | slash = strrchr(conn->request_info.uri, '/'); | |
| 3280 | if ((s = strrchr(prog, '/')) == NULL) | |
| 3281 | s = prog; | |
| 3282 | addenv(blk, "SCRIPT_NAME=%.*s%s", (int) (slash - conn->request_info.uri), | |
| 3283 | conn->request_info.uri, s); | |
| 3274 | // SCRIPT_NAME | |
| 3275 | assert(conn->request_info.uri[0] == '/'); | |
| 3276 | slash = strrchr(conn->request_info.uri, '/'); | |
| 3277 | if ((s = strrchr(prog, '/')) == NULL) | |
| 3278 | s = prog; | |
| 3279 | addenv(blk, "SCRIPT_NAME=%.*s%s", (int) (slash - conn->request_info.uri), | |
| 3280 | conn->request_info.uri, s); | |
| 3284 | 3281 | |
| 3285 | addenv(blk, "SCRIPT_FILENAME=%s", prog); | |
| 3286 | addenv(blk, "PATH_TRANSLATED=%s", prog); | |
| 3287 | addenv(blk, "HTTPS=%s", conn->ssl == NULL ? "off" : "on"); | |
| 3282 | addenv(blk, "SCRIPT_FILENAME=%s", prog); | |
| 3283 | addenv(blk, "PATH_TRANSLATED=%s", prog); | |
| 3284 | addenv(blk, "HTTPS=%s", conn->ssl == NULL ? "off" : "on"); | |
| 3288 | 3285 | |
| 3289 | if ((s = mg_get_header(conn, "Content-Type")) != NULL) | |
| 3290 | addenv(blk, "CONTENT_TYPE=%s", s); | |
| 3286 | if ((s = mg_get_header(conn, "Content-Type")) != NULL) | |
| 3287 | addenv(blk, "CONTENT_TYPE=%s", s); | |
| 3291 | 3288 | |
| 3292 | if (conn->request_info.query_string != NULL) | |
| 3293 | addenv(blk, "QUERY_STRING=%s", conn->request_info.query_string); | |
| 3289 | if (conn->request_info.query_string != NULL) | |
| 3290 | addenv(blk, "QUERY_STRING=%s", conn->request_info.query_string); | |
| 3294 | 3291 | |
| 3295 | if ((s = mg_get_header(conn, "Content-Length")) != NULL) | |
| 3296 | addenv(blk, "CONTENT_LENGTH=%s", s); | |
| 3292 | if ((s = mg_get_header(conn, "Content-Length")) != NULL) | |
| 3293 | addenv(blk, "CONTENT_LENGTH=%s", s); | |
| 3297 | 3294 | |
| 3298 | if ((s = getenv("PATH")) != NULL) | |
| 3299 | addenv(blk, "PATH=%s", s); | |
| 3295 | if ((s = getenv("PATH")) != NULL) | |
| 3296 | addenv(blk, "PATH=%s", s); | |
| 3300 | 3297 | |
| 3301 | if (conn->path_info != NULL) { | |
| 3302 | addenv(blk, "PATH_INFO=%s", conn->path_info); | |
| 3303 | } | |
| 3298 | if (conn->path_info != NULL) { | |
| 3299 | addenv(blk, "PATH_INFO=%s", conn->path_info); | |
| 3300 | } | |
| 3304 | 3301 | |
| 3305 | 3302 | #if defined(_WIN32) |
| 3306 | if ((s = getenv("COMSPEC")) != NULL) { | |
| 3307 | addenv(blk, "COMSPEC=%s", s); | |
| 3308 | } | |
| 3309 | if ((s = getenv("SYSTEMROOT")) != NULL) { | |
| 3310 | addenv(blk, "SYSTEMROOT=%s", s); | |
| 3311 | } | |
| 3312 | if ((s = getenv("SystemDrive")) != NULL) { | |
| 3313 | addenv(blk, "SystemDrive=%s", s); | |
| 3314 | } | |
| 3315 | if ((s = getenv("ProgramFiles")) != NULL) { | |
| 3316 | addenv(blk, "ProgramFiles=%s", s); | |
| 3317 | } | |
| 3318 | if ((s = getenv("ProgramFiles(x86)")) != NULL) { | |
| 3319 | addenv(blk, "ProgramFiles(x86)=%s", s); | |
| 3320 | } | |
| 3303 | if ((s = getenv("COMSPEC")) != NULL) { | |
| 3304 | addenv(blk, "COMSPEC=%s", s); | |
| 3305 | } | |
| 3306 | if ((s = getenv("SYSTEMROOT")) != NULL) { | |
| 3307 | addenv(blk, "SYSTEMROOT=%s", s); | |
| 3308 | } | |
| 3309 | if ((s = getenv("SystemDrive")) != NULL) { | |
| 3310 | addenv(blk, "SystemDrive=%s", s); | |
| 3311 | } | |
| 3312 | if ((s = getenv("ProgramFiles")) != NULL) { | |
| 3313 | addenv(blk, "ProgramFiles=%s", s); | |
| 3314 | } | |
| 3315 | if ((s = getenv("ProgramFiles(x86)")) != NULL) { | |
| 3316 | addenv(blk, "ProgramFiles(x86)=%s", s); | |
| 3317 | } | |
| 3321 | 3318 | #else |
| 3322 | if ((s = getenv("LD_LIBRARY_PATH")) != NULL) | |
| 3323 | addenv(blk, "LD_LIBRARY_PATH=%s", s); | |
| 3319 | if ((s = getenv("LD_LIBRARY_PATH")) != NULL) | |
| 3320 | addenv(blk, "LD_LIBRARY_PATH=%s", s); | |
| 3324 | 3321 | #endif // _WIN32 |
| 3325 | 3322 | |
| 3326 | if ((s = getenv("PERLLIB")) != NULL) | |
| 3327 | addenv(blk, "PERLLIB=%s", s); | |
| 3323 | if ((s = getenv("PERLLIB")) != NULL) | |
| 3324 | addenv(blk, "PERLLIB=%s", s); | |
| 3328 | 3325 | |
| 3329 | if (conn->request_info.remote_user != NULL) { | |
| 3330 | addenv(blk, "REMOTE_USER=%s", conn->request_info.remote_user); | |
| 3331 | addenv(blk, "%s", "AUTH_TYPE=Digest"); | |
| 3332 | } | |
| 3326 | if (conn->request_info.remote_user != NULL) { | |
| 3327 | addenv(blk, "REMOTE_USER=%s", conn->request_info.remote_user); | |
| 3328 | addenv(blk, "%s", "AUTH_TYPE=Digest"); | |
| 3329 | } | |
| 3333 | 3330 | |
| 3334 | // Add all headers as HTTP_* variables | |
| 3335 | for (i = 0; i < conn->request_info.num_headers; i++) { | |
| 3336 | p = addenv(blk, "HTTP_%s=%s", | |
| 3337 | conn->request_info.http_headers[i].name, | |
| 3338 | conn->request_info.http_headers[i].value); | |
| 3331 | // Add all headers as HTTP_* variables | |
| 3332 | for (i = 0; i < conn->request_info.num_headers; i++) { | |
| 3333 | p = addenv(blk, "HTTP_%s=%s", | |
| 3334 | conn->request_info.http_headers[i].name, | |
| 3335 | conn->request_info.http_headers[i].value); | |
| 3339 | 3336 | |
| 3340 | // Convert variable name into uppercase, and change - to _ | |
| 3341 | for (; *p != '=' && *p != '\0'; p++) { | |
| 3342 | if (*p == '-') | |
| 3343 | *p = '_'; | |
| 3344 | *p = (char) toupper(* (unsigned char *) p); | |
| 3345 | } | |
| 3346 | } | |
| 3337 | // Convert variable name into uppercase, and change - to _ | |
| 3338 | for (; *p != '=' && *p != '\0'; p++) { | |
| 3339 | if (*p == '-') | |
| 3340 | *p = '_'; | |
| 3341 | *p = (char) toupper(* (unsigned char *) p); | |
| 3342 | } | |
| 3343 | } | |
| 3347 | 3344 | |
| 3348 | // Add user-specified variables | |
| 3349 | s = conn->ctx->config[CGI_ENVIRONMENT]; | |
| 3350 | while ((s = next_option(s, &var_vec, NULL)) != NULL) { | |
| 3351 | addenv(blk, "%.*s", (int) var_vec.len, var_vec.ptr); | |
| 3352 | } | |
| 3345 | // Add user-specified variables | |
| 3346 | s = conn->ctx->config[CGI_ENVIRONMENT]; | |
| 3347 | while ((s = next_option(s, &var_vec, NULL)) != NULL) { | |
| 3348 | addenv(blk, "%.*s", (int) var_vec.len, var_vec.ptr); | |
| 3349 | } | |
| 3353 | 3350 | |
| 3354 | blk->vars[blk->nvars++] = NULL; | |
| 3355 | blk->buf[blk->len++] = '\0'; | |
| 3351 | blk->vars[blk->nvars++] = NULL; | |
| 3352 | blk->buf[blk->len++] = '\0'; | |
| 3356 | 3353 | |
| 3357 | assert(blk->nvars < (int) ARRAY_SIZE(blk->vars)); | |
| 3358 | assert(blk->len > 0); | |
| 3359 | assert(blk->len < (int) sizeof(blk->buf)); | |
| 3354 | assert(blk->nvars < (int) ARRAY_SIZE(blk->vars)); | |
| 3355 | assert(blk->len > 0); | |
| 3356 | assert(blk->len < (int) sizeof(blk->buf)); | |
| 3360 | 3357 | } |
| 3361 | 3358 | |
| 3362 | 3359 | static void handle_cgi_request(struct mg_connection *conn, const char *prog) { |
| 3363 | int headers_len, data_len, i, fd_stdin[2], fd_stdout[2]; | |
| 3364 | const char *status, *status_text; | |
| 3365 | char buf[16384], *pbuf, dir[PATH_MAX], *p; | |
| 3366 | struct mg_request_info ri; | |
| 3367 | struct cgi_env_block blk; | |
| 3368 | FILE *in, *out; | |
| 3369 | struct file fout = STRUCT_FILE_INITIALIZER; | |
| 3370 | pid_t pid; | |
| 3371 | ri.mg_request_info::num_headers = 0; | |
| 3360 | int headers_len, data_len, i, fd_stdin[2], fd_stdout[2]; | |
| 3361 | const char *status, *status_text; | |
| 3362 | char buf[16384], *pbuf, dir[PATH_MAX], *p; | |
| 3363 | struct mg_request_info ri; | |
| 3364 | struct cgi_env_block blk; | |
| 3365 | FILE *in, *out; | |
| 3366 | struct file fout = STRUCT_FILE_INITIALIZER; | |
| 3367 | pid_t pid; | |
| 3368 | ri.mg_request_info::num_headers = 0; | |
| 3372 | 3369 | |
| 3373 | ||
| 3370 | prepare_cgi_environment(conn, prog, &blk); | |
| 3374 | 3371 | |
| 3375 | // CGI must be executed in its own directory. 'dir' must point to the | |
| 3376 | // directory containing executable program, 'p' must point to the | |
| 3377 | // executable program name relative to 'dir'. | |
| 3378 | (void) mg_snprintf(conn, dir, sizeof(dir), "%s", prog); | |
| 3379 | if ((p = strrchr(dir, '/')) != NULL) { | |
| 3380 | *p++ = '\0'; | |
| 3381 | } else { | |
| 3382 | dir[0] = '.', dir[1] = '\0'; | |
| 3383 | p = (char *) prog; | |
| 3384 | } | |
| 3372 | // CGI must be executed in its own directory. 'dir' must point to the | |
| 3373 | // directory containing executable program, 'p' must point to the | |
| 3374 | // executable program name relative to 'dir'. | |
| 3375 | (void) mg_snprintf(conn, dir, sizeof(dir), "%s", prog); | |
| 3376 | if ((p = strrchr(dir, '/')) != NULL) { | |
| 3377 | *p++ = '\0'; | |
| 3378 | } else { | |
| 3379 | dir[0] = '.', dir[1] = '\0'; | |
| 3380 | p = (char *) prog; | |
| 3381 | } | |
| 3385 | 3382 | |
| 3386 | pid = (pid_t) -1; | |
| 3387 | fd_stdin[0] = fd_stdin[1] = fd_stdout[0] = fd_stdout[1] = -1; | |
| 3388 | in = out = NULL; | |
| 3383 | pid = (pid_t) -1; | |
| 3384 | fd_stdin[0] = fd_stdin[1] = fd_stdout[0] = fd_stdout[1] = -1; | |
| 3385 | in = out = NULL; | |
| 3389 | 3386 | |
| 3390 | if (pipe(fd_stdin) != 0 || pipe(fd_stdout) != 0) { | |
| 3391 | send_http_error(conn, 500, http_500_error, | |
| 3392 | "Cannot create CGI pipe: %s", strerror(ERRNO)); | |
| 3393 | goto done; | |
| 3394 | } | |
| 3387 | if (pipe(fd_stdin) != 0 || pipe(fd_stdout) != 0) { | |
| 3388 | send_http_error(conn, 500, http_500_error, | |
| 3389 | "Cannot create CGI pipe: %s", strerror(ERRNO)); | |
| 3390 | goto done; | |
| 3391 | } | |
| 3395 | 3392 | |
| 3396 | pid = spawn_process(conn, p, blk.buf, blk.vars, fd_stdin[0], fd_stdout[1], | |
| 3397 | dir); | |
| 3398 | // spawn_process() must close those! | |
| 3399 | // If we don't mark them as closed, close() attempt before | |
| 3400 | // return from this function throws an exception on Windows. | |
| 3401 | // Windows does not like when closed descriptor is closed again. | |
| 3402 | fd_stdin[0] = fd_stdout[1] = -1; | |
| 3393 | pid = spawn_process(conn, p, blk.buf, blk.vars, fd_stdin[0], fd_stdout[1], | |
| 3394 | dir); | |
| 3395 | // spawn_process() must close those! | |
| 3396 | // If we don't mark them as closed, close() attempt before | |
| 3397 | // return from this function throws an exception on Windows. | |
| 3398 | // Windows does not like when closed descriptor is closed again. | |
| 3399 | fd_stdin[0] = fd_stdout[1] = -1; | |
| 3403 | 3400 | |
| 3404 | if (pid == (pid_t) -1) { | |
| 3405 | send_http_error(conn, 500, http_500_error, | |
| 3406 | "Cannot spawn CGI process [%s]: %s", prog, strerror(ERRNO)); | |
| 3407 | goto done; | |
| 3408 | } | |
| 3401 | if (pid == (pid_t) -1) { | |
| 3402 | send_http_error(conn, 500, http_500_error, | |
| 3403 | "Cannot spawn CGI process [%s]: %s", prog, strerror(ERRNO)); | |
| 3404 | goto done; | |
| 3405 | } | |
| 3409 | 3406 | |
| 3410 | if ((in = fdopen(fd_stdin[1], "wb")) == NULL || | |
| 3411 | (out = fdopen(fd_stdout[0], "rb")) == NULL) { | |
| 3412 | send_http_error(conn, 500, http_500_error, | |
| 3413 | "fopen: %s", strerror(ERRNO)); | |
| 3414 | goto done; | |
| 3415 | } | |
| 3407 | if ((in = fdopen(fd_stdin[1], "wb")) == NULL || | |
| 3408 | (out = fdopen(fd_stdout[0], "rb")) == NULL) { | |
| 3409 | send_http_error(conn, 500, http_500_error, | |
| 3410 | "fopen: %s", strerror(ERRNO)); | |
| 3411 | goto done; | |
| 3412 | } | |
| 3416 | 3413 | |
| 3417 | setbuf(in, NULL); | |
| 3418 | setbuf(out, NULL); | |
| 3419 | fout.fp = out; | |
| 3414 | setbuf(in, NULL); | |
| 3415 | setbuf(out, NULL); | |
| 3416 | fout.fp = out; | |
| 3420 | 3417 | |
| 3421 | // Send POST data to the CGI process if needed | |
| 3422 | if (!strcmp(conn->request_info.request_method, "POST") && | |
| 3423 | !forward_body_data(conn, in, INVALID_SOCKET, NULL)) { | |
| 3424 | goto done; | |
| 3425 | } | |
| 3418 | // Send POST data to the CGI process if needed | |
| 3419 | if (!strcmp(conn->request_info.request_method, "POST") && | |
| 3420 | !forward_body_data(conn, in, INVALID_SOCKET, NULL)) { | |
| 3421 | goto done; | |
| 3422 | } | |
| 3426 | 3423 | |
| 3427 | // Close so child gets an EOF. | |
| 3428 | fclose(in); | |
| 3429 | in = NULL; | |
| 3430 | fd_stdin[1] = -1; | |
| 3424 | // Close so child gets an EOF. | |
| 3425 | fclose(in); | |
| 3426 | in = NULL; | |
| 3427 | fd_stdin[1] = -1; | |
| 3431 | 3428 | |
| 3432 | // Now read CGI reply into a buffer. We need to set correct | |
| 3433 | // status code, thus we need to see all HTTP headers first. | |
| 3434 | // Do not send anything back to client, until we buffer in all | |
| 3435 | // HTTP headers. | |
| 3436 | data_len = 0; | |
| 3437 | headers_len = read_request(out, conn, buf, sizeof(buf), &data_len); | |
| 3438 | if (headers_len <= 0) { | |
| 3439 | send_http_error(conn, 500, http_500_error, | |
| 3440 | "CGI program sent malformed or too big (>%u bytes) " | |
| 3441 | "HTTP headers: [%.*s]", | |
| 3442 | (unsigned) sizeof(buf), data_len, buf); | |
| 3443 | goto done; | |
| 3444 | } | |
| 3445 | pbuf = buf; | |
| 3446 | buf[headers_len - 1] = '\0'; | |
| 3447 | parse_http_headers(&pbuf, &ri); | |
| 3429 | // Now read CGI reply into a buffer. We need to set correct | |
| 3430 | // status code, thus we need to see all HTTP headers first. | |
| 3431 | // Do not send anything back to client, until we buffer in all | |
| 3432 | // HTTP headers. | |
| 3433 | data_len = 0; | |
| 3434 | headers_len = read_request(out, conn, buf, sizeof(buf), &data_len); | |
| 3435 | if (headers_len <= 0) { | |
| 3436 | send_http_error(conn, 500, http_500_error, | |
| 3437 | "CGI program sent malformed or too big (>%u bytes) " | |
| 3438 | "HTTP headers: [%.*s]", | |
| 3439 | (unsigned) sizeof(buf), data_len, buf); | |
| 3440 | goto done; | |
| 3441 | } | |
| 3442 | pbuf = buf; | |
| 3443 | buf[headers_len - 1] = '\0'; | |
| 3444 | parse_http_headers(&pbuf, &ri); | |
| 3448 | 3445 | |
| 3449 | // Make up and send the status line | |
| 3450 | status_text = "OK"; | |
| 3451 | if ((status = get_header(&ri, "Status")) != NULL) { | |
| 3452 | conn->status_code = atoi(status); | |
| 3453 | status_text = status; | |
| 3454 | while (isdigit(* (unsigned char *) status_text) || *status_text == ' ') { | |
| 3455 | status_text++; | |
| 3456 | } | |
| 3457 | } else if (get_header(&ri, "Location") != NULL) { | |
| 3458 | conn->status_code = 302; | |
| 3459 | } else { | |
| 3460 | conn->status_code = 200; | |
| 3461 | } | |
| 3462 | if (get_header(&ri, "Connection") != NULL && | |
| 3463 | !mg_strcasecmp(get_header(&ri, "Connection"), "keep-alive")) { | |
| 3464 | conn->must_close = 1; | |
| 3465 | } | |
| 3466 | (void) mg_printf(conn, "HTTP/1.1 %d %s\r\n", conn->status_code, | |
| 3467 | status_text); | |
| 3446 | // Make up and send the status line | |
| 3447 | status_text = "OK"; | |
| 3448 | if ((status = get_header(&ri, "Status")) != NULL) { | |
| 3449 | conn->status_code = atoi(status); | |
| 3450 | status_text = status; | |
| 3451 | while (isdigit(* (unsigned char *) status_text) || *status_text == ' ') { | |
| 3452 | status_text++; | |
| 3453 | } | |
| 3454 | } else if (get_header(&ri, "Location") != NULL) { | |
| 3455 | conn->status_code = 302; | |
| 3456 | } else { | |
| 3457 | conn->status_code = 200; | |
| 3458 | } | |
| 3459 | if (get_header(&ri, "Connection") != NULL && | |
| 3460 | !mg_strcasecmp(get_header(&ri, "Connection"), "keep-alive")) { | |
| 3461 | conn->must_close = 1; | |
| 3462 | } | |
| 3463 | (void) mg_printf(conn, "HTTP/1.1 %d %s\r\n", conn->status_code, | |
| 3464 | status_text); | |
| 3468 | 3465 | |
| 3469 | // Send headers | |
| 3470 | for (i = 0; i < ri.num_headers; i++) { | |
| 3471 | mg_printf(conn, "%s: %s\r\n", | |
| 3472 | ri.http_headers[i].name, ri.http_headers[i].value); | |
| 3473 | } | |
| 3474 | mg_write(conn, "\r\n", 2); | |
| 3466 | // Send headers | |
| 3467 | for (i = 0; i < ri.num_headers; i++) { | |
| 3468 | mg_printf(conn, "%s: %s\r\n", | |
| 3469 | ri.http_headers[i].name, ri.http_headers[i].value); | |
| 3470 | } | |
| 3471 | mg_write(conn, "\r\n", 2); | |
| 3475 | 3472 | |
| 3476 | // Send chunk of data that may have been read after the headers | |
| 3477 | conn->num_bytes_sent += mg_write(conn, buf + headers_len, | |
| 3478 | (size_t)(data_len - headers_len)); | |
| 3473 | // Send chunk of data that may have been read after the headers | |
| 3474 | conn->num_bytes_sent += mg_write(conn, buf + headers_len, | |
| 3475 | (size_t)(data_len - headers_len)); | |
| 3479 | 3476 | |
| 3480 | // Read the rest of CGI output and send to the client | |
| 3481 | send_file_data(conn, &fout, 0, INT64_MAX); | |
| 3477 | // Read the rest of CGI output and send to the client | |
| 3478 | send_file_data(conn, &fout, 0, INT64_MAX); | |
| 3482 | 3479 | |
| 3483 | 3480 | done: |
| 3484 | if (pid != (pid_t) -1) { | |
| 3485 | kill(pid, SIGKILL); | |
| 3486 | } | |
| 3487 | if (fd_stdin[0] != -1) { | |
| 3488 | close(fd_stdin[0]); | |
| 3489 | } | |
| 3490 | if (fd_stdout[1] != -1) { | |
| 3491 | close(fd_stdout[1]); | |
| 3492 | } | |
| 3481 | if (pid != (pid_t) -1) { | |
| 3482 | kill(pid, SIGKILL); | |
| 3483 | } | |
| 3484 | if (fd_stdin[0] != -1) { | |
| 3485 | close(fd_stdin[0]); | |
| 3486 | } | |
| 3487 | if (fd_stdout[1] != -1) { | |
| 3488 | close(fd_stdout[1]); | |
| 3489 | } | |
| 3493 | 3490 | |
| 3494 | if (in != NULL) { | |
| 3495 | fclose(in); | |
| 3496 | } else if (fd_stdin[1] != -1) { | |
| 3497 | close(fd_stdin[1]); | |
| 3498 | } | |
| 3491 | if (in != NULL) { | |
| 3492 | fclose(in); | |
| 3493 | } else if (fd_stdin[1] != -1) { | |
| 3494 | close(fd_stdin[1]); | |
| 3495 | } | |
| 3499 | 3496 | |
| 3500 | if (out != NULL) { | |
| 3501 | fclose(out); | |
| 3502 | } else if (fd_stdout[0] != -1) { | |
| 3503 | close(fd_stdout[0]); | |
| 3504 | } | |
| 3497 | if (out != NULL) { | |
| 3498 | fclose(out); | |
| 3499 | } else if (fd_stdout[0] != -1) { | |
| 3500 | close(fd_stdout[0]); | |
| 3501 | } | |
| 3505 | 3502 | } |
| 3506 | 3503 | #endif // !NO_CGI |
| 3507 | 3504 | |
| r25360 | r25361 | |
| 3509 | 3506 | // for given path. Return 0 if the path itself is a directory, |
| 3510 | 3507 | // or -1 on error, 1 if OK. |
| 3511 | 3508 | static int put_dir(struct mg_connection *conn, const char *path) { |
| 3512 | char buf[PATH_MAX]; | |
| 3513 | const char *s, *p; | |
| 3514 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 3515 | int len, res = 1; | |
| 3509 | char buf[PATH_MAX]; | |
| 3510 | const char *s, *p; | |
| 3511 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 3512 | int len, res = 1; | |
| 3516 | 3513 | |
| 3517 | for (s = p = path + 2; (p = strchr(s, '/')) != NULL; s = ++p) { | |
| 3518 | len = p - path; | |
| 3519 | if (len >= (int) sizeof(buf)) { | |
| 3520 | res = -1; | |
| 3521 | break; | |
| 3522 | } | |
| 3523 | memcpy(buf, path, len); | |
| 3524 | buf[len] = '\0'; | |
| 3514 | for (s = p = path + 2; (p = strchr(s, '/')) != NULL; s = ++p) { | |
| 3515 | len = p - path; | |
| 3516 | if (len >= (int) sizeof(buf)) { | |
| 3517 | res = -1; | |
| 3518 | break; | |
| 3519 | } | |
| 3520 | memcpy(buf, path, len); | |
| 3521 | buf[len] = '\0'; | |
| 3525 | 3522 | |
| 3526 | // Try to create intermediate directory | |
| 3527 | DEBUG_TRACE(("mkdir(%s)", buf)); | |
| 3528 | if (!mg_stat(conn, buf, &file) && mg_mkdir(buf, 0755) != 0) { | |
| 3529 | res = -1; | |
| 3530 | break; | |
| 3531 | } | |
| 3523 | // Try to create intermediate directory | |
| 3524 | DEBUG_TRACE(("mkdir(%s)", buf)); | |
| 3525 | if (!mg_stat(conn, buf, &file) && mg_mkdir(buf, 0755) != 0) { | |
| 3526 | res = -1; | |
| 3527 | break; | |
| 3528 | } | |
| 3532 | 3529 | |
| 3533 | // Is path itself a directory? | |
| 3534 | if (p[1] == '\0') { | |
| 3535 | res = 0; | |
| 3536 | } | |
| 3537 | } | |
| 3530 | // Is path itself a directory? | |
| 3531 | if (p[1] == '\0') { | |
| 3532 | res = 0; | |
| 3533 | } | |
| 3534 | } | |
| 3538 | 3535 | |
| 3539 | ||
| 3536 | return res; | |
| 3540 | 3537 | } |
| 3541 | 3538 | |
| 3542 | 3539 | static void mkcol(struct mg_connection *conn, const char *path) { |
| 3543 | int rc, body_len; | |
| 3544 | struct de de; | |
| 3545 | memset(&de.file, 0, sizeof(de.file)); | |
| 3546 | mg_stat(conn, path, &de.file); | |
| 3540 | int rc, body_len; | |
| 3541 | struct de de; | |
| 3542 | memset(&de.file, 0, sizeof(de.file)); | |
| 3543 | mg_stat(conn, path, &de.file); | |
| 3547 | 3544 | |
| 3548 | if(de.file.modification_time) { | |
| 3549 | send_http_error(conn, 405, "Method Not Allowed", | |
| 3550 | "mkcol(%s): %s", path, strerror(ERRNO)); | |
| 3551 | return; | |
| 3552 | } | |
| 3545 | if(de.file.modification_time) { | |
| 3546 | send_http_error(conn, 405, "Method Not Allowed", | |
| 3547 | "mkcol(%s): %s", path, strerror(ERRNO)); | |
| 3548 | return; | |
| 3549 | } | |
| 3553 | 3550 | |
| 3554 | body_len = conn->data_len - conn->request_len; | |
| 3555 | if(body_len > 0) { | |
| 3556 | send_http_error(conn, 415, "Unsupported media type", | |
| 3557 | "mkcol(%s): %s", path, strerror(ERRNO)); | |
| 3558 | return; | |
| 3559 | } | |
| 3551 | body_len = conn->data_len - conn->request_len; | |
| 3552 | if(body_len > 0) { | |
| 3553 | send_http_error(conn, 415, "Unsupported media type", | |
| 3554 | "mkcol(%s): %s", path, strerror(ERRNO)); | |
| 3555 | return; | |
| 3556 | } | |
| 3560 | 3557 | |
| 3561 | ||
| 3558 | rc = mg_mkdir(path, 0755); | |
| 3562 | 3559 | |
| 3563 | if (rc == 0) { | |
| 3564 | conn->status_code = 201; | |
| 3565 | mg_printf(conn, "HTTP/1.1 %d Created\r\n\r\n", conn->status_code); | |
| 3566 | } else if (rc == -1) { | |
| 3567 | if(errno == EEXIST) | |
| 3568 | send_http_error(conn, 405, "Method Not Allowed", | |
| 3569 | "mkcol(%s): %s", path, strerror(ERRNO)); | |
| 3570 | else if(errno == EACCES) | |
| 3571 | send_http_error(conn, 403, "Forbidden", | |
| 3572 | "mkcol(%s): %s", path, strerror(ERRNO)); | |
| 3573 | else if(errno == ENOENT) | |
| 3574 | send_http_error(conn, 409, "Conflict", | |
| 3575 | "mkcol(%s): %s", path, strerror(ERRNO)); | |
| 3576 | else | |
| 3577 | send_http_error(conn, 500, http_500_error, | |
| 3578 | "fopen(%s): %s", path, strerror(ERRNO)); | |
| 3579 | } | |
| 3560 | if (rc == 0) { | |
| 3561 | conn->status_code = 201; | |
| 3562 | mg_printf(conn, "HTTP/1.1 %d Created\r\n\r\n", conn->status_code); | |
| 3563 | } else if (rc == -1) { | |
| 3564 | if(errno == EEXIST) | |
| 3565 | send_http_error(conn, 405, "Method Not Allowed", | |
| 3566 | "mkcol(%s): %s", path, strerror(ERRNO)); | |
| 3567 | else if(errno == EACCES) | |
| 3568 | send_http_error(conn, 403, "Forbidden", | |
| 3569 | "mkcol(%s): %s", path, strerror(ERRNO)); | |
| 3570 | else if(errno == ENOENT) | |
| 3571 | send_http_error(conn, 409, "Conflict", | |
| 3572 | "mkcol(%s): %s", path, strerror(ERRNO)); | |
| 3573 | else | |
| 3574 | send_http_error(conn, 500, http_500_error, | |
| 3575 | "fopen(%s): %s", path, strerror(ERRNO)); | |
| 3576 | } | |
| 3580 | 3577 | } |
| 3581 | 3578 | |
| 3582 | 3579 | static void put_file(struct mg_connection *conn, const char *path) { |
| 3583 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 3584 | const char *range; | |
| 3585 | int64_t r1, r2; | |
| 3586 | int rc; | |
| 3580 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 3581 | const char *range; | |
| 3582 | int64_t r1, r2; | |
| 3583 | int rc; | |
| 3587 | 3584 | |
| 3588 | ||
| 3585 | conn->status_code = mg_stat(conn, path, &file) ? 200 : 201; | |
| 3589 | 3586 | |
| 3590 | if ((rc = put_dir(conn, path)) == 0) { | |
| 3591 | mg_printf(conn, "HTTP/1.1 %d OK\r\n\r\n", conn->status_code); | |
| 3592 | } else if (rc == -1) { | |
| 3593 | send_http_error(conn, 500, http_500_error, | |
| 3594 | "put_dir(%s): %s", path, strerror(ERRNO)); | |
| 3595 | } else if (!mg_fopen(conn, path, "wb+", &file) || file.fp == NULL) { | |
| 3596 | mg_fclose(&file); | |
| 3597 | send_http_error(conn, 500, http_500_error, | |
| 3598 | "fopen(%s): %s", path, strerror(ERRNO)); | |
| 3599 | } else { | |
| 3600 | fclose_on_exec(&file); | |
| 3601 | range = mg_get_header(conn, "Content-Range"); | |
| 3602 | r1 = r2 = 0; | |
| 3603 | if (range != NULL && parse_range_header(range, &r1, &r2) > 0) { | |
| 3604 | conn->status_code = 206; | |
| 3605 | fseeko(file.fp, r1, SEEK_SET); | |
| 3606 | } | |
| 3607 | if (forward_body_data(conn, file.fp, INVALID_SOCKET, NULL)) { | |
| 3608 | mg_printf(conn, "HTTP/1.1 %d OK\r\n\r\n", conn->status_code); | |
| 3609 | } | |
| 3610 | mg_fclose(&file); | |
| 3611 | } | |
| 3587 | if ((rc = put_dir(conn, path)) == 0) { | |
| 3588 | mg_printf(conn, "HTTP/1.1 %d OK\r\n\r\n", conn->status_code); | |
| 3589 | } else if (rc == -1) { | |
| 3590 | send_http_error(conn, 500, http_500_error, | |
| 3591 | "put_dir(%s): %s", path, strerror(ERRNO)); | |
| 3592 | } else if (!mg_fopen(conn, path, "wb+", &file) || file.fp == NULL) { | |
| 3593 | mg_fclose(&file); | |
| 3594 | send_http_error(conn, 500, http_500_error, | |
| 3595 | "fopen(%s): %s", path, strerror(ERRNO)); | |
| 3596 | } else { | |
| 3597 | fclose_on_exec(&file); | |
| 3598 | range = mg_get_header(conn, "Content-Range"); | |
| 3599 | r1 = r2 = 0; | |
| 3600 | if (range != NULL && parse_range_header(range, &r1, &r2) > 0) { | |
| 3601 | conn->status_code = 206; | |
| 3602 | fseeko(file.fp, r1, SEEK_SET); | |
| 3603 | } | |
| 3604 | if (forward_body_data(conn, file.fp, INVALID_SOCKET, NULL)) { | |
| 3605 | mg_printf(conn, "HTTP/1.1 %d OK\r\n\r\n", conn->status_code); | |
| 3606 | } | |
| 3607 | mg_fclose(&file); | |
| 3608 | } | |
| 3612 | 3609 | } |
| 3613 | 3610 | |
| 3614 | 3611 | static void send_ssi_file(struct mg_connection *, const char *, |
| 3615 | ||
| 3612 | struct file *, int); | |
| 3616 | 3613 | |
| 3617 | 3614 | static void do_ssi_include(struct mg_connection *conn, const char *ssi, |
| 3618 | char *tag, int include_level) { | |
| 3619 | char file_name[MG_BUF_LEN], path[PATH_MAX], *p; | |
| 3620 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 3615 | char *tag, int include_level) { | |
| 3616 | char file_name[MG_BUF_LEN], path[PATH_MAX], *p; | |
| 3617 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 3621 | 3618 | |
| 3622 | // sscanf() is safe here, since send_ssi_file() also uses buffer | |
| 3623 | // of size MG_BUF_LEN to get the tag. So strlen(tag) is always < MG_BUF_LEN. | |
| 3624 | if (sscanf(tag, " virtual=\"%[^\"]\"", file_name) == 1) { | |
| 3625 | // File name is relative to the webserver root | |
| 3626 | (void) mg_snprintf(conn, path, sizeof(path), "%s%c%s", | |
| 3627 | conn->ctx->config[DOCUMENT_ROOT], '/', file_name); | |
| 3628 | } else if (sscanf(tag, " file=\"%[^\"]\"", file_name) == 1) { | |
| 3629 | // File name is relative to the webserver working directory | |
| 3630 | // or it is absolute system path | |
| 3631 | (void) mg_snprintf(conn, path, sizeof(path), "%s", file_name); | |
| 3632 | } else if (sscanf(tag, " \"%[^\"]\"", file_name) == 1) { | |
| 3633 | // File name is relative to the currect document | |
| 3634 | (void) mg_snprintf(conn, path, sizeof(path), "%s", ssi); | |
| 3635 | if ((p = strrchr(path, '/')) != NULL) { | |
| 3636 | p[1] = '\0'; | |
| 3637 | } | |
| 3638 | (void) mg_snprintf(conn, path + strlen(path), | |
| 3639 | sizeof(path) - strlen(path), "%s", file_name); | |
| 3640 | } else { | |
| 3641 | cry(conn, "Bad SSI #include: [%s]", tag); | |
| 3642 | return; | |
| 3643 | } | |
| 3619 | // sscanf() is safe here, since send_ssi_file() also uses buffer | |
| 3620 | // of size MG_BUF_LEN to get the tag. So strlen(tag) is always < MG_BUF_LEN. | |
| 3621 | if (sscanf(tag, " virtual=\"%[^\"]\"", file_name) == 1) { | |
| 3622 | // File name is relative to the webserver root | |
| 3623 | (void) mg_snprintf(conn, path, sizeof(path), "%s%c%s", | |
| 3624 | conn->ctx->config[DOCUMENT_ROOT], '/', file_name); | |
| 3625 | } else if (sscanf(tag, " file=\"%[^\"]\"", file_name) == 1) { | |
| 3626 | // File name is relative to the webserver working directory | |
| 3627 | // or it is absolute system path | |
| 3628 | (void) mg_snprintf(conn, path, sizeof(path), "%s", file_name); | |
| 3629 | } else if (sscanf(tag, " \"%[^\"]\"", file_name) == 1) { | |
| 3630 | // File name is relative to the currect document | |
| 3631 | (void) mg_snprintf(conn, path, sizeof(path), "%s", ssi); | |
| 3632 | if ((p = strrchr(path, '/')) != NULL) { | |
| 3633 | p[1] = '\0'; | |
| 3634 | } | |
| 3635 | (void) mg_snprintf(conn, path + strlen(path), | |
| 3636 | sizeof(path) - strlen(path), "%s", file_name); | |
| 3637 | } else { | |
| 3638 | cry(conn, "Bad SSI #include: [%s]", tag); | |
| 3639 | return; | |
| 3640 | } | |
| 3644 | 3641 | |
| 3645 | if (!mg_fopen(conn, path, "rb", &file)) { | |
| 3646 | cry(conn, "Cannot open SSI #include: [%s]: fopen(%s): %s", | |
| 3647 | tag, path, strerror(ERRNO)); | |
| 3648 | } else { | |
| 3649 | fclose_on_exec(&file); | |
| 3650 | if (match_prefix(conn->ctx->config[SSI_EXTENSIONS], | |
| 3651 | strlen(conn->ctx->config[SSI_EXTENSIONS]), path) > 0) { | |
| 3652 | send_ssi_file(conn, path, &file, include_level + 1); | |
| 3653 | } else { | |
| 3654 | send_file_data(conn, &file, 0, INT64_MAX); | |
| 3655 | } | |
| 3656 | mg_fclose(&file); | |
| 3657 | } | |
| 3642 | if (!mg_fopen(conn, path, "rb", &file)) { | |
| 3643 | cry(conn, "Cannot open SSI #include: [%s]: fopen(%s): %s", | |
| 3644 | tag, path, strerror(ERRNO)); | |
| 3645 | } else { | |
| 3646 | fclose_on_exec(&file); | |
| 3647 | if (match_prefix(conn->ctx->config[SSI_EXTENSIONS], | |
| 3648 | strlen(conn->ctx->config[SSI_EXTENSIONS]), path) > 0) { | |
| 3649 | send_ssi_file(conn, path, &file, include_level + 1); | |
| 3650 | } else { | |
| 3651 | send_file_data(conn, &file, 0, INT64_MAX); | |
| 3652 | } | |
| 3653 | mg_fclose(&file); | |
| 3654 | } | |
| 3658 | 3655 | } |
| 3659 | 3656 | |
| 3660 | 3657 | #if !defined(NO_POPEN) |
| 3661 | 3658 | static void do_ssi_exec(struct mg_connection *conn, char *tag) { |
| 3662 | char cmd[MG_BUF_LEN]; | |
| 3663 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 3659 | char cmd[MG_BUF_LEN]; | |
| 3660 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 3664 | 3661 | |
| 3665 | if (sscanf(tag, " \"%[^\"]\"", cmd) != 1) { | |
| 3666 | cry(conn, "Bad SSI #exec: [%s]", tag); | |
| 3667 | } else if ((file.fp = popen(cmd, "r")) == NULL) { | |
| 3668 | cry(conn, "Cannot SSI #exec: [%s]: %s", cmd, strerror(ERRNO)); | |
| 3669 | } else { | |
| 3670 | send_file_data(conn, &file, 0, INT64_MAX); | |
| 3671 | pclose(file.fp); | |
| 3672 | } | |
| 3662 | if (sscanf(tag, " \"%[^\"]\"", cmd) != 1) { | |
| 3663 | cry(conn, "Bad SSI #exec: [%s]", tag); | |
| 3664 | } else if ((file.fp = popen(cmd, "r")) == NULL) { | |
| 3665 | cry(conn, "Cannot SSI #exec: [%s]: %s", cmd, strerror(ERRNO)); | |
| 3666 | } else { | |
| 3667 | send_file_data(conn, &file, 0, INT64_MAX); | |
| 3668 | pclose(file.fp); | |
| 3669 | } | |
| 3673 | 3670 | } |
| 3674 | 3671 | #endif // !NO_POPEN |
| 3675 | 3672 | |
| 3676 | 3673 | static int mg_fgetc(struct file *filep, int offset) { |
| 3677 | if (filep->membuf != NULL && offset >=0 && offset < filep->size) { | |
| 3678 | return ((unsigned char *) filep->membuf)[offset]; | |
| 3679 | } else if (filep->fp != NULL) { | |
| 3680 | return fgetc(filep->fp); | |
| 3681 | } else { | |
| 3682 | return EOF; | |
| 3683 | } | |
| 3674 | if (filep->membuf != NULL && offset >=0 && offset < filep->size) { | |
| 3675 | return ((unsigned char *) filep->membuf)[offset]; | |
| 3676 | } else if (filep->fp != NULL) { | |
| 3677 | return fgetc(filep->fp); | |
| 3678 | } else { | |
| 3679 | return EOF; | |
| 3680 | } | |
| 3684 | 3681 | } |
| 3685 | 3682 | |
| 3686 | 3683 | static void send_ssi_file(struct mg_connection *conn, const char *path, |
| 3687 | struct file *filep, int include_level) { | |
| 3688 | char buf[MG_BUF_LEN]; | |
| 3689 | int ch, offset, len, in_ssi_tag; | |
| 3684 | struct file *filep, int include_level) { | |
| 3685 | char buf[MG_BUF_LEN]; | |
| 3686 | int ch, offset, len, in_ssi_tag; | |
| 3690 | 3687 | |
| 3691 | if (include_level > 10) { | |
| 3692 | cry(conn, "SSI #include level is too deep (%s)", path); | |
| 3693 | return; | |
| 3694 | } | |
| 3688 | if (include_level > 10) { | |
| 3689 | cry(conn, "SSI #include level is too deep (%s)", path); | |
| 3690 | return; | |
| 3691 | } | |
| 3695 | 3692 | |
| 3696 | in_ssi_tag = len = offset = 0; | |
| 3697 | while ((ch = mg_fgetc(filep, offset)) != EOF) { | |
| 3698 | if (in_ssi_tag && ch == '>') { | |
| 3699 | in_ssi_tag = 0; | |
| 3700 | buf[len++] = (char) ch; | |
| 3701 | buf[len] = '\0'; | |
| 3702 | assert(len <= (int) sizeof(buf)); | |
| 3703 | if (len < 6 || memcmp(buf, "<!--#", 5) != 0) { | |
| 3704 | // Not an SSI tag, pass it | |
| 3705 | (void) mg_write(conn, buf, (size_t) len); | |
| 3706 | } else { | |
| 3707 | if (!memcmp(buf + 5, "include", 7)) { | |
| 3708 | do_ssi_include(conn, path, buf + 12, include_level); | |
| 3693 | in_ssi_tag = len = offset = 0; | |
| 3694 | while ((ch = mg_fgetc(filep, offset)) != EOF) { | |
| 3695 | if (in_ssi_tag && ch == '>') { | |
| 3696 | in_ssi_tag = 0; | |
| 3697 | buf[len++] = (char) ch; | |
| 3698 | buf[len] = '\0'; | |
| 3699 | assert(len <= (int) sizeof(buf)); | |
| 3700 | if (len < 6 || memcmp(buf, "<!--#", 5) != 0) { | |
| 3701 | // Not an SSI tag, pass it | |
| 3702 | (void) mg_write(conn, buf, (size_t) len); | |
| 3703 | } else { | |
| 3704 | if (!memcmp(buf + 5, "include", 7)) { | |
| 3705 | do_ssi_include(conn, path, buf + 12, include_level); | |
| 3709 | 3706 | #if !defined(NO_POPEN) |
| 3710 | } else if (!memcmp(buf + 5, "exec", 4)) { | |
| 3711 | do_ssi_exec(conn, buf + 9); | |
| 3707 | } else if (!memcmp(buf + 5, "exec", 4)) { | |
| 3708 | do_ssi_exec(conn, buf + 9); | |
| 3712 | 3709 | #endif // !NO_POPEN |
| 3713 | } else { | |
| 3714 | cry(conn, "%s: unknown SSI " "command: \"%s\"", path, buf); | |
| 3715 | } | |
| 3716 | } | |
| 3717 | len = 0; | |
| 3718 | } else if (in_ssi_tag) { | |
| 3719 | if (len == 5 && memcmp(buf, "<!--#", 5) != 0) { | |
| 3720 | // Not an SSI tag | |
| 3721 | in_ssi_tag = 0; | |
| 3722 | } else if (len == (int) sizeof(buf) - 2) { | |
| 3723 | cry(conn, "%s: SSI tag is too large", path); | |
| 3724 | len = 0; | |
| 3725 | } | |
| 3726 | buf[len++] = ch & 0xff; | |
| 3727 | } else if (ch == '<') { | |
| 3728 | in_ssi_tag = 1; | |
| 3729 | if (len > 0) { | |
| 3730 | mg_write(conn, buf, (size_t) len); | |
| 3731 | } | |
| 3732 | len = 0; | |
| 3733 | buf[len++] = ch & 0xff; | |
| 3734 | } else { | |
| 3735 | buf[len++] = ch & 0xff; | |
| 3736 | if (len == (int) sizeof(buf)) { | |
| 3737 | mg_write(conn, buf, (size_t) len); | |
| 3738 | len = 0; | |
| 3739 | } | |
| 3740 | } | |
| 3741 | } | |
| 3710 | } else { | |
| 3711 | cry(conn, "%s: unknown SSI " "command: \"%s\"", path, buf); | |
| 3712 | } | |
| 3713 | } | |
| 3714 | len = 0; | |
| 3715 | } else if (in_ssi_tag) { | |
| 3716 | if (len == 5 && memcmp(buf, "<!--#", 5) != 0) { | |
| 3717 | // Not an SSI tag | |
| 3718 | in_ssi_tag = 0; | |
| 3719 | } else if (len == (int) sizeof(buf) - 2) { | |
| 3720 | cry(conn, "%s: SSI tag is too large", path); | |
| 3721 | len = 0; | |
| 3722 | } | |
| 3723 | buf[len++] = ch & 0xff; | |
| 3724 | } else if (ch == '<') { | |
| 3725 | in_ssi_tag = 1; | |
| 3726 | if (len > 0) { | |
| 3727 | mg_write(conn, buf, (size_t) len); | |
| 3728 | } | |
| 3729 | len = 0; | |
| 3730 | buf[len++] = ch & 0xff; | |
| 3731 | } else { | |
| 3732 | buf[len++] = ch & 0xff; | |
| 3733 | if (len == (int) sizeof(buf)) { | |
| 3734 | mg_write(conn, buf, (size_t) len); | |
| 3735 | len = 0; | |
| 3736 | } | |
| 3737 | } | |
| 3738 | } | |
| 3742 | 3739 | |
| 3743 | // Send the rest of buffered data | |
| 3744 | if (len > 0) { | |
| 3745 | mg_write(conn, buf, (size_t) len); | |
| 3746 | } | |
| 3740 | // Send the rest of buffered data | |
| 3741 | if (len > 0) { | |
| 3742 | mg_write(conn, buf, (size_t) len); | |
| 3743 | } | |
| 3747 | 3744 | } |
| 3748 | 3745 | |
| 3749 | 3746 | static void handle_ssi_file_request(struct mg_connection *conn, |
| 3750 | const char *path) { | |
| 3751 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 3747 | const char *path) { | |
| 3748 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 3752 | 3749 | |
| 3753 | if (!mg_fopen(conn, path, "rb", &file)) { | |
| 3754 | send_http_error(conn, 500, http_500_error, "fopen(%s): %s", path, | |
| 3755 | strerror(ERRNO)); | |
| 3756 | } else { | |
| 3757 | conn->must_close = 1; | |
| 3758 | fclose_on_exec(&file); | |
| 3759 | mg_printf(conn, "HTTP/1.1 200 OK\r\n" | |
| 3760 | "Content-Type: text/html\r\nConnection: %s\r\n\r\n", | |
| 3761 | suggest_connection_header(conn)); | |
| 3762 | send_ssi_file(conn, path, &file, 0); | |
| 3763 | mg_fclose(&file); | |
| 3764 | } | |
| 3750 | if (!mg_fopen(conn, path, "rb", &file)) { | |
| 3751 | send_http_error(conn, 500, http_500_error, "fopen(%s): %s", path, | |
| 3752 | strerror(ERRNO)); | |
| 3753 | } else { | |
| 3754 | conn->must_close = 1; | |
| 3755 | fclose_on_exec(&file); | |
| 3756 | mg_printf(conn, "HTTP/1.1 200 OK\r\n" | |
| 3757 | "Content-Type: text/html\r\nConnection: %s\r\n\r\n", | |
| 3758 | suggest_connection_header(conn)); | |
| 3759 | send_ssi_file(conn, path, &file, 0); | |
| 3760 | mg_fclose(&file); | |
| 3761 | } | |
| 3765 | 3762 | } |
| 3766 | 3763 | |
| 3767 | 3764 | static void send_options(struct mg_connection *conn) { |
| 3768 | ||
| 3765 | conn->status_code = 200; | |
| 3769 | 3766 | |
| 3770 | mg_printf(conn, "%s", "HTTP/1.1 200 OK\r\n" | |
| 3771 | "Allow: GET, POST, HEAD, CONNECT, PUT, DELETE, OPTIONS, PROPFIND, MKCOL\r\n" | |
| 3772 | "DAV: 1\r\n\r\n"); | |
| 3767 | mg_printf(conn, "%s", "HTTP/1.1 200 OK\r\n" | |
| 3768 | "Allow: GET, POST, HEAD, CONNECT, PUT, DELETE, OPTIONS, PROPFIND, MKCOL\r\n" | |
| 3769 | "DAV: 1\r\n\r\n"); | |
| 3773 | 3770 | } |
| 3774 | 3771 | |
| 3775 | 3772 | // Writes PROPFIND properties for a collection element |
| 3776 | 3773 | static void print_props(struct mg_connection *conn, const char* uri, |
| 3777 | struct file *filep) { | |
| 3778 | char mtime[64]; | |
| 3779 | gmt_time_string(mtime, sizeof(mtime), &filep->modification_time); | |
| 3780 | conn->num_bytes_sent += mg_printf(conn, | |
| 3781 | "<d:response>" | |
| 3782 | "<d:href>%s</d:href>" | |
| 3783 | "<d:propstat>" | |
| 3784 | "<d:prop>" | |
| 3785 | "<d:resourcetype>%s</d:resourcetype>" | |
| 3786 | "<d:getcontentlength>%" INT64_FMT "</d:getcontentlength>" | |
| 3787 | "<d:getlastmodified>%s</d:getlastmodified>" | |
| 3788 | "</d:prop>" | |
| 3789 | "<d:status>HTTP/1.1 200 OK</d:status>" | |
| 3790 | "</d:propstat>" | |
| 3791 | "</d:response>\n", | |
| 3792 | uri, | |
| 3793 | filep->is_directory ? "<d:collection/>" : "", | |
| 3794 | filep->size, | |
| 3795 | mtime); | |
| 3774 | struct file *filep) { | |
| 3775 | char mtime[64]; | |
| 3776 | gmt_time_string(mtime, sizeof(mtime), &filep->modification_time); | |
| 3777 | conn->num_bytes_sent += mg_printf(conn, | |
| 3778 | "<d:response>" | |
| 3779 | "<d:href>%s</d:href>" | |
| 3780 | "<d:propstat>" | |
| 3781 | "<d:prop>" | |
| 3782 | "<d:resourcetype>%s</d:resourcetype>" | |
| 3783 | "<d:getcontentlength>%" INT64_FMT "</d:getcontentlength>" | |
| 3784 | "<d:getlastmodified>%s</d:getlastmodified>" | |
| 3785 | "</d:prop>" | |
| 3786 | "<d:status>HTTP/1.1 200 OK</d:status>" | |
| 3787 | "</d:propstat>" | |
| 3788 | "</d:response>\n", | |
| 3789 | uri, | |
| 3790 | filep->is_directory ? "<d:collection/>" : "", | |
| 3791 | filep->size, | |
| 3792 | mtime); | |
| 3796 | 3793 | } |
| 3797 | 3794 | |
| 3798 | 3795 | static void print_dav_dir_entry(struct de *de, void *data) { |
| 3799 | char href[PATH_MAX]; | |
| 3800 | char href_encoded[PATH_MAX]; | |
| 3801 | struct mg_connection *conn = (struct mg_connection *) data; | |
| 3802 | mg_snprintf(conn, href, sizeof(href), "%s%s", | |
| 3803 | conn->request_info.uri, de->file_name); | |
| 3804 | mg_url_encode(href, href_encoded, PATH_MAX-1); | |
| 3805 | print_props(conn, href_encoded, &de->file); | |
| 3796 | char href[PATH_MAX]; | |
| 3797 | char href_encoded[PATH_MAX]; | |
| 3798 | struct mg_connection *conn = (struct mg_connection *) data; | |
| 3799 | mg_snprintf(conn, href, sizeof(href), "%s%s", | |
| 3800 | conn->request_info.uri, de->file_name); | |
| 3801 | mg_url_encode(href, href_encoded, PATH_MAX-1); | |
| 3802 | print_props(conn, href_encoded, &de->file); | |
| 3806 | 3803 | } |
| 3807 | 3804 | |
| 3808 | 3805 | static void handle_propfind(struct mg_connection *conn, const char *path, |
| 3809 | struct file *filep) { | |
| 3810 | const char *depth = mg_get_header(conn, "Depth"); | |
| 3806 | struct file *filep) { | |
| 3807 | const char *depth = mg_get_header(conn, "Depth"); | |
| 3811 | 3808 | |
| 3812 | conn->must_close = 1; | |
| 3813 | conn->status_code = 207; | |
| 3814 | mg_printf(conn, "HTTP/1.1 207 Multi-Status\r\n" | |
| 3815 | "Connection: close\r\n" | |
| 3816 | "Content-Type: text/xml; charset=utf-8\r\n\r\n"); | |
| 3809 | conn->must_close = 1; | |
| 3810 | conn->status_code = 207; | |
| 3811 | mg_printf(conn, "HTTP/1.1 207 Multi-Status\r\n" | |
| 3812 | "Connection: close\r\n" | |
| 3813 | "Content-Type: text/xml; charset=utf-8\r\n\r\n"); | |
| 3817 | 3814 | |
| 3818 | conn->num_bytes_sent += mg_printf(conn, | |
| 3819 | "<?xml version=\"1.0\" encoding=\"utf-8\"?>" | |
| 3820 | "<d:multistatus xmlns:d='DAV:'>\n"); | |
| 3815 | conn->num_bytes_sent += mg_printf(conn, | |
| 3816 | "<?xml version=\"1.0\" encoding=\"utf-8\"?>" | |
| 3817 | "<d:multistatus xmlns:d='DAV:'>\n"); | |
| 3821 | 3818 | |
| 3822 | // Print properties for the requested resource itself | |
| 3823 | print_props(conn, conn->request_info.uri, filep); | |
| 3819 | // Print properties for the requested resource itself | |
| 3820 | print_props(conn, conn->request_info.uri, filep); | |
| 3824 | 3821 | |
| 3825 | // If it is a directory, print directory entries too if Depth is not 0 | |
| 3826 | if (filep->is_directory && | |
| 3827 | !mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING], "yes") && | |
| 3828 | (depth == NULL || strcmp(depth, "0") != 0)) { | |
| 3829 | scan_directory(conn, path, conn, &print_dav_dir_entry); | |
| 3830 | } | |
| 3822 | // If it is a directory, print directory entries too if Depth is not 0 | |
| 3823 | if (filep->is_directory && | |
| 3824 | !mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING], "yes") && | |
| 3825 | (depth == NULL || strcmp(depth, "0") != 0)) { | |
| 3826 | scan_directory(conn, path, conn, &print_dav_dir_entry); | |
| 3827 | } | |
| 3831 | 3828 | |
| 3832 | ||
| 3829 | conn->num_bytes_sent += mg_printf(conn, "%s\n", "</d:multistatus>"); | |
| 3833 | 3830 | } |
| 3834 | 3831 | |
| 3835 | 3832 | #if defined(USE_WEBSOCKET) |
| r25360 | r25361 | |
| 3846 | 3843 | #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) |
| 3847 | 3844 | |
| 3848 | 3845 | static uint32_t blk0(union char64long16 *block, int i) { |
| 3849 | // Forrest: SHA expect BIG_ENDIAN, swap if LITTLE_ENDIAN | |
| 3850 | if (!is_big_endian()) { | |
| 3851 | block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | | |
| 3852 | (rol(block->l[i], 8) & 0x00FF00FF); | |
| 3853 | } | |
| 3854 | return block->l[i]; | |
| 3846 | // Forrest: SHA expect BIG_ENDIAN, swap if LITTLE_ENDIAN | |
| 3847 | if (!is_big_endian()) { | |
| 3848 | block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | | |
| 3849 | (rol(block->l[i], 8) & 0x00FF00FF); | |
| 3850 | } | |
| 3851 | return block->l[i]; | |
| 3855 | 3852 | } |
| 3856 | 3853 | |
| 3857 | 3854 | #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ |
| 3858 | ||
| 3855 | ^block->l[(i+2)&15]^block->l[i&15],1)) | |
| 3859 | 3856 | #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(block, i)+0x5A827999+rol(v,5);w=rol(w,30); |
| 3860 | 3857 | #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); |
| 3861 | 3858 | #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); |
| r25360 | r25361 | |
| 3863 | 3860 | #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); |
| 3864 | 3861 | |
| 3865 | 3862 | typedef struct { |
| 3866 | uint32_t state[5]; | |
| 3867 | uint32_t count[2]; | |
| 3868 | unsigned char buffer[64]; | |
| 3863 | uint32_t state[5]; | |
| 3864 | uint32_t count[2]; | |
| 3865 | unsigned char buffer[64]; | |
| 3869 | 3866 | } SHA1_CTX; |
| 3870 | 3867 | |
| 3871 | 3868 | static void SHA1Transform(uint32_t state[5], const unsigned char buffer[64]) { |
| 3872 | uint32_t a, b, c, d, e; | |
| 3873 | union char64long16 block[1]; | |
| 3869 | uint32_t a, b, c, d, e; | |
| 3870 | union char64long16 block[1]; | |
| 3874 | 3871 | |
| 3875 | memcpy(block, buffer, 64); | |
| 3876 | a = state[0]; | |
| 3877 | b = state[1]; | |
| 3878 | c = state[2]; | |
| 3879 | d = state[3]; | |
| 3880 | e = state[4]; | |
| 3881 | R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); | |
| 3882 | R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); | |
| 3883 | R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); | |
| 3884 | R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); | |
| 3885 | R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); | |
| 3886 | R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); | |
| 3887 | R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); | |
| 3888 | R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); | |
| 3889 | R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); | |
| 3890 | R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); | |
| 3891 | R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); | |
| 3892 | R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); | |
| 3893 | R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); | |
| 3894 | R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); | |
| 3895 | R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); | |
| 3896 | R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); | |
| 3897 | R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); | |
| 3898 | R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); | |
| 3899 | R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); | |
| 3900 | R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); | |
| 3901 | state[0] += a; | |
| 3902 | state[1] += b; | |
| 3903 | state[2] += c; | |
| 3904 | state[3] += d; | |
| 3905 | state[4] += e; | |
| 3906 | a = b = c = d = e = 0; | |
| 3907 | memset(block, '\0', sizeof(block)); | |
| 3872 | memcpy(block, buffer, 64); | |
| 3873 | a = state[0]; | |
| 3874 | b = state[1]; | |
| 3875 | c = state[2]; | |
| 3876 | d = state[3]; | |
| 3877 | e = state[4]; | |
| 3878 | R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); | |
| 3879 | R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); | |
| 3880 | R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); | |
| 3881 | R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); | |
| 3882 | R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); | |
| 3883 | R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); | |
| 3884 | R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); | |
| 3885 | R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); | |
| 3886 | R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); | |
| 3887 | R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); | |
| 3888 | R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); | |
| 3889 | R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); | |
| 3890 | R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); | |
| 3891 | R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); | |
| 3892 | R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); | |
| 3893 | R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); | |
| 3894 | R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); | |
| 3895 | R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); | |
| 3896 | R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); | |
| 3897 | R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); | |
| 3898 | state[0] += a; | |
| 3899 | state[1] += b; | |
| 3900 | state[2] += c; | |
| 3901 | state[3] += d; | |
| 3902 | state[4] += e; | |
| 3903 | a = b = c = d = e = 0; | |
| 3904 | memset(block, '\0', sizeof(block)); | |
| 3908 | 3905 | } |
| 3909 | 3906 | |
| 3910 | 3907 | static void SHA1Init(SHA1_CTX* context) { |
| 3911 | context->state[0] = 0x67452301; | |
| 3912 | context->state[1] = 0xEFCDAB89; | |
| 3913 | context->state[2] = 0x98BADCFE; | |
| 3914 | context->state[3] = 0x10325476; | |
| 3915 | context->state[4] = 0xC3D2E1F0; | |
| 3916 | context->count[0] = context->count[1] = 0; | |
| 3908 | context->state[0] = 0x67452301; | |
| 3909 | context->state[1] = 0xEFCDAB89; | |
| 3910 | context->state[2] = 0x98BADCFE; | |
| 3911 | context->state[3] = 0x10325476; | |
| 3912 | context->state[4] = 0xC3D2E1F0; | |
| 3913 | context->count[0] = context->count[1] = 0; | |
| 3917 | 3914 | } |
| 3918 | 3915 | |
| 3919 | 3916 | static void SHA1Update(SHA1_CTX* context, const unsigned char* data, |
| 3920 | uint32_t len) { | |
| 3921 | uint32_t i, j; | |
| 3917 | uint32_t len) { | |
| 3918 | uint32_t i, j; | |
| 3922 | 3919 | |
| 3923 | j = context->count[0]; | |
| 3924 | if ((context->count[0] += len << 3) < j) | |
| 3925 | context->count[1]++; | |
| 3926 | context->count[1] += (len>>29); | |
| 3927 | j = (j >> 3) & 63; | |
| 3928 | if ((j + len) > 63) { | |
| 3929 | memcpy(&context->buffer[j], data, (i = 64-j)); | |
| 3930 | SHA1Transform(context->state, context->buffer); | |
| 3931 | for ( ; i + 63 < len; i += 64) { | |
| 3932 | SHA1Transform(context->state, &data[i]); | |
| 3933 | } | |
| 3934 | j = 0; | |
| 3935 | } | |
| 3936 | else i = 0; | |
| 3937 | memcpy(&context->buffer[j], &data[i], len - i); | |
| 3920 | j = context->count[0]; | |
| 3921 | if ((context->count[0] += len << 3) < j) | |
| 3922 | context->count[1]++; | |
| 3923 | context->count[1] += (len>>29); | |
| 3924 | j = (j >> 3) & 63; | |
| 3925 | if ((j + len) > 63) { | |
| 3926 | memcpy(&context->buffer[j], data, (i = 64-j)); | |
| 3927 | SHA1Transform(context->state, context->buffer); | |
| 3928 | for ( ; i + 63 < len; i += 64) { | |
| 3929 | SHA1Transform(context->state, &data[i]); | |
| 3930 | } | |
| 3931 | j = 0; | |
| 3932 | } | |
| 3933 | else i = 0; | |
| 3934 | memcpy(&context->buffer[j], &data[i], len - i); | |
| 3938 | 3935 | } |
| 3939 | 3936 | |
| 3940 | 3937 | static void SHA1Final(unsigned char digest[20], SHA1_CTX* context) { |
| 3941 | unsigned i; | |
| 3942 | unsigned char finalcount[8], c; | |
| 3938 | unsigned i; | |
| 3939 | unsigned char finalcount[8], c; | |
| 3943 | 3940 | |
| 3944 | for (i = 0; i < 8; i++) { | |
| 3945 | finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] | |
| 3946 | >> ((3-(i & 3)) * 8) ) & 255); | |
| 3947 | } | |
| 3948 | c = 0200; | |
| 3949 | SHA1Update(context, &c, 1); | |
| 3950 | while ((context->count[0] & 504) != 448) { | |
| 3951 | c = 0000; | |
| 3952 | SHA1Update(context, &c, 1); | |
| 3953 | } | |
| 3954 | SHA1Update(context, finalcount, 8); | |
| 3955 | for (i = 0; i < 20; i++) { | |
| 3956 | digest[i] = (unsigned char) | |
| 3957 | ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); | |
| 3958 | } | |
| 3959 | memset(context, '\0', sizeof(*context)); | |
| 3960 | memset(&finalcount, '\0', sizeof(finalcount)); | |
| 3941 | for (i = 0; i < 8; i++) { | |
| 3942 | finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] | |
| 3943 | >> ((3-(i & 3)) * 8) ) & 255); | |
| 3944 | } | |
| 3945 | c = 0200; | |
| 3946 | SHA1Update(context, &c, 1); | |
| 3947 | while ((context->count[0] & 504) != 448) { | |
| 3948 | c = 0000; | |
| 3949 | SHA1Update(context, &c, 1); | |
| 3950 | } | |
| 3951 | SHA1Update(context, finalcount, 8); | |
| 3952 | for (i = 0; i < 20; i++) { | |
| 3953 | digest[i] = (unsigned char) | |
| 3954 | ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); | |
| 3955 | } | |
| 3956 | memset(context, '\0', sizeof(*context)); | |
| 3957 | memset(&finalcount, '\0', sizeof(finalcount)); | |
| 3961 | 3958 | } |
| 3962 | 3959 | // END OF SHA1 CODE |
| 3963 | 3960 | |
| 3964 | 3961 | static void base64_encode(const unsigned char *src, int src_len, char *dst) { |
| 3965 | static const char *b64 = | |
| 3966 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
| 3967 | int i, j, a, b, c; | |
| 3962 | static const char *b64 = | |
| 3963 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
| 3964 | int i, j, a, b, c; | |
| 3968 | 3965 | |
| 3969 | for (i = j = 0; i < src_len; i += 3) { | |
| 3970 | a = src[i]; | |
| 3971 | b = i + 1 >= src_len ? 0 : src[i + 1]; | |
| 3972 | c = i + 2 >= src_len ? 0 : src[i + 2]; | |
| 3966 | for (i = j = 0; i < src_len; i += 3) { | |
| 3967 | a = src[i]; | |
| 3968 | b = i + 1 >= src_len ? 0 : src[i + 1]; | |
| 3969 | c = i + 2 >= src_len ? 0 : src[i + 2]; | |
| 3973 | 3970 | |
| 3974 | dst[j++] = b64[a >> 2]; | |
| 3975 | dst[j++] = b64[((a & 3) << 4) | (b >> 4)]; | |
| 3976 | if (i + 1 < src_len) { | |
| 3977 | dst[j++] = b64[(b & 15) << 2 | (c >> 6)]; | |
| 3978 | } | |
| 3979 | if (i + 2 < src_len) { | |
| 3980 | dst[j++] = b64[c & 63]; | |
| 3981 | } | |
| 3982 | } | |
| 3983 | while (j % 4 != 0) { | |
| 3984 | dst[j++] = '='; | |
| 3985 | } | |
| 3986 | dst[j++] = '\0'; | |
| 3971 | dst[j++] = b64[a >> 2]; | |
| 3972 | dst[j++] = b64[((a & 3) << 4) | (b >> 4)]; | |
| 3973 | if (i + 1 < src_len) { | |
| 3974 | dst[j++] = b64[(b & 15) << 2 | (c >> 6)]; | |
| 3975 | } | |
| 3976 | if (i + 2 < src_len) { | |
| 3977 | dst[j++] = b64[c & 63]; | |
| 3978 | } | |
| 3979 | } | |
| 3980 | while (j % 4 != 0) { | |
| 3981 | dst[j++] = '='; | |
| 3982 | } | |
| 3983 | dst[j++] = '\0'; | |
| 3987 | 3984 | } |
| 3988 | 3985 | |
| 3989 | 3986 | static void send_websocket_handshake(struct mg_connection *conn) { |
| 3990 | static const char *magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; | |
| 3991 | char buf[100], sha[20], b64_sha[sizeof(sha) * 2]; | |
| 3992 | SHA1_CTX sha_ctx; | |
| 3987 | static const char *magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; | |
| 3988 | char buf[100], sha[20], b64_sha[sizeof(sha) * 2]; | |
| 3989 | SHA1_CTX sha_ctx; | |
| 3993 | 3990 | |
| 3994 | mg_snprintf(conn, buf, sizeof(buf), "%s%s", | |
| 3995 | mg_get_header(conn, "Sec-WebSocket-Key"), magic); | |
| 3996 | SHA1Init(&sha_ctx); | |
| 3997 | SHA1Update(&sha_ctx, (unsigned char *) buf, strlen(buf)); | |
| 3998 | SHA1Final((unsigned char *) sha, &sha_ctx); | |
| 3999 | base64_encode((unsigned char *) sha, sizeof(sha), b64_sha); | |
| 4000 | mg_printf(conn, "%s%s%s", | |
| 4001 | "HTTP/1.1 101 Switching Protocols\r\n" | |
| 4002 | "Upgrade: websocket\r\n" | |
| 4003 | "Connection: Upgrade\r\n" | |
| 4004 | "Sec-WebSocket-Accept: ", b64_sha, "\r\n\r\n"); | |
| 3991 | mg_snprintf(conn, buf, sizeof(buf), "%s%s", | |
| 3992 | mg_get_header(conn, "Sec-WebSocket-Key"), magic); | |
| 3993 | SHA1Init(&sha_ctx); | |
| 3994 | SHA1Update(&sha_ctx, (unsigned char *) buf, strlen(buf)); | |
| 3995 | SHA1Final((unsigned char *) sha, &sha_ctx); | |
| 3996 | base64_encode((unsigned char *) sha, sizeof(sha), b64_sha); | |
| 3997 | mg_printf(conn, "%s%s%s", | |
| 3998 | "HTTP/1.1 101 Switching Protocols\r\n" | |
| 3999 | "Upgrade: websocket\r\n" | |
| 4000 | "Connection: Upgrade\r\n" | |
| 4001 | "Sec-WebSocket-Accept: ", b64_sha, "\r\n\r\n"); | |
| 4005 | 4002 | } |
| 4006 | 4003 | |
| 4007 | 4004 | static void read_websocket(struct mg_connection *conn) { |
| 4008 | // Pointer to the beginning of the portion of the incoming websocket message | |
| 4009 | // queue. The original websocket upgrade request is never removed, | |
| 4010 | // so the queue begins after it. | |
| 4011 | unsigned char *buf = (unsigned char *) conn->buf + conn->request_len; | |
| 4012 | int bits, n, stop = 0; | |
| 4013 | size_t i, len, mask_len, data_len, header_len, body_len; | |
| 4014 | // data points to the place where the message is stored when passed to the | |
| 4015 | // websocket_data callback. This is either mem on the stack, | |
| 4016 | // or a dynamically allocated buffer if it is too large. | |
| 4017 | char mem[4 * 1024], mask[4], *data; | |
| 4005 | // Pointer to the beginning of the portion of the incoming websocket message | |
| 4006 | // queue. The original websocket upgrade request is never removed, | |
| 4007 | // so the queue begins after it. | |
| 4008 | unsigned char *buf = (unsigned char *) conn->buf + conn->request_len; | |
| 4009 | int bits, n, stop = 0; | |
| 4010 | size_t i, len, mask_len, data_len, header_len, body_len; | |
| 4011 | // data points to the place where the message is stored when passed to the | |
| 4012 | // websocket_data callback. This is either mem on the stack, | |
| 4013 | // or a dynamically allocated buffer if it is too large. | |
| 4014 | char mem[4 * 1024], mask[4], *data; | |
| 4018 | 4015 | |
| 4019 | ||
| 4016 | assert(conn->content_len == 0); | |
| 4020 | 4017 | |
| 4021 | // Loop continuously, reading messages from the socket, invoking the callback, | |
| 4022 | // and waiting repeatedly until an error occurs. | |
| 4023 | while (!stop) { | |
| 4024 | header_len = 0; | |
| 4025 | // body_len is the length of the entire queue in bytes | |
| 4026 | // len is the length of the current message | |
| 4027 | // data_len is the length of the current message's data payload | |
| 4028 | // header_len is the length of the current message's header | |
| 4029 | if ((body_len = conn->data_len - conn->request_len) >= 2) { | |
| 4030 | len = buf[1] & 127; | |
| 4031 | mask_len = buf[1] & 128 ? 4 : 0; | |
| 4032 | if (len < 126 && body_len >= mask_len) { | |
| 4033 | data_len = len; | |
| 4034 | header_len = 2 + mask_len; | |
| 4035 | } else if (len == 126 && body_len >= 4 + mask_len) { | |
| 4036 | header_len = 4 + mask_len; | |
| 4037 | data_len = ((((int) buf[2]) << 8) + buf[3]); | |
| 4038 | } else if (body_len >= 10 + mask_len) { | |
| 4039 | header_len = 10 + mask_len; | |
| 4040 | data_len = (((uint64_t) htonl(* (uint32_t *) &buf[2])) << 32) + | |
| 4041 | htonl(* (uint32_t *) &buf[6]); | |
| 4042 | } | |
| 4043 | } | |
| 4018 | // Loop continuously, reading messages from the socket, invoking the callback, | |
| 4019 | // and waiting repeatedly until an error occurs. | |
| 4020 | while (!stop) { | |
| 4021 | header_len = 0; | |
| 4022 | // body_len is the length of the entire queue in bytes | |
| 4023 | // len is the length of the current message | |
| 4024 | // data_len is the length of the current message's data payload | |
| 4025 | // header_len is the length of the current message's header | |
| 4026 | if ((body_len = conn->data_len - conn->request_len) >= 2) { | |
| 4027 | len = buf[1] & 127; | |
| 4028 | mask_len = buf[1] & 128 ? 4 : 0; | |
| 4029 | if (len < 126 && body_len >= mask_len) { | |
| 4030 | data_len = len; | |
| 4031 | header_len = 2 + mask_len; | |
| 4032 | } else if (len == 126 && body_len >= 4 + mask_len) { | |
| 4033 | header_len = 4 + mask_len; | |
| 4034 | data_len = ((((int) buf[2]) << 8) + buf[3]); | |
| 4035 | } else if (body_len >= 10 + mask_len) { | |
| 4036 | header_len = 10 + mask_len; | |
| 4037 | data_len = (((uint64_t) htonl(* (uint32_t *) &buf[2])) << 32) + | |
| 4038 | htonl(* (uint32_t *) &buf[6]); | |
| 4039 | } | |
| 4040 | } | |
| 4044 | 4041 | |
| 4045 | // Data layout is as follows: | |
| 4046 | // conn->buf buf | |
| 4047 | // v v frame1 | frame2 | |
| 4048 | // |---------------------|----------------|--------------|------- | |
| 4049 | // | |<--header_len-->|<--data_len-->| | |
| 4050 | // |<-conn->request_len->|<-----body_len----------->| | |
| 4051 | // |<-------------------conn->data_len------------->| | |
| 4042 | // Data layout is as follows: | |
| 4043 | // conn->buf buf | |
| 4044 | // v v frame1 | frame2 | |
| 4045 | // |---------------------|----------------|--------------|------- | |
| 4046 | // | |<--header_len-->|<--data_len-->| | |
| 4047 | // |<-conn->request_len->|<-----body_len----------->| | |
| 4048 | // |<-------------------conn->data_len------------->| | |
| 4052 | 4049 | |
| 4053 | if (header_len > 0) { | |
| 4054 | // Allocate space to hold websocket payload | |
| 4055 | data = mem; | |
| 4056 | if (data_len > sizeof(mem) && (data = (char*)malloc(data_len)) == NULL) { | |
| 4057 | // Allocation failed, exit the loop and then close the connection | |
| 4058 | // TODO: notify user about the failure | |
| 4059 | break; | |
| 4060 | } | |
| 4050 | if (header_len > 0) { | |
| 4051 | // Allocate space to hold websocket payload | |
| 4052 | data = mem; | |
| 4053 | if (data_len > sizeof(mem) && (data = (char*)malloc(data_len)) == NULL) { | |
| 4054 | // Allocation failed, exit the loop and then close the connection | |
| 4055 | // TODO: notify user about the failure | |
| 4056 | break; | |
| 4057 | } | |
| 4061 | 4058 | |
| 4062 | // Save mask and bits, otherwise it may be clobbered by memmove below | |
| 4063 | bits = buf[0]; | |
| 4064 | memcpy(mask, buf + header_len - mask_len, mask_len); | |
| 4059 | // Save mask and bits, otherwise it may be clobbered by memmove below | |
| 4060 | bits = buf[0]; | |
| 4061 | memcpy(mask, buf + header_len - mask_len, mask_len); | |
| 4065 | 4062 | |
| 4066 | // Read frame payload into the allocated buffer. | |
| 4067 | assert(body_len >= header_len); | |
| 4068 | if (data_len + header_len > body_len) { | |
| 4069 | len = body_len - header_len; | |
| 4070 | memcpy(data, buf + header_len, len); | |
| 4071 | // TODO: handle pull error | |
| 4072 | pull_all(NULL, conn, data + len, data_len - len); | |
| 4073 | conn->data_len = conn->request_len; | |
| 4074 | } else { | |
| 4075 | len = data_len + header_len; | |
| 4076 | memcpy(data, buf + header_len, data_len); | |
| 4077 | memmove(buf, buf + len, body_len - len); | |
| 4078 | conn->data_len -= len; | |
| 4079 | } | |
| 4063 | // Read frame payload into the allocated buffer. | |
| 4064 | assert(body_len >= header_len); | |
| 4065 | if (data_len + header_len > body_len) { | |
| 4066 | len = body_len - header_len; | |
| 4067 | memcpy(data, buf + header_len, len); | |
| 4068 | // TODO: handle pull error | |
| 4069 | pull_all(NULL, conn, data + len, data_len - len); | |
| 4070 | conn->data_len = conn->request_len; | |
| 4071 | } else { | |
| 4072 | len = data_len + header_len; | |
| 4073 | memcpy(data, buf + header_len, data_len); | |
| 4074 | memmove(buf, buf + len, body_len - len); | |
| 4075 | conn->data_len -= len; | |
| 4076 | } | |
| 4080 | 4077 | |
| 4081 | // Apply mask if necessary | |
| 4082 | if (mask_len > 0) { | |
| 4083 | for (i = 0; i < data_len; i++) { | |
| 4084 | data[i] ^= mask[i % 4]; | |
| 4085 | } | |
| 4086 | } | |
| 4078 | // Apply mask if necessary | |
| 4079 | if (mask_len > 0) { | |
| 4080 | for (i = 0; i < data_len; i++) { | |
| 4081 | data[i] ^= mask[i % 4]; | |
| 4082 | } | |
| 4083 | } | |
| 4087 | 4084 | |
| 4088 | // Exit the loop if callback signalled to exit, | |
| 4089 | // or "connection close" opcode received. | |
| 4090 | if ((conn->ctx->callbacks.websocket_data != NULL && | |
| 4091 | !conn->ctx->callbacks.websocket_data(conn, bits, data, data_len)) || | |
| 4092 | (bits & 0xf) == 8) { // Opcode == 8, connection close | |
| 4093 | stop = 1; | |
| 4094 | } | |
| 4085 | // Exit the loop if callback signalled to exit, | |
| 4086 | // or "connection close" opcode received. | |
| 4087 | if ((conn->ctx->callbacks.websocket_data != NULL && | |
| 4088 | !conn->ctx->callbacks.websocket_data(conn, bits, data, data_len)) || | |
| 4089 | (bits & 0xf) == 8) { // Opcode == 8, connection close | |
| 4090 | stop = 1; | |
| 4091 | } | |
| 4095 | 4092 | |
| 4096 | if (data != mem) { | |
| 4097 | free(data); | |
| 4098 | } | |
| 4099 | // Not breaking the loop, process next websocket frame. | |
| 4100 | } else { | |
| 4101 | // Buffering websocket request | |
| 4102 | if ((n = pull(NULL, conn, conn->buf + conn->data_len, | |
| 4103 | conn->buf_size - conn->data_len)) <= 0) { | |
| 4104 | break; | |
| 4105 | } | |
| 4106 | conn->data_len += n; | |
| 4107 | } | |
| 4108 | } | |
| 4093 | if (data != mem) { | |
| 4094 | free(data); | |
| 4095 | } | |
| 4096 | // Not breaking the loop, process next websocket frame. | |
| 4097 | } else { | |
| 4098 | // Buffering websocket request | |
| 4099 | if ((n = pull(NULL, conn, conn->buf + conn->data_len, | |
| 4100 | conn->buf_size - conn->data_len)) <= 0) { | |
| 4101 | break; | |
| 4102 | } | |
| 4103 | conn->data_len += n; | |
| 4104 | } | |
| 4105 | } | |
| 4109 | 4106 | } |
| 4110 | 4107 | |
| 4111 | 4108 | int mg_websocket_write(struct mg_connection* conn, int opcode, |
| 4112 | const char *data, size_t data_len) { | |
| 4113 | unsigned char *copy; | |
| 4114 | size_t copy_len = 0; | |
| 4115 | int retval = -1; | |
| 4109 | const char *data, size_t data_len) { | |
| 4110 | unsigned char *copy; | |
| 4111 | size_t copy_len = 0; | |
| 4112 | int retval = -1; | |
| 4116 | 4113 | |
| 4117 | if ((copy = (unsigned char *) malloc(data_len + 10)) == NULL) { | |
| 4118 | return -1; | |
| 4119 | } | |
| 4114 | if ((copy = (unsigned char *) malloc(data_len + 10)) == NULL) { | |
| 4115 | return -1; | |
| 4116 | } | |
| 4120 | 4117 | |
| 4121 | ||
| 4118 | copy[0] = 0x80 + (opcode & 0x0f); | |
| 4122 | 4119 | |
| 4123 | // Frame format: http://tools.ietf.org/html/rfc6455#section-5.2 | |
| 4124 | if (data_len < 126) { | |
| 4125 | // Inline 7-bit length field | |
| 4126 | copy[1] = data_len; | |
| 4127 | memcpy(copy + 2, data, data_len); | |
| 4128 | copy_len = 2 + data_len; | |
| 4129 | } else if (data_len <= 0xFFFF) { | |
| 4130 | // 16-bit length field | |
| 4131 | copy[1] = 126; | |
| 4132 | * (uint16_t *) (copy + 2) = htons(data_len); | |
| 4133 | memcpy(copy + 4, data, data_len); | |
| 4134 | copy_len = 4 + data_len; | |
| 4135 | } else { | |
| 4136 | // 64-bit length field | |
| 4137 | copy[1] = 127; | |
| 4138 | * (uint32_t *) (copy + 2) = htonl((uint64_t) data_len >> 32); | |
| 4139 | * (uint32_t *) (copy + 6) = htonl(data_len & 0xffffffff); | |
| 4140 | memcpy(copy + 10, data, data_len); | |
| 4141 | copy_len = 10 + data_len; | |
| 4142 | } | |
| 4120 | // Frame format: http://tools.ietf.org/html/rfc6455#section-5.2 | |
| 4121 | if (data_len < 126) { | |
| 4122 | // Inline 7-bit length field | |
| 4123 | copy[1] = data_len; | |
| 4124 | memcpy(copy + 2, data, data_len); | |
| 4125 | copy_len = 2 + data_len; | |
| 4126 | } else if (data_len <= 0xFFFF) { | |
| 4127 | // 16-bit length field | |
| 4128 | copy[1] = 126; | |
| 4129 | * (uint16_t *) (copy + 2) = htons(data_len); | |
| 4130 | memcpy(copy + 4, data, data_len); | |
| 4131 | copy_len = 4 + data_len; | |
| 4132 | } else { | |
| 4133 | // 64-bit length field | |
| 4134 | copy[1] = 127; | |
| 4135 | * (uint32_t *) (copy + 2) = htonl((uint64_t) data_len >> 32); | |
| 4136 | * (uint32_t *) (copy + 6) = htonl(data_len & 0xffffffff); | |
| 4137 | memcpy(copy + 10, data, data_len); | |
| 4138 | copy_len = 10 + data_len; | |
| 4139 | } | |
| 4143 | 4140 | |
| 4144 | // Not thread safe | |
| 4145 | if (copy_len > 0) { | |
| 4146 | retval = mg_write(conn, copy, copy_len); | |
| 4147 | } | |
| 4148 | free(copy); | |
| 4141 | // Not thread safe | |
| 4142 | if (copy_len > 0) { | |
| 4143 | retval = mg_write(conn, copy, copy_len); | |
| 4144 | } | |
| 4145 | free(copy); | |
| 4149 | 4146 | |
| 4150 | ||
| 4147 | return retval; | |
| 4151 | 4148 | } |
| 4152 | 4149 | |
| 4153 | 4150 | static void handle_websocket_request(struct mg_connection *conn) { |
| 4154 | const char *version = mg_get_header(conn, "Sec-WebSocket-Version"); | |
| 4155 | if (version == NULL || strcmp(version, "13") != 0) { | |
| 4156 | send_http_error(conn, 426, "Upgrade Required", "%s", "Upgrade Required"); | |
| 4157 | } else if (conn->ctx->callbacks.websocket_connect != NULL && | |
| 4158 | conn->ctx->callbacks.websocket_connect(conn) != 0) { | |
| 4159 | // Callback has returned non-zero, do not proceed with handshake | |
| 4160 | } else { | |
| 4161 | send_websocket_handshake(conn); | |
| 4162 | if (conn->ctx->callbacks.websocket_ready != NULL) { | |
| 4163 | conn->ctx->callbacks.websocket_ready(conn); | |
| 4164 | } | |
| 4165 | read_websocket(conn); | |
| 4166 | } | |
| 4151 | const char *version = mg_get_header(conn, "Sec-WebSocket-Version"); | |
| 4152 | if (version == NULL || strcmp(version, "13") != 0) { | |
| 4153 | send_http_error(conn, 426, "Upgrade Required", "%s", "Upgrade Required"); | |
| 4154 | } else if (conn->ctx->callbacks.websocket_connect != NULL && | |
| 4155 | conn->ctx->callbacks.websocket_connect(conn) != 0) { | |
| 4156 | // Callback has returned non-zero, do not proceed with handshake | |
| 4157 | } else { | |
| 4158 | send_websocket_handshake(conn); | |
| 4159 | if (conn->ctx->callbacks.websocket_ready != NULL) { | |
| 4160 | conn->ctx->callbacks.websocket_ready(conn); | |
| 4161 | } | |
| 4162 | read_websocket(conn); | |
| 4163 | } | |
| 4167 | 4164 | } |
| 4168 | 4165 | |
| 4169 | 4166 | static int is_websocket_request(const struct mg_connection *conn) { |
| 4170 | ||
| 4167 | const char *host, *upgrade, *connection, *version, *key; | |
| 4171 | 4168 | |
| 4172 | host = mg_get_header(conn, "Host"); | |
| 4173 | upgrade = mg_get_header(conn, "Upgrade"); | |
| 4174 | connection = mg_get_header(conn, "Connection"); | |
| 4175 | key = mg_get_header(conn, "Sec-WebSocket-Key"); | |
| 4176 | version = mg_get_header(conn, "Sec-WebSocket-Version"); | |
| 4169 | host = mg_get_header(conn, "Host"); | |
| 4170 | upgrade = mg_get_header(conn, "Upgrade"); | |
| 4171 | connection = mg_get_header(conn, "Connection"); | |
| 4172 | key = mg_get_header(conn, "Sec-WebSocket-Key"); | |
| 4173 | version = mg_get_header(conn, "Sec-WebSocket-Version"); | |
| 4177 | 4174 | |
| 4178 | return host != NULL && upgrade != NULL && connection != NULL && | |
| 4179 | key != NULL && version != NULL && | |
| 4180 | mg_strcasestr(upgrade, "websocket") != NULL && | |
| 4181 | mg_strcasestr(connection, "Upgrade") != NULL; | |
| 4175 | return host != NULL && upgrade != NULL && connection != NULL && | |
| 4176 | key != NULL && version != NULL && | |
| 4177 | mg_strcasestr(upgrade, "websocket") != NULL && | |
| 4178 | mg_strcasestr(connection, "Upgrade") != NULL; | |
| 4182 | 4179 | } |
| 4183 | 4180 | #endif // !USE_WEBSOCKET |
| 4184 | 4181 | |
| 4185 | 4182 | static int isbyte(int n) { |
| 4186 | ||
| 4183 | return n >= 0 && n <= 255; | |
| 4187 | 4184 | } |
| 4188 | 4185 | |
| 4189 | 4186 | static int parse_net(const char *spec, uint32_t *net, uint32_t *mask) { |
| 4190 | ||
| 4187 | int n, a, b, c, d, slash = 32, len = 0; | |
| 4191 | 4188 | |
| 4192 | if ((sscanf(spec, "%d.%d.%d.%d/%d%n", &a, &b, &c, &d, &slash, &n) == 5 || | |
| 4193 | sscanf(spec, "%d.%d.%d.%d%n", &a, &b, &c, &d, &n) == 4) && | |
| 4194 | isbyte(a) && isbyte(b) && isbyte(c) && isbyte(d) && | |
| 4195 | slash >= 0 && slash < 33) { | |
| 4196 | len = n; | |
| 4197 | *net = ((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8) | d; | |
| 4198 | *mask = slash ? 0xffffffffU << (32 - slash) : 0; | |
| 4199 | } | |
| 4189 | if ((sscanf(spec, "%d.%d.%d.%d/%d%n", &a, &b, &c, &d, &slash, &n) == 5 || | |
| 4190 | sscanf(spec, "%d.%d.%d.%d%n", &a, &b, &c, &d, &n) == 4) && | |
| 4191 | isbyte(a) && isbyte(b) && isbyte(c) && isbyte(d) && | |
| 4192 | slash >= 0 && slash < 33) { | |
| 4193 | len = n; | |
| 4194 | *net = ((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8) | d; | |
| 4195 | *mask = slash ? 0xffffffffU << (32 - slash) : 0; | |
| 4196 | } | |
| 4200 | 4197 | |
| 4201 | ||
| 4198 | return len; | |
| 4202 | 4199 | } |
| 4203 | 4200 | |
| 4204 | 4201 | static int set_throttle(const char *spec, uint32_t remote_ip, const char *uri) { |
| 4205 | int throttle = 0; | |
| 4206 | struct vec vec, val; | |
| 4207 | uint32_t net, mask; | |
| 4208 | char mult; | |
| 4209 | double v; | |
| 4202 | int throttle = 0; | |
| 4203 | struct vec vec, val; | |
| 4204 | uint32_t net, mask; | |
| 4205 | char mult; | |
| 4206 | double v; | |
| 4210 | 4207 | |
| 4211 | while ((spec = next_option(spec, &vec, &val)) != NULL) { | |
| 4212 | mult = ','; | |
| 4213 | if (sscanf(val.ptr, "%lf%c", &v, &mult) < 1 || v < 0 || | |
| 4214 | (lowercase(&mult) != 'k' && lowercase(&mult) != 'm' && mult != ',')) { | |
| 4215 | continue; | |
| 4216 | } | |
| 4217 | v *= lowercase(&mult) == 'k' ? 1024 : lowercase(&mult) == 'm' ? 1048576 : 1; | |
| 4218 | if (vec.len == 1 && vec.ptr[0] == '*') { | |
| 4219 | throttle = (int) v; | |
| 4220 | } else if (parse_net(vec.ptr, &net, &mask) > 0) { | |
| 4221 | if ((remote_ip & mask) == net) { | |
| 4222 | throttle = (int) v; | |
| 4223 | } | |
| 4224 | } else if (match_prefix(vec.ptr, vec.len, uri) > 0) { | |
| 4225 | throttle = (int) v; | |
| 4226 | } | |
| 4227 | } | |
| 4208 | while ((spec = next_option(spec, &vec, &val)) != NULL) { | |
| 4209 | mult = ','; | |
| 4210 | if (sscanf(val.ptr, "%lf%c", &v, &mult) < 1 || v < 0 || | |
| 4211 | (lowercase(&mult) != 'k' && lowercase(&mult) != 'm' && mult != ',')) { | |
| 4212 | continue; | |
| 4213 | } | |
| 4214 | v *= lowercase(&mult) == 'k' ? 1024 : lowercase(&mult) == 'm' ? 1048576 : 1; | |
| 4215 | if (vec.len == 1 && vec.ptr[0] == '*') { | |
| 4216 | throttle = (int) v; | |
| 4217 | } else if (parse_net(vec.ptr, &net, &mask) > 0) { | |
| 4218 | if ((remote_ip & mask) == net) { | |
| 4219 | throttle = (int) v; | |
| 4220 | } | |
| 4221 | } else if (match_prefix(vec.ptr, vec.len, uri) > 0) { | |
| 4222 | throttle = (int) v; | |
| 4223 | } | |
| 4224 | } | |
| 4228 | 4225 | |
| 4229 | ||
| 4226 | return throttle; | |
| 4230 | 4227 | } |
| 4231 | 4228 | |
| 4232 | 4229 | static uint32_t get_remote_ip(const struct mg_connection *conn) { |
| 4233 | ||
| 4230 | return ntohl(* (uint32_t *) &conn->client.rsa.sin.sin_addr); | |
| 4234 | 4231 | } |
| 4235 | 4232 | |
| 4236 | 4233 | #ifdef USE_LUA |
| r25360 | r25361 | |
| 4238 | 4235 | #endif // USE_LUA |
| 4239 | 4236 | |
| 4240 | 4237 | int mg_upload(struct mg_connection *conn, const char *destination_dir) { |
| 4241 | const char *content_type_header, *boundary_start; | |
| 4242 | char buf[MG_BUF_LEN], path[PATH_MAX], fname[1024], boundary[100], *s; | |
| 4243 | FILE *fp; | |
| 4244 | int bl, n, i, j, headers_len, boundary_len, eof, | |
| 4245 | len = 0, num_uploaded_files = 0; | |
| 4238 | const char *content_type_header, *boundary_start; | |
| 4239 | char buf[MG_BUF_LEN], path[PATH_MAX], fname[1024], boundary[100], *s; | |
| 4240 | FILE *fp; | |
| 4241 | int bl, n, i, j, headers_len, boundary_len, eof, | |
| 4242 | len = 0, num_uploaded_files = 0; | |
| 4246 | 4243 | |
| 4247 | // Request looks like this: | |
| 4248 | // | |
| 4249 | // POST /upload HTTP/1.1 | |
| 4250 | // Host: 127.0.0.1:8080 | |
| 4251 | // Content-Length: 244894 | |
| 4252 | // Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryRVr | |
| 4253 | // | |
| 4254 | // ------WebKitFormBoundaryRVr | |
| 4255 | // Content-Disposition: form-data; name="file"; filename="accum.png" | |
| 4256 | // Content-Type: image/png | |
| 4257 | // | |
| 4258 | // <89>PNG | |
| 4259 | // <PNG DATA> | |
| 4260 | // ------WebKitFormBoundaryRVr | |
| 4244 | // Request looks like this: | |
| 4245 | // | |
| 4246 | // POST /upload HTTP/1.1 | |
| 4247 | // Host: 127.0.0.1:8080 | |
| 4248 | // Content-Length: 244894 | |
| 4249 | // Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryRVr | |
| 4250 | // | |
| 4251 | // ------WebKitFormBoundaryRVr | |
| 4252 | // Content-Disposition: form-data; name="file"; filename="accum.png" | |
| 4253 | // Content-Type: image/png | |
| 4254 | // | |
| 4255 | // <89>PNG | |
| 4256 | // <PNG DATA> | |
| 4257 | // ------WebKitFormBoundaryRVr | |
| 4261 | 4258 | |
| 4262 | // Extract boundary string from the Content-Type header | |
| 4263 | if ((content_type_header = mg_get_header(conn, "Content-Type")) == NULL || | |
| 4264 | (boundary_start = mg_strcasestr(content_type_header, | |
| 4265 | "boundary=")) == NULL || | |
| 4266 | (sscanf(boundary_start, "boundary=\"%99[^\"]\"", boundary) == 0 && | |
| 4267 | sscanf(boundary_start, "boundary=%99s", boundary) == 0) || | |
| 4268 | boundary[0] == '\0') { | |
| 4269 | return num_uploaded_files; | |
| 4270 | } | |
| 4259 | // Extract boundary string from the Content-Type header | |
| 4260 | if ((content_type_header = mg_get_header(conn, "Content-Type")) == NULL || | |
| 4261 | (boundary_start = mg_strcasestr(content_type_header, | |
| 4262 | "boundary=")) == NULL || | |
| 4263 | (sscanf(boundary_start, "boundary=\"%99[^\"]\"", boundary) == 0 && | |
| 4264 | sscanf(boundary_start, "boundary=%99s", boundary) == 0) || | |
| 4265 | boundary[0] == '\0') { | |
| 4266 | return num_uploaded_files; | |
| 4267 | } | |
| 4271 | 4268 | |
| 4272 | boundary_len = strlen(boundary); | |
| 4273 | bl = boundary_len + 4; // \r\n--<boundary> | |
| 4274 | for (;;) { | |
| 4275 | // Pull in headers | |
| 4276 | assert(len >= 0 && len <= (int) sizeof(buf)); | |
| 4277 | while ((n = mg_read(conn, buf + len, sizeof(buf) - len)) > 0) { | |
| 4278 | len += n; | |
| 4279 | } | |
| 4280 | if ((headers_len = get_request_len(buf, len)) <= 0) { | |
| 4281 | break; | |
| 4282 | } | |
| 4269 | boundary_len = strlen(boundary); | |
| 4270 | bl = boundary_len + 4; // \r\n--<boundary> | |
| 4271 | for (;;) { | |
| 4272 | // Pull in headers | |
| 4273 | assert(len >= 0 && len <= (int) sizeof(buf)); | |
| 4274 | while ((n = mg_read(conn, buf + len, sizeof(buf) - len)) > 0) { | |
| 4275 | len += n; | |
| 4276 | } | |
| 4277 | if ((headers_len = get_request_len(buf, len)) <= 0) { | |
| 4278 | break; | |
| 4279 | } | |
| 4283 | 4280 | |
| 4284 | // Fetch file name. | |
| 4285 | fname[0] = '\0'; | |
| 4286 | for (i = j = 0; i < headers_len; i++) { | |
| 4287 | if (buf[i] == '\r' && buf[i + 1] == '\n') { | |
| 4288 | buf[i] = buf[i + 1] = '\0'; | |
| 4289 | // TODO(lsm): don't expect filename to be the 3rd field, | |
| 4290 | // parse the header properly instead. | |
| 4291 | sscanf(&buf[j], "Content-Disposition: %*s %*s filename=\"%1023[^\"]", | |
| 4292 | fname); | |
| 4293 | j = i + 2; | |
| 4294 | } | |
| 4295 | } | |
| 4281 | // Fetch file name. | |
| 4282 | fname[0] = '\0'; | |
| 4283 | for (i = j = 0; i < headers_len; i++) { | |
| 4284 | if (buf[i] == '\r' && buf[i + 1] == '\n') { | |
| 4285 | buf[i] = buf[i + 1] = '\0'; | |
| 4286 | // TODO(lsm): don't expect filename to be the 3rd field, | |
| 4287 | // parse the header properly instead. | |
| 4288 | sscanf(&buf[j], "Content-Disposition: %*s %*s filename=\"%1023[^\"]", | |
| 4289 | fname); | |
| 4290 | j = i + 2; | |
| 4291 | } | |
| 4292 | } | |
| 4296 | 4293 | |
| 4297 | // Give up if the headers are not what we expect | |
| 4298 | if (fname[0] == '\0') { | |
| 4299 | break; | |
| 4300 | } | |
| 4294 | // Give up if the headers are not what we expect | |
| 4295 | if (fname[0] == '\0') { | |
| 4296 | break; | |
| 4297 | } | |
| 4301 | 4298 | |
| 4302 | // Move data to the beginning of the buffer | |
| 4303 | assert(len >= headers_len); | |
| 4304 | memmove(buf, &buf[headers_len], len - headers_len); | |
| 4305 | len -= headers_len; | |
| 4299 | // Move data to the beginning of the buffer | |
| 4300 | assert(len >= headers_len); | |
| 4301 | memmove(buf, &buf[headers_len], len - headers_len); | |
| 4302 | len -= headers_len; | |
| 4306 | 4303 | |
| 4307 | // We open the file with exclusive lock held. This guarantee us | |
| 4308 | // there is no other thread can save into the same file simultaneously. | |
| 4309 | fp = NULL; | |
| 4310 | // Construct destination file name. Do not allow paths to have slashes. | |
| 4311 | if ((s = strrchr(fname, '/')) == NULL && | |
| 4304 | // We open the file with exclusive lock held. This guarantee us | |
| 4305 | // there is no other thread can save into the same file simultaneously. | |
| 4306 | fp = NULL; | |
| 4307 | // Construct destination file name. Do not allow paths to have slashes. | |
| 4308 | if ((s = strrchr(fname, '/')) == NULL && | |
| 4312 | 4309 | (s = strrchr(fname, '\\')) == NULL) { |
| 4313 | s = fname; | |
| 4314 | } | |
| 4310 | s = fname; | |
| 4311 | } | |
| 4315 | 4312 | |
| 4316 | // Open file in binary mode. TODO: set an exclusive lock. | |
| 4317 | snprintf(path, sizeof(path), "%s/%s", destination_dir, s); | |
| 4318 | if ((fp = fopen(path, "wb")) == NULL) { | |
| 4319 | break; | |
| 4320 | } | |
| 4313 | // Open file in binary mode. TODO: set an exclusive lock. | |
| 4314 | snprintf(path, sizeof(path), "%s/%s", destination_dir, s); | |
| 4315 | if ((fp = fopen(path, "wb")) == NULL) { | |
| 4316 | break; | |
| 4317 | } | |
| 4321 | 4318 | |
| 4322 | // Read POST data, write into file until boundary is found. | |
| 4323 | eof = n = 0; | |
| 4324 | do { | |
| 4325 | len += n; | |
| 4326 | for (i = 0; i < len - bl; i++) { | |
| 4327 | if (!memcmp(&buf[i], "\r\n--", 4) && | |
| 4328 | !memcmp(&buf[i + 4], boundary, boundary_len)) { | |
| 4329 | // Found boundary, that's the end of file data. | |
| 4330 | fwrite(buf, 1, i, fp); | |
| 4331 | eof = 1; | |
| 4332 | memmove(buf, &buf[i + bl], len - (i + bl)); | |
| 4333 | len -= i + bl; | |
| 4334 | break; | |
| 4335 | } | |
| 4336 | } | |
| 4337 | if (!eof && len > bl) { | |
| 4338 | fwrite(buf, 1, len - bl, fp); | |
| 4339 | memmove(buf, &buf[len - bl], bl); | |
| 4340 | len = bl; | |
| 4341 | } | |
| 4342 | } while (!eof && (n = mg_read(conn, buf + len, sizeof(buf) - len)) > 0); | |
| 4343 | fclose(fp); | |
| 4344 | if (eof) { | |
| 4345 | num_uploaded_files++; | |
| 4346 | if (conn->ctx->callbacks.upload != NULL) { | |
| 4347 | conn->ctx->callbacks.upload(conn, path); | |
| 4348 | } | |
| 4349 | } | |
| 4350 | } | |
| 4319 | // Read POST data, write into file until boundary is found. | |
| 4320 | eof = n = 0; | |
| 4321 | do { | |
| 4322 | len += n; | |
| 4323 | for (i = 0; i < len - bl; i++) { | |
| 4324 | if (!memcmp(&buf[i], "\r\n--", 4) && | |
| 4325 | !memcmp(&buf[i + 4], boundary, boundary_len)) { | |
| 4326 | // Found boundary, that's the end of file data. | |
| 4327 | fwrite(buf, 1, i, fp); | |
| 4328 | eof = 1; | |
| 4329 | memmove(buf, &buf[i + bl], len - (i + bl)); | |
| 4330 | len -= i + bl; | |
| 4331 | break; | |
| 4332 | } | |
| 4333 | } | |
| 4334 | if (!eof && len > bl) { | |
| 4335 | fwrite(buf, 1, len - bl, fp); | |
| 4336 | memmove(buf, &buf[len - bl], bl); | |
| 4337 | len = bl; | |
| 4338 | } | |
| 4339 | } while (!eof && (n = mg_read(conn, buf + len, sizeof(buf) - len)) > 0); | |
| 4340 | fclose(fp); | |
| 4341 | if (eof) { | |
| 4342 | num_uploaded_files++; | |
| 4343 | if (conn->ctx->callbacks.upload != NULL) { | |
| 4344 | conn->ctx->callbacks.upload(conn, path); | |
| 4345 | } | |
| 4346 | } | |
| 4347 | } | |
| 4351 | 4348 | |
| 4352 | ||
| 4349 | return num_uploaded_files; | |
| 4353 | 4350 | } |
| 4354 | 4351 | |
| 4355 | 4352 | static int is_put_or_delete_request(const struct mg_connection *conn) { |
| 4356 | const char *s = conn->request_info.request_method; | |
| 4357 | return s != NULL && (!strcmp(s, "PUT") || !strcmp(s, "DELETE") || !strcmp(s, "MKCOL")); | |
| 4353 | const char *s = conn->request_info.request_method; | |
| 4354 | return s != NULL && (!strcmp(s, "PUT") || !strcmp(s, "DELETE") || !strcmp(s, "MKCOL")); | |
| 4358 | 4355 | } |
| 4359 | 4356 | |
| 4360 | 4357 | static int get_first_ssl_listener_index(const struct mg_context *ctx) { |
| 4361 | int i, index = -1; | |
| 4362 | for (i = 0; index == -1 && i < ctx->num_listening_sockets; i++) { | |
| 4363 | index = ctx->listening_sockets[i].is_ssl ? i : -1; | |
| 4364 | } | |
| 4365 | return index; | |
| 4358 | int i, index = -1; | |
| 4359 | for (i = 0; index == -1 && i < ctx->num_listening_sockets; i++) { | |
| 4360 | index = ctx->listening_sockets[i].is_ssl ? i : -1; | |
| 4361 | } | |
| 4362 | return index; | |
| 4366 | 4363 | } |
| 4367 | 4364 | |
| 4368 | 4365 | static void redirect_to_https_port(struct mg_connection *conn, int ssl_index) { |
| 4369 | char host[1025]; | |
| 4370 | const char *host_header; | |
| 4366 | char host[1025]; | |
| 4367 | const char *host_header; | |
| 4371 | 4368 | |
| 4372 | if ((host_header = mg_get_header(conn, "Host")) == NULL || | |
| 4373 | sscanf(host_header, "%1024[^:]", host) == 0) { | |
| 4374 | // Cannot get host from the Host: header. Fallback to our IP address. | |
| 4375 | sockaddr_to_string(host, sizeof(host), &conn->client.lsa); | |
| 4376 | } | |
| 4369 | if ((host_header = mg_get_header(conn, "Host")) == NULL || | |
| 4370 | sscanf(host_header, "%1024[^:]", host) == 0) { | |
| 4371 | // Cannot get host from the Host: header. Fallback to our IP address. | |
| 4372 | sockaddr_to_string(host, sizeof(host), &conn->client.lsa); | |
| 4373 | } | |
| 4377 | 4374 | |
| 4378 | mg_printf(conn, "HTTP/1.1 302 Found\r\nLocation: https://%s:%d%s\r\n\r\n", | |
| 4379 | host, (int) ntohs(conn->ctx->listening_sockets[ssl_index]. | |
| 4380 | lsa.sin.sin_port), conn->request_info.uri); | |
| 4375 | mg_printf(conn, "HTTP/1.1 302 Found\r\nLocation: https://%s:%d%s\r\n\r\n", | |
| 4376 | host, (int) ntohs(conn->ctx->listening_sockets[ssl_index]. | |
| 4377 | lsa.sin.sin_port), conn->request_info.uri); | |
| 4381 | 4378 | } |
| 4382 | 4379 | |
| 4383 | 4380 | // This is the heart of the Mongoose's logic. |
| r25360 | r25361 | |
| 4385 | 4382 | // and Mongoose must decide what action to take: serve a file, or |
| 4386 | 4383 | // a directory, or call embedded function, etcetera. |
| 4387 | 4384 | static void handle_request(struct mg_connection *conn) { |
| 4388 | struct mg_request_info *ri = &conn->request_info; | |
| 4389 | char path[PATH_MAX]; | |
| 4390 | int uri_len, ssl_index; | |
| 4391 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 4385 | struct mg_request_info *ri = &conn->request_info; | |
| 4386 | char path[PATH_MAX]; | |
| 4387 | int uri_len, ssl_index; | |
| 4388 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 4392 | 4389 | |
| 4393 | if ((conn->request_info.query_string = strchr(ri->uri, '?')) != NULL) { | |
| 4394 | * ((char *) conn->request_info.query_string++) = '\0'; | |
| 4395 | } | |
| 4396 | uri_len = (int) strlen(ri->uri); | |
| 4397 | mg_url_decode(ri->uri, uri_len, (char *) ri->uri, uri_len + 1, 0); | |
| 4398 | remove_double_dots_and_double_slashes((char *) ri->uri); | |
| 4399 | convert_uri_to_file_name(conn, path, sizeof(path), &file); | |
| 4400 | conn->throttle = set_throttle(conn->ctx->config[THROTTLE], | |
| 4401 | get_remote_ip(conn), ri->uri); | |
| 4390 | if ((conn->request_info.query_string = strchr(ri->uri, '?')) != NULL) { | |
| 4391 | * ((char *) conn->request_info.query_string++) = '\0'; | |
| 4392 | } | |
| 4393 | uri_len = (int) strlen(ri->uri); | |
| 4394 | mg_url_decode(ri->uri, uri_len, (char *) ri->uri, uri_len + 1, 0); | |
| 4395 | remove_double_dots_and_double_slashes((char *) ri->uri); | |
| 4396 | convert_uri_to_file_name(conn, path, sizeof(path), &file); | |
| 4397 | conn->throttle = set_throttle(conn->ctx->config[THROTTLE], | |
| 4398 | get_remote_ip(conn), ri->uri); | |
| 4402 | 4399 | |
| 4403 | DEBUG_TRACE(("%s", ri->uri)); | |
| 4404 | // Perform redirect and auth checks before calling begin_request() handler. | |
| 4405 | // Otherwise, begin_request() would need to perform auth checks and redirects. | |
| 4406 | if (!conn->client.is_ssl && conn->client.ssl_redir && | |
| 4407 | (ssl_index = get_first_ssl_listener_index(conn->ctx)) > -1) { | |
| 4408 | redirect_to_https_port(conn, ssl_index); | |
| 4409 | } else if (!is_put_or_delete_request(conn) && | |
| 4410 | !check_authorization(conn, path)) { | |
| 4411 | send_authorization_request(conn); | |
| 4412 | } else if (conn->ctx->callbacks.begin_request != NULL && | |
| 4413 | conn->ctx->callbacks.begin_request(conn)) { | |
| 4414 | // Do nothing, callback has served the request | |
| 4400 | DEBUG_TRACE(("%s", ri->uri)); | |
| 4401 | // Perform redirect and auth checks before calling begin_request() handler. | |
| 4402 | // Otherwise, begin_request() would need to perform auth checks and redirects. | |
| 4403 | if (!conn->client.is_ssl && conn->client.ssl_redir && | |
| 4404 | (ssl_index = get_first_ssl_listener_index(conn->ctx)) > -1) { | |
| 4405 | redirect_to_https_port(conn, ssl_index); | |
| 4406 | } else if (!is_put_or_delete_request(conn) && | |
| 4407 | !check_authorization(conn, path)) { | |
| 4408 | send_authorization_request(conn); | |
| 4409 | } else if (conn->ctx->callbacks.begin_request != NULL && | |
| 4410 | conn->ctx->callbacks.begin_request(conn)) { | |
| 4411 | // Do nothing, callback has served the request | |
| 4415 | 4412 | #if defined(USE_WEBSOCKET) |
| 4416 | } else if (is_websocket_request(conn)) { | |
| 4417 | handle_websocket_request(conn); | |
| 4413 | } else if (is_websocket_request(conn)) { | |
| 4414 | handle_websocket_request(conn); | |
| 4418 | 4415 | #endif |
| 4419 | } else if (!strcmp(ri->request_method, "OPTIONS")) { | |
| 4420 | send_options(conn); | |
| 4421 | } else if (conn->ctx->config[DOCUMENT_ROOT] == NULL) { | |
| 4422 | send_http_error(conn, 404, "Not Found", "Not Found"); | |
| 4423 | } else if (is_put_or_delete_request(conn) && | |
| 4424 | (is_authorized_for_put(conn) != 1)) { | |
| 4425 | send_authorization_request(conn); | |
| 4426 | } else if (!strcmp(ri->request_method, "PUT")) { | |
| 4427 | put_file(conn, path); | |
| 4428 | } else if (!strcmp(ri->request_method, "MKCOL")) { | |
| 4429 | mkcol(conn, path); | |
| 4430 | } else if (!strcmp(ri->request_method, "DELETE")) { | |
| 4431 | struct de de; | |
| 4432 | memset(&de.file, 0, sizeof(de.file)); | |
| 4433 | if(!mg_stat(conn, path, &de.file)) { | |
| 4434 | send_http_error(conn, 404, "Not Found", "%s", "File not found"); | |
| 4435 | } else { | |
| 4436 | if(de.file.modification_time) { | |
| 4437 | if(de.file.is_directory) { | |
| 4438 | remove_directory(conn, path); | |
| 4439 | send_http_error(conn, 204, "No Content", "%s", ""); | |
| 4440 | } else if (mg_remove(path) == 0) { | |
| 4441 | send_http_error(conn, 204, "No Content", "%s", ""); | |
| 4442 | } else { | |
| 4443 | send_http_error(conn, 423, "Locked", "remove(%s): %s", path, | |
| 4444 | strerror(ERRNO)); | |
| 4445 | } | |
| 4446 | } | |
| 4447 | else { | |
| 4448 | send_http_error(conn, 500, http_500_error, "remove(%s): %s", path, | |
| 4449 | strerror(ERRNO)); | |
| 4450 | } | |
| 4451 | } | |
| 4452 | } else if ((file.membuf == NULL && file.modification_time == (time_t) 0) || | |
| 4453 | must_hide_file(conn, path)) { | |
| 4454 | send_http_error(conn, 404, "Not Found", "%s", "File not found"); | |
| 4455 | } else if (file.is_directory && ri->uri[uri_len - 1] != '/') { | |
| 4456 | mg_printf(conn, "HTTP/1.1 301 Moved Permanently\r\n" | |
| 4457 | "Location: %s/\r\n\r\n", ri->uri); | |
| 4458 | } else if (!strcmp(ri->request_method, "PROPFIND")) { | |
| 4459 | handle_propfind(conn, path, &file); | |
| 4460 | } else if (file.is_directory && | |
| 4461 | !substitute_index_file(conn, path, sizeof(path), &file)) { | |
| 4462 | if (!mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING], "yes")) { | |
| 4463 | handle_directory_request(conn, path); | |
| 4464 | } else { | |
| 4465 | send_http_error(conn, 403, "Directory Listing Denied", | |
| 4466 | "Directory listing denied"); | |
| 4467 | } | |
| 4416 | } else if (!strcmp(ri->request_method, "OPTIONS")) { | |
| 4417 | send_options(conn); | |
| 4418 | } else if (conn->ctx->config[DOCUMENT_ROOT] == NULL) { | |
| 4419 | send_http_error(conn, 404, "Not Found", "Not Found"); | |
| 4420 | } else if (is_put_or_delete_request(conn) && | |
| 4421 | (is_authorized_for_put(conn) != 1)) { | |
| 4422 | send_authorization_request(conn); | |
| 4423 | } else if (!strcmp(ri->request_method, "PUT")) { | |
| 4424 | put_file(conn, path); | |
| 4425 | } else if (!strcmp(ri->request_method, "MKCOL")) { | |
| 4426 | mkcol(conn, path); | |
| 4427 | } else if (!strcmp(ri->request_method, "DELETE")) { | |
| 4428 | struct de de; | |
| 4429 | memset(&de.file, 0, sizeof(de.file)); | |
| 4430 | if(!mg_stat(conn, path, &de.file)) { | |
| 4431 | send_http_error(conn, 404, "Not Found", "%s", "File not found"); | |
| 4432 | } else { | |
| 4433 | if(de.file.modification_time) { | |
| 4434 | if(de.file.is_directory) { | |
| 4435 | remove_directory(conn, path); | |
| 4436 | send_http_error(conn, 204, "No Content", "%s", ""); | |
| 4437 | } else if (mg_remove(path) == 0) { | |
| 4438 | send_http_error(conn, 204, "No Content", "%s", ""); | |
| 4439 | } else { | |
| 4440 | send_http_error(conn, 423, "Locked", "remove(%s): %s", path, | |
| 4441 | strerror(ERRNO)); | |
| 4442 | } | |
| 4443 | } | |
| 4444 | else { | |
| 4445 | send_http_error(conn, 500, http_500_error, "remove(%s): %s", path, | |
| 4446 | strerror(ERRNO)); | |
| 4447 | } | |
| 4448 | } | |
| 4449 | } else if ((file.membuf == NULL && file.modification_time == (time_t) 0) || | |
| 4450 | must_hide_file(conn, path)) { | |
| 4451 | send_http_error(conn, 404, "Not Found", "%s", "File not found"); | |
| 4452 | } else if (file.is_directory && ri->uri[uri_len - 1] != '/') { | |
| 4453 | mg_printf(conn, "HTTP/1.1 301 Moved Permanently\r\n" | |
| 4454 | "Location: %s/\r\n\r\n", ri->uri); | |
| 4455 | } else if (!strcmp(ri->request_method, "PROPFIND")) { | |
| 4456 | handle_propfind(conn, path, &file); | |
| 4457 | } else if (file.is_directory && | |
| 4458 | !substitute_index_file(conn, path, sizeof(path), &file)) { | |
| 4459 | if (!mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING], "yes")) { | |
| 4460 | handle_directory_request(conn, path); | |
| 4461 | } else { | |
| 4462 | send_http_error(conn, 403, "Directory Listing Denied", | |
| 4463 | "Directory listing denied"); | |
| 4464 | } | |
| 4468 | 4465 | #ifdef USE_LUA |
| 4469 | } else if (match_prefix("**.lp$", 6, path) > 0) { | |
| 4470 | handle_lsp_request(conn, path, &file, NULL); | |
| 4466 | } else if (match_prefix("**.lp$", 6, path) > 0) { | |
| 4467 | handle_lsp_request(conn, path, &file, NULL); | |
| 4471 | 4468 | #endif |
| 4472 | 4469 | #if !defined(NO_CGI) |
| 4473 | } else if (match_prefix(conn->ctx->config[CGI_EXTENSIONS], | |
| 4474 | strlen(conn->ctx->config[CGI_EXTENSIONS]), | |
| 4475 | path) > 0) { | |
| 4476 | if (strcmp(ri->request_method, "POST") && | |
| 4477 | strcmp(ri->request_method, "HEAD") && | |
| 4478 | strcmp(ri->request_method, "GET")) { | |
| 4479 | send_http_error(conn, 501, "Not Implemented", | |
| 4480 | "Method %s is not implemented", ri->request_method); | |
| 4481 | } else { | |
| 4482 | handle_cgi_request(conn, path); | |
| 4483 | } | |
| 4470 | } else if (match_prefix(conn->ctx->config[CGI_EXTENSIONS], | |
| 4471 | strlen(conn->ctx->config[CGI_EXTENSIONS]), | |
| 4472 | path) > 0) { | |
| 4473 | if (strcmp(ri->request_method, "POST") && | |
| 4474 | strcmp(ri->request_method, "HEAD") && | |
| 4475 | strcmp(ri->request_method, "GET")) { | |
| 4476 | send_http_error(conn, 501, "Not Implemented", | |
| 4477 | "Method %s is not implemented", ri->request_method); | |
| 4478 | } else { | |
| 4479 | handle_cgi_request(conn, path); | |
| 4480 | } | |
| 4484 | 4481 | #endif // !NO_CGI |
| 4485 | } else if (match_prefix(conn->ctx->config[SSI_EXTENSIONS], | |
| 4486 | strlen(conn->ctx->config[SSI_EXTENSIONS]), | |
| 4487 | path) > 0) { | |
| 4488 | handle_ssi_file_request(conn, path); | |
| 4489 | } else if (is_not_modified(conn, &file)) { | |
| 4490 | send_http_error(conn, 304, "Not Modified", "%s", ""); | |
| 4491 | } else { | |
| 4492 | handle_file_request(conn, path, &file); | |
| 4493 | } | |
| 4482 | } else if (match_prefix(conn->ctx->config[SSI_EXTENSIONS], | |
| 4483 | strlen(conn->ctx->config[SSI_EXTENSIONS]), | |
| 4484 | path) > 0) { | |
| 4485 | handle_ssi_file_request(conn, path); | |
| 4486 | } else if (is_not_modified(conn, &file)) { | |
| 4487 | send_http_error(conn, 304, "Not Modified", "%s", ""); | |
| 4488 | } else { | |
| 4489 | handle_file_request(conn, path, &file); | |
| 4490 | } | |
| 4494 | 4491 | } |
| 4495 | 4492 | |
| 4496 | 4493 | static void close_all_listening_sockets(struct mg_context *ctx) { |
| 4497 | int i; | |
| 4498 | for (i = 0; i < ctx->num_listening_sockets; i++) { | |
| 4499 | closesocket(ctx->listening_sockets[i].sock); | |
| 4500 | } | |
| 4501 | free(ctx->listening_sockets); | |
| 4494 | int i; | |
| 4495 | for (i = 0; i < ctx->num_listening_sockets; i++) { | |
| 4496 | closesocket(ctx->listening_sockets[i].sock); | |
| 4497 | } | |
| 4498 | free(ctx->listening_sockets); | |
| 4502 | 4499 | } |
| 4503 | 4500 | |
| 4504 | 4501 | // Valid listening port specification is: [ip_address:]port[s] |
| 4505 | 4502 | // Examples: 80, 443s, 127.0.0.1:3128, 1.2.3.4:8080s |
| 4506 | 4503 | // TODO(lsm): add parsing of the IPv6 address |
| 4507 | 4504 | static int parse_port_string(const struct vec *vec, struct socket *so) { |
| 4508 | ||
| 4505 | int a, b, c, d, port, len; | |
| 4509 | 4506 | |
| 4510 | // MacOS needs that. If we do not zero it, subsequent bind() will fail. | |
| 4511 | // Also, all-zeroes in the socket address means binding to all addresses | |
| 4512 | // for both IPv4 and IPv6 (INADDR_ANY and IN6ADDR_ANY_INIT). | |
| 4513 | memset(so, 0, sizeof(*so)); | |
| 4507 | // MacOS needs that. If we do not zero it, subsequent bind() will fail. | |
| 4508 | // Also, all-zeroes in the socket address means binding to all addresses | |
| 4509 | // for both IPv4 and IPv6 (INADDR_ANY and IN6ADDR_ANY_INIT). | |
| 4510 | memset(so, 0, sizeof(*so)); | |
| 4514 | 4511 | |
| 4515 | if (sscanf(vec->ptr, "%d.%d.%d.%d:%d%n", &a, &b, &c, &d, &port, &len) == 5) { | |
| 4516 | // Bind to a specific IPv4 address | |
| 4517 | so->lsa.sin.sin_addr.s_addr = htonl((a << 24) | (b << 16) | (c << 8) | d); | |
| 4518 | } else if (sscanf(vec->ptr, "%d%n", &port, &len) != 1 || | |
| 4519 | len <= 0 || | |
| 4520 | len > (int) vec->len || | |
| 4521 | port < 1 || | |
| 4522 | port > 65535 || | |
| 4523 | (vec->ptr[len] && vec->ptr[len] != 's' && | |
| 4524 | vec->ptr[len] != 'r' && vec->ptr[len] != ',')) { | |
| 4525 | return 0; | |
| 4526 | } | |
| 4512 | if (sscanf(vec->ptr, "%d.%d.%d.%d:%d%n", &a, &b, &c, &d, &port, &len) == 5) { | |
| 4513 | // Bind to a specific IPv4 address | |
| 4514 | so->lsa.sin.sin_addr.s_addr = htonl((a << 24) | (b << 16) | (c << 8) | d); | |
| 4515 | } else if (sscanf(vec->ptr, "%d%n", &port, &len) != 1 || | |
| 4516 | len <= 0 || | |
| 4517 | len > (int) vec->len || | |
| 4518 | port < 1 || | |
| 4519 | port > 65535 || | |
| 4520 | (vec->ptr[len] && vec->ptr[len] != 's' && | |
| 4521 | vec->ptr[len] != 'r' && vec->ptr[len] != ',')) { | |
| 4522 | return 0; | |
| 4523 | } | |
| 4527 | 4524 | |
| 4528 | so->is_ssl = vec->ptr[len] == 's'; | |
| 4529 | so->ssl_redir = vec->ptr[len] == 'r'; | |
| 4525 | so->is_ssl = vec->ptr[len] == 's'; | |
| 4526 | so->ssl_redir = vec->ptr[len] == 'r'; | |
| 4530 | 4527 | #if defined(USE_IPV6) |
| 4531 | so->lsa.sin6.sin6_family = AF_INET6; | |
| 4532 | so->lsa.sin6.sin6_port = htons((uint16_t) port); | |
| 4528 | so->lsa.sin6.sin6_family = AF_INET6; | |
| 4529 | so->lsa.sin6.sin6_port = htons((uint16_t) port); | |
| 4533 | 4530 | #else |
| 4534 | so->lsa.sin.sin_family = AF_INET; | |
| 4535 | so->lsa.sin.sin_port = htons((uint16_t) port); | |
| 4531 | so->lsa.sin.sin_family = AF_INET; | |
| 4532 | so->lsa.sin.sin_port = htons((uint16_t) port); | |
| 4536 | 4533 | #endif |
| 4537 | 4534 | |
| 4538 | ||
| 4535 | return 1; | |
| 4539 | 4536 | } |
| 4540 | 4537 | |
| 4541 | 4538 | static int set_ports_option(struct mg_context *ctx) { |
| 4542 | const char *list = ctx->config[LISTENING_PORTS]; | |
| 4543 | int on = 1, success = 1; | |
| 4539 | const char *list = ctx->config[LISTENING_PORTS]; | |
| 4540 | int on = 1, success = 1; | |
| 4544 | 4541 | #if defined(USE_IPV6) |
| 4545 | ||
| 4542 | int off = 0; | |
| 4546 | 4543 | #endif |
| 4547 | struct vec vec; | |
| 4548 | struct socket so, *ptr; | |
| 4544 | struct vec vec; | |
| 4545 | struct socket so, *ptr; | |
| 4549 | 4546 | |
| 4550 | while (success && (list = next_option(list, &vec, NULL)) != NULL) { | |
| 4551 | if (!parse_port_string(&vec, &so)) { | |
| 4552 | cry(fc(ctx), "%s: %.*s: invalid port spec. Expecting list of: %s", | |
| 4553 | __func__, (int) vec.len, vec.ptr, "[IP_ADDRESS:]PORT[s|p]"); | |
| 4554 | success = 0; | |
| 4555 | } else if (so.is_ssl && ctx->ssl_ctx == NULL) { | |
| 4556 | cry(fc(ctx), "Cannot add SSL socket, is -ssl_certificate option set?"); | |
| 4557 | success = 0; | |
| 4558 | } else if ((so.sock = socket(so.lsa.sa.sa_family, SOCK_STREAM, 6)) == | |
| 4559 | INVALID_SOCKET || | |
| 4560 | // On Windows, SO_REUSEADDR is recommended only for | |
| 4561 | // broadcast UDP sockets | |
| 4562 | setsockopt(so.sock, SOL_SOCKET, SO_REUSEADDR, | |
| 4563 | (SETSOCKOPT_CAST) &on, sizeof(on)) != 0 || | |
| 4547 | while (success && (list = next_option(list, &vec, NULL)) != NULL) { | |
| 4548 | if (!parse_port_string(&vec, &so)) { | |
| 4549 | cry(fc(ctx), "%s: %.*s: invalid port spec. Expecting list of: %s", | |
| 4550 | __func__, (int) vec.len, vec.ptr, "[IP_ADDRESS:]PORT[s|p]"); | |
| 4551 | success = 0; | |
| 4552 | } else if (so.is_ssl && ctx->ssl_ctx == NULL) { | |
| 4553 | cry(fc(ctx), "Cannot add SSL socket, is -ssl_certificate option set?"); | |
| 4554 | success = 0; | |
| 4555 | } else if ((so.sock = socket(so.lsa.sa.sa_family, SOCK_STREAM, 6)) == | |
| 4556 | INVALID_SOCKET || | |
| 4557 | // On Windows, SO_REUSEADDR is recommended only for | |
| 4558 | // broadcast UDP sockets | |
| 4559 | setsockopt(so.sock, SOL_SOCKET, SO_REUSEADDR, | |
| 4560 | (SETSOCKOPT_CAST) &on, sizeof(on)) != 0 || | |
| 4564 | 4561 | #if defined(USE_IPV6) |
| 4565 | setsockopt(so.sock, IPPROTO_IPV6, IPV6_V6ONLY, (SETSOCKOPT_CAST) &off, | |
| 4566 | sizeof(off)) != 0 || | |
| 4562 | setsockopt(so.sock, IPPROTO_IPV6, IPV6_V6ONLY, (SETSOCKOPT_CAST) &off, | |
| 4563 | sizeof(off)) != 0 || | |
| 4567 | 4564 | #endif |
| 4568 | bind(so.sock, &so.lsa.sa, sizeof(so.lsa)) != 0 || | |
| 4569 | listen(so.sock, SOMAXCONN) != 0) { | |
| 4570 | cry(fc(ctx), "%s: cannot bind to %.*s: %s", __func__, | |
| 4571 | (int) vec.len, vec.ptr, strerror(ERRNO)); | |
| 4572 | closesocket(so.sock); | |
| 4573 | success = 0; | |
| 4574 | } else if ((ptr = (struct socket*)realloc(ctx->listening_sockets, | |
| 4575 | (ctx->num_listening_sockets + 1) * | |
| 4576 | sizeof(ctx->listening_sockets[0]))) == NULL) { | |
| 4577 | closesocket(so.sock); | |
| 4578 | success = 0; | |
| 4579 | } else { | |
| 4580 | set_close_on_exec(so.sock); | |
| 4581 | ctx->listening_sockets = ptr; | |
| 4582 | ctx->listening_sockets[ctx->num_listening_sockets] = so; | |
| 4583 | ctx->num_listening_sockets++; | |
| 4584 | } | |
| 4585 | } | |
| 4565 | bind(so.sock, &so.lsa.sa, sizeof(so.lsa)) != 0 || | |
| 4566 | listen(so.sock, SOMAXCONN) != 0) { | |
| 4567 | cry(fc(ctx), "%s: cannot bind to %.*s: %s", __func__, | |
| 4568 | (int) vec.len, vec.ptr, strerror(ERRNO)); | |
| 4569 | closesocket(so.sock); | |
| 4570 | success = 0; | |
| 4571 | } else if ((ptr = (struct socket*)realloc(ctx->listening_sockets, | |
| 4572 | (ctx->num_listening_sockets + 1) * | |
| 4573 | sizeof(ctx->listening_sockets[0]))) == NULL) { | |
| 4574 | closesocket(so.sock); | |
| 4575 | success = 0; | |
| 4576 | } else { | |
| 4577 | set_close_on_exec(so.sock); | |
| 4578 | ctx->listening_sockets = ptr; | |
| 4579 | ctx->listening_sockets[ctx->num_listening_sockets] = so; | |
| 4580 | ctx->num_listening_sockets++; | |
| 4581 | } | |
| 4582 | } | |
| 4586 | 4583 | |
| 4587 | if (!success) { | |
| 4588 | close_all_listening_sockets(ctx); | |
| 4589 | } | |
| 4584 | if (!success) { | |
| 4585 | close_all_listening_sockets(ctx); | |
| 4586 | } | |
| 4590 | 4587 | |
| 4591 | ||
| 4588 | return success; | |
| 4592 | 4589 | } |
| 4593 | 4590 | |
| 4594 | 4591 | static void log_header(const struct mg_connection *conn, const char *header, |
| 4595 | FILE *fp) { | |
| 4596 | const char *header_value; | |
| 4592 | FILE *fp) { | |
| 4593 | const char *header_value; | |
| 4597 | 4594 | |
| 4598 | if ((header_value = mg_get_header(conn, header)) == NULL) { | |
| 4599 | (void) fprintf(fp, "%s", " -"); | |
| 4600 | } else { | |
| 4601 | (void) fprintf(fp, " \"%s\"", header_value); | |
| 4602 | } | |
| 4595 | if ((header_value = mg_get_header(conn, header)) == NULL) { | |
| 4596 | (void) fprintf(fp, "%s", " -"); | |
| 4597 | } else { | |
| 4598 | (void) fprintf(fp, " \"%s\"", header_value); | |
| 4599 | } | |
| 4603 | 4600 | } |
| 4604 | 4601 | |
| 4605 | 4602 | static void log_access(const struct mg_connection *conn) { |
| 4606 | const struct mg_request_info *ri; | |
| 4607 | FILE *fp; | |
| 4608 | char date[64], src_addr[IP_ADDR_STR_LEN]; | |
| 4603 | const struct mg_request_info *ri; | |
| 4604 | FILE *fp; | |
| 4605 | char date[64], src_addr[IP_ADDR_STR_LEN]; | |
| 4609 | 4606 | |
| 4610 | fp = conn->ctx->config[ACCESS_LOG_FILE] == NULL ? NULL : | |
| 4611 | fopen(conn->ctx->config[ACCESS_LOG_FILE], "a+"); | |
| 4607 | fp = conn->ctx->config[ACCESS_LOG_FILE] == NULL ? NULL : | |
| 4608 | fopen(conn->ctx->config[ACCESS_LOG_FILE], "a+"); | |
| 4612 | 4609 | |
| 4613 | if (fp == NULL) | |
| 4614 | return; | |
| 4610 | if (fp == NULL) | |
| 4611 | return; | |
| 4615 | 4612 | |
| 4616 | strftime(date, sizeof(date), "%d/%b/%Y:%H:%M:%S %z", | |
| 4617 | localtime(&conn->birth_time)); | |
| 4613 | strftime(date, sizeof(date), "%d/%b/%Y:%H:%M:%S %z", | |
| 4614 | localtime(&conn->birth_time)); | |
| 4618 | 4615 | |
| 4619 | ri = &conn->request_info; | |
| 4620 | flockfile(fp); | |
| 4616 | ri = &conn->request_info; | |
| 4617 | flockfile(fp); | |
| 4621 | 4618 | |
| 4622 | sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa); | |
| 4623 | fprintf(fp, "%s - %s [%s] \"%s %s HTTP/%s\" %d %" INT64_FMT, | |
| 4624 | src_addr, ri->remote_user == NULL ? "-" : ri->remote_user, date, | |
| 4625 | ri->request_method ? ri->request_method : "-", | |
| 4626 | ri->uri ? ri->uri : "-", ri->http_version, | |
| 4627 | conn->status_code, conn->num_bytes_sent); | |
| 4628 | log_header(conn, "Referer", fp); | |
| 4629 | log_header(conn, "User-Agent", fp); | |
| 4630 | fputc('\n', fp); | |
| 4631 | fflush(fp); | |
| 4619 | sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa); | |
| 4620 | fprintf(fp, "%s - %s [%s] \"%s %s HTTP/%s\" %d %" INT64_FMT, | |
| 4621 | src_addr, ri->remote_user == NULL ? "-" : ri->remote_user, date, | |
| 4622 | ri->request_method ? ri->request_method : "-", | |
| 4623 | ri->uri ? ri->uri : "-", ri->http_version, | |
| 4624 | conn->status_code, conn->num_bytes_sent); | |
| 4625 | log_header(conn, "Referer", fp); | |
| 4626 | log_header(conn, "User-Agent", fp); | |
| 4627 | fputc('\n', fp); | |
| 4628 | fflush(fp); | |
| 4632 | 4629 | |
| 4633 | funlockfile(fp); | |
| 4634 | fclose(fp); | |
| 4630 | funlockfile(fp); | |
| 4631 | fclose(fp); | |
| 4635 | 4632 | } |
| 4636 | 4633 | |
| 4637 | 4634 | // Verify given socket address against the ACL. |
| 4638 | 4635 | // Return -1 if ACL is malformed, 0 if address is disallowed, 1 if allowed. |
| 4639 | 4636 | static int check_acl(struct mg_context *ctx, uint32_t remote_ip) { |
| 4640 | int allowed, flag; | |
| 4641 | uint32_t net, mask; | |
| 4642 | struct vec vec; | |
| 4643 | const char *list = ctx->config[ACCESS_CONTROL_LIST]; | |
| 4637 | int allowed, flag; | |
| 4638 | uint32_t net, mask; | |
| 4639 | struct vec vec; | |
| 4640 | const char *list = ctx->config[ACCESS_CONTROL_LIST]; | |
| 4644 | 4641 | |
| 4645 | // If any ACL is set, deny by default | |
| 4646 | allowed = list == NULL ? '+' : '-'; | |
| 4642 | // If any ACL is set, deny by default | |
| 4643 | allowed = list == NULL ? '+' : '-'; | |
| 4647 | 4644 | |
| 4648 | while ((list = next_option(list, &vec, NULL)) != NULL) { | |
| 4649 | flag = vec.ptr[0]; | |
| 4650 | if ((flag != '+' && flag != '-') || | |
| 4651 | parse_net(&vec.ptr[1], &net, &mask) == 0) { | |
| 4652 | cry(fc(ctx), "%s: subnet must be [+|-]x.x.x.x[/x]", __func__); | |
| 4653 | return -1; | |
| 4654 | } | |
| 4645 | while ((list = next_option(list, &vec, NULL)) != NULL) { | |
| 4646 | flag = vec.ptr[0]; | |
| 4647 | if ((flag != '+' && flag != '-') || | |
| 4648 | parse_net(&vec.ptr[1], &net, &mask) == 0) { | |
| 4649 | cry(fc(ctx), "%s: subnet must be [+|-]x.x.x.x[/x]", __func__); | |
| 4650 | return -1; | |
| 4651 | } | |
| 4655 | 4652 | |
| 4656 | if (net == (remote_ip & mask)) { | |
| 4657 | allowed = flag; | |
| 4658 | } | |
| 4659 | } | |
| 4653 | if (net == (remote_ip & mask)) { | |
| 4654 | allowed = flag; | |
| 4655 | } | |
| 4656 | } | |
| 4660 | 4657 | |
| 4661 | ||
| 4658 | return allowed == '+'; | |
| 4662 | 4659 | } |
| 4663 | 4660 | |
| 4664 | 4661 | #if !defined(_WIN32) |
| 4665 | 4662 | static int set_uid_option(struct mg_context *ctx) { |
| 4666 | struct passwd *pw; | |
| 4667 | const char *uid = ctx->config[RUN_AS_USER]; | |
| 4668 | int success = 0; | |
| 4663 | struct passwd *pw; | |
| 4664 | const char *uid = ctx->config[RUN_AS_USER]; | |
| 4665 | int success = 0; | |
| 4669 | 4666 | |
| 4670 | if (uid == NULL) { | |
| 4671 | success = 1; | |
| 4672 | } else { | |
| 4673 | if ((pw = getpwnam(uid)) == NULL) { | |
| 4674 | cry(fc(ctx), "%s: unknown user [%s]", __func__, uid); | |
| 4675 | } else if (setgid(pw->pw_gid) == -1) { | |
| 4676 | cry(fc(ctx), "%s: setgid(%s): %s", __func__, uid, strerror(errno)); | |
| 4677 | } else if (setuid(pw->pw_uid) == -1) { | |
| 4678 | cry(fc(ctx), "%s: setuid(%s): %s", __func__, uid, strerror(errno)); | |
| 4679 | } else { | |
| 4680 | success = 1; | |
| 4681 | } | |
| 4682 | } | |
| 4667 | if (uid == NULL) { | |
| 4668 | success = 1; | |
| 4669 | } else { | |
| 4670 | if ((pw = getpwnam(uid)) == NULL) { | |
| 4671 | cry(fc(ctx), "%s: unknown user [%s]", __func__, uid); | |
| 4672 | } else if (setgid(pw->pw_gid) == -1) { | |
| 4673 | cry(fc(ctx), "%s: setgid(%s): %s", __func__, uid, strerror(errno)); | |
| 4674 | } else if (setuid(pw->pw_uid) == -1) { | |
| 4675 | cry(fc(ctx), "%s: setuid(%s): %s", __func__, uid, strerror(errno)); | |
| 4676 | } else { | |
| 4677 | success = 1; | |
| 4678 | } | |
| 4679 | } | |
| 4683 | 4680 | |
| 4684 | ||
| 4681 | return success; | |
| 4685 | 4682 | } |
| 4686 | 4683 | #endif // !_WIN32 |
| 4687 | 4684 | |
| r25360 | r25361 | |
| 4689 | 4686 | static pthread_mutex_t *ssl_mutexes; |
| 4690 | 4687 | |
| 4691 | 4688 | static int sslize(struct mg_connection *conn, SSL_CTX *s, int (*func)(SSL *)) { |
| 4692 | return (conn->ssl = SSL_new(s)) != NULL && | |
| 4693 | SSL_set_fd(conn->ssl, conn->client.sock) == 1 && | |
| 4694 | func(conn->ssl) == 1; | |
| 4689 | return (conn->ssl = SSL_new(s)) != NULL && | |
| 4690 | SSL_set_fd(conn->ssl, conn->client.sock) == 1 && | |
| 4691 | func(conn->ssl) == 1; | |
| 4695 | 4692 | } |
| 4696 | 4693 | |
| 4697 | 4694 | // Return OpenSSL error message |
| 4698 | 4695 | static const char *ssl_error(void) { |
| 4699 | unsigned long err; | |
| 4700 | err = ERR_get_error(); | |
| 4701 | return err == 0 ? "" : ERR_error_string(err, NULL); | |
| 4696 | unsigned long err; | |
| 4697 | err = ERR_get_error(); | |
| 4698 | return err == 0 ? "" : ERR_error_string(err, NULL); | |
| 4702 | 4699 | } |
| 4703 | 4700 | |
| 4704 | 4701 | static void ssl_locking_callback(int mode, int mutex_num, const char *file, |
| 4705 | int line) { | |
| 4706 | (void) line; | |
| 4707 | (void) file; | |
| 4702 | int line) { | |
| 4703 | (void) line; | |
| 4704 | (void) file; | |
| 4708 | 4705 | |
| 4709 | if (mode & 1) { // 1 is CRYPTO_LOCK | |
| 4710 | (void) pthread_mutex_lock(&ssl_mutexes[mutex_num]); | |
| 4711 | } else { | |
| 4712 | (void) pthread_mutex_unlock(&ssl_mutexes[mutex_num]); | |
| 4713 | } | |
| 4706 | if (mode & 1) { // 1 is CRYPTO_LOCK | |
| 4707 | (void) pthread_mutex_lock(&ssl_mutexes[mutex_num]); | |
| 4708 | } else { | |
| 4709 | (void) pthread_mutex_unlock(&ssl_mutexes[mutex_num]); | |
| 4710 | } | |
| 4714 | 4711 | } |
| 4715 | 4712 | |
| 4716 | 4713 | static unsigned long ssl_id_callback(void) { |
| 4717 | ||
| 4714 | return (unsigned long) pthread_self(); | |
| 4718 | 4715 | } |
| 4719 | 4716 | |
| 4720 | 4717 | #if !defined(NO_SSL_DL) |
| 4721 | 4718 | static int load_dll(struct mg_context *ctx, const char *dll_name, |
| 4722 | struct ssl_func *sw) { | |
| 4723 | union {void *p; void (*fp)(void);} u; | |
| 4724 | void *dll_handle; | |
| 4725 | struct ssl_func *fp; | |
| 4719 | struct ssl_func *sw) { | |
| 4720 | union {void *p; void (*fp)(void);} u; | |
| 4721 | void *dll_handle; | |
| 4722 | struct ssl_func *fp; | |
| 4726 | 4723 | |
| 4727 | if ((dll_handle = dlopen(dll_name, RTLD_LAZY)) == NULL) { | |
| 4728 | cry(fc(ctx), "%s: cannot load %s", __func__, dll_name); | |
| 4729 | return 0; | |
| 4730 | } | |
| 4724 | if ((dll_handle = dlopen(dll_name, RTLD_LAZY)) == NULL) { | |
| 4725 | cry(fc(ctx), "%s: cannot load %s", __func__, dll_name); | |
| 4726 | return 0; | |
| 4727 | } | |
| 4731 | 4728 | |
| 4732 | ||
| 4729 | for (fp = sw; fp->name != NULL; fp++) { | |
| 4733 | 4730 | #ifdef _WIN32 |
| 4734 | // GetProcAddress() returns pointer to function | |
| 4735 | u.fp = (void (*)(void)) dlsym(dll_handle, fp->name); | |
| 4731 | // GetProcAddress() returns pointer to function | |
| 4732 | u.fp = (void (*)(void)) dlsym(dll_handle, fp->name); | |
| 4736 | 4733 | #else |
| 4737 | // dlsym() on UNIX returns void *. ISO C forbids casts of data pointers to | |
| 4738 | // function pointers. We need to use a union to make a cast. | |
| 4739 | u.p = dlsym(dll_handle, fp->name); | |
| 4734 | // dlsym() on UNIX returns void *. ISO C forbids casts of data pointers to | |
| 4735 | // function pointers. We need to use a union to make a cast. | |
| 4736 | u.p = dlsym(dll_handle, fp->name); | |
| 4740 | 4737 | #endif // _WIN32 |
| 4741 | if (u.fp == NULL) { | |
| 4742 | cry(fc(ctx), "%s: %s: cannot find %s", __func__, dll_name, fp->name); | |
| 4743 | return 0; | |
| 4744 | } else { | |
| 4745 | fp->ptr = u.fp; | |
| 4746 | } | |
| 4747 | } | |
| 4738 | if (u.fp == NULL) { | |
| 4739 | cry(fc(ctx), "%s: %s: cannot find %s", __func__, dll_name, fp->name); | |
| 4740 | return 0; | |
| 4741 | } else { | |
| 4742 | fp->ptr = u.fp; | |
| 4743 | } | |
| 4744 | } | |
| 4748 | 4745 | |
| 4749 | ||
| 4746 | return 1; | |
| 4750 | 4747 | } |
| 4751 | 4748 | #endif // NO_SSL_DL |
| 4752 | 4749 | |
| 4753 | 4750 | // Dynamically load SSL library. Set up ctx->ssl_ctx pointer. |
| 4754 | 4751 | static int set_ssl_option(struct mg_context *ctx) { |
| 4755 | int i, size; | |
| 4756 | const char *pem; | |
| 4752 | int i, size; | |
| 4753 | const char *pem; | |
| 4757 | 4754 | |
| 4758 | // If PEM file is not specified, skip SSL initialization. | |
| 4759 | if ((pem = ctx->config[SSL_CERTIFICATE]) == NULL) { | |
| 4760 | return 1; | |
| 4761 | } | |
| 4755 | // If PEM file is not specified, skip SSL initialization. | |
| 4756 | if ((pem = ctx->config[SSL_CERTIFICATE]) == NULL) { | |
| 4757 | return 1; | |
| 4758 | } | |
| 4762 | 4759 | |
| 4763 | 4760 | #if !defined(NO_SSL_DL) |
| 4764 | if (!load_dll(ctx, SSL_LIB, ssl_sw) || | |
| 4765 | !load_dll(ctx, CRYPTO_LIB, crypto_sw)) { | |
| 4766 | return 0; | |
| 4767 | } | |
| 4761 | if (!load_dll(ctx, SSL_LIB, ssl_sw) || | |
| 4762 | !load_dll(ctx, CRYPTO_LIB, crypto_sw)) { | |
| 4763 | return 0; | |
| 4764 | } | |
| 4768 | 4765 | #endif // NO_SSL_DL |
| 4769 | 4766 | |
| 4770 | // Initialize SSL library | |
| 4771 | SSL_library_init(); | |
| 4772 | SSL_load_error_strings(); | |
| 4767 | // Initialize SSL library | |
| 4768 | SSL_library_init(); | |
| 4769 | SSL_load_error_strings(); | |
| 4773 | 4770 | |
| 4774 | if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) { | |
| 4775 | cry(fc(ctx), "SSL_CTX_new (server) error: %s", ssl_error()); | |
| 4776 | return 0; | |
| 4777 | } | |
| 4771 | if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) { | |
| 4772 | cry(fc(ctx), "SSL_CTX_new (server) error: %s", ssl_error()); | |
| 4773 | return 0; | |
| 4774 | } | |
| 4778 | 4775 | |
| 4779 | // If user callback returned non-NULL, that means that user callback has | |
| 4780 | // set up certificate itself. In this case, skip sertificate setting. | |
| 4781 | if ((ctx->callbacks.init_ssl == NULL || | |
| 4782 | !ctx->callbacks.init_ssl(ctx->ssl_ctx, ctx->user_data)) && | |
| 4783 | (SSL_CTX_use_certificate_file(ctx->ssl_ctx, pem, 1) == 0 || | |
| 4784 | SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, pem, 1) == 0)) { | |
| 4785 | cry(fc(ctx), "%s: cannot open %s: %s", __func__, pem, ssl_error()); | |
| 4786 | return 0; | |
| 4787 | } | |
| 4776 | // If user callback returned non-NULL, that means that user callback has | |
| 4777 | // set up certificate itself. In this case, skip sertificate setting. | |
| 4778 | if ((ctx->callbacks.init_ssl == NULL || | |
| 4779 | !ctx->callbacks.init_ssl(ctx->ssl_ctx, ctx->user_data)) && | |
| 4780 | (SSL_CTX_use_certificate_file(ctx->ssl_ctx, pem, 1) == 0 || | |
| 4781 | SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, pem, 1) == 0)) { | |
| 4782 | cry(fc(ctx), "%s: cannot open %s: %s", __func__, pem, ssl_error()); | |
| 4783 | return 0; | |
| 4784 | } | |
| 4788 | 4785 | |
| 4789 | if (pem != NULL) { | |
| 4790 | (void) SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, pem); | |
| 4791 | } | |
| 4786 | if (pem != NULL) { | |
| 4787 | (void) SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, pem); | |
| 4788 | } | |
| 4792 | 4789 | |
| 4793 | // Initialize locking callbacks, needed for thread safety. | |
| 4794 | // http://www.openssl.org/support/faq.html#PROG1 | |
| 4795 | size = sizeof(pthread_mutex_t) * CRYPTO_num_locks(); | |
| 4796 | if ((ssl_mutexes = (pthread_mutex_t *) malloc((size_t)size)) == NULL) { | |
| 4797 | cry(fc(ctx), "%s: cannot allocate mutexes: %s", __func__, ssl_error()); | |
| 4798 | return 0; | |
| 4799 | } | |
| 4790 | // Initialize locking callbacks, needed for thread safety. | |
| 4791 | // http://www.openssl.org/support/faq.html#PROG1 | |
| 4792 | size = sizeof(pthread_mutex_t) * CRYPTO_num_locks(); | |
| 4793 | if ((ssl_mutexes = (pthread_mutex_t *) malloc((size_t)size)) == NULL) { | |
| 4794 | cry(fc(ctx), "%s: cannot allocate mutexes: %s", __func__, ssl_error()); | |
| 4795 | return 0; | |
| 4796 | } | |
| 4800 | 4797 | |
| 4801 | for (i = 0; i < CRYPTO_num_locks(); i++) { | |
| 4802 | pthread_mutex_init(&ssl_mutexes[i], NULL); | |
| 4803 | } | |
| 4798 | for (i = 0; i < CRYPTO_num_locks(); i++) { | |
| 4799 | pthread_mutex_init(&ssl_mutexes[i], NULL); | |
| 4800 | } | |
| 4804 | 4801 | |
| 4805 | CRYPTO_set_locking_callback(&ssl_locking_callback); | |
| 4806 | CRYPTO_set_id_callback(&ssl_id_callback); | |
| 4802 | CRYPTO_set_locking_callback(&ssl_locking_callback); | |
| 4803 | CRYPTO_set_id_callback(&ssl_id_callback); | |
| 4807 | 4804 | |
| 4808 | ||
| 4805 | return 1; | |
| 4809 | 4806 | } |
| 4810 | 4807 | |
| 4811 | 4808 | static void uninitialize_ssl(struct mg_context *ctx) { |
| 4812 | int i; | |
| 4813 | if (ctx->ssl_ctx != NULL) { | |
| 4814 | CRYPTO_set_locking_callback(NULL); | |
| 4815 | for (i = 0; i < CRYPTO_num_locks(); i++) { | |
| 4816 | pthread_mutex_destroy(&ssl_mutexes[i]); | |
| 4817 | } | |
| 4818 | CRYPTO_set_locking_callback(NULL); | |
| 4819 | CRYPTO_set_id_callback(NULL); | |
| 4820 | } | |
| 4809 | int i; | |
| 4810 | if (ctx->ssl_ctx != NULL) { | |
| 4811 | CRYPTO_set_locking_callback(NULL); | |
| 4812 | for (i = 0; i < CRYPTO_num_locks(); i++) { | |
| 4813 | pthread_mutex_destroy(&ssl_mutexes[i]); | |
| 4814 | } | |
| 4815 | CRYPTO_set_locking_callback(NULL); | |
| 4816 | CRYPTO_set_id_callback(NULL); | |
| 4817 | } | |
| 4821 | 4818 | } |
| 4822 | 4819 | #endif // !NO_SSL |
| 4823 | 4820 | |
| 4824 | 4821 | static int set_gpass_option(struct mg_context *ctx) { |
| 4825 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 4826 | const char *path = ctx->config[GLOBAL_PASSWORDS_FILE]; | |
| 4827 | if (path != NULL && !mg_stat(fc(ctx), path, &file)) { | |
| 4828 | cry(fc(ctx), "Cannot open %s: %s", path, strerror(ERRNO)); | |
| 4829 | return 0; | |
| 4830 | } | |
| 4831 | return 1; | |
| 4822 | struct file file = STRUCT_FILE_INITIALIZER; | |
| 4823 | const char *path = ctx->config[GLOBAL_PASSWORDS_FILE]; | |
| 4824 | if (path != NULL && !mg_stat(fc(ctx), path, &file)) { | |
| 4825 | cry(fc(ctx), "Cannot open %s: %s", path, strerror(ERRNO)); | |
| 4826 | return 0; | |
| 4827 | } | |
| 4828 | return 1; | |
| 4832 | 4829 | } |
| 4833 | 4830 | |
| 4834 | 4831 | static int set_acl_option(struct mg_context *ctx) { |
| 4835 | ||
| 4832 | return check_acl(ctx, (uint32_t) 0x7f000001UL) != -1; | |
| 4836 | 4833 | } |
| 4837 | 4834 | |
| 4838 | 4835 | static void reset_per_request_attributes(struct mg_connection *conn) { |
| 4839 | conn->path_info = NULL; | |
| 4840 | conn->num_bytes_sent = conn->consumed_content = 0; | |
| 4841 | conn->status_code = -1; | |
| 4842 | conn->must_close = conn->request_len = conn->throttle = 0; | |
| 4836 | conn->path_info = NULL; | |
| 4837 | conn->num_bytes_sent = conn->consumed_content = 0; | |
| 4838 | conn->status_code = -1; | |
| 4839 | conn->must_close = conn->request_len = conn->throttle = 0; | |
| 4843 | 4840 | } |
| 4844 | 4841 | |
| 4845 | 4842 | static void close_socket_gracefully(struct mg_connection *conn) { |
| 4846 | 4843 | #if defined(_WIN32) |
| 4847 | char buf[MG_BUF_LEN]; | |
| 4848 | int n; | |
| 4844 | char buf[MG_BUF_LEN]; | |
| 4845 | int n; | |
| 4849 | 4846 | #endif |
| 4850 | ||
| 4847 | struct linger linger; | |
| 4851 | 4848 | |
| 4852 | // Set linger option to avoid socket hanging out after close. This prevent | |
| 4853 | // ephemeral port exhaust problem under high QPS. | |
| 4854 | linger.l_onoff = 1; | |
| 4855 | linger.l_linger = 1; | |
| 4856 | setsockopt(conn->client.sock, SOL_SOCKET, SO_LINGER, | |
| 4857 | (char *) &linger, sizeof(linger)); | |
| 4849 | // Set linger option to avoid socket hanging out after close. This prevent | |
| 4850 | // ephemeral port exhaust problem under high QPS. | |
| 4851 | linger.l_onoff = 1; | |
| 4852 | linger.l_linger = 1; | |
| 4853 | setsockopt(conn->client.sock, SOL_SOCKET, SO_LINGER, | |
| 4854 | (char *) &linger, sizeof(linger)); | |
| 4858 | 4855 | |
| 4859 | // Send FIN to the client | |
| 4860 | shutdown(conn->client.sock, SHUT_WR); | |
| 4861 | set_non_blocking_mode(conn->client.sock); | |
| 4856 | // Send FIN to the client | |
| 4857 | shutdown(conn->client.sock, SHUT_WR); | |
| 4858 | set_non_blocking_mode(conn->client.sock); | |
| 4862 | 4859 | |
| 4863 | 4860 | #if defined(_WIN32) |
| 4864 | // Read and discard pending incoming data. If we do not do that and close the | |
| 4865 | // socket, the data in the send buffer may be discarded. This | |
| 4866 | // behaviour is seen on Windows, when client keeps sending data | |
| 4867 | // when server decides to close the connection; then when client | |
| 4868 | // does recv() it gets no data back. | |
| 4869 | do { | |
| 4870 | n = pull(NULL, conn, buf, sizeof(buf)); | |
| 4871 | } while (n > 0); | |
| 4861 | // Read and discard pending incoming data. If we do not do that and close the | |
| 4862 | // socket, the data in the send buffer may be discarded. This | |
| 4863 | // behaviour is seen on Windows, when client keeps sending data | |
| 4864 | // when server decides to close the connection; then when client | |
| 4865 | // does recv() it gets no data back. | |
| 4866 | do { | |
| 4867 | n = pull(NULL, conn, buf, sizeof(buf)); | |
| 4868 | } while (n > 0); | |
| 4872 | 4869 | #endif |
| 4873 | 4870 | |
| 4874 | // Now we know that our FIN is ACK-ed, safe to close | |
| 4875 | closesocket(conn->client.sock); | |
| 4871 | // Now we know that our FIN is ACK-ed, safe to close | |
| 4872 | closesocket(conn->client.sock); | |
| 4876 | 4873 | } |
| 4877 | 4874 | |
| 4878 | 4875 | static void close_connection(struct mg_connection *conn) { |
| 4879 | ||
| 4876 | conn->must_close = 1; | |
| 4880 | 4877 | |
| 4881 | 4878 | #ifndef NO_SSL |
| 4882 | if (conn->ssl != NULL) { | |
| 4883 | // Run SSL_shutdown twice to ensure completly close SSL connection | |
| 4884 | SSL_shutdown(conn->ssl); | |
| 4885 | SSL_free(conn->ssl); | |
| 4886 | conn->ssl = NULL; | |
| 4887 | } | |
| 4879 | if (conn->ssl != NULL) { | |
| 4880 | // Run SSL_shutdown twice to ensure completly close SSL connection | |
| 4881 | SSL_shutdown(conn->ssl); | |
| 4882 | SSL_free(conn->ssl); | |
| 4883 | conn->ssl = NULL; | |
| 4884 | } | |
| 4888 | 4885 | #endif |
| 4889 | if (conn->client.sock != INVALID_SOCKET) { | |
| 4890 | close_socket_gracefully(conn); | |
| 4891 | conn->client.sock = INVALID_SOCKET; | |
| 4892 | } | |
| 4886 | if (conn->client.sock != INVALID_SOCKET) { | |
| 4887 | close_socket_gracefully(conn); | |
| 4888 | conn->client.sock = INVALID_SOCKET; | |
| 4889 | } | |
| 4893 | 4890 | } |
| 4894 | 4891 | |
| 4895 | 4892 | void mg_close_connection(struct mg_connection *conn) { |
| 4896 | 4893 | #ifndef NO_SSL |
| 4897 | if (conn->client_ssl_ctx != NULL) { | |
| 4898 | SSL_CTX_free((SSL_CTX *) conn->client_ssl_ctx); | |
| 4899 | } | |
| 4894 | if (conn->client_ssl_ctx != NULL) { | |
| 4895 | SSL_CTX_free((SSL_CTX *) conn->client_ssl_ctx); | |
| 4896 | } | |
| 4900 | 4897 | #endif |
| 4901 | close_connection(conn); | |
| 4902 | free(conn); | |
| 4898 | close_connection(conn); | |
| 4899 | free(conn); | |
| 4903 | 4900 | } |
| 4904 | 4901 | |
| 4905 | 4902 | struct mg_connection *mg_connect(const char *host, int port, int use_ssl, |
| 4906 | char *ebuf, size_t ebuf_len) { | |
| 4907 | static struct mg_context fake_ctx; | |
| 4908 | struct mg_connection *conn = NULL; | |
| 4909 | SOCKET sock; | |
| 4903 | char *ebuf, size_t ebuf_len) { | |
| 4904 | static struct mg_context fake_ctx; | |
| 4905 | struct mg_connection *conn = NULL; | |
| 4906 | SOCKET sock; | |
| 4910 | 4907 | |
| 4911 | if ((sock = conn2(host, port, use_ssl, ebuf, ebuf_len)) == INVALID_SOCKET) { | |
| 4912 | } else if ((conn = (struct mg_connection *) | |
| 4913 | calloc(1, sizeof(*conn) + MAX_REQUEST_SIZE)) == NULL) { | |
| 4914 | snprintf(ebuf, ebuf_len, "calloc(): %s", strerror(ERRNO)); | |
| 4915 | closesocket(sock); | |
| 4908 | if ((sock = conn2(host, port, use_ssl, ebuf, ebuf_len)) == INVALID_SOCKET) { | |
| 4909 | } else if ((conn = (struct mg_connection *) | |
| 4910 | calloc(1, sizeof(*conn) + MAX_REQUEST_SIZE)) == NULL) { | |
| 4911 | snprintf(ebuf, ebuf_len, "calloc(): %s", strerror(ERRNO)); | |
| 4912 | closesocket(sock); | |
| 4916 | 4913 | #ifndef NO_SSL |
| 4917 | } else if (use_ssl && (conn->client_ssl_ctx = | |
| 4918 | SSL_CTX_new(SSLv23_client_method())) == NULL) { | |
| 4919 | snprintf(ebuf, ebuf_len, "SSL_CTX_new error"); | |
| 4920 | closesocket(sock); | |
| 4921 | free(conn); | |
| 4922 | conn = NULL; | |
| 4914 | } else if (use_ssl && (conn->client_ssl_ctx = | |
| 4915 | SSL_CTX_new(SSLv23_client_method())) == NULL) { | |
| 4916 | snprintf(ebuf, ebuf_len, "SSL_CTX_new error"); | |
| 4917 | closesocket(sock); | |
| 4918 | free(conn); | |
| 4919 | conn = NULL; | |
| 4923 | 4920 | #endif // NO_SSL |
| 4924 | } else { | |
| 4925 | socklen_t len; | |
| 4926 | conn->buf_size = MAX_REQUEST_SIZE; | |
| 4927 | conn->buf = (char *) (conn + 1); | |
| 4928 | conn->ctx = &fake_ctx; | |
| 4929 | conn->client.sock = sock; | |
| 4930 | getsockname(sock, &conn->client.rsa.sa, &len); | |
| 4931 | conn->client.is_ssl = use_ssl; | |
| 4921 | } else { | |
| 4922 | socklen_t len; | |
| 4923 | conn->buf_size = MAX_REQUEST_SIZE; | |
| 4924 | conn->buf = (char *) (conn + 1); | |
| 4925 | conn->ctx = &fake_ctx; | |
| 4926 | conn->client.sock = sock; | |
| 4927 | getsockname(sock, &conn->client.rsa.sa, &len); | |
| 4928 | conn->client.is_ssl = use_ssl; | |
| 4932 | 4929 | #ifndef NO_SSL |
| 4933 | if (use_ssl) { | |
| 4934 | // SSL_CTX_set_verify call is needed to switch off server certificate | |
| 4935 | // checking, which is off by default in OpenSSL and on in yaSSL. | |
| 4936 | SSL_CTX_set_verify(conn->client_ssl_ctx, 0, 0); | |
| 4937 | sslize(conn, conn->client_ssl_ctx, SSL_connect); | |
| 4938 | } | |
| 4930 | if (use_ssl) { | |
| 4931 | // SSL_CTX_set_verify call is needed to switch off server certificate | |
| 4932 | // checking, which is off by default in OpenSSL and on in yaSSL. | |
| 4933 | SSL_CTX_set_verify(conn->client_ssl_ctx, 0, 0); | |
| 4934 | sslize(conn, conn->client_ssl_ctx, SSL_connect); | |
| 4935 | } | |
| 4939 | 4936 | #endif |
| 4940 | ||
| 4937 | } | |
| 4941 | 4938 | |
| 4942 | ||
| 4939 | return conn; | |
| 4943 | 4940 | } |
| 4944 | 4941 | |
| 4945 | 4942 | static int is_valid_uri(const char *uri) { |
| 4946 | // Conform to http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2 | |
| 4947 | // URI can be an asterisk (*) or should start with slash. | |
| 4948 | return uri[0] == '/' || (uri[0] == '*' && uri[1] == '\0'); | |
| 4943 | // Conform to http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2 | |
| 4944 | // URI can be an asterisk (*) or should start with slash. | |
| 4945 | return uri[0] == '/' || (uri[0] == '*' && uri[1] == '\0'); | |
| 4949 | 4946 | } |
| 4950 | 4947 | |
| 4951 | 4948 | static int getreq(struct mg_connection *conn, char *ebuf, size_t ebuf_len) { |
| 4952 | ||
| 4949 | const char *cl; | |
| 4953 | 4950 | |
| 4954 | ebuf[0] = '\0'; | |
| 4955 | reset_per_request_attributes(conn); | |
| 4956 | conn->request_len = read_request(NULL, conn, conn->buf, conn->buf_size, | |
| 4957 | &conn->data_len); | |
| 4958 | assert(conn->request_len < 0 || conn->data_len >= conn->request_len); | |
| 4951 | ebuf[0] = '\0'; | |
| 4952 | reset_per_request_attributes(conn); | |
| 4953 | conn->request_len = read_request(NULL, conn, conn->buf, conn->buf_size, | |
| 4954 | &conn->data_len); | |
| 4955 | assert(conn->request_len < 0 || conn->data_len >= conn->request_len); | |
| 4959 | 4956 | |
| 4960 | if (conn->request_len == 0 && conn->data_len == conn->buf_size) { | |
| 4961 | snprintf(ebuf, ebuf_len, "%s", "Request Too Large"); | |
| 4962 | } else if (conn->request_len <= 0) { | |
| 4963 | snprintf(ebuf, ebuf_len, "%s", "Client closed connection"); | |
| 4964 | } else if (parse_http_message(conn->buf, conn->buf_size, | |
| 4965 | &conn->request_info) <= 0) { | |
| 4966 | snprintf(ebuf, ebuf_len, "Bad request: [%.*s]", conn->data_len, conn->buf); | |
| 4967 | } else { | |
| 4968 | // Request is valid | |
| 4969 | if ((cl = get_header(&conn->request_info, "Content-Length")) != NULL) { | |
| 4970 | conn->content_len = strtoll(cl, NULL, 10); | |
| 4971 | } else if (!mg_strcasecmp(conn->request_info.request_method, "POST") || | |
| 4972 | !mg_strcasecmp(conn->request_info.request_method, "PUT")) { | |
| 4973 | conn->content_len = -1; | |
| 4974 | } else { | |
| 4975 | conn->content_len = 0; | |
| 4976 | } | |
| 4977 | conn->birth_time = time(NULL); | |
| 4978 | } | |
| 4979 | return ebuf[0] == '\0'; | |
| 4957 | if (conn->request_len == 0 && conn->data_len == conn->buf_size) { | |
| 4958 | snprintf(ebuf, ebuf_len, "%s", "Request Too Large"); | |
| 4959 | } else if (conn->request_len <= 0) { | |
| 4960 | snprintf(ebuf, ebuf_len, "%s", "Client closed connection"); | |
| 4961 | } else if (parse_http_message(conn->buf, conn->buf_size, | |
| 4962 | &conn->request_info) <= 0) { | |
| 4963 | snprintf(ebuf, ebuf_len, "Bad request: [%.*s]", conn->data_len, conn->buf); | |
| 4964 | } else { | |
| 4965 | // Request is valid | |
| 4966 | if ((cl = get_header(&conn->request_info, "Content-Length")) != NULL) { | |
| 4967 | conn->content_len = strtoll(cl, NULL, 10); | |
| 4968 | } else if (!mg_strcasecmp(conn->request_info.request_method, "POST") || | |
| 4969 | !mg_strcasecmp(conn->request_info.request_method, "PUT")) { | |
| 4970 | conn->content_len = -1; | |
| 4971 | } else { | |
| 4972 | conn->content_len = 0; | |
| 4973 | } | |
| 4974 | conn->birth_time = time(NULL); | |
| 4975 | } | |
| 4976 | return ebuf[0] == '\0'; | |
| 4980 | 4977 | } |
| 4981 | 4978 | |
| 4982 | 4979 | struct mg_connection *mg_download(const char *host, int port, int use_ssl, |
| 4983 | char *ebuf, size_t ebuf_len, | |
| 4984 | const char *fmt, ...) { | |
| 4985 | struct mg_connection *conn; | |
| 4986 | va_list ap; | |
| 4980 | char *ebuf, size_t ebuf_len, | |
| 4981 | const char *fmt, ...) { | |
| 4982 | struct mg_connection *conn; | |
| 4983 | va_list ap; | |
| 4987 | 4984 | |
| 4988 | va_start(ap, fmt); | |
| 4989 | ebuf[0] = '\0'; | |
| 4990 | if ((conn = mg_connect(host, port, use_ssl, ebuf, ebuf_len)) == NULL) { | |
| 4991 | } else if (mg_vprintf(conn, fmt, ap) <= 0) { | |
| 4992 | snprintf(ebuf, ebuf_len, "%s", "Error sending request"); | |
| 4993 | } else { | |
| 4994 | getreq(conn, ebuf, ebuf_len); | |
| 4995 | } | |
| 4996 | if (ebuf[0] != '\0' && conn != NULL) { | |
| 4997 | mg_close_connection(conn); | |
| 4998 | conn = NULL; | |
| 4999 | } | |
| 4985 | va_start(ap, fmt); | |
| 4986 | ebuf[0] = '\0'; | |
| 4987 | if ((conn = mg_connect(host, port, use_ssl, ebuf, ebuf_len)) == NULL) { | |
| 4988 | } else if (mg_vprintf(conn, fmt, ap) <= 0) { | |
| 4989 | snprintf(ebuf, ebuf_len, "%s", "Error sending request"); | |
| 4990 | } else { | |
| 4991 | getreq(conn, ebuf, ebuf_len); | |
| 4992 | } | |
| 4993 | if (ebuf[0] != '\0' && conn != NULL) { | |
| 4994 | mg_close_connection(conn); | |
| 4995 | conn = NULL; | |
| 4996 | } | |
| 5000 | 4997 | |
| 5001 | ||
| 4998 | return conn; | |
| 5002 | 4999 | } |
| 5003 | 5000 | |
| 5004 | 5001 | static void process_new_connection(struct mg_connection *conn) { |
| 5005 | struct mg_request_info *ri = &conn->request_info; | |
| 5006 | int keep_alive_enabled, keep_alive, discard_len; | |
| 5007 | char ebuf[100]; | |
| 5002 | struct mg_request_info *ri = &conn->request_info; | |
| 5003 | int keep_alive_enabled, keep_alive, discard_len; | |
| 5004 | char ebuf[100]; | |
| 5008 | 5005 | |
| 5009 | keep_alive_enabled = !strcmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes"); | |
| 5010 | keep_alive = 0; | |
| 5006 | keep_alive_enabled = !strcmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes"); | |
| 5007 | keep_alive = 0; | |
| 5011 | 5008 | |
| 5012 | // Important: on new connection, reset the receiving buffer. Credit goes | |
| 5013 | // to crule42. | |
| 5014 | conn->data_len = 0; | |
| 5015 | do { | |
| 5016 | if (!getreq(conn, ebuf, sizeof(ebuf))) { | |
| 5017 | send_http_error(conn, 500, "Server Error", "%s", ebuf); | |
| 5018 | conn->must_close = 1; | |
| 5019 | } else if (!is_valid_uri(conn->request_info.uri)) { | |
| 5020 | snprintf(ebuf, sizeof(ebuf), "Invalid URI: [%s]", ri->uri); | |
| 5021 | send_http_error(conn, 400, "Bad Request", "%s", ebuf); | |
| 5022 | } else if (strcmp(ri->http_version, "1.0") && | |
| 5023 | strcmp(ri->http_version, "1.1")) { | |
| 5024 | snprintf(ebuf, sizeof(ebuf), "Bad HTTP version: [%s]", ri->http_version); | |
| 5025 | send_http_error(conn, 505, "Bad HTTP version", "%s", ebuf); | |
| 5026 | } | |
| 5009 | // Important: on new connection, reset the receiving buffer. Credit goes | |
| 5010 | // to crule42. | |
| 5011 | conn->data_len = 0; | |
| 5012 | do { | |
| 5013 | if (!getreq(conn, ebuf, sizeof(ebuf))) { | |
| 5014 | send_http_error(conn, 500, "Server Error", "%s", ebuf); | |
| 5015 | conn->must_close = 1; | |
| 5016 | } else if (!is_valid_uri(conn->request_info.uri)) { | |
| 5017 | snprintf(ebuf, sizeof(ebuf), "Invalid URI: [%s]", ri->uri); | |
| 5018 | send_http_error(conn, 400, "Bad Request", "%s", ebuf); | |
| 5019 | } else if (strcmp(ri->http_version, "1.0") && | |
| 5020 | strcmp(ri->http_version, "1.1")) { | |
| 5021 | snprintf(ebuf, sizeof(ebuf), "Bad HTTP version: [%s]", ri->http_version); | |
| 5022 | send_http_error(conn, 505, "Bad HTTP version", "%s", ebuf); | |
| 5023 | } | |
| 5027 | 5024 | |
| 5028 | if (ebuf[0] == '\0') { | |
| 5029 | handle_request(conn); | |
| 5030 | if (conn->ctx->callbacks.end_request != NULL) { | |
| 5031 | conn->ctx->callbacks.end_request(conn, conn->status_code); | |
| 5032 | } | |
| 5033 | log_access(conn); | |
| 5034 | } | |
| 5035 | if (ri->remote_user != NULL) { | |
| 5036 | free((void *) ri->remote_user); | |
| 5037 | // Important! When having connections with and without auth | |
| 5038 | // would cause double free and then crash | |
| 5039 | ri->remote_user = NULL; | |
| 5040 | } | |
| 5025 | if (ebuf[0] == '\0') { | |
| 5026 | handle_request(conn); | |
| 5027 | if (conn->ctx->callbacks.end_request != NULL) { | |
| 5028 | conn->ctx->callbacks.end_request(conn, conn->status_code); | |
| 5029 | } | |
| 5030 | log_access(conn); | |
| 5031 | } | |
| 5032 | if (ri->remote_user != NULL) { | |
| 5033 | free((void *) ri->remote_user); | |
| 5034 | // Important! When having connections with and without auth | |
| 5035 | // would cause double free and then crash | |
| 5036 | ri->remote_user = NULL; | |
| 5037 | } | |
| 5041 | 5038 | |
| 5042 | // NOTE(lsm): order is important here. should_keep_alive() call | |
| 5043 | // is using parsed request, which will be invalid after memmove's below. | |
| 5044 | // Therefore, memorize should_keep_alive() result now for later use | |
| 5045 | // in loop exit condition. | |
| 5046 | keep_alive = conn->ctx->stop_flag == 0 && keep_alive_enabled && | |
| 5047 | conn->content_len >= 0 && should_keep_alive(conn); | |
| 5039 | // NOTE(lsm): order is important here. should_keep_alive() call | |
| 5040 | // is using parsed request, which will be invalid after memmove's below. | |
| 5041 | // Therefore, memorize should_keep_alive() result now for later use | |
| 5042 | // in loop exit condition. | |
| 5043 | keep_alive = conn->ctx->stop_flag == 0 && keep_alive_enabled && | |
| 5044 | conn->content_len >= 0 && should_keep_alive(conn); | |
| 5048 | 5045 | |
| 5049 | // Discard all buffered data for this request | |
| 5050 | discard_len = conn->content_len >= 0 && conn->request_len > 0 && | |
| 5051 | conn->request_len + conn->content_len < (int64_t) conn->data_len ? | |
| 5052 | (int) (conn->request_len + conn->content_len) : conn->data_len; | |
| 5053 | assert(discard_len >= 0); | |
| 5054 | memmove(conn->buf, conn->buf + discard_len, conn->data_len - discard_len); | |
| 5055 | conn->data_len -= discard_len; | |
| 5056 | assert(conn->data_len >= 0); | |
| 5057 | assert(conn->data_len <= conn->buf_size); | |
| 5058 | } while (keep_alive); | |
| 5046 | // Discard all buffered data for this request | |
| 5047 | discard_len = conn->content_len >= 0 && conn->request_len > 0 && | |
| 5048 | conn->request_len + conn->content_len < (int64_t) conn->data_len ? | |
| 5049 | (int) (conn->request_len + conn->content_len) : conn->data_len; | |
| 5050 | assert(discard_len >= 0); | |
| 5051 | memmove(conn->buf, conn->buf + discard_len, conn->data_len - discard_len); | |
| 5052 | conn->data_len -= discard_len; | |
| 5053 | assert(conn->data_len >= 0); | |
| 5054 | assert(conn->data_len <= conn->buf_size); | |
| 5055 | } while (keep_alive); | |
| 5059 | 5056 | } |
| 5060 | 5057 | |
| 5061 | 5058 | // Worker threads take accepted socket from the queue |
| 5062 | 5059 | static int consume_socket(struct mg_context *ctx, struct socket *sp) { |
| 5063 | (void) pthread_mutex_lock(&ctx->mutex); | |
| 5064 | DEBUG_TRACE(("going idle")); | |
| 5060 | (void) pthread_mutex_lock(&ctx->mutex); | |
| 5061 | DEBUG_TRACE(("going idle")); | |
| 5065 | 5062 | |
| 5066 | // If the queue is empty, wait. We're idle at this point. | |
| 5067 | while (ctx->sq_head == ctx->sq_tail && ctx->stop_flag == 0) { | |
| 5068 | pthread_cond_wait(&ctx->sq_full, &ctx->mutex); | |
| 5069 | } | |
| 5063 | // If the queue is empty, wait. We're idle at this point. | |
| 5064 | while (ctx->sq_head == ctx->sq_tail && ctx->stop_flag == 0) { | |
| 5065 | pthread_cond_wait(&ctx->sq_full, &ctx->mutex); | |
| 5066 | } | |
| 5070 | 5067 | |
| 5071 | // If we're stopping, sq_head may be equal to sq_tail. | |
| 5072 | if (ctx->sq_head > ctx->sq_tail) { | |
| 5073 | // Copy socket from the queue and increment tail | |
| 5074 | *sp = ctx->queue[ctx->sq_tail % ARRAY_SIZE(ctx->queue)]; | |
| 5075 | ctx->sq_tail++; | |
| 5076 | DEBUG_TRACE(("grabbed socket %d, going busy", sp->sock)); | |
| 5068 | // If we're stopping, sq_head may be equal to sq_tail. | |
| 5069 | if (ctx->sq_head > ctx->sq_tail) { | |
| 5070 | // Copy socket from the queue and increment tail | |
| 5071 | *sp = ctx->queue[ctx->sq_tail % ARRAY_SIZE(ctx->queue)]; | |
| 5072 | ctx->sq_tail++; | |
| 5073 | DEBUG_TRACE(("grabbed socket %d, going busy", sp->sock)); | |
| 5077 | 5074 | |
| 5078 | // Wrap pointers if needed | |
| 5079 | while (ctx->sq_tail > (int) ARRAY_SIZE(ctx->queue)) { | |
| 5080 | ctx->sq_tail -= ARRAY_SIZE(ctx->queue); | |
| 5081 | ctx->sq_head -= ARRAY_SIZE(ctx->queue); | |
| 5082 | } | |
| 5083 | } | |
| 5075 | // Wrap pointers if needed | |
| 5076 | while (ctx->sq_tail > (int) ARRAY_SIZE(ctx->queue)) { | |
| 5077 | ctx->sq_tail -= ARRAY_SIZE(ctx->queue); | |
| 5078 | ctx->sq_head -= ARRAY_SIZE(ctx->queue); | |
| 5079 | } | |
| 5080 | } | |
| 5084 | 5081 | |
| 5085 | (void) pthread_cond_signal(&ctx->sq_empty); | |
| 5086 | (void) pthread_mutex_unlock(&ctx->mutex); | |
| 5082 | (void) pthread_cond_signal(&ctx->sq_empty); | |
| 5083 | (void) pthread_mutex_unlock(&ctx->mutex); | |
| 5087 | 5084 | |
| 5088 | ||
| 5085 | return !ctx->stop_flag; | |
| 5089 | 5086 | } |
| 5090 | 5087 | |
| 5091 | 5088 | static void *worker_thread(void *thread_func_param) { |
| 5092 | struct mg_context *ctx = (struct mg_context *)thread_func_param; | |
| 5093 | struct mg_connection *conn; | |
| 5089 | struct mg_context *ctx = (struct mg_context *)thread_func_param; | |
| 5090 | struct mg_connection *conn; | |
| 5094 | 5091 | |
| 5095 | conn = (struct mg_connection *) calloc(1, sizeof(*conn) + MAX_REQUEST_SIZE); | |
| 5096 | if (conn == NULL) { | |
| 5097 | cry(fc(ctx), "%s", "Cannot create new connection struct, OOM"); | |
| 5098 | } else { | |
| 5099 | conn->buf_size = MAX_REQUEST_SIZE; | |
| 5100 | conn->buf = (char *) (conn + 1); | |
| 5101 | conn->ctx = ctx; | |
| 5102 | conn->request_info.user_data = ctx->user_data; | |
| 5092 | conn = (struct mg_connection *) calloc(1, sizeof(*conn) + MAX_REQUEST_SIZE); | |
| 5093 | if (conn == NULL) { | |
| 5094 | cry(fc(ctx), "%s", "Cannot create new connection struct, OOM"); | |
| 5095 | } else { | |
| 5096 | conn->buf_size = MAX_REQUEST_SIZE; | |
| 5097 | conn->buf = (char *) (conn + 1); | |
| 5098 | conn->ctx = ctx; | |
| 5099 | conn->request_info.user_data = ctx->user_data; | |
| 5103 | 5100 | |
| 5104 | // Call consume_socket() even when ctx->stop_flag > 0, to let it signal | |
| 5105 | // sq_empty condvar to wake up the master waiting in produce_socket() | |
| 5106 | while (consume_socket(ctx, &conn->client)) { | |
| 5107 | conn->birth_time = time(NULL); | |
| 5101 | // Call consume_socket() even when ctx->stop_flag > 0, to let it signal | |
| 5102 | // sq_empty condvar to wake up the master waiting in produce_socket() | |
| 5103 | while (consume_socket(ctx, &conn->client)) { | |
| 5104 | conn->birth_time = time(NULL); | |
| 5108 | 5105 | |
| 5109 | // Fill in IP, port info early so even if SSL setup below fails, | |
| 5110 | // error handler would have the corresponding info. | |
| 5111 | // Thanks to Johannes Winkelmann for the patch. | |
| 5112 | // TODO(lsm): Fix IPv6 case | |
| 5113 | conn->request_info.remote_port = ntohs(conn->client.rsa.sin.sin_port); | |
| 5114 | memcpy(&conn->request_info.remote_ip, | |
| 5115 | &conn->client.rsa.sin.sin_addr.s_addr, 4); | |
| 5116 | conn->request_info.remote_ip = ntohl(conn->request_info.remote_ip); | |
| 5117 | conn->request_info.is_ssl = conn->client.is_ssl; | |
| 5106 | // Fill in IP, port info early so even if SSL setup below fails, | |
| 5107 | // error handler would have the corresponding info. | |
| 5108 | // Thanks to Johannes Winkelmann for the patch. | |
| 5109 | // TODO(lsm): Fix IPv6 case | |
| 5110 | conn->request_info.remote_port = ntohs(conn->client.rsa.sin.sin_port); | |
| 5111 | memcpy(&conn->request_info.remote_ip, | |
| 5112 | &conn->client.rsa.sin.sin_addr.s_addr, 4); | |
| 5113 | conn->request_info.remote_ip = ntohl(conn->request_info.remote_ip); | |
| 5114 | conn->request_info.is_ssl = conn->client.is_ssl; | |
| 5118 | 5115 | |
| 5119 | ||
| 5116 | if (!conn->client.is_ssl | |
| 5120 | 5117 | #ifndef NO_SSL |
| 5121 | ||
| 5118 | || sslize(conn, conn->ctx->ssl_ctx, SSL_accept) | |
| 5122 | 5119 | #endif |
| 5123 | ) { | |
| 5124 | process_new_connection(conn); | |
| 5125 | } | |
| 5120 | ) { | |
| 5121 | process_new_connection(conn); | |
| 5122 | } | |
| 5126 | 5123 | |
| 5127 | close_connection(conn); | |
| 5128 | } | |
| 5129 | free(conn); | |
| 5130 | } | |
| 5124 | close_connection(conn); | |
| 5125 | } | |
| 5126 | free(conn); | |
| 5127 | } | |
| 5131 | 5128 | |
| 5132 | // Signal master that we're done with connection and exiting | |
| 5133 | (void) pthread_mutex_lock(&ctx->mutex); | |
| 5134 | ctx->num_threads--; | |
| 5135 | (void) pthread_cond_signal(&ctx->cond); | |
| 5136 | assert(ctx->num_threads >= 0); | |
| 5137 | (void) pthread_mutex_unlock(&ctx->mutex); | |
| 5129 | // Signal master that we're done with connection and exiting | |
| 5130 | (void) pthread_mutex_lock(&ctx->mutex); | |
| 5131 | ctx->num_threads--; | |
| 5132 | (void) pthread_cond_signal(&ctx->cond); | |
| 5133 | assert(ctx->num_threads >= 0); | |
| 5134 | (void) pthread_mutex_unlock(&ctx->mutex); | |
| 5138 | 5135 | |
| 5139 | DEBUG_TRACE(("exiting")); | |
| 5140 | return NULL; | |
| 5136 | DEBUG_TRACE(("exiting")); | |
| 5137 | return NULL; | |
| 5141 | 5138 | } |
| 5142 | 5139 | |
| 5143 | 5140 | // Master thread adds accepted socket to a queue |
| 5144 | 5141 | static void produce_socket(struct mg_context *ctx, const struct socket *sp) { |
| 5145 | ||
| 5142 | (void) pthread_mutex_lock(&ctx->mutex); | |
| 5146 | 5143 | |
| 5147 | // If the queue is full, wait | |
| 5148 | while (ctx->stop_flag == 0 && | |
| 5149 | ctx->sq_head - ctx->sq_tail >= (int) ARRAY_SIZE(ctx->queue)) { | |
| 5150 | (void) pthread_cond_wait(&ctx->sq_empty, &ctx->mutex); | |
| 5151 | } | |
| 5144 | // If the queue is full, wait | |
| 5145 | while (ctx->stop_flag == 0 && | |
| 5146 | ctx->sq_head - ctx->sq_tail >= (int) ARRAY_SIZE(ctx->queue)) { | |
| 5147 | (void) pthread_cond_wait(&ctx->sq_empty, &ctx->mutex); | |
| 5148 | } | |
| 5152 | 5149 | |
| 5153 | if (ctx->sq_head - ctx->sq_tail < (int) ARRAY_SIZE(ctx->queue)) { | |
| 5154 | // Copy socket to the queue and increment head | |
| 5155 | ctx->queue[ctx->sq_head % ARRAY_SIZE(ctx->queue)] = *sp; | |
| 5156 | ctx->sq_head++; | |
| 5157 | DEBUG_TRACE(("queued socket %d", sp->sock)); | |
| 5158 | } | |
| 5150 | if (ctx->sq_head - ctx->sq_tail < (int) ARRAY_SIZE(ctx->queue)) { | |
| 5151 | // Copy socket to the queue and increment head | |
| 5152 | ctx->queue[ctx->sq_head % ARRAY_SIZE(ctx->queue)] = *sp; | |
| 5153 | ctx->sq_head++; | |
| 5154 | DEBUG_TRACE(("queued socket %d", sp->sock)); | |
| 5155 | } | |
| 5159 | 5156 | |
| 5160 | (void) pthread_cond_signal(&ctx->sq_full); | |
| 5161 | (void) pthread_mutex_unlock(&ctx->mutex); | |
| 5157 | (void) pthread_cond_signal(&ctx->sq_full); | |
| 5158 | (void) pthread_mutex_unlock(&ctx->mutex); | |
| 5162 | 5159 | } |
| 5163 | 5160 | |
| 5164 | 5161 | static int set_sock_timeout(SOCKET sock, int milliseconds) { |
| 5165 | 5162 | #ifdef _WIN32 |
| 5166 | ||
| 5163 | DWORD t = milliseconds; | |
| 5167 | 5164 | #else |
| 5168 | struct timeval t; | |
| 5169 | t.tv_sec = milliseconds / 1000; | |
| 5170 | t.tv_usec = (milliseconds * 1000) % 1000000; | |
| 5165 | struct timeval t; | |
| 5166 | t.tv_sec = milliseconds / 1000; | |
| 5167 | t.tv_usec = (milliseconds * 1000) % 1000000; | |
| 5171 | 5168 | #endif |
| 5172 | return setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (SETSOCKOPT_CAST) &t, sizeof(t)) || | |
| 5173 | setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (SETSOCKOPT_CAST) &t, sizeof(t)); | |
| 5169 | return setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (SETSOCKOPT_CAST) &t, sizeof(t)) || | |
| 5170 | setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (SETSOCKOPT_CAST) &t, sizeof(t)); | |
| 5174 | 5171 | } |
| 5175 | 5172 | |
| 5176 | 5173 | static void accept_new_connection(const struct socket *listener, |
| 5177 | struct mg_context *ctx) { | |
| 5178 | struct socket so; | |
| 5179 | char src_addr[IP_ADDR_STR_LEN]; | |
| 5180 | socklen_t len = sizeof(so.rsa); | |
| 5181 | int on = 1; | |
| 5174 | struct mg_context *ctx) { | |
| 5175 | struct socket so; | |
| 5176 | char src_addr[IP_ADDR_STR_LEN]; | |
| 5177 | socklen_t len = sizeof(so.rsa); | |
| 5178 | int on = 1; | |
| 5182 | 5179 | |
| 5183 | if ((so.sock = accept(listener->sock, &so.rsa.sa, &len)) == INVALID_SOCKET) { | |
| 5184 | } else if (!check_acl(ctx, ntohl(* (uint32_t *) &so.rsa.sin.sin_addr))) { | |
| 5185 | sockaddr_to_string(src_addr, sizeof(src_addr), &so.rsa); | |
| 5186 | cry(fc(ctx), "%s: %s is not allowed to connect", __func__, src_addr); | |
| 5187 | closesocket(so.sock); | |
| 5188 | } else { | |
| 5189 | // Put so socket structure into the queue | |
| 5190 | DEBUG_TRACE(("Accepted socket %d", (int) so.sock)); | |
| 5191 | so.is_ssl = listener->is_ssl; | |
| 5192 | so.ssl_redir = listener->ssl_redir; | |
| 5193 | getsockname(so.sock, &so.lsa.sa, &len); | |
| 5194 | // Set TCP keep-alive. This is needed because if HTTP-level keep-alive | |
| 5195 | // is enabled, and client resets the connection, server won't get | |
| 5196 | // TCP FIN or RST and will keep the connection open forever. With TCP | |
| 5197 | // keep-alive, next keep-alive handshake will figure out that the client | |
| 5198 | // is down and will close the server end. | |
| 5199 | // Thanks to Igor Klopov who suggested the patch. | |
| 5200 | setsockopt(so.sock, SOL_SOCKET, SO_KEEPALIVE, (SETSOCKOPT_CAST) &on, sizeof(on)); | |
| 5201 | set_sock_timeout(so.sock, atoi(ctx->config[REQUEST_TIMEOUT])); | |
| 5202 | produce_socket(ctx, &so); | |
| 5203 | } | |
| 5180 | if ((so.sock = accept(listener->sock, &so.rsa.sa, &len)) == INVALID_SOCKET) { | |
| 5181 | } else if (!check_acl(ctx, ntohl(* (uint32_t *) &so.rsa.sin.sin_addr))) { | |
| 5182 | sockaddr_to_string(src_addr, sizeof(src_addr), &so.rsa); | |
| 5183 | cry(fc(ctx), "%s: %s is not allowed to connect", __func__, src_addr); | |
| 5184 | closesocket(so.sock); | |
| 5185 | } else { | |
| 5186 | // Put so socket structure into the queue | |
| 5187 | DEBUG_TRACE(("Accepted socket %d", (int) so.sock)); | |
| 5188 | so.is_ssl = listener->is_ssl; | |
| 5189 | so.ssl_redir = listener->ssl_redir; | |
| 5190 | getsockname(so.sock, &so.lsa.sa, &len); | |
| 5191 | // Set TCP keep-alive. This is needed because if HTTP-level keep-alive | |
| 5192 | // is enabled, and client resets the connection, server won't get | |
| 5193 | // TCP FIN or RST and will keep the connection open forever. With TCP | |
| 5194 | // keep-alive, next keep-alive handshake will figure out that the client | |
| 5195 | // is down and will close the server end. | |
| 5196 | // Thanks to Igor Klopov who suggested the patch. | |
| 5197 | setsockopt(so.sock, SOL_SOCKET, SO_KEEPALIVE, (SETSOCKOPT_CAST) &on, sizeof(on)); | |
| 5198 | set_sock_timeout(so.sock, atoi(ctx->config[REQUEST_TIMEOUT])); | |
| 5199 | produce_socket(ctx, &so); | |
| 5200 | } | |
| 5204 | 5201 | } |
| 5205 | 5202 | |
| 5206 | 5203 | static void *master_thread(void *thread_func_param) { |
| 5207 | struct mg_context *ctx = (struct mg_context *)thread_func_param; | |
| 5208 | struct pollfd *pfd; | |
| 5209 | int i; | |
| 5204 | struct mg_context *ctx = (struct mg_context *)thread_func_param; | |
| 5205 | struct pollfd *pfd; | |
| 5206 | int i; | |
| 5210 | 5207 | |
| 5211 | ||
| 5208 | // Increase priority of the master thread | |
| 5212 | 5209 | #if defined(_WIN32) |
| 5213 | ||
| 5210 | SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); | |
| 5214 | 5211 | #endif |
| 5215 | 5212 | |
| 5216 | 5213 | #if defined(ISSUE_317) |
| 5217 | struct sched_param sched_param; | |
| 5218 | sched_param.sched_priority = sched_get_priority_max(SCHED_RR); | |
| 5219 | pthread_setschedparam(pthread_self(), SCHED_RR, &sched_param); | |
| 5214 | struct sched_param sched_param; | |
| 5215 | sched_param.sched_priority = sched_get_priority_max(SCHED_RR); | |
| 5216 | pthread_setschedparam(pthread_self(), SCHED_RR, &sched_param); | |
| 5220 | 5217 | #endif |
| 5221 | 5218 | |
| 5222 | pfd = (struct pollfd *)calloc(ctx->num_listening_sockets, sizeof(pfd[0])); | |
| 5223 | while (pfd != NULL && ctx->stop_flag == 0) { | |
| 5224 | for (i = 0; i < ctx->num_listening_sockets; i++) { | |
| 5225 | pfd[i].fd = ctx->listening_sockets[i].sock; | |
| 5226 | pfd[i].events = POLLIN; | |
| 5227 | } | |
| 5219 | pfd = (struct pollfd *)calloc(ctx->num_listening_sockets, sizeof(pfd[0])); | |
| 5220 | while (pfd != NULL && ctx->stop_flag == 0) { | |
| 5221 | for (i = 0; i < ctx->num_listening_sockets; i++) { | |
| 5222 | pfd[i].fd = ctx->listening_sockets[i].sock; | |
| 5223 | pfd[i].events = POLLIN; | |
| 5224 | } | |
| 5228 | 5225 | |
| 5229 | if (poll(pfd, ctx->num_listening_sockets, 200) > 0) { | |
| 5230 | for (i = 0; i < ctx->num_listening_sockets; i++) { | |
| 5231 | // NOTE(lsm): on QNX, poll() returns POLLRDNORM after the | |
| 5232 | // successfull poll, and POLLIN is defined as (POLLRDNORM | POLLRDBAND) | |
| 5233 | // Therefore, we're checking pfd[i].revents & POLLIN, not | |
| 5234 | // pfd[i].revents == POLLIN. | |
| 5235 | if (ctx->stop_flag == 0 && (pfd[i].revents & POLLIN)) { | |
| 5236 | accept_new_connection(&ctx->listening_sockets[i], ctx); | |
| 5237 | } | |
| 5238 | } | |
| 5239 | } | |
| 5240 | } | |
| 5241 | free(pfd); | |
| 5242 | DEBUG_TRACE(("stopping workers")); | |
| 5226 | if (poll(pfd, ctx->num_listening_sockets, 200) > 0) { | |
| 5227 | for (i = 0; i < ctx->num_listening_sockets; i++) { | |
| 5228 | // NOTE(lsm): on QNX, poll() returns POLLRDNORM after the | |
| 5229 | // successfull poll, and POLLIN is defined as (POLLRDNORM | POLLRDBAND) | |
| 5230 | // Therefore, we're checking pfd[i].revents & POLLIN, not | |
| 5231 | // pfd[i].revents == POLLIN. | |
| 5232 | if (ctx->stop_flag == 0 && (pfd[i].revents & POLLIN)) { | |
| 5233 | accept_new_connection(&ctx->listening_sockets[i], ctx); | |
| 5234 | } | |
| 5235 | } | |
| 5236 | } | |
| 5237 | } | |
| 5238 | free(pfd); | |
| 5239 | DEBUG_TRACE(("stopping workers")); | |
| 5243 | 5240 | |
| 5244 | // Stop signal received: somebody called mg_stop. Quit. | |
| 5245 | close_all_listening_sockets(ctx); | |
| 5241 | // Stop signal received: somebody called mg_stop. Quit. | |
| 5242 | close_all_listening_sockets(ctx); | |
| 5246 | 5243 | |
| 5247 | // Wakeup workers that are waiting for connections to handle. | |
| 5248 | pthread_cond_broadcast(&ctx->sq_full); | |
| 5244 | // Wakeup workers that are waiting for connections to handle. | |
| 5245 | pthread_cond_broadcast(&ctx->sq_full); | |
| 5249 | 5246 | |
| 5250 | // Wait until all threads finish | |
| 5251 | (void) pthread_mutex_lock(&ctx->mutex); | |
| 5252 | while (ctx->num_threads > 0) { | |
| 5253 | (void) pthread_cond_wait(&ctx->cond, &ctx->mutex); | |
| 5254 | } | |
| 5255 | (void) pthread_mutex_unlock(&ctx->mutex); | |
| 5247 | // Wait until all threads finish | |
| 5248 | (void) pthread_mutex_lock(&ctx->mutex); | |
| 5249 | while (ctx->num_threads > 0) { | |
| 5250 | (void) pthread_cond_wait(&ctx->cond, &ctx->mutex); | |
| 5251 | } | |
| 5252 | (void) pthread_mutex_unlock(&ctx->mutex); | |
| 5256 | 5253 | |
| 5257 | // All threads exited, no sync is needed. Destroy mutex and condvars | |
| 5258 | (void) pthread_mutex_destroy(&ctx->mutex); | |
| 5259 | (void) pthread_cond_destroy(&ctx->cond); | |
| 5260 | (void) pthread_cond_destroy(&ctx->sq_empty); | |
| 5261 | (void) pthread_cond_destroy(&ctx->sq_full); | |
| 5254 | // All threads exited, no sync is needed. Destroy mutex and condvars | |
| 5255 | (void) pthread_mutex_destroy(&ctx->mutex); | |
| 5256 | (void) pthread_cond_destroy(&ctx->cond); | |
| 5257 | (void) pthread_cond_destroy(&ctx->sq_empty); | |
| 5258 | (void) pthread_cond_destroy(&ctx->sq_full); | |
| 5262 | 5259 | |
| 5263 | 5260 | #if !defined(NO_SSL) |
| 5264 | ||
| 5261 | uninitialize_ssl(ctx); | |
| 5265 | 5262 | #endif |
| 5266 | ||
| 5263 | DEBUG_TRACE(("exiting")); | |
| 5267 | 5264 | |
| 5268 | // Signal mg_stop() that we're done. | |
| 5269 | // WARNING: This must be the very last thing this | |
| 5270 | // thread does, as ctx becomes invalid after this line. | |
| 5271 | ctx->stop_flag = 2; | |
| 5272 | return NULL; | |
| 5265 | // Signal mg_stop() that we're done. | |
| 5266 | // WARNING: This must be the very last thing this | |
| 5267 | // thread does, as ctx becomes invalid after this line. | |
| 5268 | ctx->stop_flag = 2; | |
| 5269 | return NULL; | |
| 5273 | 5270 | } |
| 5274 | 5271 | |
| 5275 | 5272 | static void free_context(struct mg_context *ctx) { |
| 5276 | ||
| 5273 | int i; | |
| 5277 | 5274 | |
| 5278 | // Deallocate config parameters | |
| 5279 | for (i = 0; i < NUM_OPTIONS; i++) { | |
| 5280 | if (ctx->config[i] != NULL) | |
| 5281 | free(ctx->config[i]); | |
| 5282 | } | |
| 5275 | // Deallocate config parameters | |
| 5276 | for (i = 0; i < NUM_OPTIONS; i++) { | |
| 5277 | if (ctx->config[i] != NULL) | |
| 5278 | free(ctx->config[i]); | |
| 5279 | } | |
| 5283 | 5280 | |
| 5284 | 5281 | #ifndef NO_SSL |
| 5285 | // Deallocate SSL context | |
| 5286 | if (ctx->ssl_ctx != NULL) { | |
| 5287 | SSL_CTX_free(ctx->ssl_ctx); | |
| 5288 | } | |
| 5289 | if (ssl_mutexes != NULL) { | |
| 5290 | free(ssl_mutexes); | |
| 5291 | ssl_mutexes = NULL; | |
| 5292 | } | |
| 5282 | // Deallocate SSL context | |
| 5283 | if (ctx->ssl_ctx != NULL) { | |
| 5284 | SSL_CTX_free(ctx->ssl_ctx); | |
| 5285 | } | |
| 5286 | if (ssl_mutexes != NULL) { | |
| 5287 | free(ssl_mutexes); | |
| 5288 | ssl_mutexes = NULL; | |
| 5289 | } | |
| 5293 | 5290 | #endif // !NO_SSL |
| 5294 | 5291 | |
| 5295 | // Deallocate context itself | |
| 5296 | free(ctx); | |
| 5292 | // Deallocate context itself | |
| 5293 | free(ctx); | |
| 5297 | 5294 | } |
| 5298 | 5295 | |
| 5299 | 5296 | void mg_stop(struct mg_context *ctx) { |
| 5300 | 5297 | if (!ctx) return; |
| 5301 | ||
| 5298 | ctx->stop_flag = 1; | |
| 5302 | 5299 | |
| 5303 | // Wait until mg_fini() stops | |
| 5304 | while (ctx->stop_flag != 2) { | |
| 5305 | (void) mg_sleep(10); | |
| 5306 | } | |
| 5307 | free_context(ctx); | |
| 5300 | // Wait until mg_fini() stops | |
| 5301 | while (ctx->stop_flag != 2) { | |
| 5302 | (void) mg_sleep(10); | |
| 5303 | } | |
| 5304 | free_context(ctx); | |
| 5308 | 5305 | |
| 5309 | 5306 | #if defined(_WIN32) && !defined(__SYMBIAN32__) |
| 5310 | ||
| 5307 | (void) WSACleanup(); | |
| 5311 | 5308 | #endif // _WIN32 |
| 5312 | 5309 | } |
| 5313 | 5310 | |
| 5314 | 5311 | struct mg_context *mg_start(const struct mg_callbacks *callbacks, |
| 5315 | void *user_data, | |
| 5316 | const char **options) { | |
| 5317 | struct mg_context *ctx; | |
| 5318 | const char *name, *value, *default_value; | |
| 5319 | int i; | |
| 5312 | void *user_data, | |
| 5313 | const char **options) { | |
| 5314 | struct mg_context *ctx; | |
| 5315 | const char *name, *value, *default_value; | |
| 5316 | int i; | |
| 5320 | 5317 | |
| 5321 | 5318 | #if defined(_WIN32) && !defined(__SYMBIAN32__) |
| 5322 | WSADATA data; | |
| 5323 | WSAStartup(MAKEWORD(2,2), &data); | |
| 5324 | InitializeCriticalSection(&global_log_file_lock); | |
| 5319 | WSADATA data; | |
| 5320 | WSAStartup(MAKEWORD(2,2), &data); | |
| 5321 | InitializeCriticalSection(&global_log_file_lock); | |
| 5325 | 5322 | #endif // _WIN32 |
| 5326 | 5323 | |
| 5327 | // Allocate context and initialize reasonable general case defaults. | |
| 5328 | // TODO(lsm): do proper error handling here. | |
| 5329 | if ((ctx = (struct mg_context *) calloc(1, sizeof(*ctx))) == NULL) { | |
| 5330 | return NULL; | |
| 5331 | } | |
| 5332 | ctx->callbacks = *callbacks; | |
| 5333 | ctx->user_data = user_data; | |
| 5324 | // Allocate context and initialize reasonable general case defaults. | |
| 5325 | // TODO(lsm): do proper error handling here. | |
| 5326 | if ((ctx = (struct mg_context *) calloc(1, sizeof(*ctx))) == NULL) { | |
| 5327 | return NULL; | |
| 5328 | } | |
| 5329 | ctx->callbacks = *callbacks; | |
| 5330 | ctx->user_data = user_data; | |
| 5334 | 5331 | |
| 5335 | while (options && (name = *options++) != NULL) { | |
| 5336 | if ((i = get_option_index(name)) == -1) { | |
| 5337 | cry(fc(ctx), "Invalid option: %s", name); | |
| 5338 | free_context(ctx); | |
| 5339 | return NULL; | |
| 5340 | } else if ((value = *options++) == NULL) { | |
| 5341 | cry(fc(ctx), "%s: option value cannot be NULL", name); | |
| 5342 | free_context(ctx); | |
| 5343 | return NULL; | |
| 5344 | } | |
| 5345 | if (ctx->config[i] != NULL) { | |
| 5346 | cry(fc(ctx), "warning: %s: duplicate option", name); | |
| 5347 | free(ctx->config[i]); | |
| 5348 | } | |
| 5349 | ctx->config[i] = mg_strdup(value); | |
| 5350 | DEBUG_TRACE(("[%s] -> [%s]", name, value)); | |
| 5351 | } | |
| 5332 | while (options && (name = *options++) != NULL) { | |
| 5333 | if ((i = get_option_index(name)) == -1) { | |
| 5334 | cry(fc(ctx), "Invalid option: %s", name); | |
| 5335 | free_context(ctx); | |
| 5336 | return NULL; | |
| 5337 | } else if ((value = *options++) == NULL) { | |
| 5338 | cry(fc(ctx), "%s: option value cannot be NULL", name); | |
| 5339 | free_context(ctx); | |
| 5340 | return NULL; | |
| 5341 | } | |
| 5342 | if (ctx->config[i] != NULL) { | |
| 5343 | cry(fc(ctx), "warning: %s: duplicate option", name); | |
| 5344 | free(ctx->config[i]); | |
| 5345 | } | |
| 5346 | ctx->config[i] = mg_strdup(value); | |
| 5347 | DEBUG_TRACE(("[%s] -> [%s]", name, value)); | |
| 5348 | } | |
| 5352 | 5349 | |
| 5353 | // Set default value if needed | |
| 5354 | for (i = 0; config_options[i * 2] != NULL; i++) { | |
| 5355 | default_value = config_options[i * 2 + 1]; | |
| 5356 | if (ctx->config[i] == NULL && default_value != NULL) { | |
| 5357 | ctx->config[i] = mg_strdup(default_value); | |
| 5358 | } | |
| 5359 | } | |
| 5350 | // Set default value if needed | |
| 5351 | for (i = 0; config_options[i * 2] != NULL; i++) { | |
| 5352 | default_value = config_options[i * 2 + 1]; | |
| 5353 | if (ctx->config[i] == NULL && default_value != NULL) { | |
| 5354 | ctx->config[i] = mg_strdup(default_value); | |
| 5355 | } | |
| 5356 | } | |
| 5360 | 5357 | |
| 5361 | // NOTE(lsm): order is important here. SSL certificates must | |
| 5362 | // be initialized before listening ports. UID must be set last. | |
| 5363 | if (!set_gpass_option(ctx) || | |
| 5358 | // NOTE(lsm): order is important here. SSL certificates must | |
| 5359 | // be initialized before listening ports. UID must be set last. | |
| 5360 | if (!set_gpass_option(ctx) || | |
| 5364 | 5361 | #if !defined(NO_SSL) |
| 5365 | ||
| 5362 | !set_ssl_option(ctx) || | |
| 5366 | 5363 | #endif |
| 5367 | ||
| 5364 | !set_ports_option(ctx) || | |
| 5368 | 5365 | #if !defined(_WIN32) |
| 5369 | ||
| 5366 | !set_uid_option(ctx) || | |
| 5370 | 5367 | #endif |
| 5371 | !set_acl_option(ctx)) { | |
| 5372 | free_context(ctx); | |
| 5373 | return NULL; | |
| 5374 | } | |
| 5368 | !set_acl_option(ctx)) { | |
| 5369 | free_context(ctx); | |
| 5370 | return NULL; | |
| 5371 | } | |
| 5375 | 5372 | |
| 5376 | 5373 | #if !defined(_WIN32) && !defined(__SYMBIAN32__) |
| 5377 | // Ignore SIGPIPE signal, so if browser cancels the request, it | |
| 5378 | // won't kill the whole process. | |
| 5379 | (void) signal(SIGPIPE, SIG_IGN); | |
| 5380 | // Also ignoring SIGCHLD to let the OS to reap zombies properly. | |
| 5381 | (void) signal(SIGCHLD, SIG_IGN); | |
| 5374 | // Ignore SIGPIPE signal, so if browser cancels the request, it | |
| 5375 | // won't kill the whole process. | |
| 5376 | (void) signal(SIGPIPE, SIG_IGN); | |
| 5377 | // Also ignoring SIGCHLD to let the OS to reap zombies properly. | |
| 5378 | (void) signal(SIGCHLD, SIG_IGN); | |
| 5382 | 5379 | #endif // !_WIN32 |
| 5383 | 5380 | |
| 5384 | (void) pthread_mutex_init(&ctx->mutex, NULL); | |
| 5385 | (void) pthread_cond_init(&ctx->cond, NULL); | |
| 5386 | (void) pthread_cond_init(&ctx->sq_empty, NULL); | |
| 5387 | (void) pthread_cond_init(&ctx->sq_full, NULL); | |
| 5381 | (void) pthread_mutex_init(&ctx->mutex, NULL); | |
| 5382 | (void) pthread_cond_init(&ctx->cond, NULL); | |
| 5383 | (void) pthread_cond_init(&ctx->sq_empty, NULL); | |
| 5384 | (void) pthread_cond_init(&ctx->sq_full, NULL); | |
| 5388 | 5385 | |
| 5389 | // Start master (listening) thread | |
| 5390 | mg_start_thread(master_thread, ctx); | |
| 5386 | // Start master (listening) thread | |
| 5387 | mg_start_thread(master_thread, ctx); | |
| 5391 | 5388 | |
| 5392 | // Start worker threads | |
| 5393 | for (i = 0; i < atoi(ctx->config[NUM_THREADS]); i++) { | |
| 5394 | if (mg_start_thread(worker_thread, ctx) != 0) { | |
| 5395 | cry(fc(ctx), "Cannot start worker thread: %ld", (long) ERRNO); | |
| 5396 | } else { | |
| 5397 | ctx->num_threads++; | |
| 5398 | } | |
| 5399 | } | |
| 5389 | // Start worker threads | |
| 5390 | for (i = 0; i < atoi(ctx->config[NUM_THREADS]); i++) { | |
| 5391 | if (mg_start_thread(worker_thread, ctx) != 0) { | |
| 5392 | cry(fc(ctx), "Cannot start worker thread: %ld", (long) ERRNO); | |
| 5393 | } else { | |
| 5394 | ctx->num_threads++; | |
| 5395 | } | |
| 5396 | } | |
| 5400 | 5397 | |
| 5401 | ||
| 5398 | return ctx; | |
| 5402 | 5399 | } |
| r25360 | r25361 | |
|---|---|---|
| 12 | 12 | # ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION |
| 13 | 13 | |
| 14 | 14 | namespace Json { |
| 15 | ||
| 16 | 15 | /* Fast memory allocator. |
| 17 | 16 | * |
| 18 | 17 | * This memory allocator allocates memory for a batch of object (specified by |
| r25360 | r25361 | |
| 21 | 20 | * It does not allow the destruction of a single object. All the allocated objects |
| 22 | 21 | * can be destroyed at once. The memory can be either released or reused for future |
| 23 | 22 | * allocation. |
| 24 | * | |
| 23 | * | |
| 25 | 24 | * The in-place new operator must be used to construct the object using the pointer |
| 26 | 25 | * returned by allocate. |
| 27 | 26 | */ |
| 28 | 27 | template<typename AllocatedType |
| 29 | ||
| 28 | ,const unsigned int objectPerAllocation> | |
| 30 | 29 | class BatchAllocator |
| 31 | 30 | { |
| 32 | 31 | public: |
| 33 | ||
| 32 | typedef AllocatedType Type; | |
| 34 | 33 | |
| 35 | BatchAllocator( unsigned int objectsPerPage = 255 ) | |
| 36 | : freeHead_( 0 ) | |
| 37 | , objectsPerPage_( objectsPerPage ) | |
| 38 | { | |
| 34 | BatchAllocator( unsigned int objectsPerPage = 255 ) | |
| 35 | : freeHead_( 0 ) | |
| 36 | , objectsPerPage_( objectsPerPage ) | |
| 37 | { | |
| 39 | 38 | // printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() ); |
| 40 | assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space. | |
| 41 | assert( objectsPerPage >= 16 ); | |
| 42 | batches_ = allocateBatch( 0 ); // allocated a dummy page | |
| 43 | currentBatch_ = batches_; | |
| 44 | } | |
| 39 | assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space. | |
| 40 | assert( objectsPerPage >= 16 ); | |
| 41 | batches_ = allocateBatch( 0 ); // allocated a dummy page | |
| 42 | currentBatch_ = batches_; | |
| 43 | } | |
| 45 | 44 | |
| 46 | ~BatchAllocator() | |
| 47 | { | |
| 48 | for ( BatchInfo *batch = batches_; batch; ) | |
| 49 | { | |
| 50 | BatchInfo *nextBatch = batch->next_; | |
| 51 | free( batch ); | |
| 52 | batch = nextBatch; | |
| 53 | } | |
| 54 | } | |
| 45 | ~BatchAllocator() | |
| 46 | { | |
| 47 | for ( BatchInfo *batch = batches_; batch; ) | |
| 48 | { | |
| 49 | BatchInfo *nextBatch = batch->next_; | |
| 50 | free( batch ); | |
| 51 | batch = nextBatch; | |
| 52 | } | |
| 53 | } | |
| 55 | 54 | |
| 56 | /// allocate space for an array of objectPerAllocation object. | |
| 57 | /// @warning it is the responsability of the caller to call objects constructors. | |
| 58 | AllocatedType *allocate() | |
| 59 | { | |
| 60 | if ( freeHead_ ) // returns node from free list. | |
| 61 | { | |
| 62 | AllocatedType *object = freeHead_; | |
| 63 | freeHead_ = *(AllocatedType **)object; | |
| 64 | return object; | |
| 65 | } | |
| 66 | if ( currentBatch_->used_ == currentBatch_->end_ ) | |
| 67 | { | |
| 68 | currentBatch_ = currentBatch_->next_; | |
| 69 | while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ ) | |
| 70 | currentBatch_ = currentBatch_->next_; | |
| 55 | /// allocate space for an array of objectPerAllocation object. | |
| 56 | /// @warning it is the responsability of the caller to call objects constructors. | |
| 57 | AllocatedType *allocate() | |
| 58 | { | |
| 59 | if ( freeHead_ ) // returns node from free list. | |
| 60 | { | |
| 61 | AllocatedType *object = freeHead_; | |
| 62 | freeHead_ = *(AllocatedType **)object; | |
| 63 | return object; | |
| 64 | } | |
| 65 | if ( currentBatch_->used_ == currentBatch_->end_ ) | |
| 66 | { | |
| 67 | currentBatch_ = currentBatch_->next_; | |
| 68 | while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ ) | |
| 69 | currentBatch_ = currentBatch_->next_; | |
| 71 | 70 | |
| 72 | if ( !currentBatch_ ) // no free batch found, allocate a new one | |
| 73 | { | |
| 74 | currentBatch_ = allocateBatch( objectsPerPage_ ); | |
| 75 | currentBatch_->next_ = batches_; // insert at the head of the list | |
| 76 | batches_ = currentBatch_; | |
| 77 | } | |
| 78 | } | |
| 79 | AllocatedType *allocated = currentBatch_->used_; | |
| 80 | currentBatch_->used_ += objectPerAllocation; | |
| 81 | return allocated; | |
| 82 | } | |
| 71 | if ( !currentBatch_ ) // no free batch found, allocate a new one | |
| 72 | { | |
| 73 | currentBatch_ = allocateBatch( objectsPerPage_ ); | |
| 74 | currentBatch_->next_ = batches_; // insert at the head of the list | |
| 75 | batches_ = currentBatch_; | |
| 76 | } | |
| 77 | } | |
| 78 | AllocatedType *allocated = currentBatch_->used_; | |
| 79 | currentBatch_->used_ += objectPerAllocation; | |
| 80 | return allocated; | |
| 81 | } | |
| 83 | 82 | |
| 84 | /// Release the object. | |
| 85 | /// @warning it is the responsability of the caller to actually destruct the object. | |
| 86 | void release( AllocatedType *object ) | |
| 87 | { | |
| 88 | assert( object != 0 ); | |
| 89 | *(AllocatedType **)object = freeHead_; | |
| 90 | freeHead_ = object; | |
| 91 | } | |
| 83 | /// Release the object. | |
| 84 | /// @warning it is the responsability of the caller to actually destruct the object. | |
| 85 | void release( AllocatedType *object ) | |
| 86 | { | |
| 87 | assert( object != 0 ); | |
| 88 | *(AllocatedType **)object = freeHead_; | |
| 89 | freeHead_ = object; | |
| 90 | } | |
| 92 | 91 | |
| 93 | 92 | private: |
| 94 | struct BatchInfo | |
| 95 | { | |
| 96 | BatchInfo *next_; | |
| 97 | AllocatedType *used_; | |
| 98 | AllocatedType *end_; | |
| 99 | AllocatedType buffer_[objectPerAllocation]; | |
| 100 | }; | |
| 93 | struct BatchInfo | |
| 94 | { | |
| 95 | BatchInfo *next_; | |
| 96 | AllocatedType *used_; | |
| 97 | AllocatedType *end_; | |
| 98 | AllocatedType buffer_[objectPerAllocation]; | |
| 99 | }; | |
| 101 | 100 | |
| 102 | // disabled copy constructor and assignement operator. | |
| 103 | BatchAllocator( const BatchAllocator & ); | |
| 104 | void operator =( const BatchAllocator &); | |
| 101 | // disabled copy constructor and assignement operator. | |
| 102 | BatchAllocator( const BatchAllocator & ); | |
| 103 | void operator =( const BatchAllocator &); | |
| 105 | 104 | |
| 106 | static BatchInfo *allocateBatch( unsigned int objectsPerPage ) | |
| 107 | { | |
| 108 | const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation | |
| 109 | + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage; | |
| 110 | BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) ); | |
| 111 | batch->next_ = 0; | |
| 112 | batch->used_ = batch->buffer_; | |
| 113 | batch->end_ = batch->buffer_ + objectsPerPage; | |
| 114 | return batch; | |
| 115 | } | |
| 105 | static BatchInfo *allocateBatch( unsigned int objectsPerPage ) | |
| 106 | { | |
| 107 | const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation | |
| 108 | + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage; | |
| 109 | BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) ); | |
| 110 | batch->next_ = 0; | |
| 111 | batch->used_ = batch->buffer_; | |
| 112 | batch->end_ = batch->buffer_ + objectsPerPage; | |
| 113 | return batch; | |
| 114 | } | |
| 116 | 115 | |
| 117 | BatchInfo *batches_; | |
| 118 | BatchInfo *currentBatch_; | |
| 119 | /// Head of a single linked list within the allocated space of freeed object | |
| 120 | AllocatedType *freeHead_; | |
| 121 | unsigned int objectsPerPage_; | |
| 116 | BatchInfo *batches_; | |
| 117 | BatchInfo *currentBatch_; | |
| 118 | /// Head of a single linked list within the allocated space of freeed object | |
| 119 | AllocatedType *freeHead_; | |
| 120 | unsigned int objectsPerPage_; | |
| 122 | 121 | }; |
| 123 | 122 | |
| 124 | 123 | |
| r25360 | r25361 | |
| 127 | 126 | # endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION |
| 128 | 127 | |
| 129 | 128 | #endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED |
| 130 |
| r25360 | r25361 | |
|---|---|---|
| 24 | 24 | /** \brief JSON (JavaScript Object Notation). |
| 25 | 25 | */ |
| 26 | 26 | namespace Json { |
| 27 | /** \brief Type of the value held by a Value object. | |
| 28 | */ | |
| 29 | enum ValueType | |
| 30 | { | |
| 31 | nullValue = 0, ///< 'null' value | |
| 32 | intValue, ///< signed integer value | |
| 33 | uintValue, ///< unsigned integer value | |
| 34 | realValue, ///< double value | |
| 35 | stringValue, ///< UTF-8 string value | |
| 36 | booleanValue, ///< bool value | |
| 37 | arrayValue, ///< array value (ordered list) | |
| 38 | objectValue ///< object value (collection of name/value pairs). | |
| 39 | }; | |
| 27 | 40 | |
| 28 | /** \brief Type of the value held by a Value object. | |
| 29 | */ | |
| 30 | enum ValueType | |
| 31 | { | |
| 32 | nullValue = 0, ///< 'null' value | |
| 33 | intValue, ///< signed integer value | |
| 34 | uintValue, ///< unsigned integer value | |
| 35 | realValue, ///< double value | |
| 36 | stringValue, ///< UTF-8 string value | |
| 37 | booleanValue, ///< bool value | |
| 38 | arrayValue, ///< array value (ordered list) | |
| 39 | objectValue ///< object value (collection of name/value pairs). | |
| 40 | }; | |
| 41 | enum CommentPlacement | |
| 42 | { | |
| 43 | commentBefore = 0, ///< a comment placed on the line before a value | |
| 44 | commentAfterOnSameLine, ///< a comment just after a value on the same line | |
| 45 | commentAfter, ///< a comment on the line after a value (only make sense for root value) | |
| 46 | numberOfCommentPlacement | |
| 47 | }; | |
| 41 | 48 | |
| 42 | enum CommentPlacement | |
| 43 | { | |
| 44 | commentBefore = 0, ///< a comment placed on the line before a value | |
| 45 | commentAfterOnSameLine, ///< a comment just after a value on the same line | |
| 46 | commentAfter, ///< a comment on the line after a value (only make sense for root value) | |
| 47 | numberOfCommentPlacement | |
| 48 | }; | |
| 49 | ||
| 50 | 49 | //# ifdef JSON_USE_CPPTL |
| 51 | 50 | // typedef CppTL::AnyEnumerator<const char *> EnumMemberNames; |
| 52 | 51 | // typedef CppTL::AnyEnumerator<const Value &> EnumValues; |
| 53 | 52 | //# endif |
| 54 | 53 | |
| 55 | /** \brief Lightweight wrapper to tag static string. | |
| 56 | * | |
| 57 | * Value constructor and objectValue member assignement takes advantage of the | |
| 58 | * StaticString and avoid the cost of string duplication when storing the | |
| 59 | * string or the member name. | |
| 60 | * | |
| 61 | * Example of usage: | |
| 62 | * \code | |
| 63 | * Json::Value aValue( StaticString("some text") ); | |
| 64 | * Json::Value object; | |
| 65 | * static const StaticString code("code"); | |
| 66 | * object[code] = 1234; | |
| 67 | * \endcode | |
| 68 | */ | |
| 69 | class JSON_API StaticString | |
| 70 | { | |
| 71 | public: | |
| 72 | explicit StaticString( const char *czstring ) | |
| 73 | : str_( czstring ) | |
| 74 | { | |
| 75 | } | |
| 54 | /** \brief Lightweight wrapper to tag static string. | |
| 55 | * | |
| 56 | * Value constructor and objectValue member assignement takes advantage of the | |
| 57 | * StaticString and avoid the cost of string duplication when storing the | |
| 58 | * string or the member name. | |
| 59 | * | |
| 60 | * Example of usage: | |
| 61 | * \code | |
| 62 | * Json::Value aValue( StaticString("some text") ); | |
| 63 | * Json::Value object; | |
| 64 | * static const StaticString code("code"); | |
| 65 | * object[code] = 1234; | |
| 66 | * \endcode | |
| 67 | */ | |
| 68 | class JSON_API StaticString | |
| 69 | { | |
| 70 | public: | |
| 71 | explicit StaticString( const char *czstring ) | |
| 72 | : str_( czstring ) | |
| 73 | { | |
| 74 | } | |
| 76 | 75 | |
| 77 | operator const char *() const | |
| 78 | { | |
| 79 | return str_; | |
| 80 | } | |
| 76 | operator const char *() const | |
| 77 | { | |
| 78 | return str_; | |
| 79 | } | |
| 81 | 80 | |
| 82 | const char *c_str() const | |
| 83 | { | |
| 84 | return str_; | |
| 85 | } | |
| 81 | const char *c_str() const | |
| 82 | { | |
| 83 | return str_; | |
| 84 | } | |
| 86 | 85 | |
| 87 | private: | |
| 88 | const char *str_; | |
| 89 | }; | |
| 86 | private: | |
| 87 | const char *str_; | |
| 88 | }; | |
| 90 | 89 | |
| 91 | /** \brief Represents a <a HREF="http://www.json.org">JSON</a> value. | |
| 92 | * | |
| 93 | * This class is a discriminated union wrapper that can represents a: | |
| 94 | * - signed integer [range: Value::minInt - Value::maxInt] | |
| 95 | * - unsigned integer (range: 0 - Value::maxUInt) | |
| 96 | * - double | |
| 97 | * - UTF-8 string | |
| 98 | * - boolean | |
| 99 | * - 'null' | |
| 100 | * - an ordered list of Value | |
| 101 | * - collection of name/value pairs (javascript object) | |
| 102 | * | |
| 103 | * The type of the held value is represented by a #ValueType and | |
| 104 | * can be obtained using type(). | |
| 105 | * | |
| 106 | * values of an #objectValue or #arrayValue can be accessed using operator[]() methods. | |
| 107 | * Non const methods will automatically create the a #nullValue element | |
| 108 | * if it does not exist. | |
| 109 | * The sequence of an #arrayValue will be automatically resize and initialized | |
| 110 | * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. | |
| 111 | * | |
| 112 | * The get() methods can be used to obtanis default value in the case the required element | |
| 113 | * does not exist. | |
| 114 | * | |
| 115 | * It is possible to iterate over the list of a #objectValue values using | |
| 116 | * the getMemberNames() method. | |
| 117 | */ | |
| 118 | class JSON_API Value | |
| 119 | { | |
| 120 | friend class ValueIteratorBase; | |
| 90 | /** \brief Represents a <a HREF="http://www.json.org">JSON</a> value. | |
| 91 | * | |
| 92 | * This class is a discriminated union wrapper that can represents a: | |
| 93 | * - signed integer [range: Value::minInt - Value::maxInt] | |
| 94 | * - unsigned integer (range: 0 - Value::maxUInt) | |
| 95 | * - double | |
| 96 | * - UTF-8 string | |
| 97 | * - boolean | |
| 98 | * - 'null' | |
| 99 | * - an ordered list of Value | |
| 100 | * - collection of name/value pairs (javascript object) | |
| 101 | * | |
| 102 | * The type of the held value is represented by a #ValueType and | |
| 103 | * can be obtained using type(). | |
| 104 | * | |
| 105 | * values of an #objectValue or #arrayValue can be accessed using operator[]() methods. | |
| 106 | * Non const methods will automatically create the a #nullValue element | |
| 107 | * if it does not exist. | |
| 108 | * The sequence of an #arrayValue will be automatically resize and initialized | |
| 109 | * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. | |
| 110 | * | |
| 111 | * The get() methods can be used to obtanis default value in the case the required element | |
| 112 | * does not exist. | |
| 113 | * | |
| 114 | * It is possible to iterate over the list of a #objectValue values using | |
| 115 | * the getMemberNames() method. | |
| 116 | */ | |
| 117 | class JSON_API Value | |
| 118 | { | |
| 119 | friend class ValueIteratorBase; | |
| 121 | 120 | # ifdef JSON_VALUE_USE_INTERNAL_MAP |
| 122 | friend class ValueInternalLink; | |
| 123 | friend class ValueInternalMap; | |
| 121 | friend class ValueInternalLink; | |
| 122 | friend class ValueInternalMap; | |
| 124 | 123 | # endif |
| 125 | public: | |
| 126 | typedef std::vector<std::string> Members; | |
| 127 | typedef ValueIterator iterator; | |
| 128 | typedef ValueConstIterator const_iterator; | |
| 129 | typedef Json::UInt UInt; | |
| 130 | typedef Json::Int Int; | |
| 124 | public: | |
| 125 | typedef std::vector<std::string> Members; | |
| 126 | typedef ValueIterator iterator; | |
| 127 | typedef ValueConstIterator const_iterator; | |
| 128 | typedef Json::UInt UInt; | |
| 129 | typedef Json::Int Int; | |
| 131 | 130 | # if defined(JSON_HAS_INT64) |
| 132 | typedef Json::UInt64 UInt64; | |
| 133 | typedef Json::Int64 Int64; | |
| 131 | typedef Json::UInt64 UInt64; | |
| 132 | typedef Json::Int64 Int64; | |
| 134 | 133 | #endif // defined(JSON_HAS_INT64) |
| 135 | typedef Json::LargestInt LargestInt; | |
| 136 | typedef Json::LargestUInt LargestUInt; | |
| 137 | typedef Json::ArrayIndex ArrayIndex; | |
| 134 | typedef Json::LargestInt LargestInt; | |
| 135 | typedef Json::LargestUInt LargestUInt; | |
| 136 | typedef Json::ArrayIndex ArrayIndex; | |
| 138 | 137 | |
| 139 | static const Value null; | |
| 140 | /// Minimum signed integer value that can be stored in a Json::Value. | |
| 141 | static const LargestInt minLargestInt; | |
| 142 | /// Maximum signed integer value that can be stored in a Json::Value. | |
| 143 | static const LargestInt maxLargestInt; | |
| 144 | /// Maximum unsigned integer value that can be stored in a Json::Value. | |
| 145 | static const LargestUInt maxLargestUInt; | |
| 138 | static const Value null; | |
| 139 | /// Minimum signed integer value that can be stored in a Json::Value. | |
| 140 | static const LargestInt minLargestInt; | |
| 141 | /// Maximum signed integer value that can be stored in a Json::Value. | |
| 142 | static const LargestInt maxLargestInt; | |
| 143 | /// Maximum unsigned integer value that can be stored in a Json::Value. | |
| 144 | static const LargestUInt maxLargestUInt; | |
| 146 | 145 | |
| 147 | /// Minimum signed int value that can be stored in a Json::Value. | |
| 148 | static const Int minInt; | |
| 149 | /// Maximum signed int value that can be stored in a Json::Value. | |
| 150 | static const Int maxInt; | |
| 151 | /// Maximum unsigned int value that can be stored in a Json::Value. | |
| 152 | static const UInt maxUInt; | |
| 146 | /// Minimum signed int value that can be stored in a Json::Value. | |
| 147 | static const Int minInt; | |
| 148 | /// Maximum signed int value that can be stored in a Json::Value. | |
| 149 | static const Int maxInt; | |
| 150 | /// Maximum unsigned int value that can be stored in a Json::Value. | |
| 151 | static const UInt maxUInt; | |
| 153 | 152 | |
| 154 | /// Minimum signed 64 bits int value that can be stored in a Json::Value. | |
| 155 | static const Int64 minInt64; | |
| 156 | /// Maximum signed 64 bits int value that can be stored in a Json::Value. | |
| 157 | static const Int64 maxInt64; | |
| 158 | /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. | |
| 159 | static const UInt64 maxUInt64; | |
| 153 | /// Minimum signed 64 bits int value that can be stored in a Json::Value. | |
| 154 | static const Int64 minInt64; | |
| 155 | /// Maximum signed 64 bits int value that can be stored in a Json::Value. | |
| 156 | static const Int64 maxInt64; | |
| 157 | /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. | |
| 158 | static const UInt64 maxUInt64; | |
| 160 | 159 | |
| 161 | ||
| 160 | private: | |
| 162 | 161 | #ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION |
| 163 | 162 | # ifndef JSON_VALUE_USE_INTERNAL_MAP |
| 164 | class CZString | |
| 165 | { | |
| 166 | public: | |
| 167 | enum DuplicationPolicy | |
| 168 | { | |
| 169 | noDuplication = 0, | |
| 170 | duplicate, | |
| 171 | duplicateOnCopy | |
| 172 | }; | |
| 173 | CZString( ArrayIndex index ); | |
| 174 | CZString( const char *cstr, DuplicationPolicy allocate ); | |
| 175 | CZString( const CZString &other ); | |
| 176 | ~CZString(); | |
| 177 | CZString &operator =( const CZString &other ); | |
| 178 | bool operator<( const CZString &other ) const; | |
| 179 | bool operator==( const CZString &other ) const; | |
| 180 | ArrayIndex index() const; | |
| 181 | const char *c_str() const; | |
| 182 | bool isStaticString() const; | |
| 183 | private: | |
| 184 | void swap( CZString &other ); | |
| 185 | const char *cstr_; | |
| 186 | ArrayIndex index_; | |
| 187 | }; | |
| 163 | class CZString | |
| 164 | { | |
| 165 | public: | |
| 166 | enum DuplicationPolicy | |
| 167 | { | |
| 168 | noDuplication = 0, | |
| 169 | duplicate, | |
| 170 | duplicateOnCopy | |
| 171 | }; | |
| 172 | CZString( ArrayIndex index ); | |
| 173 | CZString( const char *cstr, DuplicationPolicy allocate ); | |
| 174 | CZString( const CZString &other ); | |
| 175 | ~CZString(); | |
| 176 | CZString &operator =( const CZString &other ); | |
| 177 | bool operator<( const CZString &other ) const; | |
| 178 | bool operator==( const CZString &other ) const; | |
| 179 | ArrayIndex index() const; | |
| 180 | const char *c_str() const; | |
| 181 | bool isStaticString() const; | |
| 182 | private: | |
| 183 | void swap( CZString &other ); | |
| 184 | const char *cstr_; | |
| 185 | ArrayIndex index_; | |
| 186 | }; | |
| 188 | 187 | |
| 189 | ||
| 188 | public: | |
| 190 | 189 | # ifndef JSON_USE_CPPTL_SMALLMAP |
| 191 | ||
| 190 | typedef std::map<CZString, Value> ObjectValues; | |
| 192 | 191 | # else |
| 193 | ||
| 192 | typedef CppTL::SmallMap<CZString, Value> ObjectValues; | |
| 194 | 193 | # endif // ifndef JSON_USE_CPPTL_SMALLMAP |
| 195 | 194 | # endif // ifndef JSON_VALUE_USE_INTERNAL_MAP |
| 196 | 195 | #endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION |
| 197 | 196 | |
| 198 | public: | |
| 199 | /** \brief Create a default Value of the given type. | |
| 197 | public: | |
| 198 | /** \brief Create a default Value of the given type. | |
| 200 | 199 | |
| 201 | This is a very useful constructor. | |
| 202 | To create an empty array, pass arrayValue. | |
| 203 | To create an empty object, pass objectValue. | |
| 204 | Another Value can then be set to this one by assignment. | |
| 205 | This is useful since clear() and resize() will not alter types. | |
| 200 | This is a very useful constructor. | |
| 201 | To create an empty array, pass arrayValue. | |
| 202 | To create an empty object, pass objectValue. | |
| 203 | Another Value can then be set to this one by assignment. | |
| 204 | This is useful since clear() and resize() will not alter types. | |
| 206 | 205 | |
| 207 | Examples: | |
| 208 | \code | |
| 209 | Json::Value null_value; // null | |
| 210 | Json::Value arr_value(Json::arrayValue); // [] | |
| 211 | Json::Value obj_value(Json::objectValue); // {} | |
| 212 | \endcode | |
| 213 | */ | |
| 214 | Value( ValueType type = nullValue ); | |
| 215 | Value( Int value ); | |
| 216 | Value( UInt value ); | |
| 206 | Examples: | |
| 207 | \code | |
| 208 | Json::Value null_value; // null | |
| 209 | Json::Value arr_value(Json::arrayValue); // [] | |
| 210 | Json::Value obj_value(Json::objectValue); // {} | |
| 211 | \endcode | |
| 212 | */ | |
| 213 | Value( ValueType type = nullValue ); | |
| 214 | Value( Int value ); | |
| 215 | Value( UInt value ); | |
| 217 | 216 | #if defined(JSON_HAS_INT64) |
| 218 | Value( Int64 value ); | |
| 219 | Value( UInt64 value ); | |
| 217 | Value( Int64 value ); | |
| 218 | Value( UInt64 value ); | |
| 220 | 219 | #endif // if defined(JSON_HAS_INT64) |
| 221 | Value( double value ); | |
| 222 | Value( const char *value ); | |
| 223 | Value( const char *beginValue, const char *endValue ); | |
| 224 | /** \brief Constructs a value from a static string. | |
| 220 | Value( double value ); | |
| 221 | Value( const char *value ); | |
| 222 | Value( const char *beginValue, const char *endValue ); | |
| 223 | /** \brief Constructs a value from a static string. | |
| 225 | 224 | |
| 226 | * Like other value string constructor but do not duplicate the string for | |
| 227 | * internal storage. The given string must remain alive after the call to this | |
| 228 | * constructor. | |
| 229 | * Example of usage: | |
| 230 | * \code | |
| 231 | * Json::Value aValue( StaticString("some text") ); | |
| 232 | * \endcode | |
| 233 | */ | |
| 234 | Value( const StaticString &value ); | |
| 235 | Value( const std::string &value ); | |
| 225 | * Like other value string constructor but do not duplicate the string for | |
| 226 | * internal storage. The given string must remain alive after the call to this | |
| 227 | * constructor. | |
| 228 | * Example of usage: | |
| 229 | * \code | |
| 230 | * Json::Value aValue( StaticString("some text") ); | |
| 231 | * \endcode | |
| 232 | */ | |
| 233 | Value( const StaticString &value ); | |
| 234 | Value( const std::string &value ); | |
| 236 | 235 | # ifdef JSON_USE_CPPTL |
| 237 | ||
| 236 | Value( const CppTL::ConstString &value ); | |
| 238 | 237 | # endif |
| 239 | Value( bool value ); | |
| 240 | Value( const Value &other ); | |
| 241 | ~Value(); | |
| 238 | Value( bool value ); | |
| 239 | Value( const Value &other ); | |
| 240 | ~Value(); | |
| 242 | 241 | |
| 243 | Value &operator=( const Value &other ); | |
| 244 | /// Swap values. | |
| 245 | /// \note Currently, comments are intentionally not swapped, for | |
| 246 | /// both logic and efficiency. | |
| 247 | void swap( Value &other ); | |
| 242 | Value &operator=( const Value &other ); | |
| 243 | /// Swap values. | |
| 244 | /// \note Currently, comments are intentionally not swapped, for | |
| 245 | /// both logic and efficiency. | |
| 246 | void swap( Value &other ); | |
| 248 | 247 | |
| 249 | ||
| 248 | ValueType type() const; | |
| 250 | 249 | |
| 251 | bool operator <( const Value &other ) const; | |
| 252 | bool operator <=( const Value &other ) const; | |
| 253 | bool operator >=( const Value &other ) const; | |
| 254 | bool operator >( const Value &other ) const; | |
| 250 | bool operator <( const Value &other ) const; | |
| 251 | bool operator <=( const Value &other ) const; | |
| 252 | bool operator >=( const Value &other ) const; | |
| 253 | bool operator >( const Value &other ) const; | |
| 255 | 254 | |
| 256 | bool operator ==( const Value &other ) const; | |
| 257 | bool operator !=( const Value &other ) const; | |
| 255 | bool operator ==( const Value &other ) const; | |
| 256 | bool operator !=( const Value &other ) const; | |
| 258 | 257 | |
| 259 | ||
| 258 | int compare( const Value &other ) const; | |
| 260 | 259 | |
| 261 | const char *asCString() const; | |
| 262 | std::string asString() const; | |
| 260 | const char *asCString() const; | |
| 261 | std::string asString() const; | |
| 263 | 262 | # ifdef JSON_USE_CPPTL |
| 264 | ||
| 263 | CppTL::ConstString asConstString() const; | |
| 265 | 264 | # endif |
| 266 | Int asInt() const; | |
| 267 | UInt asUInt() const; | |
| 268 | Int64 asInt64() const; | |
| 269 | UInt64 asUInt64() const; | |
| 270 | LargestInt asLargestInt() const; | |
| 271 | LargestUInt asLargestUInt() const; | |
| 272 | float asFloat() const; | |
| 273 | double asDouble() const; | |
| 274 | bool asBool() const; | |
| 265 | Int asInt() const; | |
| 266 | UInt asUInt() const; | |
| 267 | Int64 asInt64() const; | |
| 268 | UInt64 asUInt64() const; | |
| 269 | LargestInt asLargestInt() const; | |
| 270 | LargestUInt asLargestUInt() const; | |
| 271 | float asFloat() const; | |
| 272 | double asDouble() const; | |
| 273 | bool asBool() const; | |
| 275 | 274 | |
| 276 | bool isNull() const; | |
| 277 | bool isBool() const; | |
| 278 | bool isInt() const; | |
| 279 | bool isUInt() const; | |
| 280 | bool isIntegral() const; | |
| 281 | bool isDouble() const; | |
| 282 | bool isNumeric() const; | |
| 283 | bool isString() const; | |
| 284 | bool isArray() const; | |
| 285 | bool isObject() const; | |
| 275 | bool isNull() const; | |
| 276 | bool isBool() const; | |
| 277 | bool isInt() const; | |
| 278 | bool isUInt() const; | |
| 279 | bool isIntegral() const; | |
| 280 | bool isDouble() const; | |
| 281 | bool isNumeric() const; | |
| 282 | bool isString() const; | |
| 283 | bool isArray() const; | |
| 284 | bool isObject() const; | |
| 286 | 285 | |
| 287 | ||
| 286 | bool isConvertibleTo( ValueType other ) const; | |
| 288 | 287 | |
| 289 | /// Number of values in array or object | |
| 290 | ArrayIndex size() const; | |
| 288 | /// Number of values in array or object | |
| 289 | ArrayIndex size() const; | |
| 291 | 290 | |
| 292 | /// \brief Return true if empty array, empty object, or null; | |
| 293 | /// otherwise, false. | |
| 294 | bool empty() const; | |
| 291 | /// \brief Return true if empty array, empty object, or null; | |
| 292 | /// otherwise, false. | |
| 293 | bool empty() const; | |
| 295 | 294 | |
| 296 | /// Return isNull() | |
| 297 | bool operator!() const; | |
| 295 | /// Return isNull() | |
| 296 | bool operator!() const; | |
| 298 | 297 | |
| 299 | /// Remove all object members and array elements. | |
| 300 | /// \pre type() is arrayValue, objectValue, or nullValue | |
| 301 | /// \post type() is unchanged | |
| 302 | void clear(); | |
| 298 | /// Remove all object members and array elements. | |
| 299 | /// \pre type() is arrayValue, objectValue, or nullValue | |
| 300 | /// \post type() is unchanged | |
| 301 | void clear(); | |
| 303 | 302 | |
| 304 | /// Resize the array to size elements. | |
| 305 | /// New elements are initialized to null. | |
| 306 | /// May only be called on nullValue or arrayValue. | |
| 307 | /// \pre type() is arrayValue or nullValue | |
| 308 | /// \post type() is arrayValue | |
| 309 | void resize( ArrayIndex size ); | |
| 303 | /// Resize the array to size elements. | |
| 304 | /// New elements are initialized to null. | |
| 305 | /// May only be called on nullValue or arrayValue. | |
| 306 | /// \pre type() is arrayValue or nullValue | |
| 307 | /// \post type() is arrayValue | |
| 308 | void resize( ArrayIndex size ); | |
| 310 | 309 | |
| 311 | /// Access an array element (zero based index ). | |
| 312 | /// If the array contains less than index element, then null value are inserted | |
| 313 | /// in the array so that its size is index+1. | |
| 314 | /// (You may need to say 'value[0u]' to get your compiler to distinguish | |
| 315 | /// this from the operator[] which takes a string.) | |
| 316 | Value &operator[]( ArrayIndex index ); | |
| 310 | /// Access an array element (zero based index ). | |
| 311 | /// If the array contains less than index element, then null value are inserted | |
| 312 | /// in the array so that its size is index+1. | |
| 313 | /// (You may need to say 'value[0u]' to get your compiler to distinguish | |
| 314 | /// this from the operator[] which takes a string.) | |
| 315 | Value &operator[]( ArrayIndex index ); | |
| 317 | 316 | |
| 318 | /// Access an array element (zero based index ). | |
| 319 | /// If the array contains less than index element, then null value are inserted | |
| 320 | /// in the array so that its size is index+1. | |
| 321 | /// (You may need to say 'value[0u]' to get your compiler to distinguish | |
| 322 | /// this from the operator[] which takes a string.) | |
| 323 | Value &operator[]( int index ); | |
| 317 | /// Access an array element (zero based index ). | |
| 318 | /// If the array contains less than index element, then null value are inserted | |
| 319 | /// in the array so that its size is index+1. | |
| 320 | /// (You may need to say 'value[0u]' to get your compiler to distinguish | |
| 321 | /// this from the operator[] which takes a string.) | |
| 322 | Value &operator[]( int index ); | |
| 324 | 323 | |
| 325 | /// Access an array element (zero based index ) | |
| 326 | /// (You may need to say 'value[0u]' to get your compiler to distinguish | |
| 327 | /// this from the operator[] which takes a string.) | |
| 328 | const Value &operator[]( ArrayIndex index ) const; | |
| 324 | /// Access an array element (zero based index ) | |
| 325 | /// (You may need to say 'value[0u]' to get your compiler to distinguish | |
| 326 | /// this from the operator[] which takes a string.) | |
| 327 | const Value &operator[]( ArrayIndex index ) const; | |
| 329 | 328 | |
| 330 | /// Access an array element (zero based index ) | |
| 331 | /// (You may need to say 'value[0u]' to get your compiler to distinguish | |
| 332 | /// this from the operator[] which takes a string.) | |
| 333 | const Value &operator[]( int index ) const; | |
| 329 | /// Access an array element (zero based index ) | |
| 330 | /// (You may need to say 'value[0u]' to get your compiler to distinguish | |
| 331 | /// this from the operator[] which takes a string.) | |
| 332 | const Value &operator[]( int index ) const; | |
| 334 | 333 | |
| 335 | /// If the array contains at least index+1 elements, returns the element value, | |
| 336 | /// otherwise returns defaultValue. | |
| 337 | Value get( ArrayIndex index, | |
| 338 | const Value &defaultValue ) const; | |
| 339 | /// Return true if index < size(). | |
| 340 | bool isValidIndex( ArrayIndex index ) const; | |
| 341 | /// \brief Append value to array at the end. | |
| 342 | /// | |
| 343 | /// Equivalent to jsonvalue[jsonvalue.size()] = value; | |
| 344 | Value &append( const Value &value ); | |
| 334 | /// If the array contains at least index+1 elements, returns the element value, | |
| 335 | /// otherwise returns defaultValue. | |
| 336 | Value get( ArrayIndex index, | |
| 337 | const Value &defaultValue ) const; | |
| 338 | /// Return true if index < size(). | |
| 339 | bool isValidIndex( ArrayIndex index ) const; | |
| 340 | /// \brief Append value to array at the end. | |
| 341 | /// | |
| 342 | /// Equivalent to jsonvalue[jsonvalue.size()] = value; | |
| 343 | Value &append( const Value &value ); | |
| 345 | 344 | |
| 346 | /// Access an object value by name, create a null member if it does not exist. | |
| 347 | Value &operator[]( const char *key ); | |
| 348 | /// Access an object value by name, returns null if there is no member with that name. | |
| 349 | const Value &operator[]( const char *key ) const; | |
| 350 | /// Access an object value by name, create a null member if it does not exist. | |
| 351 | Value &operator[]( const std::string &key ); | |
| 352 | /// Access an object value by name, returns null if there is no member with that name. | |
| 353 | const Value &operator[]( const std::string &key ) const; | |
| 354 | /** \brief Access an object value by name, create a null member if it does not exist. | |
| 345 | /// Access an object value by name, create a null member if it does not exist. | |
| 346 | Value &operator[]( const char *key ); | |
| 347 | /// Access an object value by name, returns null if there is no member with that name. | |
| 348 | const Value &operator[]( const char *key ) const; | |
| 349 | /// Access an object value by name, create a null member if it does not exist. | |
| 350 | Value &operator[]( const std::string &key ); | |
| 351 | /// Access an object value by name, returns null if there is no member with that name. | |
| 352 | const Value &operator[]( const std::string &key ) const; | |
| 353 | /** \brief Access an object value by name, create a null member if it does not exist. | |
| 355 | 354 | |
| 356 | * If the object as no entry for that name, then the member name used to store | |
| 357 | * the new entry is not duplicated. | |
| 358 | * Example of use: | |
| 359 | * \code | |
| 360 | * Json::Value object; | |
| 361 | * static const StaticString code("code"); | |
| 362 | * object[code] = 1234; | |
| 363 | * \endcode | |
| 364 | */ | |
| 365 | Value &operator[]( const StaticString &key ); | |
| 355 | * If the object as no entry for that name, then the member name used to store | |
| 356 | * the new entry is not duplicated. | |
| 357 | * Example of use: | |
| 358 | * \code | |
| 359 | * Json::Value object; | |
| 360 | * static const StaticString code("code"); | |
| 361 | * object[code] = 1234; | |
| 362 | * \endcode | |
| 363 | */ | |
| 364 | Value &operator[]( const StaticString &key ); | |
| 366 | 365 | # ifdef JSON_USE_CPPTL |
| 367 | /// Access an object value by name, create a null member if it does not exist. | |
| 368 | Value &operator[]( const CppTL::ConstString &key ); | |
| 369 | /// Access an object value by name, returns null if there is no member with that name. | |
| 370 | const Value &operator[]( const CppTL::ConstString &key ) const; | |
| 366 | /// Access an object value by name, create a null member if it does not exist. | |
| 367 | Value &operator[]( const CppTL::ConstString &key ); | |
| 368 | /// Access an object value by name, returns null if there is no member with that name. | |
| 369 | const Value &operator[]( const CppTL::ConstString &key ) const; | |
| 371 | 370 | # endif |
| 372 | /// Return the member named key if it exist, defaultValue otherwise. | |
| 373 | Value get( const char *key, | |
| 374 | const Value &defaultValue ) const; | |
| 375 | /// Return the member named key if it exist, defaultValue otherwise. | |
| 376 | Value get( const std::string &key, | |
| 377 | const Value &defaultValue ) const; | |
| 371 | /// Return the member named key if it exist, defaultValue otherwise. | |
| 372 | Value get( const char *key, | |
| 373 | const Value &defaultValue ) const; | |
| 374 | /// Return the member named key if it exist, defaultValue otherwise. | |
| 375 | Value get( const std::string &key, | |
| 376 | const Value &defaultValue ) const; | |
| 378 | 377 | # ifdef JSON_USE_CPPTL |
| 379 | /// Return the member named key if it exist, defaultValue otherwise. | |
| 380 | Value get( const CppTL::ConstString &key, | |
| 381 | const Value &defaultValue ) const; | |
| 378 | /// Return the member named key if it exist, defaultValue otherwise. | |
| 379 | Value get( const CppTL::ConstString &key, | |
| 380 | const Value &defaultValue ) const; | |
| 382 | 381 | # endif |
| 383 | /// \brief Remove and return the named member. | |
| 384 | /// | |
| 385 | /// Do nothing if it did not exist. | |
| 386 | /// \return the removed Value, or null. | |
| 387 | /// \pre type() is objectValue or nullValue | |
| 388 | /// \post type() is unchanged | |
| 389 | Value removeMember( const char* key ); | |
| 390 | /// Same as removeMember(const char*) | |
| 391 | Value removeMember( const std::string &key ); | |
| 382 | /// \brief Remove and return the named member. | |
| 383 | /// | |
| 384 | /// Do nothing if it did not exist. | |
| 385 | /// \return the removed Value, or null. | |
| 386 | /// \pre type() is objectValue or nullValue | |
| 387 | /// \post type() is unchanged | |
| 388 | Value removeMember( const char* key ); | |
| 389 | /// Same as removeMember(const char*) | |
| 390 | Value removeMember( const std::string &key ); | |
| 392 | 391 | |
| 393 | /// Return true if the object has a member named key. | |
| 394 | bool isMember( const char *key ) const; | |
| 395 | /// Return true if the object has a member named key. | |
| 396 | bool isMember( const std::string &key ) const; | |
| 392 | /// Return true if the object has a member named key. | |
| 393 | bool isMember( const char *key ) const; | |
| 394 | /// Return true if the object has a member named key. | |
| 395 | bool isMember( const std::string &key ) const; | |
| 397 | 396 | # ifdef JSON_USE_CPPTL |
| 398 | /// Return true if the object has a member named key. | |
| 399 | bool isMember( const CppTL::ConstString &key ) const; | |
| 397 | /// Return true if the object has a member named key. | |
| 398 | bool isMember( const CppTL::ConstString &key ) const; | |
| 400 | 399 | # endif |
| 401 | 400 | |
| 402 | /// \brief Return a list of the member names. | |
| 403 | /// | |
| 404 | /// If null, return an empty list. | |
| 405 | /// \pre type() is objectValue or nullValue | |
| 406 | /// \post if type() was nullValue, it remains nullValue | |
| 407 | Members getMemberNames() const; | |
| 401 | /// \brief Return a list of the member names. | |
| 402 | /// | |
| 403 | /// If null, return an empty list. | |
| 404 | /// \pre type() is objectValue or nullValue | |
| 405 | /// \post if type() was nullValue, it remains nullValue | |
| 406 | Members getMemberNames() const; | |
| 408 | 407 | |
| 409 | 408 | //# ifdef JSON_USE_CPPTL |
| 410 | 409 | // EnumMemberNames enumMemberNames() const; |
| 411 | 410 | // EnumValues enumValues() const; |
| 412 | 411 | //# endif |
| 413 | 412 | |
| 414 | /// Comments must be //... or /* ... */ | |
| 415 | void setComment( const char *comment, | |
| 416 | CommentPlacement placement ); | |
| 417 | /// Comments must be //... or /* ... */ | |
| 418 | void setComment( const std::string &comment, | |
| 419 | CommentPlacement placement ); | |
| 420 | bool hasComment( CommentPlacement placement ) const; | |
| 421 | /// Include delimiters and embedded newlines. | |
| 422 | std::string getComment( CommentPlacement placement ) const; | |
| 413 | /// Comments must be //... or /* ... */ | |
| 414 | void setComment( const char *comment, | |
| 415 | CommentPlacement placement ); | |
| 416 | /// Comments must be //... or /* ... */ | |
| 417 | void setComment( const std::string &comment, | |
| 418 | CommentPlacement placement ); | |
| 419 | bool hasComment( CommentPlacement placement ) const; | |
| 420 | /// Include delimiters and embedded newlines. | |
| 421 | std::string getComment( CommentPlacement placement ) const; | |
| 423 | 422 | |
| 424 | ||
| 423 | std::string toStyledString() const; | |
| 425 | 424 | |
| 426 | const_iterator begin() const; | |
| 427 | const_iterator end() const; | |
| 425 | const_iterator begin() const; | |
| 426 | const_iterator end() const; | |
| 428 | 427 | |
| 429 | iterator begin(); | |
| 430 | iterator end(); | |
| 428 | iterator begin(); | |
| 429 | iterator end(); | |
| 431 | 430 | |
| 432 | private: | |
| 433 | Value &resolveReference( const char *key, | |
| 434 | bool isStatic ); | |
| 431 | private: | |
| 432 | Value &resolveReference( const char *key, | |
| 433 | bool isStatic ); | |
| 435 | 434 | |
| 436 | 435 | # ifdef JSON_VALUE_USE_INTERNAL_MAP |
| 437 | inline bool isItemAvailable() const | |
| 438 | { | |
| 439 | return itemIsUsed_ == 0; | |
| 440 | } | |
| 436 | inline bool isItemAvailable() const | |
| 437 | { | |
| 438 | return itemIsUsed_ == 0; | |
| 439 | } | |
| 441 | 440 | |
| 442 | inline void setItemUsed( bool isUsed = true ) | |
| 443 | { | |
| 444 | itemIsUsed_ = isUsed ? 1 : 0; | |
| 445 | } | |
| 441 | inline void setItemUsed( bool isUsed = true ) | |
| 442 | { | |
| 443 | itemIsUsed_ = isUsed ? 1 : 0; | |
| 444 | } | |
| 446 | 445 | |
| 447 | inline bool isMemberNameStatic() const | |
| 448 | { | |
| 449 | return memberNameIsStatic_ == 0; | |
| 450 | } | |
| 446 | inline bool isMemberNameStatic() const | |
| 447 | { | |
| 448 | return memberNameIsStatic_ == 0; | |
| 449 | } | |
| 451 | 450 | |
| 452 | inline void setMemberNameIsStatic( bool isStatic ) | |
| 453 | { | |
| 454 | memberNameIsStatic_ = isStatic ? 1 : 0; | |
| 455 | } | |
| 451 | inline void setMemberNameIsStatic( bool isStatic ) | |
| 452 | { | |
| 453 | memberNameIsStatic_ = isStatic ? 1 : 0; | |
| 454 | } | |
| 456 | 455 | # endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP |
| 457 | 456 | |
| 458 | private: | |
| 459 | struct CommentInfo | |
| 460 | { | |
| 461 | CommentInfo(); | |
| 462 | ~CommentInfo(); | |
| 457 | private: | |
| 458 | struct CommentInfo | |
| 459 | { | |
| 460 | CommentInfo(); | |
| 461 | ~CommentInfo(); | |
| 463 | 462 | |
| 464 | ||
| 463 | void setComment( const char *text ); | |
| 465 | 464 | |
| 466 | char *comment_; | |
| 467 | }; | |
| 465 | char *comment_; | |
| 466 | }; | |
| 468 | 467 | |
| 469 | //struct MemberNamesTransform | |
| 470 | //{ | |
| 471 | // typedef const char *result_type; | |
| 472 | // const char *operator()( const CZString &name ) const | |
| 473 | // { | |
| 474 | // return name.c_str(); | |
| 475 | // } | |
| 476 | //}; | |
| 468 | //struct MemberNamesTransform | |
| 469 | //{ | |
| 470 | // typedef const char *result_type; | |
| 471 | // const char *operator()( const CZString &name ) const | |
| 472 | // { | |
| 473 | // return name.c_str(); | |
| 474 | // } | |
| 475 | //}; | |
| 477 | 476 | |
| 478 | union ValueHolder | |
| 479 | { | |
| 480 | LargestInt int_; | |
| 481 | LargestUInt uint_; | |
| 482 | double real_; | |
| 483 | bool bool_; | |
| 484 | char *string_; | |
| 477 | union ValueHolder | |
| 478 | { | |
| 479 | LargestInt int_; | |
| 480 | LargestUInt uint_; | |
| 481 | double real_; | |
| 482 | bool bool_; | |
| 483 | char *string_; | |
| 485 | 484 | # ifdef JSON_VALUE_USE_INTERNAL_MAP |
| 486 | ValueInternalArray *array_; | |
| 487 | ValueInternalMap *map_; | |
| 485 | ValueInternalArray *array_; | |
| 486 | ValueInternalMap *map_; | |
| 488 | 487 | #else |
| 489 | ||
| 488 | ObjectValues *map_; | |
| 490 | 489 | # endif |
| 491 | } value_; | |
| 492 | ValueType type_ : 8; | |
| 493 | int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. | |
| 490 | } value_; | |
| 491 | ValueType type_ : 8; | |
| 492 | int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. | |
| 494 | 493 | # ifdef JSON_VALUE_USE_INTERNAL_MAP |
| 495 | unsigned int itemIsUsed_ : 1; // used by the ValueInternalMap container. | |
| 496 | int memberNameIsStatic_ : 1; // used by the ValueInternalMap container. | |
| 494 | unsigned int itemIsUsed_ : 1; // used by the ValueInternalMap container. | |
| 495 | int memberNameIsStatic_ : 1; // used by the ValueInternalMap container. | |
| 497 | 496 | # endif |
| 498 | CommentInfo *comments_; | |
| 499 | }; | |
| 497 | CommentInfo *comments_; | |
| 498 | }; | |
| 500 | 499 | |
| 501 | 500 | |
| 502 | /** \brief Experimental and untested: represents an element of the "path" to access a node. | |
| 503 | */ | |
| 504 | class PathArgument | |
| 505 | { | |
| 506 | public: | |
| 507 | friend class Path; | |
| 501 | /** \brief Experimental and untested: represents an element of the "path" to access a node. | |
| 502 | */ | |
| 503 | class PathArgument | |
| 504 | { | |
| 505 | public: | |
| 506 | friend class Path; | |
| 508 | 507 | |
| 509 | PathArgument(); | |
| 510 | PathArgument( ArrayIndex index ); | |
| 511 | PathArgument( const char *key ); | |
| 512 | PathArgument( const std::string &key ); | |
| 508 | PathArgument(); | |
| 509 | PathArgument( ArrayIndex index ); | |
| 510 | PathArgument( const char *key ); | |
| 511 | PathArgument( const std::string &key ); | |
| 513 | 512 | |
| 514 | private: | |
| 515 | enum Kind | |
| 516 | { | |
| 517 | kindNone = 0, | |
| 518 | kindIndex, | |
| 519 | kindKey | |
| 520 | }; | |
| 521 | std::string key_; | |
| 522 | ArrayIndex index_; | |
| 523 | Kind kind_; | |
| 524 | }; | |
| 513 | private: | |
| 514 | enum Kind | |
| 515 | { | |
| 516 | kindNone = 0, | |
| 517 | kindIndex, | |
| 518 | kindKey | |
| 519 | }; | |
| 520 | std::string key_; | |
| 521 | ArrayIndex index_; | |
| 522 | Kind kind_; | |
| 523 | }; | |
| 525 | 524 | |
| 526 | /** \brief Experimental and untested: represents a "path" to access a node. | |
| 527 | * | |
| 528 | * Syntax: | |
| 529 | * - "." => root node | |
| 530 | * - ".[n]" => elements at index 'n' of root node (an array value) | |
| 531 | * - ".name" => member named 'name' of root node (an object value) | |
| 532 | * - ".name1.name2.name3" | |
| 533 | * - ".[0][1][2].name1[3]" | |
| 534 | * - ".%" => member name is provided as parameter | |
| 535 | * - ".[%]" => index is provied as parameter | |
| 536 | */ | |
| 537 | class Path | |
| 538 | { | |
| 539 | public: | |
| 540 | Path( const std::string &path, | |
| 541 | const PathArgument &a1 = PathArgument(), | |
| 542 | const PathArgument &a2 = PathArgument(), | |
| 543 | const PathArgument &a3 = PathArgument(), | |
| 544 | const PathArgument &a4 = PathArgument(), | |
| 545 | const PathArgument &a5 = PathArgument() ); | |
| 525 | /** \brief Experimental and untested: represents a "path" to access a node. | |
| 526 | * | |
| 527 | * Syntax: | |
| 528 | * - "." => root node | |
| 529 | * - ".[n]" => elements at index 'n' of root node (an array value) | |
| 530 | * - ".name" => member named 'name' of root node (an object value) | |
| 531 | * - ".name1.name2.name3" | |
| 532 | * - ".[0][1][2].name1[3]" | |
| 533 | * - ".%" => member name is provided as parameter | |
| 534 | * - ".[%]" => index is provied as parameter | |
| 535 | */ | |
| 536 | class Path | |
| 537 | { | |
| 538 | public: | |
| 539 | Path( const std::string &path, | |
| 540 | const PathArgument &a1 = PathArgument(), | |
| 541 | const PathArgument &a2 = PathArgument(), | |
| 542 | const PathArgument &a3 = PathArgument(), | |
| 543 | const PathArgument &a4 = PathArgument(), | |
| 544 | const PathArgument &a5 = PathArgument() ); | |
| 546 | 545 | |
| 547 | const Value &resolve( const Value &root ) const; | |
| 548 | Value resolve( const Value &root, | |
| 549 | const Value &defaultValue ) const; | |
| 550 | /// Creates the "path" to access the specified node and returns a reference on the node. | |
| 551 | Value &make( Value &root ) const; | |
| 546 | const Value &resolve( const Value &root ) const; | |
| 547 | Value resolve( const Value &root, | |
| 548 | const Value &defaultValue ) const; | |
| 549 | /// Creates the "path" to access the specified node and returns a reference on the node. | |
| 550 | Value &make( Value &root ) const; | |
| 552 | 551 | |
| 553 | private: | |
| 554 | typedef std::vector<const PathArgument *> InArgs; | |
| 555 | typedef std::vector<PathArgument> Args; | |
| 552 | private: | |
| 553 | typedef std::vector<const PathArgument *> InArgs; | |
| 554 | typedef std::vector<PathArgument> Args; | |
| 556 | 555 | |
| 557 | void makePath( const std::string &path, | |
| 558 | const InArgs &in ); | |
| 559 | void addPathInArg( const std::string &path, | |
| 560 | const InArgs &in, | |
| 561 | InArgs::const_iterator &itInArg, | |
| 562 | PathArgument::Kind kind ); | |
| 563 | void invalidPath( const std::string &path, | |
| 564 | int location ); | |
| 556 | void makePath( const std::string &path, | |
| 557 | const InArgs &in ); | |
| 558 | void addPathInArg( const std::string &path, | |
| 559 | const InArgs &in, | |
| 560 | InArgs::const_iterator &itInArg, | |
| 561 | PathArgument::Kind kind ); | |
| 562 | void invalidPath( const std::string &path, | |
| 563 | int location ); | |
| 565 | 564 | |
| 566 | Args args_; | |
| 567 | }; | |
| 565 | Args args_; | |
| 566 | }; | |
| 568 | 567 | |
| 569 | 568 | |
| 570 | 569 | |
| 571 | 570 | #ifdef JSON_VALUE_USE_INTERNAL_MAP |
| 572 | /** \brief Allocator to customize Value internal map. | |
| 573 | * Below is an example of a simple implementation (default implementation actually | |
| 574 | * use memory pool for speed). | |
| 575 | * \code | |
| 576 | class DefaultValueMapAllocator : public ValueMapAllocator | |
| 577 | { | |
| 578 | public: // overridden from ValueMapAllocator | |
| 579 | virtual ValueInternalMap *newMap() | |
| 580 | { | |
| 581 | return new ValueInternalMap(); | |
| 582 | } | |
| 571 | /** \brief Allocator to customize Value internal map. | |
| 572 | * Below is an example of a simple implementation (default implementation actually | |
| 573 | * use memory pool for speed). | |
| 574 | * \code | |
| 575 | class DefaultValueMapAllocator : public ValueMapAllocator | |
| 576 | { | |
| 577 | public: // overridden from ValueMapAllocator | |
| 578 | virtual ValueInternalMap *newMap() | |
| 579 | { | |
| 580 | return new ValueInternalMap(); | |
| 581 | } | |
| 583 | 582 | |
| 584 | virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) | |
| 585 | { | |
| 586 | return new ValueInternalMap( other ); | |
| 587 | } | |
| 583 | virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) | |
| 584 | { | |
| 585 | return new ValueInternalMap( other ); | |
| 586 | } | |
| 588 | 587 | |
| 589 | virtual void destructMap( ValueInternalMap *map ) | |
| 590 | { | |
| 591 | delete map; | |
| 592 | } | |
| 588 | virtual void destructMap( ValueInternalMap *map ) | |
| 589 | { | |
| 590 | delete map; | |
| 591 | } | |
| 593 | 592 | |
| 594 | virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) | |
| 595 | { | |
| 596 | return new ValueInternalLink[size]; | |
| 597 | } | |
| 593 | virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) | |
| 594 | { | |
| 595 | return new ValueInternalLink[size]; | |
| 596 | } | |
| 598 | 597 | |
| 599 | virtual void releaseMapBuckets( ValueInternalLink *links ) | |
| 600 | { | |
| 601 | delete [] links; | |
| 602 | } | |
| 598 | virtual void releaseMapBuckets( ValueInternalLink *links ) | |
| 599 | { | |
| 600 | delete [] links; | |
| 601 | } | |
| 603 | 602 | |
| 604 | virtual ValueInternalLink *allocateMapLink() | |
| 605 | { | |
| 606 | return new ValueInternalLink(); | |
| 607 | } | |
| 603 | virtual ValueInternalLink *allocateMapLink() | |
| 604 | { | |
| 605 | return new ValueInternalLink(); | |
| 606 | } | |
| 608 | 607 | |
| 609 | virtual void releaseMapLink( ValueInternalLink *link ) | |
| 610 | { | |
| 611 | delete link; | |
| 612 | } | |
| 613 | }; | |
| 614 | * \endcode | |
| 615 | */ | |
| 616 | class JSON_API ValueMapAllocator | |
| 617 | { | |
| 618 | public: | |
| 619 | virtual ~ValueMapAllocator(); | |
| 620 | virtual ValueInternalMap *newMap() = 0; | |
| 621 | virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) = 0; | |
| 622 | virtual void destructMap( ValueInternalMap *map ) = 0; | |
| 623 | virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) = 0; | |
| 624 | virtual void releaseMapBuckets( ValueInternalLink *links ) = 0; | |
| 625 | virtual ValueInternalLink *allocateMapLink() = 0; | |
| 626 | virtual void releaseMapLink( ValueInternalLink *link ) = 0; | |
| 627 | }; | |
| 608 | virtual void releaseMapLink( ValueInternalLink *link ) | |
| 609 | { | |
| 610 | delete link; | |
| 611 | } | |
| 612 | }; | |
| 613 | * \endcode | |
| 614 | */ | |
| 615 | class JSON_API ValueMapAllocator | |
| 616 | { | |
| 617 | public: | |
| 618 | virtual ~ValueMapAllocator(); | |
| 619 | virtual ValueInternalMap *newMap() = 0; | |
| 620 | virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) = 0; | |
| 621 | virtual void destructMap( ValueInternalMap *map ) = 0; | |
| 622 | virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) = 0; | |
| 623 | virtual void releaseMapBuckets( ValueInternalLink *links ) = 0; | |
| 624 | virtual ValueInternalLink *allocateMapLink() = 0; | |
| 625 | virtual void releaseMapLink( ValueInternalLink *link ) = 0; | |
| 626 | }; | |
| 628 | 627 | |
| 629 | /** \brief ValueInternalMap hash-map bucket chain link (for internal use only). | |
| 630 | * \internal previous_ & next_ allows for bidirectional traversal. | |
| 631 | */ | |
| 632 | class JSON_API ValueInternalLink | |
| 633 | { | |
| 634 | public: | |
| 635 | enum { itemPerLink = 6 }; // sizeof(ValueInternalLink) = 128 on 32 bits architecture. | |
| 636 | enum InternalFlags { | |
| 637 | flagAvailable = 0, | |
| 638 | flagUsed = 1 | |
| 639 | }; | |
| 628 | /** \brief ValueInternalMap hash-map bucket chain link (for internal use only). | |
| 629 | * \internal previous_ & next_ allows for bidirectional traversal. | |
| 630 | */ | |
| 631 | class JSON_API ValueInternalLink | |
| 632 | { | |
| 633 | public: | |
| 634 | enum { itemPerLink = 6 }; // sizeof(ValueInternalLink) = 128 on 32 bits architecture. | |
| 635 | enum InternalFlags { | |
| 636 | flagAvailable = 0, | |
| 637 | flagUsed = 1 | |
| 638 | }; | |
| 640 | 639 | |
| 641 | ||
| 640 | ValueInternalLink(); | |
| 642 | 641 | |
| 643 | ||
| 642 | ~ValueInternalLink(); | |
| 644 | 643 | |
| 645 | Value items_[itemPerLink]; | |
| 646 | char *keys_[itemPerLink]; | |
| 647 | ValueInternalLink *previous_; | |
| 648 | ValueInternalLink *next_; | |
| 649 | }; | |
| 644 | Value items_[itemPerLink]; | |
| 645 | char *keys_[itemPerLink]; | |
| 646 | ValueInternalLink *previous_; | |
| 647 | ValueInternalLink *next_; | |
| 648 | }; | |
| 650 | 649 | |
| 651 | 650 | |
| 652 | /** \brief A linked page based hash-table implementation used internally by Value. | |
| 653 | * \internal ValueInternalMap is a tradional bucket based hash-table, with a linked | |
| 654 | * list in each bucket to handle collision. There is an addional twist in that | |
| 655 | * each node of the collision linked list is a page containing a fixed amount of | |
| 656 | * value. This provides a better compromise between memory usage and speed. | |
| 657 | * | |
| 658 | * Each bucket is made up of a chained list of ValueInternalLink. The last | |
| 659 | * link of a given bucket can be found in the 'previous_' field of the following bucket. | |
| 660 | * The last link of the last bucket is stored in tailLink_ as it has no following bucket. | |
| 661 | * Only the last link of a bucket may contains 'available' item. The last link always | |
| 662 | * contains at least one element unless is it the bucket one very first link. | |
| 663 | */ | |
| 664 | class JSON_API ValueInternalMap | |
| 665 | { | |
| 666 | friend class ValueIteratorBase; | |
| 667 | friend class Value; | |
| 668 | public: | |
| 669 | typedef unsigned int HashKey; | |
| 670 | typedef unsigned int BucketIndex; | |
| 651 | /** \brief A linked page based hash-table implementation used internally by Value. | |
| 652 | * \internal ValueInternalMap is a tradional bucket based hash-table, with a linked | |
| 653 | * list in each bucket to handle collision. There is an addional twist in that | |
| 654 | * each node of the collision linked list is a page containing a fixed amount of | |
| 655 | * value. This provides a better compromise between memory usage and speed. | |
| 656 | * | |
| 657 | * Each bucket is made up of a chained list of ValueInternalLink. The last | |
| 658 | * link of a given bucket can be found in the 'previous_' field of the following bucket. | |
| 659 | * The last link of the last bucket is stored in tailLink_ as it has no following bucket. | |
| 660 | * Only the last link of a bucket may contains 'available' item. The last link always | |
| 661 | * contains at least one element unless is it the bucket one very first link. | |
| 662 | */ | |
| 663 | class JSON_API ValueInternalMap | |
| 664 | { | |
| 665 | friend class ValueIteratorBase; | |
| 666 | friend class Value; | |
| 667 | public: | |
| 668 | typedef unsigned int HashKey; | |
| 669 | typedef unsigned int BucketIndex; | |
| 671 | 670 | |
| 672 | 671 | # ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION |
| 673 | struct IteratorState | |
| 674 | { | |
| 675 | IteratorState() | |
| 676 | : map_(0) | |
| 677 | , link_(0) | |
| 678 | , itemIndex_(0) | |
| 679 | , bucketIndex_(0) | |
| 680 | { | |
| 681 | } | |
| 682 | ValueInternalMap *map_; | |
| 683 | ValueInternalLink *link_; | |
| 684 | BucketIndex itemIndex_; | |
| 685 | BucketIndex bucketIndex_; | |
| 686 | }; | |
| 672 | struct IteratorState | |
| 673 | { | |
| 674 | IteratorState() | |
| 675 | : map_(0) | |
| 676 | , link_(0) | |
| 677 | , itemIndex_(0) | |
| 678 | , bucketIndex_(0) | |
| 679 | { | |
| 680 | } | |
| 681 | ValueInternalMap *map_; | |
| 682 | ValueInternalLink *link_; | |
| 683 | BucketIndex itemIndex_; | |
| 684 | BucketIndex bucketIndex_; | |
| 685 | }; | |
| 687 | 686 | # endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION |
| 688 | 687 | |
| 689 | ValueInternalMap(); | |
| 690 | ValueInternalMap( const ValueInternalMap &other ); | |
| 691 | ValueInternalMap &operator =( const ValueInternalMap &other ); | |
| 692 | ~ValueInternalMap(); | |
| 688 | ValueInternalMap(); | |
| 689 | ValueInternalMap( const ValueInternalMap &other ); | |
| 690 | ValueInternalMap &operator =( const ValueInternalMap &other ); | |
| 691 | ~ValueInternalMap(); | |
| 693 | 692 | |
| 694 | ||
| 693 | void swap( ValueInternalMap &other ); | |
| 695 | 694 | |
| 696 | ||
| 695 | BucketIndex size() const; | |
| 697 | 696 | |
| 698 | ||
| 697 | void clear(); | |
| 699 | 698 | |
| 700 | ||
| 699 | bool reserveDelta( BucketIndex growth ); | |
| 701 | 700 | |
| 702 | ||
| 701 | bool reserve( BucketIndex newItemCount ); | |
| 703 | 702 | |
| 704 | ||
| 703 | const Value *find( const char *key ) const; | |
| 705 | 704 | |
| 706 | ||
| 705 | Value *find( const char *key ); | |
| 707 | 706 | |
| 708 | Value &resolveReference( const char *key, | |
| 709 | bool isStatic ); | |
| 707 | Value &resolveReference( const char *key, | |
| 708 | bool isStatic ); | |
| 710 | 709 | |
| 711 | ||
| 710 | void remove( const char *key ); | |
| 712 | 711 | |
| 713 | void doActualRemove( ValueInternalLink *link, | |
| 714 | BucketIndex index, | |
| 715 | BucketIndex bucketIndex ); | |
| 712 | void doActualRemove( ValueInternalLink *link, | |
| 713 | BucketIndex index, | |
| 714 | BucketIndex bucketIndex ); | |
| 716 | 715 | |
| 717 | ||
| 716 | ValueInternalLink *&getLastLinkInBucket( BucketIndex bucketIndex ); | |
| 718 | 717 | |
| 719 | Value &setNewItem( const char *key, | |
| 720 | bool isStatic, | |
| 721 | ValueInternalLink *link, | |
| 722 | BucketIndex index ); | |
| 718 | Value &setNewItem( const char *key, | |
| 719 | bool isStatic, | |
| 720 | ValueInternalLink *link, | |
| 721 | BucketIndex index ); | |
| 723 | 722 | |
| 724 | Value &unsafeAdd( const char *key, | |
| 725 | bool isStatic, | |
| 726 | HashKey hashedKey ); | |
| 723 | Value &unsafeAdd( const char *key, | |
| 724 | bool isStatic, | |
| 725 | HashKey hashedKey ); | |
| 727 | 726 | |
| 728 | ||
| 727 | HashKey hash( const char *key ) const; | |
| 729 | 728 | |
| 730 | ||
| 729 | int compare( const ValueInternalMap &other ) const; | |
| 731 | 730 | |
| 732 | private: | |
| 733 | void makeBeginIterator( IteratorState &it ) const; | |
| 734 | void makeEndIterator( IteratorState &it ) const; | |
| 735 | static bool equals( const IteratorState &x, const IteratorState &other ); | |
| 736 | static void increment( IteratorState &iterator ); | |
| 737 | static void incrementBucket( IteratorState &iterator ); | |
| 738 | static void decrement( IteratorState &iterator ); | |
| 739 | static const char *key( const IteratorState &iterator ); | |
| 740 | static const char *key( const IteratorState &iterator, bool &isStatic ); | |
| 741 | static Value &value( const IteratorState &iterator ); | |
| 742 | static int distance( const IteratorState &x, const IteratorState &y ); | |
| 731 | private: | |
| 732 | void makeBeginIterator( IteratorState &it ) const; | |
| 733 | void makeEndIterator( IteratorState &it ) const; | |
| 734 | static bool equals( const IteratorState &x, const IteratorState &other ); | |
| 735 | static void increment( IteratorState &iterator ); | |
| 736 | static void incrementBucket( IteratorState &iterator ); | |
| 737 | static void decrement( IteratorState &iterator ); | |
| 738 | static const char *key( const IteratorState &iterator ); | |
| 739 | static const char *key( const IteratorState &iterator, bool &isStatic ); | |
| 740 | static Value &value( const IteratorState &iterator ); | |
| 741 | static int distance( const IteratorState &x, const IteratorState &y ); | |
| 743 | 742 | |
| 744 | private: | |
| 745 | ValueInternalLink *buckets_; | |
| 746 | ValueInternalLink *tailLink_; | |
| 747 | BucketIndex bucketsSize_; | |
| 748 | BucketIndex itemCount_; | |
| 749 | }; | |
| 743 | private: | |
| 744 | ValueInternalLink *buckets_; | |
| 745 | ValueInternalLink *tailLink_; | |
| 746 | BucketIndex bucketsSize_; | |
| 747 | BucketIndex itemCount_; | |
| 748 | }; | |
| 750 | 749 | |
| 751 | /** \brief A simplified deque implementation used internally by Value. | |
| 752 | * \internal | |
| 753 | * It is based on a list of fixed "page", each page contains a fixed number of items. | |
| 754 | * Instead of using a linked-list, a array of pointer is used for fast item look-up. | |
| 755 | * Look-up for an element is as follow: | |
| 756 | * - compute page index: pageIndex = itemIndex / itemsPerPage | |
| 757 | * - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage] | |
| 758 | * | |
| 759 | * Insertion is amortized constant time (only the array containing the index of pointers | |
| 760 | * need to be reallocated when items are appended). | |
| 761 | */ | |
| 762 | class JSON_API ValueInternalArray | |
| 763 | { | |
| 764 | friend class Value; | |
| 765 | friend class ValueIteratorBase; | |
| 766 | public: | |
| 767 | enum { itemsPerPage = 8 }; // should be a power of 2 for fast divide and modulo. | |
| 768 | typedef Value::ArrayIndex ArrayIndex; | |
| 769 | typedef unsigned int PageIndex; | |
| 750 | /** \brief A simplified deque implementation used internally by Value. | |
| 751 | * \internal | |
| 752 | * It is based on a list of fixed "page", each page contains a fixed number of items. | |
| 753 | * Instead of using a linked-list, a array of pointer is used for fast item look-up. | |
| 754 | * Look-up for an element is as follow: | |
| 755 | * - compute page index: pageIndex = itemIndex / itemsPerPage | |
| 756 | * - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage] | |
| 757 | * | |
| 758 | * Insertion is amortized constant time (only the array containing the index of pointers | |
| 759 | * need to be reallocated when items are appended). | |
| 760 | */ | |
| 761 | class JSON_API ValueInternalArray | |
| 762 | { | |
| 763 | friend class Value; | |
| 764 | friend class ValueIteratorBase; | |
| 765 | public: | |
| 766 | enum { itemsPerPage = 8 }; // should be a power of 2 for fast divide and modulo. | |
| 767 | typedef Value::ArrayIndex ArrayIndex; | |
| 768 | typedef unsigned int PageIndex; | |
| 770 | 769 | |
| 771 | 770 | # ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION |
| 772 | struct IteratorState // Must be a POD | |
| 773 | { | |
| 774 | IteratorState() | |
| 775 | : array_(0) | |
| 776 | , currentPageIndex_(0) | |
| 777 | , currentItemIndex_(0) | |
| 778 | { | |
| 779 | } | |
| 780 | ValueInternalArray *array_; | |
| 781 | Value **currentPageIndex_; | |
| 782 | unsigned int currentItemIndex_; | |
| 783 | }; | |
| 771 | struct IteratorState // Must be a POD | |
| 772 | { | |
| 773 | IteratorState() | |
| 774 | : array_(0) | |
| 775 | , currentPageIndex_(0) | |
| 776 | , currentItemIndex_(0) | |
| 777 | { | |
| 778 | } | |
| 779 | ValueInternalArray *array_; | |
| 780 | Value **currentPageIndex_; | |
| 781 | unsigned int currentItemIndex_; | |
| 782 | }; | |
| 784 | 783 | # endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION |
| 785 | 784 | |
| 786 | ValueInternalArray(); | |
| 787 | ValueInternalArray( const ValueInternalArray &other ); | |
| 788 | ValueInternalArray &operator =( const ValueInternalArray &other ); | |
| 789 | ~ValueInternalArray(); | |
| 790 | void swap( ValueInternalArray &other ); | |
| 785 | ValueInternalArray(); | |
| 786 | ValueInternalArray( const ValueInternalArray &other ); | |
| 787 | ValueInternalArray &operator =( const ValueInternalArray &other ); | |
| 788 | ~ValueInternalArray(); | |
| 789 | void swap( ValueInternalArray &other ); | |
| 791 | 790 | |
| 792 | void clear(); | |
| 793 | void resize( ArrayIndex newSize ); | |
| 791 | void clear(); | |
| 792 | void resize( ArrayIndex newSize ); | |
| 794 | 793 | |
| 795 | ||
| 794 | Value &resolveReference( ArrayIndex index ); | |
| 796 | 795 | |
| 797 | ||
| 796 | Value *find( ArrayIndex index ) const; | |
| 798 | 797 | |
| 799 | ||
| 798 | ArrayIndex size() const; | |
| 800 | 799 | |
| 801 | ||
| 800 | int compare( const ValueInternalArray &other ) const; | |
| 802 | 801 | |
| 803 | private: | |
| 804 | static bool equals( const IteratorState &x, const IteratorState &other ); | |
| 805 | static void increment( IteratorState &iterator ); | |
| 806 | static void decrement( IteratorState &iterator ); | |
| 807 | static Value &dereference( const IteratorState &iterator ); | |
| 808 | static Value &unsafeDereference( const IteratorState &iterator ); | |
| 809 | static int distance( const IteratorState &x, const IteratorState &y ); | |
| 810 | static ArrayIndex indexOf( const IteratorState &iterator ); | |
| 811 | void makeBeginIterator( IteratorState &it ) const; | |
| 812 | void makeEndIterator( IteratorState &it ) const; | |
| 813 | void makeIterator( IteratorState &it, ArrayIndex index ) const; | |
| 802 | private: | |
| 803 | static bool equals( const IteratorState &x, const IteratorState &other ); | |
| 804 | static void increment( IteratorState &iterator ); | |
| 805 | static void decrement( IteratorState &iterator ); | |
| 806 | static Value &dereference( const IteratorState &iterator ); | |
| 807 | static Value &unsafeDereference( const IteratorState &iterator ); | |
| 808 | static int distance( const IteratorState &x, const IteratorState &y ); | |
| 809 | static ArrayIndex indexOf( const IteratorState &iterator ); | |
| 810 | void makeBeginIterator( IteratorState &it ) const; | |
| 811 | void makeEndIterator( IteratorState &it ) const; | |
| 812 | void makeIterator( IteratorState &it, ArrayIndex index ) const; | |
| 814 | 813 | |
| 815 | ||
| 814 | void makeIndexValid( ArrayIndex index ); | |
| 816 | 815 | |
| 817 | Value **pages_; | |
| 818 | ArrayIndex size_; | |
| 819 | PageIndex pageCount_; | |
| 820 | }; | |
| 816 | Value **pages_; | |
| 817 | ArrayIndex size_; | |
| 818 | PageIndex pageCount_; | |
| 819 | }; | |
| 821 | 820 | |
| 822 | /** \brief Experimental: do not use. Allocator to customize Value internal array. | |
| 823 | * Below is an example of a simple implementation (actual implementation use | |
| 824 | * memory pool). | |
| 825 | \code | |
| 821 | /** \brief Experimental: do not use. Allocator to customize Value internal array. | |
| 822 | * Below is an example of a simple implementation (actual implementation use | |
| 823 | * memory pool). | |
| 824 | \code | |
| 826 | 825 | class DefaultValueArrayAllocator : public ValueArrayAllocator |
| 827 | 826 | { |
| 828 | 827 | public: // overridden from ValueArrayAllocator |
| 829 | virtual ~DefaultValueArrayAllocator() | |
| 830 | { | |
| 831 | } | |
| 828 | virtual ~DefaultValueArrayAllocator() | |
| 829 | { | |
| 830 | } | |
| 832 | 831 | |
| 833 | virtual ValueInternalArray *newArray() | |
| 834 | { | |
| 835 | return new ValueInternalArray(); | |
| 836 | } | |
| 832 | virtual ValueInternalArray *newArray() | |
| 833 | { | |
| 834 | return new ValueInternalArray(); | |
| 835 | } | |
| 837 | 836 | |
| 838 | virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) | |
| 839 | { | |
| 840 | return new ValueInternalArray( other ); | |
| 841 | } | |
| 837 | virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) | |
| 838 | { | |
| 839 | return new ValueInternalArray( other ); | |
| 840 | } | |
| 842 | 841 | |
| 843 | virtual void destruct( ValueInternalArray *array ) | |
| 844 | { | |
| 845 | delete array; | |
| 846 | } | |
| 842 | virtual void destruct( ValueInternalArray *array ) | |
| 843 | { | |
| 844 | delete array; | |
| 845 | } | |
| 847 | 846 | |
| 848 | virtual void reallocateArrayPageIndex( Value **&indexes, | |
| 849 | ValueInternalArray::PageIndex &indexCount, | |
| 850 | ValueInternalArray::PageIndex minNewIndexCount ) | |
| 851 | { | |
| 852 | ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1; | |
| 853 | if ( minNewIndexCount > newIndexCount ) | |
| 854 | newIndexCount = minNewIndexCount; | |
| 855 | void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount ); | |
| 856 | if ( !newIndexes ) | |
| 857 | throw std::bad_alloc(); | |
| 858 | indexCount = newIndexCount; | |
| 859 | indexes = static_cast<Value **>( newIndexes ); | |
| 860 | } | |
| 861 | virtual void releaseArrayPageIndex( Value **indexes, | |
| 862 | ValueInternalArray::PageIndex indexCount ) | |
| 863 | { | |
| 864 | if ( indexes ) | |
| 865 | free( indexes ); | |
| 866 | } | |
| 847 | virtual void reallocateArrayPageIndex( Value **&indexes, | |
| 848 | ValueInternalArray::PageIndex &indexCount, | |
| 849 | ValueInternalArray::PageIndex minNewIndexCount ) | |
| 850 | { | |
| 851 | ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1; | |
| 852 | if ( minNewIndexCount > newIndexCount ) | |
| 853 | newIndexCount = minNewIndexCount; | |
| 854 | void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount ); | |
| 855 | if ( !newIndexes ) | |
| 856 | throw std::bad_alloc(); | |
| 857 | indexCount = newIndexCount; | |
| 858 | indexes = static_cast<Value **>( newIndexes ); | |
| 859 | } | |
| 860 | virtual void releaseArrayPageIndex( Value **indexes, | |
| 861 | ValueInternalArray::PageIndex indexCount ) | |
| 862 | { | |
| 863 | if ( indexes ) | |
| 864 | free( indexes ); | |
| 865 | } | |
| 867 | 866 | |
| 868 | virtual Value *allocateArrayPage() | |
| 869 | { | |
| 870 | return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) ); | |
| 871 | } | |
| 867 | virtual Value *allocateArrayPage() | |
| 868 | { | |
| 869 | return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) ); | |
| 870 | } | |
| 872 | 871 | |
| 873 | virtual void releaseArrayPage( Value *value ) | |
| 874 | { | |
| 875 | if ( value ) | |
| 876 | free( value ); | |
| 877 | } | |
| 872 | virtual void releaseArrayPage( Value *value ) | |
| 873 | { | |
| 874 | if ( value ) | |
| 875 | free( value ); | |
| 876 | } | |
| 878 | 877 | }; |
| 879 | \endcode | |
| 880 | */ | |
| 881 | class JSON_API ValueArrayAllocator | |
| 882 | { | |
| 883 | public: | |
| 884 | virtual ~ValueArrayAllocator(); | |
| 885 | virtual ValueInternalArray *newArray() = 0; | |
| 886 | virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) = 0; | |
| 887 | virtual void destructArray( ValueInternalArray *array ) = 0; | |
| 888 | /** \brief Reallocate array page index. | |
| 889 | * Reallocates an array of pointer on each page. | |
| 890 | * \param indexes [input] pointer on the current index. May be \c NULL. | |
| 891 | * [output] pointer on the new index of at least | |
| 892 | * \a minNewIndexCount pages. | |
| 893 | * \param indexCount [input] current number of pages in the index. | |
| 894 | * [output] number of page the reallocated index can handle. | |
| 895 | * \b MUST be >= \a minNewIndexCount. | |
| 896 | * \param minNewIndexCount Minimum number of page the new index must be able to | |
| 897 | * handle. | |
| 898 | */ | |
| 899 | virtual void reallocateArrayPageIndex( Value **&indexes, | |
| 900 | ValueInternalArray::PageIndex &indexCount, | |
| 901 | ValueInternalArray::PageIndex minNewIndexCount ) = 0; | |
| 902 | virtual void releaseArrayPageIndex( Value **indexes, | |
| 903 | ValueInternalArray::PageIndex indexCount ) = 0; | |
| 904 | virtual Value *allocateArrayPage() = 0; | |
| 905 | virtual void releaseArrayPage( Value *value ) = 0; | |
| 906 | }; | |
| 878 | \endcode | |
| 879 | */ | |
| 880 | class JSON_API ValueArrayAllocator | |
| 881 | { | |
| 882 | public: | |
| 883 | virtual ~ValueArrayAllocator(); | |
| 884 | virtual ValueInternalArray *newArray() = 0; | |
| 885 | virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) = 0; | |
| 886 | virtual void destructArray( ValueInternalArray *array ) = 0; | |
| 887 | /** \brief Reallocate array page index. | |
| 888 | * Reallocates an array of pointer on each page. | |
| 889 | * \param indexes [input] pointer on the current index. May be \c NULL. | |
| 890 | * [output] pointer on the new index of at least | |
| 891 | * \a minNewIndexCount pages. | |
| 892 | * \param indexCount [input] current number of pages in the index. | |
| 893 | * [output] number of page the reallocated index can handle. | |
| 894 | * \b MUST be >= \a minNewIndexCount. | |
| 895 | * \param minNewIndexCount Minimum number of page the new index must be able to | |
| 896 | * handle. | |
| 897 | */ | |
| 898 | virtual void reallocateArrayPageIndex( Value **&indexes, | |
| 899 | ValueInternalArray::PageIndex &indexCount, | |
| 900 | ValueInternalArray::PageIndex minNewIndexCount ) = 0; | |
| 901 | virtual void releaseArrayPageIndex( Value **indexes, | |
| 902 | ValueInternalArray::PageIndex indexCount ) = 0; | |
| 903 | virtual Value *allocateArrayPage() = 0; | |
| 904 | virtual void releaseArrayPage( Value *value ) = 0; | |
| 905 | }; | |
| 907 | 906 | #endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP |
| 908 | 907 | |
| 909 | 908 | |
| 910 | /** \brief base class for Value iterators. | |
| 911 | * | |
| 912 | */ | |
| 913 | class ValueIteratorBase | |
| 914 | { | |
| 915 | public: | |
| 916 | typedef unsigned int size_t; | |
| 917 | typedef int difference_type; | |
| 918 | typedef ValueIteratorBase SelfType; | |
| 909 | /** \brief base class for Value iterators. | |
| 910 | * | |
| 911 | */ | |
| 912 | class ValueIteratorBase | |
| 913 | { | |
| 914 | public: | |
| 915 | typedef unsigned int size_t; | |
| 916 | typedef int difference_type; | |
| 917 | typedef ValueIteratorBase SelfType; | |
| 919 | 918 | |
| 920 | ||
| 919 | ValueIteratorBase(); | |
| 921 | 920 | #ifndef JSON_VALUE_USE_INTERNAL_MAP |
| 922 | ||
| 921 | explicit ValueIteratorBase( const Value::ObjectValues::iterator ¤t ); | |
| 923 | 922 | #else |
| 924 | ValueIteratorBase( const ValueInternalArray::IteratorState &state ); | |
| 925 | ValueIteratorBase( const ValueInternalMap::IteratorState &state ); | |
| 923 | ValueIteratorBase( const ValueInternalArray::IteratorState &state ); | |
| 924 | ValueIteratorBase( const ValueInternalMap::IteratorState &state ); | |
| 926 | 925 | #endif |
| 927 | 926 | |
| 928 | bool operator ==( const SelfType &other ) const | |
| 929 | { | |
| 930 | return isEqual( other ); | |
| 931 | } | |
| 927 | bool operator ==( const SelfType &other ) const | |
| 928 | { | |
| 929 | return isEqual( other ); | |
| 930 | } | |
| 932 | 931 | |
| 933 | bool operator !=( const SelfType &other ) const | |
| 934 | { | |
| 935 | return !isEqual( other ); | |
| 936 | } | |
| 932 | bool operator !=( const SelfType &other ) const | |
| 933 | { | |
| 934 | return !isEqual( other ); | |
| 935 | } | |
| 937 | 936 | |
| 938 | difference_type operator -( const SelfType &other ) const | |
| 939 | { | |
| 940 | return computeDistance( other ); | |
| 941 | } | |
| 937 | difference_type operator -( const SelfType &other ) const | |
| 938 | { | |
| 939 | return computeDistance( other ); | |
| 940 | } | |
| 942 | 941 | |
| 943 | /// Return either the index or the member name of the referenced value as a Value. | |
| 944 | Value key() const; | |
| 942 | /// Return either the index or the member name of the referenced value as a Value. | |
| 943 | Value key() const; | |
| 945 | 944 | |
| 946 | /// Return the index of the referenced Value. -1 if it is not an arrayValue. | |
| 947 | UInt index() const; | |
| 945 | /// Return the index of the referenced Value. -1 if it is not an arrayValue. | |
| 946 | UInt index() const; | |
| 948 | 947 | |
| 949 | /// Return the member name of the referenced Value. "" if it is not an objectValue. | |
| 950 | const char *memberName() const; | |
| 948 | /// Return the member name of the referenced Value. "" if it is not an objectValue. | |
| 949 | const char *memberName() const; | |
| 951 | 950 | |
| 952 | protected: | |
| 953 | Value &deref() const; | |
| 951 | protected: | |
| 952 | Value &deref() const; | |
| 954 | 953 | |
| 955 | ||
| 954 | void increment(); | |
| 956 | 955 | |
| 957 | ||
| 956 | void decrement(); | |
| 958 | 957 | |
| 959 | ||
| 958 | difference_type computeDistance( const SelfType &other ) const; | |
| 960 | 959 | |
| 961 | ||
| 960 | bool isEqual( const SelfType &other ) const; | |
| 962 | 961 | |
| 963 | ||
| 962 | void copy( const SelfType &other ); | |
| 964 | 963 | |
| 965 | ||
| 964 | private: | |
| 966 | 965 | #ifndef JSON_VALUE_USE_INTERNAL_MAP |
| 967 | Value::ObjectValues::iterator current_; | |
| 968 | // Indicates that iterator is for a null value. | |
| 969 | bool isNull_; | |
| 966 | Value::ObjectValues::iterator current_; | |
| 967 | // Indicates that iterator is for a null value. | |
| 968 | bool isNull_; | |
| 970 | 969 | #else |
| 971 | union | |
| 972 | { | |
| 973 | ValueInternalArray::IteratorState array_; | |
| 974 | ValueInternalMap::IteratorState map_; | |
| 975 | } iterator_; | |
| 976 | bool isArray_; | |
| 970 | union | |
| 971 | { | |
| 972 | ValueInternalArray::IteratorState array_; | |
| 973 | ValueInternalMap::IteratorState map_; | |
| 974 | } iterator_; | |
| 975 | bool isArray_; | |
| 977 | 976 | #endif |
| 978 | ||
| 977 | }; | |
| 979 | 978 | |
| 980 | /** \brief const iterator for object and array value. | |
| 981 | * | |
| 982 | */ | |
| 983 | class ValueConstIterator : public ValueIteratorBase | |
| 984 | { | |
| 985 | friend class Value; | |
| 986 | public: | |
| 987 | typedef unsigned int size_t; | |
| 988 | typedef int difference_type; | |
| 989 | typedef const Value &reference; | |
| 990 | typedef const Value *pointer; | |
| 991 | typedef ValueConstIterator SelfType; | |
| 979 | /** \brief const iterator for object and array value. | |
| 980 | * | |
| 981 | */ | |
| 982 | class ValueConstIterator : public ValueIteratorBase | |
| 983 | { | |
| 984 | friend class Value; | |
| 985 | public: | |
| 986 | typedef unsigned int size_t; | |
| 987 | typedef int difference_type; | |
| 988 | typedef const Value &reference; | |
| 989 | typedef const Value *pointer; | |
| 990 | typedef ValueConstIterator SelfType; | |
| 992 | 991 | |
| 993 | ValueConstIterator(); | |
| 994 | private: | |
| 995 | /*! \internal Use by Value to create an iterator. | |
| 996 | */ | |
| 992 | ValueConstIterator(); | |
| 993 | private: | |
| 994 | /*! \internal Use by Value to create an iterator. | |
| 995 | */ | |
| 997 | 996 | #ifndef JSON_VALUE_USE_INTERNAL_MAP |
| 998 | ||
| 997 | explicit ValueConstIterator( const Value::ObjectValues::iterator ¤t ); | |
| 999 | 998 | #else |
| 1000 | ValueConstIterator( const ValueInternalArray::IteratorState &state ); | |
| 1001 | ValueConstIterator( const ValueInternalMap::IteratorState &state ); | |
| 999 | ValueConstIterator( const ValueInternalArray::IteratorState &state ); | |
| 1000 | ValueConstIterator( const ValueInternalMap::IteratorState &state ); | |
| 1002 | 1001 | #endif |
| 1003 | public: | |
| 1004 | SelfType &operator =( const ValueIteratorBase &other ); | |
| 1002 | public: | |
| 1003 | SelfType &operator =( const ValueIteratorBase &other ); | |
| 1005 | 1004 | |
| 1006 | SelfType operator++( int ) | |
| 1007 | { | |
| 1008 | SelfType temp( *this ); | |
| 1009 | ++*this; | |
| 1010 | return temp; | |
| 1011 | } | |
| 1005 | SelfType operator++( int ) | |
| 1006 | { | |
| 1007 | SelfType temp( *this ); | |
| 1008 | ++*this; | |
| 1009 | return temp; | |
| 1010 | } | |
| 1012 | 1011 | |
| 1013 | SelfType operator--( int ) | |
| 1014 | { | |
| 1015 | SelfType temp( *this ); | |
| 1016 | --*this; | |
| 1017 | return temp; | |
| 1018 | } | |
| 1012 | SelfType operator--( int ) | |
| 1013 | { | |
| 1014 | SelfType temp( *this ); | |
| 1015 | --*this; | |
| 1016 | return temp; | |
| 1017 | } | |
| 1019 | 1018 | |
| 1020 | SelfType &operator--() | |
| 1021 | { | |
| 1022 | decrement(); | |
| 1023 | return *this; | |
| 1024 | } | |
| 1019 | SelfType &operator--() | |
| 1020 | { | |
| 1021 | decrement(); | |
| 1022 | return *this; | |
| 1023 | } | |
| 1025 | 1024 | |
| 1026 | SelfType &operator++() | |
| 1027 | { | |
| 1028 | increment(); | |
| 1029 | return *this; | |
| 1030 | } | |
| 1025 | SelfType &operator++() | |
| 1026 | { | |
| 1027 | increment(); | |
| 1028 | return *this; | |
| 1029 | } | |
| 1031 | 1030 | |
| 1032 | reference operator *() const | |
| 1033 | { | |
| 1034 | return deref(); | |
| 1035 | } | |
| 1036 | }; | |
| 1031 | reference operator *() const | |
| 1032 | { | |
| 1033 | return deref(); | |
| 1034 | } | |
| 1035 | }; | |
| 1037 | 1036 | |
| 1038 | 1037 | |
| 1039 | /** \brief Iterator for object and array value. | |
| 1040 | */ | |
| 1041 | class ValueIterator : public ValueIteratorBase | |
| 1042 | { | |
| 1043 | friend class Value; | |
| 1044 | public: | |
| 1045 | typedef unsigned int size_t; | |
| 1046 | typedef int difference_type; | |
| 1047 | typedef Value &reference; | |
| 1048 | typedef Value *pointer; | |
| 1049 | typedef ValueIterator SelfType; | |
| 1038 | /** \brief Iterator for object and array value. | |
| 1039 | */ | |
| 1040 | class ValueIterator : public ValueIteratorBase | |
| 1041 | { | |
| 1042 | friend class Value; | |
| 1043 | public: | |
| 1044 | typedef unsigned int size_t; | |
| 1045 | typedef int difference_type; | |
| 1046 | typedef Value &reference; | |
| 1047 | typedef Value *pointer; | |
| 1048 | typedef ValueIterator SelfType; | |
| 1050 | 1049 | |
| 1051 | ValueIterator(); | |
| 1052 | ValueIterator( const ValueConstIterator &other ); | |
| 1053 | ValueIterator( const ValueIterator &other ); | |
| 1054 | private: | |
| 1055 | /*! \internal Use by Value to create an iterator. | |
| 1056 | */ | |
| 1050 | ValueIterator(); | |
| 1051 | ValueIterator( const ValueConstIterator &other ); | |
| 1052 | ValueIterator( const ValueIterator &other ); | |
| 1053 | private: | |
| 1054 | /*! \internal Use by Value to create an iterator. | |
| 1055 | */ | |
| 1057 | 1056 | #ifndef JSON_VALUE_USE_INTERNAL_MAP |
| 1058 | ||
| 1057 | explicit ValueIterator( const Value::ObjectValues::iterator ¤t ); | |
| 1059 | 1058 | #else |
| 1060 | ValueIterator( const ValueInternalArray::IteratorState &state ); | |
| 1061 | ValueIterator( const ValueInternalMap::IteratorState &state ); | |
| 1059 | ValueIterator( const ValueInternalArray::IteratorState &state ); | |
| 1060 | ValueIterator( const ValueInternalMap::IteratorState &state ); | |
| 1062 | 1061 | #endif |
| 1063 | ||
| 1062 | public: | |
| 1064 | 1063 | |
| 1065 | ||
| 1064 | SelfType &operator =( const SelfType &other ); | |
| 1066 | 1065 | |
| 1067 | SelfType operator++( int ) | |
| 1068 | { | |
| 1069 | SelfType temp( *this ); | |
| 1070 | ++*this; | |
| 1071 | return temp; | |
| 1072 | } | |
| 1066 | SelfType operator++( int ) | |
| 1067 | { | |
| 1068 | SelfType temp( *this ); | |
| 1069 | ++*this; | |
| 1070 | return temp; | |
| 1071 | } | |
| 1073 | 1072 | |
| 1074 | SelfType operator--( int ) | |
| 1075 | { | |
| 1076 | SelfType temp( *this ); | |
| 1077 | --*this; | |
| 1078 | return temp; | |
| 1079 | } | |
| 1073 | SelfType operator--( int ) | |
| 1074 | { | |
| 1075 | SelfType temp( *this ); | |
| 1076 | --*this; | |
| 1077 | return temp; | |
| 1078 | } | |
| 1080 | 1079 | |
| 1081 | SelfType &operator--() | |
| 1082 | { | |
| 1083 | decrement(); | |
| 1084 | return *this; | |
| 1085 | } | |
| 1080 | SelfType &operator--() | |
| 1081 | { | |
| 1082 | decrement(); | |
| 1083 | return *this; | |
| 1084 | } | |
| 1086 | 1085 | |
| 1087 | SelfType &operator++() | |
| 1088 | { | |
| 1089 | increment(); | |
| 1090 | return *this; | |
| 1091 | } | |
| 1086 | SelfType &operator++() | |
| 1087 | { | |
| 1088 | increment(); | |
| 1089 | return *this; | |
| 1090 | } | |
| 1092 | 1091 | |
| 1093 | reference operator *() const | |
| 1094 | { | |
| 1095 | return deref(); | |
| 1096 | } | |
| 1097 | }; | |
| 1092 | reference operator *() const | |
| 1093 | { | |
| 1094 | return deref(); | |
| 1095 | } | |
| 1096 | }; | |
| 1098 | 1097 | |
| 1099 | 1098 | |
| 1100 | 1099 | } // namespace Json |
| r25360 | r25361 | |
|---|---|---|
| 14 | 14 | # include <iostream> |
| 15 | 15 | |
| 16 | 16 | namespace Json { |
| 17 | class Value; | |
| 17 | 18 | |
| 18 | class Value; | |
| 19 | /** \brief Abstract class for writers. | |
| 20 | */ | |
| 21 | class JSON_API Writer | |
| 22 | { | |
| 23 | public: | |
| 24 | virtual ~Writer(); | |
| 19 | 25 | |
| 20 | /** \brief Abstract class for writers. | |
| 21 | */ | |
| 22 | class JSON_API Writer | |
| 23 | { | |
| 24 | public: | |
| 25 | virtual ~Writer(); | |
| 26 | virtual std::string write( const Value &root ) = 0; | |
| 27 | }; | |
| 26 | 28 | |
| 27 | virtual std::string write( const Value &root ) = 0; | |
| 28 | }; | |
| 29 | /** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format without formatting (not human friendly). | |
| 30 | * | |
| 31 | * The JSON document is written in a single line. It is not intended for 'human' consumption, | |
| 32 | * but may be usefull to support feature such as RPC where bandwith is limited. | |
| 33 | * \sa Reader, Value | |
| 34 | */ | |
| 35 | class JSON_API FastWriter : public Writer | |
| 36 | { | |
| 37 | public: | |
| 38 | FastWriter(); | |
| 39 | virtual ~FastWriter(){} | |
| 29 | 40 | |
| 30 | /** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format without formatting (not human friendly). | |
| 31 | * | |
| 32 | * The JSON document is written in a single line. It is not intended for 'human' consumption, | |
| 33 | * but may be usefull to support feature such as RPC where bandwith is limited. | |
| 34 | * \sa Reader, Value | |
| 35 | */ | |
| 36 | class JSON_API FastWriter : public Writer | |
| 37 | { | |
| 38 | public: | |
| 39 | FastWriter(); | |
| 40 | virtual ~FastWriter(){} | |
| 41 | void enableYAMLCompatibility(); | |
| 41 | 42 | |
| 42 | void enableYAMLCompatibility(); | |
| 43 | public: // overridden from Writer | |
| 44 | virtual std::string write( const Value &root ); | |
| 43 | 45 | |
| 44 | public: // overridden from Writer | |
| 45 | virtual std::string write( const Value &root ); | |
| 46 | private: | |
| 47 | void writeValue( const Value &value ); | |
| 46 | 48 | |
| 47 | private: | |
| 48 | void writeValue( const Value &value ); | |
| 49 | std::string document_; | |
| 50 | bool yamlCompatiblityEnabled_; | |
| 51 | }; | |
| 49 | 52 | |
| 50 | std::string document_; | |
| 51 | bool yamlCompatiblityEnabled_; | |
| 52 | }; | |
| 53 | /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way. | |
| 54 | * | |
| 55 | * The rules for line break and indent are as follow: | |
| 56 | * - Object value: | |
| 57 | * - if empty then print {} without indent and line break | |
| 58 | * - if not empty the print '{', line break & indent, print one value per line | |
| 59 | * and then unindent and line break and print '}'. | |
| 60 | * - Array value: | |
| 61 | * - if empty then print [] without indent and line break | |
| 62 | * - if the array contains no object value, empty array or some other value types, | |
| 63 | * and all the values fit on one lines, then print the array on a single line. | |
| 64 | * - otherwise, it the values do not fit on one line, or the array contains | |
| 65 | * object or non empty array, then print one value per line. | |
| 66 | * | |
| 67 | * If the Value have comments then they are outputed according to their #CommentPlacement. | |
| 68 | * | |
| 69 | * \sa Reader, Value, Value::setComment() | |
| 70 | */ | |
| 71 | class JSON_API StyledWriter: public Writer | |
| 72 | { | |
| 73 | public: | |
| 74 | StyledWriter(); | |
| 75 | virtual ~StyledWriter(){} | |
| 53 | 76 | |
| 54 | /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way. | |
| 55 | * | |
| 56 | * The rules for line break and indent are as follow: | |
| 57 | * - Object value: | |
| 58 | * - if empty then print {} without indent and line break | |
| 59 | * - if not empty the print '{', line break & indent, print one value per line | |
| 60 | * and then unindent and line break and print '}'. | |
| 61 | * - Array value: | |
| 62 | * - if empty then print [] without indent and line break | |
| 63 | * - if the array contains no object value, empty array or some other value types, | |
| 64 | * and all the values fit on one lines, then print the array on a single line. | |
| 65 | * - otherwise, it the values do not fit on one line, or the array contains | |
| 66 | * object or non empty array, then print one value per line. | |
| 67 | * | |
| 68 | * If the Value have comments then they are outputed according to their #CommentPlacement. | |
| 69 | * | |
| 70 | * \sa Reader, Value, Value::setComment() | |
| 71 | */ | |
| 72 | class JSON_API StyledWriter: public Writer | |
| 73 | { | |
| 74 | public: | |
| 75 | StyledWriter(); | |
| 76 | virtual ~StyledWriter(){} | |
| 77 | public: // overridden from Writer | |
| 78 | /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format. | |
| 79 | * \param root Value to serialize. | |
| 80 | * \return String containing the JSON document that represents the root value. | |
| 81 | */ | |
| 82 | virtual std::string write( const Value &root ); | |
| 77 | 83 | |
| 78 | public: // overridden from Writer | |
| 79 | /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format. | |
| 80 | * \param root Value to serialize. | |
| 81 | * \return String containing the JSON document that represents the root value. | |
| 82 | */ | |
| 83 | virtual std::string write( const Value &root ); | |
| 84 | private: | |
| 85 | void writeValue( const Value &value ); | |
| 86 | void writeArrayValue( const Value &value ); | |
| 87 | bool isMultineArray( const Value &value ); | |
| 88 | void pushValue( const std::string &value ); | |
| 89 | void writeIndent(); | |
| 90 | void writeWithIndent( const std::string &value ); | |
| 91 | void indent(); | |
| 92 | void unindent(); | |
| 93 | void writeCommentBeforeValue( const Value &root ); | |
| 94 | void writeCommentAfterValueOnSameLine( const Value &root ); | |
| 95 | bool hasCommentForValue( const Value &value ); | |
| 96 | static std::string normalizeEOL( const std::string &text ); | |
| 84 | 97 | |
| 85 | private: | |
| 86 | void writeValue( const Value &value ); | |
| 87 | void writeArrayValue( const Value &value ); | |
| 88 | bool isMultineArray( const Value &value ); | |
| 89 | void pushValue( const std::string &value ); | |
| 90 | void writeIndent(); | |
| 91 | void writeWithIndent( const std::string &value ); | |
| 92 | void indent(); | |
| 93 | void unindent(); | |
| 94 | void writeCommentBeforeValue( const Value &root ); | |
| 95 | void writeCommentAfterValueOnSameLine( const Value &root ); | |
| 96 | bool hasCommentForValue( const Value &value ); | |
| 97 | static std::string normalizeEOL( const std::string &text ); | |
| 98 | typedef std::vector<std::string> ChildValues; | |
| 98 | 99 | |
| 99 | typedef std::vector<std::string> ChildValues; | |
| 100 | ChildValues childValues_; | |
| 101 | std::string document_; | |
| 102 | std::string indentString_; | |
| 103 | int rightMargin_; | |
| 104 | int indentSize_; | |
| 105 | bool addChildValues_; | |
| 106 | }; | |
| 100 | 107 | |
| 101 | ChildValues childValues_; | |
| 102 | std::string document_; | |
| 103 | std::string indentString_; | |
| 104 | int rightMargin_; | |
| 105 | int indentSize_; | |
| 106 | bool addChildValues_; | |
| 107 | }; | |
| 108 | /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way, | |
| 109 | to a stream rather than to a string. | |
| 110 | * | |
| 111 | * The rules for line break and indent are as follow: | |
| 112 | * - Object value: | |
| 113 | * - if empty then print {} without indent and line break | |
| 114 | * - if not empty the print '{', line break & indent, print one value per line | |
| 115 | * and then unindent and line break and print '}'. | |
| 116 | * - Array value: | |
| 117 | * - if empty then print [] without indent and line break | |
| 118 | * - if the array contains no object value, empty array or some other value types, | |
| 119 | * and all the values fit on one lines, then print the array on a single line. | |
| 120 | * - otherwise, it the values do not fit on one line, or the array contains | |
| 121 | * object or non empty array, then print one value per line. | |
| 122 | * | |
| 123 | * If the Value have comments then they are outputed according to their #CommentPlacement. | |
| 124 | * | |
| 125 | * \param indentation Each level will be indented by this amount extra. | |
| 126 | * \sa Reader, Value, Value::setComment() | |
| 127 | */ | |
| 128 | class JSON_API StyledStreamWriter | |
| 129 | { | |
| 130 | public: | |
| 131 | StyledStreamWriter( std::string indentation="\t" ); | |
| 132 | ~StyledStreamWriter(){} | |
| 108 | 133 | |
| 109 | /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way, | |
| 110 | to a stream rather than to a string. | |
| 111 | * | |
| 112 | * The rules for line break and indent are as follow: | |
| 113 | * - Object value: | |
| 114 | * - if empty then print {} without indent and line break | |
| 115 | * - if not empty the print '{', line break & indent, print one value per line | |
| 116 | * and then unindent and line break and print '}'. | |
| 117 | * - Array value: | |
| 118 | * - if empty then print [] without indent and line break | |
| 119 | * - if the array contains no object value, empty array or some other value types, | |
| 120 | * and all the values fit on one lines, then print the array on a single line. | |
| 121 | * - otherwise, it the values do not fit on one line, or the array contains | |
| 122 | * object or non empty array, then print one value per line. | |
| 123 | * | |
| 124 | * If the Value have comments then they are outputed according to their #CommentPlacement. | |
| 125 | * | |
| 126 | * \param indentation Each level will be indented by this amount extra. | |
| 127 | * \sa Reader, Value, Value::setComment() | |
| 128 | */ | |
| 129 | class JSON_API StyledStreamWriter | |
| 130 | { | |
| 131 | public: | |
| 132 | StyledStreamWriter( std::string indentation="\t" ); | |
| 133 | ~StyledStreamWriter(){} | |
| 134 | public: | |
| 135 | /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format. | |
| 136 | * \param out Stream to write to. (Can be ostringstream, e.g.) | |
| 137 | * \param root Value to serialize. | |
| 138 | * \note There is no point in deriving from Writer, since write() should not return a value. | |
| 139 | */ | |
| 140 | void write( std::ostream &out, const Value &root ); | |
| 134 | 141 | |
| 135 | public: | |
| 136 | /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format. | |
| 137 | * \param out Stream to write to. (Can be ostringstream, e.g.) | |
| 138 | * \param root Value to serialize. | |
| 139 | * \note There is no point in deriving from Writer, since write() should not return a value. | |
| 140 | */ | |
| 141 | void write( std::ostream &out, const Value &root ); | |
| 142 | private: | |
| 143 | void writeValue( const Value &value ); | |
| 144 | void writeArrayValue( const Value &value ); | |
| 145 | bool isMultineArray( const Value &value ); | |
| 146 | void pushValue( const std::string &value ); | |
| 147 | void writeIndent(); | |
| 148 | void writeWithIndent( const std::string &value ); | |
| 149 | void indent(); | |
| 150 | void unindent(); | |
| 151 | void writeCommentBeforeValue( const Value &root ); | |
| 152 | void writeCommentAfterValueOnSameLine( const Value &root ); | |
| 153 | bool hasCommentForValue( const Value &value ); | |
| 154 | static std::string normalizeEOL( const std::string &text ); | |
| 142 | 155 | |
| 143 | private: | |
| 144 | void writeValue( const Value &value ); | |
| 145 | void writeArrayValue( const Value &value ); | |
| 146 | bool isMultineArray( const Value &value ); | |
| 147 | void pushValue( const std::string &value ); | |
| 148 | void writeIndent(); | |
| 149 | void writeWithIndent( const std::string &value ); | |
| 150 | void indent(); | |
| 151 | void unindent(); | |
| 152 | void writeCommentBeforeValue( const Value &root ); | |
| 153 | void writeCommentAfterValueOnSameLine( const Value &root ); | |
| 154 | bool hasCommentForValue( const Value &value ); | |
| 155 | static std::string normalizeEOL( const std::string &text ); | |
| 156 | typedef std::vector<std::string> ChildValues; | |
| 156 | 157 | |
| 157 | typedef std::vector<std::string> ChildValues; | |
| 158 | ChildValues childValues_; | |
| 159 | std::ostream* document_; | |
| 160 | std::string indentString_; | |
| 161 | int rightMargin_; | |
| 162 | std::string indentation_; | |
| 163 | bool addChildValues_; | |
| 164 | }; | |
| 158 | 165 | |
| 159 | ChildValues childValues_; | |
| 160 | std::ostream* document_; | |
| 161 | std::string indentString_; | |
| 162 | int rightMargin_; | |
| 163 | std::string indentation_; | |
| 164 | bool addChildValues_; | |
| 165 | }; | |
| 166 | ||
| 167 | 166 | # if defined(JSON_HAS_INT64) |
| 168 | std::string JSON_API valueToString( Int value ); | |
| 169 | std::string JSON_API valueToString( UInt value ); | |
| 167 | std::string JSON_API valueToString( Int value ); | |
| 168 | std::string JSON_API valueToString( UInt value ); | |
| 170 | 169 | # endif // if defined(JSON_HAS_INT64) |
| 171 | std::string JSON_API valueToString( LargestInt value ); | |
| 172 | std::string JSON_API valueToString( LargestUInt value ); | |
| 173 | std::string JSON_API valueToString( double value ); | |
| 174 | std::string JSON_API valueToString( bool value ); | |
| 175 | std::string JSON_API valueToQuotedString( const char *value ); | |
| 170 | std::string JSON_API valueToString( LargestInt value ); | |
| 171 | std::string JSON_API valueToString( LargestUInt value ); | |
| 172 | std::string JSON_API valueToString( double value ); | |
| 173 | std::string JSON_API valueToString( bool value ); | |
| 174 | std::string JSON_API valueToQuotedString( const char *value ); | |
| 176 | 175 | |
| 177 | /// \brief Output using the StyledStreamWriter. | |
| 178 | /// \see Json::operator>>() | |
| 179 | std::ostream& operator<<( std::ostream&, const Value &root ); | |
| 176 | /// \brief Output using the StyledStreamWriter. | |
| 177 | /// \see Json::operator>>() | |
| 178 | std::ostream& operator<<( std::ostream&, const Value &root ); | |
| 180 | 179 | |
| 181 | 180 | } // namespace Json |
| 182 | 181 |
| r25360 | r25361 | |
|---|---|---|
| 11 | 11 | #endif // if !defined(JSON_IS_AMALGAMATION) |
| 12 | 12 | |
| 13 | 13 | namespace Json { |
| 14 | /** \brief Configuration passed to reader and writer. | |
| 15 | * This configuration object can be used to force the Reader or Writer | |
| 16 | * to behave in a standard conforming way. | |
| 17 | */ | |
| 18 | class JSON_API Features | |
| 19 | { | |
| 20 | public: | |
| 21 | /** \brief A configuration that allows all features and assumes all strings are UTF-8. | |
| 22 | * - C & C++ comments are allowed | |
| 23 | * - Root object can be any JSON value | |
| 24 | * - Assumes Value strings are encoded in UTF-8 | |
| 25 | */ | |
| 26 | static Features all(); | |
| 14 | 27 | |
| 15 | /** \brief Configuration passed to reader and writer. | |
| 16 | * This configuration object can be used to force the Reader or Writer | |
| 17 | * to behave in a standard conforming way. | |
| 18 | */ | |
| 19 | class JSON_API Features | |
| 20 | { | |
| 21 | public: | |
| 22 | /** \brief A configuration that allows all features and assumes all strings are UTF-8. | |
| 23 | * - C & C++ comments are allowed | |
| 24 | * - Root object can be any JSON value | |
| 25 | * - Assumes Value strings are encoded in UTF-8 | |
| 26 | */ | |
| 27 | static Features all(); | |
| 28 | /** \brief A configuration that is strictly compatible with the JSON specification. | |
| 29 | * - Comments are forbidden. | |
| 30 | * - Root object must be either an array or an object value. | |
| 31 | * - Assumes Value strings are encoded in UTF-8 | |
| 32 | */ | |
| 33 | static Features strictMode(); | |
| 28 | 34 | |
| 29 | /** \brief A configuration that is strictly compatible with the JSON specification. | |
| 30 | * - Comments are forbidden. | |
| 31 | * - Root object must be either an array or an object value. | |
| 32 | * - Assumes Value strings are encoded in UTF-8 | |
| 33 | */ | |
| 34 | static Features strictMode(); | |
| 35 | /** \brief Initialize the configuration like JsonConfig::allFeatures; | |
| 36 | */ | |
| 37 | Features(); | |
| 35 | 38 | |
| 36 | /** \brief Initialize the configuration like JsonConfig::allFeatures; | |
| 37 | */ | |
| 38 | Features(); | |
| 39 | /// \c true if comments are allowed. Default: \c true. | |
| 40 | bool allowComments_; | |
| 39 | 41 | |
| 40 | /// \c true if comments are allowed. Default: \c true. | |
| 41 | bool allowComments_; | |
| 42 | /// \c true if root must be either an array or an object value. Default: \c false. | |
| 43 | bool strictRoot_; | |
| 44 | }; | |
| 42 | 45 | |
| 43 | /// \c true if root must be either an array or an object value. Default: \c false. | |
| 44 | bool strictRoot_; | |
| 45 | }; | |
| 46 | ||
| 47 | 46 | } // namespace Json |
| 48 | 47 | |
| 49 | 48 | #endif // CPPTL_JSON_FEATURES_H_INCLUDED |
| r25360 | r25361 | |
|---|---|---|
| 11 | 11 | #endif // if !defined(JSON_IS_AMALGAMATION) |
| 12 | 12 | |
| 13 | 13 | namespace Json { |
| 14 | // writer.h | |
| 15 | class FastWriter; | |
| 16 | class StyledWriter; | |
| 14 | 17 | |
| 15 | // writer.h | |
| 16 | class FastWriter; | |
| 17 | class StyledWriter; | |
| 18 | // reader.h | |
| 19 | class Reader; | |
| 18 | 20 | |
| 19 | // reader.h | |
| 20 | class Reader; | |
| 21 | // features.h | |
| 22 | class Features; | |
| 21 | 23 | |
| 22 | // features.h | |
| 23 | class Features; | |
| 24 | ||
| 25 | // value.h | |
| 26 | typedef unsigned int ArrayIndex; | |
| 27 | class StaticString; | |
| 28 | class Path; | |
| 29 | class PathArgument; | |
| 30 | class Value; | |
| 31 | class ValueIteratorBase; | |
| 32 | class ValueIterator; | |
| 33 | class ValueConstIterator; | |
| 24 | // value.h | |
| 25 | typedef unsigned int ArrayIndex; | |
| 26 | class StaticString; | |
| 27 | class Path; | |
| 28 | class PathArgument; | |
| 29 | class Value; | |
| 30 | class ValueIteratorBase; | |
| 31 | class ValueIterator; | |
| 32 | class ValueConstIterator; | |
| 34 | 33 | #ifdef JSON_VALUE_USE_INTERNAL_MAP |
| 35 | class ValueMapAllocator; | |
| 36 | class ValueInternalLink; | |
| 37 | class ValueInternalArray; | |
| 38 | class ValueInternalMap; | |
| 34 | class ValueMapAllocator; | |
| 35 | class ValueInternalLink; | |
| 36 | class ValueInternalArray; | |
| 37 | class ValueInternalMap; | |
| 39 | 38 | #endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP |
| 40 | 39 | |
| 41 | 40 | } // namespace Json |
| r25360 | r25361 | |
|---|---|---|
| 16 | 16 | # include <iostream> |
| 17 | 17 | |
| 18 | 18 | namespace Json { |
| 19 | /** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a Value. | |
| 20 | * | |
| 21 | */ | |
| 22 | class JSON_API Reader | |
| 23 | { | |
| 24 | public: | |
| 25 | typedef char Char; | |
| 26 | typedef const Char *Location; | |
| 19 | 27 | |
| 20 | /** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a Value. | |
| 21 | * | |
| 22 | */ | |
| 23 | class JSON_API Reader | |
| 24 | { | |
| 25 | public: | |
| 26 | typedef char Char; | |
| 27 | typedef const Char *Location; | |
| 28 | /** \brief Constructs a Reader allowing all features | |
| 29 | * for parsing. | |
| 30 | */ | |
| 31 | Reader(); | |
| 28 | 32 | |
| 29 | /** \brief Constructs a Reader allowing all features | |
| 30 | * for parsing. | |
| 31 | */ | |
| 32 | Reader(); | |
| 33 | /** \brief Constructs a Reader allowing the specified feature set | |
| 34 | * for parsing. | |
| 35 | */ | |
| 36 | Reader( const Features &features ); | |
| 33 | 37 | |
| 34 | /** \brief Constructs a Reader allowing the specified feature set | |
| 35 | * for parsing. | |
| 36 | */ | |
| 37 | Reader( const Features &features ); | |
| 38 | /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document. | |
| 39 | * \param document UTF-8 encoded string containing the document to read. | |
| 40 | * \param root [out] Contains the root value of the document if it was | |
| 41 | * successfully parsed. | |
| 42 | * \param collectComments \c true to collect comment and allow writing them back during | |
| 43 | * serialization, \c false to discard comments. | |
| 44 | * This parameter is ignored if Features::allowComments_ | |
| 45 | * is \c false. | |
| 46 | * \return \c true if the document was successfully parsed, \c false if an error occurred. | |
| 47 | */ | |
| 48 | bool parse( const std::string &document, | |
| 49 | Value &root, | |
| 50 | bool collectComments = true ); | |
| 38 | 51 | |
| 39 | /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document. | |
| 40 | * \param document UTF-8 encoded string containing the document to read. | |
| 41 | * \param root [out] Contains the root value of the document if it was | |
| 42 | * successfully parsed. | |
| 43 | * \param collectComments \c true to collect comment and allow writing them back during | |
| 44 | * serialization, \c false to discard comments. | |
| 45 | * This parameter is ignored if Features::allowComments_ | |
| 46 | * is \c false. | |
| 47 | * \return \c true if the document was successfully parsed, \c false if an error occurred. | |
| 48 | */ | |
| 49 | bool parse( const std::string &document, | |
| 50 | Value &root, | |
| 51 | bool collectComments = true ); | |
| 52 | /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document. | |
| 53 | * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the document to read. | |
| 54 | * \param endDoc Pointer on the end of the UTF-8 encoded string of the document to read. | |
| 55 | \ Must be >= beginDoc. | |
| 56 | * \param root [out] Contains the root value of the document if it was | |
| 57 | * successfully parsed. | |
| 58 | * \param collectComments \c true to collect comment and allow writing them back during | |
| 59 | * serialization, \c false to discard comments. | |
| 60 | * This parameter is ignored if Features::allowComments_ | |
| 61 | * is \c false. | |
| 62 | * \return \c true if the document was successfully parsed, \c false if an error occurred. | |
| 63 | */ | |
| 64 | bool parse( const char *beginDoc, const char *endDoc, | |
| 65 | Value &root, | |
| 66 | bool collectComments = true ); | |
| 52 | 67 | |
| 53 | /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document. | |
| 54 | * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the document to read. | |
| 55 | * \param endDoc Pointer on the end of the UTF-8 encoded string of the document to read. | |
| 56 | \ Must be >= beginDoc. | |
| 57 | * \param root [out] Contains the root value of the document if it was | |
| 58 | * successfully parsed. | |
| 59 | * \param collectComments \c true to collect comment and allow writing them back during | |
| 60 | * serialization, \c false to discard comments. | |
| 61 | * This parameter is ignored if Features::allowComments_ | |
| 62 | * is \c false. | |
| 63 | * \return \c true if the document was successfully parsed, \c false if an error occurred. | |
| 64 | */ | |
| 65 | bool parse( const char *beginDoc, const char *endDoc, | |
| 66 | Value &root, | |
| 67 | bool collectComments = true ); | |
| 68 | /// \brief Parse from input stream. | |
| 69 | /// \see Json::operator>>(std::istream&, Json::Value&). | |
| 70 | bool parse( std::istream &is, | |
| 71 | Value &root, | |
| 72 | bool collectComments = true ); | |
| 68 | 73 | |
| 69 | /// \brief Parse from input stream. | |
| 70 | /// \see Json::operator>>(std::istream&, Json::Value&). | |
| 71 | bool parse( std::istream &is, | |
| 72 | Value &root, | |
| 73 | bool collectComments = true ); | |
| 74 | /** \brief Returns a user friendly string that list errors in the parsed document. | |
| 75 | * \return Formatted error message with the list of errors with their location in | |
| 76 | * the parsed document. An empty string is returned if no error occurred | |
| 77 | * during parsing. | |
| 78 | * \deprecated Use getFormattedErrorMessages() instead (typo fix). | |
| 79 | */ | |
| 80 | JSONCPP_DEPRECATED("Use getFormattedErrorMessages instead") | |
| 81 | std::string getFormatedErrorMessages() const; | |
| 74 | 82 | |
| 75 | /** \brief Returns a user friendly string that list errors in the parsed document. | |
| 76 | * \return Formatted error message with the list of errors with their location in | |
| 77 | * the parsed document. An empty string is returned if no error occurred | |
| 78 | * during parsing. | |
| 79 | * \deprecated Use getFormattedErrorMessages() instead (typo fix). | |
| 80 | */ | |
| 81 | JSONCPP_DEPRECATED("Use getFormattedErrorMessages instead") | |
| 82 | std::string getFormatedErrorMessages() const; | |
| 83 | /** \brief Returns a user friendly string that list errors in the parsed document. | |
| 84 | * \return Formatted error message with the list of errors with their location in | |
| 85 | * the parsed document. An empty string is returned if no error occurred | |
| 86 | * during parsing. | |
| 87 | */ | |
| 88 | std::string getFormattedErrorMessages() const; | |
| 83 | 89 | |
| 84 | /** \brief Returns a user friendly string that list errors in the parsed document. | |
| 85 | * \return Formatted error message with the list of errors with their location in | |
| 86 | * the parsed document. An empty string is returned if no error occurred | |
| 87 | * during parsing. | |
| 88 | */ | |
| 89 | std::string getFormattedErrorMessages() const; | |
| 90 | private: | |
| 91 | enum TokenType | |
| 92 | { | |
| 93 | tokenEndOfStream = 0, | |
| 94 | tokenObjectBegin, | |
| 95 | tokenObjectEnd, | |
| 96 | tokenArrayBegin, | |
| 97 | tokenArrayEnd, | |
| 98 | tokenString, | |
| 99 | tokenNumber, | |
| 100 | tokenTrue, | |
| 101 | tokenFalse, | |
| 102 | tokenNull, | |
| 103 | tokenArraySeparator, | |
| 104 | tokenMemberSeparator, | |
| 105 | tokenComment, | |
| 106 | tokenError | |
| 107 | }; | |
| 90 | 108 | |
| 91 | private: | |
| 92 | enum TokenType | |
| 93 | { | |
| 94 | tokenEndOfStream = 0, | |
| 95 | tokenObjectBegin, | |
| 96 | tokenObjectEnd, | |
| 97 | tokenArrayBegin, | |
| 98 | tokenArrayEnd, | |
| 99 | tokenString, | |
| 100 | tokenNumber, | |
| 101 | tokenTrue, | |
| 102 | tokenFalse, | |
| 103 | tokenNull, | |
| 104 | tokenArraySeparator, | |
| 105 | tokenMemberSeparator, | |
| 106 | tokenComment, | |
| 107 | tokenError | |
| 108 | }; | |
| 109 | class Token | |
| 110 | { | |
| 111 | public: | |
| 112 | TokenType type_; | |
| 113 | Location start_; | |
| 114 | Location end_; | |
| 115 | }; | |
| 109 | 116 | |
| 110 | class Token | |
| 111 | { | |
| 112 | public: | |
| 113 | TokenType type_; | |
| 114 | Location start_; | |
| 115 | Location end_; | |
| 116 | }; | |
| 117 | class ErrorInfo | |
| 118 | { | |
| 119 | public: | |
| 120 | Token token_; | |
| 121 | std::string message_; | |
| 122 | Location extra_; | |
| 123 | }; | |
| 117 | 124 | |
| 118 | class ErrorInfo | |
| 119 | { | |
| 120 | public: | |
| 121 | Token token_; | |
| 122 | std::string message_; | |
| 123 | Location extra_; | |
| 124 | }; | |
| 125 | typedef std::deque<ErrorInfo> Errors; | |
| 125 | 126 | |
| 126 | typedef std::deque<ErrorInfo> Errors; | |
| 127 | bool expectToken( TokenType type, Token &token, const char *message ); | |
| 128 | bool readToken( Token &token ); | |
| 129 | void skipSpaces(); | |
| 130 | bool match( Location pattern, | |
| 131 | int patternLength ); | |
| 132 | bool readComment(); | |
| 133 | bool readCStyleComment(); | |
| 134 | bool readCppStyleComment(); | |
| 135 | bool readString(); | |
| 136 | void readNumber(); | |
| 137 | bool readValue(); | |
| 138 | bool readObject( Token &token ); | |
| 139 | bool readArray( Token &token ); | |
| 140 | bool decodeNumber( Token &token ); | |
| 141 | bool decodeString( Token &token ); | |
| 142 | bool decodeString( Token &token, std::string &decoded ); | |
| 143 | bool decodeDouble( Token &token ); | |
| 144 | bool decodeUnicodeCodePoint( Token &token, | |
| 145 | Location ¤t, | |
| 146 | Location end, | |
| 147 | unsigned int &unicode ); | |
| 148 | bool decodeUnicodeEscapeSequence( Token &token, | |
| 149 | Location ¤t, | |
| 150 | Location end, | |
| 151 | unsigned int &unicode ); | |
| 152 | bool addError( const std::string &message, | |
| 153 | Token &token, | |
| 154 | Location extra = 0 ); | |
| 155 | bool recoverFromError( TokenType skipUntilToken ); | |
| 156 | bool addErrorAndRecover( const std::string &message, | |
| 157 | Token &token, | |
| 158 | TokenType skipUntilToken ); | |
| 159 | void skipUntilSpace(); | |
| 160 | Value ¤tValue(); | |
| 161 | Char getNextChar(); | |
| 162 | void getLocationLineAndColumn( Location location, | |
| 163 | int &line, | |
| 164 | int &column ) const; | |
| 165 | std::string getLocationLineAndColumn( Location location ) const; | |
| 166 | void addComment( Location begin, | |
| 167 | Location end, | |
| 168 | CommentPlacement placement ); | |
| 169 | void skipCommentTokens( Token &token ); | |
| 127 | 170 | |
| 128 | bool expectToken( TokenType type, Token &token, const char *message ); | |
| 129 | bool readToken( Token &token ); | |
| 130 | void skipSpaces(); | |
| 131 | bool match( Location pattern, | |
| 132 | int patternLength ); | |
| 133 | bool readComment(); | |
| 134 | bool readCStyleComment(); | |
| 135 | bool readCppStyleComment(); | |
| 136 | bool readString(); | |
| 137 | void readNumber(); | |
| 138 | bool readValue(); | |
| 139 | bool readObject( Token &token ); | |
| 140 | bool readArray( Token &token ); | |
| 141 | bool decodeNumber( Token &token ); | |
| 142 | bool decodeString( Token &token ); | |
| 143 | bool decodeString( Token &token, std::string &decoded ); | |
| 144 | bool decodeDouble( Token &token ); | |
| 145 | bool decodeUnicodeCodePoint( Token &token, | |
| 146 | Location ¤t, | |
| 147 | Location end, | |
| 148 | unsigned int &unicode ); | |
| 149 | bool decodeUnicodeEscapeSequence( Token &token, | |
| 150 | Location ¤t, | |
| 151 | Location end, | |
| 152 | unsigned int &unicode ); | |
| 153 | bool addError( const std::string &message, | |
| 154 | Token &token, | |
| 155 | Location extra = 0 ); | |
| 156 | bool recoverFromError( TokenType skipUntilToken ); | |
| 157 | bool addErrorAndRecover( const std::string &message, | |
| 158 | Token &token, | |
| 159 | TokenType skipUntilToken ); | |
| 160 | void skipUntilSpace(); | |
| 161 | Value ¤tValue(); | |
| 162 | Char getNextChar(); | |
| 163 | void getLocationLineAndColumn( Location location, | |
| 164 | int &line, | |
| 165 | int &column ) const; | |
| 166 | std::string getLocationLineAndColumn( Location location ) const; | |
| 167 | void addComment( Location begin, | |
| 168 | Location end, | |
| 169 | CommentPlacement placement ); | |
| 170 | void skipCommentTokens( Token &token ); | |
| 171 | ||
| 172 | typedef std::stack<Value *> Nodes; | |
| 173 | Nodes nodes_; | |
| 174 | Errors errors_; | |
| 175 | std::string document_; | |
| 176 | Location begin_; | |
| 177 | Location end_; | |
| 178 | Location current_; | |
| 179 | Location lastValueEnd_; | |
| 180 | Value *lastValue_; | |
| 181 | std::string commentsBefore_; | |
| 182 | Features features_; | |
| 183 | bool collectComments_; | |
| 184 | }; | |
| 171 | typedef std::stack<Value *> Nodes; | |
| 172 | Nodes nodes_; | |
| 173 | Errors errors_; | |
| 174 | std::string document_; | |
| 175 | Location begin_; | |
| 176 | Location end_; | |
| 177 | Location current_; | |
| 178 | Location lastValueEnd_; | |
| 179 | Value *lastValue_; | |
| 180 | std::string commentsBefore_; | |
| 181 | Features features_; | |
| 182 | bool collectComments_; | |
| 183 | }; | |
| 185 | 184 | |
| 186 | ||
| 185 | /** \brief Read from 'sin' into 'root'. | |
| 187 | 186 | |
| 188 | ||
| 187 | Always keep comments from the input JSON. | |
| 189 | 188 | |
| 190 | This can be used to read a file into a particular sub-object. | |
| 191 | For example: | |
| 192 | \code | |
| 193 | Json::Value root; | |
| 194 | cin >> root["dir"]["file"]; | |
| 195 | cout << root; | |
| 196 | \endcode | |
| 197 | Result: | |
| 198 | \verbatim | |
| 199 | { | |
| 200 | "dir": { | |
| 201 | "file": { | |
| 202 | // The input stream JSON would be nested here. | |
| 203 | } | |
| 204 | } | |
| 205 | } | |
| 206 | \endverbatim | |
| 207 | \throw std::exception on parse error. | |
| 208 | \see Json::operator<<() | |
| 209 | */ | |
| 210 | std::istream& operator>>( std::istream&, Value& ); | |
| 189 | This can be used to read a file into a particular sub-object. | |
| 190 | For example: | |
| 191 | \code | |
| 192 | Json::Value root; | |
| 193 | cin >> root["dir"]["file"]; | |
| 194 | cout << root; | |
| 195 | \endcode | |
| 196 | Result: | |
| 197 | \verbatim | |
| 198 | { | |
| 199 | "dir": { | |
| 200 | "file": { | |
| 201 | // The input stream JSON would be nested here. | |
| 202 | } | |
| 203 | } | |
| 204 | } | |
| 205 | \endverbatim | |
| 206 | \throw std::exception on parse error. | |
| 207 | \see Json::operator<<() | |
| 208 | */ | |
| 209 | std::istream& operator>>( std::istream&, Value& ); | |
| 211 | 210 | |
| 212 | 211 | } // namespace Json |
| 213 | 212 |
| r25360 | r25361 | |
|---|---|---|
| 71 | 71 | #endif // if !defined(JSONCPP_DEPRECATED) |
| 72 | 72 | |
| 73 | 73 | namespace Json { |
| 74 | typedef int Int; | |
| 75 | typedef unsigned int UInt; | |
| 74 | typedef int Int; | |
| 75 | typedef unsigned int UInt; | |
| 76 | 76 | # if defined(JSON_NO_INT64) |
| 77 | typedef int LargestInt; | |
| 78 | typedef unsigned int LargestUInt; | |
| 77 | typedef int LargestInt; | |
| 78 | typedef unsigned int LargestUInt; | |
| 79 | 79 | # undef JSON_HAS_INT64 |
| 80 | 80 | # else // if defined(JSON_NO_INT64) |
| 81 | ||
| 81 | // For Microsoft Visual use specific types as long long is not supported | |
| 82 | 82 | # if defined(_MSC_VER) // Microsoft Visual Studio |
| 83 | typedef __int64 Int64; | |
| 84 | typedef unsigned __int64 UInt64; | |
| 83 | typedef __int64 Int64; | |
| 84 | typedef unsigned __int64 UInt64; | |
| 85 | 85 | # else // if defined(_MSC_VER) // Other platforms, use long long |
| 86 | typedef long long int Int64; | |
| 87 | typedef unsigned long long int UInt64; | |
| 86 | typedef long long int Int64; | |
| 87 | typedef unsigned long long int UInt64; | |
| 88 | 88 | # endif // if defined(_MSC_VER) |
| 89 | typedef Int64 LargestInt; | |
| 90 | typedef UInt64 LargestUInt; | |
| 89 | typedef Int64 LargestInt; | |
| 90 | typedef UInt64 LargestUInt; | |
| 91 | 91 | # define JSON_HAS_INT64 |
| 92 | 92 | # endif // if defined(JSON_NO_INT64) |
| 93 | 93 | } // end namespace Json |
| r25360 | r25361 | |
|---|---|---|
| 13 | 13 | */ |
| 14 | 14 | |
| 15 | 15 | namespace Json { |
| 16 | ||
| 17 | 16 | /// Converts a unicode code-point to UTF-8. |
| 18 | static inline std::string | |
| 17 | static inline std::string | |
| 19 | 18 | codePointToUTF8(unsigned int cp) |
| 20 | 19 | { |
| 21 | std::string result; | |
| 22 | ||
| 23 | // based on description from http://en.wikipedia.org/wiki/UTF-8 | |
| 20 | std::string result; | |
| 24 | 21 | |
| 25 | if (cp <= 0x7f) | |
| 26 | { | |
| 27 | result.resize(1); | |
| 28 | result[0] = static_cast<char>(cp); | |
| 29 | } | |
| 30 | else if (cp <= 0x7FF) | |
| 31 | { | |
| 32 | result.resize(2); | |
| 33 | result[1] = static_cast<char>(0x80 | (0x3f & cp)); | |
| 34 | result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6))); | |
| 35 | } | |
| 36 | else if (cp <= 0xFFFF) | |
| 37 | { | |
| 38 | result.resize(3); | |
| 39 | result[2] = static_cast<char>(0x80 | (0x3f & cp)); | |
| 40 | result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6))); | |
| 41 | result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12))); | |
| 42 | } | |
| 43 | else if (cp <= 0x10FFFF) | |
| 44 | { | |
| 45 | result.resize(4); | |
| 46 | result[3] = static_cast<char>(0x80 | (0x3f & cp)); | |
| 47 | result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6))); | |
| 48 | result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12))); | |
| 49 | result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18))); | |
| 50 | } | |
| 22 | // based on description from http://en.wikipedia.org/wiki/UTF-8 | |
| 51 | 23 | |
| 52 | return result; | |
| 24 | if (cp <= 0x7f) | |
| 25 | { | |
| 26 | result.resize(1); | |
| 27 | result[0] = static_cast<char>(cp); | |
| 28 | } | |
| 29 | else if (cp <= 0x7FF) | |
| 30 | { | |
| 31 | result.resize(2); | |
| 32 | result[1] = static_cast<char>(0x80 | (0x3f & cp)); | |
| 33 | result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6))); | |
| 34 | } | |
| 35 | else if (cp <= 0xFFFF) | |
| 36 | { | |
| 37 | result.resize(3); | |
| 38 | result[2] = static_cast<char>(0x80 | (0x3f & cp)); | |
| 39 | result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6))); | |
| 40 | result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12))); | |
| 41 | } | |
| 42 | else if (cp <= 0x10FFFF) | |
| 43 | { | |
| 44 | result.resize(4); | |
| 45 | result[3] = static_cast<char>(0x80 | (0x3f & cp)); | |
| 46 | result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6))); | |
| 47 | result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12))); | |
| 48 | result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18))); | |
| 49 | } | |
| 50 | ||
| 51 | return result; | |
| 53 | 52 | } |
| 54 | 53 | |
| 55 | 54 | |
| 56 | 55 | /// Returns true if ch is a control character (in range [0,32[). |
| 57 | static inline bool | |
| 56 | static inline bool | |
| 58 | 57 | isControlCharacter(char ch) |
| 59 | 58 | { |
| 60 | ||
| 59 | return ch > 0 && ch <= 0x1F; | |
| 61 | 60 | } |
| 62 | 61 | |
| 63 | 62 | |
| 64 | enum { | |
| 65 | /// Constant that specify the size of the buffer that must be passed to uintToString. | |
| 66 | uintToStringBufferSize = 3*sizeof(LargestUInt)+1 | |
| 63 | enum { | |
| 64 | /// Constant that specify the size of the buffer that must be passed to uintToString. | |
| 65 | uintToStringBufferSize = 3*sizeof(LargestUInt)+1 | |
| 67 | 66 | }; |
| 68 | 67 | |
| 69 | 68 | // Defines a char buffer for use with uintToString(). |
| r25360 | r25361 | |
| 72 | 71 | |
| 73 | 72 | /** Converts an unsigned integer to string. |
| 74 | 73 | * @param value Unsigned interger to convert to string |
| 75 | * @param current Input/Output string buffer. | |
| 74 | * @param current Input/Output string buffer. | |
| 76 | 75 | * Must have at least uintToStringBufferSize chars free. |
| 77 | 76 | */ |
| 78 | static inline void | |
| 79 | uintToString( LargestUInt value, | |
| 80 | char *¤t ) | |
| 77 | static inline void | |
| 78 | uintToString( LargestUInt value, | |
| 79 | char *¤t ) | |
| 81 | 80 | { |
| 82 | *--current = 0; | |
| 83 | do | |
| 84 | { | |
| 85 | *--current = char(value % 10) + '0'; | |
| 86 | value /= 10; | |
| 87 | } | |
| 88 | while ( value != 0 ); | |
| 81 | *--current = 0; | |
| 82 | do | |
| 83 | { | |
| 84 | *--current = char(value % 10) + '0'; | |
| 85 | value /= 10; | |
| 86 | } | |
| 87 | while ( value != 0 ); | |
| 89 | 88 | } |
| 90 | 89 | |
| 91 | 90 | } // namespace Json { |
| 92 | ||
| 93 | 91 | #endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED |
| r25360 | r25361 | |
|---|---|---|
| 71 | 71 | }; |
| 72 | 72 | |
| 73 | 73 | const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = { |
| 74 | 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, | |
| 75 | 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, | |
| 74 | 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, | |
| 75 | 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, | |
| 76 | 76 | 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, |
| 77 | 77 | 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, |
| 78 | 78 | 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, |
| r25360 | r25361 | |
| 100 | 100 | }; |
| 101 | 101 | |
| 102 | 102 | const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= { |
| 103 | ||
| 103 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, | |
| 104 | 104 | 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, |
| 105 | 105 | 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, |
| 106 | 106 | 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, |
| r25360 | r25361 | |
| 121 | 121 | }; |
| 122 | 122 | |
| 123 | 123 | local const int base_dist[D_CODES] = { |
| 124 | 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, | |
| 125 | 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, | |
| 126 | 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 | |
| 124 | 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, | |
| 125 | 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, | |
| 126 | 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 | |
| 127 | 127 | }; |
| 128 |
| r25360 | r25361 | |
|---|---|---|
| 18 | 18 | |
| 19 | 19 | /* Possible inflate modes between inflate() calls */ |
| 20 | 20 | typedef enum { |
| 21 | HEAD, /* i: waiting for magic header */ | |
| 22 | FLAGS, /* i: waiting for method and flags (gzip) */ | |
| 23 | TIME, /* i: waiting for modification time (gzip) */ | |
| 24 | OS, /* i: waiting for extra flags and operating system (gzip) */ | |
| 25 | EXLEN, /* i: waiting for extra length (gzip) */ | |
| 26 | EXTRA, /* i: waiting for extra bytes (gzip) */ | |
| 27 | NAME, /* i: waiting for end of file name (gzip) */ | |
| 28 | COMMENT, /* i: waiting for end of comment (gzip) */ | |
| 29 | HCRC, /* i: waiting for header crc (gzip) */ | |
| 30 | DICTID, /* i: waiting for dictionary check value */ | |
| 31 | DICT, /* waiting for inflateSetDictionary() call */ | |
| 32 | TYPE, /* i: waiting for type bits, including last-flag bit */ | |
| 33 | TYPEDO, /* i: same, but skip check to exit inflate on new block */ | |
| 34 | STORED, /* i: waiting for stored size (length and complement) */ | |
| 35 | COPY_, /* i/o: same as COPY below, but only first time in */ | |
| 36 | COPY, /* i/o: waiting for input or output to copy stored block */ | |
| 37 | TABLE, /* i: waiting for dynamic block table lengths */ | |
| 38 | LENLENS, /* i: waiting for code length code lengths */ | |
| 39 | CODELENS, /* i: waiting for length/lit and distance code lengths */ | |
| 40 | LEN_, /* i: same as LEN below, but only first time in */ | |
| 41 | LEN, /* i: waiting for length/lit/eob code */ | |
| 42 | LENEXT, /* i: waiting for length extra bits */ | |
| 43 | DIST, /* i: waiting for distance code */ | |
| 44 | DISTEXT, /* i: waiting for distance extra bits */ | |
| 45 | MATCH, /* o: waiting for output space to copy string */ | |
| 46 | LIT, /* o: waiting for output space to write literal */ | |
| 47 | CHECK, /* i: waiting for 32-bit check value */ | |
| 48 | LENGTH, /* i: waiting for 32-bit length (gzip) */ | |
| 49 | DONE, /* finished check, done -- remain here until reset */ | |
| 50 | BAD, /* got a data error -- remain here until reset */ | |
| 51 | MEM, /* got an inflate() memory error -- remain here until reset */ | |
| 52 | SYNC /* looking for synchronization bytes to restart inflate() */ | |
| 21 | HEAD, /* i: waiting for magic header */ | |
| 22 | FLAGS, /* i: waiting for method and flags (gzip) */ | |
| 23 | TIME, /* i: waiting for modification time (gzip) */ | |
| 24 | OS, /* i: waiting for extra flags and operating system (gzip) */ | |
| 25 | EXLEN, /* i: waiting for extra length (gzip) */ | |
| 26 | EXTRA, /* i: waiting for extra bytes (gzip) */ | |
| 27 | NAME, /* i: waiting for end of file name (gzip) */ | |
| 28 | COMMENT, /* i: waiting for end of comment (gzip) */ | |
| 29 | HCRC, /* i: waiting for header crc (gzip) */ | |
| 30 | DICTID, /* i: waiting for dictionary check value */ | |
| 31 | DICT, /* waiting for inflateSetDictionary() call */ | |
| 32 | TYPE, /* i: waiting for type bits, including last-flag bit */ | |
| 33 | TYPEDO, /* i: same, but skip check to exit inflate on new block */ | |
| 34 | STORED, /* i: waiting for stored size (length and complement) */ | |
| 35 | COPY_, /* i/o: same as COPY below, but only first time in */ | |
| 36 | COPY, /* i/o: waiting for input or output to copy stored block */ | |
| 37 | TABLE, /* i: waiting for dynamic block table lengths */ | |
| 38 | LENLENS, /* i: waiting for code length code lengths */ | |
| 39 | CODELENS, /* i: waiting for length/lit and distance code lengths */ | |
| 40 | LEN_, /* i: same as LEN below, but only first time in */ | |
| 41 | LEN, /* i: waiting for length/lit/eob code */ | |
| 42 | LENEXT, /* i: waiting for length extra bits */ | |
| 43 | DIST, /* i: waiting for distance code */ | |
| 44 | DISTEXT, /* i: waiting for distance extra bits */ | |
| 45 | MATCH, /* o: waiting for output space to copy string */ | |
| 46 | LIT, /* o: waiting for output space to write literal */ | |
| 47 | CHECK, /* i: waiting for 32-bit check value */ | |
| 48 | LENGTH, /* i: waiting for 32-bit length (gzip) */ | |
| 49 | DONE, /* finished check, done -- remain here until reset */ | |
| 50 | BAD, /* got a data error -- remain here until reset */ | |
| 51 | MEM, /* got an inflate() memory error -- remain here until reset */ | |
| 52 | SYNC /* looking for synchronization bytes to restart inflate() */ | |
| 53 | 53 | } inflate_mode; |
| 54 | 54 | |
| 55 | 55 | /* |
| r25360 | r25361 | |
| 79 | 79 | |
| 80 | 80 | /* state maintained between inflate() calls. Approximately 10K bytes. */ |
| 81 | 81 | struct inflate_state { |
| 82 | inflate_mode mode; /* current inflate mode */ | |
| 83 | int last; /* true if processing last block */ | |
| 84 | int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ | |
| 85 | int havedict; /* true if dictionary provided */ | |
| 86 | int flags; /* gzip header method and flags (0 if zlib) */ | |
| 87 | unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ | |
| 88 | unsigned long check; /* protected copy of check value */ | |
| 89 | unsigned long total; /* protected copy of output count */ | |
| 90 | gz_headerp head; /* where to save gzip header information */ | |
| 91 | /* sliding window */ | |
| 92 | unsigned wbits; /* log base 2 of requested window size */ | |
| 93 | unsigned wsize; /* window size or zero if not using window */ | |
| 94 | unsigned whave; /* valid bytes in the window */ | |
| 95 | unsigned wnext; /* window write index */ | |
| 96 | unsigned char FAR *window; /* allocated sliding window, if needed */ | |
| 97 | /* bit accumulator */ | |
| 98 | unsigned long hold; /* input bit accumulator */ | |
| 99 | unsigned bits; /* number of bits in "in" */ | |
| 100 | /* for string and stored block copying */ | |
| 101 | unsigned length; /* literal or length of data to copy */ | |
| 102 | unsigned offset; /* distance back to copy string from */ | |
| 103 | /* for table and code decoding */ | |
| 104 | unsigned extra; /* extra bits needed */ | |
| 105 | /* fixed and dynamic code tables */ | |
| 106 | code const FAR *lencode; /* starting table for length/literal codes */ | |
| 107 | code const FAR *distcode; /* starting table for distance codes */ | |
| 108 | unsigned lenbits; /* index bits for lencode */ | |
| 109 | unsigned distbits; /* index bits for distcode */ | |
| 110 | /* dynamic table building */ | |
| 111 | unsigned ncode; /* number of code length code lengths */ | |
| 112 | unsigned nlen; /* number of length code lengths */ | |
| 113 | unsigned ndist; /* number of distance code lengths */ | |
| 114 | unsigned have; /* number of code lengths in lens[] */ | |
| 115 | code FAR *next; /* next available space in codes[] */ | |
| 116 | unsigned short lens[320]; /* temporary storage for code lengths */ | |
| 117 | unsigned short work[288]; /* work area for code table building */ | |
| 118 | code codes[ENOUGH]; /* space for code tables */ | |
| 119 | int sane; /* if false, allow invalid distance too far */ | |
| 120 | int back; /* bits back of last unprocessed length/lit */ | |
| 121 | unsigned was; /* initial length of match */ | |
| 82 | inflate_mode mode; /* current inflate mode */ | |
| 83 | int last; /* true if processing last block */ | |
| 84 | int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ | |
| 85 | int havedict; /* true if dictionary provided */ | |
| 86 | int flags; /* gzip header method and flags (0 if zlib) */ | |
| 87 | unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ | |
| 88 | unsigned long check; /* protected copy of check value */ | |
| 89 | unsigned long total; /* protected copy of output count */ | |
| 90 | gz_headerp head; /* where to save gzip header information */ | |
| 91 | /* sliding window */ | |
| 92 | unsigned wbits; /* log base 2 of requested window size */ | |
| 93 | unsigned wsize; /* window size or zero if not using window */ | |
| 94 | unsigned whave; /* valid bytes in the window */ | |
| 95 | unsigned wnext; /* window write index */ | |
| 96 | unsigned char FAR *window; /* allocated sliding window, if needed */ | |
| 97 | /* bit accumulator */ | |
| 98 | unsigned long hold; /* input bit accumulator */ | |
| 99 | unsigned bits; /* number of bits in "in" */ | |
| 100 | /* for string and stored block copying */ | |
| 101 | unsigned length; /* literal or length of data to copy */ | |
| 102 | unsigned offset; /* distance back to copy string from */ | |
| 103 | /* for table and code decoding */ | |
| 104 | unsigned extra; /* extra bits needed */ | |
| 105 | /* fixed and dynamic code tables */ | |
| 106 | code const FAR *lencode; /* starting table for length/literal codes */ | |
| 107 | code const FAR *distcode; /* starting table for distance codes */ | |
| 108 | unsigned lenbits; /* index bits for lencode */ | |
| 109 | unsigned distbits; /* index bits for distcode */ | |
| 110 | /* dynamic table building */ | |
| 111 | unsigned ncode; /* number of code length code lengths */ | |
| 112 | unsigned nlen; /* number of length code lengths */ | |
| 113 | unsigned ndist; /* number of distance code lengths */ | |
| 114 | unsigned have; /* number of code lengths in lens[] */ | |
| 115 | code FAR *next; /* next available space in codes[] */ | |
| 116 | unsigned short lens[320]; /* temporary storage for code lengths */ | |
| 117 | unsigned short work[288]; /* work area for code table building */ | |
| 118 | code codes[ENOUGH]; /* space for code tables */ | |
| 119 | int sane; /* if false, allow invalid distance too far */ | |
| 120 | int back; /* bits back of last unprocessed length/lit */ | |
| 121 | unsigned was; /* initial length of match */ | |
| 122 | 122 | }; |
| r25360 | r25361 | |
|---|---|---|
| 110 | 110 | |
| 111 | 111 | /* gz* functions always use library allocation functions */ |
| 112 | 112 | #ifndef STDC |
| 113 | extern voidp malloc OF((uInt size)); | |
| 114 | extern void free OF((voidpf ptr)); | |
| 113 | extern voidp malloc OF((uInt size)); | |
| 114 | extern void free OF((voidpf ptr)); | |
| 115 | 115 | #endif |
| 116 | 116 | |
| 117 | 117 | /* get errno and strerror definition */ |
| r25360 | r25361 | |
| 129 | 129 | |
| 130 | 130 | /* provide prototypes for these when building zlib without LFS */ |
| 131 | 131 | #if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 |
| 132 | ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); | |
| 133 | ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); | |
| 134 | ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); | |
| 135 | ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); | |
| 132 | ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); | |
| 133 | ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); | |
| 134 | ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); | |
| 135 | ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); | |
| 136 | 136 | #endif |
| 137 | 137 | |
| 138 | 138 | /* default memLevel */ |
| r25360 | r25361 | |
| 159 | 159 | |
| 160 | 160 | /* internal gzip file state data structure */ |
| 161 | 161 | typedef struct { |
| 162 | /* exposed contents for gzgetc() macro */ | |
| 163 | struct gzFile_s x; /* "x" for exposed */ | |
| 164 | /* x.have: number of bytes available at x.next */ | |
| 165 | /* x.next: next output data to deliver or write */ | |
| 166 | /* x.pos: current position in uncompressed data */ | |
| 167 | /* used for both reading and writing */ | |
| 168 | int mode; /* see gzip modes above */ | |
| 169 | int fd; /* file descriptor */ | |
| 170 | char *path; /* path or fd for error messages */ | |
| 171 | unsigned size; /* buffer size, zero if not allocated yet */ | |
| 172 | unsigned want; /* requested buffer size, default is GZBUFSIZE */ | |
| 173 | unsigned char *in; /* input buffer */ | |
| 174 | unsigned char *out; /* output buffer (double-sized when reading) */ | |
| 175 | int direct; /* 0 if processing gzip, 1 if transparent */ | |
| 176 | /* just for reading */ | |
| 177 | int how; /* 0: get header, 1: copy, 2: decompress */ | |
| 178 | z_off64_t start; /* where the gzip data started, for rewinding */ | |
| 179 | int eof; /* true if end of input file reached */ | |
| 180 | int past; /* true if read requested past end */ | |
| 181 | /* just for writing */ | |
| 182 | int level; /* compression level */ | |
| 183 | int strategy; /* compression strategy */ | |
| 184 | /* seek request */ | |
| 185 | z_off64_t skip; /* amount to skip (already rewound if backwards) */ | |
| 186 | int seek; /* true if seek request pending */ | |
| 187 | /* error information */ | |
| 188 | int err; /* error code */ | |
| 189 | char *msg; /* error message */ | |
| 190 | /* zlib inflate or deflate stream */ | |
| 191 | z_stream strm; /* stream structure in-place (not a pointer) */ | |
| 162 | /* exposed contents for gzgetc() macro */ | |
| 163 | struct gzFile_s x; /* "x" for exposed */ | |
| 164 | /* x.have: number of bytes available at x.next */ | |
| 165 | /* x.next: next output data to deliver or write */ | |
| 166 | /* x.pos: current position in uncompressed data */ | |
| 167 | /* used for both reading and writing */ | |
| 168 | int mode; /* see gzip modes above */ | |
| 169 | int fd; /* file descriptor */ | |
| 170 | char *path; /* path or fd for error messages */ | |
| 171 | unsigned size; /* buffer size, zero if not allocated yet */ | |
| 172 | unsigned want; /* requested buffer size, default is GZBUFSIZE */ | |
| 173 | unsigned char *in; /* input buffer */ | |
| 174 | unsigned char *out; /* output buffer (double-sized when reading) */ | |
| 175 | int direct; /* 0 if processing gzip, 1 if transparent */ | |
| 176 | /* just for reading */ | |
| 177 | int how; /* 0: get header, 1: copy, 2: decompress */ | |
| 178 | z_off64_t start; /* where the gzip data started, for rewinding */ | |
| 179 | int eof; /* true if end of input file reached */ | |
| 180 | int past; /* true if read requested past end */ | |
| 181 | /* just for writing */ | |
| 182 | int level; /* compression level */ | |
| 183 | int strategy; /* compression strategy */ | |
| 184 | /* seek request */ | |
| 185 | z_off64_t skip; /* amount to skip (already rewound if backwards) */ | |
| 186 | int seek; /* true if seek request pending */ | |
| 187 | /* error information */ | |
| 188 | int err; /* error code */ | |
| 189 | char *msg; /* error message */ | |
| 190 | /* zlib inflate or deflate stream */ | |
| 191 | z_stream strm; /* stream structure in-place (not a pointer) */ | |
| 192 | 192 | } gz_state; |
| 193 | 193 | typedef gz_state FAR *gz_statep; |
| 194 | 194 |
| r25360 | r25361 | |
|---|---|---|
| 68 | 68 | z_streamp strm; |
| 69 | 69 | unsigned start; /* inflate()'s starting value for strm->avail_out */ |
| 70 | 70 | { |
| 71 | struct inflate_state FAR *state; | |
| 72 | z_const unsigned char FAR *in; /* local strm->next_in */ | |
| 73 | z_const unsigned char FAR *last; /* have enough input while in < last */ | |
| 74 | unsigned char FAR *out; /* local strm->next_out */ | |
| 75 | unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ | |
| 76 | unsigned char FAR *end; /* while out < end, enough space available */ | |
| 71 | struct inflate_state FAR *state; | |
| 72 | z_const unsigned char FAR *in; /* local strm->next_in */ | |
| 73 | z_const unsigned char FAR *last; /* have enough input while in < last */ | |
| 74 | unsigned char FAR *out; /* local strm->next_out */ | |
| 75 | unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ | |
| 76 | unsigned char FAR *end; /* while out < end, enough space available */ | |
| 77 | 77 | #ifdef INFLATE_STRICT |
| 78 | ||
| 78 | unsigned dmax; /* maximum distance from zlib header */ | |
| 79 | 79 | #endif |
| 80 | unsigned wsize; /* window size or zero if not using window */ | |
| 81 | unsigned whave; /* valid bytes in the window */ | |
| 82 | unsigned wnext; /* window write index */ | |
| 83 | unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ | |
| 84 | unsigned long hold; /* local strm->hold */ | |
| 85 | unsigned bits; /* local strm->bits */ | |
| 86 | code const FAR *lcode; /* local strm->lencode */ | |
| 87 | code const FAR *dcode; /* local strm->distcode */ | |
| 88 | unsigned lmask; /* mask for first level of length codes */ | |
| 89 | unsigned dmask; /* mask for first level of distance codes */ | |
| 90 | code here; /* retrieved table entry */ | |
| 91 | unsigned op; /* code bits, operation, extra bits, or */ | |
| 92 | /* window position, window bytes to copy */ | |
| 93 | unsigned len; /* match length, unused bytes */ | |
| 94 | unsigned dist; /* match distance */ | |
| 95 | unsigned char FAR *from; /* where to copy match from */ | |
| 80 | unsigned wsize; /* window size or zero if not using window */ | |
| 81 | unsigned whave; /* valid bytes in the window */ | |
| 82 | unsigned wnext; /* window write index */ | |
| 83 | unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ | |
| 84 | unsigned long hold; /* local strm->hold */ | |
| 85 | unsigned bits; /* local strm->bits */ | |
| 86 | code const FAR *lcode; /* local strm->lencode */ | |
| 87 | code const FAR *dcode; /* local strm->distcode */ | |
| 88 | unsigned lmask; /* mask for first level of length codes */ | |
| 89 | unsigned dmask; /* mask for first level of distance codes */ | |
| 90 | code here; /* retrieved table entry */ | |
| 91 | unsigned op; /* code bits, operation, extra bits, or */ | |
| 92 | /* window position, window bytes to copy */ | |
| 93 | unsigned len; /* match length, unused bytes */ | |
| 94 | unsigned dist; /* match distance */ | |
| 95 | unsigned char FAR *from; /* where to copy match from */ | |
| 96 | 96 | |
| 97 | /* copy state to local variables */ | |
| 98 | state = (struct inflate_state FAR *)strm->state; | |
| 99 | in = strm->next_in - OFF; | |
| 100 | last = in + (strm->avail_in - 5); | |
| 101 | out = strm->next_out - OFF; | |
| 102 | beg = out - (start - strm->avail_out); | |
| 103 | end = out + (strm->avail_out - 257); | |
| 97 | /* copy state to local variables */ | |
| 98 | state = (struct inflate_state FAR *)strm->state; | |
| 99 | in = strm->next_in - OFF; | |
| 100 | last = in + (strm->avail_in - 5); | |
| 101 | out = strm->next_out - OFF; | |
| 102 | beg = out - (start - strm->avail_out); | |
| 103 | end = out + (strm->avail_out - 257); | |
| 104 | 104 | #ifdef INFLATE_STRICT |
| 105 | ||
| 105 | dmax = state->dmax; | |
| 106 | 106 | #endif |
| 107 | wsize = state->wsize; | |
| 108 | whave = state->whave; | |
| 109 | wnext = state->wnext; | |
| 110 | window = state->window; | |
| 111 | hold = state->hold; | |
| 112 | bits = state->bits; | |
| 113 | lcode = state->lencode; | |
| 114 | dcode = state->distcode; | |
| 115 | lmask = (1U << state->lenbits) - 1; | |
| 116 | dmask = (1U << state->distbits) - 1; | |
| 107 | wsize = state->wsize; | |
| 108 | whave = state->whave; | |
| 109 | wnext = state->wnext; | |
| 110 | window = state->window; | |
| 111 | hold = state->hold; | |
| 112 | bits = state->bits; | |
| 113 | lcode = state->lencode; | |
| 114 | dcode = state->distcode; | |
| 115 | lmask = (1U << state->lenbits) - 1; | |
| 116 | dmask = (1U << state->distbits) - 1; | |
| 117 | 117 | |
| 118 | /* decode literals and length/distances until end-of-block or not enough | |
| 119 | input data or output space */ | |
| 120 | do { | |
| 121 | if (bits < 15) { | |
| 122 | hold += (unsigned long)(PUP(in)) << bits; | |
| 123 | bits += 8; | |
| 124 | hold += (unsigned long)(PUP(in)) << bits; | |
| 125 | bits += 8; | |
| 126 | } | |
| 127 | here = lcode[hold & lmask]; | |
| 128 | dolen: | |
| 129 | op = (unsigned)(here.bits); | |
| 130 | hold >>= op; | |
| 131 | bits -= op; | |
| 132 | op = (unsigned)(here.op); | |
| 133 | if (op == 0) { /* literal */ | |
| 134 | Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? | |
| 135 | "inflate: literal '%c'\n" : | |
| 136 | "inflate: literal 0x%02x\n", here.val)); | |
| 137 | PUP(out) = (unsigned char)(here.val); | |
| 138 | } | |
| 139 | else if (op & 16) { /* length base */ | |
| 140 | len = (unsigned)(here.val); | |
| 141 | op &= 15; /* number of extra bits */ | |
| 142 | if (op) { | |
| 143 | if (bits < op) { | |
| 144 | hold += (unsigned long)(PUP(in)) << bits; | |
| 145 | bits += 8; | |
| 146 | } | |
| 147 | len += (unsigned)hold & ((1U << op) - 1); | |
| 148 | hold >>= op; | |
| 149 | bits -= op; | |
| 150 | } | |
| 151 | Tracevv((stderr, "inflate: length %u\n", len)); | |
| 152 | if (bits < 15) { | |
| 153 | hold += (unsigned long)(PUP(in)) << bits; | |
| 154 | bits += 8; | |
| 155 | hold += (unsigned long)(PUP(in)) << bits; | |
| 156 | bits += 8; | |
| 157 | } | |
| 158 | here = dcode[hold & dmask]; | |
| 159 | dodist: | |
| 160 | op = (unsigned)(here.bits); | |
| 161 | hold >>= op; | |
| 162 | bits -= op; | |
| 163 | op = (unsigned)(here.op); | |
| 164 | if (op & 16) { /* distance base */ | |
| 165 | dist = (unsigned)(here.val); | |
| 166 | op &= 15; /* number of extra bits */ | |
| 167 | if (bits < op) { | |
| 168 | hold += (unsigned long)(PUP(in)) << bits; | |
| 169 | bits += 8; | |
| 170 | if (bits < op) { | |
| 171 | hold += (unsigned long)(PUP(in)) << bits; | |
| 172 | bits += 8; | |
| 173 | } | |
| 174 | } | |
| 175 | dist += (unsigned)hold & ((1U << op) - 1); | |
| 118 | /* decode literals and length/distances until end-of-block or not enough | |
| 119 | input data or output space */ | |
| 120 | do { | |
| 121 | if (bits < 15) { | |
| 122 | hold += (unsigned long)(PUP(in)) << bits; | |
| 123 | bits += 8; | |
| 124 | hold += (unsigned long)(PUP(in)) << bits; | |
| 125 | bits += 8; | |
| 126 | } | |
| 127 | here = lcode[hold & lmask]; | |
| 128 | dolen: | |
| 129 | op = (unsigned)(here.bits); | |
| 130 | hold >>= op; | |
| 131 | bits -= op; | |
| 132 | op = (unsigned)(here.op); | |
| 133 | if (op == 0) { /* literal */ | |
| 134 | Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? | |
| 135 | "inflate: literal '%c'\n" : | |
| 136 | "inflate: literal 0x%02x\n", here.val)); | |
| 137 | PUP(out) = (unsigned char)(here.val); | |
| 138 | } | |
| 139 | else if (op & 16) { /* length base */ | |
| 140 | len = (unsigned)(here.val); | |
| 141 | op &= 15; /* number of extra bits */ | |
| 142 | if (op) { | |
| 143 | if (bits < op) { | |
| 144 | hold += (unsigned long)(PUP(in)) << bits; | |
| 145 | bits += 8; | |
| 146 | } | |
| 147 | len += (unsigned)hold & ((1U << op) - 1); | |
| 148 | hold >>= op; | |
| 149 | bits -= op; | |
| 150 | } | |
| 151 | Tracevv((stderr, "inflate: length %u\n", len)); | |
| 152 | if (bits < 15) { | |
| 153 | hold += (unsigned long)(PUP(in)) << bits; | |
| 154 | bits += 8; | |
| 155 | hold += (unsigned long)(PUP(in)) << bits; | |
| 156 | bits += 8; | |
| 157 | } | |
| 158 | here = dcode[hold & dmask]; | |
| 159 | dodist: | |
| 160 | op = (unsigned)(here.bits); | |
| 161 | hold >>= op; | |
| 162 | bits -= op; | |
| 163 | op = (unsigned)(here.op); | |
| 164 | if (op & 16) { /* distance base */ | |
| 165 | dist = (unsigned)(here.val); | |
| 166 | op &= 15; /* number of extra bits */ | |
| 167 | if (bits < op) { | |
| 168 | hold += (unsigned long)(PUP(in)) << bits; | |
| 169 | bits += 8; | |
| 170 | if (bits < op) { | |
| 171 | hold += (unsigned long)(PUP(in)) << bits; | |
| 172 | bits += 8; | |
| 173 | } | |
| 174 | } | |
| 175 | dist += (unsigned)hold & ((1U << op) - 1); | |
| 176 | 176 | #ifdef INFLATE_STRICT |
| 177 | if (dist > dmax) { | |
| 178 | strm->msg = (char *)"invalid distance too far back"; | |
| 179 | state->mode = BAD; | |
| 180 | break; | |
| 181 | } | |
| 177 | if (dist > dmax) { | |
| 178 | strm->msg = (char *)"invalid distance too far back"; | |
| 179 | state->mode = BAD; | |
| 180 | break; | |
| 181 | } | |
| 182 | 182 | #endif |
| 183 | hold >>= op; | |
| 184 | bits -= op; | |
| 185 | Tracevv((stderr, "inflate: distance %u\n", dist)); | |
| 186 | op = (unsigned)(out - beg); /* max distance in output */ | |
| 187 | if (dist > op) { /* see if copy from window */ | |
| 188 | op = dist - op; /* distance back in window */ | |
| 189 | if (op > whave) { | |
| 190 | if (state->sane) { | |
| 191 | strm->msg = | |
| 192 | (char *)"invalid distance too far back"; | |
| 193 | state->mode = BAD; | |
| 194 | break; | |
| 195 | } | |
| 183 | hold >>= op; | |
| 184 | bits -= op; | |
| 185 | Tracevv((stderr, "inflate: distance %u\n", dist)); | |
| 186 | op = (unsigned)(out - beg); /* max distance in output */ | |
| 187 | if (dist > op) { /* see if copy from window */ | |
| 188 | op = dist - op; /* distance back in window */ | |
| 189 | if (op > whave) { | |
| 190 | if (state->sane) { | |
| 191 | strm->msg = | |
| 192 | (char *)"invalid distance too far back"; | |
| 193 | state->mode = BAD; | |
| 194 | break; | |
| 195 | } | |
| 196 | 196 | #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR |
| 197 | if (len <= op - whave) { | |
| 198 | do { | |
| 199 | PUP(out) = 0; | |
| 200 | } while (--len); | |
| 201 | continue; | |
| 202 | } | |
| 203 | len -= op - whave; | |
| 204 | do { | |
| 205 | PUP(out) = 0; | |
| 206 | } while (--op > whave); | |
| 207 | if (op == 0) { | |
| 208 | from = out - dist; | |
| 209 | do { | |
| 210 | PUP(out) = PUP(from); | |
| 211 | } while (--len); | |
| 212 | continue; | |
| 213 | } | |
| 197 | if (len <= op - whave) { | |
| 198 | do { | |
| 199 | PUP(out) = 0; | |
| 200 | } while (--len); | |
| 201 | continue; | |
| 202 | } | |
| 203 | len -= op - whave; | |
| 204 | do { | |
| 205 | PUP(out) = 0; | |
| 206 | } while (--op > whave); | |
| 207 | if (op == 0) { | |
| 208 | from = out - dist; | |
| 209 | do { | |
| 210 | PUP(out) = PUP(from); | |
| 211 | } while (--len); | |
| 212 | continue; | |
| 213 | } | |
| 214 | 214 | #endif |
| 215 | } | |
| 216 | from = window - OFF; | |
| 217 | if (wnext == 0) { /* very common case */ | |
| 218 | from += wsize - op; | |
| 219 | if (op < len) { /* some from window */ | |
| 220 | len -= op; | |
| 221 | do { | |
| 222 | PUP(out) = PUP(from); | |
| 223 | } while (--op); | |
| 224 | from = out - dist; /* rest from output */ | |
| 225 | } | |
| 226 | } | |
| 227 | else if (wnext < op) { /* wrap around window */ | |
| 228 | from += wsize + wnext - op; | |
| 229 | op -= wnext; | |
| 230 | if (op < len) { /* some from end of window */ | |
| 231 | len -= op; | |
| 232 | do { | |
| 233 | PUP(out) = PUP(from); | |
| 234 | } while (--op); | |
| 235 | from = window - OFF; | |
| 236 | if (wnext < len) { /* some from start of window */ | |
| 237 | op = wnext; | |
| 238 | len -= op; | |
| 239 | do { | |
| 240 | PUP(out) = PUP(from); | |
| 241 | } while (--op); | |
| 242 | from = out - dist; /* rest from output */ | |
| 243 | } | |
| 244 | } | |
| 245 | } | |
| 246 | else { /* contiguous in window */ | |
| 247 | from += wnext - op; | |
| 248 | if (op < len) { /* some from window */ | |
| 249 | len -= op; | |
| 250 | do { | |
| 251 | PUP(out) = PUP(from); | |
| 252 | } while (--op); | |
| 253 | from = out - dist; /* rest from output */ | |
| 254 | } | |
| 255 | } | |
| 256 | while (len > 2) { | |
| 257 | PUP(out) = PUP(from); | |
| 258 | PUP(out) = PUP(from); | |
| 259 | PUP(out) = PUP(from); | |
| 260 | len -= 3; | |
| 261 | } | |
| 262 | if (len) { | |
| 263 | PUP(out) = PUP(from); | |
| 264 | if (len > 1) | |
| 265 | PUP(out) = PUP(from); | |
| 266 | } | |
| 267 | } | |
| 268 | else { | |
| 269 | from = out - dist; /* copy direct from output */ | |
| 270 | do { /* minimum length is three */ | |
| 271 | PUP(out) = PUP(from); | |
| 272 | PUP(out) = PUP(from); | |
| 273 | PUP(out) = PUP(from); | |
| 274 | len -= 3; | |
| 275 | } while (len > 2); | |
| 276 | if (len) { | |
| 277 | PUP(out) = PUP(from); | |
| 278 | if (len > 1) | |
| 279 | PUP(out) = PUP(from); | |
| 280 | } | |
| 281 | } | |
| 282 | } | |
| 283 | else if ((op & 64) == 0) { /* 2nd level distance code */ | |
| 284 | here = dcode[here.val + (hold & ((1U << op) - 1))]; | |
| 285 | goto dodist; | |
| 286 | } | |
| 287 | else { | |
| 288 | strm->msg = (char *)"invalid distance code"; | |
| 289 | state->mode = BAD; | |
| 290 | break; | |
| 291 | } | |
| 292 | } | |
| 293 | else if ((op & 64) == 0) { /* 2nd level length code */ | |
| 294 | here = lcode[here.val + (hold & ((1U << op) - 1))]; | |
| 295 | goto dolen; | |
| 296 | } | |
| 297 | else if (op & 32) { /* end-of-block */ | |
| 298 | Tracevv((stderr, "inflate: end of block\n")); | |
| 299 | state->mode = TYPE; | |
| 300 | break; | |
| 301 | } | |
| 302 | else { | |
| 303 | strm->msg = (char *)"invalid literal/length code"; | |
| 304 | state->mode = BAD; | |
| 305 | break; | |
| 306 | } | |
| 307 | } while (in < last && out < end); | |
| 215 | } | |
| 216 | from = window - OFF; | |
| 217 | if (wnext == 0) { /* very common case */ | |
| 218 | from += wsize - op; | |
| 219 | if (op < len) { /* some from window */ | |
| 220 | len -= op; | |
| 221 | do { | |
| 222 | PUP(out) = PUP(from); | |
| 223 | } while (--op); | |
| 224 | from = out - dist; /* rest from output */ | |
| 225 | } | |
| 226 | } | |
| 227 | else if (wnext < op) { /* wrap around window */ | |
| 228 | from += wsize + wnext - op; | |
| 229 | op -= wnext; | |
| 230 | if (op < len) { /* some from end of window */ | |
| 231 | len -= op; | |
| 232 | do { | |
| 233 | PUP(out) = PUP(from); | |
| 234 | } while (--op); | |
| 235 | from = window - OFF; | |
| 236 | if (wnext < len) { /* some from start of window */ | |
| 237 | op = wnext; | |
| 238 | len -= op; | |
| 239 | do { | |
| 240 | PUP(out) = PUP(from); | |
| 241 | } while (--op); | |
| 242 | from = out - dist; /* rest from output */ | |
| 243 | } | |
| 244 | } | |
| 245 | } | |
| 246 | else { /* contiguous in window */ | |
| 247 | from += wnext - op; | |
| 248 | if (op < len) { /* some from window */ | |
| 249 | len -= op; | |
| 250 | do { | |
| 251 | PUP(out) = PUP(from); | |
| 252 | } while (--op); | |
| 253 | from = out - dist; /* rest from output */ | |
| 254 | } | |
| 255 | } | |
| 256 | while (len > 2) { | |
| 257 | PUP(out) = PUP(from); | |
| 258 | PUP(out) = PUP(from); | |
| 259 | PUP(out) = PUP(from); | |
| 260 | len -= 3; | |
| 261 | } | |
| 262 | if (len) { | |
| 263 | PUP(out) = PUP(from); | |
| 264 | if (len > 1) | |
| 265 | PUP(out) = PUP(from); | |
| 266 | } | |
| 267 | } | |
| 268 | else { | |
| 269 | from = out - dist; /* copy direct from output */ | |
| 270 | do { /* minimum length is three */ | |
| 271 | PUP(out) = PUP(from); | |
| 272 | PUP(out) = PUP(from); | |
| 273 | PUP(out) = PUP(from); | |
| 274 | len -= 3; | |
| 275 | } while (len > 2); | |
| 276 | if (len) { | |
| 277 | PUP(out) = PUP(from); | |
| 278 | if (len > 1) | |
| 279 | PUP(out) = PUP(from); | |
| 280 | } | |
| 281 | } | |
| 282 | } | |
| 283 | else if ((op & 64) == 0) { /* 2nd level distance code */ | |
| 284 | here = dcode[here.val + (hold & ((1U << op) - 1))]; | |
| 285 | goto dodist; | |
| 286 | } | |
| 287 | else { | |
| 288 | strm->msg = (char *)"invalid distance code"; | |
| 289 | state->mode = BAD; | |
| 290 | break; | |
| 291 | } | |
| 292 | } | |
| 293 | else if ((op & 64) == 0) { /* 2nd level length code */ | |
| 294 | here = lcode[here.val + (hold & ((1U << op) - 1))]; | |
| 295 | goto dolen; | |
| 296 | } | |
| 297 | else if (op & 32) { /* end-of-block */ | |
| 298 | Tracevv((stderr, "inflate: end of block\n")); | |
| 299 | state->mode = TYPE; | |
| 300 | break; | |
| 301 | } | |
| 302 | else { | |
| 303 | strm->msg = (char *)"invalid literal/length code"; | |
| 304 | state->mode = BAD; | |
| 305 | break; | |
| 306 | } | |
| 307 | } while (in < last && out < end); | |
| 308 | 308 | |
| 309 | /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ | |
| 310 | len = bits >> 3; | |
| 311 | in -= len; | |
| 312 | bits -= len << 3; | |
| 313 | hold &= (1U << bits) - 1; | |
| 309 | /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ | |
| 310 | len = bits >> 3; | |
| 311 | in -= len; | |
| 312 | bits -= len << 3; | |
| 313 | hold &= (1U << bits) - 1; | |
| 314 | 314 | |
| 315 | /* update state and return */ | |
| 316 | strm->next_in = in + OFF; | |
| 317 | strm->next_out = out + OFF; | |
| 318 | strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); | |
| 319 | strm->avail_out = (unsigned)(out < end ? | |
| 320 | 257 + (end - out) : 257 - (out - end)); | |
| 321 | state->hold = hold; | |
| 322 | state->bits = bits; | |
| 323 | return; | |
| 315 | /* update state and return */ | |
| 316 | strm->next_in = in + OFF; | |
| 317 | strm->next_out = out + OFF; | |
| 318 | strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); | |
| 319 | strm->avail_out = (unsigned)(out < end ? | |
| 320 | 257 + (end - out) : 257 - (out - end)); | |
| 321 | state->hold = hold; | |
| 322 | state->bits = bits; | |
| 323 | return; | |
| 324 | 324 | } |
| 325 | 325 | |
| 326 | 326 | /* |
| r25360 | r25361 | |
|---|---|---|
| 13 | 13 | /* Initialize state for writing a gzip file. Mark initialization by setting |
| 14 | 14 | state->size to non-zero. Return -1 on failure or 0 on success. */ |
| 15 | 15 | local int gz_init(state) |
| 16 | ||
| 16 | gz_statep state; | |
| 17 | 17 | { |
| 18 | int ret; | |
| 19 | z_streamp strm = &(state->strm); | |
| 18 | int ret; | |
| 19 | z_streamp strm = &(state->strm); | |
| 20 | 20 | |
| 21 | /* allocate input buffer */ | |
| 22 | state->in = (unsigned char *)malloc(state->want); | |
| 23 | if (state->in == NULL) { | |
| 24 | gz_error(state, Z_MEM_ERROR, "out of memory"); | |
| 25 | return -1; | |
| 26 | } | |
| 21 | /* allocate input buffer */ | |
| 22 | state->in = (unsigned char *)malloc(state->want); | |
| 23 | if (state->in == NULL) { | |
| 24 | gz_error(state, Z_MEM_ERROR, "out of memory"); | |
| 25 | return -1; | |
| 26 | } | |
| 27 | 27 | |
| 28 | /* only need output buffer and deflate state if compressing */ | |
| 29 | if (!state->direct) { | |
| 30 | /* allocate output buffer */ | |
| 31 | state->out = (unsigned char *)malloc(state->want); | |
| 32 | if (state->out == NULL) { | |
| 33 | free(state->in); | |
| 34 | gz_error(state, Z_MEM_ERROR, "out of memory"); | |
| 35 | return -1; | |
| 36 | } | |
| 28 | /* only need output buffer and deflate state if compressing */ | |
| 29 | if (!state->direct) { | |
| 30 | /* allocate output buffer */ | |
| 31 | state->out = (unsigned char *)malloc(state->want); | |
| 32 | if (state->out == NULL) { | |
| 33 | free(state->in); | |
| 34 | gz_error(state, Z_MEM_ERROR, "out of memory"); | |
| 35 | return -1; | |
| 36 | } | |
| 37 | 37 | |
| 38 | /* allocate deflate memory, set up for gzip compression */ | |
| 39 | strm->zalloc = Z_NULL; | |
| 40 | strm->zfree = Z_NULL; | |
| 41 | strm->opaque = Z_NULL; | |
| 42 | ret = deflateInit2(strm, state->level, Z_DEFLATED, | |
| 43 | MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy); | |
| 44 | if (ret != Z_OK) { | |
| 45 | free(state->out); | |
| 46 | free(state->in); | |
| 47 | gz_error(state, Z_MEM_ERROR, "out of memory"); | |
| 48 | return -1; | |
| 49 | } | |
| 50 | } | |
| 38 | /* allocate deflate memory, set up for gzip compression */ | |
| 39 | strm->zalloc = Z_NULL; | |
| 40 | strm->zfree = Z_NULL; | |
| 41 | strm->opaque = Z_NULL; | |
| 42 | ret = deflateInit2(strm, state->level, Z_DEFLATED, | |
| 43 | MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy); | |
| 44 | if (ret != Z_OK) { | |
| 45 | free(state->out); | |
| 46 | free(state->in); | |
| 47 | gz_error(state, Z_MEM_ERROR, "out of memory"); | |
| 48 | return -1; | |
| 49 | } | |
| 50 | } | |
| 51 | 51 | |
| 52 | /* mark state as initialized */ | |
| 53 | state->size = state->want; | |
| 52 | /* mark state as initialized */ | |
| 53 | state->size = state->want; | |
| 54 | 54 | |
| 55 | /* initialize write buffer if compressing */ | |
| 56 | if (!state->direct) { | |
| 57 | strm->avail_out = state->size; | |
| 58 | strm->next_out = state->out; | |
| 59 | state->x.next = strm->next_out; | |
| 60 | } | |
| 61 | return 0; | |
| 55 | /* initialize write buffer if compressing */ | |
| 56 | if (!state->direct) { | |
| 57 | strm->avail_out = state->size; | |
| 58 | strm->next_out = state->out; | |
| 59 | state->x.next = strm->next_out; | |
| 60 | } | |
| 61 | return 0; | |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | 64 | /* Compress whatever is at avail_in and next_in and write to the output file. |
| r25360 | r25361 | |
| 68 | 68 | is true, then simply write to the output file without compressing, and |
| 69 | 69 | ignore flush. */ |
| 70 | 70 | local int gz_comp(state, flush) |
| 71 | gz_statep state; | |
| 72 | int flush; | |
| 71 | gz_statep state; | |
| 72 | int flush; | |
| 73 | 73 | { |
| 74 | int ret, got; | |
| 75 | unsigned have; | |
| 76 | z_streamp strm = &(state->strm); | |
| 74 | int ret, got; | |
| 75 | unsigned have; | |
| 76 | z_streamp strm = &(state->strm); | |
| 77 | 77 | |
| 78 | /* allocate memory if this is the first time through */ | |
| 79 | if (state->size == 0 && gz_init(state) == -1) | |
| 80 | return -1; | |
| 78 | /* allocate memory if this is the first time through */ | |
| 79 | if (state->size == 0 && gz_init(state) == -1) | |
| 80 | return -1; | |
| 81 | 81 | |
| 82 | /* write directly if requested */ | |
| 83 | if (state->direct) { | |
| 84 | got = write(state->fd, strm->next_in, strm->avail_in); | |
| 85 | if (got < 0 || (unsigned)got != strm->avail_in) { | |
| 86 | gz_error(state, Z_ERRNO, zstrerror()); | |
| 87 | return -1; | |
| 88 | } | |
| 89 | strm->avail_in = 0; | |
| 90 | return 0; | |
| 91 | } | |
| 82 | /* write directly if requested */ | |
| 83 | if (state->direct) { | |
| 84 | got = write(state->fd, strm->next_in, strm->avail_in); | |
| 85 | if (got < 0 || (unsigned)got != strm->avail_in) { | |
| 86 | gz_error(state, Z_ERRNO, zstrerror()); | |
| 87 | return -1; | |
| 88 | } | |
| 89 | strm->avail_in = 0; | |
| 90 | return 0; | |
| 91 | } | |
| 92 | 92 | |
| 93 | /* run deflate() on provided input until it produces no more output */ | |
| 94 | ret = Z_OK; | |
| 95 | do { | |
| 96 | /* write out current buffer contents if full, or if flushing, but if | |
| 97 | doing Z_FINISH then don't write until we get to Z_STREAM_END */ | |
| 98 | if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && | |
| 99 | (flush != Z_FINISH || ret == Z_STREAM_END))) { | |
| 100 | have = (unsigned)(strm->next_out - state->x.next); | |
| 101 | if (have && ((got = write(state->fd, state->x.next, have)) < 0 || | |
| 102 | (unsigned)got != have)) { | |
| 103 | gz_error(state, Z_ERRNO, zstrerror()); | |
| 104 | return -1; | |
| 105 | } | |
| 106 | if (strm->avail_out == 0) { | |
| 107 | strm->avail_out = state->size; | |
| 108 | strm->next_out = state->out; | |
| 109 | } | |
| 110 | state->x.next = strm->next_out; | |
| 111 | } | |
| 93 | /* run deflate() on provided input until it produces no more output */ | |
| 94 | ret = Z_OK; | |
| 95 | do { | |
| 96 | /* write out current buffer contents if full, or if flushing, but if | |
| 97 | doing Z_FINISH then don't write until we get to Z_STREAM_END */ | |
| 98 | if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && | |
| 99 | (flush != Z_FINISH || ret == Z_STREAM_END))) { | |
| 100 | have = (unsigned)(strm->next_out - state->x.next); | |
| 101 | if (have && ((got = write(state->fd, state->x.next, have)) < 0 || | |
| 102 | (unsigned)got != have)) { | |
| 103 | gz_error(state, Z_ERRNO, zstrerror()); | |
| 104 | return -1; | |
| 105 | } | |
| 106 | if (strm->avail_out == 0) { | |
| 107 | strm->avail_out = state->size; | |
| 108 | strm->next_out = state->out; | |
| 109 | } | |
| 110 | state->x.next = strm->next_out; | |
| 111 | } | |
| 112 | 112 | |
| 113 | /* compress */ | |
| 114 | have = strm->avail_out; | |
| 115 | ret = deflate(strm, flush); | |
| 116 | if (ret == Z_STREAM_ERROR) { | |
| 117 | gz_error(state, Z_STREAM_ERROR, | |
| 118 | "internal error: deflate stream corrupt"); | |
| 119 | return -1; | |
| 120 | } | |
| 121 | have -= strm->avail_out; | |
| 122 | } while (have); | |
| 113 | /* compress */ | |
| 114 | have = strm->avail_out; | |
| 115 | ret = deflate(strm, flush); | |
| 116 | if (ret == Z_STREAM_ERROR) { | |
| 117 | gz_error(state, Z_STREAM_ERROR, | |
| 118 | "internal error: deflate stream corrupt"); | |
| 119 | return -1; | |
| 120 | } | |
| 121 | have -= strm->avail_out; | |
| 122 | } while (have); | |
| 123 | 123 | |
| 124 | /* if that completed a deflate stream, allow another to start */ | |
| 125 | if (flush == Z_FINISH) | |
| 126 | deflateReset(strm); | |
| 124 | /* if that completed a deflate stream, allow another to start */ | |
| 125 | if (flush == Z_FINISH) | |
| 126 | deflateReset(strm); | |
| 127 | 127 | |
| 128 | /* all done, no errors */ | |
| 129 | return 0; | |
| 128 | /* all done, no errors */ | |
| 129 | return 0; | |
| 130 | 130 | } |
| 131 | 131 | |
| 132 | 132 | /* Compress len zeros to output. Return -1 on error, 0 on success. */ |
| 133 | 133 | local int gz_zero(state, len) |
| 134 | gz_statep state; | |
| 135 | z_off64_t len; | |
| 134 | gz_statep state; | |
| 135 | z_off64_t len; | |
| 136 | 136 | { |
| 137 | int first; | |
| 138 | unsigned n; | |
| 139 | z_streamp strm = &(state->strm); | |
| 137 | int first; | |
| 138 | unsigned n; | |
| 139 | z_streamp strm = &(state->strm); | |
| 140 | 140 | |
| 141 | /* consume whatever's left in the input buffer */ | |
| 142 | if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) | |
| 143 | return -1; | |
| 141 | /* consume whatever's left in the input buffer */ | |
| 142 | if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) | |
| 143 | return -1; | |
| 144 | 144 | |
| 145 | /* compress len zeros (len guaranteed > 0) */ | |
| 146 | first = 1; | |
| 147 | while (len) { | |
| 148 | n = GT_OFF(state->size) || (z_off64_t)state->size > len ? | |
| 149 | (unsigned)len : state->size; | |
| 150 | if (first) { | |
| 151 | memset(state->in, 0, n); | |
| 152 | first = 0; | |
| 153 | } | |
| 154 | strm->avail_in = n; | |
| 155 | strm->next_in = state->in; | |
| 156 | state->x.pos += n; | |
| 157 | if (gz_comp(state, Z_NO_FLUSH) == -1) | |
| 158 | return -1; | |
| 159 | len -= n; | |
| 160 | } | |
| 161 | return 0; | |
| 145 | /* compress len zeros (len guaranteed > 0) */ | |
| 146 | first = 1; | |
| 147 | while (len) { | |
| 148 | n = GT_OFF(state->size) || (z_off64_t)state->size > len ? | |
| 149 | (unsigned)len : state->size; | |
| 150 | if (first) { | |
| 151 | memset(state->in, 0, n); | |
| 152 | first = 0; | |
| 153 | } | |
| 154 | strm->avail_in = n; | |
| 155 | strm->next_in = state->in; | |
| 156 | state->x.pos += n; | |
| 157 | if (gz_comp(state, Z_NO_FLUSH) == -1) | |
| 158 | return -1; | |
| 159 | len -= n; | |
| 160 | } | |
| 161 | return 0; | |
| 162 | 162 | } |
| 163 | 163 | |
| 164 | 164 | /* -- see zlib.h -- */ |
| 165 | 165 | int ZEXPORT gzwrite(file, buf, len) |
| 166 | gzFile file; | |
| 167 | voidpc buf; | |
| 168 | unsigned len; | |
| 166 | gzFile file; | |
| 167 | voidpc buf; | |
| 168 | unsigned len; | |
| 169 | 169 | { |
| 170 | unsigned put = len; | |
| 171 | gz_statep state; | |
| 172 | z_streamp strm; | |
| 170 | unsigned put = len; | |
| 171 | gz_statep state; | |
| 172 | z_streamp strm; | |
| 173 | 173 | |
| 174 | /* get internal structure */ | |
| 175 | if (file == NULL) | |
| 176 | return 0; | |
| 177 | state = (gz_statep)file; | |
| 178 | strm = &(state->strm); | |
| 174 | /* get internal structure */ | |
| 175 | if (file == NULL) | |
| 176 | return 0; | |
| 177 | state = (gz_statep)file; | |
| 178 | strm = &(state->strm); | |
| 179 | 179 | |
| 180 | /* check that we're writing and that there's no error */ | |
| 181 | if (state->mode != GZ_WRITE || state->err != Z_OK) | |
| 182 | return 0; | |
| 180 | /* check that we're writing and that there's no error */ | |
| 181 | if (state->mode != GZ_WRITE || state->err != Z_OK) | |
| 182 | return 0; | |
| 183 | 183 | |
| 184 | /* since an int is returned, make sure len fits in one, otherwise return | |
| 185 | with an error (this avoids the flaw in the interface) */ | |
| 186 | if ((int)len < 0) { | |
| 187 | gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); | |
| 188 | return 0; | |
| 189 | } | |
| 184 | /* since an int is returned, make sure len fits in one, otherwise return | |
| 185 | with an error (this avoids the flaw in the interface) */ | |
| 186 | if ((int)len < 0) { | |
| 187 | gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); | |
| 188 | return 0; | |
| 189 | } | |
| 190 | 190 | |
| 191 | /* if len is zero, avoid unnecessary operations */ | |
| 192 | if (len == 0) | |
| 193 | return 0; | |
| 191 | /* if len is zero, avoid unnecessary operations */ | |
| 192 | if (len == 0) | |
| 193 | return 0; | |
| 194 | 194 | |
| 195 | /* allocate memory if this is the first time through */ | |
| 196 | if (state->size == 0 && gz_init(state) == -1) | |
| 197 | return 0; | |
| 195 | /* allocate memory if this is the first time through */ | |
| 196 | if (state->size == 0 && gz_init(state) == -1) | |
| 197 | return 0; | |
| 198 | 198 | |
| 199 | /* check for seek request */ | |
| 200 | if (state->seek) { | |
| 201 | state->seek = 0; | |
| 202 | if (gz_zero(state, state->skip) == -1) | |
| 203 | return 0; | |
| 204 | } | |
| 199 | /* check for seek request */ | |
| 200 | if (state->seek) { | |
| 201 | state->seek = 0; | |
| 202 | if (gz_zero(state, state->skip) == -1) | |
| 203 | return 0; | |
| 204 | } | |
| 205 | 205 | |
| 206 | /* for small len, copy to input buffer, otherwise compress directly */ | |
| 207 | if (len < state->size) { | |
| 208 | /* copy to input buffer, compress when full */ | |
| 209 | do { | |
| 210 | unsigned have, copy; | |
| 206 | /* for small len, copy to input buffer, otherwise compress directly */ | |
| 207 | if (len < state->size) { | |
| 208 | /* copy to input buffer, compress when full */ | |
| 209 | do { | |
| 210 | unsigned have, copy; | |
| 211 | 211 | |
| 212 | if (strm->avail_in == 0) | |
| 213 | strm->next_in = state->in; | |
| 214 | have = (unsigned)((strm->next_in + strm->avail_in) - state->in); | |
| 215 | copy = state->size - have; | |
| 216 | if (copy > len) | |
| 217 | copy = len; | |
| 218 | memcpy(state->in + have, buf, copy); | |
| 219 | strm->avail_in += copy; | |
| 220 | state->x.pos += copy; | |
| 221 | buf = (const char *)buf + copy; | |
| 222 | len -= copy; | |
| 223 | if (len && gz_comp(state, Z_NO_FLUSH) == -1) | |
| 224 | return 0; | |
| 225 | } while (len); | |
| 226 | } | |
| 227 | else { | |
| 228 | /* consume whatever's left in the input buffer */ | |
| 229 | if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) | |
| 230 | return 0; | |
| 212 | if (strm->avail_in == 0) | |
| 213 | strm->next_in = state->in; | |
| 214 | have = (unsigned)((strm->next_in + strm->avail_in) - state->in); | |
| 215 | copy = state->size - have; | |
| 216 | if (copy > len) | |
| 217 | copy = len; | |
| 218 | memcpy(state->in + have, buf, copy); | |
| 219 | strm->avail_in += copy; | |
| 220 | state->x.pos += copy; | |
| 221 | buf = (const char *)buf + copy; | |
| 222 | len -= copy; | |
| 223 | if (len && gz_comp(state, Z_NO_FLUSH) == -1) | |
| 224 | return 0; | |
| 225 | } while (len); | |
| 226 | } | |
| 227 | else { | |
| 228 | /* consume whatever's left in the input buffer */ | |
| 229 | if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) | |
| 230 | return 0; | |
| 231 | 231 | |
| 232 | /* directly compress user buffer to file */ | |
| 233 | strm->avail_in = len; | |
| 234 | strm->next_in = (z_const Bytef *)buf; | |
| 235 | state->x.pos += len; | |
| 236 | if (gz_comp(state, Z_NO_FLUSH) == -1) | |
| 237 | return 0; | |
| 238 | } | |
| 232 | /* directly compress user buffer to file */ | |
| 233 | strm->avail_in = len; | |
| 234 | strm->next_in = (z_const Bytef *)buf; | |
| 235 | state->x.pos += len; | |
| 236 | if (gz_comp(state, Z_NO_FLUSH) == -1) | |
| 237 | return 0; | |
| 238 | } | |
| 239 | 239 | |
| 240 | /* input was all buffered or compressed (put will fit in int) */ | |
| 241 | return (int)put; | |
| 240 | /* input was all buffered or compressed (put will fit in int) */ | |
| 241 | return (int)put; | |
| 242 | 242 | } |
| 243 | 243 | |
| 244 | 244 | /* -- see zlib.h -- */ |
| 245 | 245 | int ZEXPORT gzputc(file, c) |
| 246 | gzFile file; | |
| 247 | int c; | |
| 246 | gzFile file; | |
| 247 | int c; | |
| 248 | 248 | { |
| 249 | unsigned have; | |
| 250 | unsigned char buf[1]; | |
| 251 | gz_statep state; | |
| 252 | z_streamp strm; | |
| 249 | unsigned have; | |
| 250 | unsigned char buf[1]; | |
| 251 | gz_statep state; | |
| 252 | z_streamp strm; | |
| 253 | 253 | |
| 254 | /* get internal structure */ | |
| 255 | if (file == NULL) | |
| 256 | return -1; | |
| 257 | state = (gz_statep)file; | |
| 258 | strm = &(state->strm); | |
| 254 | /* get internal structure */ | |
| 255 | if (file == NULL) | |
| 256 | return -1; | |
| 257 | state = (gz_statep)file; | |
| 258 | strm = &(state->strm); | |
| 259 | 259 | |
| 260 | /* check that we're writing and that there's no error */ | |
| 261 | if (state->mode != GZ_WRITE || state->err != Z_OK) | |
| 262 | return -1; | |
| 260 | /* check that we're writing and that there's no error */ | |
| 261 | if (state->mode != GZ_WRITE || state->err != Z_OK) | |
| 262 | return -1; | |
| 263 | 263 | |
| 264 | /* check for seek request */ | |
| 265 | if (state->seek) { | |
| 266 | state->seek = 0; | |
| 267 | if (gz_zero(state, state->skip) == -1) | |
| 268 | return -1; | |
| 269 | } | |
| 264 | /* check for seek request */ | |
| 265 | if (state->seek) { | |
| 266 | state->seek = 0; | |
| 267 | if (gz_zero(state, state->skip) == -1) | |
| 268 | return -1; | |
| 269 | } | |
| 270 | 270 | |
| 271 | /* try writing to input buffer for speed (state->size == 0 if buffer not | |
| 272 | initialized) */ | |
| 273 | if (state->size) { | |
| 274 | if (strm->avail_in == 0) | |
| 275 | strm->next_in = state->in; | |
| 276 | have = (unsigned)((strm->next_in + strm->avail_in) - state->in); | |
| 277 | if (have < state->size) { | |
| 278 | state->in[have] = c; | |
| 279 | strm->avail_in++; | |
| 280 | state->x.pos++; | |
| 281 | return c & 0xff; | |
| 282 | } | |
| 283 | } | |
| 271 | /* try writing to input buffer for speed (state->size == 0 if buffer not | |
| 272 | initialized) */ | |
| 273 | if (state->size) { | |
| 274 | if (strm->avail_in == 0) | |
| 275 | strm->next_in = state->in; | |
| 276 | have = (unsigned)((strm->next_in + strm->avail_in) - state->in); | |
| 277 | if (have < state->size) { | |
| 278 | state->in[have] = c; | |
| 279 | strm->avail_in++; | |
| 280 | state->x.pos++; | |
| 281 | return c & 0xff; | |
| 282 | } | |
| 283 | } | |
| 284 | 284 | |
| 285 | /* no room in buffer or not initialized, use gz_write() */ | |
| 286 | buf[0] = c; | |
| 287 | if (gzwrite(file, buf, 1) != 1) | |
| 288 | return -1; | |
| 289 | return c & 0xff; | |
| 285 | /* no room in buffer or not initialized, use gz_write() */ | |
| 286 | buf[0] = c; | |
| 287 | if (gzwrite(file, buf, 1) != 1) | |
| 288 | return -1; | |
| 289 | return c & 0xff; | |
| 290 | 290 | } |
| 291 | 291 | |
| 292 | 292 | /* -- see zlib.h -- */ |
| 293 | 293 | int ZEXPORT gzputs(file, str) |
| 294 | gzFile file; | |
| 295 | const char *str; | |
| 294 | gzFile file; | |
| 295 | const char *str; | |
| 296 | 296 | { |
| 297 | int ret; | |
| 298 | unsigned len; | |
| 297 | int ret; | |
| 298 | unsigned len; | |
| 299 | 299 | |
| 300 | /* write string */ | |
| 301 | len = (unsigned)strlen(str); | |
| 302 | ret = gzwrite(file, str, len); | |
| 303 | return ret == 0 && len != 0 ? -1 : ret; | |
| 300 | /* write string */ | |
| 301 | len = (unsigned)strlen(str); | |
| 302 | ret = gzwrite(file, str, len); | |
| 303 | return ret == 0 && len != 0 ? -1 : ret; | |
| 304 | 304 | } |
| 305 | 305 | |
| 306 | 306 | #if defined(STDC) || defined(Z_HAVE_STDARG_H) |
| r25360 | r25361 | |
| 309 | 309 | /* -- see zlib.h -- */ |
| 310 | 310 | int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) |
| 311 | 311 | { |
| 312 | int size, len; | |
| 313 | gz_statep state; | |
| 314 | z_streamp strm; | |
| 312 | int size, len; | |
| 313 | gz_statep state; | |
| 314 | z_streamp strm; | |
| 315 | 315 | |
| 316 | /* get internal structure */ | |
| 317 | if (file == NULL) | |
| 318 | return -1; | |
| 319 | state = (gz_statep)file; | |
| 320 | strm = &(state->strm); | |
| 316 | /* get internal structure */ | |
| 317 | if (file == NULL) | |
| 318 | return -1; | |
| 319 | state = (gz_statep)file; | |
| 320 | strm = &(state->strm); | |
| 321 | 321 | |
| 322 | /* check that we're writing and that there's no error */ | |
| 323 | if (state->mode != GZ_WRITE || state->err != Z_OK) | |
| 324 | return 0; | |
| 322 | /* check that we're writing and that there's no error */ | |
| 323 | if (state->mode != GZ_WRITE || state->err != Z_OK) | |
| 324 | return 0; | |
| 325 | 325 | |
| 326 | /* make sure we have some buffer space */ | |
| 327 | if (state->size == 0 && gz_init(state) == -1) | |
| 328 | return 0; | |
| 326 | /* make sure we have some buffer space */ | |
| 327 | if (state->size == 0 && gz_init(state) == -1) | |
| 328 | return 0; | |
| 329 | 329 | |
| 330 | /* check for seek request */ | |
| 331 | if (state->seek) { | |
| 332 | state->seek = 0; | |
| 333 | if (gz_zero(state, state->skip) == -1) | |
| 334 | return 0; | |
| 335 | } | |
| 330 | /* check for seek request */ | |
| 331 | if (state->seek) { | |
| 332 | state->seek = 0; | |
| 333 | if (gz_zero(state, state->skip) == -1) | |
| 334 | return 0; | |
| 335 | } | |
| 336 | 336 | |
| 337 | /* consume whatever's left in the input buffer */ | |
| 338 | if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) | |
| 339 | return 0; | |
| 337 | /* consume whatever's left in the input buffer */ | |
| 338 | if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) | |
| 339 | return 0; | |
| 340 | 340 | |
| 341 | /* do the printf() into the input buffer, put length in len */ | |
| 342 | size = (int)(state->size); | |
| 343 | state->in[size - 1] = 0; | |
| 341 | /* do the printf() into the input buffer, put length in len */ | |
| 342 | size = (int)(state->size); | |
| 343 | state->in[size - 1] = 0; | |
| 344 | 344 | #ifdef NO_vsnprintf |
| 345 | 345 | # ifdef HAS_vsprintf_void |
| 346 | (void)vsprintf((char *)(state->in), format, va); | |
| 347 | for (len = 0; len < size; len++) | |
| 348 | if (state->in[len] == 0) break; | |
| 346 | (void)vsprintf((char *)(state->in), format, va); | |
| 347 | for (len = 0; len < size; len++) | |
| 348 | if (state->in[len] == 0) break; | |
| 349 | 349 | # else |
| 350 | ||
| 350 | len = vsprintf((char *)(state->in), format, va); | |
| 351 | 351 | # endif |
| 352 | 352 | #else |
| 353 | 353 | # ifdef HAS_vsnprintf_void |
| 354 | (void)vsnprintf((char *)(state->in), size, format, va); | |
| 355 | len = strlen((char *)(state->in)); | |
| 354 | (void)vsnprintf((char *)(state->in), size, format, va); | |
| 355 | len = strlen((char *)(state->in)); | |
| 356 | 356 | # else |
| 357 | ||
| 357 | len = vsnprintf((char *)(state->in), size, format, va); | |
| 358 | 358 | # endif |
| 359 | 359 | #endif |
| 360 | 360 | |
| 361 | /* check that printf() results fit in buffer */ | |
| 362 | if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) | |
| 363 | return 0; | |
| 361 | /* check that printf() results fit in buffer */ | |
| 362 | if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) | |
| 363 | return 0; | |
| 364 | 364 | |
| 365 | /* update buffer and position, defer compression until needed */ | |
| 366 | strm->avail_in = (unsigned)len; | |
| 367 | strm->next_in = state->in; | |
| 368 | state->x.pos += len; | |
| 369 | return len; | |
| 365 | /* update buffer and position, defer compression until needed */ | |
| 366 | strm->avail_in = (unsigned)len; | |
| 367 | strm->next_in = state->in; | |
| 368 | state->x.pos += len; | |
| 369 | return len; | |
| 370 | 370 | } |
| 371 | 371 | |
| 372 | 372 | int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) |
| 373 | 373 | { |
| 374 | va_list va; | |
| 375 | int ret; | |
| 374 | va_list va; | |
| 375 | int ret; | |
| 376 | 376 | |
| 377 | va_start(va, format); | |
| 378 | ret = gzvprintf(file, format, va); | |
| 379 | va_end(va); | |
| 380 | return ret; | |
| 377 | va_start(va, format); | |
| 378 | ret = gzvprintf(file, format, va); | |
| 379 | va_end(va); | |
| 380 | return ret; | |
| 381 | 381 | } |
| 382 | 382 | |
| 383 | 383 | #else /* !STDC && !Z_HAVE_STDARG_H */ |
| 384 | 384 | |
| 385 | 385 | /* -- see zlib.h -- */ |
| 386 | 386 | int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, |
| 387 | a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) | |
| 388 | gzFile file; | |
| 389 | const char *format; | |
| 390 | int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, | |
| 391 | a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; | |
| 387 | a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) | |
| 388 | gzFile file; | |
| 389 | const char *format; | |
| 390 | int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, | |
| 391 | a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; | |
| 392 | 392 | { |
| 393 | int size, len; | |
| 394 | gz_statep state; | |
| 395 | z_streamp strm; | |
| 393 | int size, len; | |
| 394 | gz_statep state; | |
| 395 | z_streamp strm; | |
| 396 | 396 | |
| 397 | /* get internal structure */ | |
| 398 | if (file == NULL) | |
| 399 | return -1; | |
| 400 | state = (gz_statep)file; | |
| 401 | strm = &(state->strm); | |
| 397 | /* get internal structure */ | |
| 398 | if (file == NULL) | |
| 399 | return -1; | |
| 400 | state = (gz_statep)file; | |
| 401 | strm = &(state->strm); | |
| 402 | 402 | |
| 403 | /* check that can really pass pointer in ints */ | |
| 404 | if (sizeof(int) != sizeof(void *)) | |
| 405 | return 0; | |
| 403 | /* check that can really pass pointer in ints */ | |
| 404 | if (sizeof(int) != sizeof(void *)) | |
| 405 | return 0; | |
| 406 | 406 | |
| 407 | /* check that we're writing and that there's no error */ | |
| 408 | if (state->mode != GZ_WRITE || state->err != Z_OK) | |
| 409 | return 0; | |
| 407 | /* check that we're writing and that there's no error */ | |
| 408 | if (state->mode != GZ_WRITE || state->err != Z_OK) | |
| 409 | return 0; | |
| 410 | 410 | |
| 411 | /* make sure we have some buffer space */ | |
| 412 | if (state->size == 0 && gz_init(state) == -1) | |
| 413 | return 0; | |
| 411 | /* make sure we have some buffer space */ | |
| 412 | if (state->size == 0 && gz_init(state) == -1) | |
| 413 | return 0; | |
| 414 | 414 | |
| 415 | /* check for seek request */ | |
| 416 | if (state->seek) { | |
| 417 | state->seek = 0; | |
| 418 | if (gz_zero(state, state->skip) == -1) | |
| 419 | return 0; | |
| 420 | } | |
| 415 | /* check for seek request */ | |
| 416 | if (state->seek) { | |
| 417 | state->seek = 0; | |
| 418 | if (gz_zero(state, state->skip) == -1) | |
| 419 | return 0; | |
| 420 | } | |
| 421 | 421 | |
| 422 | /* consume whatever's left in the input buffer */ | |
| 423 | if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) | |
| 424 | return 0; | |
| 422 | /* consume whatever's left in the input buffer */ | |
| 423 | if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) | |
| 424 | return 0; | |
| 425 | 425 | |
| 426 | /* do the printf() into the input buffer, put length in len */ | |
| 427 | size = (int)(state->size); | |
| 428 | state->in[size - 1] = 0; | |
| 426 | /* do the printf() into the input buffer, put length in len */ | |
| 427 | size = (int)(state->size); | |
| 428 | state->in[size - 1] = 0; | |
| 429 | 429 | #ifdef NO_snprintf |
| 430 | 430 | # ifdef HAS_sprintf_void |
| 431 | sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, | |
| 432 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); | |
| 433 | for (len = 0; len < size; len++) | |
| 434 | if (state->in[len] == 0) break; | |
| 431 | sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, | |
| 432 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); | |
| 433 | for (len = 0; len < size; len++) | |
| 434 | if (state->in[len] == 0) break; | |
| 435 | 435 | # else |
| 436 | len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, | |
| 437 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); | |
| 436 | len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, | |
| 437 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); | |
| 438 | 438 | # endif |
| 439 | 439 | #else |
| 440 | 440 | # ifdef HAS_snprintf_void |
| 441 | snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8, | |
| 442 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); | |
| 443 | len = strlen((char *)(state->in)); | |
| 441 | snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8, | |
| 442 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); | |
| 443 | len = strlen((char *)(state->in)); | |
| 444 | 444 | # else |
| 445 | len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, | |
| 446 | a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, | |
| 447 | a19, a20); | |
| 445 | len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, | |
| 446 | a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, | |
| 447 | a19, a20); | |
| 448 | 448 | # endif |
| 449 | 449 | #endif |
| 450 | 450 | |
| 451 | /* check that printf() results fit in buffer */ | |
| 452 | if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) | |
| 453 | return 0; | |
| 451 | /* check that printf() results fit in buffer */ | |
| 452 | if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) | |
| 453 | return 0; | |
| 454 | 454 | |
| 455 | /* update buffer and position, defer compression until needed */ | |
| 456 | strm->avail_in = (unsigned)len; | |
| 457 | strm->next_in = state->in; | |
| 458 | state->x.pos += len; | |
| 459 | return len; | |
| 455 | /* update buffer and position, defer compression until needed */ | |
| 456 | strm->avail_in = (unsigned)len; | |
| 457 | strm->next_in = state->in; | |
| 458 | state->x.pos += len; | |
| 459 | return len; | |
| 460 | 460 | } |
| 461 | 461 | |
| 462 | 462 | #endif |
| 463 | 463 | |
| 464 | 464 | /* -- see zlib.h -- */ |
| 465 | 465 | int ZEXPORT gzflush(file, flush) |
| 466 | gzFile file; | |
| 467 | int flush; | |
| 466 | gzFile file; | |
| 467 | int flush; | |
| 468 | 468 | { |
| 469 | ||
| 469 | gz_statep state; | |
| 470 | 470 | |
| 471 | /* get internal structure */ | |
| 472 | if (file == NULL) | |
| 473 | return -1; | |
| 474 | state = (gz_statep)file; | |
| 471 | /* get internal structure */ | |
| 472 | if (file == NULL) | |
| 473 | return -1; | |
| 474 | state = (gz_statep)file; | |
| 475 | 475 | |
| 476 | /* check that we're writing and that there's no error */ | |
| 477 | if (state->mode != GZ_WRITE || state->err != Z_OK) | |
| 478 | return Z_STREAM_ERROR; | |
| 476 | /* check that we're writing and that there's no error */ | |
| 477 | if (state->mode != GZ_WRITE || state->err != Z_OK) | |
| 478 | return Z_STREAM_ERROR; | |
| 479 | 479 | |
| 480 | /* check flush parameter */ | |
| 481 | if (flush < 0 || flush > Z_FINISH) | |
| 482 | return Z_STREAM_ERROR; | |
| 480 | /* check flush parameter */ | |
| 481 | if (flush < 0 || flush > Z_FINISH) | |
| 482 | return Z_STREAM_ERROR; | |
| 483 | 483 | |
| 484 | /* check for seek request */ | |
| 485 | if (state->seek) { | |
| 486 | state->seek = 0; | |
| 487 | if (gz_zero(state, state->skip) == -1) | |
| 488 | return -1; | |
| 489 | } | |
| 484 | /* check for seek request */ | |
| 485 | if (state->seek) { | |
| 486 | state->seek = 0; | |
| 487 | if (gz_zero(state, state->skip) == -1) | |
| 488 | return -1; | |
| 489 | } | |
| 490 | 490 | |
| 491 | /* compress remaining data with requested flush */ | |
| 492 | gz_comp(state, flush); | |
| 493 | return state->err; | |
| 491 | /* compress remaining data with requested flush */ | |
| 492 | gz_comp(state, flush); | |
| 493 | return state->err; | |
| 494 | 494 | } |
| 495 | 495 | |
| 496 | 496 | /* -- see zlib.h -- */ |
| 497 | 497 | int ZEXPORT gzsetparams(file, level, strategy) |
| 498 | gzFile file; | |
| 499 | int level; | |
| 500 | int strategy; | |
| 498 | gzFile file; | |
| 499 | int level; | |
| 500 | int strategy; | |
| 501 | 501 | { |
| 502 | gz_statep state; | |
| 503 | z_streamp strm; | |
| 502 | gz_statep state; | |
| 503 | z_streamp strm; | |
| 504 | 504 | |
| 505 | /* get internal structure */ | |
| 506 | if (file == NULL) | |
| 507 | return Z_STREAM_ERROR; | |
| 508 | state = (gz_statep)file; | |
| 509 | strm = &(state->strm); | |
| 505 | /* get internal structure */ | |
| 506 | if (file == NULL) | |
| 507 | return Z_STREAM_ERROR; | |
| 508 | state = (gz_statep)file; | |
| 509 | strm = &(state->strm); | |
| 510 | 510 | |
| 511 | /* check that we're writing and that there's no error */ | |
| 512 | if (state->mode != GZ_WRITE || state->err != Z_OK) | |
| 513 | return Z_STREAM_ERROR; | |
| 511 | /* check that we're writing and that there's no error */ | |
| 512 | if (state->mode != GZ_WRITE || state->err != Z_OK) | |
| 513 | return Z_STREAM_ERROR; | |
| 514 | 514 | |
| 515 | /* if no change is requested, then do nothing */ | |
| 516 | if (level == state->level && strategy == state->strategy) | |
| 517 | return Z_OK; | |
| 515 | /* if no change is requested, then do nothing */ | |
| 516 | if (level == state->level && strategy == state->strategy) | |
| 517 | return Z_OK; | |
| 518 | 518 | |
| 519 | /* check for seek request */ | |
| 520 | if (state->seek) { | |
| 521 | state->seek = 0; | |
| 522 | if (gz_zero(state, state->skip) == -1) | |
| 523 | return -1; | |
| 524 | } | |
| 519 | /* check for seek request */ | |
| 520 | if (state->seek) { | |
| 521 | state->seek = 0; | |
| 522 | if (gz_zero(state, state->skip) == -1) | |
| 523 | return -1; | |
| 524 | } | |
| 525 | 525 | |
| 526 | /* change compression parameters for subsequent input */ | |
| 527 | if (state->size) { | |
| 528 | /* flush previous input with previous parameters before changing */ | |
| 529 | if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1) | |
| 530 | return state->err; | |
| 531 | deflateParams(strm, level, strategy); | |
| 532 | } | |
| 533 | state->level = level; | |
| 534 | state->strategy = strategy; | |
| 535 | return Z_OK; | |
| 526 | /* change compression parameters for subsequent input */ | |
| 527 | if (state->size) { | |
| 528 | /* flush previous input with previous parameters before changing */ | |
| 529 | if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1) | |
| 530 | return state->err; | |
| 531 | deflateParams(strm, level, strategy); | |
| 532 | } | |
| 533 | state->level = level; | |
| 534 | state->strategy = strategy; | |
| 535 | return Z_OK; | |
| 536 | 536 | } |
| 537 | 537 | |
| 538 | 538 | /* -- see zlib.h -- */ |
| 539 | 539 | int ZEXPORT gzclose_w(file) |
| 540 | ||
| 540 | gzFile file; | |
| 541 | 541 | { |
| 542 | int ret = Z_OK; | |
| 543 | gz_statep state; | |
| 542 | int ret = Z_OK; | |
| 543 | gz_statep state; | |
| 544 | 544 | |
| 545 | /* get internal structure */ | |
| 546 | if (file == NULL) | |
| 547 | return Z_STREAM_ERROR; | |
| 548 | state = (gz_statep)file; | |
| 545 | /* get internal structure */ | |
| 546 | if (file == NULL) | |
| 547 | return Z_STREAM_ERROR; | |
| 548 | state = (gz_statep)file; | |
| 549 | 549 | |
| 550 | /* check that we're writing */ | |
| 551 | if (state->mode != GZ_WRITE) | |
| 552 | return Z_STREAM_ERROR; | |
| 550 | /* check that we're writing */ | |
| 551 | if (state->mode != GZ_WRITE) | |
| 552 | return Z_STREAM_ERROR; | |
| 553 | 553 | |
| 554 | /* check for seek request */ | |
| 555 | if (state->seek) { | |
| 556 | state->seek = 0; | |
| 557 | if (gz_zero(state, state->skip) == -1) | |
| 558 | ret = state->err; | |
| 559 | } | |
| 554 | /* check for seek request */ | |
| 555 | if (state->seek) { | |
| 556 | state->seek = 0; | |
| 557 | if (gz_zero(state, state->skip) == -1) | |
| 558 | ret = state->err; | |
| 559 | } | |
| 560 | 560 | |
| 561 | /* flush, free memory, and close file */ | |
| 562 | if (gz_comp(state, Z_FINISH) == -1) | |
| 563 | ret = state->err; | |
| 564 | if (state->size) { | |
| 565 | if (!state->direct) { | |
| 566 | (void)deflateEnd(&(state->strm)); | |
| 567 | free(state->out); | |
| 568 | } | |
| 569 | free(state->in); | |
| 570 | } | |
| 571 | gz_error(state, Z_OK, NULL); | |
| 572 | free(state->path); | |
| 573 | if (close(state->fd) == -1) | |
| 574 | ret = Z_ERRNO; | |
| 575 | free(state); | |
| 576 | return ret; | |
| 561 | /* flush, free memory, and close file */ | |
| 562 | if (gz_comp(state, Z_FINISH) == -1) | |
| 563 | ret = state->err; | |
| 564 | if (state->size) { | |
| 565 | if (!state->direct) { | |
| 566 | (void)deflateEnd(&(state->strm)); | |
| 567 | free(state->out); | |
| 568 | } | |
| 569 | free(state->in); | |
| 570 | } | |
| 571 | gz_error(state, Z_OK, NULL); | |
| 572 | free(state->path); | |
| 573 | if (close(state->fd) == -1) | |
| 574 | ret = Z_ERRNO; | |
| 575 | free(state); | |
| 576 | return ret; | |
| 577 | 577 | } |
| r25360 | r25361 | |
|---|---|---|
| 20 | 20 | Z_STREAM_ERROR if the level parameter is invalid. |
| 21 | 21 | */ |
| 22 | 22 | int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) |
| 23 | Bytef *dest; | |
| 24 | uLongf *destLen; | |
| 25 | const Bytef *source; | |
| 26 | uLong sourceLen; | |
| 27 | int level; | |
| 23 | Bytef *dest; | |
| 24 | uLongf *destLen; | |
| 25 | const Bytef *source; | |
| 26 | uLong sourceLen; | |
| 27 | int level; | |
| 28 | 28 | { |
| 29 | z_stream stream; | |
| 30 | int err; | |
| 29 | z_stream stream; | |
| 30 | int err; | |
| 31 | 31 | |
| 32 | stream.next_in = (z_const Bytef *)source; | |
| 33 | stream.avail_in = (uInt)sourceLen; | |
| 32 | stream.next_in = (z_const Bytef *)source; | |
| 33 | stream.avail_in = (uInt)sourceLen; | |
| 34 | 34 | #ifdef MAXSEG_64K |
| 35 | /* Check for source > 64K on 16-bit machine: */ | |
| 36 | if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; | |
| 35 | /* Check for source > 64K on 16-bit machine: */ | |
| 36 | if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; | |
| 37 | 37 | #endif |
| 38 | stream.next_out = dest; | |
| 39 | stream.avail_out = (uInt)*destLen; | |
| 40 | if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; | |
| 38 | stream.next_out = dest; | |
| 39 | stream.avail_out = (uInt)*destLen; | |
| 40 | if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; | |
| 41 | 41 | |
| 42 | stream.zalloc = (alloc_func)0; | |
| 43 | stream.zfree = (free_func)0; | |
| 44 | stream.opaque = (voidpf)0; | |
| 42 | stream.zalloc = (alloc_func)0; | |
| 43 | stream.zfree = (free_func)0; | |
| 44 | stream.opaque = (voidpf)0; | |
| 45 | 45 | |
| 46 | err = deflateInit(&stream, level); | |
| 47 | if (err != Z_OK) return err; | |
| 46 | err = deflateInit(&stream, level); | |
| 47 | if (err != Z_OK) return err; | |
| 48 | 48 | |
| 49 | err = deflate(&stream, Z_FINISH); | |
| 50 | if (err != Z_STREAM_END) { | |
| 51 | deflateEnd(&stream); | |
| 52 | return err == Z_OK ? Z_BUF_ERROR : err; | |
| 53 | } | |
| 54 | *destLen = stream.total_out; | |
| 49 | err = deflate(&stream, Z_FINISH); | |
| 50 | if (err != Z_STREAM_END) { | |
| 51 | deflateEnd(&stream); | |
| 52 | return err == Z_OK ? Z_BUF_ERROR : err; | |
| 53 | } | |
| 54 | *destLen = stream.total_out; | |
| 55 | 55 | |
| 56 | err = deflateEnd(&stream); | |
| 57 | return err; | |
| 56 | err = deflateEnd(&stream); | |
| 57 | return err; | |
| 58 | 58 | } |
| 59 | 59 | |
| 60 | 60 | /* =========================================================================== |
| 61 | 61 | */ |
| 62 | 62 | int ZEXPORT compress (dest, destLen, source, sourceLen) |
| 63 | Bytef *dest; | |
| 64 | uLongf *destLen; | |
| 65 | const Bytef *source; | |
| 66 | uLong sourceLen; | |
| 63 | Bytef *dest; | |
| 64 | uLongf *destLen; | |
| 65 | const Bytef *source; | |
| 66 | uLong sourceLen; | |
| 67 | 67 | { |
| 68 | ||
| 68 | return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); | |
| 69 | 69 | } |
| 70 | 70 | |
| 71 | 71 | /* =========================================================================== |
| r25360 | r25361 | |
| 73 | 73 | this function needs to be updated. |
| 74 | 74 | */ |
| 75 | 75 | uLong ZEXPORT compressBound (sourceLen) |
| 76 | ||
| 76 | uLong sourceLen; | |
| 77 | 77 | { |
| 78 | return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + | |
| 79 | (sourceLen >> 25) + 13; | |
| 78 | return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + | |
| 79 | (sourceLen >> 25) + 13; | |
| 80 | 80 | } |
| r25360 | r25361 | |
|---|---|---|
| 27 | 27 | /* note that this assumes BASE is 65521, where 65536 % 65521 == 15 |
| 28 | 28 | (thank you to John Reiser for pointing this out) */ |
| 29 | 29 | # define CHOP(a) \ |
| 30 | do { \ | |
| 31 | unsigned long tmp = a >> 16; \ | |
| 32 | a &= 0xffffUL; \ | |
| 33 | a += (tmp << 4) - tmp; \ | |
| 34 | } while (0) | |
| 30 | do { \ | |
| 31 | unsigned long tmp = a >> 16; \ | |
| 32 | a &= 0xffffUL; \ | |
| 33 | a += (tmp << 4) - tmp; \ | |
| 34 | } while (0) | |
| 35 | 35 | # define MOD28(a) \ |
| 36 | do { \ | |
| 37 | CHOP(a); \ | |
| 38 | if (a >= BASE) a -= BASE; \ | |
| 39 | } while (0) | |
| 36 | do { \ | |
| 37 | CHOP(a); \ | |
| 38 | if (a >= BASE) a -= BASE; \ | |
| 39 | } while (0) | |
| 40 | 40 | # define MOD(a) \ |
| 41 | do { \ | |
| 42 | CHOP(a); \ | |
| 43 | MOD28(a); \ | |
| 44 | } while (0) | |
| 41 | do { \ | |
| 42 | CHOP(a); \ | |
| 43 | MOD28(a); \ | |
| 44 | } while (0) | |
| 45 | 45 | # define MOD63(a) \ |
| 46 | do { /* this assumes a is not negative */ \ | |
| 47 | z_off64_t tmp = a >> 32; \ | |
| 48 | a &= 0xffffffffL; \ | |
| 49 | a += (tmp << 8) - (tmp << 5) + tmp; \ | |
| 50 | tmp = a >> 16; \ | |
| 51 | a &= 0xffffL; \ | |
| 52 | a += (tmp << 4) - tmp; \ | |
| 53 | tmp = a >> 16; \ | |
| 54 | a &= 0xffffL; \ | |
| 55 | a += (tmp << 4) - tmp; \ | |
| 56 | if (a >= BASE) a -= BASE; \ | |
| 57 | } while (0) | |
| 46 | do { /* this assumes a is not negative */ \ | |
| 47 | z_off64_t tmp = a >> 32; \ | |
| 48 | a &= 0xffffffffL; \ | |
| 49 | a += (tmp << 8) - (tmp << 5) + tmp; \ | |
| 50 | tmp = a >> 16; \ | |
| 51 | a &= 0xffffL; \ | |
| 52 | a += (tmp << 4) - tmp; \ | |
| 53 | tmp = a >> 16; \ | |
| 54 | a &= 0xffffL; \ | |
| 55 | a += (tmp << 4) - tmp; \ | |
| 56 | if (a >= BASE) a -= BASE; \ | |
| 57 | } while (0) | |
| 58 | 58 | #else |
| 59 | 59 | # define MOD(a) a %= BASE |
| 60 | 60 | # define MOD28(a) a %= BASE |
| r25360 | r25361 | |
| 63 | 63 | |
| 64 | 64 | /* ========================================================================= */ |
| 65 | 65 | uLong ZEXPORT adler32(adler, buf, len) |
| 66 | uLong adler; | |
| 67 | const Bytef *buf; | |
| 68 | uInt len; | |
| 66 | uLong adler; | |
| 67 | const Bytef *buf; | |
| 68 | uInt len; | |
| 69 | 69 | { |
| 70 | unsigned long sum2; | |
| 71 | unsigned n; | |
| 70 | unsigned long sum2; | |
| 71 | unsigned n; | |
| 72 | 72 | |
| 73 | /* split Adler-32 into component sums */ | |
| 74 | sum2 = (adler >> 16) & 0xffff; | |
| 75 | adler &= 0xffff; | |
| 73 | /* split Adler-32 into component sums */ | |
| 74 | sum2 = (adler >> 16) & 0xffff; | |
| 75 | adler &= 0xffff; | |
| 76 | 76 | |
| 77 | /* in case user likes doing a byte at a time, keep it fast */ | |
| 78 | if (len == 1) { | |
| 79 | adler += buf[0]; | |
| 80 | if (adler >= BASE) | |
| 81 | adler -= BASE; | |
| 82 | sum2 += adler; | |
| 83 | if (sum2 >= BASE) | |
| 84 | sum2 -= BASE; | |
| 85 | return adler | (sum2 << 16); | |
| 86 | } | |
| 77 | /* in case user likes doing a byte at a time, keep it fast */ | |
| 78 | if (len == 1) { | |
| 79 | adler += buf[0]; | |
| 80 | if (adler >= BASE) | |
| 81 | adler -= BASE; | |
| 82 | sum2 += adler; | |
| 83 | if (sum2 >= BASE) | |
| 84 | sum2 -= BASE; | |
| 85 | return adler | (sum2 << 16); | |
| 86 | } | |
| 87 | 87 | |
| 88 | /* initial Adler-32 value (deferred check for len == 1 speed) */ | |
| 89 | if (buf == Z_NULL) | |
| 90 | return 1L; | |
| 88 | /* initial Adler-32 value (deferred check for len == 1 speed) */ | |
| 89 | if (buf == Z_NULL) | |
| 90 | return 1L; | |
| 91 | 91 | |
| 92 | /* in case short lengths are provided, keep it somewhat fast */ | |
| 93 | if (len < 16) { | |
| 94 | while (len--) { | |
| 95 | adler += *buf++; | |
| 96 | sum2 += adler; | |
| 97 | } | |
| 98 | if (adler >= BASE) | |
| 99 | adler -= BASE; | |
| 100 | MOD28(sum2); /* only added so many BASE's */ | |
| 101 | return adler | (sum2 << 16); | |
| 102 | } | |
| 92 | /* in case short lengths are provided, keep it somewhat fast */ | |
| 93 | if (len < 16) { | |
| 94 | while (len--) { | |
| 95 | adler += *buf++; | |
| 96 | sum2 += adler; | |
| 97 | } | |
| 98 | if (adler >= BASE) | |
| 99 | adler -= BASE; | |
| 100 | MOD28(sum2); /* only added so many BASE's */ | |
| 101 | return adler | (sum2 << 16); | |
| 102 | } | |
| 103 | 103 | |
| 104 | /* do length NMAX blocks -- requires just one modulo operation */ | |
| 105 | while (len >= NMAX) { | |
| 106 | len -= NMAX; | |
| 107 | n = NMAX / 16; /* NMAX is divisible by 16 */ | |
| 108 | do { | |
| 109 | DO16(buf); /* 16 sums unrolled */ | |
| 110 | buf += 16; | |
| 111 | } while (--n); | |
| 112 | MOD(adler); | |
| 113 | MOD(sum2); | |
| 114 | } | |
| 104 | /* do length NMAX blocks -- requires just one modulo operation */ | |
| 105 | while (len >= NMAX) { | |
| 106 | len -= NMAX; | |
| 107 | n = NMAX / 16; /* NMAX is divisible by 16 */ | |
| 108 | do { | |
| 109 | DO16(buf); /* 16 sums unrolled */ | |
| 110 | buf += 16; | |
| 111 | } while (--n); | |
| 112 | MOD(adler); | |
| 113 | MOD(sum2); | |
| 114 | } | |
| 115 | 115 | |
| 116 | /* do remaining bytes (less than NMAX, still just one modulo) */ | |
| 117 | if (len) { /* avoid modulos if none remaining */ | |
| 118 | while (len >= 16) { | |
| 119 | len -= 16; | |
| 120 | DO16(buf); | |
| 121 | buf += 16; | |
| 122 | } | |
| 123 | while (len--) { | |
| 124 | adler += *buf++; | |
| 125 | sum2 += adler; | |
| 126 | } | |
| 127 | MOD(adler); | |
| 128 | MOD(sum2); | |
| 129 | } | |
| 116 | /* do remaining bytes (less than NMAX, still just one modulo) */ | |
| 117 | if (len) { /* avoid modulos if none remaining */ | |
| 118 | while (len >= 16) { | |
| 119 | len -= 16; | |
| 120 | DO16(buf); | |
| 121 | buf += 16; | |
| 122 | } | |
| 123 | while (len--) { | |
| 124 | adler += *buf++; | |
| 125 | sum2 += adler; | |
| 126 | } | |
| 127 | MOD(adler); | |
| 128 | MOD(sum2); | |
| 129 | } | |
| 130 | 130 | |
| 131 | /* return recombined sums */ | |
| 132 | return adler | (sum2 << 16); | |
| 131 | /* return recombined sums */ | |
| 132 | return adler | (sum2 << 16); | |
| 133 | 133 | } |
| 134 | 134 | |
| 135 | 135 | /* ========================================================================= */ |
| 136 | 136 | local uLong adler32_combine_(adler1, adler2, len2) |
| 137 | uLong adler1; | |
| 138 | uLong adler2; | |
| 139 | z_off64_t len2; | |
| 137 | uLong adler1; | |
| 138 | uLong adler2; | |
| 139 | z_off64_t len2; | |
| 140 | 140 | { |
| 141 | unsigned long sum1; | |
| 142 | unsigned long sum2; | |
| 143 | unsigned rem; | |
| 141 | unsigned long sum1; | |
| 142 | unsigned long sum2; | |
| 143 | unsigned rem; | |
| 144 | 144 | |
| 145 | /* for negative len, return invalid adler32 as a clue for debugging */ | |
| 146 | if (len2 < 0) | |
| 147 | return 0xffffffffUL; | |
| 145 | /* for negative len, return invalid adler32 as a clue for debugging */ | |
| 146 | if (len2 < 0) | |
| 147 | return 0xffffffffUL; | |
| 148 | 148 | |
| 149 | /* the derivation of this formula is left as an exercise for the reader */ | |
| 150 | MOD63(len2); /* assumes len2 >= 0 */ | |
| 151 | rem = (unsigned)len2; | |
| 152 | sum1 = adler1 & 0xffff; | |
| 153 | sum2 = rem * sum1; | |
| 154 | MOD(sum2); | |
| 155 | sum1 += (adler2 & 0xffff) + BASE - 1; | |
| 156 | sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; | |
| 157 | if (sum1 >= BASE) sum1 -= BASE; | |
| 158 | if (sum1 >= BASE) sum1 -= BASE; | |
| 159 | if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1); | |
| 160 | if (sum2 >= BASE) sum2 -= BASE; | |
| 161 | return sum1 | (sum2 << 16); | |
| 149 | /* the derivation of this formula is left as an exercise for the reader */ | |
| 150 | MOD63(len2); /* assumes len2 >= 0 */ | |
| 151 | rem = (unsigned)len2; | |
| 152 | sum1 = adler1 & 0xffff; | |
| 153 | sum2 = rem * sum1; | |
| 154 | MOD(sum2); | |
| 155 | sum1 += (adler2 & 0xffff) + BASE - 1; | |
| 156 | sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; | |
| 157 | if (sum1 >= BASE) sum1 -= BASE; | |
| 158 | if (sum1 >= BASE) sum1 -= BASE; | |
| 159 | if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1); | |
| 160 | if (sum2 >= BASE) sum2 -= BASE; | |
| 161 | return sum1 | (sum2 << 16); | |
| 162 | 162 | } |
| 163 | 163 | |
| 164 | 164 | /* ========================================================================= */ |
| 165 | 165 | uLong ZEXPORT adler32_combine(adler1, adler2, len2) |
| 166 | uLong adler1; | |
| 167 | uLong adler2; | |
| 168 | z_off_t len2; | |
| 166 | uLong adler1; | |
| 167 | uLong adler2; | |
| 168 | z_off_t len2; | |
| 169 | 169 | { |
| 170 | ||
| 170 | return adler32_combine_(adler1, adler2, len2); | |
| 171 | 171 | } |
| 172 | 172 | |
| 173 | 173 | uLong ZEXPORT adler32_combine64(adler1, adler2, len2) |
| 174 | uLong adler1; | |
| 175 | uLong adler2; | |
| 176 | z_off64_t len2; | |
| 174 | uLong adler1; | |
| 175 | uLong adler2; | |
| 176 | z_off64_t len2; | |
| 177 | 177 | { |
| 178 | ||
| 178 | return adler32_combine_(adler1, adler2, len2); | |
| 179 | 179 | } |
| r25360 | r25361 | |
|---|---|---|
| 32 | 32 | const char *version; |
| 33 | 33 | int stream_size; |
| 34 | 34 | { |
| 35 | ||
| 35 | struct inflate_state FAR *state; | |
| 36 | 36 | |
| 37 | if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || | |
| 38 | stream_size != (int)(sizeof(z_stream))) | |
| 39 | return Z_VERSION_ERROR; | |
| 40 | if (strm == Z_NULL || window == Z_NULL || | |
| 41 | windowBits < 8 || windowBits > 15) | |
| 42 | return Z_STREAM_ERROR; | |
| 43 | strm->msg = Z_NULL; /* in case we return an error */ | |
| 44 | if (strm->zalloc == (alloc_func)0) { | |
| 37 | if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || | |
| 38 | stream_size != (int)(sizeof(z_stream))) | |
| 39 | return Z_VERSION_ERROR; | |
| 40 | if (strm == Z_NULL || window == Z_NULL || | |
| 41 | windowBits < 8 || windowBits > 15) | |
| 42 | return Z_STREAM_ERROR; | |
| 43 | strm->msg = Z_NULL; /* in case we return an error */ | |
| 44 | if (strm->zalloc == (alloc_func)0) { | |
| 45 | 45 | #ifdef Z_SOLO |
| 46 | ||
| 46 | return Z_STREAM_ERROR; | |
| 47 | 47 | #else |
| 48 | strm->zalloc = zcalloc; | |
| 49 | strm->opaque = (voidpf)0; | |
| 48 | strm->zalloc = zcalloc; | |
| 49 | strm->opaque = (voidpf)0; | |
| 50 | 50 | #endif |
| 51 | } | |
| 52 | if (strm->zfree == (free_func)0) | |
| 51 | } | |
| 52 | if (strm->zfree == (free_func)0) | |
| 53 | 53 | #ifdef Z_SOLO |
| 54 | ||
| 54 | return Z_STREAM_ERROR; | |
| 55 | 55 | #else |
| 56 | ||
| 56 | strm->zfree = zcfree; | |
| 57 | 57 | #endif |
| 58 | state = (struct inflate_state FAR *)ZALLOC(strm, 1, | |
| 59 | sizeof(struct inflate_state)); | |
| 60 | if (state == Z_NULL) return Z_MEM_ERROR; | |
| 61 | Tracev((stderr, "inflate: allocated\n")); | |
| 62 | strm->state = (struct internal_state FAR *)state; | |
| 63 | state->dmax = 32768U; | |
| 64 | state->wbits = windowBits; | |
| 65 | state->wsize = 1U << windowBits; | |
| 66 | state->window = window; | |
| 67 | state->wnext = 0; | |
| 68 | state->whave = 0; | |
| 69 | return Z_OK; | |
| 58 | state = (struct inflate_state FAR *)ZALLOC(strm, 1, | |
| 59 | sizeof(struct inflate_state)); | |
| 60 | if (state == Z_NULL) return Z_MEM_ERROR; | |
| 61 | Tracev((stderr, "inflate: allocated\n")); | |
| 62 | strm->state = (struct internal_state FAR *)state; | |
| 63 | state->dmax = 32768U; | |
| 64 | state->wbits = windowBits; | |
| 65 | state->wsize = 1U << windowBits; | |
| 66 | state->window = window; | |
| 67 | state->wnext = 0; | |
| 68 | state->whave = 0; | |
| 69 | return Z_OK; | |
| 70 | 70 | } |
| 71 | 71 | |
| 72 | 72 | /* |
| r25360 | r25361 | |
| 83 | 83 | struct inflate_state FAR *state; |
| 84 | 84 | { |
| 85 | 85 | #ifdef BUILDFIXED |
| 86 | static int virgin = 1; | |
| 87 | static code *lenfix, *distfix; | |
| 88 | static code fixed[544]; | |
| 86 | static int virgin = 1; | |
| 87 | static code *lenfix, *distfix; | |
| 88 | static code fixed[544]; | |
| 89 | 89 | |
| 90 | /* build fixed huffman tables if first call (may not be thread safe) */ | |
| 91 | if (virgin) { | |
| 92 | unsigned sym, bits; | |
| 93 | static code *next; | |
| 90 | /* build fixed huffman tables if first call (may not be thread safe) */ | |
| 91 | if (virgin) { | |
| 92 | unsigned sym, bits; | |
| 93 | static code *next; | |
| 94 | 94 | |
| 95 | /* literal/length table */ | |
| 96 | sym = 0; | |
| 97 | while (sym < 144) state->lens[sym++] = 8; | |
| 98 | while (sym < 256) state->lens[sym++] = 9; | |
| 99 | while (sym < 280) state->lens[sym++] = 7; | |
| 100 | while (sym < 288) state->lens[sym++] = 8; | |
| 101 | next = fixed; | |
| 102 | lenfix = next; | |
| 103 | bits = 9; | |
| 104 | inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); | |
| 95 | /* literal/length table */ | |
| 96 | sym = 0; | |
| 97 | while (sym < 144) state->lens[sym++] = 8; | |
| 98 | while (sym < 256) state->lens[sym++] = 9; | |
| 99 | while (sym < 280) state->lens[sym++] = 7; | |
| 100 | while (sym < 288) state->lens[sym++] = 8; | |
| 101 | next = fixed; | |
| 102 | lenfix = next; | |
| 103 | bits = 9; | |
| 104 | inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); | |
| 105 | 105 | |
| 106 | /* distance table */ | |
| 107 | sym = 0; | |
| 108 | while (sym < 32) state->lens[sym++] = 5; | |
| 109 | distfix = next; | |
| 110 | bits = 5; | |
| 111 | inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); | |
| 106 | /* distance table */ | |
| 107 | sym = 0; | |
| 108 | while (sym < 32) state->lens[sym++] = 5; | |
| 109 | distfix = next; | |
| 110 | bits = 5; | |
| 111 | inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); | |
| 112 | 112 | |
| 113 | /* do this just once */ | |
| 114 | virgin = 0; | |
| 115 | } | |
| 113 | /* do this just once */ | |
| 114 | virgin = 0; | |
| 115 | } | |
| 116 | 116 | #else /* !BUILDFIXED */ |
| 117 | 117 | # include "inffixed.h" |
| 118 | 118 | #endif /* BUILDFIXED */ |
| 119 | state->lencode = lenfix; | |
| 120 | state->lenbits = 9; | |
| 121 | state->distcode = distfix; | |
| 122 | state->distbits = 5; | |
| 119 | state->lencode = lenfix; | |
| 120 | state->lenbits = 9; | |
| 121 | state->distcode = distfix; | |
| 122 | state->distbits = 5; | |
| 123 | 123 | } |
| 124 | 124 | |
| 125 | 125 | /* Macros for inflateBack(): */ |
| 126 | 126 | |
| 127 | 127 | /* Load returned state from inflate_fast() */ |
| 128 | 128 | #define LOAD() \ |
| 129 | do { \ | |
| 130 | put = strm->next_out; \ | |
| 131 | left = strm->avail_out; \ | |
| 132 | next = strm->next_in; \ | |
| 133 | have = strm->avail_in; \ | |
| 134 | hold = state->hold; \ | |
| 135 | bits = state->bits; \ | |
| 136 | } while (0) | |
| 129 | do { \ | |
| 130 | put = strm->next_out; \ | |
| 131 | left = strm->avail_out; \ | |
| 132 | next = strm->next_in; \ | |
| 133 | have = strm->avail_in; \ | |
| 134 | hold = state->hold; \ | |
| 135 | bits = state->bits; \ | |
| 136 | } while (0) | |
| 137 | 137 | |
| 138 | 138 | /* Set state from registers for inflate_fast() */ |
| 139 | 139 | #define RESTORE() \ |
| 140 | do { \ | |
| 141 | strm->next_out = put; \ | |
| 142 | strm->avail_out = left; \ | |
| 143 | strm->next_in = next; \ | |
| 144 | strm->avail_in = have; \ | |
| 145 | state->hold = hold; \ | |
| 146 | state->bits = bits; \ | |
| 147 | } while (0) | |
| 140 | do { \ | |
| 141 | strm->next_out = put; \ | |
| 142 | strm->avail_out = left; \ | |
| 143 | strm->next_in = next; \ | |
| 144 | strm->avail_in = have; \ | |
| 145 | state->hold = hold; \ | |
| 146 | state->bits = bits; \ | |
| 147 | } while (0) | |
| 148 | 148 | |
| 149 | 149 | /* Clear the input bit accumulator */ |
| 150 | 150 | #define INITBITS() \ |
| 151 | do { \ | |
| 152 | hold = 0; \ | |
| 153 | bits = 0; \ | |
| 154 | } while (0) | |
| 151 | do { \ | |
| 152 | hold = 0; \ | |
| 153 | bits = 0; \ | |
| 154 | } while (0) | |
| 155 | 155 | |
| 156 | 156 | /* Assure that some input is available. If input is requested, but denied, |
| 157 | 157 | then return a Z_BUF_ERROR from inflateBack(). */ |
| 158 | 158 | #define PULL() \ |
| 159 | do { \ | |
| 160 | if (have == 0) { \ | |
| 161 | have = in(in_desc, &next); \ | |
| 162 | if (have == 0) { \ | |
| 163 | next = Z_NULL; \ | |
| 164 | ret = Z_BUF_ERROR; \ | |
| 165 | goto inf_leave; \ | |
| 166 | } \ | |
| 167 | } \ | |
| 168 | } while (0) | |
| 159 | do { \ | |
| 160 | if (have == 0) { \ | |
| 161 | have = in(in_desc, &next); \ | |
| 162 | if (have == 0) { \ | |
| 163 | next = Z_NULL; \ | |
| 164 | ret = Z_BUF_ERROR; \ | |
| 165 | goto inf_leave; \ | |
| 166 | } \ | |
| 167 | } \ | |
| 168 | } while (0) | |
| 169 | 169 | |
| 170 | 170 | /* Get a byte of input into the bit accumulator, or return from inflateBack() |
| 171 | 171 | with an error if there is no input available. */ |
| 172 | 172 | #define PULLBYTE() \ |
| 173 | do { \ | |
| 174 | PULL(); \ | |
| 175 | have--; \ | |
| 176 | hold += (unsigned long)(*next++) << bits; \ | |
| 177 | bits += 8; \ | |
| 178 | } while (0) | |
| 173 | do { \ | |
| 174 | PULL(); \ | |
| 175 | have--; \ | |
| 176 | hold += (unsigned long)(*next++) << bits; \ | |
| 177 | bits += 8; \ | |
| 178 | } while (0) | |
| 179 | 179 | |
| 180 | 180 | /* Assure that there are at least n bits in the bit accumulator. If there is |
| 181 | 181 | not enough available input to do that, then return from inflateBack() with |
| 182 | 182 | an error. */ |
| 183 | 183 | #define NEEDBITS(n) \ |
| 184 | do { \ | |
| 185 | while (bits < (unsigned)(n)) \ | |
| 186 | PULLBYTE(); \ | |
| 187 | } while (0) | |
| 184 | do { \ | |
| 185 | while (bits < (unsigned)(n)) \ | |
| 186 | PULLBYTE(); \ | |
| 187 | } while (0) | |
| 188 | 188 | |
| 189 | 189 | /* Return the low n bits of the bit accumulator (n < 16) */ |
| 190 | 190 | #define BITS(n) \ |
| 191 | ||
| 191 | ((unsigned)hold & ((1U << (n)) - 1)) | |
| 192 | 192 | |
| 193 | 193 | /* Remove n bits from the bit accumulator */ |
| 194 | 194 | #define DROPBITS(n) \ |
| 195 | do { \ | |
| 196 | hold >>= (n); \ | |
| 197 | bits -= (unsigned)(n); \ | |
| 198 | } while (0) | |
| 195 | do { \ | |
| 196 | hold >>= (n); \ | |
| 197 | bits -= (unsigned)(n); \ | |
| 198 | } while (0) | |
| 199 | 199 | |
| 200 | 200 | /* Remove zero to seven bits as needed to go to a byte boundary */ |
| 201 | 201 | #define BYTEBITS() \ |
| 202 | do { \ | |
| 203 | hold >>= bits & 7; \ | |
| 204 | bits -= bits & 7; \ | |
| 205 | } while (0) | |
| 202 | do { \ | |
| 203 | hold >>= bits & 7; \ | |
| 204 | bits -= bits & 7; \ | |
| 205 | } while (0) | |
| 206 | 206 | |
| 207 | 207 | /* Assure that some output space is available, by writing out the window |
| 208 | 208 | if it's full. If the write fails, return from inflateBack() with a |
| 209 | 209 | Z_BUF_ERROR. */ |
| 210 | 210 | #define ROOM() \ |
| 211 | do { \ | |
| 212 | if (left == 0) { \ | |
| 213 | put = state->window; \ | |
| 214 | left = state->wsize; \ | |
| 215 | state->whave = left; \ | |
| 216 | if (out(out_desc, put, left)) { \ | |
| 217 | ret = Z_BUF_ERROR; \ | |
| 218 | goto inf_leave; \ | |
| 219 | } \ | |
| 220 | } \ | |
| 221 | } while (0) | |
| 211 | do { \ | |
| 212 | if (left == 0) { \ | |
| 213 | put = state->window; \ | |
| 214 | left = state->wsize; \ | |
| 215 | state->whave = left; \ | |
| 216 | if (out(out_desc, put, left)) { \ | |
| 217 | ret = Z_BUF_ERROR; \ | |
| 218 | goto inf_leave; \ | |
| 219 | } \ | |
| 220 | } \ | |
| 221 | } while (0) | |
| 222 | 222 | |
| 223 | 223 | /* |
| 224 | 224 | strm provides the memory allocation functions and window buffer on input, |
| r25360 | r25361 | |
| 254 | 254 | out_func out; |
| 255 | 255 | void FAR *out_desc; |
| 256 | 256 | { |
| 257 | struct inflate_state FAR *state; | |
| 258 | z_const unsigned char FAR *next; /* next input */ | |
| 259 | unsigned char FAR *put; /* next output */ | |
| 260 | unsigned have, left; /* available input and output */ | |
| 261 | unsigned long hold; /* bit buffer */ | |
| 262 | unsigned bits; /* bits in bit buffer */ | |
| 263 | unsigned copy; /* number of stored or match bytes to copy */ | |
| 264 | unsigned char FAR *from; /* where to copy match bytes from */ | |
| 265 | code here; /* current decoding table entry */ | |
| 266 | code last; /* parent table entry */ | |
| 267 | unsigned len; /* length to copy for repeats, bits to drop */ | |
| 268 | int ret; /* return code */ | |
| 269 | static const unsigned short order[19] = /* permutation of code lengths */ | |
| 270 | {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; | |
| 257 | struct inflate_state FAR *state; | |
| 258 | z_const unsigned char FAR *next; /* next input */ | |
| 259 | unsigned char FAR *put; /* next output */ | |
| 260 | unsigned have, left; /* available input and output */ | |
| 261 | unsigned long hold; /* bit buffer */ | |
| 262 | unsigned bits; /* bits in bit buffer */ | |
| 263 | unsigned copy; /* number of stored or match bytes to copy */ | |
| 264 | unsigned char FAR *from; /* where to copy match bytes from */ | |
| 265 | code here; /* current decoding table entry */ | |
| 266 | code last; /* parent table entry */ | |
| 267 | unsigned len; /* length to copy for repeats, bits to drop */ | |
| 268 | int ret; /* return code */ | |
| 269 | static const unsigned short order[19] = /* permutation of code lengths */ | |
| 270 | {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; | |
| 271 | 271 | |
| 272 | /* Check that the strm exists and that the state was initialized */ | |
| 273 | if (strm == Z_NULL || strm->state == Z_NULL) | |
| 274 | return Z_STREAM_ERROR; | |
| 275 | state = (struct inflate_state FAR *)strm->state; | |
| 272 | /* Check that the strm exists and that the state was initialized */ | |
| 273 | if (strm == Z_NULL || strm->state == Z_NULL) | |
| 274 | return Z_STREAM_ERROR; | |
| 275 | state = (struct inflate_state FAR *)strm->state; | |
| 276 | 276 | |
| 277 | /* Reset the state */ | |
| 278 | strm->msg = Z_NULL; | |
| 279 | state->mode = TYPE; | |
| 280 | state->last = 0; | |
| 281 | state->whave = 0; | |
| 282 | next = strm->next_in; | |
| 283 | have = next != Z_NULL ? strm->avail_in : 0; | |
| 284 | hold = 0; | |
| 285 | bits = 0; | |
| 286 | put = state->window; | |
| 287 | left = state->wsize; | |
| 277 | /* Reset the state */ | |
| 278 | strm->msg = Z_NULL; | |
| 279 | state->mode = TYPE; | |
| 280 | state->last = 0; | |
| 281 | state->whave = 0; | |
| 282 | next = strm->next_in; | |
| 283 | have = next != Z_NULL ? strm->avail_in : 0; | |
| 284 | hold = 0; | |
| 285 | bits = 0; | |
| 286 | put = state->window; | |
| 287 | left = state->wsize; | |
| 288 | 288 | |
| 289 | /* Inflate until end of block marked as last */ | |
| 290 | for (;;) | |
| 291 | switch (state->mode) { | |
| 292 | case TYPE: | |
| 293 | /* determine and dispatch block type */ | |
| 294 | if (state->last) { | |
| 295 | BYTEBITS(); | |
| 296 | state->mode = DONE; | |
| 297 | break; | |
| 298 | } | |
| 299 | NEEDBITS(3); | |
| 300 | state->last = BITS(1); | |
| 301 | DROPBITS(1); | |
| 302 | switch (BITS(2)) { | |
| 303 | case 0: /* stored block */ | |
| 304 | Tracev((stderr, "inflate: stored block%s\n", | |
| 305 | state->last ? " (last)" : "")); | |
| 306 | state->mode = STORED; | |
| 307 | break; | |
| 308 | case 1: /* fixed block */ | |
| 309 | fixedtables(state); | |
| 310 | Tracev((stderr, "inflate: fixed codes block%s\n", | |
| 311 | state->last ? " (last)" : "")); | |
| 312 | state->mode = LEN; /* decode codes */ | |
| 313 | break; | |
| 314 | case 2: /* dynamic block */ | |
| 315 | Tracev((stderr, "inflate: dynamic codes block%s\n", | |
| 316 | state->last ? " (last)" : "")); | |
| 317 | state->mode = TABLE; | |
| 318 | break; | |
| 319 | case 3: | |
| 320 | strm->msg = (char *)"invalid block type"; | |
| 321 | state->mode = BAD; | |
| 322 | } | |
| 323 | DROPBITS(2); | |
| 324 | break; | |
| 289 | /* Inflate until end of block marked as last */ | |
| 290 | for (;;) | |
| 291 | switch (state->mode) { | |
| 292 | case TYPE: | |
| 293 | /* determine and dispatch block type */ | |
| 294 | if (state->last) { | |
| 295 | BYTEBITS(); | |
| 296 | state->mode = DONE; | |
| 297 | break; | |
| 298 | } | |
| 299 | NEEDBITS(3); | |
| 300 | state->last = BITS(1); | |
| 301 | DROPBITS(1); | |
| 302 | switch (BITS(2)) { | |
| 303 | case 0: /* stored block */ | |
| 304 | Tracev((stderr, "inflate: stored block%s\n", | |
| 305 | state->last ? " (last)" : "")); | |
| 306 | state->mode = STORED; | |
| 307 | break; | |
| 308 | case 1: /* fixed block */ | |
| 309 | fixedtables(state); | |
| 310 | Tracev((stderr, "inflate: fixed codes block%s\n", | |
| 311 | state->last ? " (last)" : "")); | |
| 312 | state->mode = LEN; /* decode codes */ | |
| 313 | break; | |
| 314 | case 2: /* dynamic block */ | |
| 315 | Tracev((stderr, "inflate: dynamic codes block%s\n", | |
| 316 | state->last ? " (last)" : "")); | |
| 317 | state->mode = TABLE; | |
| 318 | break; | |
| 319 | case 3: | |
| 320 | strm->msg = (char *)"invalid block type"; | |
| 321 | state->mode = BAD; | |
| 322 | } | |
| 323 | DROPBITS(2); | |
| 324 | break; | |
| 325 | 325 | |
| 326 | case STORED: | |
| 327 | /* get and verify stored block length */ | |
| 328 | BYTEBITS(); /* go to byte boundary */ | |
| 329 | NEEDBITS(32); | |
| 330 | if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { | |
| 331 | strm->msg = (char *)"invalid stored block lengths"; | |
| 332 | state->mode = BAD; | |
| 333 | break; | |
| 334 | } | |
| 335 | state->length = (unsigned)hold & 0xffff; | |
| 336 | Tracev((stderr, "inflate: stored length %u\n", | |
| 337 | state->length)); | |
| 338 | INITBITS(); | |
| 326 | case STORED: | |
| 327 | /* get and verify stored block length */ | |
| 328 | BYTEBITS(); /* go to byte boundary */ | |
| 329 | NEEDBITS(32); | |
| 330 | if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { | |
| 331 | strm->msg = (char *)"invalid stored block lengths"; | |
| 332 | state->mode = BAD; | |
| 333 | break; | |
| 334 | } | |
| 335 | state->length = (unsigned)hold & 0xffff; | |
| 336 | Tracev((stderr, "inflate: stored length %u\n", | |
| 337 | state->length)); | |
| 338 | INITBITS(); | |
| 339 | 339 | |
| 340 | /* copy stored block from input to output */ | |
| 341 | while (state->length != 0) { | |
| 342 | copy = state->length; | |
| 343 | PULL(); | |
| 344 | ROOM(); | |
| 345 | if (copy > have) copy = have; | |
| 346 | if (copy > left) copy = left; | |
| 347 | zmemcpy(put, next, copy); | |
| 348 | have -= copy; | |
| 349 | next += copy; | |
| 350 | left -= copy; | |
| 351 | put += copy; | |
| 352 | state->length -= copy; | |
| 353 | } | |
| 354 | Tracev((stderr, "inflate: stored end\n")); | |
| 355 | state->mode = TYPE; | |
| 356 | break; | |
| 340 | /* copy stored block from input to output */ | |
| 341 | while (state->length != 0) { | |
| 342 | copy = state->length; | |
| 343 | PULL(); | |
| 344 | ROOM(); | |
| 345 | if (copy > have) copy = have; | |
| 346 | if (copy > left) copy = left; | |
| 347 | zmemcpy(put, next, copy); | |
| 348 | have -= copy; | |
| 349 | next += copy; | |
| 350 | left -= copy; | |
| 351 | put += copy; | |
| 352 | state->length -= copy; | |
| 353 | } | |
| 354 | Tracev((stderr, "inflate: stored end\n")); | |
| 355 | state->mode = TYPE; | |
| 356 | break; | |
| 357 | 357 | |
| 358 | case TABLE: | |
| 359 | /* get dynamic table entries descriptor */ | |
| 360 | NEEDBITS(14); | |
| 361 | state->nlen = BITS(5) + 257; | |
| 362 | DROPBITS(5); | |
| 363 | state->ndist = BITS(5) + 1; | |
| 364 | DROPBITS(5); | |
| 365 | state->ncode = BITS(4) + 4; | |
| 366 | DROPBITS(4); | |
| 358 | case TABLE: | |
| 359 | /* get dynamic table entries descriptor */ | |
| 360 | NEEDBITS(14); | |
| 361 | state->nlen = BITS(5) + 257; | |
| 362 | DROPBITS(5); | |
| 363 | state->ndist = BITS(5) + 1; | |
| 364 | DROPBITS(5); | |
| 365 | state->ncode = BITS(4) + 4; | |
| 366 | DROPBITS(4); | |
| 367 | 367 | #ifndef PKZIP_BUG_WORKAROUND |
| 368 | if (state->nlen > 286 || state->ndist > 30) { | |
| 369 | strm->msg = (char *)"too many length or distance symbols"; | |
| 370 | state->mode = BAD; | |
| 371 | break; | |
| 372 | } | |
| 368 | if (state->nlen > 286 || state->ndist > 30) { | |
| 369 | strm->msg = (char *)"too many length or distance symbols"; | |
| 370 | state->mode = BAD; | |
| 371 | break; | |
| 372 | } | |
| 373 | 373 | #endif |
| 374 | ||
| 374 | Tracev((stderr, "inflate: table sizes ok\n")); | |
| 375 | 375 | |
| 376 | /* get code length code lengths (not a typo) */ | |
| 377 | state->have = 0; | |
| 378 | while (state->have < state->ncode) { | |
| 379 | NEEDBITS(3); | |
| 380 | state->lens[order[state->have++]] = (unsigned short)BITS(3); | |
| 381 | DROPBITS(3); | |
| 382 | } | |
| 383 | while (state->have < 19) | |
| 384 | state->lens[order[state->have++]] = 0; | |
| 385 | state->next = state->codes; | |
| 386 | state->lencode = (code const FAR *)(state->next); | |
| 387 | state->lenbits = 7; | |
| 388 | ret = inflate_table(CODES, state->lens, 19, &(state->next), | |
| 389 | &(state->lenbits), state->work); | |
| 390 | if (ret) { | |
| 391 | strm->msg = (char *)"invalid code lengths set"; | |
| 392 | state->mode = BAD; | |
| 393 | break; | |
| 394 | } | |
| 395 | Tracev((stderr, "inflate: code lengths ok\n")); | |
| 376 | /* get code length code lengths (not a typo) */ | |
| 377 | state->have = 0; | |
| 378 | while (state->have < state->ncode) { | |
| 379 | NEEDBITS(3); | |
| 380 | state->lens[order[state->have++]] = (unsigned short)BITS(3); | |
| 381 | DROPBITS(3); | |
| 382 | } | |
| 383 | while (state->have < 19) | |
| 384 | state->lens[order[state->have++]] = 0; | |
| 385 | state->next = state->codes; | |
| 386 | state->lencode = (code const FAR *)(state->next); | |
| 387 | state->lenbits = 7; | |
| 388 | ret = inflate_table(CODES, state->lens, 19, &(state->next), | |
| 389 | &(state->lenbits), state->work); | |
| 390 | if (ret) { | |
| 391 | strm->msg = (char *)"invalid code lengths set"; | |
| 392 | state->mode = BAD; | |
| 393 | break; | |
| 394 | } | |
| 395 | Tracev((stderr, "inflate: code lengths ok\n")); | |
| 396 | 396 | |
| 397 | /* get length and distance code code lengths */ | |
| 398 | state->have = 0; | |
| 399 | while (state->have < state->nlen + state->ndist) { | |
| 400 | for (;;) { | |
| 401 | here = state->lencode[BITS(state->lenbits)]; | |
| 402 | if ((unsigned)(here.bits) <= bits) break; | |
| 403 | PULLBYTE(); | |
| 404 | } | |
| 405 | if (here.val < 16) { | |
| 406 | DROPBITS(here.bits); | |
| 407 | state->lens[state->have++] = here.val; | |
| 408 | } | |
| 409 | else { | |
| 410 | if (here.val == 16) { | |
| 411 | NEEDBITS(here.bits + 2); | |
| 412 | DROPBITS(here.bits); | |
| 413 | if (state->have == 0) { | |
| 414 | strm->msg = (char *)"invalid bit length repeat"; | |
| 415 | state->mode = BAD; | |
| 416 | break; | |
| 417 | } | |
| 418 | len = (unsigned)(state->lens[state->have - 1]); | |
| 419 | copy = 3 + BITS(2); | |
| 420 | DROPBITS(2); | |
| 421 | } | |
| 422 | else if (here.val == 17) { | |
| 423 | NEEDBITS(here.bits + 3); | |
| 424 | DROPBITS(here.bits); | |
| 425 | len = 0; | |
| 426 | copy = 3 + BITS(3); | |
| 427 | DROPBITS(3); | |
| 428 | } | |
| 429 | else { | |
| 430 | NEEDBITS(here.bits + 7); | |
| 431 | DROPBITS(here.bits); | |
| 432 | len = 0; | |
| 433 | copy = 11 + BITS(7); | |
| 434 | DROPBITS(7); | |
| 435 | } | |
| 436 | if (state->have + copy > state->nlen + state->ndist) { | |
| 437 | strm->msg = (char *)"invalid bit length repeat"; | |
| 438 | state->mode = BAD; | |
| 439 | break; | |
| 440 | } | |
| 441 | while (copy--) | |
| 442 | state->lens[state->have++] = (unsigned short)len; | |
| 443 | } | |
| 444 | } | |
| 397 | /* get length and distance code code lengths */ | |
| 398 | state->have = 0; | |
| 399 | while (state->have < state->nlen + state->ndist) { | |
| 400 | for (;;) { | |
| 401 | here = state->lencode[BITS(state->lenbits)]; | |
| 402 | if ((unsigned)(here.bits) <= bits) break; | |
| 403 | PULLBYTE(); | |
| 404 | } | |
| 405 | if (here.val < 16) { | |
| 406 | DROPBITS(here.bits); | |
| 407 | state->lens[state->have++] = here.val; | |
| 408 | } | |
| 409 | else { | |
| 410 | if (here.val == 16) { | |
| 411 | NEEDBITS(here.bits + 2); | |
| 412 | DROPBITS(here.bits); | |
| 413 | if (state->have == 0) { | |
| 414 | strm->msg = (char *)"invalid bit length repeat"; | |
| 415 | state->mode = BAD; | |
| 416 | break; | |
| 417 | } | |
| 418 | len = (unsigned)(state->lens[state->have - 1]); | |
| 419 | copy = 3 + BITS(2); | |
| 420 | DROPBITS(2); | |
| 421 | } | |
| 422 | else if (here.val == 17) { | |
| 423 | NEEDBITS(here.bits + 3); | |
| 424 | DROPBITS(here.bits); | |
| 425 | len = 0; | |
| 426 | copy = 3 + BITS(3); | |
| 427 | DROPBITS(3); | |
| 428 | } | |
| 429 | else { | |
| 430 | NEEDBITS(here.bits + 7); | |
| 431 | DROPBITS(here.bits); | |
| 432 | len = 0; | |
| 433 | copy = 11 + BITS(7); | |
| 434 | DROPBITS(7); | |
| 435 | } | |
| 436 | if (state->have + copy > state->nlen + state->ndist) { | |
| 437 | strm->msg = (char *)"invalid bit length repeat"; | |
| 438 | state->mode = BAD; | |
| 439 | break; | |
| 440 | } | |
| 441 | while (copy--) | |
| 442 | state->lens[state->have++] = (unsigned short)len; | |
| 443 | } | |
| 444 | } | |
| 445 | 445 | |
| 446 | /* handle error breaks in while */ | |
| 447 | if (state->mode == BAD) break; | |
| 446 | /* handle error breaks in while */ | |
| 447 | if (state->mode == BAD) break; | |
| 448 | 448 | |
| 449 | /* check for end-of-block code (better have one) */ | |
| 450 | if (state->lens[256] == 0) { | |
| 451 | strm->msg = (char *)"invalid code -- missing end-of-block"; | |
| 452 | state->mode = BAD; | |
| 453 | break; | |
| 454 | } | |
| 449 | /* check for end-of-block code (better have one) */ | |
| 450 | if (state->lens[256] == 0) { | |
| 451 | strm->msg = (char *)"invalid code -- missing end-of-block"; | |
| 452 | state->mode = BAD; | |
| 453 | break; | |
| 454 | } | |
| 455 | 455 | |
| 456 | /* build code tables -- note: do not change the lenbits or distbits | |
| 457 | values here (9 and 6) without reading the comments in inftrees.h | |
| 458 | concerning the ENOUGH constants, which depend on those values */ | |
| 459 | state->next = state->codes; | |
| 460 | state->lencode = (code const FAR *)(state->next); | |
| 461 | state->lenbits = 9; | |
| 462 | ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), | |
| 463 | &(state->lenbits), state->work); | |
| 464 | if (ret) { | |
| 465 | strm->msg = (char *)"invalid literal/lengths set"; | |
| 466 | state->mode = BAD; | |
| 467 | break; | |
| 468 | } | |
| 469 | state->distcode = (code const FAR *)(state->next); | |
| 470 | state->distbits = 6; | |
| 471 | ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, | |
| 472 | &(state->next), &(state->distbits), state->work); | |
| 473 | if (ret) { | |
| 474 | strm->msg = (char *)"invalid distances set"; | |
| 475 | state->mode = BAD; | |
| 476 | break; | |
| 477 | } | |
| 478 | Tracev((stderr, "inflate: codes ok\n")); | |
| 479 | state->mode = LEN; | |
| 456 | /* build code tables -- note: do not change the lenbits or distbits | |
| 457 | values here (9 and 6) without reading the comments in inftrees.h | |
| 458 | concerning the ENOUGH constants, which depend on those values */ | |
| 459 | state->next = state->codes; | |
| 460 | state->lencode = (code const FAR *)(state->next); | |
| 461 | state->lenbits = 9; | |
| 462 | ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), | |
| 463 | &(state->lenbits), state->work); | |
| 464 | if (ret) { | |
| 465 | strm->msg = (char *)"invalid literal/lengths set"; | |
| 466 | state->mode = BAD; | |
| 467 | break; | |
| 468 | } | |
| 469 | state->distcode = (code const FAR *)(state->next); | |
| 470 | state->distbits = 6; | |
| 471 | ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, | |
| 472 | &(state->next), &(state->distbits), state->work); | |
| 473 | if (ret) { | |
| 474 | strm->msg = (char *)"invalid distances set"; | |
| 475 | state->mode = BAD; | |
| 476 | break; | |
| 477 | } | |
| 478 | Tracev((stderr, "inflate: codes ok\n")); | |
| 479 | state->mode = LEN; | |
| 480 | 480 | |
| 481 | case LEN: | |
| 482 | /* use inflate_fast() if we have enough input and output */ | |
| 483 | if (have >= 6 && left >= 258) { | |
| 484 | RESTORE(); | |
| 485 | if (state->whave < state->wsize) | |
| 486 | state->whave = state->wsize - left; | |
| 487 | inflate_fast(strm, state->wsize); | |
| 488 | LOAD(); | |
| 489 | break; | |
| 490 | } | |
| 481 | case LEN: | |
| 482 | /* use inflate_fast() if we have enough input and output */ | |
| 483 | if (have >= 6 && left >= 258) { | |
| 484 | RESTORE(); | |
| 485 | if (state->whave < state->wsize) | |
| 486 | state->whave = state->wsize - left; | |
| 487 | inflate_fast(strm, state->wsize); | |
| 488 | LOAD(); | |
| 489 | break; | |
| 490 | } | |
| 491 | 491 | |
| 492 | /* get a literal, length, or end-of-block code */ | |
| 493 | for (;;) { | |
| 494 | here = state->lencode[BITS(state->lenbits)]; | |
| 495 | if ((unsigned)(here.bits) <= bits) break; | |
| 496 | PULLBYTE(); | |
| 497 | } | |
| 498 | if (here.op && (here.op & 0xf0) == 0) { | |
| 499 | last = here; | |
| 500 | for (;;) { | |
| 501 | here = state->lencode[last.val + | |
| 502 | (BITS(last.bits + last.op) >> last.bits)]; | |
| 503 | if ((unsigned)(last.bits + here.bits) <= bits) break; | |
| 504 | PULLBYTE(); | |
| 505 | } | |
| 506 | DROPBITS(last.bits); | |
| 507 | } | |
| 508 | DROPBITS(here.bits); | |
| 509 | state->length = (unsigned)here.val; | |
| 492 | /* get a literal, length, or end-of-block code */ | |
| 493 | for (;;) { | |
| 494 | here = state->lencode[BITS(state->lenbits)]; | |
| 495 | if ((unsigned)(here.bits) <= bits) break; | |
| 496 | PULLBYTE(); | |
| 497 | } | |
| 498 | if (here.op && (here.op & 0xf0) == 0) { | |
| 499 | last = here; | |
| 500 | for (;;) { | |
| 501 | here = state->lencode[last.val + | |
| 502 | (BITS(last.bits + last.op) >> last.bits)]; | |
| 503 | if ((unsigned)(last.bits + here.bits) <= bits) break; | |
| 504 | PULLBYTE(); | |
| 505 | } | |
| 506 | DROPBITS(last.bits); | |
| 507 | } | |
| 508 | DROPBITS(here.bits); | |
| 509 | state->length = (unsigned)here.val; | |
| 510 | 510 | |
| 511 | /* process literal */ | |
| 512 | if (here.op == 0) { | |
| 513 | Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? | |
| 514 | "inflate: literal '%c'\n" : | |
| 515 | "inflate: literal 0x%02x\n", here.val)); | |
| 516 | ROOM(); | |
| 517 | *put++ = (unsigned char)(state->length); | |
| 518 | left--; | |
| 519 | state->mode = LEN; | |
| 520 | break; | |
| 521 | } | |
| 511 | /* process literal */ | |
| 512 | if (here.op == 0) { | |
| 513 | Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? | |
| 514 | "inflate: literal '%c'\n" : | |
| 515 | "inflate: literal 0x%02x\n", here.val)); | |
| 516 | ROOM(); | |
| 517 | *put++ = (unsigned char)(state->length); | |
| 518 | left--; | |
| 519 | state->mode = LEN; | |
| 520 | break; | |
| 521 | } | |
| 522 | 522 | |
| 523 | /* process end of block */ | |
| 524 | if (here.op & 32) { | |
| 525 | Tracevv((stderr, "inflate: end of block\n")); | |
| 526 | state->mode = TYPE; | |
| 527 | break; | |
| 528 | } | |
| 523 | /* process end of block */ | |
| 524 | if (here.op & 32) { | |
| 525 | Tracevv((stderr, "inflate: end of block\n")); | |
| 526 | state->mode = TYPE; | |
| 527 | break; | |
| 528 | } | |
| 529 | 529 | |
| 530 | /* invalid code */ | |
| 531 | if (here.op & 64) { | |
| 532 | strm->msg = (char *)"invalid literal/length code"; | |
| 533 | state->mode = BAD; | |
| 534 | break; | |
| 535 | } | |
| 530 | /* invalid code */ | |
| 531 | if (here.op & 64) { | |
| 532 | strm->msg = (char *)"invalid literal/length code"; | |
| 533 | state->mode = BAD; | |
| 534 | break; | |
| 535 | } | |
| 536 | 536 | |
| 537 | /* length code -- get extra bits, if any */ | |
| 538 | state->extra = (unsigned)(here.op) & 15; | |
| 539 | if (state->extra != 0) { | |
| 540 | NEEDBITS(state->extra); | |
| 541 | state->length += BITS(state->extra); | |
| 542 | DROPBITS(state->extra); | |
| 543 | } | |
| 544 | Tracevv((stderr, "inflate: length %u\n", state->length)); | |
| 537 | /* length code -- get extra bits, if any */ | |
| 538 | state->extra = (unsigned)(here.op) & 15; | |
| 539 | if (state->extra != 0) { | |
| 540 | NEEDBITS(state->extra); | |
| 541 | state->length += BITS(state->extra); | |
| 542 | DROPBITS(state->extra); | |
| 543 | } | |
| 544 | Tracevv((stderr, "inflate: length %u\n", state->length)); | |
| 545 | 545 | |
| 546 | /* get distance code */ | |
| 547 | for (;;) { | |
| 548 | here = state->distcode[BITS(state->distbits)]; | |
| 549 | if ((unsigned)(here.bits) <= bits) break; | |
| 550 | PULLBYTE(); | |
| 551 | } | |
| 552 | if ((here.op & 0xf0) == 0) { | |
| 553 | last = here; | |
| 554 | for (;;) { | |
| 555 | here = state->distcode[last.val + | |
| 556 | (BITS(last.bits + last.op) >> last.bits)]; | |
| 557 | if ((unsigned)(last.bits + here.bits) <= bits) break; | |
| 558 | PULLBYTE(); | |
| 559 | } | |
| 560 | DROPBITS(last.bits); | |
| 561 | } | |
| 562 | DROPBITS(here.bits); | |
| 563 | if (here.op & 64) { | |
| 564 | strm->msg = (char *)"invalid distance code"; | |
| 565 | state->mode = BAD; | |
| 566 | break; | |
| 567 | } | |
| 568 | state->offset = (unsigned)here.val; | |
| 546 | /* get distance code */ | |
| 547 | for (;;) { | |
| 548 | here = state->distcode[BITS(state->distbits)]; | |
| 549 | if ((unsigned)(here.bits) <= bits) break; | |
| 550 | PULLBYTE(); | |
| 551 | } | |
| 552 | if ((here.op & 0xf0) == 0) { | |
| 553 | last = here; | |
| 554 | for (;;) { | |
| 555 | here = state->distcode[last.val + | |
| 556 | (BITS(last.bits + last.op) >> last.bits)]; | |
| 557 | if ((unsigned)(last.bits + here.bits) <= bits) break; | |
| 558 | PULLBYTE(); | |
| 559 | } | |
| 560 | DROPBITS(last.bits); | |
| 561 | } | |
| 562 | DROPBITS(here.bits); | |
| 563 | if (here.op & 64) { | |
| 564 | strm->msg = (char *)"invalid distance code"; | |
| 565 | state->mode = BAD; | |
| 566 | break; | |
| 567 | } | |
| 568 | state->offset = (unsigned)here.val; | |
| 569 | 569 | |
| 570 | /* get distance extra bits, if any */ | |
| 571 | state->extra = (unsigned)(here.op) & 15; | |
| 572 | if (state->extra != 0) { | |
| 573 | NEEDBITS(state->extra); | |
| 574 | state->offset += BITS(state->extra); | |
| 575 | DROPBITS(state->extra); | |
| 576 | } | |
| 577 | if (state->offset > state->wsize - (state->whave < state->wsize ? | |
| 578 | left : 0)) { | |
| 579 | strm->msg = (char *)"invalid distance too far back"; | |
| 580 | state->mode = BAD; | |
| 581 | break; | |
| 582 | } | |
| 583 | Tracevv((stderr, "inflate: distance %u\n", state->offset)); | |
| 570 | /* get distance extra bits, if any */ | |
| 571 | state->extra = (unsigned)(here.op) & 15; | |
| 572 | if (state->extra != 0) { | |
| 573 | NEEDBITS(state->extra); | |
| 574 | state->offset += BITS(state->extra); | |
| 575 | DROPBITS(state->extra); | |
| 576 | } | |
| 577 | if (state->offset > state->wsize - (state->whave < state->wsize ? | |
| 578 | left : 0)) { | |
| 579 | strm->msg = (char *)"invalid distance too far back"; | |
| 580 | state->mode = BAD; | |
| 581 | break; | |
| 582 | } | |
| 583 | Tracevv((stderr, "inflate: distance %u\n", state->offset)); | |
| 584 | 584 | |
| 585 | /* copy match from window to output */ | |
| 586 | do { | |
| 587 | ROOM(); | |
| 588 | copy = state->wsize - state->offset; | |
| 589 | if (copy < left) { | |
| 590 | from = put + copy; | |
| 591 | copy = left - copy; | |
| 592 | } | |
| 593 | else { | |
| 594 | from = put - state->offset; | |
| 595 | copy = left; | |
| 596 | } | |
| 597 | if (copy > state->length) copy = state->length; | |
| 598 | state->length -= copy; | |
| 599 | left -= copy; | |
| 600 | do { | |
| 601 | *put++ = *from++; | |
| 602 | } while (--copy); | |
| 603 | } while (state->length != 0); | |
| 604 | break; | |
| 585 | /* copy match from window to output */ | |
| 586 | do { | |
| 587 | ROOM(); | |
| 588 | copy = state->wsize - state->offset; | |
| 589 | if (copy < left) { | |
| 590 | from = put + copy; | |
| 591 | copy = left - copy; | |
| 592 | } | |
| 593 | else { | |
| 594 | from = put - state->offset; | |
| 595 | copy = left; | |
| 596 | } | |
| 597 | if (copy > state->length) copy = state->length; | |
| 598 | state->length -= copy; | |
| 599 | left -= copy; | |
| 600 | do { | |
| 601 | *put++ = *from++; | |
| 602 | } while (--copy); | |
| 603 | } while (state->length != 0); | |
| 604 | break; | |
| 605 | 605 | |
| 606 | case DONE: | |
| 607 | /* inflate stream terminated properly -- write leftover output */ | |
| 608 | ret = Z_STREAM_END; | |
| 609 | if (left < state->wsize) { | |
| 610 | if (out(out_desc, state->window, state->wsize - left)) | |
| 611 | ret = Z_BUF_ERROR; | |
| 612 | } | |
| 613 | goto inf_leave; | |
| 606 | case DONE: | |
| 607 | /* inflate stream terminated properly -- write leftover output */ | |
| 608 | ret = Z_STREAM_END; | |
| 609 | if (left < state->wsize) { | |
| 610 | if (out(out_desc, state->window, state->wsize - left)) | |
| 611 | ret = Z_BUF_ERROR; | |
| 612 | } | |
| 613 | goto inf_leave; | |
| 614 | 614 | |
| 615 | case BAD: | |
| 616 | ret = Z_DATA_ERROR; | |
| 617 | goto inf_leave; | |
| 615 | case BAD: | |
| 616 | ret = Z_DATA_ERROR; | |
| 617 | goto inf_leave; | |
| 618 | 618 | |
| 619 | default: /* can't happen, but makes compilers happy */ | |
| 620 | ret = Z_STREAM_ERROR; | |
| 621 | goto inf_leave; | |
| 622 | } | |
| 619 | default: /* can't happen, but makes compilers happy */ | |
| 620 | ret = Z_STREAM_ERROR; | |
| 621 | goto inf_leave; | |
| 622 | } | |
| 623 | 623 | |
| 624 | /* Return unused input */ | |
| 625 | inf_leave: | |
| 626 | strm->next_in = next; | |
| 627 | strm->avail_in = have; | |
| 628 | return ret; | |
| 624 | /* Return unused input */ | |
| 625 | inf_leave: | |
| 626 | strm->next_in = next; | |
| 627 | strm->avail_in = have; | |
| 628 | return ret; | |
| 629 | 629 | } |
| 630 | 630 | |
| 631 | 631 | int ZEXPORT inflateBackEnd(strm) |
| 632 | 632 | z_streamp strm; |
| 633 | 633 | { |
| 634 | if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) | |
| 635 | return Z_STREAM_ERROR; | |
| 636 | ZFREE(strm, strm->state); | |
| 637 | strm->state = Z_NULL; | |
| 638 | Tracev((stderr, "inflate: end\n")); | |
| 639 | return Z_OK; | |
| 634 | if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) | |
| 635 | return Z_STREAM_ERROR; | |
| 636 | ZFREE(strm, strm->state); | |
| 637 | strm->state = Z_NULL; | |
| 638 | Tracev((stderr, "inflate: end\n")); | |
| 639 | return Z_OK; | |
| 640 | 640 | } |
| r25360 | r25361 | |
|---|---|---|
| 1 | /* inffixed.h -- table for decoding fixed codes | |
| 2 | * Generated automatically by makefixed(). | |
| 3 | */ | |
| 1 | /* inffixed.h -- table for decoding fixed codes | |
| 2 | * Generated automatically by makefixed(). | |
| 3 | */ | |
| 4 | 4 | |
| 5 | /* WARNING: this file should *not* be used by applications. | |
| 6 | It is part of the implementation of this library and is | |
| 7 | subject to change. Applications should only use zlib.h. | |
| 8 | */ | |
| 5 | /* WARNING: this file should *not* be used by applications. | |
| 6 | It is part of the implementation of this library and is | |
| 7 | subject to change. Applications should only use zlib.h. | |
| 8 | */ | |
| 9 | 9 | |
| 10 | static const code lenfix[512] = { | |
| 11 | {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, | |
| 12 | {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, | |
| 13 | {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, | |
| 14 | {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, | |
| 15 | {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, | |
| 16 | {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, | |
| 17 | {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, | |
| 18 | {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, | |
| 19 | {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, | |
| 20 | {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, | |
| 21 | {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, | |
| 22 | {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, | |
| 23 | {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, | |
| 24 | {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, | |
| 25 | {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, | |
| 26 | {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, | |
| 27 | {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, | |
| 28 | {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, | |
| 29 | {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, | |
| 30 | {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, | |
| 31 | {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, | |
| 32 | {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, | |
| 33 | {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, | |
| 34 | {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, | |
| 35 | {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, | |
| 36 | {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, | |
| 37 | {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, | |
| 38 | {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, | |
| 39 | {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, | |
| 40 | {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, | |
| 41 | {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, | |
| 42 | {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, | |
| 43 | {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, | |
| 44 | {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, | |
| 45 | {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, | |
| 46 | {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, | |
| 47 | {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, | |
| 48 | {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, | |
| 49 | {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, | |
| 50 | {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, | |
| 51 | {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, | |
| 52 | {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, | |
| 53 | {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, | |
| 54 | {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, | |
| 55 | {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, | |
| 56 | {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, | |
| 57 | {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, | |
| 58 | {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, | |
| 59 | {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, | |
| 60 | {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, | |
| 61 | {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, | |
| 62 | {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, | |
| 63 | {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, | |
| 64 | {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, | |
| 65 | {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, | |
| 66 | {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, | |
| 67 | {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, | |
| 68 | {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, | |
| 69 | {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, | |
| 70 | {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, | |
| 71 | {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, | |
| 72 | {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, | |
| 73 | {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, | |
| 74 | {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, | |
| 75 | {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, | |
| 76 | {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, | |
| 77 | {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, | |
| 78 | {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, | |
| 79 | {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, | |
| 80 | {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, | |
| 81 | {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, | |
| 82 | {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, | |
| 83 | {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, | |
| 84 | {0,9,255} | |
| 85 | }; | |
| 10 | static const code lenfix[512] = { | |
| 11 | {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, | |
| 12 | {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, | |
| 13 | {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, | |
| 14 | {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, | |
| 15 | {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, | |
| 16 | {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, | |
| 17 | {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, | |
| 18 | {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, | |
| 19 | {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, | |
| 20 | {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, | |
| 21 | {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, | |
| 22 | {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, | |
| 23 | {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, | |
| 24 | {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, | |
| 25 | {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, | |
| 26 | {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, | |
| 27 | {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, | |
| 28 | {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, | |
| 29 | {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, | |
| 30 | {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, | |
| 31 | {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, | |
| 32 | {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, | |
| 33 | {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, | |
| 34 | {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, | |
| 35 | {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, | |
| 36 | {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, | |
| 37 | {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, | |
| 38 | {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, | |
| 39 | {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, | |
| 40 | {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, | |
| 41 | {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, | |
| 42 | {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, | |
| 43 | {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, | |
| 44 | {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, | |
| 45 | {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, | |
| 46 | {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, | |
| 47 | {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, | |
| 48 | {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, | |
| 49 | {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, | |
| 50 | {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, | |
| 51 | {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, | |
| 52 | {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, | |
| 53 | {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, | |
| 54 | {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, | |
| 55 | {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, | |
| 56 | {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, | |
| 57 | {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, | |
| 58 | {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, | |
| 59 | {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, | |
| 60 | {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, | |
| 61 | {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, | |
| 62 | {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, | |
| 63 | {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, | |
| 64 | {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, | |
| 65 | {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, | |
| 66 | {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, | |
| 67 | {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, | |
| 68 | {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, | |
| 69 | {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, | |
| 70 | {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, | |
| 71 | {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, | |
| 72 | {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, | |
| 73 | {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, | |
| 74 | {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, | |
| 75 | {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, | |
| 76 | {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, | |
| 77 | {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, | |
| 78 | {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, | |
| 79 | {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, | |
| 80 | {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, | |
| 81 | {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, | |
| 82 | {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, | |
| 83 | {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, | |
| 84 | {0,9,255} | |
| 85 | }; | |
| 86 | 86 | |
| 87 | static const code distfix[32] = { | |
| 88 | {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, | |
| 89 | {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, | |
| 90 | {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, | |
| 91 | {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, | |
| 92 | {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, | |
| 93 | {22,5,193},{64,5,0} | |
| 94 | }; | |
| 87 | static const code distfix[32] = { | |
| 88 | {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, | |
| 89 | {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, | |
| 90 | {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, | |
| 91 | {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, | |
| 92 | {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, | |
| 93 | {22,5,193},{64,5,0} | |
| 94 | }; |
| r25360 | r25361 | |
|---|---|---|
| 52 | 52 | #include "deflate.h" |
| 53 | 53 | |
| 54 | 54 | const char deflate_copyright[] = |
| 55 | ||
| 55 | " deflate 1.2.8 Copyright 1995-2013 Jean-loup Gailly and Mark Adler "; | |
| 56 | 56 | /* |
| 57 | 57 | If you use the zlib library in a product, an acknowledgment is welcome |
| 58 | 58 | in the documentation of your product. If for some reason you cannot |
| r25360 | r25361 | |
| 64 | 64 | * Function prototypes. |
| 65 | 65 | */ |
| 66 | 66 | typedef enum { |
| 67 | need_more, /* block not completed, need more input or more output */ | |
| 68 | block_done, /* block flush performed */ | |
| 69 | finish_started, /* finish started, need only more output at next deflate */ | |
| 70 | finish_done /* finish done, accept no more input or output */ | |
| 67 | need_more, /* block not completed, need more input or more output */ | |
| 68 | block_done, /* block flush performed */ | |
| 69 | finish_started, /* finish started, need only more output at next deflate */ | |
| 70 | finish_done /* finish done, accept no more input or output */ | |
| 71 | 71 | } block_state; |
| 72 | 72 | |
| 73 | 73 | typedef block_state (*compress_func) OF((deflate_state *s, int flush)); |
| r25360 | r25361 | |
| 86 | 86 | local void flush_pending OF((z_streamp strm)); |
| 87 | 87 | local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); |
| 88 | 88 | #ifdef ASMV |
| 89 | void match_init OF((void)); /* asm code initialization */ | |
| 90 | uInt longest_match OF((deflate_state *s, IPos cur_match)); | |
| 89 | void match_init OF((void)); /* asm code initialization */ | |
| 90 | uInt longest_match OF((deflate_state *s, IPos cur_match)); | |
| 91 | 91 | #else |
| 92 | 92 | local uInt longest_match OF((deflate_state *s, IPos cur_match)); |
| 93 | 93 | #endif |
| 94 | 94 | |
| 95 | 95 | #ifdef DEBUG |
| 96 | 96 | local void check_match OF((deflate_state *s, IPos start, IPos match, |
| 97 | ||
| 97 | int length)); | |
| 98 | 98 | #endif |
| 99 | 99 | |
| 100 | 100 | /* =========================================================================== |
| r25360 | r25361 | |
| 115 | 115 | * found for specific files. |
| 116 | 116 | */ |
| 117 | 117 | typedef struct config_s { |
| 118 | ush good_length; /* reduce lazy search above this match length */ | |
| 119 | ush max_lazy; /* do not perform lazy search above this match length */ | |
| 120 | ush nice_length; /* quit search above this match length */ | |
| 121 | ush max_chain; | |
| 122 | compress_func func; | |
| 118 | ush good_length; /* reduce lazy search above this match length */ | |
| 119 | ush max_lazy; /* do not perform lazy search above this match length */ | |
| 120 | ush nice_length; /* quit search above this match length */ | |
| 121 | ush max_chain; | |
| 122 | compress_func func; | |
| 123 | 123 | } config; |
| 124 | 124 | |
| 125 | 125 | #ifdef FASTEST |
| r25360 | r25361 | |
| 179 | 179 | */ |
| 180 | 180 | #ifdef FASTEST |
| 181 | 181 | #define INSERT_STRING(s, str, match_head) \ |
| 182 | (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ | |
| 183 | match_head = s->head[s->ins_h], \ | |
| 184 | s->head[s->ins_h] = (Pos)(str)) | |
| 182 | (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ | |
| 183 | match_head = s->head[s->ins_h], \ | |
| 184 | s->head[s->ins_h] = (Pos)(str)) | |
| 185 | 185 | #else |
| 186 | 186 | #define INSERT_STRING(s, str, match_head) \ |
| 187 | (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ | |
| 188 | match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ | |
| 189 | s->head[s->ins_h] = (Pos)(str)) | |
| 187 | (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ | |
| 188 | match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ | |
| 189 | s->head[s->ins_h] = (Pos)(str)) | |
| 190 | 190 | #endif |
| 191 | 191 | |
| 192 | 192 | /* =========================================================================== |
| r25360 | r25361 | |
| 194 | 194 | * prev[] will be initialized on the fly. |
| 195 | 195 | */ |
| 196 | 196 | #define CLEAR_HASH(s) \ |
| 197 | s->head[s->hash_size-1] = NIL; \ | |
| 198 | zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); | |
| 197 | s->head[s->hash_size-1] = NIL; \ | |
| 198 | zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); | |
| 199 | 199 | |
| 200 | 200 | /* ========================================================================= */ |
| 201 | 201 | int ZEXPORT deflateInit_(strm, level, version, stream_size) |
| 202 | z_streamp strm; | |
| 203 | int level; | |
| 204 | const char *version; | |
| 205 | int stream_size; | |
| 202 | z_streamp strm; | |
| 203 | int level; | |
| 204 | const char *version; | |
| 205 | int stream_size; | |
| 206 | 206 | { |
| 207 | return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, | |
| 208 | Z_DEFAULT_STRATEGY, version, stream_size); | |
| 209 | /* To do: ignore strm->next_in if we use it as window */ | |
| 207 | return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, | |
| 208 | Z_DEFAULT_STRATEGY, version, stream_size); | |
| 209 | /* To do: ignore strm->next_in if we use it as window */ | |
| 210 | 210 | } |
| 211 | 211 | |
| 212 | 212 | /* ========================================================================= */ |
| 213 | 213 | int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, |
| 214 | version, stream_size) | |
| 215 | z_streamp strm; | |
| 216 | int level; | |
| 217 | int method; | |
| 218 | int windowBits; | |
| 219 | int memLevel; | |
| 220 | int strategy; | |
| 221 | const char *version; | |
| 222 | int stream_size; | |
| 214 | version, stream_size) | |
| 215 | z_streamp strm; | |
| 216 | int level; | |
| 217 | int method; | |
| 218 | int windowBits; | |
| 219 | int memLevel; | |
| 220 | int strategy; | |
| 221 | const char *version; | |
| 222 | int stream_size; | |
| 223 | 223 | { |
| 224 | deflate_state *s; | |
| 225 | int wrap = 1; | |
| 226 | static const char my_version[] = ZLIB_VERSION; | |
| 224 | deflate_state *s; | |
| 225 | int wrap = 1; | |
| 226 | static const char my_version[] = ZLIB_VERSION; | |
| 227 | 227 | |
| 228 | ushf *overlay; | |
| 229 | /* We overlay pending_buf and d_buf+l_buf. This works since the average | |
| 230 | * output size for (length,distance) codes is <= 24 bits. | |
| 231 | */ | |
| 228 | ushf *overlay; | |
| 229 | /* We overlay pending_buf and d_buf+l_buf. This works since the average | |
| 230 | * output size for (length,distance) codes is <= 24 bits. | |
| 231 | */ | |
| 232 | 232 | |
| 233 | if (version == Z_NULL || version[0] != my_version[0] || | |
| 234 | stream_size != sizeof(z_stream)) { | |
| 235 | return Z_VERSION_ERROR; | |
| 236 | } | |
| 237 | if (strm == Z_NULL) return Z_STREAM_ERROR; | |
| 233 | if (version == Z_NULL || version[0] != my_version[0] || | |
| 234 | stream_size != sizeof(z_stream)) { | |
| 235 | return Z_VERSION_ERROR; | |
| 236 | } | |
| 237 | if (strm == Z_NULL) return Z_STREAM_ERROR; | |
| 238 | 238 | |
| 239 | strm->msg = Z_NULL; | |
| 240 | if (strm->zalloc == (alloc_func)0) { | |
| 239 | strm->msg = Z_NULL; | |
| 240 | if (strm->zalloc == (alloc_func)0) { | |
| 241 | 241 | #ifdef Z_SOLO |
| 242 | ||
| 242 | return Z_STREAM_ERROR; | |
| 243 | 243 | #else |
| 244 | strm->zalloc = zcalloc; | |
| 245 | strm->opaque = (voidpf)0; | |
| 244 | strm->zalloc = zcalloc; | |
| 245 | strm->opaque = (voidpf)0; | |
| 246 | 246 | #endif |
| 247 | } | |
| 248 | if (strm->zfree == (free_func)0) | |
| 247 | } | |
| 248 | if (strm->zfree == (free_func)0) | |
| 249 | 249 | #ifdef Z_SOLO |
| 250 | ||
| 250 | return Z_STREAM_ERROR; | |
| 251 | 251 | #else |
| 252 | ||
| 252 | strm->zfree = zcfree; | |
| 253 | 253 | #endif |
| 254 | 254 | |
| 255 | 255 | #ifdef FASTEST |
| 256 | ||
| 256 | if (level != 0) level = 1; | |
| 257 | 257 | #else |
| 258 | ||
| 258 | if (level == Z_DEFAULT_COMPRESSION) level = 6; | |
| 259 | 259 | #endif |
| 260 | 260 | |
| 261 | if (windowBits < 0) { /* suppress zlib wrapper */ | |
| 262 | wrap = 0; | |
| 263 | windowBits = -windowBits; | |
| 264 | } | |
| 261 | if (windowBits < 0) { /* suppress zlib wrapper */ | |
| 262 | wrap = 0; | |
| 263 | windowBits = -windowBits; | |
| 264 | } | |
| 265 | 265 | #ifdef GZIP |
| 266 | else if (windowBits > 15) { | |
| 267 | wrap = 2; /* write gzip wrapper instead */ | |
| 268 | windowBits -= 16; | |
| 269 | } | |
| 266 | else if (windowBits > 15) { | |
| 267 | wrap = 2; /* write gzip wrapper instead */ | |
| 268 | windowBits -= 16; | |
| 269 | } | |
| 270 | 270 | #endif |
| 271 | if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || | |
| 272 | windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || | |
| 273 | strategy < 0 || strategy > Z_FIXED) { | |
| 274 | return Z_STREAM_ERROR; | |
| 275 | } | |
| 276 | if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ | |
| 277 | s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); | |
| 278 | if (s == Z_NULL) return Z_MEM_ERROR; | |
| 279 | strm->state = (struct internal_state FAR *)s; | |
| 280 | s->strm = strm; | |
| 271 | if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || | |
| 272 | windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || | |
| 273 | strategy < 0 || strategy > Z_FIXED) { | |
| 274 | return Z_STREAM_ERROR; | |
| 275 | } | |
| 276 | if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ | |
| 277 | s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); | |
| 278 | if (s == Z_NULL) return Z_MEM_ERROR; | |
| 279 | strm->state = (struct internal_state FAR *)s; | |
| 280 | s->strm = strm; | |
| 281 | 281 | |
| 282 | s->wrap = wrap; | |
| 283 | s->gzhead = Z_NULL; | |
| 284 | s->w_bits = windowBits; | |
| 285 | s->w_size = 1 << s->w_bits; | |
| 286 | s->w_mask = s->w_size - 1; | |
| 282 | s->wrap = wrap; | |
| 283 | s->gzhead = Z_NULL; | |
| 284 | s->w_bits = windowBits; | |
| 285 | s->w_size = 1 << s->w_bits; | |
| 286 | s->w_mask = s->w_size - 1; | |
| 287 | 287 | |
| 288 | s->hash_bits = memLevel + 7; | |
| 289 | s->hash_size = 1 << s->hash_bits; | |
| 290 | s->hash_mask = s->hash_size - 1; | |
| 291 | s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); | |
| 288 | s->hash_bits = memLevel + 7; | |
| 289 | s->hash_size = 1 << s->hash_bits; | |
| 290 | s->hash_mask = s->hash_size - 1; | |
| 291 | s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); | |
| 292 | 292 | |
| 293 | s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); | |
| 294 | s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); | |
| 295 | s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); | |
| 293 | s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); | |
| 294 | s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); | |
| 295 | s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); | |
| 296 | 296 | |
| 297 | ||
| 297 | s->high_water = 0; /* nothing written to s->window yet */ | |
| 298 | 298 | |
| 299 | ||
| 299 | s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ | |
| 300 | 300 | |
| 301 | overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); | |
| 302 | s->pending_buf = (uchf *) overlay; | |
| 303 | s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); | |
| 301 | overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); | |
| 302 | s->pending_buf = (uchf *) overlay; | |
| 303 | s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); | |
| 304 | 304 | |
| 305 | if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || | |
| 306 | s->pending_buf == Z_NULL) { | |
| 307 | s->status = FINISH_STATE; | |
| 308 | strm->msg = ERR_MSG(Z_MEM_ERROR); | |
| 309 | deflateEnd (strm); | |
| 310 | return Z_MEM_ERROR; | |
| 311 | } | |
| 312 | s->d_buf = overlay + s->lit_bufsize/sizeof(ush); | |
| 313 | s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; | |
| 305 | if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || | |
| 306 | s->pending_buf == Z_NULL) { | |
| 307 | s->status = FINISH_STATE; | |
| 308 | strm->msg = ERR_MSG(Z_MEM_ERROR); | |
| 309 | deflateEnd (strm); | |
| 310 | return Z_MEM_ERROR; | |
| 311 | } | |
| 312 | s->d_buf = overlay + s->lit_bufsize/sizeof(ush); | |
| 313 | s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; | |
| 314 | 314 | |
| 315 | s->level = level; | |
| 316 | s->strategy = strategy; | |
| 317 | s->method = (Byte)method; | |
| 315 | s->level = level; | |
| 316 | s->strategy = strategy; | |
| 317 | s->method = (Byte)method; | |
| 318 | 318 | |
| 319 | ||
| 319 | return deflateReset(strm); | |
| 320 | 320 | } |
| 321 | 321 | |
| 322 | 322 | /* ========================================================================= */ |
| 323 | 323 | int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) |
| 324 | z_streamp strm; | |
| 325 | const Bytef *dictionary; | |
| 326 | uInt dictLength; | |
| 324 | z_streamp strm; | |
| 325 | const Bytef *dictionary; | |
| 326 | uInt dictLength; | |
| 327 | 327 | { |
| 328 | deflate_state *s; | |
| 329 | uInt str, n; | |
| 330 | int wrap; | |
| 331 | unsigned avail; | |
| 332 | z_const unsigned char *next; | |
| 328 | deflate_state *s; | |
| 329 | uInt str, n; | |
| 330 | int wrap; | |
| 331 | unsigned avail; | |
| 332 | z_const unsigned char *next; | |
| 333 | 333 | |
| 334 | if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL) | |
| 335 | return Z_STREAM_ERROR; | |
| 336 | s = strm->state; | |
| 337 | wrap = s->wrap; | |
| 338 | if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead) | |
| 339 | return Z_STREAM_ERROR; | |
| 334 | if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL) | |
| 335 | return Z_STREAM_ERROR; | |
| 336 | s = strm->state; | |
| 337 | wrap = s->wrap; | |
| 338 | if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead) | |
| 339 | return Z_STREAM_ERROR; | |
| 340 | 340 | |
| 341 | /* when using zlib wrappers, compute Adler-32 for provided dictionary */ | |
| 342 | if (wrap == 1) | |
| 343 | strm->adler = adler32(strm->adler, dictionary, dictLength); | |
| 344 | s->wrap = 0; /* avoid computing Adler-32 in read_buf */ | |
| 341 | /* when using zlib wrappers, compute Adler-32 for provided dictionary */ | |
| 342 | if (wrap == 1) | |
| 343 | strm->adler = adler32(strm->adler, dictionary, dictLength); | |
| 344 | s->wrap = 0; /* avoid computing Adler-32 in read_buf */ | |
| 345 | 345 | |
| 346 | /* if dictionary would fill window, just replace the history */ | |
| 347 | if (dictLength >= s->w_size) { | |
| 348 | if (wrap == 0) { /* already empty otherwise */ | |
| 349 | CLEAR_HASH(s); | |
| 350 | s->strstart = 0; | |
| 351 | s->block_start = 0L; | |
| 352 | s->insert = 0; | |
| 353 | } | |
| 354 | dictionary += dictLength - s->w_size; /* use the tail */ | |
| 355 | dictLength = s->w_size; | |
| 356 | } | |
| 346 | /* if dictionary would fill window, just replace the history */ | |
| 347 | if (dictLength >= s->w_size) { | |
| 348 | if (wrap == 0) { /* already empty otherwise */ | |
| 349 | CLEAR_HASH(s); | |
| 350 | s->strstart = 0; | |
| 351 | s->block_start = 0L; | |
| 352 | s->insert = 0; | |
| 353 | } | |
| 354 | dictionary += dictLength - s->w_size; /* use the tail */ | |
| 355 | dictLength = s->w_size; | |
| 356 | } | |
| 357 | 357 | |
| 358 | /* insert dictionary into window and hash */ | |
| 359 | avail = strm->avail_in; | |
| 360 | next = strm->next_in; | |
| 361 | strm->avail_in = dictLength; | |
| 362 | strm->next_in = (z_const Bytef *)dictionary; | |
| 363 | fill_window(s); | |
| 364 | while (s->lookahead >= MIN_MATCH) { | |
| 365 | str = s->strstart; | |
| 366 | n = s->lookahead - (MIN_MATCH-1); | |
| 367 | do { | |
| 368 | UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); | |
| 358 | /* insert dictionary into window and hash */ | |
| 359 | avail = strm->avail_in; | |
| 360 | next = strm->next_in; | |
| 361 | strm->avail_in = dictLength; | |
| 362 | strm->next_in = (z_const Bytef *)dictionary; | |
| 363 | fill_window(s); | |
| 364 | while (s->lookahead >= MIN_MATCH) { | |
| 365 | str = s->strstart; | |
| 366 | n = s->lookahead - (MIN_MATCH-1); | |
| 367 | do { | |
| 368 | UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); | |
| 369 | 369 | #ifndef FASTEST |
| 370 | ||
| 370 | s->prev[str & s->w_mask] = s->head[s->ins_h]; | |
| 371 | 371 | #endif |
| 372 | s->head[s->ins_h] = (Pos)str; | |
| 373 | str++; | |
| 374 | } while (--n); | |
| 375 | s->strstart = str; | |
| 376 | s->lookahead = MIN_MATCH-1; | |
| 377 | fill_window(s); | |
| 378 | } | |
| 379 | s->strstart += s->lookahead; | |
| 380 | s->block_start = (long)s->strstart; | |
| 381 | s->insert = s->lookahead; | |
| 382 | s->lookahead = 0; | |
| 383 | s->match_length = s->prev_length = MIN_MATCH-1; | |
| 384 | s->match_available = 0; | |
| 385 | strm->next_in = next; | |
| 386 | strm->avail_in = avail; | |
| 387 | s->wrap = wrap; | |
| 388 | return Z_OK; | |
| 372 | s->head[s->ins_h] = (Pos)str; | |
| 373 | str++; | |
| 374 | } while (--n); | |
| 375 | s->strstart = str; | |
| 376 | s->lookahead = MIN_MATCH-1; | |
| 377 | fill_window(s); | |
| 378 | } | |
| 379 | s->strstart += s->lookahead; | |
| 380 | s->block_start = (long)s->strstart; | |
| 381 | s->insert = s->lookahead; | |
| 382 | s->lookahead = 0; | |
| 383 | s->match_length = s->prev_length = MIN_MATCH-1; | |
| 384 | s->match_available = 0; | |
| 385 | strm->next_in = next; | |
| 386 | strm->avail_in = avail; | |
| 387 | s->wrap = wrap; | |
| 388 | return Z_OK; | |
| 389 | 389 | } |
| 390 | 390 | |
| 391 | 391 | /* ========================================================================= */ |
| 392 | 392 | int ZEXPORT deflateResetKeep (strm) |
| 393 | ||
| 393 | z_streamp strm; | |
| 394 | 394 | { |
| 395 | ||
| 395 | deflate_state *s; | |
| 396 | 396 | |
| 397 | if (strm == Z_NULL || strm->state == Z_NULL || | |
| 398 | strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { | |
| 399 | return Z_STREAM_ERROR; | |
| 400 | } | |
| 397 | if (strm == Z_NULL || strm->state == Z_NULL || | |
| 398 | strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { | |
| 399 | return Z_STREAM_ERROR; | |
| 400 | } | |
| 401 | 401 | |
| 402 | strm->total_in = strm->total_out = 0; | |
| 403 | strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ | |
| 404 | strm->data_type = Z_UNKNOWN; | |
| 402 | strm->total_in = strm->total_out = 0; | |
| 403 | strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ | |
| 404 | strm->data_type = Z_UNKNOWN; | |
| 405 | 405 | |
| 406 | s = (deflate_state *)strm->state; | |
| 407 | s->pending = 0; | |
| 408 | s->pending_out = s->pending_buf; | |
| 406 | s = (deflate_state *)strm->state; | |
| 407 | s->pending = 0; | |
| 408 | s->pending_out = s->pending_buf; | |
| 409 | 409 | |
| 410 | if (s->wrap < 0) { | |
| 411 | s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ | |
| 412 | } | |
| 413 | s->status = s->wrap ? INIT_STATE : BUSY_STATE; | |
| 414 | strm->adler = | |
| 410 | if (s->wrap < 0) { | |
| 411 | s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ | |
| 412 | } | |
| 413 | s->status = s->wrap ? INIT_STATE : BUSY_STATE; | |
| 414 | strm->adler = | |
| 415 | 415 | #ifdef GZIP |
| 416 | ||
| 416 | s->wrap == 2 ? crc32(0L, Z_NULL, 0) : | |
| 417 | 417 | #endif |
| 418 | adler32(0L, Z_NULL, 0); | |
| 419 | s->last_flush = Z_NO_FLUSH; | |
| 418 | adler32(0L, Z_NULL, 0); | |
| 419 | s->last_flush = Z_NO_FLUSH; | |
| 420 | 420 | |
| 421 | ||
| 421 | _tr_init(s); | |
| 422 | 422 | |
| 423 | ||
| 423 | return Z_OK; | |
| 424 | 424 | } |
| 425 | 425 | |
| 426 | 426 | /* ========================================================================= */ |
| 427 | 427 | int ZEXPORT deflateReset (strm) |
| 428 | ||
| 428 | z_streamp strm; | |
| 429 | 429 | { |
| 430 | ||
| 430 | int ret; | |
| 431 | 431 | |
| 432 | ret = deflateResetKeep(strm); | |
| 433 | if (ret == Z_OK) | |
| 434 | lm_init(strm->state); | |
| 435 | return ret; | |
| 432 | ret = deflateResetKeep(strm); | |
| 433 | if (ret == Z_OK) | |
| 434 | lm_init(strm->state); | |
| 435 | return ret; | |
| 436 | 436 | } |
| 437 | 437 | |
| 438 | 438 | /* ========================================================================= */ |
| 439 | 439 | int ZEXPORT deflateSetHeader (strm, head) |
| 440 | z_streamp strm; | |
| 441 | gz_headerp head; | |
| 440 | z_streamp strm; | |
| 441 | gz_headerp head; | |
| 442 | 442 | { |
| 443 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 444 | if (strm->state->wrap != 2) return Z_STREAM_ERROR; | |
| 445 | strm->state->gzhead = head; | |
| 446 | return Z_OK; | |
| 443 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 444 | if (strm->state->wrap != 2) return Z_STREAM_ERROR; | |
| 445 | strm->state->gzhead = head; | |
| 446 | return Z_OK; | |
| 447 | 447 | } |
| 448 | 448 | |
| 449 | 449 | /* ========================================================================= */ |
| 450 | 450 | int ZEXPORT deflatePending (strm, pending, bits) |
| 451 | unsigned *pending; | |
| 452 | int *bits; | |
| 453 | z_streamp strm; | |
| 451 | unsigned *pending; | |
| 452 | int *bits; | |
| 453 | z_streamp strm; | |
| 454 | 454 | { |
| 455 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 456 | if (pending != Z_NULL) | |
| 457 | *pending = strm->state->pending; | |
| 458 | if (bits != Z_NULL) | |
| 459 | *bits = strm->state->bi_valid; | |
| 460 | return Z_OK; | |
| 455 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 456 | if (pending != Z_NULL) | |
| 457 | *pending = strm->state->pending; | |
| 458 | if (bits != Z_NULL) | |
| 459 | *bits = strm->state->bi_valid; | |
| 460 | return Z_OK; | |
| 461 | 461 | } |
| 462 | 462 | |
| 463 | 463 | /* ========================================================================= */ |
| 464 | 464 | int ZEXPORT deflatePrime (strm, bits, value) |
| 465 | z_streamp strm; | |
| 466 | int bits; | |
| 467 | int value; | |
| 465 | z_streamp strm; | |
| 466 | int bits; | |
| 467 | int value; | |
| 468 | 468 | { |
| 469 | deflate_state *s; | |
| 470 | int put; | |
| 469 | deflate_state *s; | |
| 470 | int put; | |
| 471 | 471 | |
| 472 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 473 | s = strm->state; | |
| 474 | if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) | |
| 475 | return Z_BUF_ERROR; | |
| 476 | do { | |
| 477 | put = Buf_size - s->bi_valid; | |
| 478 | if (put > bits) | |
| 479 | put = bits; | |
| 480 | s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid); | |
| 481 | s->bi_valid += put; | |
| 482 | _tr_flush_bits(s); | |
| 483 | value >>= put; | |
| 484 | bits -= put; | |
| 485 | } while (bits); | |
| 486 | return Z_OK; | |
| 472 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 473 | s = strm->state; | |
| 474 | if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) | |
| 475 | return Z_BUF_ERROR; | |
| 476 | do { | |
| 477 | put = Buf_size - s->bi_valid; | |
| 478 | if (put > bits) | |
| 479 | put = bits; | |
| 480 | s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid); | |
| 481 | s->bi_valid += put; | |
| 482 | _tr_flush_bits(s); | |
| 483 | value >>= put; | |
| 484 | bits -= put; | |
| 485 | } while (bits); | |
| 486 | return Z_OK; | |
| 487 | 487 | } |
| 488 | 488 | |
| 489 | 489 | /* ========================================================================= */ |
| 490 | 490 | int ZEXPORT deflateParams(strm, level, strategy) |
| 491 | z_streamp strm; | |
| 492 | int level; | |
| 493 | int strategy; | |
| 491 | z_streamp strm; | |
| 492 | int level; | |
| 493 | int strategy; | |
| 494 | 494 | { |
| 495 | deflate_state *s; | |
| 496 | compress_func func; | |
| 497 | int err = Z_OK; | |
| 495 | deflate_state *s; | |
| 496 | compress_func func; | |
| 497 | int err = Z_OK; | |
| 498 | 498 | |
| 499 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 500 | s = strm->state; | |
| 499 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 500 | s = strm->state; | |
| 501 | 501 | |
| 502 | 502 | #ifdef FASTEST |
| 503 | ||
| 503 | if (level != 0) level = 1; | |
| 504 | 504 | #else |
| 505 | ||
| 505 | if (level == Z_DEFAULT_COMPRESSION) level = 6; | |
| 506 | 506 | #endif |
| 507 | if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { | |
| 508 | return Z_STREAM_ERROR; | |
| 509 | } | |
| 510 | func = configuration_table[s->level].func; | |
| 507 | if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { | |
| 508 | return Z_STREAM_ERROR; | |
| 509 | } | |
| 510 | func = configuration_table[s->level].func; | |
| 511 | 511 | |
| 512 | if ((strategy != s->strategy || func != configuration_table[level].func) && | |
| 513 | strm->total_in != 0) { | |
| 514 | /* Flush the last buffer: */ | |
| 515 | err = deflate(strm, Z_BLOCK); | |
| 516 | if (err == Z_BUF_ERROR && s->pending == 0) | |
| 517 | err = Z_OK; | |
| 518 | } | |
| 519 | if (s->level != level) { | |
| 520 | s->level = level; | |
| 521 | s->max_lazy_match = configuration_table[level].max_lazy; | |
| 522 | s->good_match = configuration_table[level].good_length; | |
| 523 | s->nice_match = configuration_table[level].nice_length; | |
| 524 | s->max_chain_length = configuration_table[level].max_chain; | |
| 525 | } | |
| 526 | s->strategy = strategy; | |
| 527 | return err; | |
| 512 | if ((strategy != s->strategy || func != configuration_table[level].func) && | |
| 513 | strm->total_in != 0) { | |
| 514 | /* Flush the last buffer: */ | |
| 515 | err = deflate(strm, Z_BLOCK); | |
| 516 | if (err == Z_BUF_ERROR && s->pending == 0) | |
| 517 | err = Z_OK; | |
| 518 | } | |
| 519 | if (s->level != level) { | |
| 520 | s->level = level; | |
| 521 | s->max_lazy_match = configuration_table[level].max_lazy; | |
| 522 | s->good_match = configuration_table[level].good_length; | |
| 523 | s->nice_match = configuration_table[level].nice_length; | |
| 524 | s->max_chain_length = configuration_table[level].max_chain; | |
| 525 | } | |
| 526 | s->strategy = strategy; | |
| 527 | return err; | |
| 528 | 528 | } |
| 529 | 529 | |
| 530 | 530 | /* ========================================================================= */ |
| 531 | 531 | int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) |
| 532 | z_streamp strm; | |
| 533 | int good_length; | |
| 534 | int max_lazy; | |
| 535 | int nice_length; | |
| 536 | int max_chain; | |
| 532 | z_streamp strm; | |
| 533 | int good_length; | |
| 534 | int max_lazy; | |
| 535 | int nice_length; | |
| 536 | int max_chain; | |
| 537 | 537 | { |
| 538 | ||
| 538 | deflate_state *s; | |
| 539 | 539 | |
| 540 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 541 | s = strm->state; | |
| 542 | s->good_match = good_length; | |
| 543 | s->max_lazy_match = max_lazy; | |
| 544 | s->nice_match = nice_length; | |
| 545 | s->max_chain_length = max_chain; | |
| 546 | return Z_OK; | |
| 540 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 541 | s = strm->state; | |
| 542 | s->good_match = good_length; | |
| 543 | s->max_lazy_match = max_lazy; | |
| 544 | s->nice_match = nice_length; | |
| 545 | s->max_chain_length = max_chain; | |
| 546 | return Z_OK; | |
| 547 | 547 | } |
| 548 | 548 | |
| 549 | 549 | /* ========================================================================= |
| r25360 | r25361 | |
| 564 | 564 | * allocation. |
| 565 | 565 | */ |
| 566 | 566 | uLong ZEXPORT deflateBound(strm, sourceLen) |
| 567 | z_streamp strm; | |
| 568 | uLong sourceLen; | |
| 567 | z_streamp strm; | |
| 568 | uLong sourceLen; | |
| 569 | 569 | { |
| 570 | deflate_state *s; | |
| 571 | uLong complen, wraplen; | |
| 572 | Bytef *str; | |
| 570 | deflate_state *s; | |
| 571 | uLong complen, wraplen; | |
| 572 | Bytef *str; | |
| 573 | 573 | |
| 574 | /* conservative upper bound for compressed data */ | |
| 575 | complen = sourceLen + | |
| 576 | ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; | |
| 574 | /* conservative upper bound for compressed data */ | |
| 575 | complen = sourceLen + | |
| 576 | ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; | |
| 577 | 577 | |
| 578 | /* if can't get parameters, return conservative bound plus zlib wrapper */ | |
| 579 | if (strm == Z_NULL || strm->state == Z_NULL) | |
| 580 | return complen + 6; | |
| 578 | /* if can't get parameters, return conservative bound plus zlib wrapper */ | |
| 579 | if (strm == Z_NULL || strm->state == Z_NULL) | |
| 580 | return complen + 6; | |
| 581 | 581 | |
| 582 | /* compute wrapper length */ | |
| 583 | s = strm->state; | |
| 584 | switch (s->wrap) { | |
| 585 | case 0: /* raw deflate */ | |
| 586 | wraplen = 0; | |
| 587 | break; | |
| 588 | case 1: /* zlib wrapper */ | |
| 589 | wraplen = 6 + (s->strstart ? 4 : 0); | |
| 590 | break; | |
| 591 | case 2: /* gzip wrapper */ | |
| 592 | wraplen = 18; | |
| 593 | if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ | |
| 594 | if (s->gzhead->extra != Z_NULL) | |
| 595 | wraplen += 2 + s->gzhead->extra_len; | |
| 596 | str = s->gzhead->name; | |
| 597 | if (str != Z_NULL) | |
| 598 | do { | |
| 599 | wraplen++; | |
| 600 | } while (*str++); | |
| 601 | str = s->gzhead->comment; | |
| 602 | if (str != Z_NULL) | |
| 603 | do { | |
| 604 | wraplen++; | |
| 605 | } while (*str++); | |
| 606 | if (s->gzhead->hcrc) | |
| 607 | wraplen += 2; | |
| 608 | } | |
| 609 | break; | |
| 610 | default: /* for compiler happiness */ | |
| 611 | wraplen = 6; | |
| 612 | } | |
| 582 | /* compute wrapper length */ | |
| 583 | s = strm->state; | |
| 584 | switch (s->wrap) { | |
| 585 | case 0: /* raw deflate */ | |
| 586 | wraplen = 0; | |
| 587 | break; | |
| 588 | case 1: /* zlib wrapper */ | |
| 589 | wraplen = 6 + (s->strstart ? 4 : 0); | |
| 590 | break; | |
| 591 | case 2: /* gzip wrapper */ | |
| 592 | wraplen = 18; | |
| 593 | if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ | |
| 594 | if (s->gzhead->extra != Z_NULL) | |
| 595 | wraplen += 2 + s->gzhead->extra_len; | |
| 596 | str = s->gzhead->name; | |
| 597 | if (str != Z_NULL) | |
| 598 | do { | |
| 599 | wraplen++; | |
| 600 | } while (*str++); | |
| 601 | str = s->gzhead->comment; | |
| 602 | if (str != Z_NULL) | |
| 603 | do { | |
| 604 | wraplen++; | |
| 605 | } while (*str++); | |
| 606 | if (s->gzhead->hcrc) | |
| 607 | wraplen += 2; | |
| 608 | } | |
| 609 | break; | |
| 610 | default: /* for compiler happiness */ | |
| 611 | wraplen = 6; | |
| 612 | } | |
| 613 | 613 | |
| 614 | /* if not default parameters, return conservative bound */ | |
| 615 | if (s->w_bits != 15 || s->hash_bits != 8 + 7) | |
| 616 | return complen + wraplen; | |
| 614 | /* if not default parameters, return conservative bound */ | |
| 615 | if (s->w_bits != 15 || s->hash_bits != 8 + 7) | |
| 616 | return complen + wraplen; | |
| 617 | 617 | |
| 618 | /* default settings: return tight bound for that case */ | |
| 619 | return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + | |
| 620 | (sourceLen >> 25) + 13 - 6 + wraplen; | |
| 618 | /* default settings: return tight bound for that case */ | |
| 619 | return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + | |
| 620 | (sourceLen >> 25) + 13 - 6 + wraplen; | |
| 621 | 621 | } |
| 622 | 622 | |
| 623 | 623 | /* ========================================================================= |
| r25360 | r25361 | |
| 626 | 626 | * pending_buf. |
| 627 | 627 | */ |
| 628 | 628 | local void putShortMSB (s, b) |
| 629 | deflate_state *s; | |
| 630 | uInt b; | |
| 629 | deflate_state *s; | |
| 630 | uInt b; | |
| 631 | 631 | { |
| 632 | put_byte(s, (Byte)(b >> 8)); | |
| 633 | put_byte(s, (Byte)(b & 0xff)); | |
| 632 | put_byte(s, (Byte)(b >> 8)); | |
| 633 | put_byte(s, (Byte)(b & 0xff)); | |
| 634 | 634 | } |
| 635 | 635 | |
| 636 | 636 | /* ========================================================================= |
| r25360 | r25361 | |
| 640 | 640 | * (See also read_buf()). |
| 641 | 641 | */ |
| 642 | 642 | local void flush_pending(strm) |
| 643 | ||
| 643 | z_streamp strm; | |
| 644 | 644 | { |
| 645 | unsigned len; | |
| 646 | deflate_state *s = strm->state; | |
| 645 | unsigned len; | |
| 646 | deflate_state *s = strm->state; | |
| 647 | 647 | |
| 648 | _tr_flush_bits(s); | |
| 649 | len = s->pending; | |
| 650 | if (len > strm->avail_out) len = strm->avail_out; | |
| 651 | if (len == 0) return; | |
| 648 | _tr_flush_bits(s); | |
| 649 | len = s->pending; | |
| 650 | if (len > strm->avail_out) len = strm->avail_out; | |
| 651 | if (len == 0) return; | |
| 652 | 652 | |
| 653 | zmemcpy(strm->next_out, s->pending_out, len); | |
| 654 | strm->next_out += len; | |
| 655 | s->pending_out += len; | |
| 656 | strm->total_out += len; | |
| 657 | strm->avail_out -= len; | |
| 658 | s->pending -= len; | |
| 659 | if (s->pending == 0) { | |
| 660 | s->pending_out = s->pending_buf; | |
| 661 | } | |
| 653 | zmemcpy(strm->next_out, s->pending_out, len); | |
| 654 | strm->next_out += len; | |
| 655 | s->pending_out += len; | |
| 656 | strm->total_out += len; | |
| 657 | strm->avail_out -= len; | |
| 658 | s->pending -= len; | |
| 659 | if (s->pending == 0) { | |
| 660 | s->pending_out = s->pending_buf; | |
| 661 | } | |
| 662 | 662 | } |
| 663 | 663 | |
| 664 | 664 | /* ========================================================================= */ |
| 665 | 665 | int ZEXPORT deflate (strm, flush) |
| 666 | z_streamp strm; | |
| 667 | int flush; | |
| 666 | z_streamp strm; | |
| 667 | int flush; | |
| 668 | 668 | { |
| 669 | int old_flush; /* value of flush param for previous deflate call */ | |
| 670 | deflate_state *s; | |
| 669 | int old_flush; /* value of flush param for previous deflate call */ | |
| 670 | deflate_state *s; | |
| 671 | 671 | |
| 672 | if (strm == Z_NULL || strm->state == Z_NULL || | |
| 673 | flush > Z_BLOCK || flush < 0) { | |
| 674 | return Z_STREAM_ERROR; | |
| 675 | } | |
| 676 | s = strm->state; | |
| 672 | if (strm == Z_NULL || strm->state == Z_NULL || | |
| 673 | flush > Z_BLOCK || flush < 0) { | |
| 674 | return Z_STREAM_ERROR; | |
| 675 | } | |
| 676 | s = strm->state; | |
| 677 | 677 | |
| 678 | if (strm->next_out == Z_NULL || | |
| 679 | (strm->next_in == Z_NULL && strm->avail_in != 0) || | |
| 680 | (s->status == FINISH_STATE && flush != Z_FINISH)) { | |
| 681 | ERR_RETURN(strm, Z_STREAM_ERROR); | |
| 682 | } | |
| 683 | if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); | |
| 678 | if (strm->next_out == Z_NULL || | |
| 679 | (strm->next_in == Z_NULL && strm->avail_in != 0) || | |
| 680 | (s->status == FINISH_STATE && flush != Z_FINISH)) { | |
| 681 | ERR_RETURN(strm, Z_STREAM_ERROR); | |
| 682 | } | |
| 683 | if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); | |
| 684 | 684 | |
| 685 | s->strm = strm; /* just in case */ | |
| 686 | old_flush = s->last_flush; | |
| 687 | s->last_flush = flush; | |
| 685 | s->strm = strm; /* just in case */ | |
| 686 | old_flush = s->last_flush; | |
| 687 | s->last_flush = flush; | |
| 688 | 688 | |
| 689 | /* Write the header */ | |
| 690 | if (s->status == INIT_STATE) { | |
| 689 | /* Write the header */ | |
| 690 | if (s->status == INIT_STATE) { | |
| 691 | 691 | #ifdef GZIP |
| 692 | if (s->wrap == 2) { | |
| 693 | strm->adler = crc32(0L, Z_NULL, 0); | |
| 694 | put_byte(s, 31); | |
| 695 | put_byte(s, 139); | |
| 696 | put_byte(s, 8); | |
| 697 | if (s->gzhead == Z_NULL) { | |
| 698 | put_byte(s, 0); | |
| 699 | put_byte(s, 0); | |
| 700 | put_byte(s, 0); | |
| 701 | put_byte(s, 0); | |
| 702 | put_byte(s, 0); | |
| 703 | put_byte(s, s->level == 9 ? 2 : | |
| 704 | (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? | |
| 705 | 4 : 0)); | |
| 706 | put_byte(s, OS_CODE); | |
| 707 | s->status = BUSY_STATE; | |
| 708 | } | |
| 709 | else { | |
| 710 | put_byte(s, (s->gzhead->text ? 1 : 0) + | |
| 711 | (s->gzhead->hcrc ? 2 : 0) + | |
| 712 | (s->gzhead->extra == Z_NULL ? 0 : 4) + | |
| 713 | (s->gzhead->name == Z_NULL ? 0 : 8) + | |
| 714 | (s->gzhead->comment == Z_NULL ? 0 : 16) | |
| 715 | ); | |
| 716 | put_byte(s, (Byte)(s->gzhead->time & 0xff)); | |
| 717 | put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); | |
| 718 | put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); | |
| 719 | put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); | |
| 720 | put_byte(s, s->level == 9 ? 2 : | |
| 721 | (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? | |
| 722 | 4 : 0)); | |
| 723 | put_byte(s, s->gzhead->os & 0xff); | |
| 724 | if (s->gzhead->extra != Z_NULL) { | |
| 725 | put_byte(s, s->gzhead->extra_len & 0xff); | |
| 726 | put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); | |
| 727 | } | |
| 728 | if (s->gzhead->hcrc) | |
| 729 | strm->adler = crc32(strm->adler, s->pending_buf, | |
| 730 | s->pending); | |
| 731 | s->gzindex = 0; | |
| 732 | s->status = EXTRA_STATE; | |
| 733 | } | |
| 734 | } | |
| 735 | else | |
| 692 | if (s->wrap == 2) { | |
| 693 | strm->adler = crc32(0L, Z_NULL, 0); | |
| 694 | put_byte(s, 31); | |
| 695 | put_byte(s, 139); | |
| 696 | put_byte(s, 8); | |
| 697 | if (s->gzhead == Z_NULL) { | |
| 698 | put_byte(s, 0); | |
| 699 | put_byte(s, 0); | |
| 700 | put_byte(s, 0); | |
| 701 | put_byte(s, 0); | |
| 702 | put_byte(s, 0); | |
| 703 | put_byte(s, s->level == 9 ? 2 : | |
| 704 | (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? | |
| 705 | 4 : 0)); | |
| 706 | put_byte(s, OS_CODE); | |
| 707 | s->status = BUSY_STATE; | |
| 708 | } | |
| 709 | else { | |
| 710 | put_byte(s, (s->gzhead->text ? 1 : 0) + | |
| 711 | (s->gzhead->hcrc ? 2 : 0) + | |
| 712 | (s->gzhead->extra == Z_NULL ? 0 : 4) + | |
| 713 | (s->gzhead->name == Z_NULL ? 0 : 8) + | |
| 714 | (s->gzhead->comment == Z_NULL ? 0 : 16) | |
| 715 | ); | |
| 716 | put_byte(s, (Byte)(s->gzhead->time & 0xff)); | |
| 717 | put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); | |
| 718 | put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); | |
| 719 | put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); | |
| 720 | put_byte(s, s->level == 9 ? 2 : | |
| 721 | (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? | |
| 722 | 4 : 0)); | |
| 723 | put_byte(s, s->gzhead->os & 0xff); | |
| 724 | if (s->gzhead->extra != Z_NULL) { | |
| 725 | put_byte(s, s->gzhead->extra_len & 0xff); | |
| 726 | put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); | |
| 727 | } | |
| 728 | if (s->gzhead->hcrc) | |
| 729 | strm->adler = crc32(strm->adler, s->pending_buf, | |
| 730 | s->pending); | |
| 731 | s->gzindex = 0; | |
| 732 | s->status = EXTRA_STATE; | |
| 733 | } | |
| 734 | } | |
| 735 | else | |
| 736 | 736 | #endif |
| 737 | { | |
| 738 | uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; | |
| 739 | uInt level_flags; | |
| 737 | { | |
| 738 | uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; | |
| 739 | uInt level_flags; | |
| 740 | 740 | |
| 741 | if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) | |
| 742 | level_flags = 0; | |
| 743 | else if (s->level < 6) | |
| 744 | level_flags = 1; | |
| 745 | else if (s->level == 6) | |
| 746 | level_flags = 2; | |
| 747 | else | |
| 748 | level_flags = 3; | |
| 749 | header |= (level_flags << 6); | |
| 750 | if (s->strstart != 0) header |= PRESET_DICT; | |
| 751 | header += 31 - (header % 31); | |
| 741 | if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) | |
| 742 | level_flags = 0; | |
| 743 | else if (s->level < 6) | |
| 744 | level_flags = 1; | |
| 745 | else if (s->level == 6) | |
| 746 | level_flags = 2; | |
| 747 | else | |
| 748 | level_flags = 3; | |
| 749 | header |= (level_flags << 6); | |
| 750 | if (s->strstart != 0) header |= PRESET_DICT; | |
| 751 | header += 31 - (header % 31); | |
| 752 | 752 | |
| 753 | s->status = BUSY_STATE; | |
| 754 | putShortMSB(s, header); | |
| 753 | s->status = BUSY_STATE; | |
| 754 | putShortMSB(s, header); | |
| 755 | 755 | |
| 756 | /* Save the adler32 of the preset dictionary: */ | |
| 757 | if (s->strstart != 0) { | |
| 758 | putShortMSB(s, (uInt)(strm->adler >> 16)); | |
| 759 | putShortMSB(s, (uInt)(strm->adler & 0xffff)); | |
| 760 | } | |
| 761 | strm->adler = adler32(0L, Z_NULL, 0); | |
| 762 | } | |
| 763 | } | |
| 756 | /* Save the adler32 of the preset dictionary: */ | |
| 757 | if (s->strstart != 0) { | |
| 758 | putShortMSB(s, (uInt)(strm->adler >> 16)); | |
| 759 | putShortMSB(s, (uInt)(strm->adler & 0xffff)); | |
| 760 | } | |
| 761 | strm->adler = adler32(0L, Z_NULL, 0); | |
| 762 | } | |
| 763 | } | |
| 764 | 764 | #ifdef GZIP |
| 765 | if (s->status == EXTRA_STATE) { | |
| 766 | if (s->gzhead->extra != Z_NULL) { | |
| 767 | uInt beg = s->pending; /* start of bytes to update crc */ | |
| 765 | if (s->status == EXTRA_STATE) { | |
| 766 | if (s->gzhead->extra != Z_NULL) { | |
| 767 | uInt beg = s->pending; /* start of bytes to update crc */ | |
| 768 | 768 | |
| 769 | while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { | |
| 770 | if (s->pending == s->pending_buf_size) { | |
| 771 | if (s->gzhead->hcrc && s->pending > beg) | |
| 772 | strm->adler = crc32(strm->adler, s->pending_buf + beg, | |
| 773 | s->pending - beg); | |
| 774 | flush_pending(strm); | |
| 775 | beg = s->pending; | |
| 776 | if (s->pending == s->pending_buf_size) | |
| 777 | break; | |
| 778 | } | |
| 779 | put_byte(s, s->gzhead->extra[s->gzindex]); | |
| 780 | s->gzindex++; | |
| 781 | } | |
| 782 | if (s->gzhead->hcrc && s->pending > beg) | |
| 783 | strm->adler = crc32(strm->adler, s->pending_buf + beg, | |
| 784 | s->pending - beg); | |
| 785 | if (s->gzindex == s->gzhead->extra_len) { | |
| 786 | s->gzindex = 0; | |
| 787 | s->status = NAME_STATE; | |
| 788 | } | |
| 789 | } | |
| 790 | else | |
| 791 | s->status = NAME_STATE; | |
| 792 | } | |
| 793 | if (s->status == NAME_STATE) { | |
| 794 | if (s->gzhead->name != Z_NULL) { | |
| 795 | uInt beg = s->pending; /* start of bytes to update crc */ | |
| 796 | int val; | |
| 769 | while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { | |
| 770 | if (s->pending == s->pending_buf_size) { | |
| 771 | if (s->gzhead->hcrc && s->pending > beg) | |
| 772 | strm->adler = crc32(strm->adler, s->pending_buf + beg, | |
| 773 | s->pending - beg); | |
| 774 | flush_pending(strm); | |
| 775 | beg = s->pending; | |
| 776 | if (s->pending == s->pending_buf_size) | |
| 777 | break; | |
| 778 | } | |
| 779 | put_byte(s, s->gzhead->extra[s->gzindex]); | |
| 780 | s->gzindex++; | |
| 781 | } | |
| 782 | if (s->gzhead->hcrc && s->pending > beg) | |
| 783 | strm->adler = crc32(strm->adler, s->pending_buf + beg, | |
| 784 | s->pending - beg); | |
| 785 | if (s->gzindex == s->gzhead->extra_len) { | |
| 786 | s->gzindex = 0; | |
| 787 | s->status = NAME_STATE; | |
| 788 | } | |
| 789 | } | |
| 790 | else | |
| 791 | s->status = NAME_STATE; | |
| 792 | } | |
| 793 | if (s->status == NAME_STATE) { | |
| 794 | if (s->gzhead->name != Z_NULL) { | |
| 795 | uInt beg = s->pending; /* start of bytes to update crc */ | |
| 796 | int val; | |
| 797 | 797 | |
| 798 | do { | |
| 799 | if (s->pending == s->pending_buf_size) { | |
| 800 | if (s->gzhead->hcrc && s->pending > beg) | |
| 801 | strm->adler = crc32(strm->adler, s->pending_buf + beg, | |
| 802 | s->pending - beg); | |
| 803 | flush_pending(strm); | |
| 804 | beg = s->pending; | |
| 805 | if (s->pending == s->pending_buf_size) { | |
| 806 | val = 1; | |
| 807 | break; | |
| 808 | } | |
| 809 | } | |
| 810 | val = s->gzhead->name[s->gzindex++]; | |
| 811 | put_byte(s, val); | |
| 812 | } while (val != 0); | |
| 813 | if (s->gzhead->hcrc && s->pending > beg) | |
| 814 | strm->adler = crc32(strm->adler, s->pending_buf + beg, | |
| 815 | s->pending - beg); | |
| 816 | if (val == 0) { | |
| 817 | s->gzindex = 0; | |
| 818 | s->status = COMMENT_STATE; | |
| 819 | } | |
| 820 | } | |
| 821 | else | |
| 822 | s->status = COMMENT_STATE; | |
| 823 | } | |
| 824 | if (s->status == COMMENT_STATE) { | |
| 825 | if (s->gzhead->comment != Z_NULL) { | |
| 826 | uInt beg = s->pending; /* start of bytes to update crc */ | |
| 827 | int val; | |
| 798 | do { | |
| 799 | if (s->pending == s->pending_buf_size) { | |
| 800 | if (s->gzhead->hcrc && s->pending > beg) | |
| 801 | strm->adler = crc32(strm->adler, s->pending_buf + beg, | |
| 802 | s->pending - beg); | |
| 803 | flush_pending(strm); | |
| 804 | beg = s->pending; | |
| 805 | if (s->pending == s->pending_buf_size) { | |
| 806 | val = 1; | |
| 807 | break; | |
| 808 | } | |
| 809 | } | |
| 810 | val = s->gzhead->name[s->gzindex++]; | |
| 811 | put_byte(s, val); | |
| 812 | } while (val != 0); | |
| 813 | if (s->gzhead->hcrc && s->pending > beg) | |
| 814 | strm->adler = crc32(strm->adler, s->pending_buf + beg, | |
| 815 | s->pending - beg); | |
| 816 | if (val == 0) { | |
| 817 | s->gzindex = 0; | |
| 818 | s->status = COMMENT_STATE; | |
| 819 | } | |
| 820 | } | |
| 821 | else | |
| 822 | s->status = COMMENT_STATE; | |
| 823 | } | |
| 824 | if (s->status == COMMENT_STATE) { | |
| 825 | if (s->gzhead->comment != Z_NULL) { | |
| 826 | uInt beg = s->pending; /* start of bytes to update crc */ | |
| 827 | int val; | |
| 828 | 828 | |
| 829 | do { | |
| 830 | if (s->pending == s->pending_buf_size) { | |
| 831 | if (s->gzhead->hcrc && s->pending > beg) | |
| 832 | strm->adler = crc32(strm->adler, s->pending_buf + beg, | |
| 833 | s->pending - beg); | |
| 834 | flush_pending(strm); | |
| 835 | beg = s->pending; | |
| 836 | if (s->pending == s->pending_buf_size) { | |
| 837 | val = 1; | |
| 838 | break; | |
| 839 | } | |
| 840 | } | |
| 841 | val = s->gzhead->comment[s->gzindex++]; | |
| 842 | put_byte(s, val); | |
| 843 | } while (val != 0); | |
| 844 | if (s->gzhead->hcrc && s->pending > beg) | |
| 845 | strm->adler = crc32(strm->adler, s->pending_buf + beg, | |
| 846 | s->pending - beg); | |
| 847 | if (val == 0) | |
| 848 | s->status = HCRC_STATE; | |
| 849 | } | |
| 850 | else | |
| 851 | s->status = HCRC_STATE; | |
| 852 | } | |
| 853 | if (s->status == HCRC_STATE) { | |
| 854 | if (s->gzhead->hcrc) { | |
| 855 | if (s->pending + 2 > s->pending_buf_size) | |
| 856 | flush_pending(strm); | |
| 857 | if (s->pending + 2 <= s->pending_buf_size) { | |
| 858 | put_byte(s, (Byte)(strm->adler & 0xff)); | |
| 859 | put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); | |
| 860 | strm->adler = crc32(0L, Z_NULL, 0); | |
| 861 | s->status = BUSY_STATE; | |
| 862 | } | |
| 863 | } | |
| 864 | else | |
| 865 | s->status = BUSY_STATE; | |
| 866 | } | |
| 829 | do { | |
| 830 | if (s->pending == s->pending_buf_size) { | |
| 831 | if (s->gzhead->hcrc && s->pending > beg) | |
| 832 | strm->adler = crc32(strm->adler, s->pending_buf + beg, | |
| 833 | s->pending - beg); | |
| 834 | flush_pending(strm); | |
| 835 | beg = s->pending; | |
| 836 | if (s->pending == s->pending_buf_size) { | |
| 837 | val = 1; | |
| 838 | break; | |
| 839 | } | |
| 840 | } | |
| 841 | val = s->gzhead->comment[s->gzindex++]; | |
| 842 | put_byte(s, val); | |
| 843 | } while (val != 0); | |
| 844 | if (s->gzhead->hcrc && s->pending > beg) | |
| 845 | strm->adler = crc32(strm->adler, s->pending_buf + beg, | |
| 846 | s->pending - beg); | |
| 847 | if (val == 0) | |
| 848 | s->status = HCRC_STATE; | |
| 849 | } | |
| 850 | else | |
| 851 | s->status = HCRC_STATE; | |
| 852 | } | |
| 853 | if (s->status == HCRC_STATE) { | |
| 854 | if (s->gzhead->hcrc) { | |
| 855 | if (s->pending + 2 > s->pending_buf_size) | |
| 856 | flush_pending(strm); | |
| 857 | if (s->pending + 2 <= s->pending_buf_size) { | |
| 858 | put_byte(s, (Byte)(strm->adler & 0xff)); | |
| 859 | put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); | |
| 860 | strm->adler = crc32(0L, Z_NULL, 0); | |
| 861 | s->status = BUSY_STATE; | |
| 862 | } | |
| 863 | } | |
| 864 | else | |
| 865 | s->status = BUSY_STATE; | |
| 866 | } | |
| 867 | 867 | #endif |
| 868 | 868 | |
| 869 | /* Flush as much pending output as possible */ | |
| 870 | if (s->pending != 0) { | |
| 871 | flush_pending(strm); | |
| 872 | if (strm->avail_out == 0) { | |
| 873 | /* Since avail_out is 0, deflate will be called again with | |
| 874 | * more output space, but possibly with both pending and | |
| 875 | * avail_in equal to zero. There won't be anything to do, | |
| 876 | * but this is not an error situation so make sure we | |
| 877 | * return OK instead of BUF_ERROR at next call of deflate: | |
| 878 | */ | |
| 879 | s->last_flush = -1; | |
| 880 | return Z_OK; | |
| 881 | } | |
| 869 | /* Flush as much pending output as possible */ | |
| 870 | if (s->pending != 0) { | |
| 871 | flush_pending(strm); | |
| 872 | if (strm->avail_out == 0) { | |
| 873 | /* Since avail_out is 0, deflate will be called again with | |
| 874 | * more output space, but possibly with both pending and | |
| 875 | * avail_in equal to zero. There won't be anything to do, | |
| 876 | * but this is not an error situation so make sure we | |
| 877 | * return OK instead of BUF_ERROR at next call of deflate: | |
| 878 | */ | |
| 879 | s->last_flush = -1; | |
| 880 | return Z_OK; | |
| 881 | } | |
| 882 | 882 | |
| 883 | /* Make sure there is something to do and avoid duplicate consecutive | |
| 884 | * flushes. For repeated and useless calls with Z_FINISH, we keep | |
| 885 | * returning Z_STREAM_END instead of Z_BUF_ERROR. | |
| 886 | */ | |
| 887 | } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && | |
| 888 | flush != Z_FINISH) { | |
| 889 | ERR_RETURN(strm, Z_BUF_ERROR); | |
| 890 | } | |
| 883 | /* Make sure there is something to do and avoid duplicate consecutive | |
| 884 | * flushes. For repeated and useless calls with Z_FINISH, we keep | |
| 885 | * returning Z_STREAM_END instead of Z_BUF_ERROR. | |
| 886 | */ | |
| 887 | } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && | |
| 888 | flush != Z_FINISH) { | |
| 889 | ERR_RETURN(strm, Z_BUF_ERROR); | |
| 890 | } | |
| 891 | 891 | |
| 892 | /* User must not provide more input after the first FINISH: */ | |
| 893 | if (s->status == FINISH_STATE && strm->avail_in != 0) { | |
| 894 | ERR_RETURN(strm, Z_BUF_ERROR); | |
| 895 | } | |
| 892 | /* User must not provide more input after the first FINISH: */ | |
| 893 | if (s->status == FINISH_STATE && strm->avail_in != 0) { | |
| 894 | ERR_RETURN(strm, Z_BUF_ERROR); | |
| 895 | } | |
| 896 | 896 | |
| 897 | /* Start a new block or continue the current one. | |
| 898 | */ | |
| 899 | if (strm->avail_in != 0 || s->lookahead != 0 || | |
| 900 | (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { | |
| 901 | block_state bstate; | |
| 897 | /* Start a new block or continue the current one. | |
| 898 | */ | |
| 899 | if (strm->avail_in != 0 || s->lookahead != 0 || | |
| 900 | (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { | |
| 901 | block_state bstate; | |
| 902 | 902 | |
| 903 | bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : | |
| 904 | (s->strategy == Z_RLE ? deflate_rle(s, flush) : | |
| 905 | (*(configuration_table[s->level].func))(s, flush)); | |
| 903 | bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : | |
| 904 | (s->strategy == Z_RLE ? deflate_rle(s, flush) : | |
| 905 | (*(configuration_table[s->level].func))(s, flush)); | |
| 906 | 906 | |
| 907 | if (bstate == finish_started || bstate == finish_done) { | |
| 908 | s->status = FINISH_STATE; | |
| 909 | } | |
| 910 | if (bstate == need_more || bstate == finish_started) { | |
| 911 | if (strm->avail_out == 0) { | |
| 912 | s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ | |
| 913 | } | |
| 914 | return Z_OK; | |
| 915 | /* If flush != Z_NO_FLUSH && avail_out == 0, the next call | |
| 916 | * of deflate should use the same flush parameter to make sure | |
| 917 | * that the flush is complete. So we don't have to output an | |
| 918 | * empty block here, this will be done at next call. This also | |
| 919 | * ensures that for a very small output buffer, we emit at most | |
| 920 | * one empty block. | |
| 921 | */ | |
| 922 | } | |
| 923 | if (bstate == block_done) { | |
| 924 | if (flush == Z_PARTIAL_FLUSH) { | |
| 925 | _tr_align(s); | |
| 926 | } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ | |
| 927 | _tr_stored_block(s, (char*)0, 0L, 0); | |
| 928 | /* For a full flush, this empty block will be recognized | |
| 929 | * as a special marker by inflate_sync(). | |
| 930 | */ | |
| 931 | if (flush == Z_FULL_FLUSH) { | |
| 932 | CLEAR_HASH(s); /* forget history */ | |
| 933 | if (s->lookahead == 0) { | |
| 934 | s->strstart = 0; | |
| 935 | s->block_start = 0L; | |
| 936 | s->insert = 0; | |
| 937 | } | |
| 938 | } | |
| 939 | } | |
| 940 | flush_pending(strm); | |
| 941 | if (strm->avail_out == 0) { | |
| 942 | s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ | |
| 943 | return Z_OK; | |
| 944 | } | |
| 945 | } | |
| 946 | } | |
| 947 | Assert(strm->avail_out > 0, "bug2"); | |
| 907 | if (bstate == finish_started || bstate == finish_done) { | |
| 908 | s->status = FINISH_STATE; | |
| 909 | } | |
| 910 | if (bstate == need_more || bstate == finish_started) { | |
| 911 | if (strm->avail_out == 0) { | |
| 912 | s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ | |
| 913 | } | |
| 914 | return Z_OK; | |
| 915 | /* If flush != Z_NO_FLUSH && avail_out == 0, the next call | |
| 916 | * of deflate should use the same flush parameter to make sure | |
| 917 | * that the flush is complete. So we don't have to output an | |
| 918 | * empty block here, this will be done at next call. This also | |
| 919 | * ensures that for a very small output buffer, we emit at most | |
| 920 | * one empty block. | |
| 921 | */ | |
| 922 | } | |
| 923 | if (bstate == block_done) { | |
| 924 | if (flush == Z_PARTIAL_FLUSH) { | |
| 925 | _tr_align(s); | |
| 926 | } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ | |
| 927 | _tr_stored_block(s, (char*)0, 0L, 0); | |
| 928 | /* For a full flush, this empty block will be recognized | |
| 929 | * as a special marker by inflate_sync(). | |
| 930 | */ | |
| 931 | if (flush == Z_FULL_FLUSH) { | |
| 932 | CLEAR_HASH(s); /* forget history */ | |
| 933 | if (s->lookahead == 0) { | |
| 934 | s->strstart = 0; | |
| 935 | s->block_start = 0L; | |
| 936 | s->insert = 0; | |
| 937 | } | |
| 938 | } | |
| 939 | } | |
| 940 | flush_pending(strm); | |
| 941 | if (strm->avail_out == 0) { | |
| 942 | s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ | |
| 943 | return Z_OK; | |
| 944 | } | |
| 945 | } | |
| 946 | } | |
| 947 | Assert(strm->avail_out > 0, "bug2"); | |
| 948 | 948 | |
| 949 | if (flush != Z_FINISH) return Z_OK; | |
| 950 | if (s->wrap <= 0) return Z_STREAM_END; | |
| 949 | if (flush != Z_FINISH) return Z_OK; | |
| 950 | if (s->wrap <= 0) return Z_STREAM_END; | |
| 951 | 951 | |
| 952 | ||
| 952 | /* Write the trailer */ | |
| 953 | 953 | #ifdef GZIP |
| 954 | if (s->wrap == 2) { | |
| 955 | put_byte(s, (Byte)(strm->adler & 0xff)); | |
| 956 | put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); | |
| 957 | put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); | |
| 958 | put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); | |
| 959 | put_byte(s, (Byte)(strm->total_in & 0xff)); | |
| 960 | put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); | |
| 961 | put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); | |
| 962 | put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); | |
| 963 | } | |
| 964 | else | |
| 954 | if (s->wrap == 2) { | |
| 955 | put_byte(s, (Byte)(strm->adler & 0xff)); | |
| 956 | put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); | |
| 957 | put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); | |
| 958 | put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); | |
| 959 | put_byte(s, (Byte)(strm->total_in & 0xff)); | |
| 960 | put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); | |
| 961 | put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); | |
| 962 | put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); | |
| 963 | } | |
| 964 | else | |
| 965 | 965 | #endif |
| 966 | { | |
| 967 | putShortMSB(s, (uInt)(strm->adler >> 16)); | |
| 968 | putShortMSB(s, (uInt)(strm->adler & 0xffff)); | |
| 969 | } | |
| 970 | flush_pending(strm); | |
| 971 | /* If avail_out is zero, the application will call deflate again | |
| 972 | * to flush the rest. | |
| 973 | */ | |
| 974 | if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ | |
| 975 | return s->pending != 0 ? Z_OK : Z_STREAM_END; | |
| 966 | { | |
| 967 | putShortMSB(s, (uInt)(strm->adler >> 16)); | |
| 968 | putShortMSB(s, (uInt)(strm->adler & 0xffff)); | |
| 969 | } | |
| 970 | flush_pending(strm); | |
| 971 | /* If avail_out is zero, the application will call deflate again | |
| 972 | * to flush the rest. | |
| 973 | */ | |
| 974 | if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ | |
| 975 | return s->pending != 0 ? Z_OK : Z_STREAM_END; | |
| 976 | 976 | } |
| 977 | 977 | |
| 978 | 978 | /* ========================================================================= */ |
| 979 | 979 | int ZEXPORT deflateEnd (strm) |
| 980 | ||
| 980 | z_streamp strm; | |
| 981 | 981 | { |
| 982 | ||
| 982 | int status; | |
| 983 | 983 | |
| 984 | ||
| 984 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 985 | 985 | |
| 986 | status = strm->state->status; | |
| 987 | if (status != INIT_STATE && | |
| 988 | status != EXTRA_STATE && | |
| 989 | status != NAME_STATE && | |
| 990 | status != COMMENT_STATE && | |
| 991 | status != HCRC_STATE && | |
| 992 | status != BUSY_STATE && | |
| 993 | status != FINISH_STATE) { | |
| 994 | return Z_STREAM_ERROR; | |
| 995 | } | |
| 986 | status = strm->state->status; | |
| 987 | if (status != INIT_STATE && | |
| 988 | status != EXTRA_STATE && | |
| 989 | status != NAME_STATE && | |
| 990 | status != COMMENT_STATE && | |
| 991 | status != HCRC_STATE && | |
| 992 | status != BUSY_STATE && | |
| 993 | status != FINISH_STATE) { | |
| 994 | return Z_STREAM_ERROR; | |
| 995 | } | |
| 996 | 996 | |
| 997 | /* Deallocate in reverse order of allocations: */ | |
| 998 | TRY_FREE(strm, strm->state->pending_buf); | |
| 999 | TRY_FREE(strm, strm->state->head); | |
| 1000 | TRY_FREE(strm, strm->state->prev); | |
| 1001 | TRY_FREE(strm, strm->state->window); | |
| 997 | /* Deallocate in reverse order of allocations: */ | |
| 998 | TRY_FREE(strm, strm->state->pending_buf); | |
| 999 | TRY_FREE(strm, strm->state->head); | |
| 1000 | TRY_FREE(strm, strm->state->prev); | |
| 1001 | TRY_FREE(strm, strm->state->window); | |
| 1002 | 1002 | |
| 1003 | ZFREE(strm, strm->state); | |
| 1004 | strm->state = Z_NULL; | |
| 1003 | ZFREE(strm, strm->state); | |
| 1004 | strm->state = Z_NULL; | |
| 1005 | 1005 | |
| 1006 | ||
| 1006 | return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; | |
| 1007 | 1007 | } |
| 1008 | 1008 | |
| 1009 | 1009 | /* ========================================================================= |
| r25360 | r25361 | |
| 1012 | 1012 | * doesn't have enough memory anyway to duplicate compression states). |
| 1013 | 1013 | */ |
| 1014 | 1014 | int ZEXPORT deflateCopy (dest, source) |
| 1015 | z_streamp dest; | |
| 1016 | z_streamp source; | |
| 1015 | z_streamp dest; | |
| 1016 | z_streamp source; | |
| 1017 | 1017 | { |
| 1018 | 1018 | #ifdef MAXSEG_64K |
| 1019 | ||
| 1019 | return Z_STREAM_ERROR; | |
| 1020 | 1020 | #else |
| 1021 | deflate_state *ds; | |
| 1022 | deflate_state *ss; | |
| 1023 | ushf *overlay; | |
| 1021 | deflate_state *ds; | |
| 1022 | deflate_state *ss; | |
| 1023 | ushf *overlay; | |
| 1024 | 1024 | |
| 1025 | 1025 | |
| 1026 | if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { | |
| 1027 | return Z_STREAM_ERROR; | |
| 1028 | } | |
| 1026 | if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { | |
| 1027 | return Z_STREAM_ERROR; | |
| 1028 | } | |
| 1029 | 1029 | |
| 1030 | ||
| 1030 | ss = source->state; | |
| 1031 | 1031 | |
| 1032 | ||
| 1032 | zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); | |
| 1033 | 1033 | |
| 1034 | ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); | |
| 1035 | if (ds == Z_NULL) return Z_MEM_ERROR; | |
| 1036 | dest->state = (struct internal_state FAR *) ds; | |
| 1037 | zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state)); | |
| 1038 | ds->strm = dest; | |
| 1034 | ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); | |
| 1035 | if (ds == Z_NULL) return Z_MEM_ERROR; | |
| 1036 | dest->state = (struct internal_state FAR *) ds; | |
| 1037 | zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state)); | |
| 1038 | ds->strm = dest; | |
| 1039 | 1039 | |
| 1040 | ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); | |
| 1041 | ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); | |
| 1042 | ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); | |
| 1043 | overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); | |
| 1044 | ds->pending_buf = (uchf *) overlay; | |
| 1040 | ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); | |
| 1041 | ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); | |
| 1042 | ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); | |
| 1043 | overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); | |
| 1044 | ds->pending_buf = (uchf *) overlay; | |
| 1045 | 1045 | |
| 1046 | if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || | |
| 1047 | ds->pending_buf == Z_NULL) { | |
| 1048 | deflateEnd (dest); | |
| 1049 | return Z_MEM_ERROR; | |
| 1050 | } | |
| 1051 | /* following zmemcpy do not work for 16-bit MSDOS */ | |
| 1052 | zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); | |
| 1053 | zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos)); | |
| 1054 | zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos)); | |
| 1055 | zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); | |
| 1046 | if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || | |
| 1047 | ds->pending_buf == Z_NULL) { | |
| 1048 | deflateEnd (dest); | |
| 1049 | return Z_MEM_ERROR; | |
| 1050 | } | |
| 1051 | /* following zmemcpy do not work for 16-bit MSDOS */ | |
| 1052 | zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); | |
| 1053 | zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos)); | |
| 1054 | zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos)); | |
| 1055 | zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); | |
| 1056 | 1056 | |
| 1057 | ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); | |
| 1058 | ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); | |
| 1059 | ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; | |
| 1057 | ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); | |
| 1058 | ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); | |
| 1059 | ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; | |
| 1060 | 1060 | |
| 1061 | ds->l_desc.dyn_tree = ds->dyn_ltree; | |
| 1062 | ds->d_desc.dyn_tree = ds->dyn_dtree; | |
| 1063 | ds->bl_desc.dyn_tree = ds->bl_tree; | |
| 1061 | ds->l_desc.dyn_tree = ds->dyn_ltree; | |
| 1062 | ds->d_desc.dyn_tree = ds->dyn_dtree; | |
| 1063 | ds->bl_desc.dyn_tree = ds->bl_tree; | |
| 1064 | 1064 | |
| 1065 | ||
| 1065 | return Z_OK; | |
| 1066 | 1066 | #endif /* MAXSEG_64K */ |
| 1067 | 1067 | } |
| 1068 | 1068 | |
| r25360 | r25361 | |
| 1074 | 1074 | * (See also flush_pending()). |
| 1075 | 1075 | */ |
| 1076 | 1076 | local int read_buf(strm, buf, size) |
| 1077 | z_streamp strm; | |
| 1078 | Bytef *buf; | |
| 1079 | unsigned size; | |
| 1077 | z_streamp strm; | |
| 1078 | Bytef *buf; | |
| 1079 | unsigned size; | |
| 1080 | 1080 | { |
| 1081 | ||
| 1081 | unsigned len = strm->avail_in; | |
| 1082 | 1082 | |
| 1083 | if (len > size) len = size; | |
| 1084 | if (len == 0) return 0; | |
| 1083 | if (len > size) len = size; | |
| 1084 | if (len == 0) return 0; | |
| 1085 | 1085 | |
| 1086 | ||
| 1086 | strm->avail_in -= len; | |
| 1087 | 1087 | |
| 1088 | zmemcpy(buf, strm->next_in, len); | |
| 1089 | if (strm->state->wrap == 1) { | |
| 1090 | strm->adler = adler32(strm->adler, buf, len); | |
| 1091 | } | |
| 1088 | zmemcpy(buf, strm->next_in, len); | |
| 1089 | if (strm->state->wrap == 1) { | |
| 1090 | strm->adler = adler32(strm->adler, buf, len); | |
| 1091 | } | |
| 1092 | 1092 | #ifdef GZIP |
| 1093 | else if (strm->state->wrap == 2) { | |
| 1094 | strm->adler = crc32(strm->adler, buf, len); | |
| 1095 | } | |
| 1093 | else if (strm->state->wrap == 2) { | |
| 1094 | strm->adler = crc32(strm->adler, buf, len); | |
| 1095 | } | |
| 1096 | 1096 | #endif |
| 1097 | strm->next_in += len; | |
| 1098 | strm->total_in += len; | |
| 1097 | strm->next_in += len; | |
| 1098 | strm->total_in += len; | |
| 1099 | 1099 | |
| 1100 | ||
| 1100 | return (int)len; | |
| 1101 | 1101 | } |
| 1102 | 1102 | |
| 1103 | 1103 | /* =========================================================================== |
| 1104 | 1104 | * Initialize the "longest match" routines for a new zlib stream |
| 1105 | 1105 | */ |
| 1106 | 1106 | local void lm_init (s) |
| 1107 | ||
| 1107 | deflate_state *s; | |
| 1108 | 1108 | { |
| 1109 | ||
| 1109 | s->window_size = (ulg)2L*s->w_size; | |
| 1110 | 1110 | |
| 1111 | ||
| 1111 | CLEAR_HASH(s); | |
| 1112 | 1112 | |
| 1113 | /* Set the default configuration parameters: | |
| 1114 | */ | |
| 1115 | s->max_lazy_match = configuration_table[s->level].max_lazy; | |
| 1116 | s->good_match = configuration_table[s->level].good_length; | |
| 1117 | s->nice_match = configuration_table[s->level].nice_length; | |
| 1118 | s->max_chain_length = configuration_table[s->level].max_chain; | |
| 1113 | /* Set the default configuration parameters: | |
| 1114 | */ | |
| 1115 | s->max_lazy_match = configuration_table[s->level].max_lazy; | |
| 1116 | s->good_match = configuration_table[s->level].good_length; | |
| 1117 | s->nice_match = configuration_table[s->level].nice_length; | |
| 1118 | s->max_chain_length = configuration_table[s->level].max_chain; | |
| 1119 | 1119 | |
| 1120 | s->strstart = 0; | |
| 1121 | s->block_start = 0L; | |
| 1122 | s->lookahead = 0; | |
| 1123 | s->insert = 0; | |
| 1124 | s->match_length = s->prev_length = MIN_MATCH-1; | |
| 1125 | s->match_available = 0; | |
| 1126 | s->ins_h = 0; | |
| 1120 | s->strstart = 0; | |
| 1121 | s->block_start = 0L; | |
| 1122 | s->lookahead = 0; | |
| 1123 | s->insert = 0; | |
| 1124 | s->match_length = s->prev_length = MIN_MATCH-1; | |
| 1125 | s->match_available = 0; | |
| 1126 | s->ins_h = 0; | |
| 1127 | 1127 | #ifndef FASTEST |
| 1128 | 1128 | #ifdef ASMV |
| 1129 | ||
| 1129 | match_init(); /* initialize the asm code */ | |
| 1130 | 1130 | #endif |
| 1131 | 1131 | #endif |
| 1132 | 1132 | } |
| r25360 | r25361 | |
| 1146 | 1146 | * match.S. The code will be functionally equivalent. |
| 1147 | 1147 | */ |
| 1148 | 1148 | local uInt longest_match(s, cur_match) |
| 1149 | deflate_state *s; | |
| 1150 | IPos cur_match; /* current match */ | |
| 1149 | deflate_state *s; | |
| 1150 | IPos cur_match; /* current match */ | |
| 1151 | 1151 | { |
| 1152 | unsigned chain_length = s->max_chain_length;/* max hash chain length */ | |
| 1153 | register Bytef *scan = s->window + s->strstart; /* current string */ | |
| 1154 | register Bytef *match; /* matched string */ | |
| 1155 | register int len; /* length of current match */ | |
| 1156 | int best_len = s->prev_length; /* best match length so far */ | |
| 1157 | int nice_match = s->nice_match; /* stop if match long enough */ | |
| 1158 | IPos limit = s->strstart > (IPos)MAX_DIST(s) ? | |
| 1159 | s->strstart - (IPos)MAX_DIST(s) : NIL; | |
| 1160 | /* Stop when cur_match becomes <= limit. To simplify the code, | |
| 1161 | * we prevent matches with the string of window index 0. | |
| 1162 | */ | |
| 1163 | Posf *prev = s->prev; | |
| 1164 | uInt wmask = s->w_mask; | |
| 1152 | unsigned chain_length = s->max_chain_length;/* max hash chain length */ | |
| 1153 | register Bytef *scan = s->window + s->strstart; /* current string */ | |
| 1154 | register Bytef *match; /* matched string */ | |
| 1155 | register int len; /* length of current match */ | |
| 1156 | int best_len = s->prev_length; /* best match length so far */ | |
| 1157 | int nice_match = s->nice_match; /* stop if match long enough */ | |
| 1158 | IPos limit = s->strstart > (IPos)MAX_DIST(s) ? | |
| 1159 | s->strstart - (IPos)MAX_DIST(s) : NIL; | |
| 1160 | /* Stop when cur_match becomes <= limit. To simplify the code, | |
| 1161 | * we prevent matches with the string of window index 0. | |
| 1162 | */ | |
| 1163 | Posf *prev = s->prev; | |
| 1164 | uInt wmask = s->w_mask; | |
| 1165 | 1165 | |
| 1166 | 1166 | #ifdef UNALIGNED_OK |
| 1167 | /* Compare two bytes at a time. Note: this is not always beneficial. | |
| 1168 | * Try with and without -DUNALIGNED_OK to check. | |
| 1169 | */ | |
| 1170 | register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; | |
| 1171 | register ush scan_start = *(ushf*)scan; | |
| 1172 | register ush scan_end = *(ushf*)(scan+best_len-1); | |
| 1167 | /* Compare two bytes at a time. Note: this is not always beneficial. | |
| 1168 | * Try with and without -DUNALIGNED_OK to check. | |
| 1169 | */ | |
| 1170 | register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; | |
| 1171 | register ush scan_start = *(ushf*)scan; | |
| 1172 | register ush scan_end = *(ushf*)(scan+best_len-1); | |
| 1173 | 1173 | #else |
| 1174 | register Bytef *strend = s->window + s->strstart + MAX_MATCH; | |
| 1175 | register Byte scan_end1 = scan[best_len-1]; | |
| 1176 | register Byte scan_end = scan[best_len]; | |
| 1174 | register Bytef *strend = s->window + s->strstart + MAX_MATCH; | |
| 1175 | register Byte scan_end1 = scan[best_len-1]; | |
| 1176 | register Byte scan_end = scan[best_len]; | |
| 1177 | 1177 | #endif |
| 1178 | 1178 | |
| 1179 | /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. | |
| 1180 | * It is easy to get rid of this optimization if necessary. | |
| 1181 | */ | |
| 1182 | Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); | |
| 1179 | /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. | |
| 1180 | * It is easy to get rid of this optimization if necessary. | |
| 1181 | */ | |
| 1182 | Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); | |
| 1183 | 1183 | |
| 1184 | /* Do not waste too much time if we already have a good match: */ | |
| 1185 | if (s->prev_length >= s->good_match) { | |
| 1186 | chain_length >>= 2; | |
| 1187 | } | |
| 1188 | /* Do not look for matches beyond the end of the input. This is necessary | |
| 1189 | * to make deflate deterministic. | |
| 1190 | */ | |
| 1191 | if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; | |
| 1184 | /* Do not waste too much time if we already have a good match: */ | |
| 1185 | if (s->prev_length >= s->good_match) { | |
| 1186 | chain_length >>= 2; | |
| 1187 | } | |
| 1188 | /* Do not look for matches beyond the end of the input. This is necessary | |
| 1189 | * to make deflate deterministic. | |
| 1190 | */ | |
| 1191 | if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; | |
| 1192 | 1192 | |
| 1193 | ||
| 1193 | Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); | |
| 1194 | 1194 | |
| 1195 | do { | |
| 1196 | Assert(cur_match < s->strstart, "no future"); | |
| 1197 | match = s->window + cur_match; | |
| 1195 | do { | |
| 1196 | Assert(cur_match < s->strstart, "no future"); | |
| 1197 | match = s->window + cur_match; | |
| 1198 | 1198 | |
| 1199 | /* Skip to next match if the match length cannot increase | |
| 1200 | * or if the match length is less than 2. Note that the checks below | |
| 1201 | * for insufficient lookahead only occur occasionally for performance | |
| 1202 | * reasons. Therefore uninitialized memory will be accessed, and | |
| 1203 | * conditional jumps will be made that depend on those values. | |
| 1204 | * However the length of the match is limited to the lookahead, so | |
| 1205 | * the output of deflate is not affected by the uninitialized values. | |
| 1206 | */ | |
| 1199 | /* Skip to next match if the match length cannot increase | |
| 1200 | * or if the match length is less than 2. Note that the checks below | |
| 1201 | * for insufficient lookahead only occur occasionally for performance | |
| 1202 | * reasons. Therefore uninitialized memory will be accessed, and | |
| 1203 | * conditional jumps will be made that depend on those values. | |
| 1204 | * However the length of the match is limited to the lookahead, so | |
| 1205 | * the output of deflate is not affected by the uninitialized values. | |
| 1206 | */ | |
| 1207 | 1207 | #if (defined(UNALIGNED_OK) && MAX_MATCH == 258) |
| 1208 | /* This code assumes sizeof(unsigned short) == 2. Do not use | |
| 1209 | * UNALIGNED_OK if your compiler uses a different size. | |
| 1210 | */ | |
| 1211 | if (*(ushf*)(match+best_len-1) != scan_end || | |
| 1212 | *(ushf*)match != scan_start) continue; | |
| 1208 | /* This code assumes sizeof(unsigned short) == 2. Do not use | |
| 1209 | * UNALIGNED_OK if your compiler uses a different size. | |
| 1210 | */ | |
| 1211 | if (*(ushf*)(match+best_len-1) != scan_end || | |
| 1212 | *(ushf*)match != scan_start) continue; | |
| 1213 | 1213 | |
| 1214 | /* It is not necessary to compare scan[2] and match[2] since they are | |
| 1215 | * always equal when the other bytes match, given that the hash keys | |
| 1216 | * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at | |
| 1217 | * strstart+3, +5, ... up to strstart+257. We check for insufficient | |
| 1218 | * lookahead only every 4th comparison; the 128th check will be made | |
| 1219 | * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is | |
| 1220 | * necessary to put more guard bytes at the end of the window, or | |
| 1221 | * to check more often for insufficient lookahead. | |
| 1222 | */ | |
| 1223 | Assert(scan[2] == match[2], "scan[2]?"); | |
| 1224 | scan++, match++; | |
| 1225 | do { | |
| 1226 | } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && | |
| 1227 | *(ushf*)(scan+=2) == *(ushf*)(match+=2) && | |
| 1228 | *(ushf*)(scan+=2) == *(ushf*)(match+=2) && | |
| 1229 | *(ushf*)(scan+=2) == *(ushf*)(match+=2) && | |
| 1230 | scan < strend); | |
| 1231 | /* The funny "do {}" generates better code on most compilers */ | |
| 1214 | /* It is not necessary to compare scan[2] and match[2] since they are | |
| 1215 | * always equal when the other bytes match, given that the hash keys | |
| 1216 | * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at | |
| 1217 | * strstart+3, +5, ... up to strstart+257. We check for insufficient | |
| 1218 | * lookahead only every 4th comparison; the 128th check will be made | |
| 1219 | * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is | |
| 1220 | * necessary to put more guard bytes at the end of the window, or | |
| 1221 | * to check more often for insufficient lookahead. | |
| 1222 | */ | |
| 1223 | Assert(scan[2] == match[2], "scan[2]?"); | |
| 1224 | scan++, match++; | |
| 1225 | do { | |
| 1226 | } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && | |
| 1227 | *(ushf*)(scan+=2) == *(ushf*)(match+=2) && | |
| 1228 | *(ushf*)(scan+=2) == *(ushf*)(match+=2) && | |
| 1229 | *(ushf*)(scan+=2) == *(ushf*)(match+=2) && | |
| 1230 | scan < strend); | |
| 1231 | /* The funny "do {}" generates better code on most compilers */ | |
| 1232 | 1232 | |
| 1233 | /* Here, scan <= window+strstart+257 */ | |
| 1234 | Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); | |
| 1235 | if (*scan == *match) scan++; | |
| 1233 | /* Here, scan <= window+strstart+257 */ | |
| 1234 | Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); | |
| 1235 | if (*scan == *match) scan++; | |
| 1236 | 1236 | |
| 1237 | len = (MAX_MATCH - 1) - (int)(strend-scan); | |
| 1238 | scan = strend - (MAX_MATCH-1); | |
| 1237 | len = (MAX_MATCH - 1) - (int)(strend-scan); | |
| 1238 | scan = strend - (MAX_MATCH-1); | |
| 1239 | 1239 | |
| 1240 | 1240 | #else /* UNALIGNED_OK */ |
| 1241 | 1241 | |
| 1242 | if (match[best_len] != scan_end || | |
| 1243 | match[best_len-1] != scan_end1 || | |
| 1244 | *match != *scan || | |
| 1245 | *++match != scan[1]) continue; | |
| 1242 | if (match[best_len] != scan_end || | |
| 1243 | match[best_len-1] != scan_end1 || | |
| 1244 | *match != *scan || | |
| 1245 | *++match != scan[1]) continue; | |
| 1246 | 1246 | |
| 1247 | /* The check at best_len-1 can be removed because it will be made | |
| 1248 | * again later. (This heuristic is not always a win.) | |
| 1249 | * It is not necessary to compare scan[2] and match[2] since they | |
| 1250 | * are always equal when the other bytes match, given that | |
| 1251 | * the hash keys are equal and that HASH_BITS >= 8. | |
| 1252 | */ | |
| 1253 | scan += 2, match++; | |
| 1254 | Assert(*scan == *match, "match[2]?"); | |
| 1247 | /* The check at best_len-1 can be removed because it will be made | |
| 1248 | * again later. (This heuristic is not always a win.) | |
| 1249 | * It is not necessary to compare scan[2] and match[2] since they | |
| 1250 | * are always equal when the other bytes match, given that | |
| 1251 | * the hash keys are equal and that HASH_BITS >= 8. | |
| 1252 | */ | |
| 1253 | scan += 2, match++; | |
| 1254 | Assert(*scan == *match, "match[2]?"); | |
| 1255 | 1255 | |
| 1256 | /* We check for insufficient lookahead only every 8th comparison; | |
| 1257 | * the 256th check will be made at strstart+258. | |
| 1258 | */ | |
| 1259 | do { | |
| 1260 | } while (*++scan == *++match && *++scan == *++match && | |
| 1261 | *++scan == *++match && *++scan == *++match && | |
| 1262 | *++scan == *++match && *++scan == *++match && | |
| 1263 | *++scan == *++match && *++scan == *++match && | |
| 1264 | scan < strend); | |
| 1256 | /* We check for insufficient lookahead only every 8th comparison; | |
| 1257 | * the 256th check will be made at strstart+258. | |
| 1258 | */ | |
| 1259 | do { | |
| 1260 | } while (*++scan == *++match && *++scan == *++match && | |
| 1261 | *++scan == *++match && *++scan == *++match && | |
| 1262 | *++scan == *++match && *++scan == *++match && | |
| 1263 | *++scan == *++match && *++scan == *++match && | |
| 1264 | scan < strend); | |
| 1265 | 1265 | |
| 1266 | ||
| 1266 | Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); | |
| 1267 | 1267 | |
| 1268 | len = MAX_MATCH - (int)(strend - scan); | |
| 1269 | scan = strend - MAX_MATCH; | |
| 1268 | len = MAX_MATCH - (int)(strend - scan); | |
| 1269 | scan = strend - MAX_MATCH; | |
| 1270 | 1270 | |
| 1271 | 1271 | #endif /* UNALIGNED_OK */ |
| 1272 | 1272 | |
| 1273 | if (len > best_len) { | |
| 1274 | s->match_start = cur_match; | |
| 1275 | best_len = len; | |
| 1276 | if (len >= nice_match) break; | |
| 1273 | if (len > best_len) { | |
| 1274 | s->match_start = cur_match; | |
| 1275 | best_len = len; | |
| 1276 | if (len >= nice_match) break; | |
| 1277 | 1277 | #ifdef UNALIGNED_OK |
| 1278 | ||
| 1278 | scan_end = *(ushf*)(scan+best_len-1); | |
| 1279 | 1279 | #else |
| 1280 | scan_end1 = scan[best_len-1]; | |
| 1281 | scan_end = scan[best_len]; | |
| 1280 | scan_end1 = scan[best_len-1]; | |
| 1281 | scan_end = scan[best_len]; | |
| 1282 | 1282 | #endif |
| 1283 | } | |
| 1284 | } while ((cur_match = prev[cur_match & wmask]) > limit | |
| 1285 | && --chain_length != 0); | |
| 1283 | } | |
| 1284 | } while ((cur_match = prev[cur_match & wmask]) > limit | |
| 1285 | && --chain_length != 0); | |
| 1286 | 1286 | |
| 1287 | if ((uInt)best_len <= s->lookahead) return (uInt)best_len; | |
| 1288 | return s->lookahead; | |
| 1287 | if ((uInt)best_len <= s->lookahead) return (uInt)best_len; | |
| 1288 | return s->lookahead; | |
| 1289 | 1289 | } |
| 1290 | 1290 | #endif /* ASMV */ |
| 1291 | 1291 | |
| r25360 | r25361 | |
| 1295 | 1295 | * Optimized version for FASTEST only |
| 1296 | 1296 | */ |
| 1297 | 1297 | local uInt longest_match(s, cur_match) |
| 1298 | deflate_state *s; | |
| 1299 | IPos cur_match; /* current match */ | |
| 1298 | deflate_state *s; | |
| 1299 | IPos cur_match; /* current match */ | |
| 1300 | 1300 | { |
| 1301 | register Bytef *scan = s->window + s->strstart; /* current string */ | |
| 1302 | register Bytef *match; /* matched string */ | |
| 1303 | register int len; /* length of current match */ | |
| 1304 | register Bytef *strend = s->window + s->strstart + MAX_MATCH; | |
| 1301 | register Bytef *scan = s->window + s->strstart; /* current string */ | |
| 1302 | register Bytef *match; /* matched string */ | |
| 1303 | register int len; /* length of current match */ | |
| 1304 | register Bytef *strend = s->window + s->strstart + MAX_MATCH; | |
| 1305 | 1305 | |
| 1306 | /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. | |
| 1307 | * It is easy to get rid of this optimization if necessary. | |
| 1308 | */ | |
| 1309 | Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); | |
| 1306 | /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. | |
| 1307 | * It is easy to get rid of this optimization if necessary. | |
| 1308 | */ | |
| 1309 | Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); | |
| 1310 | 1310 | |
| 1311 | ||
| 1311 | Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); | |
| 1312 | 1312 | |
| 1313 | ||
| 1313 | Assert(cur_match < s->strstart, "no future"); | |
| 1314 | 1314 | |
| 1315 | ||
| 1315 | match = s->window + cur_match; | |
| 1316 | 1316 | |
| 1317 | /* Return failure if the match length is less than 2: | |
| 1318 | */ | |
| 1319 | if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; | |
| 1317 | /* Return failure if the match length is less than 2: | |
| 1318 | */ | |
| 1319 | if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; | |
| 1320 | 1320 | |
| 1321 | /* The check at best_len-1 can be removed because it will be made | |
| 1322 | * again later. (This heuristic is not always a win.) | |
| 1323 | * It is not necessary to compare scan[2] and match[2] since they | |
| 1324 | * are always equal when the other bytes match, given that | |
| 1325 | * the hash keys are equal and that HASH_BITS >= 8. | |
| 1326 | */ | |
| 1327 | scan += 2, match += 2; | |
| 1328 | Assert(*scan == *match, "match[2]?"); | |
| 1321 | /* The check at best_len-1 can be removed because it will be made | |
| 1322 | * again later. (This heuristic is not always a win.) | |
| 1323 | * It is not necessary to compare scan[2] and match[2] since they | |
| 1324 | * are always equal when the other bytes match, given that | |
| 1325 | * the hash keys are equal and that HASH_BITS >= 8. | |
| 1326 | */ | |
| 1327 | scan += 2, match += 2; | |
| 1328 | Assert(*scan == *match, "match[2]?"); | |
| 1329 | 1329 | |
| 1330 | /* We check for insufficient lookahead only every 8th comparison; | |
| 1331 | * the 256th check will be made at strstart+258. | |
| 1332 | */ | |
| 1333 | do { | |
| 1334 | } while (*++scan == *++match && *++scan == *++match && | |
| 1335 | *++scan == *++match && *++scan == *++match && | |
| 1336 | *++scan == *++match && *++scan == *++match && | |
| 1337 | *++scan == *++match && *++scan == *++match && | |
| 1338 | scan < strend); | |
| 1330 | /* We check for insufficient lookahead only every 8th comparison; | |
| 1331 | * the 256th check will be made at strstart+258. | |
| 1332 | */ | |
| 1333 | do { | |
| 1334 | } while (*++scan == *++match && *++scan == *++match && | |
| 1335 | *++scan == *++match && *++scan == *++match && | |
| 1336 | *++scan == *++match && *++scan == *++match && | |
| 1337 | *++scan == *++match && *++scan == *++match && | |
| 1338 | scan < strend); | |
| 1339 | 1339 | |
| 1340 | ||
| 1340 | Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); | |
| 1341 | 1341 | |
| 1342 | ||
| 1342 | len = MAX_MATCH - (int)(strend - scan); | |
| 1343 | 1343 | |
| 1344 | ||
| 1344 | if (len < MIN_MATCH) return MIN_MATCH - 1; | |
| 1345 | 1345 | |
| 1346 | s->match_start = cur_match; | |
| 1347 | return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; | |
| 1346 | s->match_start = cur_match; | |
| 1347 | return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; | |
| 1348 | 1348 | } |
| 1349 | 1349 | |
| 1350 | 1350 | #endif /* FASTEST */ |
| r25360 | r25361 | |
| 1354 | 1354 | * Check that the match at match_start is indeed a match. |
| 1355 | 1355 | */ |
| 1356 | 1356 | local void check_match(s, start, match, length) |
| 1357 | deflate_state *s; | |
| 1358 | IPos start, match; | |
| 1359 | int length; | |
| 1357 | deflate_state *s; | |
| 1358 | IPos start, match; | |
| 1359 | int length; | |
| 1360 | 1360 | { |
| 1361 | /* check that the match is indeed a match */ | |
| 1362 | if (zmemcmp(s->window + match, | |
| 1363 | s->window + start, length) != EQUAL) { | |
| 1364 | fprintf(stderr, " start %u, match %u, length %d\n", | |
| 1365 | start, match, length); | |
| 1366 | do { | |
| 1367 | fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); | |
| 1368 | } while (--length != 0); | |
| 1369 | z_error("invalid match"); | |
| 1370 | } | |
| 1371 | if (z_verbose > 1) { | |
| 1372 | fprintf(stderr,"\\[%d,%d]", start-match, length); | |
| 1373 | do { putc(s->window[start++], stderr); } while (--length != 0); | |
| 1374 | } | |
| 1361 | /* check that the match is indeed a match */ | |
| 1362 | if (zmemcmp(s->window + match, | |
| 1363 | s->window + start, length) != EQUAL) { | |
| 1364 | fprintf(stderr, " start %u, match %u, length %d\n", | |
| 1365 | start, match, length); | |
| 1366 | do { | |
| 1367 | fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); | |
| 1368 | } while (--length != 0); | |
| 1369 | z_error("invalid match"); | |
| 1370 | } | |
| 1371 | if (z_verbose > 1) { | |
| 1372 | fprintf(stderr,"\\[%d,%d]", start-match, length); | |
| 1373 | do { putc(s->window[start++], stderr); } while (--length != 0); | |
| 1374 | } | |
| 1375 | 1375 | } |
| 1376 | 1376 | #else |
| 1377 | 1377 | # define check_match(s, start, match, length) |
| r25360 | r25361 | |
| 1388 | 1388 | * option -- not supported here). |
| 1389 | 1389 | */ |
| 1390 | 1390 | local void fill_window(s) |
| 1391 | ||
| 1391 | deflate_state *s; | |
| 1392 | 1392 | { |
| 1393 | register unsigned n, m; | |
| 1394 | register Posf *p; | |
| 1395 | unsigned more; /* Amount of free space at the end of the window. */ | |
| 1396 | uInt wsize = s->w_size; | |
| 1393 | register unsigned n, m; | |
| 1394 | register Posf *p; | |
| 1395 | unsigned more; /* Amount of free space at the end of the window. */ | |
| 1396 | uInt wsize = s->w_size; | |
| 1397 | 1397 | |
| 1398 | ||
| 1398 | Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); | |
| 1399 | 1399 | |
| 1400 | do { | |
| 1401 | more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); | |
| 1400 | do { | |
| 1401 | more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); | |
| 1402 | 1402 | |
| 1403 | /* Deal with !@#$% 64K limit: */ | |
| 1404 | if (sizeof(int) <= 2) { | |
| 1405 | if (more == 0 && s->strstart == 0 && s->lookahead == 0) { | |
| 1406 | more = wsize; | |
| 1403 | /* Deal with !@#$% 64K limit: */ | |
| 1404 | if (sizeof(int) <= 2) { | |
| 1405 | if (more == 0 && s->strstart == 0 && s->lookahead == 0) { | |
| 1406 | more = wsize; | |
| 1407 | 1407 | |
| 1408 | } else if (more == (unsigned)(-1)) { | |
| 1409 | /* Very unlikely, but possible on 16 bit machine if | |
| 1410 | * strstart == 0 && lookahead == 1 (input done a byte at time) | |
| 1411 | */ | |
| 1412 | more--; | |
| 1413 | } | |
| 1414 | } | |
| 1408 | } else if (more == (unsigned)(-1)) { | |
| 1409 | /* Very unlikely, but possible on 16 bit machine if | |
| 1410 | * strstart == 0 && lookahead == 1 (input done a byte at time) | |
| 1411 | */ | |
| 1412 | more--; | |
| 1413 | } | |
| 1414 | } | |
| 1415 | 1415 | |
| 1416 | /* If the window is almost full and there is insufficient lookahead, | |
| 1417 | * move the upper half to the lower one to make room in the upper half. | |
| 1418 | */ | |
| 1419 | if (s->strstart >= wsize+MAX_DIST(s)) { | |
| 1416 | /* If the window is almost full and there is insufficient lookahead, | |
| 1417 | * move the upper half to the lower one to make room in the upper half. | |
| 1418 | */ | |
| 1419 | if (s->strstart >= wsize+MAX_DIST(s)) { | |
| 1420 | zmemcpy(s->window, s->window+wsize, (unsigned)wsize); | |
| 1421 | s->match_start -= wsize; | |
| 1422 | s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ | |
| 1423 | s->block_start -= (long) wsize; | |
| 1420 | 1424 | |
| 1421 | zmemcpy(s->window, s->window+wsize, (unsigned)wsize); | |
| 1422 | s->match_start -= wsize; | |
| 1423 | s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ | |
| 1424 | s->block_start -= (long) wsize; | |
| 1425 | /* Slide the hash table (could be avoided with 32 bit values | |
| 1426 | at the expense of memory usage). We slide even when level == 0 | |
| 1427 | to keep the hash table consistent if we switch back to level > 0 | |
| 1428 | later. (Using level 0 permanently is not an optimal usage of | |
| 1429 | zlib, so we don't care about this pathological case.) | |
| 1430 | */ | |
| 1431 | n = s->hash_size; | |
| 1432 | p = &s->head[n]; | |
| 1433 | do { | |
| 1434 | m = *--p; | |
| 1435 | *p = (Pos)(m >= wsize ? m-wsize : NIL); | |
| 1436 | } while (--n); | |
| 1425 | 1437 | |
| 1426 | /* Slide the hash table (could be avoided with 32 bit values | |
| 1427 | at the expense of memory usage). We slide even when level == 0 | |
| 1428 | to keep the hash table consistent if we switch back to level > 0 | |
| 1429 | later. (Using level 0 permanently is not an optimal usage of | |
| 1430 | zlib, so we don't care about this pathological case.) | |
| 1431 | */ | |
| 1432 | n = s->hash_size; | |
| 1433 | p = &s->head[n]; | |
| 1434 | do { | |
| 1435 | m = *--p; | |
| 1436 | *p = (Pos)(m >= wsize ? m-wsize : NIL); | |
| 1437 | } while (--n); | |
| 1438 | ||
| 1439 | n = wsize; | |
| 1438 | n = wsize; | |
| 1440 | 1439 | #ifndef FASTEST |
| 1441 | p = &s->prev[n]; | |
| 1442 | do { | |
| 1443 | m = *--p; | |
| 1444 | *p = (Pos)(m >= wsize ? m-wsize : NIL); | |
| 1445 | /* If n is not on any hash chain, prev[n] is garbage but | |
| 1446 | * its value will never be used. | |
| 1447 | */ | |
| 1448 | } while (--n); | |
| 1440 | p = &s->prev[n]; | |
| 1441 | do { | |
| 1442 | m = *--p; | |
| 1443 | *p = (Pos)(m >= wsize ? m-wsize : NIL); | |
| 1444 | /* If n is not on any hash chain, prev[n] is garbage but | |
| 1445 | * its value will never be used. | |
| 1446 | */ | |
| 1447 | } while (--n); | |
| 1449 | 1448 | #endif |
| 1450 | more += wsize; | |
| 1451 | } | |
| 1452 | if (s->strm->avail_in == 0) break; | |
| 1449 | more += wsize; | |
| 1450 | } | |
| 1451 | if (s->strm->avail_in == 0) break; | |
| 1453 | 1452 | |
| 1454 | /* If there was no sliding: | |
| 1455 | * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && | |
| 1456 | * more == window_size - lookahead - strstart | |
| 1457 | * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) | |
| 1458 | * => more >= window_size - 2*WSIZE + 2 | |
| 1459 | * In the BIG_MEM or MMAP case (not yet supported), | |
| 1460 | * window_size == input_size + MIN_LOOKAHEAD && | |
| 1461 | * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. | |
| 1462 | * Otherwise, window_size == 2*WSIZE so more >= 2. | |
| 1463 | * If there was sliding, more >= WSIZE. So in all cases, more >= 2. | |
| 1464 | */ | |
| 1465 | Assert(more >= 2, "more < 2"); | |
| 1453 | /* If there was no sliding: | |
| 1454 | * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && | |
| 1455 | * more == window_size - lookahead - strstart | |
| 1456 | * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) | |
| 1457 | * => more >= window_size - 2*WSIZE + 2 | |
| 1458 | * In the BIG_MEM or MMAP case (not yet supported), | |
| 1459 | * window_size == input_size + MIN_LOOKAHEAD && | |
| 1460 | * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. | |
| 1461 | * Otherwise, window_size == 2*WSIZE so more >= 2. | |
| 1462 | * If there was sliding, more >= WSIZE. So in all cases, more >= 2. | |
| 1463 | */ | |
| 1464 | Assert(more >= 2, "more < 2"); | |
| 1466 | 1465 | |
| 1467 | n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); | |
| 1468 | s->lookahead += n; | |
| 1466 | n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); | |
| 1467 | s->lookahead += n; | |
| 1469 | 1468 | |
| 1470 | /* Initialize the hash value now that we have some input: */ | |
| 1471 | if (s->lookahead + s->insert >= MIN_MATCH) { | |
| 1472 | uInt str = s->strstart - s->insert; | |
| 1473 | s->ins_h = s->window[str]; | |
| 1474 | UPDATE_HASH(s, s->ins_h, s->window[str + 1]); | |
| 1469 | /* Initialize the hash value now that we have some input: */ | |
| 1470 | if (s->lookahead + s->insert >= MIN_MATCH) { | |
| 1471 | uInt str = s->strstart - s->insert; | |
| 1472 | s->ins_h = s->window[str]; | |
| 1473 | UPDATE_HASH(s, s->ins_h, s->window[str + 1]); | |
| 1475 | 1474 | #if MIN_MATCH != 3 |
| 1476 | ||
| 1475 | Call UPDATE_HASH() MIN_MATCH-3 more times | |
| 1477 | 1476 | #endif |
| 1478 | while (s->insert) { | |
| 1479 | UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); | |
| 1477 | while (s->insert) { | |
| 1478 | UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); | |
| 1480 | 1479 | #ifndef FASTEST |
| 1481 | ||
| 1480 | s->prev[str & s->w_mask] = s->head[s->ins_h]; | |
| 1482 | 1481 | #endif |
| 1483 | s->head[s->ins_h] = (Pos)str; | |
| 1484 | str++; | |
| 1485 | s->insert--; | |
| 1486 | if (s->lookahead + s->insert < MIN_MATCH) | |
| 1487 | break; | |
| 1488 | } | |
| 1489 | } | |
| 1490 | /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, | |
| 1491 | * but this is not important since only literal bytes will be emitted. | |
| 1492 | */ | |
| 1482 | s->head[s->ins_h] = (Pos)str; | |
| 1483 | str++; | |
| 1484 | s->insert--; | |
| 1485 | if (s->lookahead + s->insert < MIN_MATCH) | |
| 1486 | break; | |
| 1487 | } | |
| 1488 | } | |
| 1489 | /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, | |
| 1490 | * but this is not important since only literal bytes will be emitted. | |
| 1491 | */ | |
| 1493 | 1492 | |
| 1494 | ||
| 1493 | } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); | |
| 1495 | 1494 | |
| 1496 | /* If the WIN_INIT bytes after the end of the current data have never been | |
| 1497 | * written, then zero those bytes in order to avoid memory check reports of | |
| 1498 | * the use of uninitialized (or uninitialised as Julian writes) bytes by | |
| 1499 | * the longest match routines. Update the high water mark for the next | |
| 1500 | * time through here. WIN_INIT is set to MAX_MATCH since the longest match | |
| 1501 | * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. | |
| 1502 | */ | |
| 1503 | if (s->high_water < s->window_size) { | |
| 1504 | ulg curr = s->strstart + (ulg)(s->lookahead); | |
| 1505 | ulg init; | |
| 1495 | /* If the WIN_INIT bytes after the end of the current data have never been | |
| 1496 | * written, then zero those bytes in order to avoid memory check reports of | |
| 1497 | * the use of uninitialized (or uninitialised as Julian writes) bytes by | |
| 1498 | * the longest match routines. Update the high water mark for the next | |
| 1499 | * time through here. WIN_INIT is set to MAX_MATCH since the longest match | |
| 1500 | * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. | |
| 1501 | */ | |
| 1502 | if (s->high_water < s->window_size) { | |
| 1503 | ulg curr = s->strstart + (ulg)(s->lookahead); | |
| 1504 | ulg init; | |
| 1506 | 1505 | |
| 1507 | if (s->high_water < curr) { | |
| 1508 | /* Previous high water mark below current data -- zero WIN_INIT | |
| 1509 | * bytes or up to end of window, whichever is less. | |
| 1510 | */ | |
| 1511 | init = s->window_size - curr; | |
| 1512 | if (init > WIN_INIT) | |
| 1513 | init = WIN_INIT; | |
| 1514 | zmemzero(s->window + curr, (unsigned)init); | |
| 1515 | s->high_water = curr + init; | |
| 1516 | } | |
| 1517 | else if (s->high_water < (ulg)curr + WIN_INIT) { | |
| 1518 | /* High water mark at or above current data, but below current data | |
| 1519 | * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up | |
| 1520 | * to end of window, whichever is less. | |
| 1521 | */ | |
| 1522 | init = (ulg)curr + WIN_INIT - s->high_water; | |
| 1523 | if (init > s->window_size - s->high_water) | |
| 1524 | init = s->window_size - s->high_water; | |
| 1525 | zmemzero(s->window + s->high_water, (unsigned)init); | |
| 1526 | s->high_water += init; | |
| 1527 | } | |
| 1528 | } | |
| 1506 | if (s->high_water < curr) { | |
| 1507 | /* Previous high water mark below current data -- zero WIN_INIT | |
| 1508 | * bytes or up to end of window, whichever is less. | |
| 1509 | */ | |
| 1510 | init = s->window_size - curr; | |
| 1511 | if (init > WIN_INIT) | |
| 1512 | init = WIN_INIT; | |
| 1513 | zmemzero(s->window + curr, (unsigned)init); | |
| 1514 | s->high_water = curr + init; | |
| 1515 | } | |
| 1516 | else if (s->high_water < (ulg)curr + WIN_INIT) { | |
| 1517 | /* High water mark at or above current data, but below current data | |
| 1518 | * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up | |
| 1519 | * to end of window, whichever is less. | |
| 1520 | */ | |
| 1521 | init = (ulg)curr + WIN_INIT - s->high_water; | |
| 1522 | if (init > s->window_size - s->high_water) | |
| 1523 | init = s->window_size - s->high_water; | |
| 1524 | zmemzero(s->window + s->high_water, (unsigned)init); | |
| 1525 | s->high_water += init; | |
| 1526 | } | |
| 1527 | } | |
| 1529 | 1528 | |
| 1530 | Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, | |
| 1531 | "not enough room for search"); | |
| 1529 | Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, | |
| 1530 | "not enough room for search"); | |
| 1532 | 1531 | } |
| 1533 | 1532 | |
| 1534 | 1533 | /* =========================================================================== |
| r25360 | r25361 | |
| 1536 | 1535 | * IN assertion: strstart is set to the end of the current match. |
| 1537 | 1536 | */ |
| 1538 | 1537 | #define FLUSH_BLOCK_ONLY(s, last) { \ |
| 1539 | _tr_flush_block(s, (s->block_start >= 0L ? \ | |
| 1540 | (charf *)&s->window[(unsigned)s->block_start] : \ | |
| 1541 | (charf *)Z_NULL), \ | |
| 1542 | (ulg)((long)s->strstart - s->block_start), \ | |
| 1543 | (last)); \ | |
| 1544 | s->block_start = s->strstart; \ | |
| 1545 | flush_pending(s->strm); \ | |
| 1546 | Tracev((stderr,"[FLUSH]")); \ | |
| 1538 | _tr_flush_block(s, (s->block_start >= 0L ? \ | |
| 1539 | (charf *)&s->window[(unsigned)s->block_start] : \ | |
| 1540 | (charf *)Z_NULL), \ | |
| 1541 | (ulg)((long)s->strstart - s->block_start), \ | |
| 1542 | (last)); \ | |
| 1543 | s->block_start = s->strstart; \ | |
| 1544 | flush_pending(s->strm); \ | |
| 1545 | Tracev((stderr,"[FLUSH]")); \ | |
| 1547 | 1546 | } |
| 1548 | 1547 | |
| 1549 | 1548 | /* Same but force premature exit if necessary. */ |
| 1550 | 1549 | #define FLUSH_BLOCK(s, last) { \ |
| 1551 | FLUSH_BLOCK_ONLY(s, last); \ | |
| 1552 | if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ | |
| 1550 | FLUSH_BLOCK_ONLY(s, last); \ | |
| 1551 | if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ | |
| 1553 | 1552 | } |
| 1554 | 1553 | |
| 1555 | 1554 | /* =========================================================================== |
| r25360 | r25361 | |
| 1562 | 1561 | * window to pending_buf. |
| 1563 | 1562 | */ |
| 1564 | 1563 | local block_state deflate_stored(s, flush) |
| 1565 | deflate_state *s; | |
| 1566 | int flush; | |
| 1564 | deflate_state *s; | |
| 1565 | int flush; | |
| 1567 | 1566 | { |
| 1568 | /* Stored blocks are limited to 0xffff bytes, pending_buf is limited | |
| 1569 | * to pending_buf_size, and each stored block has a 5 byte header: | |
| 1570 | */ | |
| 1571 | ulg max_block_size = 0xffff; | |
| 1572 | ulg max_start; | |
| 1567 | /* Stored blocks are limited to 0xffff bytes, pending_buf is limited | |
| 1568 | * to pending_buf_size, and each stored block has a 5 byte header: | |
| 1569 | */ | |
| 1570 | ulg max_block_size = 0xffff; | |
| 1571 | ulg max_start; | |
| 1573 | 1572 | |
| 1574 | if (max_block_size > s->pending_buf_size - 5) { | |
| 1575 | max_block_size = s->pending_buf_size - 5; | |
| 1576 | } | |
| 1573 | if (max_block_size > s->pending_buf_size - 5) { | |
| 1574 | max_block_size = s->pending_buf_size - 5; | |
| 1575 | } | |
| 1577 | 1576 | |
| 1578 | /* Copy as much as possible from input to output: */ | |
| 1579 | for (;;) { | |
| 1580 | /* Fill the window as much as possible: */ | |
| 1581 | if (s->lookahead <= 1) { | |
| 1577 | /* Copy as much as possible from input to output: */ | |
| 1578 | for (;;) { | |
| 1579 | /* Fill the window as much as possible: */ | |
| 1580 | if (s->lookahead <= 1) { | |
| 1581 | Assert(s->strstart < s->w_size+MAX_DIST(s) || | |
| 1582 | s->block_start >= (long)s->w_size, "slide too late"); | |
| 1582 | 1583 | |
| 1583 | Assert(s->strstart < s->w_size+MAX_DIST(s) || | |
| 1584 | s->block_start >= (long)s->w_size, "slide too late"); | |
| 1584 | fill_window(s); | |
| 1585 | if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; | |
| 1585 | 1586 | |
| 1586 | fill_window(s); | |
| 1587 | if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; | |
| 1587 | if (s->lookahead == 0) break; /* flush the current block */ | |
| 1588 | } | |
| 1589 | Assert(s->block_start >= 0L, "block gone"); | |
| 1588 | 1590 | |
| 1589 | if (s->lookahead == 0) break; /* flush the current block */ | |
| 1590 | } | |
| 1591 | Assert(s->block_start >= 0L, "block gone"); | |
| 1591 | s->strstart += s->lookahead; | |
| 1592 | s->lookahead = 0; | |
| 1592 | 1593 | |
| 1593 | s->strstart += s->lookahead; | |
| 1594 | s->lookahead = 0; | |
| 1595 | ||
| 1596 | /* Emit a stored block if pending_buf will be full: */ | |
| 1597 | max_start = s->block_start + max_block_size; | |
| 1598 | if (s->strstart == 0 || (ulg)s->strstart >= max_start) { | |
| 1599 | /* strstart == 0 is possible when wraparound on 16-bit machine */ | |
| 1600 | s->lookahead = (uInt)(s->strstart - max_start); | |
| 1601 | s->strstart = (uInt)max_start; | |
| 1602 | FLUSH_BLOCK(s, 0); | |
| 1603 | } | |
| 1604 | /* Flush if we may have to slide, otherwise block_start may become | |
| 1605 | * negative and the data will be gone: | |
| 1606 | */ | |
| 1607 | if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { | |
| 1608 | FLUSH_BLOCK(s, 0); | |
| 1609 | } | |
| 1610 | } | |
| 1611 | s->insert = 0; | |
| 1612 | if (flush == Z_FINISH) { | |
| 1613 | FLUSH_BLOCK(s, 1); | |
| 1614 | return finish_done; | |
| 1615 | } | |
| 1616 | if ((long)s->strstart > s->block_start) | |
| 1617 | FLUSH_BLOCK(s, 0); | |
| 1618 | return block_done; | |
| 1594 | /* Emit a stored block if pending_buf will be full: */ | |
| 1595 | max_start = s->block_start + max_block_size; | |
| 1596 | if (s->strstart == 0 || (ulg)s->strstart >= max_start) { | |
| 1597 | /* strstart == 0 is possible when wraparound on 16-bit machine */ | |
| 1598 | s->lookahead = (uInt)(s->strstart - max_start); | |
| 1599 | s->strstart = (uInt)max_start; | |
| 1600 | FLUSH_BLOCK(s, 0); | |
| 1601 | } | |
| 1602 | /* Flush if we may have to slide, otherwise block_start may become | |
| 1603 | * negative and the data will be gone: | |
| 1604 | */ | |
| 1605 | if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { | |
| 1606 | FLUSH_BLOCK(s, 0); | |
| 1607 | } | |
| 1608 | } | |
| 1609 | s->insert = 0; | |
| 1610 | if (flush == Z_FINISH) { | |
| 1611 | FLUSH_BLOCK(s, 1); | |
| 1612 | return finish_done; | |
| 1613 | } | |
| 1614 | if ((long)s->strstart > s->block_start) | |
| 1615 | FLUSH_BLOCK(s, 0); | |
| 1616 | return block_done; | |
| 1619 | 1617 | } |
| 1620 | 1618 | |
| 1621 | 1619 | /* =========================================================================== |
| r25360 | r25361 | |
| 1626 | 1624 | * matches. It is used only for the fast compression options. |
| 1627 | 1625 | */ |
| 1628 | 1626 | local block_state deflate_fast(s, flush) |
| 1629 | deflate_state *s; | |
| 1630 | int flush; | |
| 1627 | deflate_state *s; | |
| 1628 | int flush; | |
| 1631 | 1629 | { |
| 1632 | IPos hash_head; /* head of the hash chain */ | |
| 1633 | int bflush; /* set if current block must be flushed */ | |
| 1630 | IPos hash_head; /* head of the hash chain */ | |
| 1631 | int bflush; /* set if current block must be flushed */ | |
| 1634 | 1632 | |
| 1635 | for (;;) { | |
| 1636 | /* Make sure that we always have enough lookahead, except | |
| 1637 | * at the end of the input file. We need MAX_MATCH bytes | |
| 1638 | * for the next match, plus MIN_MATCH bytes to insert the | |
| 1639 | * string following the next match. | |
| 1640 | */ | |
| 1641 | if (s->lookahead < MIN_LOOKAHEAD) { | |
| 1642 | fill_window(s); | |
| 1643 | if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { | |
| 1644 | return need_more; | |
| 1645 | } | |
| 1646 | if (s->lookahead == 0) break; /* flush the current block */ | |
| 1647 | } | |
| 1633 | for (;;) { | |
| 1634 | /* Make sure that we always have enough lookahead, except | |
| 1635 | * at the end of the input file. We need MAX_MATCH bytes | |
| 1636 | * for the next match, plus MIN_MATCH bytes to insert the | |
| 1637 | * string following the next match. | |
| 1638 | */ | |
| 1639 | if (s->lookahead < MIN_LOOKAHEAD) { | |
| 1640 | fill_window(s); | |
| 1641 | if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { | |
| 1642 | return need_more; | |
| 1643 | } | |
| 1644 | if (s->lookahead == 0) break; /* flush the current block */ | |
| 1645 | } | |
| 1648 | 1646 | |
| 1649 | /* Insert the string window[strstart .. strstart+2] in the | |
| 1650 | * dictionary, and set hash_head to the head of the hash chain: | |
| 1651 | */ | |
| 1652 | hash_head = NIL; | |
| 1653 | if (s->lookahead >= MIN_MATCH) { | |
| 1654 | INSERT_STRING(s, s->strstart, hash_head); | |
| 1655 | } | |
| 1647 | /* Insert the string window[strstart .. strstart+2] in the | |
| 1648 | * dictionary, and set hash_head to the head of the hash chain: | |
| 1649 | */ | |
| 1650 | hash_head = NIL; | |
| 1651 | if (s->lookahead >= MIN_MATCH) { | |
| 1652 | INSERT_STRING(s, s->strstart, hash_head); | |
| 1653 | } | |
| 1656 | 1654 | |
| 1657 | /* Find the longest match, discarding those <= prev_length. | |
| 1658 | * At this point we have always match_length < MIN_MATCH | |
| 1659 | */ | |
| 1660 | if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { | |
| 1661 | /* To simplify the code, we prevent matches with the string | |
| 1662 | * of window index 0 (in particular we have to avoid a match | |
| 1663 | * of the string with itself at the start of the input file). | |
| 1664 | */ | |
| 1665 | s->match_length = longest_match (s, hash_head); | |
| 1666 | /* longest_match() sets match_start */ | |
| 1667 | } | |
| 1668 | if (s->match_length >= MIN_MATCH) { | |
| 1669 | check_match(s, s->strstart, s->match_start, s->match_length); | |
| 1655 | /* Find the longest match, discarding those <= prev_length. | |
| 1656 | * At this point we have always match_length < MIN_MATCH | |
| 1657 | */ | |
| 1658 | if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { | |
| 1659 | /* To simplify the code, we prevent matches with the string | |
| 1660 | * of window index 0 (in particular we have to avoid a match | |
| 1661 | * of the string with itself at the start of the input file). | |
| 1662 | */ | |
| 1663 | s->match_length = longest_match (s, hash_head); | |
| 1664 | /* longest_match() sets match_start */ | |
| 1665 | } | |
| 1666 | if (s->match_length >= MIN_MATCH) { | |
| 1667 | check_match(s, s->strstart, s->match_start, s->match_length); | |
| 1670 | 1668 | |
| 1671 | _tr_tally_dist(s, s->strstart - s->match_start, | |
| 1672 | s->match_length - MIN_MATCH, bflush); | |
| 1669 | _tr_tally_dist(s, s->strstart - s->match_start, | |
| 1670 | s->match_length - MIN_MATCH, bflush); | |
| 1673 | 1671 | |
| 1674 | ||
| 1672 | s->lookahead -= s->match_length; | |
| 1675 | 1673 | |
| 1676 | /* Insert new strings in the hash table only if the match length | |
| 1677 | * is not too large. This saves time but degrades compression. | |
| 1678 | */ | |
| 1674 | /* Insert new strings in the hash table only if the match length | |
| 1675 | * is not too large. This saves time but degrades compression. | |
| 1676 | */ | |
| 1679 | 1677 | #ifndef FASTEST |
| 1680 | if (s->match_length <= s->max_insert_length && | |
| 1681 | s->lookahead >= MIN_MATCH) { | |
| 1682 | s->match_length--; /* string at strstart already in table */ | |
| 1683 | do { | |
| 1684 | s->strstart++; | |
| 1685 | INSERT_STRING(s, s->strstart, hash_head); | |
| 1686 | /* strstart never exceeds WSIZE-MAX_MATCH, so there are | |
| 1687 | * always MIN_MATCH bytes ahead. | |
| 1688 | */ | |
| 1689 | } while (--s->match_length != 0); | |
| 1690 | s->strstart++; | |
| 1691 | } else | |
| 1678 | if (s->match_length <= s->max_insert_length && | |
| 1679 | s->lookahead >= MIN_MATCH) { | |
| 1680 | s->match_length--; /* string at strstart already in table */ | |
| 1681 | do { | |
| 1682 | s->strstart++; | |
| 1683 | INSERT_STRING(s, s->strstart, hash_head); | |
| 1684 | /* strstart never exceeds WSIZE-MAX_MATCH, so there are | |
| 1685 | * always MIN_MATCH bytes ahead. | |
| 1686 | */ | |
| 1687 | } while (--s->match_length != 0); | |
| 1688 | s->strstart++; | |
| 1689 | } else | |
| 1692 | 1690 | #endif |
| 1693 | { | |
| 1694 | s->strstart += s->match_length; | |
| 1695 | s->match_length = 0; | |
| 1696 | s->ins_h = s->window[s->strstart]; | |
| 1697 | UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); | |
| 1691 | { | |
| 1692 | s->strstart += s->match_length; | |
| 1693 | s->match_length = 0; | |
| 1694 | s->ins_h = s->window[s->strstart]; | |
| 1695 | UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); | |
| 1698 | 1696 | #if MIN_MATCH != 3 |
| 1699 | ||
| 1697 | Call UPDATE_HASH() MIN_MATCH-3 more times | |
| 1700 | 1698 | #endif |
| 1701 | /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not | |
| 1702 | * matter since it will be recomputed at next deflate call. | |
| 1703 | */ | |
| 1704 | } | |
| 1705 | } else { | |
| 1706 | /* No match, output a literal byte */ | |
| 1707 | Tracevv((stderr,"%c", s->window[s->strstart])); | |
| 1708 | _tr_tally_lit (s, s->window[s->strstart], bflush); | |
| 1709 | s->lookahead--; | |
| 1710 | s->strstart++; | |
| 1711 | } | |
| 1712 | if (bflush) FLUSH_BLOCK(s, 0); | |
| 1713 | } | |
| 1714 | s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; | |
| 1715 | if (flush == Z_FINISH) { | |
| 1716 | FLUSH_BLOCK(s, 1); | |
| 1717 | return finish_done; | |
| 1718 | } | |
| 1719 | if (s->last_lit) | |
| 1720 | FLUSH_BLOCK(s, 0); | |
| 1721 | return block_done; | |
| 1699 | /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not | |
| 1700 | * matter since it will be recomputed at next deflate call. | |
| 1701 | */ | |
| 1702 | } | |
| 1703 | } else { | |
| 1704 | /* No match, output a literal byte */ | |
| 1705 | Tracevv((stderr,"%c", s->window[s->strstart])); | |
| 1706 | _tr_tally_lit (s, s->window[s->strstart], bflush); | |
| 1707 | s->lookahead--; | |
| 1708 | s->strstart++; | |
| 1709 | } | |
| 1710 | if (bflush) FLUSH_BLOCK(s, 0); | |
| 1711 | } | |
| 1712 | s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; | |
| 1713 | if (flush == Z_FINISH) { | |
| 1714 | FLUSH_BLOCK(s, 1); | |
| 1715 | return finish_done; | |
| 1716 | } | |
| 1717 | if (s->last_lit) | |
| 1718 | FLUSH_BLOCK(s, 0); | |
| 1719 | return block_done; | |
| 1722 | 1720 | } |
| 1723 | 1721 | |
| 1724 | 1722 | #ifndef FASTEST |
| r25360 | r25361 | |
| 1728 | 1726 | * no better match at the next window position. |
| 1729 | 1727 | */ |
| 1730 | 1728 | local block_state deflate_slow(s, flush) |
| 1731 | deflate_state *s; | |
| 1732 | int flush; | |
| 1729 | deflate_state *s; | |
| 1730 | int flush; | |
| 1733 | 1731 | { |
| 1734 | IPos hash_head; /* head of hash chain */ | |
| 1735 | int bflush; /* set if current block must be flushed */ | |
| 1732 | IPos hash_head; /* head of hash chain */ | |
| 1733 | int bflush; /* set if current block must be flushed */ | |
| 1736 | 1734 | |
| 1737 | /* Process the input block. */ | |
| 1738 | for (;;) { | |
| 1739 | /* Make sure that we always have enough lookahead, except | |
| 1740 | * at the end of the input file. We need MAX_MATCH bytes | |
| 1741 | * for the next match, plus MIN_MATCH bytes to insert the | |
| 1742 | * string following the next match. | |
| 1743 | */ | |
| 1744 | if (s->lookahead < MIN_LOOKAHEAD) { | |
| 1745 | fill_window(s); | |
| 1746 | if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { | |
| 1747 | return need_more; | |
| 1748 | } | |
| 1749 | if (s->lookahead == 0) break; /* flush the current block */ | |
| 1750 | } | |
| 1735 | /* Process the input block. */ | |
| 1736 | for (;;) { | |
| 1737 | /* Make sure that we always have enough lookahead, except | |
| 1738 | * at the end of the input file. We need MAX_MATCH bytes | |
| 1739 | * for the next match, plus MIN_MATCH bytes to insert the | |
| 1740 | * string following the next match. | |
| 1741 | */ | |
| 1742 | if (s->lookahead < MIN_LOOKAHEAD) { | |
| 1743 | fill_window(s); | |
| 1744 | if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { | |
| 1745 | return need_more; | |
| 1746 | } | |
| 1747 | if (s->lookahead == 0) break; /* flush the current block */ | |
| 1748 | } | |
| 1751 | 1749 | |
| 1752 | /* Insert the string window[strstart .. strstart+2] in the | |
| 1753 | * dictionary, and set hash_head to the head of the hash chain: | |
| 1754 | */ | |
| 1755 | hash_head = NIL; | |
| 1756 | if (s->lookahead >= MIN_MATCH) { | |
| 1757 | INSERT_STRING(s, s->strstart, hash_head); | |
| 1758 | } | |
| 1750 | /* Insert the string window[strstart .. strstart+2] in the | |
| 1751 | * dictionary, and set hash_head to the head of the hash chain: | |
| 1752 | */ | |
| 1753 | hash_head = NIL; | |
| 1754 | if (s->lookahead >= MIN_MATCH) { | |
| 1755 | INSERT_STRING(s, s->strstart, hash_head); | |
| 1756 | } | |
| 1759 | 1757 | |
| 1760 | /* Find the longest match, discarding those <= prev_length. | |
| 1761 | */ | |
| 1762 | s->prev_length = s->match_length, s->prev_match = s->match_start; | |
| 1763 | s->match_length = MIN_MATCH-1; | |
| 1758 | /* Find the longest match, discarding those <= prev_length. | |
| 1759 | */ | |
| 1760 | s->prev_length = s->match_length, s->prev_match = s->match_start; | |
| 1761 | s->match_length = MIN_MATCH-1; | |
| 1764 | 1762 | |
| 1765 | if (hash_head != NIL && s->prev_length < s->max_lazy_match && | |
| 1766 | s->strstart - hash_head <= MAX_DIST(s)) { | |
| 1767 | /* To simplify the code, we prevent matches with the string | |
| 1768 | * of window index 0 (in particular we have to avoid a match | |
| 1769 | * of the string with itself at the start of the input file). | |
| 1770 | */ | |
| 1771 | s->match_length = longest_match (s, hash_head); | |
| 1772 | /* longest_match() sets match_start */ | |
| 1763 | if (hash_head != NIL && s->prev_length < s->max_lazy_match && | |
| 1764 | s->strstart - hash_head <= MAX_DIST(s)) { | |
| 1765 | /* To simplify the code, we prevent matches with the string | |
| 1766 | * of window index 0 (in particular we have to avoid a match | |
| 1767 | * of the string with itself at the start of the input file). | |
| 1768 | */ | |
| 1769 | s->match_length = longest_match (s, hash_head); | |
| 1770 | /* longest_match() sets match_start */ | |
| 1773 | 1771 | |
| 1774 | ||
| 1772 | if (s->match_length <= 5 && (s->strategy == Z_FILTERED | |
| 1775 | 1773 | #if TOO_FAR <= 32767 |
| 1776 | || (s->match_length == MIN_MATCH && | |
| 1777 | s->strstart - s->match_start > TOO_FAR) | |
| 1774 | || (s->match_length == MIN_MATCH && | |
| 1775 | s->strstart - s->match_start > TOO_FAR) | |
| 1778 | 1776 | #endif |
| 1779 | )) { | |
| 1777 | )) { | |
| 1778 | /* If prev_match is also MIN_MATCH, match_start is garbage | |
| 1779 | * but we will ignore the current match anyway. | |
| 1780 | */ | |
| 1781 | s->match_length = MIN_MATCH-1; | |
| 1782 | } | |
| 1783 | } | |
| 1784 | /* If there was a match at the previous step and the current | |
| 1785 | * match is not better, output the previous match: | |
| 1786 | */ | |
| 1787 | if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { | |
| 1788 | uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; | |
| 1789 | /* Do not insert strings in hash table beyond this. */ | |
| 1780 | 1790 | |
| 1781 | /* If prev_match is also MIN_MATCH, match_start is garbage | |
| 1782 | * but we will ignore the current match anyway. | |
| 1783 | */ | |
| 1784 | s->match_length = MIN_MATCH-1; | |
| 1785 | } | |
| 1786 | } | |
| 1787 | /* If there was a match at the previous step and the current | |
| 1788 | * match is not better, output the previous match: | |
| 1789 | */ | |
| 1790 | if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { | |
| 1791 | uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; | |
| 1792 | /* Do not insert strings in hash table beyond this. */ | |
| 1791 | check_match(s, s->strstart-1, s->prev_match, s->prev_length); | |
| 1793 | 1792 | |
| 1794 | check_match(s, s->strstart-1, s->prev_match, s->prev_length); | |
| 1793 | _tr_tally_dist(s, s->strstart -1 - s->prev_match, | |
| 1794 | s->prev_length - MIN_MATCH, bflush); | |
| 1795 | 1795 | |
| 1796 | _tr_tally_dist(s, s->strstart -1 - s->prev_match, | |
| 1797 | s->prev_length - MIN_MATCH, bflush); | |
| 1796 | /* Insert in hash table all strings up to the end of the match. | |
| 1797 | * strstart-1 and strstart are already inserted. If there is not | |
| 1798 | * enough lookahead, the last two strings are not inserted in | |
| 1799 | * the hash table. | |
| 1800 | */ | |
| 1801 | s->lookahead -= s->prev_length-1; | |
| 1802 | s->prev_length -= 2; | |
| 1803 | do { | |
| 1804 | if (++s->strstart <= max_insert) { | |
| 1805 | INSERT_STRING(s, s->strstart, hash_head); | |
| 1806 | } | |
| 1807 | } while (--s->prev_length != 0); | |
| 1808 | s->match_available = 0; | |
| 1809 | s->match_length = MIN_MATCH-1; | |
| 1810 | s->strstart++; | |
| 1798 | 1811 | |
| 1799 | /* Insert in hash table all strings up to the end of the match. | |
| 1800 | * strstart-1 and strstart are already inserted. If there is not | |
| 1801 | * enough lookahead, the last two strings are not inserted in | |
| 1802 | * the hash table. | |
| 1803 | */ | |
| 1804 | s->lookahead -= s->prev_length-1; | |
| 1805 | s->prev_length -= 2; | |
| 1806 | do { | |
| 1807 | if (++s->strstart <= max_insert) { | |
| 1808 | INSERT_STRING(s, s->strstart, hash_head); | |
| 1809 | } | |
| 1810 | } while (--s->prev_length != 0); | |
| 1811 | s->match_available = 0; | |
| 1812 | s->match_length = MIN_MATCH-1; | |
| 1813 | s->strstart++; | |
| 1812 | if (bflush) FLUSH_BLOCK(s, 0); | |
| 1814 | 1813 | |
| 1815 | if (bflush) FLUSH_BLOCK(s, 0); | |
| 1816 | ||
| 1817 | } else if (s->match_available) { | |
| 1818 | /* If there was no match at the previous position, output a | |
| 1819 | * single literal. If there was a match but the current match | |
| 1820 | * is longer, truncate the previous match to a single literal. | |
| 1821 | */ | |
| 1822 | Tracevv((stderr,"%c", s->window[s->strstart-1])); | |
| 1823 | _tr_tally_lit(s, s->window[s->strstart-1], bflush); | |
| 1824 | if (bflush) { | |
| 1825 | FLUSH_BLOCK_ONLY(s, 0); | |
| 1826 | } | |
| 1827 | s->strstart++; | |
| 1828 | s->lookahead--; | |
| 1829 | if (s->strm->avail_out == 0) return need_more; | |
| 1830 | } else { | |
| 1831 | /* There is no previous match to compare with, wait for | |
| 1832 | * the next step to decide. | |
| 1833 | */ | |
| 1834 | s->match_available = 1; | |
| 1835 | s->strstart++; | |
| 1836 | s->lookahead--; | |
| 1837 | } | |
| 1838 | } | |
| 1839 | Assert (flush != Z_NO_FLUSH, "no flush?"); | |
| 1840 | if (s->match_available) { | |
| 1841 | Tracevv((stderr,"%c", s->window[s->strstart-1])); | |
| 1842 | _tr_tally_lit(s, s->window[s->strstart-1], bflush); | |
| 1843 | s->match_available = 0; | |
| 1844 | } | |
| 1845 | s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; | |
| 1846 | if (flush == Z_FINISH) { | |
| 1847 | FLUSH_BLOCK(s, 1); | |
| 1848 | return finish_done; | |
| 1849 | } | |
| 1850 | if (s->last_lit) | |
| 1851 | FLUSH_BLOCK(s, 0); | |
| 1852 | return block_done; | |
| 1814 | } else if (s->match_available) { | |
| 1815 | /* If there was no match at the previous position, output a | |
| 1816 | * single literal. If there was a match but the current match | |
| 1817 | * is longer, truncate the previous match to a single literal. | |
| 1818 | */ | |
| 1819 | Tracevv((stderr,"%c", s->window[s->strstart-1])); | |
| 1820 | _tr_tally_lit(s, s->window[s->strstart-1], bflush); | |
| 1821 | if (bflush) { | |
| 1822 | FLUSH_BLOCK_ONLY(s, 0); | |
| 1823 | } | |
| 1824 | s->strstart++; | |
| 1825 | s->lookahead--; | |
| 1826 | if (s->strm->avail_out == 0) return need_more; | |
| 1827 | } else { | |
| 1828 | /* There is no previous match to compare with, wait for | |
| 1829 | * the next step to decide. | |
| 1830 | */ | |
| 1831 | s->match_available = 1; | |
| 1832 | s->strstart++; | |
| 1833 | s->lookahead--; | |
| 1834 | } | |
| 1835 | } | |
| 1836 | Assert (flush != Z_NO_FLUSH, "no flush?"); | |
| 1837 | if (s->match_available) { | |
| 1838 | Tracevv((stderr,"%c", s->window[s->strstart-1])); | |
| 1839 | _tr_tally_lit(s, s->window[s->strstart-1], bflush); | |
| 1840 | s->match_available = 0; | |
| 1841 | } | |
| 1842 | s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; | |
| 1843 | if (flush == Z_FINISH) { | |
| 1844 | FLUSH_BLOCK(s, 1); | |
| 1845 | return finish_done; | |
| 1846 | } | |
| 1847 | if (s->last_lit) | |
| 1848 | FLUSH_BLOCK(s, 0); | |
| 1849 | return block_done; | |
| 1853 | 1850 | } |
| 1854 | 1851 | #endif /* FASTEST */ |
| 1855 | 1852 | |
| r25360 | r25361 | |
| 1859 | 1856 | * deflate switches away from Z_RLE.) |
| 1860 | 1857 | */ |
| 1861 | 1858 | local block_state deflate_rle(s, flush) |
| 1862 | deflate_state *s; | |
| 1863 | int flush; | |
| 1859 | deflate_state *s; | |
| 1860 | int flush; | |
| 1864 | 1861 | { |
| 1865 | int bflush; /* set if current block must be flushed */ | |
| 1866 | uInt prev; /* byte at distance one to match */ | |
| 1867 | Bytef *scan, *strend; /* scan goes up to strend for length of run */ | |
| 1862 | int bflush; /* set if current block must be flushed */ | |
| 1863 | uInt prev; /* byte at distance one to match */ | |
| 1864 | Bytef *scan, *strend; /* scan goes up to strend for length of run */ | |
| 1868 | 1865 | |
| 1869 | for (;;) { | |
| 1870 | /* Make sure that we always have enough lookahead, except | |
| 1871 | * at the end of the input file. We need MAX_MATCH bytes | |
| 1872 | * for the longest run, plus one for the unrolled loop. | |
| 1873 | */ | |
| 1874 | if (s->lookahead <= MAX_MATCH) { | |
| 1875 | fill_window(s); | |
| 1876 | if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) { | |
| 1877 | return need_more; | |
| 1878 | } | |
| 1879 | if (s->lookahead == 0) break; /* flush the current block */ | |
| 1880 | } | |
| 1866 | for (;;) { | |
| 1867 | /* Make sure that we always have enough lookahead, except | |
| 1868 | * at the end of the input file. We need MAX_MATCH bytes | |
| 1869 | * for the longest run, plus one for the unrolled loop. | |
| 1870 | */ | |
| 1871 | if (s->lookahead <= MAX_MATCH) { | |
| 1872 | fill_window(s); | |
| 1873 | if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) { | |
| 1874 | return need_more; | |
| 1875 | } | |
| 1876 | if (s->lookahead == 0) break; /* flush the current block */ | |
| 1877 | } | |
| 1881 | 1878 | |
| 1882 | /* See how many times the previous byte repeats */ | |
| 1883 | s->match_length = 0; | |
| 1884 | if (s->lookahead >= MIN_MATCH && s->strstart > 0) { | |
| 1885 | scan = s->window + s->strstart - 1; | |
| 1886 | prev = *scan; | |
| 1887 | if (prev == *++scan && prev == *++scan && prev == *++scan) { | |
| 1888 | strend = s->window + s->strstart + MAX_MATCH; | |
| 1889 | do { | |
| 1890 | } while (prev == *++scan && prev == *++scan && | |
| 1891 | prev == *++scan && prev == *++scan && | |
| 1892 | prev == *++scan && prev == *++scan && | |
| 1893 | prev == *++scan && prev == *++scan && | |
| 1894 | scan < strend); | |
| 1895 | s->match_length = MAX_MATCH - (int)(strend - scan); | |
| 1896 | if (s->match_length > s->lookahead) | |
| 1897 | s->match_length = s->lookahead; | |
| 1898 | } | |
| 1899 | Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); | |
| 1900 | } | |
| 1879 | /* See how many times the previous byte repeats */ | |
| 1880 | s->match_length = 0; | |
| 1881 | if (s->lookahead >= MIN_MATCH && s->strstart > 0) { | |
| 1882 | scan = s->window + s->strstart - 1; | |
| 1883 | prev = *scan; | |
| 1884 | if (prev == *++scan && prev == *++scan && prev == *++scan) { | |
| 1885 | strend = s->window + s->strstart + MAX_MATCH; | |
| 1886 | do { | |
| 1887 | } while (prev == *++scan && prev == *++scan && | |
| 1888 | prev == *++scan && prev == *++scan && | |
| 1889 | prev == *++scan && prev == *++scan && | |
| 1890 | prev == *++scan && prev == *++scan && | |
| 1891 | scan < strend); | |
| 1892 | s->match_length = MAX_MATCH - (int)(strend - scan); | |
| 1893 | if (s->match_length > s->lookahead) | |
| 1894 | s->match_length = s->lookahead; | |
| 1895 | } | |
| 1896 | Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); | |
| 1897 | } | |
| 1901 | 1898 | |
| 1902 | /* Emit match if have run of MIN_MATCH or longer, else emit literal */ | |
| 1903 | if (s->match_length >= MIN_MATCH) { | |
| 1904 | check_match(s, s->strstart, s->strstart - 1, s->match_length); | |
| 1899 | /* Emit match if have run of MIN_MATCH or longer, else emit literal */ | |
| 1900 | if (s->match_length >= MIN_MATCH) { | |
| 1901 | check_match(s, s->strstart, s->strstart - 1, s->match_length); | |
| 1905 | 1902 | |
| 1906 | ||
| 1903 | _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush); | |
| 1907 | 1904 | |
| 1908 | s->lookahead -= s->match_length; | |
| 1909 | s->strstart += s->match_length; | |
| 1910 | s->match_length = 0; | |
| 1911 | } else { | |
| 1912 | /* No match, output a literal byte */ | |
| 1913 | Tracevv((stderr,"%c", s->window[s->strstart])); | |
| 1914 | _tr_tally_lit (s, s->window[s->strstart], bflush); | |
| 1915 | s->lookahead--; | |
| 1916 | s->strstart++; | |
| 1917 | } | |
| 1918 | if (bflush) FLUSH_BLOCK(s, 0); | |
| 1919 | } | |
| 1920 | s->insert = 0; | |
| 1921 | if (flush == Z_FINISH) { | |
| 1922 | FLUSH_BLOCK(s, 1); | |
| 1923 | return finish_done; | |
| 1924 | } | |
| 1925 | if (s->last_lit) | |
| 1926 | FLUSH_BLOCK(s, 0); | |
| 1927 | return block_done; | |
| 1905 | s->lookahead -= s->match_length; | |
| 1906 | s->strstart += s->match_length; | |
| 1907 | s->match_length = 0; | |
| 1908 | } else { | |
| 1909 | /* No match, output a literal byte */ | |
| 1910 | Tracevv((stderr,"%c", s->window[s->strstart])); | |
| 1911 | _tr_tally_lit (s, s->window[s->strstart], bflush); | |
| 1912 | s->lookahead--; | |
| 1913 | s->strstart++; | |
| 1914 | } | |
| 1915 | if (bflush) FLUSH_BLOCK(s, 0); | |
| 1916 | } | |
| 1917 | s->insert = 0; | |
| 1918 | if (flush == Z_FINISH) { | |
| 1919 | FLUSH_BLOCK(s, 1); | |
| 1920 | return finish_done; | |
| 1921 | } | |
| 1922 | if (s->last_lit) | |
| 1923 | FLUSH_BLOCK(s, 0); | |
| 1924 | return block_done; | |
| 1928 | 1925 | } |
| 1929 | 1926 | |
| 1930 | 1927 | /* =========================================================================== |
| r25360 | r25361 | |
| 1932 | 1929 | * (It will be regenerated if this run of deflate switches away from Huffman.) |
| 1933 | 1930 | */ |
| 1934 | 1931 | local block_state deflate_huff(s, flush) |
| 1935 | deflate_state *s; | |
| 1936 | int flush; | |
| 1932 | deflate_state *s; | |
| 1933 | int flush; | |
| 1937 | 1934 | { |
| 1938 | ||
| 1935 | int bflush; /* set if current block must be flushed */ | |
| 1939 | 1936 | |
| 1940 | for (;;) { | |
| 1941 | /* Make sure that we have a literal to write. */ | |
| 1942 | if (s->lookahead == 0) { | |
| 1943 | fill_window(s); | |
| 1944 | if (s->lookahead == 0) { | |
| 1945 | if (flush == Z_NO_FLUSH) | |
| 1946 | return need_more; | |
| 1947 | break; /* flush the current block */ | |
| 1948 | } | |
| 1949 | } | |
| 1937 | for (;;) { | |
| 1938 | /* Make sure that we have a literal to write. */ | |
| 1939 | if (s->lookahead == 0) { | |
| 1940 | fill_window(s); | |
| 1941 | if (s->lookahead == 0) { | |
| 1942 | if (flush == Z_NO_FLUSH) | |
| 1943 | return need_more; | |
| 1944 | break; /* flush the current block */ | |
| 1945 | } | |
| 1946 | } | |
| 1950 | 1947 | |
| 1951 | /* Output a literal byte */ | |
| 1952 | s->match_length = 0; | |
| 1953 | Tracevv((stderr,"%c", s->window[s->strstart])); | |
| 1954 | _tr_tally_lit (s, s->window[s->strstart], bflush); | |
| 1955 | s->lookahead--; | |
| 1956 | s->strstart++; | |
| 1957 | if (bflush) FLUSH_BLOCK(s, 0); | |
| 1958 | } | |
| 1959 | s->insert = 0; | |
| 1960 | if (flush == Z_FINISH) { | |
| 1961 | FLUSH_BLOCK(s, 1); | |
| 1962 | return finish_done; | |
| 1963 | } | |
| 1964 | if (s->last_lit) | |
| 1965 | FLUSH_BLOCK(s, 0); | |
| 1966 | return block_done; | |
| 1948 | /* Output a literal byte */ | |
| 1949 | s->match_length = 0; | |
| 1950 | Tracevv((stderr,"%c", s->window[s->strstart])); | |
| 1951 | _tr_tally_lit (s, s->window[s->strstart], bflush); | |
| 1952 | s->lookahead--; | |
| 1953 | s->strstart++; | |
| 1954 | if (bflush) FLUSH_BLOCK(s, 0); | |
| 1955 | } | |
| 1956 | s->insert = 0; | |
| 1957 | if (flush == Z_FINISH) { | |
| 1958 | FLUSH_BLOCK(s, 1); | |
| 1959 | return finish_done; | |
| 1960 | } | |
| 1961 | if (s->last_lit) | |
| 1962 | FLUSH_BLOCK(s, 0); | |
| 1963 | return block_done; | |
| 1967 | 1964 | } |
| r25360 | r25361 | |
|---|---|---|
| 83 | 83 | struct internal_state; |
| 84 | 84 | |
| 85 | 85 | typedef struct z_stream_s { |
| 86 | z_const Bytef *next_in; /* next input byte */ | |
| 87 | uInt avail_in; /* number of bytes available at next_in */ | |
| 88 | uLong total_in; /* total number of input bytes read so far */ | |
| 86 | z_const Bytef *next_in; /* next input byte */ | |
| 87 | uInt avail_in; /* number of bytes available at next_in */ | |
| 88 | uLong total_in; /* total number of input bytes read so far */ | |
| 89 | 89 | |
| 90 | Bytef *next_out; /* next output byte should be put there */ | |
| 91 | uInt avail_out; /* remaining free space at next_out */ | |
| 92 | uLong total_out; /* total number of bytes output so far */ | |
| 90 | Bytef *next_out; /* next output byte should be put there */ | |
| 91 | uInt avail_out; /* remaining free space at next_out */ | |
| 92 | uLong total_out; /* total number of bytes output so far */ | |
| 93 | 93 | |
| 94 | z_const char *msg; /* last error message, NULL if no error */ | |
| 95 | struct internal_state FAR *state; /* not visible by applications */ | |
| 94 | z_const char *msg; /* last error message, NULL if no error */ | |
| 95 | struct internal_state FAR *state; /* not visible by applications */ | |
| 96 | 96 | |
| 97 | alloc_func zalloc; /* used to allocate the internal state */ | |
| 98 | free_func zfree; /* used to free the internal state */ | |
| 99 | voidpf opaque; /* private data object passed to zalloc and zfree */ | |
| 97 | alloc_func zalloc; /* used to allocate the internal state */ | |
| 98 | free_func zfree; /* used to free the internal state */ | |
| 99 | voidpf opaque; /* private data object passed to zalloc and zfree */ | |
| 100 | 100 | |
| 101 | int data_type; /* best guess about the data type: binary or text */ | |
| 102 | uLong adler; /* adler32 value of the uncompressed data */ | |
| 103 | uLong reserved; /* reserved for future use */ | |
| 101 | int data_type; /* best guess about the data type: binary or text */ | |
| 102 | uLong adler; /* adler32 value of the uncompressed data */ | |
| 103 | uLong reserved; /* reserved for future use */ | |
| 104 | 104 | } z_stream; |
| 105 | 105 | |
| 106 | 106 | typedef z_stream FAR *z_streamp; |
| r25360 | r25361 | |
| 110 | 110 | for more details on the meanings of these fields. |
| 111 | 111 | */ |
| 112 | 112 | typedef struct gz_header_s { |
| 113 | int text; /* true if compressed data believed to be text */ | |
| 114 | uLong time; /* modification time */ | |
| 115 | int xflags; /* extra flags (not used when writing a gzip file) */ | |
| 116 | int os; /* operating system */ | |
| 117 | Bytef *extra; /* pointer to extra field or Z_NULL if none */ | |
| 118 | uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ | |
| 119 | uInt extra_max; /* space at extra (only when reading header) */ | |
| 120 | Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ | |
| 121 | uInt name_max; /* space at name (only when reading header) */ | |
| 122 | Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ | |
| 123 | uInt comm_max; /* space at comment (only when reading header) */ | |
| 124 | int hcrc; /* true if there was or will be a header crc */ | |
| 125 | int done; /* true when done reading gzip header (not used | |
| 113 | int text; /* true if compressed data believed to be text */ | |
| 114 | uLong time; /* modification time */ | |
| 115 | int xflags; /* extra flags (not used when writing a gzip file) */ | |
| 116 | int os; /* operating system */ | |
| 117 | Bytef *extra; /* pointer to extra field or Z_NULL if none */ | |
| 118 | uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ | |
| 119 | uInt extra_max; /* space at extra (only when reading header) */ | |
| 120 | Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ | |
| 121 | uInt name_max; /* space at name (only when reading header) */ | |
| 122 | Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ | |
| 123 | uInt comm_max; /* space at comment (only when reading header) */ | |
| 124 | int hcrc; /* true if there was or will be a header crc */ | |
| 125 | int done; /* true when done reading gzip header (not used | |
| 126 | 126 | when writing a gzip file) */ |
| 127 | 127 | } gz_header; |
| 128 | 128 | |
| r25360 | r25361 | |
| 159 | 159 | if the decompressor wants to decompress everything in a single step). |
| 160 | 160 | */ |
| 161 | 161 | |
| 162 | ||
| 162 | /* constants */ | |
| 163 | 163 | |
| 164 | 164 | #define Z_NO_FLUSH 0 |
| 165 | 165 | #define Z_PARTIAL_FLUSH 1 |
| r25360 | r25361 | |
| 211 | 211 | /* for compatibility with versions < 1.0.2 */ |
| 212 | 212 | |
| 213 | 213 | |
| 214 | ||
| 214 | /* basic functions */ | |
| 215 | 215 | |
| 216 | 216 | ZEXTERN const char * ZEXPORT zlibVersion OF((void)); |
| 217 | 217 | /* The application can compare zlibVersion and ZLIB_VERSION for consistency. |
| r25360 | r25361 | |
| 517 | 517 | */ |
| 518 | 518 | |
| 519 | 519 | |
| 520 | ||
| 520 | /* Advanced functions */ | |
| 521 | 521 | |
| 522 | 522 | /* |
| 523 | 523 | The following functions are needed only in some special applications. |
| r25360 | r25361 | |
| 585 | 585 | */ |
| 586 | 586 | |
| 587 | 587 | ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, |
| 588 | const Bytef *dictionary, | |
| 589 | uInt dictLength)); | |
| 588 | const Bytef *dictionary, | |
| 589 | uInt dictLength)); | |
| 590 | 590 | /* |
| 591 | 591 | Initializes the compression dictionary from the given byte sequence |
| 592 | 592 | without producing any compressed output. When using the zlib format, this |
| r25360 | r25361 | |
| 629 | 629 | */ |
| 630 | 630 | |
| 631 | 631 | ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, |
| 632 | ||
| 632 | z_streamp source)); | |
| 633 | 633 | /* |
| 634 | 634 | Sets the destination stream as a complete copy of the source stream. |
| 635 | 635 | |
| r25360 | r25361 | |
| 658 | 658 | */ |
| 659 | 659 | |
| 660 | 660 | ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, |
| 661 | int level, | |
| 662 | int strategy)); | |
| 661 | int level, | |
| 662 | int strategy)); | |
| 663 | 663 | /* |
| 664 | 664 | Dynamically update the compression level and compression strategy. The |
| 665 | 665 | interpretation of level and strategy is as in deflateInit2. This can be |
| r25360 | r25361 | |
| 679 | 679 | */ |
| 680 | 680 | |
| 681 | 681 | ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, |
| 682 | int good_length, | |
| 683 | int max_lazy, | |
| 684 | int nice_length, | |
| 685 | int max_chain)); | |
| 682 | int good_length, | |
| 683 | int max_lazy, | |
| 684 | int nice_length, | |
| 685 | int max_chain)); | |
| 686 | 686 | /* |
| 687 | 687 | Fine tune deflate's internal compression parameters. This should only be |
| 688 | 688 | used by someone who understands the algorithm used by zlib's deflate for |
| r25360 | r25361 | |
| 696 | 696 | */ |
| 697 | 697 | |
| 698 | 698 | ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, |
| 699 | ||
| 699 | uLong sourceLen)); | |
| 700 | 700 | /* |
| 701 | 701 | deflateBound() returns an upper bound on the compressed size after |
| 702 | 702 | deflation of sourceLen bytes. It must be called after deflateInit() or |
| r25360 | r25361 | |
| 711 | 711 | */ |
| 712 | 712 | |
| 713 | 713 | ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, |
| 714 | unsigned *pending, | |
| 715 | int *bits)); | |
| 714 | unsigned *pending, | |
| 715 | int *bits)); | |
| 716 | 716 | /* |
| 717 | 717 | deflatePending() returns the number of bytes and bits of output that have |
| 718 | 718 | been generated, but not yet provided in the available output. The bytes not |
| r25360 | r25361 | |
| 726 | 726 | */ |
| 727 | 727 | |
| 728 | 728 | ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, |
| 729 | int bits, | |
| 730 | int value)); | |
| 729 | int bits, | |
| 730 | int value)); | |
| 731 | 731 | /* |
| 732 | 732 | deflatePrime() inserts bits in the deflate output stream. The intent |
| 733 | 733 | is that this function is used to start off the deflate output with the bits |
| r25360 | r25361 | |
| 743 | 743 | */ |
| 744 | 744 | |
| 745 | 745 | ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, |
| 746 | ||
| 746 | gz_headerp head)); | |
| 747 | 747 | /* |
| 748 | 748 | deflateSetHeader() provides gzip header information for when a gzip |
| 749 | 749 | stream is requested by deflateInit2(). deflateSetHeader() may be called |
| r25360 | r25361 | |
| 817 | 817 | */ |
| 818 | 818 | |
| 819 | 819 | ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, |
| 820 | const Bytef *dictionary, | |
| 821 | uInt dictLength)); | |
| 820 | const Bytef *dictionary, | |
| 821 | uInt dictLength)); | |
| 822 | 822 | /* |
| 823 | 823 | Initializes the decompression dictionary from the given uncompressed byte |
| 824 | 824 | sequence. This function must be called immediately after a call of inflate, |
| r25360 | r25361 | |
| 840 | 840 | */ |
| 841 | 841 | |
| 842 | 842 | ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, |
| 843 | Bytef *dictionary, | |
| 844 | uInt *dictLength)); | |
| 843 | Bytef *dictionary, | |
| 844 | uInt *dictLength)); | |
| 845 | 845 | /* |
| 846 | 846 | Returns the sliding dictionary being maintained by inflate. dictLength is |
| 847 | 847 | set to the number of bytes in the dictionary, and that many bytes are copied |
| r25360 | r25361 | |
| 874 | 874 | */ |
| 875 | 875 | |
| 876 | 876 | ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, |
| 877 | ||
| 877 | z_streamp source)); | |
| 878 | 878 | /* |
| 879 | 879 | Sets the destination stream as a complete copy of the source stream. |
| 880 | 880 | |
| r25360 | r25361 | |
| 900 | 900 | */ |
| 901 | 901 | |
| 902 | 902 | ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, |
| 903 | ||
| 903 | int windowBits)); | |
| 904 | 904 | /* |
| 905 | 905 | This function is the same as inflateReset, but it also permits changing |
| 906 | 906 | the wrap and window size requests. The windowBits parameter is interpreted |
| r25360 | r25361 | |
| 912 | 912 | */ |
| 913 | 913 | |
| 914 | 914 | ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, |
| 915 | int bits, | |
| 916 | int value)); | |
| 915 | int bits, | |
| 916 | int value)); | |
| 917 | 917 | /* |
| 918 | 918 | This function inserts bits in the inflate input stream. The intent is |
| 919 | 919 | that this function is used to start inflating at a bit position in the |
| r25360 | r25361 | |
| 961 | 961 | */ |
| 962 | 962 | |
| 963 | 963 | ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, |
| 964 | ||
| 964 | gz_headerp head)); | |
| 965 | 965 | /* |
| 966 | 966 | inflateGetHeader() requests that gzip header information be stored in the |
| 967 | 967 | provided gz_header structure. inflateGetHeader() may be called after |
| r25360 | r25361 | |
| 1023 | 1023 | */ |
| 1024 | 1024 | |
| 1025 | 1025 | typedef unsigned (*in_func) OF((void FAR *, |
| 1026 | ||
| 1026 | z_const unsigned char FAR * FAR *)); | |
| 1027 | 1027 | typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); |
| 1028 | 1028 | |
| 1029 | 1029 | ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, |
| 1030 | in_func in, void FAR *in_desc, | |
| 1031 | out_func out, void FAR *out_desc)); | |
| 1030 | in_func in, void FAR *in_desc, | |
| 1031 | out_func out, void FAR *out_desc)); | |
| 1032 | 1032 | /* |
| 1033 | 1033 | inflateBack() does a raw inflate with a single call using a call-back |
| 1034 | 1034 | interface for input and output. This is potentially more efficient than |
| r25360 | r25361 | |
| 1147 | 1147 | |
| 1148 | 1148 | #ifndef Z_SOLO |
| 1149 | 1149 | |
| 1150 | ||
| 1150 | /* utility functions */ | |
| 1151 | 1151 | |
| 1152 | 1152 | /* |
| 1153 | 1153 | The following utility functions are implemented on top of the basic |
| r25360 | r25361 | |
| 1158 | 1158 | */ |
| 1159 | 1159 | |
| 1160 | 1160 | ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, |
| 1161 | ||
| 1161 | const Bytef *source, uLong sourceLen)); | |
| 1162 | 1162 | /* |
| 1163 | 1163 | Compresses the source buffer into the destination buffer. sourceLen is |
| 1164 | 1164 | the byte length of the source buffer. Upon entry, destLen is the total size |
| r25360 | r25361 | |
| 1172 | 1172 | */ |
| 1173 | 1173 | |
| 1174 | 1174 | ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, |
| 1175 | const Bytef *source, uLong sourceLen, | |
| 1176 | int level)); | |
| 1175 | const Bytef *source, uLong sourceLen, | |
| 1176 | int level)); | |
| 1177 | 1177 | /* |
| 1178 | 1178 | Compresses the source buffer into the destination buffer. The level |
| 1179 | 1179 | parameter has the same meaning as in deflateInit. sourceLen is the byte |
| r25360 | r25361 | |
| 1195 | 1195 | */ |
| 1196 | 1196 | |
| 1197 | 1197 | ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, |
| 1198 | ||
| 1198 | const Bytef *source, uLong sourceLen)); | |
| 1199 | 1199 | /* |
| 1200 | 1200 | Decompresses the source buffer into the destination buffer. sourceLen is |
| 1201 | 1201 | the byte length of the source buffer. Upon entry, destLen is the total size |
| r25360 | r25361 | |
| 1212 | 1212 | buffer with the uncompressed data up to that point. |
| 1213 | 1213 | */ |
| 1214 | 1214 | |
| 1215 | ||
| 1215 | /* gzip file access functions */ | |
| 1216 | 1216 | |
| 1217 | 1217 | /* |
| 1218 | 1218 | This library supports reading and writing files in gzip (.gz) format with |
| r25360 | r25361 | |
| 1339 | 1339 | */ |
| 1340 | 1340 | |
| 1341 | 1341 | ZEXTERN int ZEXPORT gzwrite OF((gzFile file, |
| 1342 | ||
| 1342 | voidpc buf, unsigned len)); | |
| 1343 | 1343 | /* |
| 1344 | 1344 | Writes the given number of uncompressed bytes into the compressed file. |
| 1345 | 1345 | gzwrite returns the number of uncompressed bytes written or 0 in case of |
| r25360 | r25361 | |
| 1558 | 1558 | |
| 1559 | 1559 | #endif /* !Z_SOLO */ |
| 1560 | 1560 | |
| 1561 | ||
| 1561 | /* checksum functions */ | |
| 1562 | 1562 | |
| 1563 | 1563 | /* |
| 1564 | 1564 | These functions are not related to compression but are exported |
| r25360 | r25361 | |
| 1625 | 1625 | */ |
| 1626 | 1626 | |
| 1627 | 1627 | |
| 1628 | ||
| 1628 | /* various hacks, don't look :) */ | |
| 1629 | 1629 | |
| 1630 | 1630 | /* deflateInit and inflateInit are macros to allow checking the zlib version |
| 1631 | 1631 | * and the compiler's view of z_stream: |
| 1632 | 1632 | */ |
| 1633 | 1633 | ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, |
| 1634 | ||
| 1634 | const char *version, int stream_size)); | |
| 1635 | 1635 | ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, |
| 1636 | ||
| 1636 | const char *version, int stream_size)); | |
| 1637 | 1637 | ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, |
| 1638 | int windowBits, int memLevel, | |
| 1639 | int strategy, const char *version, | |
| 1640 | int stream_size)); | |
| 1638 | int windowBits, int memLevel, | |
| 1639 | int strategy, const char *version, | |
| 1640 | int stream_size)); | |
| 1641 | 1641 | ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, |
| 1642 | ||
| 1642 | const char *version, int stream_size)); | |
| 1643 | 1643 | ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, |
| 1644 | unsigned char FAR *window, | |
| 1645 | const char *version, | |
| 1646 | int stream_size)); | |
| 1644 | unsigned char FAR *window, | |
| 1645 | const char *version, | |
| 1646 | int stream_size)); | |
| 1647 | 1647 | #define deflateInit(strm, level) \ |
| 1648 | ||
| 1648 | deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) | |
| 1649 | 1649 | #define inflateInit(strm) \ |
| 1650 | ||
| 1650 | inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) | |
| 1651 | 1651 | #define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ |
| 1652 | deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ | |
| 1653 | (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) | |
| 1652 | deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ | |
| 1653 | (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) | |
| 1654 | 1654 | #define inflateInit2(strm, windowBits) \ |
| 1655 | inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ | |
| 1656 | (int)sizeof(z_stream)) | |
| 1655 | inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ | |
| 1656 | (int)sizeof(z_stream)) | |
| 1657 | 1657 | #define inflateBackInit(strm, windowBits, window) \ |
| 1658 | inflateBackInit_((strm), (windowBits), (window), \ | |
| 1659 | ZLIB_VERSION, (int)sizeof(z_stream)) | |
| 1658 | inflateBackInit_((strm), (windowBits), (window), \ | |
| 1659 | ZLIB_VERSION, (int)sizeof(z_stream)) | |
| 1660 | 1660 | |
| 1661 | 1661 | #ifndef Z_SOLO |
| 1662 | 1662 | |
| r25360 | r25361 | |
| 1668 | 1668 | * only be used by the gzgetc() macro. You have been warned. |
| 1669 | 1669 | */ |
| 1670 | 1670 | struct gzFile_s { |
| 1671 | unsigned have; | |
| 1672 | unsigned char *next; | |
| 1673 | z_off64_t pos; | |
| 1671 | unsigned have; | |
| 1672 | unsigned char *next; | |
| 1673 | z_off64_t pos; | |
| 1674 | 1674 | }; |
| 1675 | 1675 | ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ |
| 1676 | 1676 | #ifdef Z_PREFIX_SET |
| 1677 | 1677 | # undef z_gzgetc |
| 1678 | 1678 | # define z_gzgetc(g) \ |
| 1679 | ||
| 1679 | ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) | |
| 1680 | 1680 | #else |
| 1681 | 1681 | # define gzgetc(g) \ |
| 1682 | ||
| 1682 | ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) | |
| 1683 | 1683 | #endif |
| 1684 | 1684 | |
| 1685 | 1685 | /* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or |
| r25360 | r25361 | |
| 1689 | 1689 | * without large file support, _LFS64_LARGEFILE must also be true |
| 1690 | 1690 | */ |
| 1691 | 1691 | #ifdef Z_LARGE64 |
| 1692 | ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); | |
| 1693 | ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); | |
| 1694 | ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); | |
| 1695 | ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); | |
| 1696 | ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); | |
| 1697 | ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); | |
| 1692 | ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); | |
| 1693 | ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); | |
| 1694 | ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); | |
| 1695 | ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); | |
| 1696 | ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); | |
| 1697 | ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); | |
| 1698 | 1698 | #endif |
| 1699 | 1699 | |
| 1700 | 1700 | #if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) |
| r25360 | r25361 | |
| 1714 | 1714 | # define crc32_combine crc32_combine64 |
| 1715 | 1715 | # endif |
| 1716 | 1716 | # ifndef Z_LARGE64 |
| 1717 | ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); | |
| 1718 | ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); | |
| 1719 | ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); | |
| 1720 | ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); | |
| 1721 | ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); | |
| 1722 | ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); | |
| 1717 | ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); | |
| 1718 | ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); | |
| 1719 | ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); | |
| 1720 | ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); | |
| 1721 | ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); | |
| 1722 | ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); | |
| 1723 | 1723 | # endif |
| 1724 | 1724 | #else |
| 1725 | ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); | |
| 1726 | ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); | |
| 1727 | ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); | |
| 1728 | ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); | |
| 1729 | ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); | |
| 1730 | ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); | |
| 1725 | ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); | |
| 1726 | ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); | |
| 1727 | ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); | |
| 1728 | ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); | |
| 1729 | ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); | |
| 1730 | ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); | |
| 1731 | 1731 | #endif |
| 1732 | 1732 | |
| 1733 | 1733 | #else /* Z_SOLO */ |
| 1734 | 1734 | |
| 1735 | ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); | |
| 1736 | ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); | |
| 1735 | ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); | |
| 1736 | ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); | |
| 1737 | 1737 | |
| 1738 | 1738 | #endif /* !Z_SOLO */ |
| 1739 | 1739 | |
| 1740 | 1740 | /* hack for buggy compilers */ |
| 1741 | 1741 | #if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) |
| 1742 | ||
| 1742 | struct internal_state {int dummy;}; | |
| 1743 | 1743 | #endif |
| 1744 | 1744 | |
| 1745 | 1745 | /* undocumented functions */ |
| r25360 | r25361 | |
| 1751 | 1751 | ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); |
| 1752 | 1752 | #if defined(_WIN32) && !defined(Z_SOLO) |
| 1753 | 1753 | ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, |
| 1754 | ||
| 1754 | const char *mode)); | |
| 1755 | 1755 | #endif |
| 1756 | 1756 | #if defined(STDC) || defined(Z_HAVE_STDARG_H) |
| 1757 | 1757 | # ifndef Z_SOLO |
| 1758 | 1758 | ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, |
| 1759 | const char *format, | |
| 1760 | va_list va)); | |
| 1759 | const char *format, | |
| 1760 | va_list va)); | |
| 1761 | 1761 | # endif |
| 1762 | 1762 | #endif |
| 1763 | 1763 |
| r25360 | r25361 | |
|---|---|---|
| 9 | 9 | That way the other gzclose functions can be used instead to avoid linking in |
| 10 | 10 | unneeded compression or decompression routines. */ |
| 11 | 11 | int ZEXPORT gzclose(file) |
| 12 | ||
| 12 | gzFile file; | |
| 13 | 13 | { |
| 14 | 14 | #ifndef NO_GZCOMPRESS |
| 15 | ||
| 15 | gz_statep state; | |
| 16 | 16 | |
| 17 | if (file == NULL) | |
| 18 | return Z_STREAM_ERROR; | |
| 19 | state = (gz_statep)file; | |
| 17 | if (file == NULL) | |
| 18 | return Z_STREAM_ERROR; | |
| 19 | state = (gz_statep)file; | |
| 20 | 20 | |
| 21 | ||
| 21 | return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file); | |
| 22 | 22 | #else |
| 23 | ||
| 23 | return gzclose_r(file); | |
| 24 | 24 | #endif |
| 25 | 25 | } |
| r25360 | r25361 | |
|---|---|---|
| 29 | 29 | |
| 30 | 30 | const char * ZEXPORT zlibVersion() |
| 31 | 31 | { |
| 32 | ||
| 32 | return ZLIB_VERSION; | |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | 35 | uLong ZEXPORT zlibCompileFlags() |
| 36 | 36 | { |
| 37 | ||
| 37 | uLong flags; | |
| 38 | 38 | |
| 39 | flags = 0; | |
| 40 | switch ((int)(sizeof(uInt))) { | |
| 41 | case 2: break; | |
| 42 | case 4: flags += 1; break; | |
| 43 | case 8: flags += 2; break; | |
| 44 | default: flags += 3; | |
| 45 | } | |
| 46 | switch ((int)(sizeof(uLong))) { | |
| 47 | case 2: break; | |
| 48 | case 4: flags += 1 << 2; break; | |
| 49 | case 8: flags += 2 << 2; break; | |
| 50 | default: flags += 3 << 2; | |
| 51 | } | |
| 52 | switch ((int)(sizeof(voidpf))) { | |
| 53 | case 2: break; | |
| 54 | case 4: flags += 1 << 4; break; | |
| 55 | case 8: flags += 2 << 4; break; | |
| 56 | default: flags += 3 << 4; | |
| 57 | } | |
| 58 | switch ((int)(sizeof(z_off_t))) { | |
| 59 | case 2: break; | |
| 60 | case 4: flags += 1 << 6; break; | |
| 61 | case 8: flags += 2 << 6; break; | |
| 62 | default: flags += 3 << 6; | |
| 63 | } | |
| 39 | flags = 0; | |
| 40 | switch ((int)(sizeof(uInt))) { | |
| 41 | case 2: break; | |
| 42 | case 4: flags += 1; break; | |
| 43 | case 8: flags += 2; break; | |
| 44 | default: flags += 3; | |
| 45 | } | |
| 46 | switch ((int)(sizeof(uLong))) { | |
| 47 | case 2: break; | |
| 48 | case 4: flags += 1 << 2; break; | |
| 49 | case 8: flags += 2 << 2; break; | |
| 50 | default: flags += 3 << 2; | |
| 51 | } | |
| 52 | switch ((int)(sizeof(voidpf))) { | |
| 53 | case 2: break; | |
| 54 | case 4: flags += 1 << 4; break; | |
| 55 | case 8: flags += 2 << 4; break; | |
| 56 | default: flags += 3 << 4; | |
| 57 | } | |
| 58 | switch ((int)(sizeof(z_off_t))) { | |
| 59 | case 2: break; | |
| 60 | case 4: flags += 1 << 6; break; | |
| 61 | case 8: flags += 2 << 6; break; | |
| 62 | default: flags += 3 << 6; | |
| 63 | } | |
| 64 | 64 | #ifdef DEBUG |
| 65 | ||
| 65 | flags += 1 << 8; | |
| 66 | 66 | #endif |
| 67 | 67 | #if defined(ASMV) || defined(ASMINF) |
| 68 | ||
| 68 | flags += 1 << 9; | |
| 69 | 69 | #endif |
| 70 | 70 | #ifdef ZLIB_WINAPI |
| 71 | ||
| 71 | flags += 1 << 10; | |
| 72 | 72 | #endif |
| 73 | 73 | #ifdef BUILDFIXED |
| 74 | ||
| 74 | flags += 1 << 12; | |
| 75 | 75 | #endif |
| 76 | 76 | #ifdef DYNAMIC_CRC_TABLE |
| 77 | ||
| 77 | flags += 1 << 13; | |
| 78 | 78 | #endif |
| 79 | 79 | #ifdef NO_GZCOMPRESS |
| 80 | ||
| 80 | flags += 1L << 16; | |
| 81 | 81 | #endif |
| 82 | 82 | #ifdef NO_GZIP |
| 83 | ||
| 83 | flags += 1L << 17; | |
| 84 | 84 | #endif |
| 85 | 85 | #ifdef PKZIP_BUG_WORKAROUND |
| 86 | ||
| 86 | flags += 1L << 20; | |
| 87 | 87 | #endif |
| 88 | 88 | #ifdef FASTEST |
| 89 | ||
| 89 | flags += 1L << 21; | |
| 90 | 90 | #endif |
| 91 | 91 | #if defined(STDC) || defined(Z_HAVE_STDARG_H) |
| 92 | 92 | # ifdef NO_vsnprintf |
| 93 | ||
| 93 | flags += 1L << 25; | |
| 94 | 94 | # ifdef HAS_vsprintf_void |
| 95 | ||
| 95 | flags += 1L << 26; | |
| 96 | 96 | # endif |
| 97 | 97 | # else |
| 98 | 98 | # ifdef HAS_vsnprintf_void |
| 99 | ||
| 99 | flags += 1L << 26; | |
| 100 | 100 | # endif |
| 101 | 101 | # endif |
| 102 | 102 | #else |
| 103 | ||
| 103 | flags += 1L << 24; | |
| 104 | 104 | # ifdef NO_snprintf |
| 105 | ||
| 105 | flags += 1L << 25; | |
| 106 | 106 | # ifdef HAS_sprintf_void |
| 107 | ||
| 107 | flags += 1L << 26; | |
| 108 | 108 | # endif |
| 109 | 109 | # else |
| 110 | 110 | # ifdef HAS_snprintf_void |
| 111 | ||
| 111 | flags += 1L << 26; | |
| 112 | 112 | # endif |
| 113 | 113 | # endif |
| 114 | 114 | #endif |
| 115 | ||
| 115 | return flags; | |
| 116 | 116 | } |
| 117 | 117 | |
| 118 | 118 | #ifdef DEBUG |
| r25360 | r25361 | |
| 123 | 123 | int ZLIB_INTERNAL z_verbose = verbose; |
| 124 | 124 | |
| 125 | 125 | void ZLIB_INTERNAL z_error (m) |
| 126 | ||
| 126 | char *m; | |
| 127 | 127 | { |
| 128 | fprintf(stderr, "%s\n", m); | |
| 129 | exit(1); | |
| 128 | fprintf(stderr, "%s\n", m); | |
| 129 | exit(1); | |
| 130 | 130 | } |
| 131 | 131 | #endif |
| 132 | 132 | |
| r25360 | r25361 | |
| 134 | 134 | * uncompress() |
| 135 | 135 | */ |
| 136 | 136 | const char * ZEXPORT zError(err) |
| 137 | ||
| 137 | int err; | |
| 138 | 138 | { |
| 139 | ||
| 139 | return ERR_MSG(err); | |
| 140 | 140 | } |
| 141 | 141 | |
| 142 | 142 | #if defined(_WIN32_WCE) |
| 143 | /* The Microsoft C Run-Time Library for Windows CE doesn't have | |
| 144 | * errno. We define it as a global variable to simplify porting. | |
| 145 | * Its value is always 0 and should not be used. | |
| 146 | */ | |
| 147 | int errno = 0; | |
| 143 | /* The Microsoft C Run-Time Library for Windows CE doesn't have | |
| 144 | * errno. We define it as a global variable to simplify porting. | |
| 145 | * Its value is always 0 and should not be used. | |
| 146 | */ | |
| 147 | int errno = 0; | |
| 148 | 148 | #endif |
| 149 | 149 | |
| 150 | 150 | #ifndef HAVE_MEMCPY |
| 151 | 151 | |
| 152 | 152 | void ZLIB_INTERNAL zmemcpy(dest, source, len) |
| 153 | Bytef* dest; | |
| 154 | const Bytef* source; | |
| 155 | uInt len; | |
| 153 | Bytef* dest; | |
| 154 | const Bytef* source; | |
| 155 | uInt len; | |
| 156 | 156 | { |
| 157 | if (len == 0) return; | |
| 158 | do { | |
| 159 | *dest++ = *source++; /* ??? to be unrolled */ | |
| 160 | } while (--len != 0); | |
| 157 | if (len == 0) return; | |
| 158 | do { | |
| 159 | *dest++ = *source++; /* ??? to be unrolled */ | |
| 160 | } while (--len != 0); | |
| 161 | 161 | } |
| 162 | 162 | |
| 163 | 163 | int ZLIB_INTERNAL zmemcmp(s1, s2, len) |
| 164 | const Bytef* s1; | |
| 165 | const Bytef* s2; | |
| 166 | uInt len; | |
| 164 | const Bytef* s1; | |
| 165 | const Bytef* s2; | |
| 166 | uInt len; | |
| 167 | 167 | { |
| 168 | ||
| 168 | uInt j; | |
| 169 | 169 | |
| 170 | for (j = 0; j < len; j++) { | |
| 171 | if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; | |
| 172 | } | |
| 173 | return 0; | |
| 170 | for (j = 0; j < len; j++) { | |
| 171 | if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; | |
| 172 | } | |
| 173 | return 0; | |
| 174 | 174 | } |
| 175 | 175 | |
| 176 | 176 | void ZLIB_INTERNAL zmemzero(dest, len) |
| 177 | Bytef* dest; | |
| 178 | uInt len; | |
| 177 | Bytef* dest; | |
| 178 | uInt len; | |
| 179 | 179 | { |
| 180 | if (len == 0) return; | |
| 181 | do { | |
| 182 | *dest++ = 0; /* ??? to be unrolled */ | |
| 183 | } while (--len != 0); | |
| 180 | if (len == 0) return; | |
| 181 | do { | |
| 182 | *dest++ = 0; /* ??? to be unrolled */ | |
| 183 | } while (--len != 0); | |
| 184 | 184 | } |
| 185 | 185 | #endif |
| 186 | 186 | |
| r25360 | r25361 | |
| 205 | 205 | local int next_ptr = 0; |
| 206 | 206 | |
| 207 | 207 | typedef struct ptr_table_s { |
| 208 | voidpf org_ptr; | |
| 209 | voidpf new_ptr; | |
| 208 | voidpf org_ptr; | |
| 209 | voidpf new_ptr; | |
| 210 | 210 | } ptr_table; |
| 211 | 211 | |
| 212 | 212 | local ptr_table table[MAX_PTR]; |
| r25360 | r25361 | |
| 219 | 219 | |
| 220 | 220 | voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) |
| 221 | 221 | { |
| 222 | voidpf buf = opaque; /* just to make some compilers happy */ | |
| 223 | ulg bsize = (ulg)items*size; | |
| 222 | voidpf buf = opaque; /* just to make some compilers happy */ | |
| 223 | ulg bsize = (ulg)items*size; | |
| 224 | 224 | |
| 225 | /* If we allocate less than 65520 bytes, we assume that farmalloc | |
| 226 | * will return a usable pointer which doesn't have to be normalized. | |
| 227 | */ | |
| 228 | if (bsize < 65520L) { | |
| 229 | buf = farmalloc(bsize); | |
| 230 | if (*(ush*)&buf != 0) return buf; | |
| 231 | } else { | |
| 232 | buf = farmalloc(bsize + 16L); | |
| 233 | } | |
| 234 | if (buf == NULL || next_ptr >= MAX_PTR) return NULL; | |
| 235 | table[next_ptr].org_ptr = buf; | |
| 225 | /* If we allocate less than 65520 bytes, we assume that farmalloc | |
| 226 | * will return a usable pointer which doesn't have to be normalized. | |
| 227 | */ | |
| 228 | if (bsize < 65520L) { | |
| 229 | buf = farmalloc(bsize); | |
| 230 | if (*(ush*)&buf != 0) return buf; | |
| 231 | } else { | |
| 232 | buf = farmalloc(bsize + 16L); | |
| 233 | } | |
| 234 | if (buf == NULL || next_ptr >= MAX_PTR) return NULL; | |
| 235 | table[next_ptr].org_ptr = buf; | |
| 236 | 236 | |
| 237 | /* Normalize the pointer to seg:0 */ | |
| 238 | *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; | |
| 239 | *(ush*)&buf = 0; | |
| 240 | table[next_ptr++].new_ptr = buf; | |
| 241 | return buf; | |
| 237 | /* Normalize the pointer to seg:0 */ | |
| 238 | *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; | |
| 239 | *(ush*)&buf = 0; | |
| 240 | table[next_ptr++].new_ptr = buf; | |
| 241 | return buf; | |
| 242 | 242 | } |
| 243 | 243 | |
| 244 | 244 | void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) |
| 245 | 245 | { |
| 246 | int n; | |
| 247 | if (*(ush*)&ptr != 0) { /* object < 64K */ | |
| 248 | farfree(ptr); | |
| 249 | return; | |
| 250 | } | |
| 251 | /* Find the original pointer */ | |
| 252 | for (n = 0; n < next_ptr; n++) { | |
| 253 | if (ptr != table[n].new_ptr) continue; | |
| 246 | int n; | |
| 247 | if (*(ush*)&ptr != 0) { /* object < 64K */ | |
| 248 | farfree(ptr); | |
| 249 | return; | |
| 250 | } | |
| 251 | /* Find the original pointer */ | |
| 252 | for (n = 0; n < next_ptr; n++) { | |
| 253 | if (ptr != table[n].new_ptr) continue; | |
| 254 | 254 | |
| 255 | farfree(table[n].org_ptr); | |
| 256 | while (++n < next_ptr) { | |
| 257 | table[n-1] = table[n]; | |
| 258 | } | |
| 259 | next_ptr--; | |
| 260 | return; | |
| 261 | } | |
| 262 | ptr = opaque; /* just to make some compilers happy */ | |
| 263 | Assert(0, "zcfree: ptr not found"); | |
| 255 | farfree(table[n].org_ptr); | |
| 256 | while (++n < next_ptr) { | |
| 257 | table[n-1] = table[n]; | |
| 258 | } | |
| 259 | next_ptr--; | |
| 260 | return; | |
| 261 | } | |
| 262 | ptr = opaque; /* just to make some compilers happy */ | |
| 263 | Assert(0, "zcfree: ptr not found"); | |
| 264 | 264 | } |
| 265 | 265 | |
| 266 | 266 | #endif /* __TURBOC__ */ |
| r25360 | r25361 | |
| 278 | 278 | |
| 279 | 279 | voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) |
| 280 | 280 | { |
| 281 | if (opaque) opaque = 0; /* to make compiler happy */ | |
| 282 | return _halloc((long)items, size); | |
| 281 | if (opaque) opaque = 0; /* to make compiler happy */ | |
| 282 | return _halloc((long)items, size); | |
| 283 | 283 | } |
| 284 | 284 | |
| 285 | 285 | void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) |
| 286 | 286 | { |
| 287 | if (opaque) opaque = 0; /* to make compiler happy */ | |
| 288 | _hfree(ptr); | |
| 287 | if (opaque) opaque = 0; /* to make compiler happy */ | |
| 288 | _hfree(ptr); | |
| 289 | 289 | } |
| 290 | 290 | |
| 291 | 291 | #endif /* M_I86 */ |
| r25360 | r25361 | |
| 302 | 302 | #endif |
| 303 | 303 | |
| 304 | 304 | voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) |
| 305 | voidpf opaque; | |
| 306 | unsigned items; | |
| 307 | unsigned size; | |
| 305 | voidpf opaque; | |
| 306 | unsigned items; | |
| 307 | unsigned size; | |
| 308 | 308 | { |
| 309 | if (opaque) items += size - size; /* make compiler happy */ | |
| 310 | return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : | |
| 311 | (voidpf)calloc(items, size); | |
| 309 | if (opaque) items += size - size; /* make compiler happy */ | |
| 310 | return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : | |
| 311 | (voidpf)calloc(items, size); | |
| 312 | 312 | } |
| 313 | 313 | |
| 314 | 314 | void ZLIB_INTERNAL zcfree (opaque, ptr) |
| 315 | voidpf opaque; | |
| 316 | voidpf ptr; | |
| 315 | voidpf opaque; | |
| 316 | voidpf ptr; | |
| 317 | 317 | { |
| 318 | free(ptr); | |
| 319 | if (opaque) return; /* make compiler happy */ | |
| 318 | free(ptr); | |
| 319 | if (opaque) return; /* make compiler happy */ | |
| 320 | 320 | } |
| 321 | 321 | |
| 322 | 322 | #endif /* MY_ZCALLOC */ |
| r25360 | r25361 | |
|---|---|---|
| 31 | 31 | The gz_strwinerror function does not change the current setting of |
| 32 | 32 | GetLastError. */ |
| 33 | 33 | char ZLIB_INTERNAL *gz_strwinerror (error) |
| 34 | ||
| 34 | DWORD error; | |
| 35 | 35 | { |
| 36 | ||
| 36 | static char buf[1024]; | |
| 37 | 37 | |
| 38 | wchar_t *msgbuf; | |
| 39 | DWORD lasterr = GetLastError(); | |
| 40 | DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | |
| 41 | | FORMAT_MESSAGE_ALLOCATE_BUFFER, | |
| 42 | NULL, | |
| 43 | error, | |
| 44 | 0, /* Default language */ | |
| 45 | (LPVOID)&msgbuf, | |
| 46 | 0, | |
| 47 | NULL); | |
| 48 | if (chars != 0) { | |
| 49 | /* If there is an \r\n appended, zap it. */ | |
| 50 | if (chars >= 2 | |
| 51 | && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { | |
| 52 | chars -= 2; | |
| 53 | msgbuf[chars] = 0; | |
| 54 | } | |
| 38 | wchar_t *msgbuf; | |
| 39 | DWORD lasterr = GetLastError(); | |
| 40 | DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | |
| 41 | | FORMAT_MESSAGE_ALLOCATE_BUFFER, | |
| 42 | NULL, | |
| 43 | error, | |
| 44 | 0, /* Default language */ | |
| 45 | (LPVOID)&msgbuf, | |
| 46 | 0, | |
| 47 | NULL); | |
| 48 | if (chars != 0) { | |
| 49 | /* If there is an \r\n appended, zap it. */ | |
| 50 | if (chars >= 2 | |
| 51 | && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { | |
| 52 | chars -= 2; | |
| 53 | msgbuf[chars] = 0; | |
| 54 | } | |
| 55 | 55 | |
| 56 | if (chars > sizeof (buf) - 1) { | |
| 57 | chars = sizeof (buf) - 1; | |
| 58 | msgbuf[chars] = 0; | |
| 59 | } | |
| 56 | if (chars > sizeof (buf) - 1) { | |
| 57 | chars = sizeof (buf) - 1; | |
| 58 | msgbuf[chars] = 0; | |
| 59 | } | |
| 60 | 60 | |
| 61 | wcstombs(buf, msgbuf, chars + 1); | |
| 62 | LocalFree(msgbuf); | |
| 63 | } | |
| 64 | else { | |
| 65 | sprintf(buf, "unknown win32 error (%ld)", error); | |
| 66 | } | |
| 61 | wcstombs(buf, msgbuf, chars + 1); | |
| 62 | LocalFree(msgbuf); | |
| 63 | } | |
| 64 | else { | |
| 65 | sprintf(buf, "unknown win32 error (%ld)", error); | |
| 66 | } | |
| 67 | 67 | |
| 68 | SetLastError(lasterr); | |
| 69 | return buf; | |
| 68 | SetLastError(lasterr); | |
| 69 | return buf; | |
| 70 | 70 | } |
| 71 | 71 | |
| 72 | 72 | #endif /* UNDER_CE */ |
| 73 | 73 | |
| 74 | 74 | /* Reset gzip file state */ |
| 75 | 75 | local void gz_reset(state) |
| 76 | ||
| 76 | gz_statep state; | |
| 77 | 77 | { |
| 78 | state->x.have = 0; /* no output data available */ | |
| 79 | if (state->mode == GZ_READ) { /* for reading ... */ | |
| 80 | state->eof = 0; /* not at end of file */ | |
| 81 | state->past = 0; /* have not read past end yet */ | |
| 82 | state->how = LOOK; /* look for gzip header */ | |
| 83 | } | |
| 84 | state->seek = 0; /* no seek request pending */ | |
| 85 | gz_error(state, Z_OK, NULL); /* clear error */ | |
| 86 | state->x.pos = 0; /* no uncompressed data yet */ | |
| 87 | state->strm.avail_in = 0; /* no input data yet */ | |
| 78 | state->x.have = 0; /* no output data available */ | |
| 79 | if (state->mode == GZ_READ) { /* for reading ... */ | |
| 80 | state->eof = 0; /* not at end of file */ | |
| 81 | state->past = 0; /* have not read past end yet */ | |
| 82 | state->how = LOOK; /* look for gzip header */ | |
| 83 | } | |
| 84 | state->seek = 0; /* no seek request pending */ | |
| 85 | gz_error(state, Z_OK, NULL); /* clear error */ | |
| 86 | state->x.pos = 0; /* no uncompressed data yet */ | |
| 87 | state->strm.avail_in = 0; /* no input data yet */ | |
| 88 | 88 | } |
| 89 | 89 | |
| 90 | 90 | /* Open a gzip file either by name or file descriptor. */ |
| 91 | 91 | local gzFile gz_open(path, fd, mode) |
| 92 | const void *path; | |
| 93 | int fd; | |
| 94 | const char *mode; | |
| 92 | const void *path; | |
| 93 | int fd; | |
| 94 | const char *mode; | |
| 95 | 95 | { |
| 96 | gz_statep state; | |
| 97 | size_t len; | |
| 98 | int oflag; | |
| 96 | gz_statep state; | |
| 97 | size_t len; | |
| 98 | int oflag; | |
| 99 | 99 | #ifdef O_CLOEXEC |
| 100 | ||
| 100 | int cloexec = 0; | |
| 101 | 101 | #endif |
| 102 | 102 | #ifdef O_EXCL |
| 103 | ||
| 103 | int exclusive = 0; | |
| 104 | 104 | #endif |
| 105 | 105 | |
| 106 | /* check input */ | |
| 107 | if (path == NULL) | |
| 108 | return NULL; | |
| 106 | /* check input */ | |
| 107 | if (path == NULL) | |
| 108 | return NULL; | |
| 109 | 109 | |
| 110 | /* allocate gzFile structure to return */ | |
| 111 | state = (gz_statep)malloc(sizeof(gz_state)); | |
| 112 | if (state == NULL) | |
| 113 | return NULL; | |
| 114 | state->size = 0; /* no buffers allocated yet */ | |
| 115 | state->want = GZBUFSIZE; /* requested buffer size */ | |
| 116 | state->msg = NULL; /* no error message yet */ | |
| 110 | /* allocate gzFile structure to return */ | |
| 111 | state = (gz_statep)malloc(sizeof(gz_state)); | |
| 112 | if (state == NULL) | |
| 113 | return NULL; | |
| 114 | state->size = 0; /* no buffers allocated yet */ | |
| 115 | state->want = GZBUFSIZE; /* requested buffer size */ | |
| 116 | state->msg = NULL; /* no error message yet */ | |
| 117 | 117 | |
| 118 | /* interpret mode */ | |
| 119 | state->mode = GZ_NONE; | |
| 120 | state->level = Z_DEFAULT_COMPRESSION; | |
| 121 | state->strategy = Z_DEFAULT_STRATEGY; | |
| 122 | state->direct = 0; | |
| 123 | while (*mode) { | |
| 124 | if (*mode >= '0' && *mode <= '9') | |
| 125 | state->level = *mode - '0'; | |
| 126 | else | |
| 127 | switch (*mode) { | |
| 128 | case 'r': | |
| 129 | state->mode = GZ_READ; | |
| 130 | break; | |
| 118 | /* interpret mode */ | |
| 119 | state->mode = GZ_NONE; | |
| 120 | state->level = Z_DEFAULT_COMPRESSION; | |
| 121 | state->strategy = Z_DEFAULT_STRATEGY; | |
| 122 | state->direct = 0; | |
| 123 | while (*mode) { | |
| 124 | if (*mode >= '0' && *mode <= '9') | |
| 125 | state->level = *mode - '0'; | |
| 126 | else | |
| 127 | switch (*mode) { | |
| 128 | case 'r': | |
| 129 | state->mode = GZ_READ; | |
| 130 | break; | |
| 131 | 131 | #ifndef NO_GZCOMPRESS |
| 132 | case 'w': | |
| 133 | state->mode = GZ_WRITE; | |
| 134 | break; | |
| 135 | case 'a': | |
| 136 | state->mode = GZ_APPEND; | |
| 137 | break; | |
| 132 | case 'w': | |
| 133 | state->mode = GZ_WRITE; | |
| 134 | break; | |
| 135 | case 'a': | |
| 136 | state->mode = GZ_APPEND; | |
| 137 | break; | |
| 138 | 138 | #endif |
| 139 | case '+': /* can't read and write at the same time */ | |
| 140 | free(state); | |
| 141 | return NULL; | |
| 142 | case 'b': /* ignore -- will request binary anyway */ | |
| 143 | break; | |
| 139 | case '+': /* can't read and write at the same time */ | |
| 140 | free(state); | |
| 141 | return NULL; | |
| 142 | case 'b': /* ignore -- will request binary anyway */ | |
| 143 | break; | |
| 144 | 144 | #ifdef O_CLOEXEC |
| 145 | case 'e': | |
| 146 | cloexec = 1; | |
| 147 | break; | |
| 145 | case 'e': | |
| 146 | cloexec = 1; | |
| 147 | break; | |
| 148 | 148 | #endif |
| 149 | 149 | #ifdef O_EXCL |
| 150 | case 'x': | |
| 151 | exclusive = 1; | |
| 152 | break; | |
| 150 | case 'x': | |
| 151 | exclusive = 1; | |
| 152 | break; | |
| 153 | 153 | #endif |
| 154 | case 'f': | |
| 155 | state->strategy = Z_FILTERED; | |
| 156 | break; | |
| 157 | case 'h': | |
| 158 | state->strategy = Z_HUFFMAN_ONLY; | |
| 159 | break; | |
| 160 | case 'R': | |
| 161 | state->strategy = Z_RLE; | |
| 162 | break; | |
| 163 | case 'F': | |
| 164 | state->strategy = Z_FIXED; | |
| 165 | break; | |
| 166 | case 'T': | |
| 167 | state->direct = 1; | |
| 168 | break; | |
| 169 | default: /* could consider as an error, but just ignore */ | |
| 170 | ; | |
| 171 | } | |
| 172 | mode++; | |
| 173 | } | |
| 154 | case 'f': | |
| 155 | state->strategy = Z_FILTERED; | |
| 156 | break; | |
| 157 | case 'h': | |
| 158 | state->strategy = Z_HUFFMAN_ONLY; | |
| 159 | break; | |
| 160 | case 'R': | |
| 161 | state->strategy = Z_RLE; | |
| 162 | break; | |
| 163 | case 'F': | |
| 164 | state->strategy = Z_FIXED; | |
| 165 | break; | |
| 166 | case 'T': | |
| 167 | state->direct = 1; | |
| 168 | break; | |
| 169 | default: /* could consider as an error, but just ignore */ | |
| 170 | ; | |
| 171 | } | |
| 172 | mode++; | |
| 173 | } | |
| 174 | 174 | |
| 175 | /* must provide an "r", "w", or "a" */ | |
| 176 | if (state->mode == GZ_NONE) { | |
| 177 | free(state); | |
| 178 | return NULL; | |
| 179 | } | |
| 175 | /* must provide an "r", "w", or "a" */ | |
| 176 | if (state->mode == GZ_NONE) { | |
| 177 | free(state); | |
| 178 | return NULL; | |
| 179 | } | |
| 180 | 180 | |
| 181 | /* can't force transparent read */ | |
| 182 | if (state->mode == GZ_READ) { | |
| 183 | if (state->direct) { | |
| 184 | free(state); | |
| 185 | return NULL; | |
| 186 | } | |
| 187 | state->direct = 1; /* for empty file */ | |
| 188 | } | |
| 181 | /* can't force transparent read */ | |
| 182 | if (state->mode == GZ_READ) { | |
| 183 | if (state->direct) { | |
| 184 | free(state); | |
| 185 | return NULL; | |
| 186 | } | |
| 187 | state->direct = 1; /* for empty file */ | |
| 188 | } | |
| 189 | 189 | |
| 190 | ||
| 190 | /* save the path name for error messages */ | |
| 191 | 191 | #ifdef _WIN32 |
| 192 | if (fd == -2) { | |
| 193 | len = wcstombs(NULL, path, 0); | |
| 194 | if (len == (size_t)-1) | |
| 195 | len = 0; | |
| 196 | } | |
| 197 | else | |
| 192 | if (fd == -2) { | |
| 193 | len = wcstombs(NULL, path, 0); | |
| 194 | if (len == (size_t)-1) | |
| 195 | len = 0; | |
| 196 | } | |
| 197 | else | |
| 198 | 198 | #endif |
| 199 | len = strlen((const char *)path); | |
| 200 | state->path = (char *)malloc(len + 1); | |
| 201 | if (state->path == NULL) { | |
| 202 | free(state); | |
| 203 | return NULL; | |
| 204 | } | |
| 199 | len = strlen((const char *)path); | |
| 200 | state->path = (char *)malloc(len + 1); | |
| 201 | if (state->path == NULL) { | |
| 202 | free(state); | |
| 203 | return NULL; | |
| 204 | } | |
| 205 | 205 | #ifdef _WIN32 |
| 206 | if (fd == -2) | |
| 207 | if (len) | |
| 208 | wcstombs(state->path, path, len + 1); | |
| 209 | else | |
| 210 | *(state->path) = 0; | |
| 211 | else | |
| 206 | if (fd == -2) | |
| 207 | if (len) | |
| 208 | wcstombs(state->path, path, len + 1); | |
| 209 | else | |
| 210 | *(state->path) = 0; | |
| 211 | else | |
| 212 | 212 | #endif |
| 213 | 213 | #if !defined(NO_snprintf) && !defined(NO_vsnprintf) |
| 214 | ||
| 214 | snprintf(state->path, len + 1, "%s", (const char *)path); | |
| 215 | 215 | #else |
| 216 | ||
| 216 | strcpy(state->path, path); | |
| 217 | 217 | #endif |
| 218 | 218 | |
| 219 | /* compute the flags for open() */ | |
| 220 | oflag = | |
| 219 | /* compute the flags for open() */ | |
| 220 | oflag = | |
| 221 | 221 | #ifdef O_LARGEFILE |
| 222 | ||
| 222 | O_LARGEFILE | | |
| 223 | 223 | #endif |
| 224 | 224 | #ifdef O_BINARY |
| 225 | ||
| 225 | O_BINARY | | |
| 226 | 226 | #endif |
| 227 | 227 | #ifdef O_CLOEXEC |
| 228 | ||
| 228 | (cloexec ? O_CLOEXEC : 0) | | |
| 229 | 229 | #endif |
| 230 | (state->mode == GZ_READ ? | |
| 231 | O_RDONLY : | |
| 232 | (O_WRONLY | O_CREAT | | |
| 230 | (state->mode == GZ_READ ? | |
| 231 | O_RDONLY : | |
| 232 | (O_WRONLY | O_CREAT | | |
| 233 | 233 | #ifdef O_EXCL |
| 234 | ||
| 234 | (exclusive ? O_EXCL : 0) | | |
| 235 | 235 | #endif |
| 236 | (state->mode == GZ_WRITE ? | |
| 237 | O_TRUNC : | |
| 238 | O_APPEND))); | |
| 236 | (state->mode == GZ_WRITE ? | |
| 237 | O_TRUNC : | |
| 238 | O_APPEND))); | |
| 239 | 239 | |
| 240 | /* open the file with the appropriate flags (or just use fd) */ | |
| 241 | state->fd = fd > -1 ? fd : ( | |
| 240 | /* open the file with the appropriate flags (or just use fd) */ | |
| 241 | state->fd = fd > -1 ? fd : ( | |
| 242 | 242 | #ifdef _WIN32 |
| 243 | ||
| 243 | fd == -2 ? _wopen(path, oflag, 0666) : | |
| 244 | 244 | #endif |
| 245 | open((const char *)path, oflag, 0666)); | |
| 246 | if (state->fd == -1) { | |
| 247 | free(state->path); | |
| 248 | free(state); | |
| 249 | return NULL; | |
| 250 | } | |
| 251 | if (state->mode == GZ_APPEND) | |
| 252 | state->mode = GZ_WRITE; /* simplify later checks */ | |
| 245 | open((const char *)path, oflag, 0666)); | |
| 246 | if (state->fd == -1) { | |
| 247 | free(state->path); | |
| 248 | free(state); | |
| 249 | return NULL; | |
| 250 | } | |
| 251 | if (state->mode == GZ_APPEND) | |
| 252 | state->mode = GZ_WRITE; /* simplify later checks */ | |
| 253 | 253 | |
| 254 | /* save the current position for rewinding (only if reading) */ | |
| 255 | if (state->mode == GZ_READ) { | |
| 256 | state->start = LSEEK(state->fd, 0, SEEK_CUR); | |
| 257 | if (state->start == -1) state->start = 0; | |
| 258 | } | |
| 254 | /* save the current position for rewinding (only if reading) */ | |
| 255 | if (state->mode == GZ_READ) { | |
| 256 | state->start = LSEEK(state->fd, 0, SEEK_CUR); | |
| 257 | if (state->start == -1) state->start = 0; | |
| 258 | } | |
| 259 | 259 | |
| 260 | /* initialize stream */ | |
| 261 | gz_reset(state); | |
| 260 | /* initialize stream */ | |
| 261 | gz_reset(state); | |
| 262 | 262 | |
| 263 | /* return stream */ | |
| 264 | return (gzFile)state; | |
| 263 | /* return stream */ | |
| 264 | return (gzFile)state; | |
| 265 | 265 | } |
| 266 | 266 | |
| 267 | 267 | /* -- see zlib.h -- */ |
| 268 | 268 | gzFile ZEXPORT gzopen(path, mode) |
| 269 | const char *path; | |
| 270 | const char *mode; | |
| 269 | const char *path; | |
| 270 | const char *mode; | |
| 271 | 271 | { |
| 272 | ||
| 272 | return gz_open(path, -1, mode); | |
| 273 | 273 | } |
| 274 | 274 | |
| 275 | 275 | /* -- see zlib.h -- */ |
| 276 | 276 | gzFile ZEXPORT gzopen64(path, mode) |
| 277 | const char *path; | |
| 278 | const char *mode; | |
| 277 | const char *path; | |
| 278 | const char *mode; | |
| 279 | 279 | { |
| 280 | ||
| 280 | return gz_open(path, -1, mode); | |
| 281 | 281 | } |
| 282 | 282 | |
| 283 | 283 | /* -- see zlib.h -- */ |
| 284 | 284 | gzFile ZEXPORT gzdopen(fd, mode) |
| 285 | int fd; | |
| 286 | const char *mode; | |
| 285 | int fd; | |
| 286 | const char *mode; | |
| 287 | 287 | { |
| 288 | char *path; /* identifier for error messages */ | |
| 289 | gzFile gz; | |
| 288 | char *path; /* identifier for error messages */ | |
| 289 | gzFile gz; | |
| 290 | 290 | |
| 291 | if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) | |
| 292 | return NULL; | |
| 291 | if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) | |
| 292 | return NULL; | |
| 293 | 293 | #if !defined(NO_snprintf) && !defined(NO_vsnprintf) |
| 294 | ||
| 294 | snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); /* for debugging */ | |
| 295 | 295 | #else |
| 296 | ||
| 296 | sprintf(path, "<fd:%d>", fd); /* for debugging */ | |
| 297 | 297 | #endif |
| 298 | gz = gz_open(path, fd, mode); | |
| 299 | free(path); | |
| 300 | return gz; | |
| 298 | gz = gz_open(path, fd, mode); | |
| 299 | free(path); | |
| 300 | return gz; | |
| 301 | 301 | } |
| 302 | 302 | |
| 303 | 303 | /* -- see zlib.h -- */ |
| 304 | 304 | #ifdef _WIN32 |
| 305 | 305 | gzFile ZEXPORT gzopen_w(path, mode) |
| 306 | const wchar_t *path; | |
| 307 | const char *mode; | |
| 306 | const wchar_t *path; | |
| 307 | const char *mode; | |
| 308 | 308 | { |
| 309 | ||
| 309 | return gz_open(path, -2, mode); | |
| 310 | 310 | } |
| 311 | 311 | #endif |
| 312 | 312 | |
| 313 | 313 | /* -- see zlib.h -- */ |
| 314 | 314 | int ZEXPORT gzbuffer(file, size) |
| 315 | gzFile file; | |
| 316 | unsigned size; | |
| 315 | gzFile file; | |
| 316 | unsigned size; | |
| 317 | 317 | { |
| 318 | ||
| 318 | gz_statep state; | |
| 319 | 319 | |
| 320 | /* get internal structure and check integrity */ | |
| 321 | if (file == NULL) | |
| 322 | return -1; | |
| 323 | state = (gz_statep)file; | |
| 324 | if (state->mode != GZ_READ && state->mode != GZ_WRITE) | |
| 325 | return -1; | |
| 320 | /* get internal structure and check integrity */ | |
| 321 | if (file == NULL) | |
| 322 | return -1; | |
| 323 | state = (gz_statep)file; | |
| 324 | if (state->mode != GZ_READ && state->mode != GZ_WRITE) | |
| 325 | return -1; | |
| 326 | 326 | |
| 327 | /* make sure we haven't already allocated memory */ | |
| 328 | if (state->size != 0) | |
| 329 | return -1; | |
| 327 | /* make sure we haven't already allocated memory */ | |
| 328 | if (state->size != 0) | |
| 329 | return -1; | |
| 330 | 330 | |
| 331 | /* check and set requested size */ | |
| 332 | if (size < 2) | |
| 333 | size = 2; /* need two bytes to check magic header */ | |
| 334 | state->want = size; | |
| 335 | return 0; | |
| 331 | /* check and set requested size */ | |
| 332 | if (size < 2) | |
| 333 | size = 2; /* need two bytes to check magic header */ | |
| 334 | state->want = size; | |
| 335 | return 0; | |
| 336 | 336 | } |
| 337 | 337 | |
| 338 | 338 | /* -- see zlib.h -- */ |
| 339 | 339 | int ZEXPORT gzrewind(file) |
| 340 | ||
| 340 | gzFile file; | |
| 341 | 341 | { |
| 342 | ||
| 342 | gz_statep state; | |
| 343 | 343 | |
| 344 | /* get internal structure */ | |
| 345 | if (file == NULL) | |
| 346 | return -1; | |
| 347 | state = (gz_statep)file; | |
| 344 | /* get internal structure */ | |
| 345 | if (file == NULL) | |
| 346 | return -1; | |
| 347 | state = (gz_statep)file; | |
| 348 | 348 | |
| 349 | /* check that we're reading and that there's no error */ | |
| 350 | if (state->mode != GZ_READ || | |
| 351 | (state->err != Z_OK && state->err != Z_BUF_ERROR)) | |
| 352 | return -1; | |
| 349 | /* check that we're reading and that there's no error */ | |
| 350 | if (state->mode != GZ_READ || | |
| 351 | (state->err != Z_OK && state->err != Z_BUF_ERROR)) | |
| 352 | return -1; | |
| 353 | 353 | |
| 354 | /* back up and start over */ | |
| 355 | if (LSEEK(state->fd, state->start, SEEK_SET) == -1) | |
| 356 | return -1; | |
| 357 | gz_reset(state); | |
| 358 | return 0; | |
| 354 | /* back up and start over */ | |
| 355 | if (LSEEK(state->fd, state->start, SEEK_SET) == -1) | |
| 356 | return -1; | |
| 357 | gz_reset(state); | |
| 358 | return 0; | |
| 359 | 359 | } |
| 360 | 360 | |
| 361 | 361 | /* -- see zlib.h -- */ |
| 362 | 362 | z_off64_t ZEXPORT gzseek64(file, offset, whence) |
| 363 | gzFile file; | |
| 364 | z_off64_t offset; | |
| 365 | int whence; | |
| 363 | gzFile file; | |
| 364 | z_off64_t offset; | |
| 365 | int whence; | |
| 366 | 366 | { |
| 367 | unsigned n; | |
| 368 | z_off64_t ret; | |
| 369 | gz_statep state; | |
| 367 | unsigned n; | |
| 368 | z_off64_t ret; | |
| 369 | gz_statep state; | |
| 370 | 370 | |
| 371 | /* get internal structure and check integrity */ | |
| 372 | if (file == NULL) | |
| 373 | return -1; | |
| 374 | state = (gz_statep)file; | |
| 375 | if (state->mode != GZ_READ && state->mode != GZ_WRITE) | |
| 376 | return -1; | |
| 371 | /* get internal structure and check integrity */ | |
| 372 | if (file == NULL) | |
| 373 | return -1; | |
| 374 | state = (gz_statep)file; | |
| 375 | if (state->mode != GZ_READ && state->mode != GZ_WRITE) | |
| 376 | return -1; | |
| 377 | 377 | |
| 378 | /* check that there's no error */ | |
| 379 | if (state->err != Z_OK && state->err != Z_BUF_ERROR) | |
| 380 | return -1; | |
| 378 | /* check that there's no error */ | |
| 379 | if (state->err != Z_OK && state->err != Z_BUF_ERROR) | |
| 380 | return -1; | |
| 381 | 381 | |
| 382 | /* can only seek from start or relative to current position */ | |
| 383 | if (whence != SEEK_SET && whence != SEEK_CUR) | |
| 384 | return -1; | |
| 382 | /* can only seek from start or relative to current position */ | |
| 383 | if (whence != SEEK_SET && whence != SEEK_CUR) | |
| 384 | return -1; | |
| 385 | 385 | |
| 386 | /* normalize offset to a SEEK_CUR specification */ | |
| 387 | if (whence == SEEK_SET) | |
| 388 | offset -= state->x.pos; | |
| 389 | else if (state->seek) | |
| 390 | offset += state->skip; | |
| 391 | state->seek = 0; | |
| 386 | /* normalize offset to a SEEK_CUR specification */ | |
| 387 | if (whence == SEEK_SET) | |
| 388 | offset -= state->x.pos; | |
| 389 | else if (state->seek) | |
| 390 | offset += state->skip; | |
| 391 | state->seek = 0; | |
| 392 | 392 | |
| 393 | /* if within raw area while reading, just go there */ | |
| 394 | if (state->mode == GZ_READ && state->how == COPY && | |
| 395 | state->x.pos + offset >= 0) { | |
| 396 | ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR); | |
| 397 | if (ret == -1) | |
| 398 | return -1; | |
| 399 | state->x.have = 0; | |
| 400 | state->eof = 0; | |
| 401 | state->past = 0; | |
| 402 | state->seek = 0; | |
| 403 | gz_error(state, Z_OK, NULL); | |
| 404 | state->strm.avail_in = 0; | |
| 405 | state->x.pos += offset; | |
| 406 | return state->x.pos; | |
| 407 | } | |
| 393 | /* if within raw area while reading, just go there */ | |
| 394 | if (state->mode == GZ_READ && state->how == COPY && | |
| 395 | state->x.pos + offset >= 0) { | |
| 396 | ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR); | |
| 397 | if (ret == -1) | |
| 398 | return -1; | |
| 399 | state->x.have = 0; | |
| 400 | state->eof = 0; | |
| 401 | state->past = 0; | |
| 402 | state->seek = 0; | |
| 403 | gz_error(state, Z_OK, NULL); | |
| 404 | state->strm.avail_in = 0; | |
| 405 | state->x.pos += offset; | |
| 406 | return state->x.pos; | |
| 407 | } | |
| 408 | 408 | |
| 409 | /* calculate skip amount, rewinding if needed for back seek when reading */ | |
| 410 | if (offset < 0) { | |
| 411 | if (state->mode != GZ_READ) /* writing -- can't go backwards */ | |
| 412 | return -1; | |
| 413 | offset += state->x.pos; | |
| 414 | if (offset < 0) /* before start of file! */ | |
| 415 | return -1; | |
| 416 | if (gzrewind(file) == -1) /* rewind, then skip to offset */ | |
| 417 | return -1; | |
| 418 | } | |
| 409 | /* calculate skip amount, rewinding if needed for back seek when reading */ | |
| 410 | if (offset < 0) { | |
| 411 | if (state->mode != GZ_READ) /* writing -- can't go backwards */ | |
| 412 | return -1; | |
| 413 | offset += state->x.pos; | |
| 414 | if (offset < 0) /* before start of file! */ | |
| 415 | return -1; | |
| 416 | if (gzrewind(file) == -1) /* rewind, then skip to offset */ | |
| 417 | return -1; | |
| 418 | } | |
| 419 | 419 | |
| 420 | /* if reading, skip what's in output buffer (one less gzgetc() check) */ | |
| 421 | if (state->mode == GZ_READ) { | |
| 422 | n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? | |
| 423 | (unsigned)offset : state->x.have; | |
| 424 | state->x.have -= n; | |
| 425 | state->x.next += n; | |
| 426 | state->x.pos += n; | |
| 427 | offset -= n; | |
| 428 | } | |
| 420 | /* if reading, skip what's in output buffer (one less gzgetc() check) */ | |
| 421 | if (state->mode == GZ_READ) { | |
| 422 | n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? | |
| 423 | (unsigned)offset : state->x.have; | |
| 424 | state->x.have -= n; | |
| 425 | state->x.next += n; | |
| 426 | state->x.pos += n; | |
| 427 | offset -= n; | |
| 428 | } | |
| 429 | 429 | |
| 430 | /* request skip (if not zero) */ | |
| 431 | if (offset) { | |
| 432 | state->seek = 1; | |
| 433 | state->skip = offset; | |
| 434 | } | |
| 435 | return state->x.pos + offset; | |
| 430 | /* request skip (if not zero) */ | |
| 431 | if (offset) { | |
| 432 | state->seek = 1; | |
| 433 | state->skip = offset; | |
| 434 | } | |
| 435 | return state->x.pos + offset; | |
| 436 | 436 | } |
| 437 | 437 | |
| 438 | 438 | /* -- see zlib.h -- */ |
| 439 | 439 | z_off_t ZEXPORT gzseek(file, offset, whence) |
| 440 | gzFile file; | |
| 441 | z_off_t offset; | |
| 442 | int whence; | |
| 440 | gzFile file; | |
| 441 | z_off_t offset; | |
| 442 | int whence; | |
| 443 | 443 | { |
| 444 | ||
| 444 | z_off64_t ret; | |
| 445 | 445 | |
| 446 | ret = gzseek64(file, (z_off64_t)offset, whence); | |
| 447 | return ret == (z_off_t)ret ? (z_off_t)ret : -1; | |
| 446 | ret = gzseek64(file, (z_off64_t)offset, whence); | |
| 447 | return ret == (z_off_t)ret ? (z_off_t)ret : -1; | |
| 448 | 448 | } |
| 449 | 449 | |
| 450 | 450 | /* -- see zlib.h -- */ |
| 451 | 451 | z_off64_t ZEXPORT gztell64(file) |
| 452 | ||
| 452 | gzFile file; | |
| 453 | 453 | { |
| 454 | ||
| 454 | gz_statep state; | |
| 455 | 455 | |
| 456 | /* get internal structure and check integrity */ | |
| 457 | if (file == NULL) | |
| 458 | return -1; | |
| 459 | state = (gz_statep)file; | |
| 460 | if (state->mode != GZ_READ && state->mode != GZ_WRITE) | |
| 461 | return -1; | |
| 456 | /* get internal structure and check integrity */ | |
| 457 | if (file == NULL) | |
| 458 | return -1; | |
| 459 | state = (gz_statep)file; | |
| 460 | if (state->mode != GZ_READ && state->mode != GZ_WRITE) | |
| 461 | return -1; | |
| 462 | 462 | |
| 463 | /* return position */ | |
| 464 | return state->x.pos + (state->seek ? state->skip : 0); | |
| 463 | /* return position */ | |
| 464 | return state->x.pos + (state->seek ? state->skip : 0); | |
| 465 | 465 | } |
| 466 | 466 | |
| 467 | 467 | /* -- see zlib.h -- */ |
| 468 | 468 | z_off_t ZEXPORT gztell(file) |
| 469 | ||
| 469 | gzFile file; | |
| 470 | 470 | { |
| 471 | ||
| 471 | z_off64_t ret; | |
| 472 | 472 | |
| 473 | ret = gztell64(file); | |
| 474 | return ret == (z_off_t)ret ? (z_off_t)ret : -1; | |
| 473 | ret = gztell64(file); | |
| 474 | return ret == (z_off_t)ret ? (z_off_t)ret : -1; | |
| 475 | 475 | } |
| 476 | 476 | |
| 477 | 477 | /* -- see zlib.h -- */ |
| 478 | 478 | z_off64_t ZEXPORT gzoffset64(file) |
| 479 | ||
| 479 | gzFile file; | |
| 480 | 480 | { |
| 481 | z_off64_t offset; | |
| 482 | gz_statep state; | |
| 481 | z_off64_t offset; | |
| 482 | gz_statep state; | |
| 483 | 483 | |
| 484 | /* get internal structure and check integrity */ | |
| 485 | if (file == NULL) | |
| 486 | return -1; | |
| 487 | state = (gz_statep)file; | |
| 488 | if (state->mode != GZ_READ && state->mode != GZ_WRITE) | |
| 489 | return -1; | |
| 484 | /* get internal structure and check integrity */ | |
| 485 | if (file == NULL) | |
| 486 | return -1; | |
| 487 | state = (gz_statep)file; | |
| 488 | if (state->mode != GZ_READ && state->mode != GZ_WRITE) | |
| 489 | return -1; | |
| 490 | 490 | |
| 491 | /* compute and return effective offset in file */ | |
| 492 | offset = LSEEK(state->fd, 0, SEEK_CUR); | |
| 493 | if (offset == -1) | |
| 494 | return -1; | |
| 495 | if (state->mode == GZ_READ) /* reading */ | |
| 496 | offset -= state->strm.avail_in; /* don't count buffered input */ | |
| 497 | return offset; | |
| 491 | /* compute and return effective offset in file */ | |
| 492 | offset = LSEEK(state->fd, 0, SEEK_CUR); | |
| 493 | if (offset == -1) | |
| 494 | return -1; | |
| 495 | if (state->mode == GZ_READ) /* reading */ | |
| 496 | offset -= state->strm.avail_in; /* don't count buffered input */ | |
| 497 | return offset; | |
| 498 | 498 | } |
| 499 | 499 | |
| 500 | 500 | /* -- see zlib.h -- */ |
| 501 | 501 | z_off_t ZEXPORT gzoffset(file) |
| 502 | ||
| 502 | gzFile file; | |
| 503 | 503 | { |
| 504 | ||
| 504 | z_off64_t ret; | |
| 505 | 505 | |
| 506 | ret = gzoffset64(file); | |
| 507 | return ret == (z_off_t)ret ? (z_off_t)ret : -1; | |
| 506 | ret = gzoffset64(file); | |
| 507 | return ret == (z_off_t)ret ? (z_off_t)ret : -1; | |
| 508 | 508 | } |
| 509 | 509 | |
| 510 | 510 | /* -- see zlib.h -- */ |
| 511 | 511 | int ZEXPORT gzeof(file) |
| 512 | ||
| 512 | gzFile file; | |
| 513 | 513 | { |
| 514 | ||
| 514 | gz_statep state; | |
| 515 | 515 | |
| 516 | /* get internal structure and check integrity */ | |
| 517 | if (file == NULL) | |
| 518 | return 0; | |
| 519 | state = (gz_statep)file; | |
| 520 | if (state->mode != GZ_READ && state->mode != GZ_WRITE) | |
| 521 | return 0; | |
| 516 | /* get internal structure and check integrity */ | |
| 517 | if (file == NULL) | |
| 518 | return 0; | |
| 519 | state = (gz_statep)file; | |
| 520 | if (state->mode != GZ_READ && state->mode != GZ_WRITE) | |
| 521 | return 0; | |
| 522 | 522 | |
| 523 | /* return end-of-file state */ | |
| 524 | return state->mode == GZ_READ ? state->past : 0; | |
| 523 | /* return end-of-file state */ | |
| 524 | return state->mode == GZ_READ ? state->past : 0; | |
| 525 | 525 | } |
| 526 | 526 | |
| 527 | 527 | /* -- see zlib.h -- */ |
| 528 | 528 | const char * ZEXPORT gzerror(file, errnum) |
| 529 | gzFile file; | |
| 530 | int *errnum; | |
| 529 | gzFile file; | |
| 530 | int *errnum; | |
| 531 | 531 | { |
| 532 | ||
| 532 | gz_statep state; | |
| 533 | 533 | |
| 534 | /* get internal structure and check integrity */ | |
| 535 | if (file == NULL) | |
| 536 | return NULL; | |
| 537 | state = (gz_statep)file; | |
| 538 | if (state->mode != GZ_READ && state->mode != GZ_WRITE) | |
| 539 | return NULL; | |
| 534 | /* get internal structure and check integrity */ | |
| 535 | if (file == NULL) | |
| 536 | return NULL; | |
| 537 | state = (gz_statep)file; | |
| 538 | if (state->mode != GZ_READ && state->mode != GZ_WRITE) | |
| 539 | return NULL; | |
| 540 | 540 | |
| 541 | /* return error information */ | |
| 542 | if (errnum != NULL) | |
| 543 | *errnum = state->err; | |
| 544 | return state->err == Z_MEM_ERROR ? "out of memory" : | |
| 545 | (state->msg == NULL ? "" : state->msg); | |
| 541 | /* return error information */ | |
| 542 | if (errnum != NULL) | |
| 543 | *errnum = state->err; | |
| 544 | return state->err == Z_MEM_ERROR ? "out of memory" : | |
| 545 | (state->msg == NULL ? "" : state->msg); | |
| 546 | 546 | } |
| 547 | 547 | |
| 548 | 548 | /* -- see zlib.h -- */ |
| 549 | 549 | void ZEXPORT gzclearerr(file) |
| 550 | ||
| 550 | gzFile file; | |
| 551 | 551 | { |
| 552 | ||
| 552 | gz_statep state; | |
| 553 | 553 | |
| 554 | /* get internal structure and check integrity */ | |
| 555 | if (file == NULL) | |
| 556 | return; | |
| 557 | state = (gz_statep)file; | |
| 558 | if (state->mode != GZ_READ && state->mode != GZ_WRITE) | |
| 559 | return; | |
| 554 | /* get internal structure and check integrity */ | |
| 555 | if (file == NULL) | |
| 556 | return; | |
| 557 | state = (gz_statep)file; | |
| 558 | if (state->mode != GZ_READ && state->mode != GZ_WRITE) | |
| 559 | return; | |
| 560 | 560 | |
| 561 | /* clear error and end-of-file */ | |
| 562 | if (state->mode == GZ_READ) { | |
| 563 | state->eof = 0; | |
| 564 | state->past = 0; | |
| 565 | } | |
| 566 | gz_error(state, Z_OK, NULL); | |
| 561 | /* clear error and end-of-file */ | |
| 562 | if (state->mode == GZ_READ) { | |
| 563 | state->eof = 0; | |
| 564 | state->past = 0; | |
| 565 | } | |
| 566 | gz_error(state, Z_OK, NULL); | |
| 567 | 567 | } |
| 568 | 568 | |
| 569 | 569 | /* Create an error message in allocated memory and set state->err and |
| r25360 | r25361 | |
| 573 | 573 | allocation failure constructing the error message, then convert the error to |
| 574 | 574 | out of memory. */ |
| 575 | 575 | void ZLIB_INTERNAL gz_error(state, err, msg) |
| 576 | gz_statep state; | |
| 577 | int err; | |
| 578 | const char *msg; | |
| 576 | gz_statep state; | |
| 577 | int err; | |
| 578 | const char *msg; | |
| 579 | 579 | { |
| 580 | /* free previously allocated message and clear */ | |
| 581 | if (state->msg != NULL) { | |
| 582 | if (state->err != Z_MEM_ERROR) | |
| 583 | free(state->msg); | |
| 584 | state->msg = NULL; | |
| 585 | } | |
| 580 | /* free previously allocated message and clear */ | |
| 581 | if (state->msg != NULL) { | |
| 582 | if (state->err != Z_MEM_ERROR) | |
| 583 | free(state->msg); | |
| 584 | state->msg = NULL; | |
| 585 | } | |
| 586 | 586 | |
| 587 | /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */ | |
| 588 | if (err != Z_OK && err != Z_BUF_ERROR) | |
| 589 | state->x.have = 0; | |
| 587 | /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */ | |
| 588 | if (err != Z_OK && err != Z_BUF_ERROR) | |
| 589 | state->x.have = 0; | |
| 590 | 590 | |
| 591 | /* set error code, and if no message, then done */ | |
| 592 | state->err = err; | |
| 593 | if (msg == NULL) | |
| 594 | return; | |
| 591 | /* set error code, and if no message, then done */ | |
| 592 | state->err = err; | |
| 593 | if (msg == NULL) | |
| 594 | return; | |
| 595 | 595 | |
| 596 | /* for an out of memory error, return literal string when requested */ | |
| 597 | if (err == Z_MEM_ERROR) | |
| 598 | return; | |
| 596 | /* for an out of memory error, return literal string when requested */ | |
| 597 | if (err == Z_MEM_ERROR) | |
| 598 | return; | |
| 599 | 599 | |
| 600 | /* construct error message with path */ | |
| 601 | if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == | |
| 602 | NULL) { | |
| 603 | state->err = Z_MEM_ERROR; | |
| 604 | return; | |
| 605 | } | |
| 600 | /* construct error message with path */ | |
| 601 | if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == | |
| 602 | NULL) { | |
| 603 | state->err = Z_MEM_ERROR; | |
| 604 | return; | |
| 605 | } | |
| 606 | 606 | #if !defined(NO_snprintf) && !defined(NO_vsnprintf) |
| 607 | snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, | |
| 608 | "%s%s%s", state->path, ": ", msg); | |
| 607 | snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, | |
| 608 | "%s%s%s", state->path, ": ", msg); | |
| 609 | 609 | #else |
| 610 | strcpy(state->msg, state->path); | |
| 611 | strcat(state->msg, ": "); | |
| 612 | strcat(state->msg, msg); | |
| 610 | strcpy(state->msg, state->path); | |
| 611 | strcat(state->msg, ": "); | |
| 612 | strcat(state->msg, msg); | |
| 613 | 613 | #endif |
| 614 | ||
| 614 | return; | |
| 615 | 615 | } |
| 616 | 616 | |
| 617 | 617 | #ifndef INT_MAX |
| r25360 | r25361 | |
| 621 | 621 | otherwise we could just use ((unsigned)-1) >> 1 */ |
| 622 | 622 | unsigned ZLIB_INTERNAL gz_intmax() |
| 623 | 623 | { |
| 624 | ||
| 624 | unsigned p, q; | |
| 625 | 625 | |
| 626 | p = 1; | |
| 627 | do { | |
| 628 | q = p; | |
| 629 | p <<= 1; | |
| 630 | p++; | |
| 631 | } while (p > q); | |
| 632 | return q >> 1; | |
| 626 | p = 1; | |
| 627 | do { | |
| 628 | q = p; | |
| 629 | p <<= 1; | |
| 630 | p++; | |
| 631 | } while (p > q); | |
| 632 | return q >> 1; | |
| 633 | 633 | } |
| 634 | 634 | #endif |
| r25360 | r25361 | |
|---|---|---|
| 63 | 63 | |
| 64 | 64 | /* Data structure describing a single value and its code string. */ |
| 65 | 65 | typedef struct ct_data_s { |
| 66 | union { | |
| 67 | ush freq; /* frequency count */ | |
| 68 | ush code; /* bit string */ | |
| 69 | } fc; | |
| 70 | union { | |
| 71 | ush dad; /* father node in Huffman tree */ | |
| 72 | ush len; /* length of bit string */ | |
| 73 | } dl; | |
| 66 | union { | |
| 67 | ush freq; /* frequency count */ | |
| 68 | ush code; /* bit string */ | |
| 69 | } fc; | |
| 70 | union { | |
| 71 | ush dad; /* father node in Huffman tree */ | |
| 72 | ush len; /* length of bit string */ | |
| 73 | } dl; | |
| 74 | 74 | } FAR ct_data; |
| 75 | 75 | |
| 76 | 76 | #define Freq fc.freq |
| r25360 | r25361 | |
| 81 | 81 | typedef struct static_tree_desc_s static_tree_desc; |
| 82 | 82 | |
| 83 | 83 | typedef struct tree_desc_s { |
| 84 | ct_data *dyn_tree; /* the dynamic tree */ | |
| 85 | int max_code; /* largest code with non zero frequency */ | |
| 86 | static_tree_desc *stat_desc; /* the corresponding static tree */ | |
| 84 | ct_data *dyn_tree; /* the dynamic tree */ | |
| 85 | int max_code; /* largest code with non zero frequency */ | |
| 86 | static_tree_desc *stat_desc; /* the corresponding static tree */ | |
| 87 | 87 | } FAR tree_desc; |
| 88 | 88 | |
| 89 | 89 | typedef ush Pos; |
| r25360 | r25361 | |
| 95 | 95 | */ |
| 96 | 96 | |
| 97 | 97 | typedef struct internal_state { |
| 98 | z_streamp strm; /* pointer back to this zlib stream */ | |
| 99 | int status; /* as the name implies */ | |
| 100 | Bytef *pending_buf; /* output still pending */ | |
| 101 | ulg pending_buf_size; /* size of pending_buf */ | |
| 102 | Bytef *pending_out; /* next pending byte to output to the stream */ | |
| 103 | uInt pending; /* nb of bytes in the pending buffer */ | |
| 104 | int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ | |
| 105 | gz_headerp gzhead; /* gzip header information to write */ | |
| 106 | uInt gzindex; /* where in extra, name, or comment */ | |
| 107 | Byte method; /* can only be DEFLATED */ | |
| 108 | int last_flush; /* value of flush param for previous deflate call */ | |
| 98 | z_streamp strm; /* pointer back to this zlib stream */ | |
| 99 | int status; /* as the name implies */ | |
| 100 | Bytef *pending_buf; /* output still pending */ | |
| 101 | ulg pending_buf_size; /* size of pending_buf */ | |
| 102 | Bytef *pending_out; /* next pending byte to output to the stream */ | |
| 103 | uInt pending; /* nb of bytes in the pending buffer */ | |
| 104 | int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ | |
| 105 | gz_headerp gzhead; /* gzip header information to write */ | |
| 106 | uInt gzindex; /* where in extra, name, or comment */ | |
| 107 | Byte method; /* can only be DEFLATED */ | |
| 108 | int last_flush; /* value of flush param for previous deflate call */ | |
| 109 | 109 | |
| 110 | ||
| 110 | /* used by deflate.c: */ | |
| 111 | 111 | |
| 112 | uInt w_size; /* LZ77 window size (32K by default) */ | |
| 113 | uInt w_bits; /* log2(w_size) (8..16) */ | |
| 114 | uInt w_mask; /* w_size - 1 */ | |
| 112 | uInt w_size; /* LZ77 window size (32K by default) */ | |
| 113 | uInt w_bits; /* log2(w_size) (8..16) */ | |
| 114 | uInt w_mask; /* w_size - 1 */ | |
| 115 | 115 | |
| 116 | Bytef *window; | |
| 117 | /* Sliding window. Input bytes are read into the second half of the window, | |
| 118 | * and move to the first half later to keep a dictionary of at least wSize | |
| 119 | * bytes. With this organization, matches are limited to a distance of | |
| 120 | * wSize-MAX_MATCH bytes, but this ensures that IO is always | |
| 121 | * performed with a length multiple of the block size. Also, it limits | |
| 122 | * the window size to 64K, which is quite useful on MSDOS. | |
| 123 | * To do: use the user input buffer as sliding window. | |
| 124 | */ | |
| 116 | Bytef *window; | |
| 117 | /* Sliding window. Input bytes are read into the second half of the window, | |
| 118 | * and move to the first half later to keep a dictionary of at least wSize | |
| 119 | * bytes. With this organization, matches are limited to a distance of | |
| 120 | * wSize-MAX_MATCH bytes, but this ensures that IO is always | |
| 121 | * performed with a length multiple of the block size. Also, it limits | |
| 122 | * the window size to 64K, which is quite useful on MSDOS. | |
| 123 | * To do: use the user input buffer as sliding window. | |
| 124 | */ | |
| 125 | 125 | |
| 126 | ulg window_size; | |
| 127 | /* Actual size of window: 2*wSize, except when the user input buffer | |
| 128 | * is directly used as sliding window. | |
| 129 | */ | |
| 126 | ulg window_size; | |
| 127 | /* Actual size of window: 2*wSize, except when the user input buffer | |
| 128 | * is directly used as sliding window. | |
| 129 | */ | |
| 130 | 130 | |
| 131 | Posf *prev; | |
| 132 | /* Link to older string with same hash index. To limit the size of this | |
| 133 | * array to 64K, this link is maintained only for the last 32K strings. | |
| 134 | * An index in this array is thus a window index modulo 32K. | |
| 135 | */ | |
| 131 | Posf *prev; | |
| 132 | /* Link to older string with same hash index. To limit the size of this | |
| 133 | * array to 64K, this link is maintained only for the last 32K strings. | |
| 134 | * An index in this array is thus a window index modulo 32K. | |
| 135 | */ | |
| 136 | 136 | |
| 137 | ||
| 137 | Posf *head; /* Heads of the hash chains or NIL. */ | |
| 138 | 138 | |
| 139 | uInt ins_h; /* hash index of string to be inserted */ | |
| 140 | uInt hash_size; /* number of elements in hash table */ | |
| 141 | uInt hash_bits; /* log2(hash_size) */ | |
| 142 | uInt hash_mask; /* hash_size-1 */ | |
| 139 | uInt ins_h; /* hash index of string to be inserted */ | |
| 140 | uInt hash_size; /* number of elements in hash table */ | |
| 141 | uInt hash_bits; /* log2(hash_size) */ | |
| 142 | uInt hash_mask; /* hash_size-1 */ | |
| 143 | 143 | |
| 144 | uInt hash_shift; | |
| 145 | /* Number of bits by which ins_h must be shifted at each input | |
| 146 | * step. It must be such that after MIN_MATCH steps, the oldest | |
| 147 | * byte no longer takes part in the hash key, that is: | |
| 148 | * hash_shift * MIN_MATCH >= hash_bits | |
| 149 | */ | |
| 144 | uInt hash_shift; | |
| 145 | /* Number of bits by which ins_h must be shifted at each input | |
| 146 | * step. It must be such that after MIN_MATCH steps, the oldest | |
| 147 | * byte no longer takes part in the hash key, that is: | |
| 148 | * hash_shift * MIN_MATCH >= hash_bits | |
| 149 | */ | |
| 150 | 150 | |
| 151 | long block_start; | |
| 152 | /* Window position at the beginning of the current output block. Gets | |
| 153 | * negative when the window is moved backwards. | |
| 154 | */ | |
| 151 | long block_start; | |
| 152 | /* Window position at the beginning of the current output block. Gets | |
| 153 | * negative when the window is moved backwards. | |
| 154 | */ | |
| 155 | 155 | |
| 156 | uInt match_length; /* length of best match */ | |
| 157 | IPos prev_match; /* previous match */ | |
| 158 | int match_available; /* set if previous match exists */ | |
| 159 | uInt strstart; /* start of string to insert */ | |
| 160 | uInt match_start; /* start of matching string */ | |
| 161 | uInt lookahead; /* number of valid bytes ahead in window */ | |
| 156 | uInt match_length; /* length of best match */ | |
| 157 | IPos prev_match; /* previous match */ | |
| 158 | int match_available; /* set if previous match exists */ | |
| 159 | uInt strstart; /* start of string to insert */ | |
| 160 | uInt match_start; /* start of matching string */ | |
| 161 | uInt lookahead; /* number of valid bytes ahead in window */ | |
| 162 | 162 | |
| 163 | uInt prev_length; | |
| 164 | /* Length of the best match at previous step. Matches not greater than this | |
| 165 | * are discarded. This is used in the lazy match evaluation. | |
| 166 | */ | |
| 163 | uInt prev_length; | |
| 164 | /* Length of the best match at previous step. Matches not greater than this | |
| 165 | * are discarded. This is used in the lazy match evaluation. | |
| 166 | */ | |
| 167 | 167 | |
| 168 | uInt max_chain_length; | |
| 169 | /* To speed up deflation, hash chains are never searched beyond this | |
| 170 | * length. A higher limit improves compression ratio but degrades the | |
| 171 | * speed. | |
| 172 | */ | |
| 168 | uInt max_chain_length; | |
| 169 | /* To speed up deflation, hash chains are never searched beyond this | |
| 170 | * length. A higher limit improves compression ratio but degrades the | |
| 171 | * speed. | |
| 172 | */ | |
| 173 | 173 | |
| 174 | uInt max_lazy_match; | |
| 175 | /* Attempt to find a better match only when the current match is strictly | |
| 176 | * smaller than this value. This mechanism is used only for compression | |
| 177 | * levels >= 4. | |
| 178 | */ | |
| 174 | uInt max_lazy_match; | |
| 175 | /* Attempt to find a better match only when the current match is strictly | |
| 176 | * smaller than this value. This mechanism is used only for compression | |
| 177 | * levels >= 4. | |
| 178 | */ | |
| 179 | 179 | # define max_insert_length max_lazy_match |
| 180 | /* Insert new strings in the hash table only if the match length is not | |
| 181 | * greater than this length. This saves time but degrades compression. | |
| 182 | * max_insert_length is used only for compression levels <= 3. | |
| 183 | */ | |
| 180 | /* Insert new strings in the hash table only if the match length is not | |
| 181 | * greater than this length. This saves time but degrades compression. | |
| 182 | * max_insert_length is used only for compression levels <= 3. | |
| 183 | */ | |
| 184 | 184 | |
| 185 | int level; /* compression level (1..9) */ | |
| 186 | int strategy; /* favor or force Huffman coding*/ | |
| 185 | int level; /* compression level (1..9) */ | |
| 186 | int strategy; /* favor or force Huffman coding*/ | |
| 187 | 187 | |
| 188 | uInt good_match; | |
| 189 | /* Use a faster search when the previous match is longer than this */ | |
| 188 | uInt good_match; | |
| 189 | /* Use a faster search when the previous match is longer than this */ | |
| 190 | 190 | |
| 191 | ||
| 191 | int nice_match; /* Stop searching when current match exceeds this */ | |
| 192 | 192 | |
| 193 | /* used by trees.c: */ | |
| 194 | /* Didn't use ct_data typedef below to suppress compiler warning */ | |
| 195 | struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ | |
| 196 | struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ | |
| 197 | struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ | |
| 193 | /* used by trees.c: */ | |
| 194 | /* Didn't use ct_data typedef below to suppress compiler warning */ | |
| 195 | struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ | |
| 196 | struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ | |
| 197 | struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ | |
| 198 | 198 | |
| 199 | struct tree_desc_s l_desc; /* desc. for literal tree */ | |
| 200 | struct tree_desc_s d_desc; /* desc. for distance tree */ | |
| 201 | struct tree_desc_s bl_desc; /* desc. for bit length tree */ | |
| 199 | struct tree_desc_s l_desc; /* desc. for literal tree */ | |
| 200 | struct tree_desc_s d_desc; /* desc. for distance tree */ | |
| 201 | struct tree_desc_s bl_desc; /* desc. for bit length tree */ | |
| 202 | 202 | |
| 203 | ush bl_count[MAX_BITS+1]; | |
| 204 | /* number of codes at each bit length for an optimal tree */ | |
| 203 | ush bl_count[MAX_BITS+1]; | |
| 204 | /* number of codes at each bit length for an optimal tree */ | |
| 205 | 205 | |
| 206 | int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ | |
| 207 | int heap_len; /* number of elements in the heap */ | |
| 208 | int heap_max; /* element of largest frequency */ | |
| 209 | /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. | |
| 210 | * The same heap array is used to build all trees. | |
| 211 | */ | |
| 206 | int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ | |
| 207 | int heap_len; /* number of elements in the heap */ | |
| 208 | int heap_max; /* element of largest frequency */ | |
| 209 | /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. | |
| 210 | * The same heap array is used to build all trees. | |
| 211 | */ | |
| 212 | 212 | |
| 213 | uch depth[2*L_CODES+1]; | |
| 214 | /* Depth of each subtree used as tie breaker for trees of equal frequency | |
| 215 | */ | |
| 213 | uch depth[2*L_CODES+1]; | |
| 214 | /* Depth of each subtree used as tie breaker for trees of equal frequency | |
| 215 | */ | |
| 216 | 216 | |
| 217 | ||
| 217 | uchf *l_buf; /* buffer for literals or lengths */ | |
| 218 | 218 | |
| 219 | uInt lit_bufsize; | |
| 220 | /* Size of match buffer for literals/lengths. There are 4 reasons for | |
| 221 | * limiting lit_bufsize to 64K: | |
| 222 | * - frequencies can be kept in 16 bit counters | |
| 223 | * - if compression is not successful for the first block, all input | |
| 224 | * data is still in the window so we can still emit a stored block even | |
| 225 | * when input comes from standard input. (This can also be done for | |
| 226 | * all blocks if lit_bufsize is not greater than 32K.) | |
| 227 | * - if compression is not successful for a file smaller than 64K, we can | |
| 228 | * even emit a stored file instead of a stored block (saving 5 bytes). | |
| 229 | * This is applicable only for zip (not gzip or zlib). | |
| 230 | * - creating new Huffman trees less frequently may not provide fast | |
| 231 | * adaptation to changes in the input data statistics. (Take for | |
| 232 | * example a binary file with poorly compressible code followed by | |
| 233 | * a highly compressible string table.) Smaller buffer sizes give | |
| 234 | * fast adaptation but have of course the overhead of transmitting | |
| 235 | * trees more frequently. | |
| 236 | * - I can't count above 4 | |
| 237 | */ | |
| 219 | uInt lit_bufsize; | |
| 220 | /* Size of match buffer for literals/lengths. There are 4 reasons for | |
| 221 | * limiting lit_bufsize to 64K: | |
| 222 | * - frequencies can be kept in 16 bit counters | |
| 223 | * - if compression is not successful for the first block, all input | |
| 224 | * data is still in the window so we can still emit a stored block even | |
| 225 | * when input comes from standard input. (This can also be done for | |
| 226 | * all blocks if lit_bufsize is not greater than 32K.) | |
| 227 | * - if compression is not successful for a file smaller than 64K, we can | |
| 228 | * even emit a stored file instead of a stored block (saving 5 bytes). | |
| 229 | * This is applicable only for zip (not gzip or zlib). | |
| 230 | * - creating new Huffman trees less frequently may not provide fast | |
| 231 | * adaptation to changes in the input data statistics. (Take for | |
| 232 | * example a binary file with poorly compressible code followed by | |
| 233 | * a highly compressible string table.) Smaller buffer sizes give | |
| 234 | * fast adaptation but have of course the overhead of transmitting | |
| 235 | * trees more frequently. | |
| 236 | * - I can't count above 4 | |
| 237 | */ | |
| 238 | 238 | |
| 239 | ||
| 239 | uInt last_lit; /* running index in l_buf */ | |
| 240 | 240 | |
| 241 | ushf *d_buf; | |
| 242 | /* Buffer for distances. To simplify the code, d_buf and l_buf have | |
| 243 | * the same number of elements. To use different lengths, an extra flag | |
| 244 | * array would be necessary. | |
| 245 | */ | |
| 241 | ushf *d_buf; | |
| 242 | /* Buffer for distances. To simplify the code, d_buf and l_buf have | |
| 243 | * the same number of elements. To use different lengths, an extra flag | |
| 244 | * array would be necessary. | |
| 245 | */ | |
| 246 | 246 | |
| 247 | ulg opt_len; /* bit length of current block with optimal trees */ | |
| 248 | ulg static_len; /* bit length of current block with static trees */ | |
| 249 | uInt matches; /* number of string matches in current block */ | |
| 250 | uInt insert; /* bytes at end of window left to insert */ | |
| 247 | ulg opt_len; /* bit length of current block with optimal trees */ | |
| 248 | ulg static_len; /* bit length of current block with static trees */ | |
| 249 | uInt matches; /* number of string matches in current block */ | |
| 250 | uInt insert; /* bytes at end of window left to insert */ | |
| 251 | 251 | |
| 252 | 252 | #ifdef DEBUG |
| 253 | ulg compressed_len; /* total bit length of compressed file mod 2^32 */ | |
| 254 | ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ | |
| 253 | ulg compressed_len; /* total bit length of compressed file mod 2^32 */ | |
| 254 | ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ | |
| 255 | 255 | #endif |
| 256 | 256 | |
| 257 | ush bi_buf; | |
| 258 | /* Output buffer. bits are inserted starting at the bottom (least | |
| 259 | * significant bits). | |
| 260 | */ | |
| 261 | int bi_valid; | |
| 262 | /* Number of valid bits in bi_buf. All bits above the last valid bit | |
| 263 | * are always zero. | |
| 264 | */ | |
| 257 | ush bi_buf; | |
| 258 | /* Output buffer. bits are inserted starting at the bottom (least | |
| 259 | * significant bits). | |
| 260 | */ | |
| 261 | int bi_valid; | |
| 262 | /* Number of valid bits in bi_buf. All bits above the last valid bit | |
| 263 | * are always zero. | |
| 264 | */ | |
| 265 | 265 | |
| 266 | ulg high_water; | |
| 267 | /* High water mark offset in window for initialized bytes -- bytes above | |
| 268 | * this are set to zero in order to avoid memory check warnings when | |
| 269 | * longest match routines access bytes past the input. This is then | |
| 270 | * updated to the new high water mark. | |
| 271 | */ | |
| 266 | ulg high_water; | |
| 267 | /* High water mark offset in window for initialized bytes -- bytes above | |
| 268 | * this are set to zero in order to avoid memory check warnings when | |
| 269 | * longest match routines access bytes past the input. This is then | |
| 270 | * updated to the new high water mark. | |
| 271 | */ | |
| 272 | 272 | |
| 273 | 273 | } FAR deflate_state; |
| 274 | 274 | |
| r25360 | r25361 | |
| 292 | 292 | /* Number of bytes after end of data in window to initialize in order to avoid |
| 293 | 293 | memory checker errors from longest match routines */ |
| 294 | 294 | |
| 295 | ||
| 295 | /* in trees.c */ | |
| 296 | 296 | void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); |
| 297 | 297 | int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); |
| 298 | 298 | void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, |
| 299 | ||
| 299 | ulg stored_len, int last)); | |
| 300 | 300 | void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s)); |
| 301 | 301 | void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); |
| 302 | 302 | void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, |
| 303 | ||
| 303 | ulg stored_len, int last)); | |
| 304 | 304 | |
| 305 | 305 | #define d_code(dist) \ |
| 306 | ||
| 306 | ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) | |
| 307 | 307 | /* Mapping from a distance to a distance code. dist is the distance - 1 and |
| 308 | 308 | * must not have side effects. _dist_code[256] and _dist_code[257] are never |
| 309 | 309 | * used. |
| r25360 | r25361 | |
| 313 | 313 | /* Inline versions of _tr_tally for speed: */ |
| 314 | 314 | |
| 315 | 315 | #if defined(GEN_TREES_H) || !defined(STDC) |
| 316 | extern uch ZLIB_INTERNAL _length_code[]; | |
| 317 | extern uch ZLIB_INTERNAL _dist_code[]; | |
| 316 | extern uch ZLIB_INTERNAL _length_code[]; | |
| 317 | extern uch ZLIB_INTERNAL _dist_code[]; | |
| 318 | 318 | #else |
| 319 | extern const uch ZLIB_INTERNAL _length_code[]; | |
| 320 | extern const uch ZLIB_INTERNAL _dist_code[]; | |
| 319 | extern const uch ZLIB_INTERNAL _length_code[]; | |
| 320 | extern const uch ZLIB_INTERNAL _dist_code[]; | |
| 321 | 321 | #endif |
| 322 | 322 | |
| 323 | 323 | # define _tr_tally_lit(s, c, flush) \ |
| 324 | { uch cc = (c); \ | |
| 325 | s->d_buf[s->last_lit] = 0; \ | |
| 326 | s->l_buf[s->last_lit++] = cc; \ | |
| 327 | s->dyn_ltree[cc].Freq++; \ | |
| 328 | flush = (s->last_lit == s->lit_bufsize-1); \ | |
| 329 | } | |
| 324 | { uch cc = (c); \ | |
| 325 | s->d_buf[s->last_lit] = 0; \ | |
| 326 | s->l_buf[s->last_lit++] = cc; \ | |
| 327 | s->dyn_ltree[cc].Freq++; \ | |
| 328 | flush = (s->last_lit == s->lit_bufsize-1); \ | |
| 329 | } | |
| 330 | 330 | # define _tr_tally_dist(s, distance, length, flush) \ |
| 331 | { uch len = (length); \ | |
| 332 | ush dist = (distance); \ | |
| 333 | s->d_buf[s->last_lit] = dist; \ | |
| 334 | s->l_buf[s->last_lit++] = len; \ | |
| 335 | dist--; \ | |
| 336 | s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ | |
| 337 | s->dyn_dtree[d_code(dist)].Freq++; \ | |
| 338 | flush = (s->last_lit == s->lit_bufsize-1); \ | |
| 339 | } | |
| 331 | { uch len = (length); \ | |
| 332 | ush dist = (distance); \ | |
| 333 | s->d_buf[s->last_lit] = dist; \ | |
| 334 | s->l_buf[s->last_lit++] = len; \ | |
| 335 | dist--; \ | |
| 336 | s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ | |
| 337 | s->dyn_dtree[d_code(dist)].Freq++; \ | |
| 338 | flush = (s->last_lit == s->lit_bufsize-1); \ | |
| 339 | } | |
| 340 | 340 | #else |
| 341 | 341 | # define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) |
| 342 | 342 | # define _tr_tally_dist(s, distance, length, flush) \ |
| 343 | ||
| 343 | flush = _tr_tally(s, distance, length) | |
| 344 | 344 | #endif |
| 345 | 345 | |
| 346 | 346 | #endif /* DEFLATE_H */ |
| r25360 | r25361 | |
|---|---|---|
| 18 | 18 | This function needs to loop on read(), since read() is not guaranteed to |
| 19 | 19 | read the number of bytes requested, depending on the type of descriptor. */ |
| 20 | 20 | local int gz_load(state, buf, len, have) |
| 21 | gz_statep state; | |
| 22 | unsigned char *buf; | |
| 23 | unsigned len; | |
| 24 | unsigned *have; | |
| 21 | gz_statep state; | |
| 22 | unsigned char *buf; | |
| 23 | unsigned len; | |
| 24 | unsigned *have; | |
| 25 | 25 | { |
| 26 | ||
| 26 | int ret; | |
| 27 | 27 | |
| 28 | *have = 0; | |
| 29 | do { | |
| 30 | ret = read(state->fd, buf + *have, len - *have); | |
| 31 | if (ret <= 0) | |
| 32 | break; | |
| 33 | *have += ret; | |
| 34 | } while (*have < len); | |
| 35 | if (ret < 0) { | |
| 36 | gz_error(state, Z_ERRNO, zstrerror()); | |
| 37 | return -1; | |
| 38 | } | |
| 39 | if (ret == 0) | |
| 40 | state->eof = 1; | |
| 41 | return 0; | |
| 28 | *have = 0; | |
| 29 | do { | |
| 30 | ret = read(state->fd, buf + *have, len - *have); | |
| 31 | if (ret <= 0) | |
| 32 | break; | |
| 33 | *have += ret; | |
| 34 | } while (*have < len); | |
| 35 | if (ret < 0) { | |
| 36 | gz_error(state, Z_ERRNO, zstrerror()); | |
| 37 | return -1; | |
| 38 | } | |
| 39 | if (ret == 0) | |
| 40 | state->eof = 1; | |
| 41 | return 0; | |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | 44 | /* Load up input buffer and set eof flag if last data loaded -- return -1 on |
| r25360 | r25361 | |
| 49 | 49 | the input buffer, and then the remainder of the buffer is loaded with the |
| 50 | 50 | available data from the input file. */ |
| 51 | 51 | local int gz_avail(state) |
| 52 | ||
| 52 | gz_statep state; | |
| 53 | 53 | { |
| 54 | unsigned got; | |
| 55 | z_streamp strm = &(state->strm); | |
| 54 | unsigned got; | |
| 55 | z_streamp strm = &(state->strm); | |
| 56 | 56 | |
| 57 | if (state->err != Z_OK && state->err != Z_BUF_ERROR) | |
| 58 | return -1; | |
| 59 | if (state->eof == 0) { | |
| 60 | if (strm->avail_in) { /* copy what's there to the start */ | |
| 61 | unsigned char *p = state->in; | |
| 62 | unsigned const char *q = strm->next_in; | |
| 63 | unsigned n = strm->avail_in; | |
| 64 | do { | |
| 65 | *p++ = *q++; | |
| 66 | } while (--n); | |
| 67 | } | |
| 68 | if (gz_load(state, state->in + strm->avail_in, | |
| 69 | state->size - strm->avail_in, &got) == -1) | |
| 70 | return -1; | |
| 71 | strm->avail_in += got; | |
| 72 | strm->next_in = state->in; | |
| 73 | } | |
| 74 | return 0; | |
| 57 | if (state->err != Z_OK && state->err != Z_BUF_ERROR) | |
| 58 | return -1; | |
| 59 | if (state->eof == 0) { | |
| 60 | if (strm->avail_in) { /* copy what's there to the start */ | |
| 61 | unsigned char *p = state->in; | |
| 62 | unsigned const char *q = strm->next_in; | |
| 63 | unsigned n = strm->avail_in; | |
| 64 | do { | |
| 65 | *p++ = *q++; | |
| 66 | } while (--n); | |
| 67 | } | |
| 68 | if (gz_load(state, state->in + strm->avail_in, | |
| 69 | state->size - strm->avail_in, &got) == -1) | |
| 70 | return -1; | |
| 71 | strm->avail_in += got; | |
| 72 | strm->next_in = state->in; | |
| 73 | } | |
| 74 | return 0; | |
| 75 | 75 | } |
| 76 | 76 | |
| 77 | 77 | /* Look for gzip header, set up for inflate or copy. state->x.have must be 0. |
| r25360 | r25361 | |
| 84 | 84 | a user buffer. If decompressing, the inflate state will be initialized. |
| 85 | 85 | gz_look() will return 0 on success or -1 on failure. */ |
| 86 | 86 | local int gz_look(state) |
| 87 | ||
| 87 | gz_statep state; | |
| 88 | 88 | { |
| 89 | ||
| 89 | z_streamp strm = &(state->strm); | |
| 90 | 90 | |
| 91 | /* allocate read buffers and inflate memory */ | |
| 92 | if (state->size == 0) { | |
| 93 | /* allocate buffers */ | |
| 94 | state->in = (unsigned char *)malloc(state->want); | |
| 95 | state->out = (unsigned char *)malloc(state->want << 1); | |
| 96 | if (state->in == NULL || state->out == NULL) { | |
| 97 | if (state->out != NULL) | |
| 98 | free(state->out); | |
| 99 | if (state->in != NULL) | |
| 100 | free(state->in); | |
| 101 | gz_error(state, Z_MEM_ERROR, "out of memory"); | |
| 102 | return -1; | |
| 103 | } | |
| 104 | state->size = state->want; | |
| 91 | /* allocate read buffers and inflate memory */ | |
| 92 | if (state->size == 0) { | |
| 93 | /* allocate buffers */ | |
| 94 | state->in = (unsigned char *)malloc(state->want); | |
| 95 | state->out = (unsigned char *)malloc(state->want << 1); | |
| 96 | if (state->in == NULL || state->out == NULL) { | |
| 97 | if (state->out != NULL) | |
| 98 | free(state->out); | |
| 99 | if (state->in != NULL) | |
| 100 | free(state->in); | |
| 101 | gz_error(state, Z_MEM_ERROR, "out of memory"); | |
| 102 | return -1; | |
| 103 | } | |
| 104 | state->size = state->want; | |
| 105 | 105 | |
| 106 | /* allocate inflate memory */ | |
| 107 | state->strm.zalloc = Z_NULL; | |
| 108 | state->strm.zfree = Z_NULL; | |
| 109 | state->strm.opaque = Z_NULL; | |
| 110 | state->strm.avail_in = 0; | |
| 111 | state->strm.next_in = Z_NULL; | |
| 112 | if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */ | |
| 113 | free(state->out); | |
| 114 | free(state->in); | |
| 115 | state->size = 0; | |
| 116 | gz_error(state, Z_MEM_ERROR, "out of memory"); | |
| 117 | return -1; | |
| 118 | } | |
| 119 | } | |
| 106 | /* allocate inflate memory */ | |
| 107 | state->strm.zalloc = Z_NULL; | |
| 108 | state->strm.zfree = Z_NULL; | |
| 109 | state->strm.opaque = Z_NULL; | |
| 110 | state->strm.avail_in = 0; | |
| 111 | state->strm.next_in = Z_NULL; | |
| 112 | if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */ | |
| 113 | free(state->out); | |
| 114 | free(state->in); | |
| 115 | state->size = 0; | |
| 116 | gz_error(state, Z_MEM_ERROR, "out of memory"); | |
| 117 | return -1; | |
| 118 | } | |
| 119 | } | |
| 120 | 120 | |
| 121 | /* get at least the magic bytes in the input buffer */ | |
| 122 | if (strm->avail_in < 2) { | |
| 123 | if (gz_avail(state) == -1) | |
| 124 | return -1; | |
| 125 | if (strm->avail_in == 0) | |
| 126 | return 0; | |
| 127 | } | |
| 121 | /* get at least the magic bytes in the input buffer */ | |
| 122 | if (strm->avail_in < 2) { | |
| 123 | if (gz_avail(state) == -1) | |
| 124 | return -1; | |
| 125 | if (strm->avail_in == 0) | |
| 126 | return 0; | |
| 127 | } | |
| 128 | 128 | |
| 129 | /* look for gzip magic bytes -- if there, do gzip decoding (note: there is | |
| 130 | a logical dilemma here when considering the case of a partially written | |
| 131 | gzip file, to wit, if a single 31 byte is written, then we cannot tell | |
| 132 | whether this is a single-byte file, or just a partially written gzip | |
| 133 | file -- for here we assume that if a gzip file is being written, then | |
| 134 | the header will be written in a single operation, so that reading a | |
| 135 | single byte is sufficient indication that it is not a gzip file) */ | |
| 136 | if (strm->avail_in > 1 && | |
| 137 | strm->next_in[0] == 31 && strm->next_in[1] == 139) { | |
| 138 | inflateReset(strm); | |
| 139 | state->how = GZIP; | |
| 140 | state->direct = 0; | |
| 141 | return 0; | |
| 142 | } | |
| 129 | /* look for gzip magic bytes -- if there, do gzip decoding (note: there is | |
| 130 | a logical dilemma here when considering the case of a partially written | |
| 131 | gzip file, to wit, if a single 31 byte is written, then we cannot tell | |
| 132 | whether this is a single-byte file, or just a partially written gzip | |
| 133 | file -- for here we assume that if a gzip file is being written, then | |
| 134 | the header will be written in a single operation, so that reading a | |
| 135 | single byte is sufficient indication that it is not a gzip file) */ | |
| 136 | if (strm->avail_in > 1 && | |
| 137 | strm->next_in[0] == 31 && strm->next_in[1] == 139) { | |
| 138 | inflateReset(strm); | |
| 139 | state->how = GZIP; | |
| 140 | state->direct = 0; | |
| 141 | return 0; | |
| 142 | } | |
| 143 | 143 | |
| 144 | /* no gzip header -- if we were decoding gzip before, then this is trailing | |
| 145 | garbage. Ignore the trailing garbage and finish. */ | |
| 146 | if (state->direct == 0) { | |
| 147 | strm->avail_in = 0; | |
| 148 | state->eof = 1; | |
| 149 | state->x.have = 0; | |
| 150 | return 0; | |
| 151 | } | |
| 144 | /* no gzip header -- if we were decoding gzip before, then this is trailing | |
| 145 | garbage. Ignore the trailing garbage and finish. */ | |
| 146 | if (state->direct == 0) { | |
| 147 | strm->avail_in = 0; | |
| 148 | state->eof = 1; | |
| 149 | state->x.have = 0; | |
| 150 | return 0; | |
| 151 | } | |
| 152 | 152 | |
| 153 | /* doing raw i/o, copy any leftover input to output -- this assumes that | |
| 154 | the output buffer is larger than the input buffer, which also assures | |
| 155 | space for gzungetc() */ | |
| 156 | state->x.next = state->out; | |
| 157 | if (strm->avail_in) { | |
| 158 | memcpy(state->x.next, strm->next_in, strm->avail_in); | |
| 159 | state->x.have = strm->avail_in; | |
| 160 | strm->avail_in = 0; | |
| 161 | } | |
| 162 | state->how = COPY; | |
| 163 | state->direct = 1; | |
| 164 | return 0; | |
| 153 | /* doing raw i/o, copy any leftover input to output -- this assumes that | |
| 154 | the output buffer is larger than the input buffer, which also assures | |
| 155 | space for gzungetc() */ | |
| 156 | state->x.next = state->out; | |
| 157 | if (strm->avail_in) { | |
| 158 | memcpy(state->x.next, strm->next_in, strm->avail_in); | |
| 159 | state->x.have = strm->avail_in; | |
| 160 | strm->avail_in = 0; | |
| 161 | } | |
| 162 | state->how = COPY; | |
| 163 | state->direct = 1; | |
| 164 | return 0; | |
| 165 | 165 | } |
| 166 | 166 | |
| 167 | 167 | /* Decompress from input to the provided next_out and avail_out in the state. |
| r25360 | r25361 | |
| 170 | 170 | the next gzip stream or raw data, once state->x.have is depleted. Returns 0 |
| 171 | 171 | on success, -1 on failure. */ |
| 172 | 172 | local int gz_decomp(state) |
| 173 | ||
| 173 | gz_statep state; | |
| 174 | 174 | { |
| 175 | int ret = Z_OK; | |
| 176 | unsigned had; | |
| 177 | z_streamp strm = &(state->strm); | |
| 175 | int ret = Z_OK; | |
| 176 | unsigned had; | |
| 177 | z_streamp strm = &(state->strm); | |
| 178 | 178 | |
| 179 | /* fill output buffer up to end of deflate stream */ | |
| 180 | had = strm->avail_out; | |
| 181 | do { | |
| 182 | /* get more input for inflate() */ | |
| 183 | if (strm->avail_in == 0 && gz_avail(state) == -1) | |
| 184 | return -1; | |
| 185 | if (strm->avail_in == 0) { | |
| 186 | gz_error(state, Z_BUF_ERROR, "unexpected end of file"); | |
| 187 | break; | |
| 188 | } | |
| 179 | /* fill output buffer up to end of deflate stream */ | |
| 180 | had = strm->avail_out; | |
| 181 | do { | |
| 182 | /* get more input for inflate() */ | |
| 183 | if (strm->avail_in == 0 && gz_avail(state) == -1) | |
| 184 | return -1; | |
| 185 | if (strm->avail_in == 0) { | |
| 186 | gz_error(state, Z_BUF_ERROR, "unexpected end of file"); | |
| 187 | break; | |
| 188 | } | |
| 189 | 189 | |
| 190 | /* decompress and handle errors */ | |
| 191 | ret = inflate(strm, Z_NO_FLUSH); | |
| 192 | if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { | |
| 193 | gz_error(state, Z_STREAM_ERROR, | |
| 194 | "internal error: inflate stream corrupt"); | |
| 195 | return -1; | |
| 196 | } | |
| 197 | if (ret == Z_MEM_ERROR) { | |
| 198 | gz_error(state, Z_MEM_ERROR, "out of memory"); | |
| 199 | return -1; | |
| 200 | } | |
| 201 | if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ | |
| 202 | gz_error(state, Z_DATA_ERROR, | |
| 203 | strm->msg == NULL ? "compressed data error" : strm->msg); | |
| 204 | return -1; | |
| 205 | } | |
| 206 | } while (strm->avail_out && ret != Z_STREAM_END); | |
| 190 | /* decompress and handle errors */ | |
| 191 | ret = inflate(strm, Z_NO_FLUSH); | |
| 192 | if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { | |
| 193 | gz_error(state, Z_STREAM_ERROR, | |
| 194 | "internal error: inflate stream corrupt"); | |
| 195 | return -1; | |
| 196 | } | |
| 197 | if (ret == Z_MEM_ERROR) { | |
| 198 | gz_error(state, Z_MEM_ERROR, "out of memory"); | |
| 199 | return -1; | |
| 200 | } | |
| 201 | if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ | |
| 202 | gz_error(state, Z_DATA_ERROR, | |
| 203 | strm->msg == NULL ? "compressed data error" : strm->msg); | |
| 204 | return -1; | |
| 205 | } | |
| 206 | } while (strm->avail_out && ret != Z_STREAM_END); | |
| 207 | 207 | |
| 208 | /* update available output */ | |
| 209 | state->x.have = had - strm->avail_out; | |
| 210 | state->x.next = strm->next_out - state->x.have; | |
| 208 | /* update available output */ | |
| 209 | state->x.have = had - strm->avail_out; | |
| 210 | state->x.next = strm->next_out - state->x.have; | |
| 211 | 211 | |
| 212 | /* if the gzip stream completed successfully, look for another */ | |
| 213 | if (ret == Z_STREAM_END) | |
| 214 | state->how = LOOK; | |
| 212 | /* if the gzip stream completed successfully, look for another */ | |
| 213 | if (ret == Z_STREAM_END) | |
| 214 | state->how = LOOK; | |
| 215 | 215 | |
| 216 | /* good decompression */ | |
| 217 | return 0; | |
| 216 | /* good decompression */ | |
| 217 | return 0; | |
| 218 | 218 | } |
| 219 | 219 | |
| 220 | 220 | /* Fetch data and put it in the output buffer. Assumes state->x.have is 0. |
| r25360 | r25361 | |
| 224 | 224 | otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the |
| 225 | 225 | end of the input file has been reached and all data has been processed. */ |
| 226 | 226 | local int gz_fetch(state) |
| 227 | ||
| 227 | gz_statep state; | |
| 228 | 228 | { |
| 229 | ||
| 229 | z_streamp strm = &(state->strm); | |
| 230 | 230 | |
| 231 | do { | |
| 232 | switch(state->how) { | |
| 233 | case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */ | |
| 234 | if (gz_look(state) == -1) | |
| 235 | return -1; | |
| 236 | if (state->how == LOOK) | |
| 237 | return 0; | |
| 238 | break; | |
| 239 | case COPY: /* -> COPY */ | |
| 240 | if (gz_load(state, state->out, state->size << 1, &(state->x.have)) | |
| 241 | == -1) | |
| 242 | return -1; | |
| 243 | state->x.next = state->out; | |
| 244 | return 0; | |
| 245 | case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */ | |
| 246 | strm->avail_out = state->size << 1; | |
| 247 | strm->next_out = state->out; | |
| 248 | if (gz_decomp(state) == -1) | |
| 249 | return -1; | |
| 250 | } | |
| 251 | } while (state->x.have == 0 && (!state->eof || strm->avail_in)); | |
| 252 | return 0; | |
| 231 | do { | |
| 232 | switch(state->how) { | |
| 233 | case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */ | |
| 234 | if (gz_look(state) == -1) | |
| 235 | return -1; | |
| 236 | if (state->how == LOOK) | |
| 237 | return 0; | |
| 238 | break; | |
| 239 | case COPY: /* -> COPY */ | |
| 240 | if (gz_load(state, state->out, state->size << 1, &(state->x.have)) | |
| 241 | == -1) | |
| 242 | return -1; | |
| 243 | state->x.next = state->out; | |
| 244 | return 0; | |
| 245 | case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */ | |
| 246 | strm->avail_out = state->size << 1; | |
| 247 | strm->next_out = state->out; | |
| 248 | if (gz_decomp(state) == -1) | |
| 249 | return -1; | |
| 250 | } | |
| 251 | } while (state->x.have == 0 && (!state->eof || strm->avail_in)); | |
| 252 | return 0; | |
| 253 | 253 | } |
| 254 | 254 | |
| 255 | 255 | /* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ |
| 256 | 256 | local int gz_skip(state, len) |
| 257 | gz_statep state; | |
| 258 | z_off64_t len; | |
| 257 | gz_statep state; | |
| 258 | z_off64_t len; | |
| 259 | 259 | { |
| 260 | ||
| 260 | unsigned n; | |
| 261 | 261 | |
| 262 | /* skip over len bytes or reach end-of-file, whichever comes first */ | |
| 263 | while (len) | |
| 264 | /* skip over whatever is in output buffer */ | |
| 265 | if (state->x.have) { | |
| 266 | n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ? | |
| 267 | (unsigned)len : state->x.have; | |
| 268 | state->x.have -= n; | |
| 269 | state->x.next += n; | |
| 270 | state->x.pos += n; | |
| 271 | len -= n; | |
| 272 | } | |
| 262 | /* skip over len bytes or reach end-of-file, whichever comes first */ | |
| 263 | while (len) | |
| 264 | /* skip over whatever is in output buffer */ | |
| 265 | if (state->x.have) { | |
| 266 | n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ? | |
| 267 | (unsigned)len : state->x.have; | |
| 268 | state->x.have -= n; | |
| 269 | state->x.next += n; | |
| 270 | state->x.pos += n; | |
| 271 | len -= n; | |
| 272 | } | |
| 273 | 273 | |
| 274 | /* output buffer empty -- return if we're at the end of the input */ | |
| 275 | else if (state->eof && state->strm.avail_in == 0) | |
| 276 | break; | |
| 274 | /* output buffer empty -- return if we're at the end of the input */ | |
| 275 | else if (state->eof && state->strm.avail_in == 0) | |
| 276 | break; | |
| 277 | 277 | |
| 278 | /* need more data to skip -- load up output buffer */ | |
| 279 | else { | |
| 280 | /* get more output, looking for header if required */ | |
| 281 | if (gz_fetch(state) == -1) | |
| 282 | return -1; | |
| 283 | } | |
| 284 | return 0; | |
| 278 | /* need more data to skip -- load up output buffer */ | |
| 279 | else { | |
| 280 | /* get more output, looking for header if required */ | |
| 281 | if (gz_fetch(state) == -1) | |
| 282 | return -1; | |
| 283 | } | |
| 284 | return 0; | |
| 285 | 285 | } |
| 286 | 286 | |
| 287 | 287 | /* -- see zlib.h -- */ |
| 288 | 288 | int ZEXPORT gzread(file, buf, len) |
| 289 | gzFile file; | |
| 290 | voidp buf; | |
| 291 | unsigned len; | |
| 289 | gzFile file; | |
| 290 | voidp buf; | |
| 291 | unsigned len; | |
| 292 | 292 | { |
| 293 | unsigned got, n; | |
| 294 | gz_statep state; | |
| 295 | z_streamp strm; | |
| 293 | unsigned got, n; | |
| 294 | gz_statep state; | |
| 295 | z_streamp strm; | |
| 296 | 296 | |
| 297 | /* get internal structure */ | |
| 298 | if (file == NULL) | |
| 299 | return -1; | |
| 300 | state = (gz_statep)file; | |
| 301 | strm = &(state->strm); | |
| 297 | /* get internal structure */ | |
| 298 | if (file == NULL) | |
| 299 | return -1; | |
| 300 | state = (gz_statep)file; | |
| 301 | strm = &(state->strm); | |
| 302 | 302 | |
| 303 | /* check that we're reading and that there's no (serious) error */ | |
| 304 | if (state->mode != GZ_READ || | |
| 305 | (state->err != Z_OK && state->err != Z_BUF_ERROR)) | |
| 306 | return -1; | |
| 303 | /* check that we're reading and that there's no (serious) error */ | |
| 304 | if (state->mode != GZ_READ || | |
| 305 | (state->err != Z_OK && state->err != Z_BUF_ERROR)) | |
| 306 | return -1; | |
| 307 | 307 | |
| 308 | /* since an int is returned, make sure len fits in one, otherwise return | |
| 309 | with an error (this avoids the flaw in the interface) */ | |
| 310 | if ((int)len < 0) { | |
| 311 | gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); | |
| 312 | return -1; | |
| 313 | } | |
| 308 | /* since an int is returned, make sure len fits in one, otherwise return | |
| 309 | with an error (this avoids the flaw in the interface) */ | |
| 310 | if ((int)len < 0) { | |
| 311 | gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); | |
| 312 | return -1; | |
| 313 | } | |
| 314 | 314 | |
| 315 | /* if len is zero, avoid unnecessary operations */ | |
| 316 | if (len == 0) | |
| 317 | return 0; | |
| 315 | /* if len is zero, avoid unnecessary operations */ | |
| 316 | if (len == 0) | |
| 317 | return 0; | |
| 318 | 318 | |
| 319 | /* process a skip request */ | |
| 320 | if (state->seek) { | |
| 321 | state->seek = 0; | |
| 322 | if (gz_skip(state, state->skip) == -1) | |
| 323 | return -1; | |
| 324 | } | |
| 319 | /* process a skip request */ | |
| 320 | if (state->seek) { | |
| 321 | state->seek = 0; | |
| 322 | if (gz_skip(state, state->skip) == -1) | |
| 323 | return -1; | |
| 324 | } | |
| 325 | 325 | |
| 326 | /* get len bytes to buf, or less than len if at the end */ | |
| 327 | got = 0; | |
| 328 | do { | |
| 329 | /* first just try copying data from the output buffer */ | |
| 330 | if (state->x.have) { | |
| 331 | n = state->x.have > len ? len : state->x.have; | |
| 332 | memcpy(buf, state->x.next, n); | |
| 333 | state->x.next += n; | |
| 334 | state->x.have -= n; | |
| 335 | } | |
| 326 | /* get len bytes to buf, or less than len if at the end */ | |
| 327 | got = 0; | |
| 328 | do { | |
| 329 | /* first just try copying data from the output buffer */ | |
| 330 | if (state->x.have) { | |
| 331 | n = state->x.have > len ? len : state->x.have; | |
| 332 | memcpy(buf, state->x.next, n); | |
| 333 | state->x.next += n; | |
| 334 | state->x.have -= n; | |
| 335 | } | |
| 336 | 336 | |
| 337 | /* output buffer empty -- return if we're at the end of the input */ | |
| 338 | else if (state->eof && strm->avail_in == 0) { | |
| 339 | state->past = 1; /* tried to read past end */ | |
| 340 | break; | |
| 341 | } | |
| 337 | /* output buffer empty -- return if we're at the end of the input */ | |
| 338 | else if (state->eof && strm->avail_in == 0) { | |
| 339 | state->past = 1; /* tried to read past end */ | |
| 340 | break; | |
| 341 | } | |
| 342 | 342 | |
| 343 | /* need output data -- for small len or new stream load up our output | |
| 344 | buffer */ | |
| 345 | else if (state->how == LOOK || len < (state->size << 1)) { | |
| 346 | /* get more output, looking for header if required */ | |
| 347 | if (gz_fetch(state) == -1) | |
| 348 | return -1; | |
| 349 | continue; /* no progress yet -- go back to copy above */ | |
| 350 | /* the copy above assures that we will leave with space in the | |
| 351 | output buffer, allowing at least one gzungetc() to succeed */ | |
| 352 | } | |
| 343 | /* need output data -- for small len or new stream load up our output | |
| 344 | buffer */ | |
| 345 | else if (state->how == LOOK || len < (state->size << 1)) { | |
| 346 | /* get more output, looking for header if required */ | |
| 347 | if (gz_fetch(state) == -1) | |
| 348 | return -1; | |
| 349 | continue; /* no progress yet -- go back to copy above */ | |
| 350 | /* the copy above assures that we will leave with space in the | |
| 351 | output buffer, allowing at least one gzungetc() to succeed */ | |
| 352 | } | |
| 353 | 353 | |
| 354 | /* large len -- read directly into user buffer */ | |
| 355 | else if (state->how == COPY) { /* read directly */ | |
| 356 | if (gz_load(state, (unsigned char *)buf, len, &n) == -1) | |
| 357 | return -1; | |
| 358 | } | |
| 354 | /* large len -- read directly into user buffer */ | |
| 355 | else if (state->how == COPY) { /* read directly */ | |
| 356 | if (gz_load(state, (unsigned char *)buf, len, &n) == -1) | |
| 357 | return -1; | |
| 358 | } | |
| 359 | 359 | |
| 360 | /* large len -- decompress directly into user buffer */ | |
| 361 | else { /* state->how == GZIP */ | |
| 362 | strm->avail_out = len; | |
| 363 | strm->next_out = (unsigned char *)buf; | |
| 364 | if (gz_decomp(state) == -1) | |
| 365 | return -1; | |
| 366 | n = state->x.have; | |
| 367 | state->x.have = 0; | |
| 368 | } | |
| 360 | /* large len -- decompress directly into user buffer */ | |
| 361 | else { /* state->how == GZIP */ | |
| 362 | strm->avail_out = len; | |
| 363 | strm->next_out = (unsigned char *)buf; | |
| 364 | if (gz_decomp(state) == -1) | |
| 365 | return -1; | |
| 366 | n = state->x.have; | |
| 367 | state->x.have = 0; | |
| 368 | } | |
| 369 | 369 | |
| 370 | /* update progress */ | |
| 371 | len -= n; | |
| 372 | buf = (char *)buf + n; | |
| 373 | got += n; | |
| 374 | state->x.pos += n; | |
| 375 | } while (len); | |
| 370 | /* update progress */ | |
| 371 | len -= n; | |
| 372 | buf = (char *)buf + n; | |
| 373 | got += n; | |
| 374 | state->x.pos += n; | |
| 375 | } while (len); | |
| 376 | 376 | |
| 377 | /* return number of bytes read into user buffer (will fit in int) */ | |
| 378 | return (int)got; | |
| 377 | /* return number of bytes read into user buffer (will fit in int) */ | |
| 378 | return (int)got; | |
| 379 | 379 | } |
| 380 | 380 | |
| 381 | 381 | /* -- see zlib.h -- */ |
| r25360 | r25361 | |
| 385 | 385 | # undef gzgetc |
| 386 | 386 | #endif |
| 387 | 387 | int ZEXPORT gzgetc(file) |
| 388 | ||
| 388 | gzFile file; | |
| 389 | 389 | { |
| 390 | int ret; | |
| 391 | unsigned char buf[1]; | |
| 392 | gz_statep state; | |
| 390 | int ret; | |
| 391 | unsigned char buf[1]; | |
| 392 | gz_statep state; | |
| 393 | 393 | |
| 394 | /* get internal structure */ | |
| 395 | if (file == NULL) | |
| 396 | return -1; | |
| 397 | state = (gz_statep)file; | |
| 394 | /* get internal structure */ | |
| 395 | if (file == NULL) | |
| 396 | return -1; | |
| 397 | state = (gz_statep)file; | |
| 398 | 398 | |
| 399 | /* check that we're reading and that there's no (serious) error */ | |
| 400 | if (state->mode != GZ_READ || | |
| 401 | (state->err != Z_OK && state->err != Z_BUF_ERROR)) | |
| 402 | return -1; | |
| 399 | /* check that we're reading and that there's no (serious) error */ | |
| 400 | if (state->mode != GZ_READ || | |
| 401 | (state->err != Z_OK && state->err != Z_BUF_ERROR)) | |
| 402 | return -1; | |
| 403 | 403 | |
| 404 | /* try output buffer (no need to check for skip request) */ | |
| 405 | if (state->x.have) { | |
| 406 | state->x.have--; | |
| 407 | state->x.pos++; | |
| 408 | return *(state->x.next)++; | |
| 409 | } | |
| 404 | /* try output buffer (no need to check for skip request) */ | |
| 405 | if (state->x.have) { | |
| 406 | state->x.have--; | |
| 407 | state->x.pos++; | |
| 408 | return *(state->x.next)++; | |
| 409 | } | |
| 410 | 410 | |
| 411 | /* nothing there -- try gzread() */ | |
| 412 | ret = gzread(file, buf, 1); | |
| 413 | return ret < 1 ? -1 : buf[0]; | |
| 411 | /* nothing there -- try gzread() */ | |
| 412 | ret = gzread(file, buf, 1); | |
| 413 | return ret < 1 ? -1 : buf[0]; | |
| 414 | 414 | } |
| 415 | 415 | |
| 416 | 416 | int ZEXPORT gzgetc_(file) |
| 417 | 417 | gzFile file; |
| 418 | 418 | { |
| 419 | ||
| 419 | return gzgetc(file); | |
| 420 | 420 | } |
| 421 | 421 | |
| 422 | 422 | /* -- see zlib.h -- */ |
| 423 | 423 | int ZEXPORT gzungetc(c, file) |
| 424 | int c; | |
| 425 | gzFile file; | |
| 424 | int c; | |
| 425 | gzFile file; | |
| 426 | 426 | { |
| 427 | ||
| 427 | gz_statep state; | |
| 428 | 428 | |
| 429 | /* get internal structure */ | |
| 430 | if (file == NULL) | |
| 431 | return -1; | |
| 432 | state = (gz_statep)file; | |
| 429 | /* get internal structure */ | |
| 430 | if (file == NULL) | |
| 431 | return -1; | |
| 432 | state = (gz_statep)file; | |
| 433 | 433 | |
| 434 | /* check that we're reading and that there's no (serious) error */ | |
| 435 | if (state->mode != GZ_READ || | |
| 436 | (state->err != Z_OK && state->err != Z_BUF_ERROR)) | |
| 437 | return -1; | |
| 434 | /* check that we're reading and that there's no (serious) error */ | |
| 435 | if (state->mode != GZ_READ || | |
| 436 | (state->err != Z_OK && state->err != Z_BUF_ERROR)) | |
| 437 | return -1; | |
| 438 | 438 | |
| 439 | /* process a skip request */ | |
| 440 | if (state->seek) { | |
| 441 | state->seek = 0; | |
| 442 | if (gz_skip(state, state->skip) == -1) | |
| 443 | return -1; | |
| 444 | } | |
| 439 | /* process a skip request */ | |
| 440 | if (state->seek) { | |
| 441 | state->seek = 0; | |
| 442 | if (gz_skip(state, state->skip) == -1) | |
| 443 | return -1; | |
| 444 | } | |
| 445 | 445 | |
| 446 | /* can't push EOF */ | |
| 447 | if (c < 0) | |
| 448 | return -1; | |
| 446 | /* can't push EOF */ | |
| 447 | if (c < 0) | |
| 448 | return -1; | |
| 449 | 449 | |
| 450 | /* if output buffer empty, put byte at end (allows more pushing) */ | |
| 451 | if (state->x.have == 0) { | |
| 452 | state->x.have = 1; | |
| 453 | state->x.next = state->out + (state->size << 1) - 1; | |
| 454 | state->x.next[0] = c; | |
| 455 | state->x.pos--; | |
| 456 | state->past = 0; | |
| 457 | return c; | |
| 458 | } | |
| 450 | /* if output buffer empty, put byte at end (allows more pushing) */ | |
| 451 | if (state->x.have == 0) { | |
| 452 | state->x.have = 1; | |
| 453 | state->x.next = state->out + (state->size << 1) - 1; | |
| 454 | state->x.next[0] = c; | |
| 455 | state->x.pos--; | |
| 456 | state->past = 0; | |
| 457 | return c; | |
| 458 | } | |
| 459 | 459 | |
| 460 | /* if no room, give up (must have already done a gzungetc()) */ | |
| 461 | if (state->x.have == (state->size << 1)) { | |
| 462 | gz_error(state, Z_DATA_ERROR, "out of room to push characters"); | |
| 463 | return -1; | |
| 464 | } | |
| 460 | /* if no room, give up (must have already done a gzungetc()) */ | |
| 461 | if (state->x.have == (state->size << 1)) { | |
| 462 | gz_error(state, Z_DATA_ERROR, "out of room to push characters"); | |
| 463 | return -1; | |
| 464 | } | |
| 465 | 465 | |
| 466 | /* slide output data if needed and insert byte before existing data */ | |
| 467 | if (state->x.next == state->out) { | |
| 468 | unsigned char *src = state->out + state->x.have; | |
| 469 | unsigned char *dest = state->out + (state->size << 1); | |
| 470 | while (src > state->out) | |
| 471 | *--dest = *--src; | |
| 472 | state->x.next = dest; | |
| 473 | } | |
| 474 | state->x.have++; | |
| 475 | state->x.next--; | |
| 476 | state->x.next[0] = c; | |
| 477 | state->x.pos--; | |
| 478 | state->past = 0; | |
| 479 | return c; | |
| 466 | /* slide output data if needed and insert byte before existing data */ | |
| 467 | if (state->x.next == state->out) { | |
| 468 | unsigned char *src = state->out + state->x.have; | |
| 469 | unsigned char *dest = state->out + (state->size << 1); | |
| 470 | while (src > state->out) | |
| 471 | *--dest = *--src; | |
| 472 | state->x.next = dest; | |
| 473 | } | |
| 474 | state->x.have++; | |
| 475 | state->x.next--; | |
| 476 | state->x.next[0] = c; | |
| 477 | state->x.pos--; | |
| 478 | state->past = 0; | |
| 479 | return c; | |
| 480 | 480 | } |
| 481 | 481 | |
| 482 | 482 | /* -- see zlib.h -- */ |
| 483 | 483 | char * ZEXPORT gzgets(file, buf, len) |
| 484 | gzFile file; | |
| 485 | char *buf; | |
| 486 | int len; | |
| 484 | gzFile file; | |
| 485 | char *buf; | |
| 486 | int len; | |
| 487 | 487 | { |
| 488 | unsigned left, n; | |
| 489 | char *str; | |
| 490 | unsigned char *eol; | |
| 491 | gz_statep state; | |
| 488 | unsigned left, n; | |
| 489 | char *str; | |
| 490 | unsigned char *eol; | |
| 491 | gz_statep state; | |
| 492 | 492 | |
| 493 | /* check parameters and get internal structure */ | |
| 494 | if (file == NULL || buf == NULL || len < 1) | |
| 495 | return NULL; | |
| 496 | state = (gz_statep)file; | |
| 493 | /* check parameters and get internal structure */ | |
| 494 | if (file == NULL || buf == NULL || len < 1) | |
| 495 | return NULL; | |
| 496 | state = (gz_statep)file; | |
| 497 | 497 | |
| 498 | /* check that we're reading and that there's no (serious) error */ | |
| 499 | if (state->mode != GZ_READ || | |
| 500 | (state->err != Z_OK && state->err != Z_BUF_ERROR)) | |
| 501 | return NULL; | |
| 498 | /* check that we're reading and that there's no (serious) error */ | |
| 499 | if (state->mode != GZ_READ || | |
| 500 | (state->err != Z_OK && state->err != Z_BUF_ERROR)) | |
| 501 | return NULL; | |
| 502 | 502 | |
| 503 | /* process a skip request */ | |
| 504 | if (state->seek) { | |
| 505 | state->seek = 0; | |
| 506 | if (gz_skip(state, state->skip) == -1) | |
| 507 | return NULL; | |
| 508 | } | |
| 503 | /* process a skip request */ | |
| 504 | if (state->seek) { | |
| 505 | state->seek = 0; | |
| 506 | if (gz_skip(state, state->skip) == -1) | |
| 507 | return NULL; | |
| 508 | } | |
| 509 | 509 | |
| 510 | /* copy output bytes up to new line or len - 1, whichever comes first -- | |
| 511 | append a terminating zero to the string (we don't check for a zero in | |
| 512 | the contents, let the user worry about that) */ | |
| 513 | str = buf; | |
| 514 | left = (unsigned)len - 1; | |
| 515 | if (left) do { | |
| 516 | /* assure that something is in the output buffer */ | |
| 517 | if (state->x.have == 0 && gz_fetch(state) == -1) | |
| 518 | return NULL; /* error */ | |
| 519 | if (state->x.have == 0) { /* end of file */ | |
| 520 | state->past = 1; /* read past end */ | |
| 521 | break; /* return what we have */ | |
| 522 | } | |
| 510 | /* copy output bytes up to new line or len - 1, whichever comes first -- | |
| 511 | append a terminating zero to the string (we don't check for a zero in | |
| 512 | the contents, let the user worry about that) */ | |
| 513 | str = buf; | |
| 514 | left = (unsigned)len - 1; | |
| 515 | if (left) do { | |
| 516 | /* assure that something is in the output buffer */ | |
| 517 | if (state->x.have == 0 && gz_fetch(state) == -1) | |
| 518 | return NULL; /* error */ | |
| 519 | if (state->x.have == 0) { /* end of file */ | |
| 520 | state->past = 1; /* read past end */ | |
| 521 | break; /* return what we have */ | |
| 522 | } | |
| 523 | 523 | |
| 524 | /* look for end-of-line in current output buffer */ | |
| 525 | n = state->x.have > left ? left : state->x.have; | |
| 526 | eol = (unsigned char *)memchr(state->x.next, '\n', n); | |
| 527 | if (eol != NULL) | |
| 528 | n = (unsigned)(eol - state->x.next) + 1; | |
| 524 | /* look for end-of-line in current output buffer */ | |
| 525 | n = state->x.have > left ? left : state->x.have; | |
| 526 | eol = (unsigned char *)memchr(state->x.next, '\n', n); | |
| 527 | if (eol != NULL) | |
| 528 | n = (unsigned)(eol - state->x.next) + 1; | |
| 529 | 529 | |
| 530 | /* copy through end-of-line, or remainder if not found */ | |
| 531 | memcpy(buf, state->x.next, n); | |
| 532 | state->x.have -= n; | |
| 533 | state->x.next += n; | |
| 534 | state->x.pos += n; | |
| 535 | left -= n; | |
| 536 | buf += n; | |
| 537 | } while (left && eol == NULL); | |
| 530 | /* copy through end-of-line, or remainder if not found */ | |
| 531 | memcpy(buf, state->x.next, n); | |
| 532 | state->x.have -= n; | |
| 533 | state->x.next += n; | |
| 534 | state->x.pos += n; | |
| 535 | left -= n; | |
| 536 | buf += n; | |
| 537 | } while (left && eol == NULL); | |
| 538 | 538 | |
| 539 | /* return terminated string, or if nothing, end of file */ | |
| 540 | if (buf == str) | |
| 541 | return NULL; | |
| 542 | buf[0] = 0; | |
| 543 | return str; | |
| 539 | /* return terminated string, or if nothing, end of file */ | |
| 540 | if (buf == str) | |
| 541 | return NULL; | |
| 542 | buf[0] = 0; | |
| 543 | return str; | |
| 544 | 544 | } |
| 545 | 545 | |
| 546 | 546 | /* -- see zlib.h -- */ |
| 547 | 547 | int ZEXPORT gzdirect(file) |
| 548 | ||
| 548 | gzFile file; | |
| 549 | 549 | { |
| 550 | ||
| 550 | gz_statep state; | |
| 551 | 551 | |
| 552 | /* get internal structure */ | |
| 553 | if (file == NULL) | |
| 554 | return 0; | |
| 555 | state = (gz_statep)file; | |
| 552 | /* get internal structure */ | |
| 553 | if (file == NULL) | |
| 554 | return 0; | |
| 555 | state = (gz_statep)file; | |
| 556 | 556 | |
| 557 | /* if the state is not known, but we can find out, then do so (this is | |
| 558 | mainly for right after a gzopen() or gzdopen()) */ | |
| 559 | if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) | |
| 560 | (void)gz_look(state); | |
| 557 | /* if the state is not known, but we can find out, then do so (this is | |
| 558 | mainly for right after a gzopen() or gzdopen()) */ | |
| 559 | if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) | |
| 560 | (void)gz_look(state); | |
| 561 | 561 | |
| 562 | /* return 1 if transparent, 0 if processing a gzip stream */ | |
| 563 | return state->direct; | |
| 562 | /* return 1 if transparent, 0 if processing a gzip stream */ | |
| 563 | return state->direct; | |
| 564 | 564 | } |
| 565 | 565 | |
| 566 | 566 | /* -- see zlib.h -- */ |
| 567 | 567 | int ZEXPORT gzclose_r(file) |
| 568 | ||
| 568 | gzFile file; | |
| 569 | 569 | { |
| 570 | int ret, err; | |
| 571 | gz_statep state; | |
| 570 | int ret, err; | |
| 571 | gz_statep state; | |
| 572 | 572 | |
| 573 | /* get internal structure */ | |
| 574 | if (file == NULL) | |
| 575 | return Z_STREAM_ERROR; | |
| 576 | state = (gz_statep)file; | |
| 573 | /* get internal structure */ | |
| 574 | if (file == NULL) | |
| 575 | return Z_STREAM_ERROR; | |
| 576 | state = (gz_statep)file; | |
| 577 | 577 | |
| 578 | /* check that we're reading */ | |
| 579 | if (state->mode != GZ_READ) | |
| 580 | return Z_STREAM_ERROR; | |
| 578 | /* check that we're reading */ | |
| 579 | if (state->mode != GZ_READ) | |
| 580 | return Z_STREAM_ERROR; | |
| 581 | 581 | |
| 582 | /* free memory and close file */ | |
| 583 | if (state->size) { | |
| 584 | inflateEnd(&(state->strm)); | |
| 585 | free(state->out); | |
| 586 | free(state->in); | |
| 587 | } | |
| 588 | err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK; | |
| 589 | gz_error(state, Z_OK, NULL); | |
| 590 | free(state->path); | |
| 591 | ret = close(state->fd); | |
| 592 | free(state); | |
| 593 | return ret ? Z_ERRNO : err; | |
| 582 | /* free memory and close file */ | |
| 583 | if (state->size) { | |
| 584 | inflateEnd(&(state->strm)); | |
| 585 | free(state->out); | |
| 586 | free(state->in); | |
| 587 | } | |
| 588 | err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK; | |
| 589 | gz_error(state, Z_OK, NULL); | |
| 590 | free(state->path); | |
| 591 | ret = close(state->fd); | |
| 592 | free(state); | |
| 593 | return ret ? Z_ERRNO : err; | |
| 594 | 594 | } |
| r25360 | r25361 | |
|---|---|---|
| 30 | 30 | #endif |
| 31 | 31 | |
| 32 | 32 | #ifdef Z_SOLO |
| 33 | ||
| 33 | typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ | |
| 34 | 34 | #endif |
| 35 | 35 | |
| 36 | 36 | #ifndef local |
| r25360 | r25361 | |
| 50 | 50 | #define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] |
| 51 | 51 | |
| 52 | 52 | #define ERR_RETURN(strm,err) \ |
| 53 | ||
| 53 | return (strm->msg = ERR_MSG(err), (err)) | |
| 54 | 54 | /* To be used only when the state is known to be valid */ |
| 55 | 55 | |
| 56 | ||
| 56 | /* common constants */ | |
| 57 | 57 | |
| 58 | 58 | #ifndef DEF_WBITS |
| 59 | 59 | # define DEF_WBITS MAX_WBITS |
| r25360 | r25361 | |
| 78 | 78 | |
| 79 | 79 | #define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ |
| 80 | 80 | |
| 81 | ||
| 81 | /* target dependencies */ | |
| 82 | 82 | |
| 83 | 83 | #if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) |
| 84 | 84 | # define OS_CODE 0x00 |
| 85 | 85 | # ifndef Z_SOLO |
| 86 | 86 | # if defined(__TURBOC__) || defined(__BORLANDC__) |
| 87 | 87 | # if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) |
| 88 | /* Allow compilation with ANSI keywords only enabled */ | |
| 89 | void _Cdecl farfree( void *block ); | |
| 90 | void *_Cdecl farmalloc( unsigned long nbytes ); | |
| 88 | /* Allow compilation with ANSI keywords only enabled */ | |
| 89 | void _Cdecl farfree( void *block ); | |
| 90 | void *_Cdecl farmalloc( unsigned long nbytes ); | |
| 91 | 91 | # else |
| 92 | 92 | # include <alloc.h> |
| 93 | 93 | # endif |
| r25360 | r25361 | |
| 104 | 104 | #if defined(VAXC) || defined(VMS) |
| 105 | 105 | # define OS_CODE 0x02 |
| 106 | 106 | # define F_OPEN(name, mode) \ |
| 107 | ||
| 107 | fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") | |
| 108 | 108 | #endif |
| 109 | 109 | |
| 110 | 110 | #if defined(ATARI) || defined(atarist) |
| r25360 | r25361 | |
| 153 | 153 | # if defined(_WIN32_WCE) |
| 154 | 154 | # define fdopen(fd,mode) NULL /* No fdopen() */ |
| 155 | 155 | # ifndef _PTRDIFF_T_DEFINED |
| 156 | ||
| 156 | typedef int ptrdiff_t; | |
| 157 | 157 | # define _PTRDIFF_T_DEFINED |
| 158 | 158 | # endif |
| 159 | 159 | # else |
| r25360 | r25361 | |
| 162 | 162 | #endif |
| 163 | 163 | |
| 164 | 164 | #if defined(__BORLANDC__) && !defined(MSDOS) |
| 165 | #pragma warn -8004 | |
| 166 | #pragma warn -8008 | |
| 167 | #pragma warn -8066 | |
| 165 | #pragma warn -8004 | |
| 166 | #pragma warn -8008 | |
| 167 | #pragma warn -8066 | |
| 168 | 168 | #endif |
| 169 | 169 | |
| 170 | 170 | /* provide prototypes for these when building zlib without LFS */ |
| 171 | 171 | #if !defined(_WIN32) && \ |
| 172 | (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) | |
| 173 | ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); | |
| 174 | ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); | |
| 172 | (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) | |
| 173 | ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); | |
| 174 | ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); | |
| 175 | 175 | #endif |
| 176 | 176 | |
| 177 | ||
| 177 | /* common defaults */ | |
| 178 | 178 | |
| 179 | 179 | #ifndef OS_CODE |
| 180 | 180 | # define OS_CODE 0x03 /* assume Unix */ |
| r25360 | r25361 | |
| 184 | 184 | # define F_OPEN(name, mode) fopen((name), (mode)) |
| 185 | 185 | #endif |
| 186 | 186 | |
| 187 | ||
| 187 | /* functions */ | |
| 188 | 188 | |
| 189 | 189 | #if defined(pyr) || defined(Z_SOLO) |
| 190 | 190 | # define NO_MEMCPY |
| 191 | 191 | #endif |
| 192 | 192 | #if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) |
| 193 | /* Use our own functions for small and medium model with MSC <= 5.0. | |
| 194 | * You may have to use the same strategy for Borland C (untested). | |
| 195 | * The __SC__ check is for Symantec. | |
| 196 | */ | |
| 193 | /* Use our own functions for small and medium model with MSC <= 5.0. | |
| 194 | * You may have to use the same strategy for Borland C (untested). | |
| 195 | * The __SC__ check is for Symantec. | |
| 196 | */ | |
| 197 | 197 | # define NO_MEMCPY |
| 198 | 198 | #endif |
| 199 | 199 | #if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) |
| r25360 | r25361 | |
| 210 | 210 | # define zmemzero(dest, len) memset(dest, 0, len) |
| 211 | 211 | # endif |
| 212 | 212 | #else |
| 213 | void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); | |
| 214 | int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); | |
| 215 | void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); | |
| 213 | void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); | |
| 214 | int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); | |
| 215 | void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); | |
| 216 | 216 | #endif |
| 217 | 217 | |
| 218 | 218 | /* Diagnostic functions */ |
| 219 | 219 | #ifdef DEBUG |
| 220 | 220 | # include <stdio.h> |
| 221 | extern int ZLIB_INTERNAL z_verbose; | |
| 222 | extern void ZLIB_INTERNAL z_error OF((char *m)); | |
| 221 | extern int ZLIB_INTERNAL z_verbose; | |
| 222 | extern void ZLIB_INTERNAL z_error OF((char *m)); | |
| 223 | 223 | # define Assert(cond,msg) {if(!(cond)) z_error(msg);} |
| 224 | 224 | # define Trace(x) {if (z_verbose>=0) fprintf x ;} |
| 225 | 225 | # define Tracev(x) {if (z_verbose>0) fprintf x ;} |
| r25360 | r25361 | |
| 236 | 236 | #endif |
| 237 | 237 | |
| 238 | 238 | #ifndef Z_SOLO |
| 239 | voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, | |
| 240 | unsigned size)); | |
| 241 | void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); | |
| 239 | voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, | |
| 240 | unsigned size)); | |
| 241 | void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); | |
| 242 | 242 | #endif |
| 243 | 243 | |
| 244 | 244 | #define ZALLOC(strm, items, size) \ |
| 245 | ||
| 245 | (*((strm)->zalloc))((strm)->opaque, (items), (size)) | |
| 246 | 246 | #define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) |
| 247 | 247 | #define TRY_FREE(s, p) {if (p) ZFREE(s, p);} |
| 248 | 248 | |
| 249 | 249 | /* Reverse the bytes in a 32-bit value */ |
| 250 | 250 | #define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ |
| 251 | ||
| 251 | (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) | |
| 252 | 252 | |
| 253 | 253 | #endif /* ZUTIL_H */ |
| r25360 | r25361 | |
|---|---|---|
| 37 | 37 | # define BYFOUR |
| 38 | 38 | #endif |
| 39 | 39 | #ifdef BYFOUR |
| 40 | local unsigned long crc32_little OF((unsigned long, | |
| 41 | const unsigned char FAR *, unsigned)); | |
| 42 | local unsigned long crc32_big OF((unsigned long, | |
| 43 | const unsigned char FAR *, unsigned)); | |
| 40 | local unsigned long crc32_little OF((unsigned long, | |
| 41 | const unsigned char FAR *, unsigned)); | |
| 42 | local unsigned long crc32_big OF((unsigned long, | |
| 43 | const unsigned char FAR *, unsigned)); | |
| 44 | 44 | # define TBLS 8 |
| 45 | 45 | #else |
| 46 | 46 | # define TBLS 1 |
| r25360 | r25361 | |
| 48 | 48 | |
| 49 | 49 | /* Local functions for crc concatenation */ |
| 50 | 50 | local unsigned long gf2_matrix_times OF((unsigned long *mat, |
| 51 | ||
| 51 | unsigned long vec)); | |
| 52 | 52 | local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); |
| 53 | 53 | local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2)); |
| 54 | 54 | |
| r25360 | r25361 | |
| 59 | 59 | local z_crc_t FAR crc_table[TBLS][256]; |
| 60 | 60 | local void make_crc_table OF((void)); |
| 61 | 61 | #ifdef MAKECRCH |
| 62 | ||
| 62 | local void write_table OF((FILE *, const z_crc_t FAR *)); | |
| 63 | 63 | #endif /* MAKECRCH */ |
| 64 | 64 | /* |
| 65 | 65 | Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: |
| r25360 | r25361 | |
| 89 | 89 | */ |
| 90 | 90 | local void make_crc_table() |
| 91 | 91 | { |
| 92 | z_crc_t c; | |
| 93 | int n, k; | |
| 94 | z_crc_t poly; /* polynomial exclusive-or pattern */ | |
| 95 | /* terms of polynomial defining this crc (except x^32): */ | |
| 96 | static volatile int first = 1; /* flag to limit concurrent making */ | |
| 97 | static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; | |
| 92 | z_crc_t c; | |
| 93 | int n, k; | |
| 94 | z_crc_t poly; /* polynomial exclusive-or pattern */ | |
| 95 | /* terms of polynomial defining this crc (except x^32): */ | |
| 96 | static volatile int first = 1; /* flag to limit concurrent making */ | |
| 97 | static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; | |
| 98 | 98 | |
| 99 | /* See if another task is already doing this (not thread-safe, but better | |
| 100 | than nothing -- significantly reduces duration of vulnerability in | |
| 101 | case the advice about DYNAMIC_CRC_TABLE is ignored) */ | |
| 102 | if (first) { | |
| 103 | first = 0; | |
| 99 | /* See if another task is already doing this (not thread-safe, but better | |
| 100 | than nothing -- significantly reduces duration of vulnerability in | |
| 101 | case the advice about DYNAMIC_CRC_TABLE is ignored) */ | |
| 102 | if (first) { | |
| 103 | first = 0; | |
| 104 | 104 | |
| 105 | /* make exclusive-or pattern from polynomial (0xedb88320UL) */ | |
| 106 | poly = 0; | |
| 107 | for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++) | |
| 108 | poly |= (z_crc_t)1 << (31 - p[n]); | |
| 105 | /* make exclusive-or pattern from polynomial (0xedb88320UL) */ | |
| 106 | poly = 0; | |
| 107 | for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++) | |
| 108 | poly |= (z_crc_t)1 << (31 - p[n]); | |
| 109 | 109 | |
| 110 | /* generate a crc for every 8-bit value */ | |
| 111 | for (n = 0; n < 256; n++) { | |
| 112 | c = (z_crc_t)n; | |
| 113 | for (k = 0; k < 8; k++) | |
| 114 | c = c & 1 ? poly ^ (c >> 1) : c >> 1; | |
| 115 | crc_table[0][n] = c; | |
| 116 | } | |
| 110 | /* generate a crc for every 8-bit value */ | |
| 111 | for (n = 0; n < 256; n++) { | |
| 112 | c = (z_crc_t)n; | |
| 113 | for (k = 0; k < 8; k++) | |
| 114 | c = c & 1 ? poly ^ (c >> 1) : c >> 1; | |
| 115 | crc_table[0][n] = c; | |
| 116 | } | |
| 117 | 117 | |
| 118 | 118 | #ifdef BYFOUR |
| 119 | /* generate crc for each value followed by one, two, and three zeros, | |
| 120 | and then the byte reversal of those as well as the first table */ | |
| 121 | for (n = 0; n < 256; n++) { | |
| 122 | c = crc_table[0][n]; | |
| 123 | crc_table[4][n] = ZSWAP32(c); | |
| 124 | for (k = 1; k < 4; k++) { | |
| 125 | c = crc_table[0][c & 0xff] ^ (c >> 8); | |
| 126 | crc_table[k][n] = c; | |
| 127 | crc_table[k + 4][n] = ZSWAP32(c); | |
| 128 | } | |
| 129 | } | |
| 119 | /* generate crc for each value followed by one, two, and three zeros, | |
| 120 | and then the byte reversal of those as well as the first table */ | |
| 121 | for (n = 0; n < 256; n++) { | |
| 122 | c = crc_table[0][n]; | |
| 123 | crc_table[4][n] = ZSWAP32(c); | |
| 124 | for (k = 1; k < 4; k++) { | |
| 125 | c = crc_table[0][c & 0xff] ^ (c >> 8); | |
| 126 | crc_table[k][n] = c; | |
| 127 | crc_table[k + 4][n] = ZSWAP32(c); | |
| 128 | } | |
| 129 | } | |
| 130 | 130 | #endif /* BYFOUR */ |
| 131 | 131 | |
| 132 | crc_table_empty = 0; | |
| 133 | } | |
| 134 | else { /* not first */ | |
| 135 | /* wait for the other guy to finish (not efficient, but rare) */ | |
| 136 | while (crc_table_empty) | |
| 137 | ; | |
| 138 | } | |
| 132 | crc_table_empty = 0; | |
| 133 | } | |
| 134 | else { /* not first */ | |
| 135 | /* wait for the other guy to finish (not efficient, but rare) */ | |
| 136 | while (crc_table_empty) | |
| 137 | ; | |
| 138 | } | |
| 139 | 139 | |
| 140 | 140 | #ifdef MAKECRCH |
| 141 | /* write out CRC tables to crc32.h */ | |
| 142 | { | |
| 143 | FILE *out; | |
| 141 | /* write out CRC tables to crc32.h */ | |
| 142 | { | |
| 143 | FILE *out; | |
| 144 | 144 | |
| 145 | out = fopen("crc32.h", "w"); | |
| 146 | if (out == NULL) return; | |
| 147 | fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); | |
| 148 | fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); | |
| 149 | fprintf(out, "local const z_crc_t FAR "); | |
| 150 | fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); | |
| 151 | write_table(out, crc_table[0]); | |
| 145 | out = fopen("crc32.h", "w"); | |
| 146 | if (out == NULL) return; | |
| 147 | fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); | |
| 148 | fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); | |
| 149 | fprintf(out, "local const z_crc_t FAR "); | |
| 150 | fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); | |
| 151 | write_table(out, crc_table[0]); | |
| 152 | 152 | # ifdef BYFOUR |
| 153 | fprintf(out, "#ifdef BYFOUR\n"); | |
| 154 | for (k = 1; k < 8; k++) { | |
| 155 | fprintf(out, " },\n {\n"); | |
| 156 | write_table(out, crc_table[k]); | |
| 157 | } | |
| 158 | fprintf(out, "#endif\n"); | |
| 153 | fprintf(out, "#ifdef BYFOUR\n"); | |
| 154 | for (k = 1; k < 8; k++) { | |
| 155 | fprintf(out, " },\n {\n"); | |
| 156 | write_table(out, crc_table[k]); | |
| 157 | } | |
| 158 | fprintf(out, "#endif\n"); | |
| 159 | 159 | # endif /* BYFOUR */ |
| 160 | fprintf(out, " }\n};\n"); | |
| 161 | fclose(out); | |
| 162 | } | |
| 160 | fprintf(out, " }\n};\n"); | |
| 161 | fclose(out); | |
| 162 | } | |
| 163 | 163 | #endif /* MAKECRCH */ |
| 164 | 164 | } |
| 165 | 165 | |
| 166 | 166 | #ifdef MAKECRCH |
| 167 | 167 | local void write_table(out, table) |
| 168 | FILE *out; | |
| 169 | const z_crc_t FAR *table; | |
| 168 | FILE *out; | |
| 169 | const z_crc_t FAR *table; | |
| 170 | 170 | { |
| 171 | ||
| 171 | int n; | |
| 172 | 172 | |
| 173 | for (n = 0; n < 256; n++) | |
| 174 | fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", | |
| 175 | (unsigned long)(table[n]), | |
| 176 | n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); | |
| 173 | for (n = 0; n < 256; n++) | |
| 174 | fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", | |
| 175 | (unsigned long)(table[n]), | |
| 176 | n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); | |
| 177 | 177 | } |
| 178 | 178 | #endif /* MAKECRCH */ |
| 179 | 179 | |
| r25360 | r25361 | |
| 190 | 190 | const z_crc_t FAR * ZEXPORT get_crc_table() |
| 191 | 191 | { |
| 192 | 192 | #ifdef DYNAMIC_CRC_TABLE |
| 193 | if (crc_table_empty) | |
| 194 | make_crc_table(); | |
| 193 | if (crc_table_empty) | |
| 194 | make_crc_table(); | |
| 195 | 195 | #endif /* DYNAMIC_CRC_TABLE */ |
| 196 | ||
| 196 | return (const z_crc_t FAR *)crc_table; | |
| 197 | 197 | } |
| 198 | 198 | |
| 199 | 199 | /* ========================================================================= */ |
| r25360 | r25361 | |
| 202 | 202 | |
| 203 | 203 | /* ========================================================================= */ |
| 204 | 204 | unsigned long ZEXPORT crc32(crc, buf, len) |
| 205 | unsigned long crc; | |
| 206 | const unsigned char FAR *buf; | |
| 207 | uInt len; | |
| 205 | unsigned long crc; | |
| 206 | const unsigned char FAR *buf; | |
| 207 | uInt len; | |
| 208 | 208 | { |
| 209 | ||
| 209 | if (buf == Z_NULL) return 0UL; | |
| 210 | 210 | |
| 211 | 211 | #ifdef DYNAMIC_CRC_TABLE |
| 212 | if (crc_table_empty) | |
| 213 | make_crc_table(); | |
| 212 | if (crc_table_empty) | |
| 213 | make_crc_table(); | |
| 214 | 214 | #endif /* DYNAMIC_CRC_TABLE */ |
| 215 | 215 | |
| 216 | 216 | #ifdef BYFOUR |
| 217 | if (sizeof(void *) == sizeof(ptrdiff_t)) { | |
| 218 | z_crc_t endian; | |
| 217 | if (sizeof(void *) == sizeof(ptrdiff_t)) { | |
| 218 | z_crc_t endian; | |
| 219 | 219 | |
| 220 | endian = 1; | |
| 221 | if (*((unsigned char *)(&endian))) | |
| 222 | return crc32_little(crc, buf, len); | |
| 223 | else | |
| 224 | return crc32_big(crc, buf, len); | |
| 225 | } | |
| 220 | endian = 1; | |
| 221 | if (*((unsigned char *)(&endian))) | |
| 222 | return crc32_little(crc, buf, len); | |
| 223 | else | |
| 224 | return crc32_big(crc, buf, len); | |
| 225 | } | |
| 226 | 226 | #endif /* BYFOUR */ |
| 227 | crc = crc ^ 0xffffffffUL; | |
| 228 | while (len >= 8) { | |
| 229 | DO8; | |
| 230 | len -= 8; | |
| 231 | } | |
| 232 | if (len) do { | |
| 233 | DO1; | |
| 234 | } while (--len); | |
| 235 | return crc ^ 0xffffffffUL; | |
| 227 | crc = crc ^ 0xffffffffUL; | |
| 228 | while (len >= 8) { | |
| 229 | DO8; | |
| 230 | len -= 8; | |
| 231 | } | |
| 232 | if (len) do { | |
| 233 | DO1; | |
| 234 | } while (--len); | |
| 235 | return crc ^ 0xffffffffUL; | |
| 236 | 236 | } |
| 237 | 237 | |
| 238 | 238 | #ifdef BYFOUR |
| 239 | 239 | |
| 240 | 240 | /* ========================================================================= */ |
| 241 | 241 | #define DOLIT4 c ^= *buf4++; \ |
| 242 | c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ | |
| 243 | crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] | |
| 242 | c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ | |
| 243 | crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] | |
| 244 | 244 | #define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 |
| 245 | 245 | |
| 246 | 246 | /* ========================================================================= */ |
| 247 | 247 | local unsigned long crc32_little(crc, buf, len) |
| 248 | unsigned long crc; | |
| 249 | const unsigned char FAR *buf; | |
| 250 | unsigned len; | |
| 248 | unsigned long crc; | |
| 249 | const unsigned char FAR *buf; | |
| 250 | unsigned len; | |
| 251 | 251 | { |
| 252 | register z_crc_t c; | |
| 253 | register const z_crc_t FAR *buf4; | |
| 252 | register z_crc_t c; | |
| 253 | register const z_crc_t FAR *buf4; | |
| 254 | 254 | |
| 255 | c = (z_crc_t)crc; | |
| 256 | c = ~c; | |
| 257 | while (len && ((ptrdiff_t)buf & 3)) { | |
| 258 | c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); | |
| 259 | len--; | |
| 260 | } | |
| 255 | c = (z_crc_t)crc; | |
| 256 | c = ~c; | |
| 257 | while (len && ((ptrdiff_t)buf & 3)) { | |
| 258 | c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); | |
| 259 | len--; | |
| 260 | } | |
| 261 | 261 | |
| 262 | buf4 = (const z_crc_t FAR *)(const void FAR *)buf; | |
| 263 | while (len >= 32) { | |
| 264 | DOLIT32; | |
| 265 | len -= 32; | |
| 266 | } | |
| 267 | while (len >= 4) { | |
| 268 | DOLIT4; | |
| 269 | len -= 4; | |
| 270 | } | |
| 271 | buf = (const unsigned char FAR *)buf4; | |
| 262 | buf4 = (const z_crc_t FAR *)(const void FAR *)buf; | |
| 263 | while (len >= 32) { | |
| 264 | DOLIT32; | |
| 265 | len -= 32; | |
| 266 | } | |
| 267 | while (len >= 4) { | |
| 268 | DOLIT4; | |
| 269 | len -= 4; | |
| 270 | } | |
| 271 | buf = (const unsigned char FAR *)buf4; | |
| 272 | 272 | |
| 273 | if (len) do { | |
| 274 | c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); | |
| 275 | } while (--len); | |
| 276 | c = ~c; | |
| 277 | return (unsigned long)c; | |
| 273 | if (len) do { | |
| 274 | c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); | |
| 275 | } while (--len); | |
| 276 | c = ~c; | |
| 277 | return (unsigned long)c; | |
| 278 | 278 | } |
| 279 | 279 | |
| 280 | 280 | /* ========================================================================= */ |
| 281 | 281 | #define DOBIG4 c ^= *++buf4; \ |
| 282 | c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ | |
| 283 | crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] | |
| 282 | c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ | |
| 283 | crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] | |
| 284 | 284 | #define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 |
| 285 | 285 | |
| 286 | 286 | /* ========================================================================= */ |
| 287 | 287 | local unsigned long crc32_big(crc, buf, len) |
| 288 | unsigned long crc; | |
| 289 | const unsigned char FAR *buf; | |
| 290 | unsigned len; | |
| 288 | unsigned long crc; | |
| 289 | const unsigned char FAR *buf; | |
| 290 | unsigned len; | |
| 291 | 291 | { |
| 292 | register z_crc_t c; | |
| 293 | register const z_crc_t FAR *buf4; | |
| 292 | register z_crc_t c; | |
| 293 | register const z_crc_t FAR *buf4; | |
| 294 | 294 | |
| 295 | c = ZSWAP32((z_crc_t)crc); | |
| 296 | c = ~c; | |
| 297 | while (len && ((ptrdiff_t)buf & 3)) { | |
| 298 | c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); | |
| 299 | len--; | |
| 300 | } | |
| 295 | c = ZSWAP32((z_crc_t)crc); | |
| 296 | c = ~c; | |
| 297 | while (len && ((ptrdiff_t)buf & 3)) { | |
| 298 | c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); | |
| 299 | len--; | |
| 300 | } | |
| 301 | 301 | |
| 302 | buf4 = (const z_crc_t FAR *)(const void FAR *)buf; | |
| 303 | buf4--; | |
| 304 | while (len >= 32) { | |
| 305 | DOBIG32; | |
| 306 | len -= 32; | |
| 307 | } | |
| 308 | while (len >= 4) { | |
| 309 | DOBIG4; | |
| 310 | len -= 4; | |
| 311 | } | |
| 312 | buf4++; | |
| 313 | buf = (const unsigned char FAR *)buf4; | |
| 302 | buf4 = (const z_crc_t FAR *)(const void FAR *)buf; | |
| 303 | buf4--; | |
| 304 | while (len >= 32) { | |
| 305 | DOBIG32; | |
| 306 | len -= 32; | |
| 307 | } | |
| 308 | while (len >= 4) { | |
| 309 | DOBIG4; | |
| 310 | len -= 4; | |
| 311 | } | |
| 312 | buf4++; | |
| 313 | buf = (const unsigned char FAR *)buf4; | |
| 314 | 314 | |
| 315 | if (len) do { | |
| 316 | c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); | |
| 317 | } while (--len); | |
| 318 | c = ~c; | |
| 319 | return (unsigned long)(ZSWAP32(c)); | |
| 315 | if (len) do { | |
| 316 | c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); | |
| 317 | } while (--len); | |
| 318 | c = ~c; | |
| 319 | return (unsigned long)(ZSWAP32(c)); | |
| 320 | 320 | } |
| 321 | 321 | |
| 322 | 322 | #endif /* BYFOUR */ |
| r25360 | r25361 | |
| 325 | 325 | |
| 326 | 326 | /* ========================================================================= */ |
| 327 | 327 | local unsigned long gf2_matrix_times(mat, vec) |
| 328 | unsigned long *mat; | |
| 329 | unsigned long vec; | |
| 328 | unsigned long *mat; | |
| 329 | unsigned long vec; | |
| 330 | 330 | { |
| 331 | ||
| 331 | unsigned long sum; | |
| 332 | 332 | |
| 333 | sum = 0; | |
| 334 | while (vec) { | |
| 335 | if (vec & 1) | |
| 336 | sum ^= *mat; | |
| 337 | vec >>= 1; | |
| 338 | mat++; | |
| 339 | } | |
| 340 | return sum; | |
| 333 | sum = 0; | |
| 334 | while (vec) { | |
| 335 | if (vec & 1) | |
| 336 | sum ^= *mat; | |
| 337 | vec >>= 1; | |
| 338 | mat++; | |
| 339 | } | |
| 340 | return sum; | |
| 341 | 341 | } |
| 342 | 342 | |
| 343 | 343 | /* ========================================================================= */ |
| 344 | 344 | local void gf2_matrix_square(square, mat) |
| 345 | unsigned long *square; | |
| 346 | unsigned long *mat; | |
| 345 | unsigned long *square; | |
| 346 | unsigned long *mat; | |
| 347 | 347 | { |
| 348 | ||
| 348 | int n; | |
| 349 | 349 | |
| 350 | for (n = 0; n < GF2_DIM; n++) | |
| 351 | square[n] = gf2_matrix_times(mat, mat[n]); | |
| 350 | for (n = 0; n < GF2_DIM; n++) | |
| 351 | square[n] = gf2_matrix_times(mat, mat[n]); | |
| 352 | 352 | } |
| 353 | 353 | |
| 354 | 354 | /* ========================================================================= */ |
| 355 | 355 | local uLong crc32_combine_(crc1, crc2, len2) |
| 356 | uLong crc1; | |
| 357 | uLong crc2; | |
| 358 | z_off64_t len2; | |
| 356 | uLong crc1; | |
| 357 | uLong crc2; | |
| 358 | z_off64_t len2; | |
| 359 | 359 | { |
| 360 | int n; | |
| 361 | unsigned long row; | |
| 362 | unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ | |
| 363 | unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ | |
| 360 | int n; | |
| 361 | unsigned long row; | |
| 362 | unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ | |
| 363 | unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ | |
| 364 | 364 | |
| 365 | /* degenerate case (also disallow negative lengths) */ | |
| 366 | if (len2 <= 0) | |
| 367 | return crc1; | |
| 365 | /* degenerate case (also disallow negative lengths) */ | |
| 366 | if (len2 <= 0) | |
| 367 | return crc1; | |
| 368 | 368 | |
| 369 | /* put operator for one zero bit in odd */ | |
| 370 | odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ | |
| 371 | row = 1; | |
| 372 | for (n = 1; n < GF2_DIM; n++) { | |
| 373 | odd[n] = row; | |
| 374 | row <<= 1; | |
| 375 | } | |
| 369 | /* put operator for one zero bit in odd */ | |
| 370 | odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ | |
| 371 | row = 1; | |
| 372 | for (n = 1; n < GF2_DIM; n++) { | |
| 373 | odd[n] = row; | |
| 374 | row <<= 1; | |
| 375 | } | |
| 376 | 376 | |
| 377 | /* put operator for two zero bits in even */ | |
| 378 | gf2_matrix_square(even, odd); | |
| 377 | /* put operator for two zero bits in even */ | |
| 378 | gf2_matrix_square(even, odd); | |
| 379 | 379 | |
| 380 | /* put operator for four zero bits in odd */ | |
| 381 | gf2_matrix_square(odd, even); | |
| 380 | /* put operator for four zero bits in odd */ | |
| 381 | gf2_matrix_square(odd, even); | |
| 382 | 382 | |
| 383 | /* apply len2 zeros to crc1 (first square will put the operator for one | |
| 384 | zero byte, eight zero bits, in even) */ | |
| 385 | do { | |
| 386 | /* apply zeros operator for this bit of len2 */ | |
| 387 | gf2_matrix_square(even, odd); | |
| 388 | if (len2 & 1) | |
| 389 | crc1 = gf2_matrix_times(even, crc1); | |
| 390 | len2 >>= 1; | |
| 383 | /* apply len2 zeros to crc1 (first square will put the operator for one | |
| 384 | zero byte, eight zero bits, in even) */ | |
| 385 | do { | |
| 386 | /* apply zeros operator for this bit of len2 */ | |
| 387 | gf2_matrix_square(even, odd); | |
| 388 | if (len2 & 1) | |
| 389 | crc1 = gf2_matrix_times(even, crc1); | |
| 390 | len2 >>= 1; | |
| 391 | 391 | |
| 392 | /* if no more bits set, then done */ | |
| 393 | if (len2 == 0) | |
| 394 | break; | |
| 392 | /* if no more bits set, then done */ | |
| 393 | if (len2 == 0) | |
| 394 | break; | |
| 395 | 395 | |
| 396 | /* another iteration of the loop with odd and even swapped */ | |
| 397 | gf2_matrix_square(odd, even); | |
| 398 | if (len2 & 1) | |
| 399 | crc1 = gf2_matrix_times(odd, crc1); | |
| 400 | len2 >>= 1; | |
| 396 | /* another iteration of the loop with odd and even swapped */ | |
| 397 | gf2_matrix_square(odd, even); | |
| 398 | if (len2 & 1) | |
| 399 | crc1 = gf2_matrix_times(odd, crc1); | |
| 400 | len2 >>= 1; | |
| 401 | 401 | |
| 402 | /* if no more bits set, then done */ | |
| 403 | } while (len2 != 0); | |
| 402 | /* if no more bits set, then done */ | |
| 403 | } while (len2 != 0); | |
| 404 | 404 | |
| 405 | /* return combined crc */ | |
| 406 | crc1 ^= crc2; | |
| 407 | return crc1; | |
| 405 | /* return combined crc */ | |
| 406 | crc1 ^= crc2; | |
| 407 | return crc1; | |
| 408 | 408 | } |
| 409 | 409 | |
| 410 | 410 | /* ========================================================================= */ |
| 411 | 411 | uLong ZEXPORT crc32_combine(crc1, crc2, len2) |
| 412 | uLong crc1; | |
| 413 | uLong crc2; | |
| 414 | z_off_t len2; | |
| 412 | uLong crc1; | |
| 413 | uLong crc2; | |
| 414 | z_off_t len2; | |
| 415 | 415 | { |
| 416 | ||
| 416 | return crc32_combine_(crc1, crc2, len2); | |
| 417 | 417 | } |
| 418 | 418 | |
| 419 | 419 | uLong ZEXPORT crc32_combine64(crc1, crc2, len2) |
| 420 | uLong crc1; | |
| 421 | uLong crc2; | |
| 422 | z_off64_t len2; | |
| 420 | uLong crc1; | |
| 421 | uLong crc2; | |
| 422 | z_off64_t len2; | |
| 423 | 423 | { |
| 424 | ||
| 424 | return crc32_combine_(crc1, crc2, len2); | |
| 425 | 425 | } |
| r25360 | r25361 | |
|---|---|---|
| 9 | 9 | #define MAXBITS 15 |
| 10 | 10 | |
| 11 | 11 | const char inflate_copyright[] = |
| 12 | ||
| 12 | " inflate 1.2.8 Copyright 1995-2013 Mark Adler "; | |
| 13 | 13 | /* |
| 14 | 14 | If you use the zlib library in a product, an acknowledgment is welcome |
| 15 | 15 | in the documentation of your product. If for some reason you cannot |
| r25360 | r25361 | |
| 37 | 37 | unsigned FAR *bits; |
| 38 | 38 | unsigned short FAR *work; |
| 39 | 39 | { |
| 40 | unsigned len; /* a code's length in bits */ | |
| 41 | unsigned sym; /* index of code symbols */ | |
| 42 | unsigned min, max; /* minimum and maximum code lengths */ | |
| 43 | unsigned root; /* number of index bits for root table */ | |
| 44 | unsigned curr; /* number of index bits for current table */ | |
| 45 | unsigned drop; /* code bits to drop for sub-table */ | |
| 46 | int left; /* number of prefix codes available */ | |
| 47 | unsigned used; /* code entries in table used */ | |
| 48 | unsigned huff; /* Huffman code */ | |
| 49 | unsigned incr; /* for incrementing code, index */ | |
| 50 | unsigned fill; /* index for replicating entries */ | |
| 51 | unsigned low; /* low bits for current root entry */ | |
| 52 | unsigned mask; /* mask for low root bits */ | |
| 53 | code here; /* table entry for duplication */ | |
| 54 | code FAR *next; /* next available space in table */ | |
| 55 | const unsigned short FAR *base; /* base value table to use */ | |
| 56 | const unsigned short FAR *extra; /* extra bits table to use */ | |
| 57 | int end; /* use base and extra for symbol > end */ | |
| 58 | unsigned short count[MAXBITS+1]; /* number of codes of each length */ | |
| 59 | unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ | |
| 60 | static const unsigned short lbase[31] = { /* Length codes 257..285 base */ | |
| 61 | 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, | |
| 62 | 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; | |
| 63 | static const unsigned short lext[31] = { /* Length codes 257..285 extra */ | |
| 64 | 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, | |
| 65 | 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78}; | |
| 66 | static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ | |
| 67 | 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, | |
| 68 | 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, | |
| 69 | 8193, 12289, 16385, 24577, 0, 0}; | |
| 70 | static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ | |
| 71 | 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, | |
| 72 | 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, | |
| 73 | 28, 28, 29, 29, 64, 64}; | |
| 40 | unsigned len; /* a code's length in bits */ | |
| 41 | unsigned sym; /* index of code symbols */ | |
| 42 | unsigned min, max; /* minimum and maximum code lengths */ | |
| 43 | unsigned root; /* number of index bits for root table */ | |
| 44 | unsigned curr; /* number of index bits for current table */ | |
| 45 | unsigned drop; /* code bits to drop for sub-table */ | |
| 46 | int left; /* number of prefix codes available */ | |
| 47 | unsigned used; /* code entries in table used */ | |
| 48 | unsigned huff; /* Huffman code */ | |
| 49 | unsigned incr; /* for incrementing code, index */ | |
| 50 | unsigned fill; /* index for replicating entries */ | |
| 51 | unsigned low; /* low bits for current root entry */ | |
| 52 | unsigned mask; /* mask for low root bits */ | |
| 53 | code here; /* table entry for duplication */ | |
| 54 | code FAR *next; /* next available space in table */ | |
| 55 | const unsigned short FAR *base; /* base value table to use */ | |
| 56 | const unsigned short FAR *extra; /* extra bits table to use */ | |
| 57 | int end; /* use base and extra for symbol > end */ | |
| 58 | unsigned short count[MAXBITS+1]; /* number of codes of each length */ | |
| 59 | unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ | |
| 60 | static const unsigned short lbase[31] = { /* Length codes 257..285 base */ | |
| 61 | 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, | |
| 62 | 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; | |
| 63 | static const unsigned short lext[31] = { /* Length codes 257..285 extra */ | |
| 64 | 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, | |
| 65 | 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78}; | |
| 66 | static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ | |
| 67 | 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, | |
| 68 | 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, | |
| 69 | 8193, 12289, 16385, 24577, 0, 0}; | |
| 70 | static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ | |
| 71 | 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, | |
| 72 | 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, | |
| 73 | 28, 28, 29, 29, 64, 64}; | |
| 74 | 74 | |
| 75 | /* | |
| 76 | Process a set of code lengths to create a canonical Huffman code. The | |
| 77 | code lengths are lens[0..codes-1]. Each length corresponds to the | |
| 78 | symbols 0..codes-1. The Huffman code is generated by first sorting the | |
| 79 | symbols by length from short to long, and retaining the symbol order | |
| 80 | for codes with equal lengths. Then the code starts with all zero bits | |
| 81 | for the first code of the shortest length, and the codes are integer | |
| 82 | increments for the same length, and zeros are appended as the length | |
| 83 | increases. For the deflate format, these bits are stored backwards | |
| 84 | from their more natural integer increment ordering, and so when the | |
| 85 | decoding tables are built in the large loop below, the integer codes | |
| 86 | are incremented backwards. | |
| 75 | /* | |
| 76 | Process a set of code lengths to create a canonical Huffman code. The | |
| 77 | code lengths are lens[0..codes-1]. Each length corresponds to the | |
| 78 | symbols 0..codes-1. The Huffman code is generated by first sorting the | |
| 79 | symbols by length from short to long, and retaining the symbol order | |
| 80 | for codes with equal lengths. Then the code starts with all zero bits | |
| 81 | for the first code of the shortest length, and the codes are integer | |
| 82 | increments for the same length, and zeros are appended as the length | |
| 83 | increases. For the deflate format, these bits are stored backwards | |
| 84 | from their more natural integer increment ordering, and so when the | |
| 85 | decoding tables are built in the large loop below, the integer codes | |
| 86 | are incremented backwards. | |
| 87 | 87 | |
| 88 | This routine assumes, but does not check, that all of the entries in | |
| 89 | lens[] are in the range 0..MAXBITS. The caller must assure this. | |
| 90 | 1..MAXBITS is interpreted as that code length. zero means that that | |
| 91 | symbol does not occur in this code. | |
| 88 | This routine assumes, but does not check, that all of the entries in | |
| 89 | lens[] are in the range 0..MAXBITS. The caller must assure this. | |
| 90 | 1..MAXBITS is interpreted as that code length. zero means that that | |
| 91 | symbol does not occur in this code. | |
| 92 | 92 | |
| 93 | The codes are sorted by computing a count of codes for each length, | |
| 94 | creating from that a table of starting indices for each length in the | |
| 95 | sorted table, and then entering the symbols in order in the sorted | |
| 96 | table. The sorted table is work[], with that space being provided by | |
| 97 | the caller. | |
| 93 | The codes are sorted by computing a count of codes for each length, | |
| 94 | creating from that a table of starting indices for each length in the | |
| 95 | sorted table, and then entering the symbols in order in the sorted | |
| 96 | table. The sorted table is work[], with that space being provided by | |
| 97 | the caller. | |
| 98 | 98 | |
| 99 | The length counts are used for other purposes as well, i.e. finding | |
| 100 | the minimum and maximum length codes, determining if there are any | |
| 101 | codes at all, checking for a valid set of lengths, and looking ahead | |
| 102 | at length counts to determine sub-table sizes when building the | |
| 103 | decoding tables. | |
| 104 | */ | |
| 99 | The length counts are used for other purposes as well, i.e. finding | |
| 100 | the minimum and maximum length codes, determining if there are any | |
| 101 | codes at all, checking for a valid set of lengths, and looking ahead | |
| 102 | at length counts to determine sub-table sizes when building the | |
| 103 | decoding tables. | |
| 104 | */ | |
| 105 | 105 | |
| 106 | /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ | |
| 107 | for (len = 0; len <= MAXBITS; len++) | |
| 108 | count[len] = 0; | |
| 109 | for (sym = 0; sym < codes; sym++) | |
| 110 | count[lens[sym]]++; | |
| 106 | /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ | |
| 107 | for (len = 0; len <= MAXBITS; len++) | |
| 108 | count[len] = 0; | |
| 109 | for (sym = 0; sym < codes; sym++) | |
| 110 | count[lens[sym]]++; | |
| 111 | 111 | |
| 112 | /* bound code lengths, force root to be within code lengths */ | |
| 113 | root = *bits; | |
| 114 | for (max = MAXBITS; max >= 1; max--) | |
| 115 | if (count[max] != 0) break; | |
| 116 | if (root > max) root = max; | |
| 117 | if (max == 0) { /* no symbols to code at all */ | |
| 118 | here.op = (unsigned char)64; /* invalid code marker */ | |
| 119 | here.bits = (unsigned char)1; | |
| 120 | here.val = (unsigned short)0; | |
| 121 | *(*table)++ = here; /* make a table to force an error */ | |
| 122 | *(*table)++ = here; | |
| 123 | *bits = 1; | |
| 124 | return 0; /* no symbols, but wait for decoding to report error */ | |
| 125 | } | |
| 126 | for (min = 1; min < max; min++) | |
| 127 | if (count[min] != 0) break; | |
| 128 | if (root < min) root = min; | |
| 112 | /* bound code lengths, force root to be within code lengths */ | |
| 113 | root = *bits; | |
| 114 | for (max = MAXBITS; max >= 1; max--) | |
| 115 | if (count[max] != 0) break; | |
| 116 | if (root > max) root = max; | |
| 117 | if (max == 0) { /* no symbols to code at all */ | |
| 118 | here.op = (unsigned char)64; /* invalid code marker */ | |
| 119 | here.bits = (unsigned char)1; | |
| 120 | here.val = (unsigned short)0; | |
| 121 | *(*table)++ = here; /* make a table to force an error */ | |
| 122 | *(*table)++ = here; | |
| 123 | *bits = 1; | |
| 124 | return 0; /* no symbols, but wait for decoding to report error */ | |
| 125 | } | |
| 126 | for (min = 1; min < max; min++) | |
| 127 | if (count[min] != 0) break; | |
| 128 | if (root < min) root = min; | |
| 129 | 129 | |
| 130 | /* check for an over-subscribed or incomplete set of lengths */ | |
| 131 | left = 1; | |
| 132 | for (len = 1; len <= MAXBITS; len++) { | |
| 133 | left <<= 1; | |
| 134 | left -= count[len]; | |
| 135 | if (left < 0) return -1; /* over-subscribed */ | |
| 136 | } | |
| 137 | if (left > 0 && (type == CODES || max != 1)) | |
| 138 | return -1; /* incomplete set */ | |
| 130 | /* check for an over-subscribed or incomplete set of lengths */ | |
| 131 | left = 1; | |
| 132 | for (len = 1; len <= MAXBITS; len++) { | |
| 133 | left <<= 1; | |
| 134 | left -= count[len]; | |
| 135 | if (left < 0) return -1; /* over-subscribed */ | |
| 136 | } | |
| 137 | if (left > 0 && (type == CODES || max != 1)) | |
| 138 | return -1; /* incomplete set */ | |
| 139 | 139 | |
| 140 | /* generate offsets into symbol table for each length for sorting */ | |
| 141 | offs[1] = 0; | |
| 142 | for (len = 1; len < MAXBITS; len++) | |
| 143 | offs[len + 1] = offs[len] + count[len]; | |
| 140 | /* generate offsets into symbol table for each length for sorting */ | |
| 141 | offs[1] = 0; | |
| 142 | for (len = 1; len < MAXBITS; len++) | |
| 143 | offs[len + 1] = offs[len] + count[len]; | |
| 144 | 144 | |
| 145 | /* sort symbols by length, by symbol order within each length */ | |
| 146 | for (sym = 0; sym < codes; sym++) | |
| 147 | if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; | |
| 145 | /* sort symbols by length, by symbol order within each length */ | |
| 146 | for (sym = 0; sym < codes; sym++) | |
| 147 | if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; | |
| 148 | 148 | |
| 149 | /* | |
| 150 | Create and fill in decoding tables. In this loop, the table being | |
| 151 | filled is at next and has curr index bits. The code being used is huff | |
| 152 | with length len. That code is converted to an index by dropping drop | |
| 153 | bits off of the bottom. For codes where len is less than drop + curr, | |
| 154 | those top drop + curr - len bits are incremented through all values to | |
| 155 | fill the table with replicated entries. | |
| 149 | /* | |
| 150 | Create and fill in decoding tables. In this loop, the table being | |
| 151 | filled is at next and has curr index bits. The code being used is huff | |
| 152 | with length len. That code is converted to an index by dropping drop | |
| 153 | bits off of the bottom. For codes where len is less than drop + curr, | |
| 154 | those top drop + curr - len bits are incremented through all values to | |
| 155 | fill the table with replicated entries. | |
| 156 | 156 | |
| 157 | root is the number of index bits for the root table. When len exceeds | |
| 158 | root, sub-tables are created pointed to by the root entry with an index | |
| 159 | of the low root bits of huff. This is saved in low to check for when a | |
| 160 | new sub-table should be started. drop is zero when the root table is | |
| 161 | being filled, and drop is root when sub-tables are being filled. | |
| 157 | root is the number of index bits for the root table. When len exceeds | |
| 158 | root, sub-tables are created pointed to by the root entry with an index | |
| 159 | of the low root bits of huff. This is saved in low to check for when a | |
| 160 | new sub-table should be started. drop is zero when the root table is | |
| 161 | being filled, and drop is root when sub-tables are being filled. | |
| 162 | 162 | |
| 163 | When a new sub-table is needed, it is necessary to look ahead in the | |
| 164 | code lengths to determine what size sub-table is needed. The length | |
| 165 | counts are used for this, and so count[] is decremented as codes are | |
| 166 | entered in the tables. | |
| 163 | When a new sub-table is needed, it is necessary to look ahead in the | |
| 164 | code lengths to determine what size sub-table is needed. The length | |
| 165 | counts are used for this, and so count[] is decremented as codes are | |
| 166 | entered in the tables. | |
| 167 | 167 | |
| 168 | used keeps track of how many table entries have been allocated from the | |
| 169 | provided *table space. It is checked for LENS and DIST tables against | |
| 170 | the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in | |
| 171 | the initial root table size constants. See the comments in inftrees.h | |
| 172 | for more information. | |
| 168 | used keeps track of how many table entries have been allocated from the | |
| 169 | provided *table space. It is checked for LENS and DIST tables against | |
| 170 | the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in | |
| 171 | the initial root table size constants. See the comments in inftrees.h | |
| 172 | for more information. | |
| 173 | 173 | |
| 174 | sym increments through all symbols, and the loop terminates when | |
| 175 | all codes of length max, i.e. all codes, have been processed. This | |
| 176 | routine permits incomplete codes, so another loop after this one fills | |
| 177 | in the rest of the decoding tables with invalid code markers. | |
| 178 | */ | |
| 174 | sym increments through all symbols, and the loop terminates when | |
| 175 | all codes of length max, i.e. all codes, have been processed. This | |
| 176 | routine permits incomplete codes, so another loop after this one fills | |
| 177 | in the rest of the decoding tables with invalid code markers. | |
| 178 | */ | |
| 179 | 179 | |
| 180 | /* set up for code type */ | |
| 181 | switch (type) { | |
| 182 | case CODES: | |
| 183 | base = extra = work; /* dummy value--not used */ | |
| 184 | end = 19; | |
| 185 | break; | |
| 186 | case LENS: | |
| 187 | base = lbase; | |
| 188 | base -= 257; | |
| 189 | extra = lext; | |
| 190 | extra -= 257; | |
| 191 | end = 256; | |
| 192 | break; | |
| 193 | default: /* DISTS */ | |
| 194 | base = dbase; | |
| 195 | extra = dext; | |
| 196 | end = -1; | |
| 197 | } | |
| 180 | /* set up for code type */ | |
| 181 | switch (type) { | |
| 182 | case CODES: | |
| 183 | base = extra = work; /* dummy value--not used */ | |
| 184 | end = 19; | |
| 185 | break; | |
| 186 | case LENS: | |
| 187 | base = lbase; | |
| 188 | base -= 257; | |
| 189 | extra = lext; | |
| 190 | extra -= 257; | |
| 191 | end = 256; | |
| 192 | break; | |
| 193 | default: /* DISTS */ | |
| 194 | base = dbase; | |
| 195 | extra = dext; | |
| 196 | end = -1; | |
| 197 | } | |
| 198 | 198 | |
| 199 | /* initialize state for loop */ | |
| 200 | huff = 0; /* starting code */ | |
| 201 | sym = 0; /* starting code symbol */ | |
| 202 | len = min; /* starting code length */ | |
| 203 | next = *table; /* current table to fill in */ | |
| 204 | curr = root; /* current table index bits */ | |
| 205 | drop = 0; /* current bits to drop from code for index */ | |
| 206 | low = (unsigned)(-1); /* trigger new sub-table when len > root */ | |
| 207 | used = 1U << root; /* use root table entries */ | |
| 208 | mask = used - 1; /* mask for comparing low */ | |
| 199 | /* initialize state for loop */ | |
| 200 | huff = 0; /* starting code */ | |
| 201 | sym = 0; /* starting code symbol */ | |
| 202 | len = min; /* starting code length */ | |
| 203 | next = *table; /* current table to fill in */ | |
| 204 | curr = root; /* current table index bits */ | |
| 205 | drop = 0; /* current bits to drop from code for index */ | |
| 206 | low = (unsigned)(-1); /* trigger new sub-table when len > root */ | |
| 207 | used = 1U << root; /* use root table entries */ | |
| 208 | mask = used - 1; /* mask for comparing low */ | |
| 209 | 209 | |
| 210 | /* check available table space */ | |
| 211 | if ((type == LENS && used > ENOUGH_LENS) || | |
| 212 | (type == DISTS && used > ENOUGH_DISTS)) | |
| 213 | return 1; | |
| 210 | /* check available table space */ | |
| 211 | if ((type == LENS && used > ENOUGH_LENS) || | |
| 212 | (type == DISTS && used > ENOUGH_DISTS)) | |
| 213 | return 1; | |
| 214 | 214 | |
| 215 | /* process all codes and make table entries */ | |
| 216 | for (;;) { | |
| 217 | /* create table entry */ | |
| 218 | here.bits = (unsigned char)(len - drop); | |
| 219 | if ((int)(work[sym]) < end) { | |
| 220 | here.op = (unsigned char)0; | |
| 221 | here.val = work[sym]; | |
| 222 | } | |
| 223 | else if ((int)(work[sym]) > end) { | |
| 224 | here.op = (unsigned char)(extra[work[sym]]); | |
| 225 | here.val = base[work[sym]]; | |
| 226 | } | |
| 227 | else { | |
| 228 | here.op = (unsigned char)(32 + 64); /* end of block */ | |
| 229 | here.val = 0; | |
| 230 | } | |
| 215 | /* process all codes and make table entries */ | |
| 216 | for (;;) { | |
| 217 | /* create table entry */ | |
| 218 | here.bits = (unsigned char)(len - drop); | |
| 219 | if ((int)(work[sym]) < end) { | |
| 220 | here.op = (unsigned char)0; | |
| 221 | here.val = work[sym]; | |
| 222 | } | |
| 223 | else if ((int)(work[sym]) > end) { | |
| 224 | here.op = (unsigned char)(extra[work[sym]]); | |
| 225 | here.val = base[work[sym]]; | |
| 226 | } | |
| 227 | else { | |
| 228 | here.op = (unsigned char)(32 + 64); /* end of block */ | |
| 229 | here.val = 0; | |
| 230 | } | |
| 231 | 231 | |
| 232 | /* replicate for those indices with low len bits equal to huff */ | |
| 233 | incr = 1U << (len - drop); | |
| 234 | fill = 1U << curr; | |
| 235 | min = fill; /* save offset to next table */ | |
| 236 | do { | |
| 237 | fill -= incr; | |
| 238 | next[(huff >> drop) + fill] = here; | |
| 239 | } while (fill != 0); | |
| 232 | /* replicate for those indices with low len bits equal to huff */ | |
| 233 | incr = 1U << (len - drop); | |
| 234 | fill = 1U << curr; | |
| 235 | min = fill; /* save offset to next table */ | |
| 236 | do { | |
| 237 | fill -= incr; | |
| 238 | next[(huff >> drop) + fill] = here; | |
| 239 | } while (fill != 0); | |
| 240 | 240 | |
| 241 | /* backwards increment the len-bit code huff */ | |
| 242 | incr = 1U << (len - 1); | |
| 243 | while (huff & incr) | |
| 244 | incr >>= 1; | |
| 245 | if (incr != 0) { | |
| 246 | huff &= incr - 1; | |
| 247 | huff += incr; | |
| 248 | } | |
| 249 | else | |
| 250 | huff = 0; | |
| 241 | /* backwards increment the len-bit code huff */ | |
| 242 | incr = 1U << (len - 1); | |
| 243 | while (huff & incr) | |
| 244 | incr >>= 1; | |
| 245 | if (incr != 0) { | |
| 246 | huff &= incr - 1; | |
| 247 | huff += incr; | |
| 248 | } | |
| 249 | else | |
| 250 | huff = 0; | |
| 251 | 251 | |
| 252 | /* go to next symbol, update count, len */ | |
| 253 | sym++; | |
| 254 | if (--(count[len]) == 0) { | |
| 255 | if (len == max) break; | |
| 256 | len = lens[work[sym]]; | |
| 257 | } | |
| 252 | /* go to next symbol, update count, len */ | |
| 253 | sym++; | |
| 254 | if (--(count[len]) == 0) { | |
| 255 | if (len == max) break; | |
| 256 | len = lens[work[sym]]; | |
| 257 | } | |
| 258 | 258 | |
| 259 | /* create new sub-table if needed */ | |
| 260 | if (len > root && (huff & mask) != low) { | |
| 261 | /* if first time, transition to sub-tables */ | |
| 262 | if (drop == 0) | |
| 263 | drop = root; | |
| 259 | /* create new sub-table if needed */ | |
| 260 | if (len > root && (huff & mask) != low) { | |
| 261 | /* if first time, transition to sub-tables */ | |
| 262 | if (drop == 0) | |
| 263 | drop = root; | |
| 264 | 264 | |
| 265 | /* increment past last table */ | |
| 266 | next += min; /* here min is 1 << curr */ | |
| 265 | /* increment past last table */ | |
| 266 | next += min; /* here min is 1 << curr */ | |
| 267 | 267 | |
| 268 | /* determine length of next table */ | |
| 269 | curr = len - drop; | |
| 270 | left = (int)(1 << curr); | |
| 271 | while (curr + drop < max) { | |
| 272 | left -= count[curr + drop]; | |
| 273 | if (left <= 0) break; | |
| 274 | curr++; | |
| 275 | left <<= 1; | |
| 276 | } | |
| 268 | /* determine length of next table */ | |
| 269 | curr = len - drop; | |
| 270 | left = (int)(1 << curr); | |
| 271 | while (curr + drop < max) { | |
| 272 | left -= count[curr + drop]; | |
| 273 | if (left <= 0) break; | |
| 274 | curr++; | |
| 275 | left <<= 1; | |
| 276 | } | |
| 277 | 277 | |
| 278 | /* check for enough space */ | |
| 279 | used += 1U << curr; | |
| 280 | if ((type == LENS && used > ENOUGH_LENS) || | |
| 281 | (type == DISTS && used > ENOUGH_DISTS)) | |
| 282 | return 1; | |
| 278 | /* check for enough space */ | |
| 279 | used += 1U << curr; | |
| 280 | if ((type == LENS && used > ENOUGH_LENS) || | |
| 281 | (type == DISTS && used > ENOUGH_DISTS)) | |
| 282 | return 1; | |
| 283 | 283 | |
| 284 | /* point entry in root table to sub-table */ | |
| 285 | low = huff & mask; | |
| 286 | (*table)[low].op = (unsigned char)curr; | |
| 287 | (*table)[low].bits = (unsigned char)root; | |
| 288 | (*table)[low].val = (unsigned short)(next - *table); | |
| 289 | } | |
| 290 | } | |
| 284 | /* point entry in root table to sub-table */ | |
| 285 | low = huff & mask; | |
| 286 | (*table)[low].op = (unsigned char)curr; | |
| 287 | (*table)[low].bits = (unsigned char)root; | |
| 288 | (*table)[low].val = (unsigned short)(next - *table); | |
| 289 | } | |
| 290 | } | |
| 291 | 291 | |
| 292 | /* fill in remaining table entry if code is incomplete (guaranteed to have | |
| 293 | at most one remaining entry, since if the code is incomplete, the | |
| 294 | maximum code length that was allowed to get this far is one bit) */ | |
| 295 | if (huff != 0) { | |
| 296 | here.op = (unsigned char)64; /* invalid code marker */ | |
| 297 | here.bits = (unsigned char)(len - drop); | |
| 298 | here.val = (unsigned short)0; | |
| 299 | next[huff] = here; | |
| 300 | } | |
| 292 | /* fill in remaining table entry if code is incomplete (guaranteed to have | |
| 293 | at most one remaining entry, since if the code is incomplete, the | |
| 294 | maximum code length that was allowed to get this far is one bit) */ | |
| 295 | if (huff != 0) { | |
| 296 | here.op = (unsigned char)64; /* invalid code marker */ | |
| 297 | here.bits = (unsigned char)(len - drop); | |
| 298 | here.val = (unsigned short)0; | |
| 299 | next[huff] = here; | |
| 300 | } | |
| 301 | 301 | |
| 302 | /* set return parameters */ | |
| 303 | *table += used; | |
| 304 | *bits = root; | |
| 305 | return 0; | |
| 302 | /* set return parameters */ | |
| 303 | *table += used; | |
| 304 | *bits = root; | |
| 305 | return 0; | |
| 306 | 306 | } |
| r25360 | r25361 | |
|---|---|---|
| 4 | 4 | |
| 5 | 5 | local const z_crc_t FAR crc_table[TBLS][256] = |
| 6 | 6 | { |
| 7 | { | |
| 8 | 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, | |
| 9 | 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, | |
| 10 | 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, | |
| 11 | 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, | |
| 12 | 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, | |
| 13 | 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, | |
| 14 | 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, | |
| 15 | 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, | |
| 16 | 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, | |
| 17 | 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, | |
| 18 | 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, | |
| 19 | 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, | |
| 20 | 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, | |
| 21 | 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, | |
| 22 | 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, | |
| 23 | 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, | |
| 24 | 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, | |
| 25 | 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, | |
| 26 | 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, | |
| 27 | 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, | |
| 28 | 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, | |
| 29 | 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, | |
| 30 | 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, | |
| 31 | 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, | |
| 32 | 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, | |
| 33 | 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, | |
| 34 | 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, | |
| 35 | 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, | |
| 36 | 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, | |
| 37 | 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, | |
| 38 | 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, | |
| 39 | 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, | |
| 40 | 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, | |
| 41 | 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, | |
| 42 | 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, | |
| 43 | 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, | |
| 44 | 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, | |
| 45 | 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, | |
| 46 | 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, | |
| 47 | 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, | |
| 48 | 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, | |
| 49 | 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, | |
| 50 | 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, | |
| 51 | 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, | |
| 52 | 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, | |
| 53 | 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, | |
| 54 | 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, | |
| 55 | 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, | |
| 56 | 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, | |
| 57 | 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, | |
| 58 | 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, | |
| 59 | 0x2d02ef8dUL | |
| 7 | { | |
| 8 | 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, | |
| 9 | 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, | |
| 10 | 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, | |
| 11 | 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, | |
| 12 | 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, | |
| 13 | 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, | |
| 14 | 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, | |
| 15 | 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, | |
| 16 | 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, | |
| 17 | 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, | |
| 18 | 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, | |
| 19 | 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, | |
| 20 | 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, | |
| 21 | 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, | |
| 22 | 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, | |
| 23 | 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, | |
| 24 | 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, | |
| 25 | 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, | |
| 26 | 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, | |
| 27 | 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, | |
| 28 | 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, | |
| 29 | 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, | |
| 30 | 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, | |
| 31 | 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, | |
| 32 | 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, | |
| 33 | 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, | |
| 34 | 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, | |
| 35 | 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, | |
| 36 | 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, | |
| 37 | 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, | |
| 38 | 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, | |
| 39 | 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, | |
| 40 | 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, | |
| 41 | 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, | |
| 42 | 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, | |
| 43 | 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, | |
| 44 | 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, | |
| 45 | 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, | |
| 46 | 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, | |
| 47 | 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, | |
| 48 | 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, | |
| 49 | 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, | |
| 50 | 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, | |
| 51 | 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, | |
| 52 | 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, | |
| 53 | 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, | |
| 54 | 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, | |
| 55 | 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, | |
| 56 | 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, | |
| 57 | 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, | |
| 58 | 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, | |
| 59 | 0x2d02ef8dUL | |
| 60 | 60 | #ifdef BYFOUR |
| 61 | }, | |
| 62 | { | |
| 63 | 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, | |
| 64 | 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, | |
| 65 | 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, | |
| 66 | 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, | |
| 67 | 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, | |
| 68 | 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, | |
| 69 | 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, | |
| 70 | 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, | |
| 71 | 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, | |
| 72 | 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, | |
| 73 | 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, | |
| 74 | 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, | |
| 75 | 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, | |
| 76 | 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, | |
| 77 | 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, | |
| 78 | 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, | |
| 79 | 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, | |
| 80 | 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, | |
| 81 | 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, | |
| 82 | 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, | |
| 83 | 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, | |
| 84 | 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, | |
| 85 | 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, | |
| 86 | 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, | |
| 87 | 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, | |
| 88 | 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, | |
| 89 | 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, | |
| 90 | 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, | |
| 91 | 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, | |
| 92 | 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, | |
| 93 | 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, | |
| 94 | 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, | |
| 95 | 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, | |
| 96 | 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, | |
| 97 | 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, | |
| 98 | 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, | |
| 99 | 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, | |
| 100 | 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, | |
| 101 | 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, | |
| 102 | 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, | |
| 103 | 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, | |
| 104 | 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, | |
| 105 | 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, | |
| 106 | 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, | |
| 107 | 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, | |
| 108 | 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, | |
| 109 | 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, | |
| 110 | 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, | |
| 111 | 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, | |
| 112 | 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, | |
| 113 | 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, | |
| 114 | 0x9324fd72UL | |
| 115 | }, | |
| 116 | { | |
| 117 | 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, | |
| 118 | 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, | |
| 119 | 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, | |
| 120 | 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, | |
| 121 | 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, | |
| 122 | 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, | |
| 123 | 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, | |
| 124 | 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, | |
| 125 | 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, | |
| 126 | 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, | |
| 127 | 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, | |
| 128 | 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, | |
| 129 | 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, | |
| 130 | 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, | |
| 131 | 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, | |
| 132 | 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, | |
| 133 | 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, | |
| 134 | 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, | |
| 135 | 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, | |
| 136 | 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, | |
| 137 | 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, | |
| 138 | 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, | |
| 139 | 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, | |
| 140 | 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, | |
| 141 | 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, | |
| 142 | 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, | |
| 143 | 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, | |
| 144 | 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, | |
| 145 | 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, | |
| 146 | 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, | |
| 147 | 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, | |
| 148 | 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, | |
| 149 | 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, | |
| 150 | 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, | |
| 151 | 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, | |
| 152 | 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, | |
| 153 | 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, | |
| 154 | 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, | |
| 155 | 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, | |
| 156 | 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, | |
| 157 | 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, | |
| 158 | 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, | |
| 159 | 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, | |
| 160 | 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, | |
| 161 | 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, | |
| 162 | 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, | |
| 163 | 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, | |
| 164 | 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, | |
| 165 | 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, | |
| 166 | 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, | |
| 167 | 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, | |
| 168 | 0xbe9834edUL | |
| 169 | }, | |
| 170 | { | |
| 171 | 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, | |
| 172 | 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, | |
| 173 | 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, | |
| 174 | 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, | |
| 175 | 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, | |
| 176 | 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, | |
| 177 | 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, | |
| 178 | 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, | |
| 179 | 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, | |
| 180 | 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, | |
| 181 | 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, | |
| 182 | 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, | |
| 183 | 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, | |
| 184 | 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, | |
| 185 | 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, | |
| 186 | 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, | |
| 187 | 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, | |
| 188 | 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, | |
| 189 | 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, | |
| 190 | 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, | |
| 191 | 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, | |
| 192 | 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, | |
| 193 | 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, | |
| 194 | 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, | |
| 195 | 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, | |
| 196 | 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, | |
| 197 | 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, | |
| 198 | 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, | |
| 199 | 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, | |
| 200 | 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, | |
| 201 | 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, | |
| 202 | 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, | |
| 203 | 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, | |
| 204 | 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, | |
| 205 | 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, | |
| 206 | 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, | |
| 207 | 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, | |
| 208 | 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, | |
| 209 | 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, | |
| 210 | 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, | |
| 211 | 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, | |
| 212 | 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, | |
| 213 | 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, | |
| 214 | 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, | |
| 215 | 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, | |
| 216 | 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, | |
| 217 | 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, | |
| 218 | 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, | |
| 219 | 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, | |
| 220 | 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, | |
| 221 | 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, | |
| 222 | 0xde0506f1UL | |
| 223 | }, | |
| 224 | { | |
| 225 | 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, | |
| 226 | 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, | |
| 227 | 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, | |
| 228 | 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, | |
| 229 | 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, | |
| 230 | 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, | |
| 231 | 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, | |
| 232 | 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, | |
| 233 | 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, | |
| 234 | 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, | |
| 235 | 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, | |
| 236 | 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, | |
| 237 | 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, | |
| 238 | 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, | |
| 239 | 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, | |
| 240 | 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, | |
| 241 | 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, | |
| 242 | 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, | |
| 243 | 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, | |
| 244 | 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, | |
| 245 | 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, | |
| 246 | 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, | |
| 247 | 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, | |
| 248 | 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, | |
| 249 | 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, | |
| 250 | 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, | |
| 251 | 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, | |
| 252 | 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, | |
| 253 | 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, | |
| 254 | 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, | |
| 255 | 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, | |
| 256 | 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, | |
| 257 | 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, | |
| 258 | 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, | |
| 259 | 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, | |
| 260 | 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, | |
| 261 | 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, | |
| 262 | 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, | |
| 263 | 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, | |
| 264 | 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, | |
| 265 | 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, | |
| 266 | 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, | |
| 267 | 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, | |
| 268 | 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, | |
| 269 | 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, | |
| 270 | 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, | |
| 271 | 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, | |
| 272 | 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, | |
| 273 | 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, | |
| 274 | 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, | |
| 275 | 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, | |
| 276 | 0x8def022dUL | |
| 277 | }, | |
| 278 | { | |
| 279 | 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, | |
| 280 | 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, | |
| 281 | 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, | |
| 282 | 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, | |
| 283 | 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, | |
| 284 | 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, | |
| 285 | 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, | |
| 286 | 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, | |
| 287 | 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, | |
| 288 | 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, | |
| 289 | 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, | |
| 290 | 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, | |
| 291 | 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, | |
| 292 | 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, | |
| 293 | 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, | |
| 294 | 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, | |
| 295 | 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, | |
| 296 | 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, | |
| 297 | 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, | |
| 298 | 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, | |
| 299 | 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, | |
| 300 | 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, | |
| 301 | 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, | |
| 302 | 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, | |
| 303 | 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, | |
| 304 | 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, | |
| 305 | 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, | |
| 306 | 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, | |
| 307 | 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, | |
| 308 | 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, | |
| 309 | 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, | |
| 310 | 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, | |
| 311 | 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, | |
| 312 | 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, | |
| 313 | 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, | |
| 314 | 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, | |
| 315 | 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, | |
| 316 | 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, | |
| 317 | 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, | |
| 318 | 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, | |
| 319 | 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, | |
| 320 | 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, | |
| 321 | 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, | |
| 322 | 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, | |
| 323 | 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, | |
| 324 | 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, | |
| 325 | 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, | |
| 326 | 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, | |
| 327 | 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, | |
| 328 | 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, | |
| 329 | 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, | |
| 330 | 0x72fd2493UL | |
| 331 | }, | |
| 332 | { | |
| 333 | 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, | |
| 334 | 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, | |
| 335 | 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, | |
| 336 | 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, | |
| 337 | 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, | |
| 338 | 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, | |
| 339 | 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, | |
| 340 | 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, | |
| 341 | 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, | |
| 342 | 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, | |
| 343 | 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, | |
| 344 | 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, | |
| 345 | 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, | |
| 346 | 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, | |
| 347 | 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, | |
| 348 | 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, | |
| 349 | 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, | |
| 350 | 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, | |
| 351 | 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, | |
| 352 | 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, | |
| 353 | 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, | |
| 354 | 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, | |
| 355 | 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, | |
| 356 | 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, | |
| 357 | 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, | |
| 358 | 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, | |
| 359 | 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, | |
| 360 | 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, | |
| 361 | 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, | |
| 362 | 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, | |
| 363 | 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, | |
| 364 | 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, | |
| 365 | 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, | |
| 366 | 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, | |
| 367 | 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, | |
| 368 | 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, | |
| 369 | 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, | |
| 370 | 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, | |
| 371 | 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, | |
| 372 | 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, | |
| 373 | 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, | |
| 374 | 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, | |
| 375 | 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, | |
| 376 | 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, | |
| 377 | 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, | |
| 378 | 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, | |
| 379 | 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, | |
| 380 | 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, | |
| 381 | 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, | |
| 382 | 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, | |
| 383 | 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, | |
| 384 | 0xed3498beUL | |
| 385 | }, | |
| 386 | { | |
| 387 | 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, | |
| 388 | 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, | |
| 389 | 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, | |
| 390 | 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, | |
| 391 | 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, | |
| 392 | 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, | |
| 393 | 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, | |
| 394 | 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, | |
| 395 | 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, | |
| 396 | 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, | |
| 397 | 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, | |
| 398 | 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, | |
| 399 | 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, | |
| 400 | 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, | |
| 401 | 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, | |
| 402 | 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, | |
| 403 | 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, | |
| 404 | 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, | |
| 405 | 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, | |
| 406 | 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, | |
| 407 | 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, | |
| 408 | 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, | |
| 409 | 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, | |
| 410 | 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, | |
| 411 | 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, | |
| 412 | 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, | |
| 413 | 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, | |
| 414 | 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, | |
| 415 | 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, | |
| 416 | 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, | |
| 417 | 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, | |
| 418 | 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, | |
| 419 | 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, | |
| 420 | 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, | |
| 421 | 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, | |
| 422 | 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, | |
| 423 | 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, | |
| 424 | 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, | |
| 425 | 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, | |
| 426 | 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, | |
| 427 | 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, | |
| 428 | 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, | |
| 429 | 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, | |
| 430 | 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, | |
| 431 | 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, | |
| 432 | 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, | |
| 433 | 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, | |
| 434 | 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, | |
| 435 | 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, | |
| 436 | 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, | |
| 437 | 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, | |
| 438 | 0xf10605deUL | |
| 61 | }, | |
| 62 | { | |
| 63 | 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, | |
| 64 | 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, | |
| 65 | 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, | |
| 66 | 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, | |
| 67 | 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, | |
| 68 | 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, | |
| 69 | 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, | |
| 70 | 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, | |
| 71 | 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, | |
| 72 | 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, | |
| 73 | 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, | |
| 74 | 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, | |
| 75 | 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, | |
| 76 | 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, | |
| 77 | 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, | |
| 78 | 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, | |
| 79 | 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, | |
| 80 | 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, | |
| 81 | 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, | |
| 82 | 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, | |
| 83 | 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, | |
| 84 | 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, | |
| 85 | 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, | |
| 86 | 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, | |
| 87 | 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, | |
| 88 | 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, | |
| 89 | 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, | |
| 90 | 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, | |
| 91 | 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, | |
| 92 | 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, | |
| 93 | 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, | |
| 94 | 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, | |
| 95 | 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, | |
| 96 | 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, | |
| 97 | 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, | |
| 98 | 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, | |
| 99 | 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, | |
| 100 | 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, | |
| 101 | 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, | |
| 102 | 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, | |
| 103 | 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, | |
| 104 | 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, | |
| 105 | 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, | |
| 106 | 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, | |
| 107 | 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, | |
| 108 | 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, | |
| 109 | 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, | |
| 110 | 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, | |
| 111 | 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, | |
| 112 | 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, | |
| 113 | 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, | |
| 114 | 0x9324fd72UL | |
| 115 | }, | |
| 116 | { | |
| 117 | 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, | |
| 118 | 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, | |
| 119 | 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, | |
| 120 | 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, | |
| 121 | 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, | |
| 122 | 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, | |
| 123 | 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, | |
| 124 | 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, | |
| 125 | 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, | |
| 126 | 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, | |
| 127 | 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, | |
| 128 | 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, | |
| 129 | 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, | |
| 130 | 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, | |
| 131 | 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, | |
| 132 | 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, | |
| 133 | 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, | |
| 134 | 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, | |
| 135 | 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, | |
| 136 | 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, | |
| 137 | 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, | |
| 138 | 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, | |
| 139 | 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, | |
| 140 | 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, | |
| 141 | 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, | |
| 142 | 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, | |
| 143 | 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, | |
| 144 | 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, | |
| 145 | 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, | |
| 146 | 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, | |
| 147 | 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, | |
| 148 | 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, | |
| 149 | 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, | |
| 150 | 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, | |
| 151 | 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, | |
| 152 | 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, | |
| 153 | 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, | |
| 154 | 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, | |
| 155 | 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, | |
| 156 | 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, | |
| 157 | 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, | |
| 158 | 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, | |
| 159 | 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, | |
| 160 | 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, | |
| 161 | 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, | |
| 162 | 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, | |
| 163 | 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, | |
| 164 | 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, | |
| 165 | 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, | |
| 166 | 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, | |
| 167 | 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, | |
| 168 | 0xbe9834edUL | |
| 169 | }, | |
| 170 | { | |
| 171 | 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, | |
| 172 | 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, | |
| 173 | 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, | |
| 174 | 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, | |
| 175 | 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, | |
| 176 | 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, | |
| 177 | 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, | |
| 178 | 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, | |
| 179 | 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, | |
| 180 | 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, | |
| 181 | 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, | |
| 182 | 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, | |
| 183 | 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, | |
| 184 | 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, | |
| 185 | 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, | |
| 186 | 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, | |
| 187 | 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, | |
| 188 | 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, | |
| 189 | 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, | |
| 190 | 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, | |
| 191 | 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, | |
| 192 | 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, | |
| 193 | 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, | |
| 194 | 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, | |
| 195 | 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, | |
| 196 | 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, | |
| 197 | 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, | |
| 198 | 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, | |
| 199 | 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, | |
| 200 | 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, | |
| 201 | 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, | |
| 202 | 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, | |
| 203 | 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, | |
| 204 | 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, | |
| 205 | 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, | |
| 206 | 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, | |
| 207 | 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, | |
| 208 | 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, | |
| 209 | 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, | |
| 210 | 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, | |
| 211 | 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, | |
| 212 | 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, | |
| 213 | 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, | |
| 214 | 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, | |
| 215 | 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, | |
| 216 | 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, | |
| 217 | 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, | |
| 218 | 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, | |
| 219 | 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, | |
| 220 | 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, | |
| 221 | 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, | |
| 222 | 0xde0506f1UL | |
| 223 | }, | |
| 224 | { | |
| 225 | 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, | |
| 226 | 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, | |
| 227 | 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, | |
| 228 | 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, | |
| 229 | 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, | |
| 230 | 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, | |
| 231 | 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, | |
| 232 | 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, | |
| 233 | 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, | |
| 234 | 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, | |
| 235 | 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, | |
| 236 | 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, | |
| 237 | 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, | |
| 238 | 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, | |
| 239 | 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, | |
| 240 | 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, | |
| 241 | 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, | |
| 242 | 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, | |
| 243 | 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, | |
| 244 | 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, | |
| 245 | 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, | |
| 246 | 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, | |
| 247 | 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, | |
| 248 | 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, | |
| 249 | 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, | |
| 250 | 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, | |
| 251 | 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, | |
| 252 | 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, | |
| 253 | 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, | |
| 254 | 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, | |
| 255 | 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, | |
| 256 | 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, | |
| 257 | 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, | |
| 258 | 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, | |
| 259 | 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, | |
| 260 | 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, | |
| 261 | 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, | |
| 262 | 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, | |
| 263 | 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, | |
| 264 | 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, | |
| 265 | 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, | |
| 266 | 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, | |
| 267 | 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, | |
| 268 | 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, | |
| 269 | 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, | |
| 270 | 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, | |
| 271 | 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, | |
| 272 | 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, | |
| 273 | 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, | |
| 274 | 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, | |
| 275 | 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, | |
| 276 | 0x8def022dUL | |
| 277 | }, | |
| 278 | { | |
| 279 | 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, | |
| 280 | 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, | |
| 281 | 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, | |
| 282 | 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, | |
| 283 | 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, | |
| 284 | 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, | |
| 285 | 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, | |
| 286 | 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, | |
| 287 | 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, | |
| 288 | 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, | |
| 289 | 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, | |
| 290 | 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, | |
| 291 | 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, | |
| 292 | 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, | |
| 293 | 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, | |
| 294 | 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, | |
| 295 | 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, | |
| 296 | 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, | |
| 297 | 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, | |
| 298 | 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, | |
| 299 | 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, | |
| 300 | 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, | |
| 301 | 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, | |
| 302 | 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, | |
| 303 | 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, | |
| 304 | 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, | |
| 305 | 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, | |
| 306 | 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, | |
| 307 | 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, | |
| 308 | 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, | |
| 309 | 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, | |
| 310 | 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, | |
| 311 | 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, | |
| 312 | 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, | |
| 313 | 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, | |
| 314 | 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, | |
| 315 | 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, | |
| 316 | 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, | |
| 317 | 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, | |
| 318 | 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, | |
| 319 | 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, | |
| 320 | 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, | |
| 321 | 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, | |
| 322 | 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, | |
| 323 | 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, | |
| 324 | 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, | |
| 325 | 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, | |
| 326 | 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, | |
| 327 | 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, | |
| 328 | 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, | |
| 329 | 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, | |
| 330 | 0x72fd2493UL | |
| 331 | }, | |
| 332 | { | |
| 333 | 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, | |
| 334 | 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, | |
| 335 | 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, | |
| 336 | 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, | |
| 337 | 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, | |
| 338 | 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, | |
| 339 | 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, | |
| 340 | 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, | |
| 341 | 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, | |
| 342 | 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, | |
| 343 | 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, | |
| 344 | 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, | |
| 345 | 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, | |
| 346 | 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, | |
| 347 | 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, | |
| 348 | 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, | |
| 349 | 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, | |
| 350 | 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, | |
| 351 | 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, | |
| 352 | 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, | |
| 353 | 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, | |
| 354 | 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, | |
| 355 | 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, | |
| 356 | 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, | |
| 357 | 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, | |
| 358 | 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, | |
| 359 | 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, | |
| 360 | 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, | |
| 361 | 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, | |
| 362 | 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, | |
| 363 | 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, | |
| 364 | 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, | |
| 365 | 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, | |
| 366 | 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, | |
| 367 | 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, | |
| 368 | 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, | |
| 369 | 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, | |
| 370 | 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, | |
| 371 | 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, | |
| 372 | 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, | |
| 373 | 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, | |
| 374 | 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, | |
| 375 | 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, | |
| 376 | 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, | |
| 377 | 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, | |
| 378 | 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, | |
| 379 | 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, | |
| 380 | 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, | |
| 381 | 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, | |
| 382 | 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, | |
| 383 | 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, | |
| 384 | 0xed3498beUL | |
| 385 | }, | |
| 386 | { | |
| 387 | 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, | |
| 388 | 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, | |
| 389 | 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, | |
| 390 | 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, | |
| 391 | 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, | |
| 392 | 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, | |
| 393 | 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, | |
| 394 | 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, | |
| 395 | 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, | |
| 396 | 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, | |
| 397 | 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, | |
| 398 | 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, | |
| 399 | 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, | |
| 400 | 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, | |
| 401 | 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, | |
| 402 | 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, | |
| 403 | 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, | |
| 404 | 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, | |
| 405 | 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, | |
| 406 | 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, | |
| 407 | 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, | |
| 408 | 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, | |
| 409 | 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, | |
| 410 | 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, | |
| 411 | 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, | |
| 412 | 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, | |
| 413 | 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, | |
| 414 | 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, | |
| 415 | 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, | |
| 416 | 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, | |
| 417 | 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, | |
| 418 | 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, | |
| 419 | 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, | |
| 420 | 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, | |
| 421 | 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, | |
| 422 | 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, | |
| 423 | 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, | |
| 424 | 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, | |
| 425 | 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, | |
| 426 | 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, | |
| 427 | 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, | |
| 428 | 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, | |
| 429 | 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, | |
| 430 | 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, | |
| 431 | 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, | |
| 432 | 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, | |
| 433 | 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, | |
| 434 | 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, | |
| 435 | 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, | |
| 436 | 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, | |
| 437 | 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, | |
| 438 | 0xf10605deUL | |
| 439 | 439 | #endif |
| 440 | ||
| 440 | } | |
| 441 | 441 | }; |
| r25360 | r25361 | |
|---|---|---|
| 60 | 60 | /* repeat a zero length 11-138 times (7 bits of repeat count) */ |
| 61 | 61 | |
| 62 | 62 | local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ |
| 63 | ||
| 63 | = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; | |
| 64 | 64 | |
| 65 | 65 | local const int extra_dbits[D_CODES] /* extra bits for each distance code */ |
| 66 | ||
| 66 | = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; | |
| 67 | 67 | |
| 68 | 68 | local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ |
| 69 | ||
| 69 | = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; | |
| 70 | 70 | |
| 71 | 71 | local const uch bl_order[BL_CODES] |
| 72 | ||
| 72 | = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; | |
| 73 | 73 | /* The lengths of the bit length codes are sent in order of decreasing |
| 74 | 74 | * probability, to avoid transmitting the lengths for unused bit length codes. |
| 75 | 75 | */ |
| r25360 | r25361 | |
| 115 | 115 | #endif /* GEN_TREES_H */ |
| 116 | 116 | |
| 117 | 117 | struct static_tree_desc_s { |
| 118 | const ct_data *static_tree; /* static tree or NULL */ | |
| 119 | const intf *extra_bits; /* extra bits for each code or NULL */ | |
| 120 | int extra_base; /* base index for extra_bits */ | |
| 121 | int elems; /* max number of elements in the tree */ | |
| 122 | int max_length; /* max bit length for the codes */ | |
| 118 | const ct_data *static_tree; /* static tree or NULL */ | |
| 119 | const intf *extra_bits; /* extra bits for each code or NULL */ | |
| 120 | int extra_base; /* base index for extra_bits */ | |
| 121 | int elems; /* max number of elements in the tree */ | |
| 122 | int max_length; /* max bit length for the codes */ | |
| 123 | 123 | }; |
| 124 | 124 | |
| 125 | 125 | local static_tree_desc static_l_desc = |
| r25360 | r25361 | |
| 145 | 145 | local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); |
| 146 | 146 | local int build_bl_tree OF((deflate_state *s)); |
| 147 | 147 | local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, |
| 148 | ||
| 148 | int blcodes)); | |
| 149 | 149 | local void compress_block OF((deflate_state *s, const ct_data *ltree, |
| 150 | ||
| 150 | const ct_data *dtree)); | |
| 151 | 151 | local int detect_data_type OF((deflate_state *s)); |
| 152 | 152 | local unsigned bi_reverse OF((unsigned value, int length)); |
| 153 | 153 | local void bi_windup OF((deflate_state *s)); |
| 154 | 154 | local void bi_flush OF((deflate_state *s)); |
| 155 | 155 | local void copy_block OF((deflate_state *s, charf *buf, unsigned len, |
| 156 | ||
| 156 | int header)); | |
| 157 | 157 | |
| 158 | 158 | #ifdef GEN_TREES_H |
| 159 | 159 | local void gen_trees_header OF((void)); |
| r25360 | r25361 | |
| 161 | 161 | |
| 162 | 162 | #ifndef DEBUG |
| 163 | 163 | # define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) |
| 164 | ||
| 164 | /* Send a code of the given tree. c and tree must not have side effects */ | |
| 165 | 165 | |
| 166 | 166 | #else /* DEBUG */ |
| 167 | 167 | # define send_code(s, c, tree) \ |
| 168 | { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ | |
| 169 | send_bits(s, tree[c].Code, tree[c].Len); } | |
| 168 | { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ | |
| 169 | send_bits(s, tree[c].Code, tree[c].Len); } | |
| 170 | 170 | #endif |
| 171 | 171 | |
| 172 | 172 | /* =========================================================================== |
| r25360 | r25361 | |
| 174 | 174 | * IN assertion: there is enough room in pendingBuf. |
| 175 | 175 | */ |
| 176 | 176 | #define put_short(s, w) { \ |
| 177 | put_byte(s, (uch)((w) & 0xff)); \ | |
| 178 | put_byte(s, (uch)((ush)(w) >> 8)); \ | |
| 177 | put_byte(s, (uch)((w) & 0xff)); \ | |
| 178 | put_byte(s, (uch)((ush)(w) >> 8)); \ | |
| 179 | 179 | } |
| 180 | 180 | |
| 181 | 181 | /* =========================================================================== |
| r25360 | r25361 | |
| 186 | 186 | local void send_bits OF((deflate_state *s, int value, int length)); |
| 187 | 187 | |
| 188 | 188 | local void send_bits(s, value, length) |
| 189 | deflate_state *s; | |
| 190 | int value; /* value to send */ | |
| 191 | int length; /* number of bits */ | |
| 189 | deflate_state *s; | |
| 190 | int value; /* value to send */ | |
| 191 | int length; /* number of bits */ | |
| 192 | 192 | { |
| 193 | Tracevv((stderr," l %2d v %4x ", length, value)); | |
| 194 | Assert(length > 0 && length <= 15, "invalid length"); | |
| 195 | s->bits_sent += (ulg)length; | |
| 193 | Tracevv((stderr," l %2d v %4x ", length, value)); | |
| 194 | Assert(length > 0 && length <= 15, "invalid length"); | |
| 195 | s->bits_sent += (ulg)length; | |
| 196 | 196 | |
| 197 | /* If not enough room in bi_buf, use (valid) bits from bi_buf and | |
| 198 | * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) | |
| 199 | * unused bits in value. | |
| 200 | */ | |
| 201 | if (s->bi_valid > (int)Buf_size - length) { | |
| 202 | s->bi_buf |= (ush)value << s->bi_valid; | |
| 203 | put_short(s, s->bi_buf); | |
| 204 | s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); | |
| 205 | s->bi_valid += length - Buf_size; | |
| 206 | } else { | |
| 207 | s->bi_buf |= (ush)value << s->bi_valid; | |
| 208 | s->bi_valid += length; | |
| 209 | } | |
| 197 | /* If not enough room in bi_buf, use (valid) bits from bi_buf and | |
| 198 | * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) | |
| 199 | * unused bits in value. | |
| 200 | */ | |
| 201 | if (s->bi_valid > (int)Buf_size - length) { | |
| 202 | s->bi_buf |= (ush)value << s->bi_valid; | |
| 203 | put_short(s, s->bi_buf); | |
| 204 | s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); | |
| 205 | s->bi_valid += length - Buf_size; | |
| 206 | } else { | |
| 207 | s->bi_buf |= (ush)value << s->bi_valid; | |
| 208 | s->bi_valid += length; | |
| 209 | } | |
| 210 | 210 | } |
| 211 | 211 | #else /* !DEBUG */ |
| 212 | 212 | |
| 213 | 213 | #define send_bits(s, value, length) \ |
| 214 | 214 | { int len = length;\ |
| 215 | if (s->bi_valid > (int)Buf_size - len) {\ | |
| 216 | int val = value;\ | |
| 217 | s->bi_buf |= (ush)val << s->bi_valid;\ | |
| 218 | put_short(s, s->bi_buf);\ | |
| 219 | s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ | |
| 220 | s->bi_valid += len - Buf_size;\ | |
| 221 | } else {\ | |
| 222 | s->bi_buf |= (ush)(value) << s->bi_valid;\ | |
| 223 | s->bi_valid += len;\ | |
| 224 | }\ | |
| 215 | if (s->bi_valid > (int)Buf_size - len) {\ | |
| 216 | int val = value;\ | |
| 217 | s->bi_buf |= (ush)val << s->bi_valid;\ | |
| 218 | put_short(s, s->bi_buf);\ | |
| 219 | s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ | |
| 220 | s->bi_valid += len - Buf_size;\ | |
| 221 | } else {\ | |
| 222 | s->bi_buf |= (ush)(value) << s->bi_valid;\ | |
| 223 | s->bi_valid += len;\ | |
| 224 | }\ | |
| 225 | 225 | } |
| 226 | 226 | #endif /* DEBUG */ |
| 227 | 227 | |
| r25360 | r25361 | |
| 234 | 234 | local void tr_static_init() |
| 235 | 235 | { |
| 236 | 236 | #if defined(GEN_TREES_H) || !defined(STDC) |
| 237 | static int static_init_done = 0; | |
| 238 | int n; /* iterates over tree elements */ | |
| 239 | int bits; /* bit counter */ | |
| 240 | int length; /* length value */ | |
| 241 | int code; /* code value */ | |
| 242 | int dist; /* distance index */ | |
| 243 | ush bl_count[MAX_BITS+1]; | |
| 244 | /* number of codes at each bit length for an optimal tree */ | |
| 237 | static int static_init_done = 0; | |
| 238 | int n; /* iterates over tree elements */ | |
| 239 | int bits; /* bit counter */ | |
| 240 | int length; /* length value */ | |
| 241 | int code; /* code value */ | |
| 242 | int dist; /* distance index */ | |
| 243 | ush bl_count[MAX_BITS+1]; | |
| 244 | /* number of codes at each bit length for an optimal tree */ | |
| 245 | 245 | |
| 246 | ||
| 246 | if (static_init_done) return; | |
| 247 | 247 | |
| 248 | ||
| 248 | /* For some embedded targets, global variables are not initialized: */ | |
| 249 | 249 | #ifdef NO_INIT_GLOBAL_POINTERS |
| 250 | static_l_desc.static_tree = static_ltree; | |
| 251 | static_l_desc.extra_bits = extra_lbits; | |
| 252 | static_d_desc.static_tree = static_dtree; | |
| 253 | static_d_desc.extra_bits = extra_dbits; | |
| 254 | static_bl_desc.extra_bits = extra_blbits; | |
| 250 | static_l_desc.static_tree = static_ltree; | |
| 251 | static_l_desc.extra_bits = extra_lbits; | |
| 252 | static_d_desc.static_tree = static_dtree; | |
| 253 | static_d_desc.extra_bits = extra_dbits; | |
| 254 | static_bl_desc.extra_bits = extra_blbits; | |
| 255 | 255 | #endif |
| 256 | 256 | |
| 257 | /* Initialize the mapping length (0..255) -> length code (0..28) */ | |
| 258 | length = 0; | |
| 259 | for (code = 0; code < LENGTH_CODES-1; code++) { | |
| 260 | base_length[code] = length; | |
| 261 | for (n = 0; n < (1<<extra_lbits[code]); n++) { | |
| 262 | _length_code[length++] = (uch)code; | |
| 263 | } | |
| 264 | } | |
| 265 | Assert (length == 256, "tr_static_init: length != 256"); | |
| 266 | /* Note that the length 255 (match length 258) can be represented | |
| 267 | * in two different ways: code 284 + 5 bits or code 285, so we | |
| 268 | * overwrite length_code[255] to use the best encoding: | |
| 269 | */ | |
| 270 | _length_code[length-1] = (uch)code; | |
| 257 | /* Initialize the mapping length (0..255) -> length code (0..28) */ | |
| 258 | length = 0; | |
| 259 | for (code = 0; code < LENGTH_CODES-1; code++) { | |
| 260 | base_length[code] = length; | |
| 261 | for (n = 0; n < (1<<extra_lbits[code]); n++) { | |
| 262 | _length_code[length++] = (uch)code; | |
| 263 | } | |
| 264 | } | |
| 265 | Assert (length == 256, "tr_static_init: length != 256"); | |
| 266 | /* Note that the length 255 (match length 258) can be represented | |
| 267 | * in two different ways: code 284 + 5 bits or code 285, so we | |
| 268 | * overwrite length_code[255] to use the best encoding: | |
| 269 | */ | |
| 270 | _length_code[length-1] = (uch)code; | |
| 271 | 271 | |
| 272 | /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ | |
| 273 | dist = 0; | |
| 274 | for (code = 0 ; code < 16; code++) { | |
| 275 | base_dist[code] = dist; | |
| 276 | for (n = 0; n < (1<<extra_dbits[code]); n++) { | |
| 277 | _dist_code[dist++] = (uch)code; | |
| 278 | } | |
| 279 | } | |
| 280 | Assert (dist == 256, "tr_static_init: dist != 256"); | |
| 281 | dist >>= 7; /* from now on, all distances are divided by 128 */ | |
| 282 | for ( ; code < D_CODES; code++) { | |
| 283 | base_dist[code] = dist << 7; | |
| 284 | for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { | |
| 285 | _dist_code[256 + dist++] = (uch)code; | |
| 286 | } | |
| 287 | } | |
| 288 | Assert (dist == 256, "tr_static_init: 256+dist != 512"); | |
| 272 | /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ | |
| 273 | dist = 0; | |
| 274 | for (code = 0 ; code < 16; code++) { | |
| 275 | base_dist[code] = dist; | |
| 276 | for (n = 0; n < (1<<extra_dbits[code]); n++) { | |
| 277 | _dist_code[dist++] = (uch)code; | |
| 278 | } | |
| 279 | } | |
| 280 | Assert (dist == 256, "tr_static_init: dist != 256"); | |
| 281 | dist >>= 7; /* from now on, all distances are divided by 128 */ | |
| 282 | for ( ; code < D_CODES; code++) { | |
| 283 | base_dist[code] = dist << 7; | |
| 284 | for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { | |
| 285 | _dist_code[256 + dist++] = (uch)code; | |
| 286 | } | |
| 287 | } | |
| 288 | Assert (dist == 256, "tr_static_init: 256+dist != 512"); | |
| 289 | 289 | |
| 290 | /* Construct the codes of the static literal tree */ | |
| 291 | for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; | |
| 292 | n = 0; | |
| 293 | while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; | |
| 294 | while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; | |
| 295 | while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; | |
| 296 | while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; | |
| 297 | /* Codes 286 and 287 do not exist, but we must include them in the | |
| 298 | * tree construction to get a canonical Huffman tree (longest code | |
| 299 | * all ones) | |
| 300 | */ | |
| 301 | gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); | |
| 290 | /* Construct the codes of the static literal tree */ | |
| 291 | for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; | |
| 292 | n = 0; | |
| 293 | while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; | |
| 294 | while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; | |
| 295 | while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; | |
| 296 | while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; | |
| 297 | /* Codes 286 and 287 do not exist, but we must include them in the | |
| 298 | * tree construction to get a canonical Huffman tree (longest code | |
| 299 | * all ones) | |
| 300 | */ | |
| 301 | gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); | |
| 302 | 302 | |
| 303 | /* The static distance tree is trivial: */ | |
| 304 | for (n = 0; n < D_CODES; n++) { | |
| 305 | static_dtree[n].Len = 5; | |
| 306 | static_dtree[n].Code = bi_reverse((unsigned)n, 5); | |
| 307 | } | |
| 308 | static_init_done = 1; | |
| 303 | /* The static distance tree is trivial: */ | |
| 304 | for (n = 0; n < D_CODES; n++) { | |
| 305 | static_dtree[n].Len = 5; | |
| 306 | static_dtree[n].Code = bi_reverse((unsigned)n, 5); | |
| 307 | } | |
| 308 | static_init_done = 1; | |
| 309 | 309 | |
| 310 | 310 | # ifdef GEN_TREES_H |
| 311 | ||
| 311 | gen_trees_header(); | |
| 312 | 312 | # endif |
| 313 | 313 | #endif /* defined(GEN_TREES_H) || !defined(STDC) */ |
| 314 | 314 | } |
| r25360 | r25361 | |
| 322 | 322 | # endif |
| 323 | 323 | |
| 324 | 324 | # define SEPARATOR(i, last, width) \ |
| 325 | ((i) == (last)? "\n};\n\n" : \ | |
| 326 | ((i) % (width) == (width)-1 ? ",\n" : ", ")) | |
| 325 | ((i) == (last)? "\n};\n\n" : \ | |
| 326 | ((i) % (width) == (width)-1 ? ",\n" : ", ")) | |
| 327 | 327 | |
| 328 | 328 | void gen_trees_header() |
| 329 | 329 | { |
| 330 | FILE *header = fopen("trees.h", "w"); | |
| 331 | int i; | |
| 330 | FILE *header = fopen("trees.h", "w"); | |
| 331 | int i; | |
| 332 | 332 | |
| 333 | Assert (header != NULL, "Can't open trees.h"); | |
| 334 | fprintf(header, | |
| 335 | "/* header created automatically with -DGEN_TREES_H */\n\n"); | |
| 333 | Assert (header != NULL, "Can't open trees.h"); | |
| 334 | fprintf(header, | |
| 335 | "/* header created automatically with -DGEN_TREES_H */\n\n"); | |
| 336 | 336 | |
| 337 | fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); | |
| 338 | for (i = 0; i < L_CODES+2; i++) { | |
| 339 | fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, | |
| 340 | static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); | |
| 341 | } | |
| 337 | fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); | |
| 338 | for (i = 0; i < L_CODES+2; i++) { | |
| 339 | fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, | |
| 340 | static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); | |
| 341 | } | |
| 342 | 342 | |
| 343 | fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); | |
| 344 | for (i = 0; i < D_CODES; i++) { | |
| 345 | fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, | |
| 346 | static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); | |
| 347 | } | |
| 343 | fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); | |
| 344 | for (i = 0; i < D_CODES; i++) { | |
| 345 | fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, | |
| 346 | static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); | |
| 347 | } | |
| 348 | 348 | |
| 349 | fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); | |
| 350 | for (i = 0; i < DIST_CODE_LEN; i++) { | |
| 351 | fprintf(header, "%2u%s", _dist_code[i], | |
| 352 | SEPARATOR(i, DIST_CODE_LEN-1, 20)); | |
| 353 | } | |
| 349 | fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); | |
| 350 | for (i = 0; i < DIST_CODE_LEN; i++) { | |
| 351 | fprintf(header, "%2u%s", _dist_code[i], | |
| 352 | SEPARATOR(i, DIST_CODE_LEN-1, 20)); | |
| 353 | } | |
| 354 | 354 | |
| 355 | fprintf(header, | |
| 356 | "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); | |
| 357 | for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { | |
| 358 | fprintf(header, "%2u%s", _length_code[i], | |
| 359 | SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); | |
| 360 | } | |
| 355 | fprintf(header, | |
| 356 | "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); | |
| 357 | for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { | |
| 358 | fprintf(header, "%2u%s", _length_code[i], | |
| 359 | SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); | |
| 360 | } | |
| 361 | 361 | |
| 362 | fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); | |
| 363 | for (i = 0; i < LENGTH_CODES; i++) { | |
| 364 | fprintf(header, "%1u%s", base_length[i], | |
| 365 | SEPARATOR(i, LENGTH_CODES-1, 20)); | |
| 366 | } | |
| 362 | fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); | |
| 363 | for (i = 0; i < LENGTH_CODES; i++) { | |
| 364 | fprintf(header, "%1u%s", base_length[i], | |
| 365 | SEPARATOR(i, LENGTH_CODES-1, 20)); | |
| 366 | } | |
| 367 | 367 | |
| 368 | fprintf(header, "local const int base_dist[D_CODES] = {\n"); | |
| 369 | for (i = 0; i < D_CODES; i++) { | |
| 370 | fprintf(header, "%5u%s", base_dist[i], | |
| 371 | SEPARATOR(i, D_CODES-1, 10)); | |
| 372 | } | |
| 368 | fprintf(header, "local const int base_dist[D_CODES] = {\n"); | |
| 369 | for (i = 0; i < D_CODES; i++) { | |
| 370 | fprintf(header, "%5u%s", base_dist[i], | |
| 371 | SEPARATOR(i, D_CODES-1, 10)); | |
| 372 | } | |
| 373 | 373 | |
| 374 | ||
| 374 | fclose(header); | |
| 375 | 375 | } |
| 376 | 376 | #endif /* GEN_TREES_H */ |
| 377 | 377 | |
| r25360 | r25361 | |
| 379 | 379 | * Initialize the tree data structures for a new zlib stream. |
| 380 | 380 | */ |
| 381 | 381 | void ZLIB_INTERNAL _tr_init(s) |
| 382 | ||
| 382 | deflate_state *s; | |
| 383 | 383 | { |
| 384 | ||
| 384 | tr_static_init(); | |
| 385 | 385 | |
| 386 | s->l_desc.dyn_tree = s->dyn_ltree; | |
| 387 | s->l_desc.stat_desc = &static_l_desc; | |
| 386 | s->l_desc.dyn_tree = s->dyn_ltree; | |
| 387 | s->l_desc.stat_desc = &static_l_desc; | |
| 388 | 388 | |
| 389 | s->d_desc.dyn_tree = s->dyn_dtree; | |
| 390 | s->d_desc.stat_desc = &static_d_desc; | |
| 389 | s->d_desc.dyn_tree = s->dyn_dtree; | |
| 390 | s->d_desc.stat_desc = &static_d_desc; | |
| 391 | 391 | |
| 392 | s->bl_desc.dyn_tree = s->bl_tree; | |
| 393 | s->bl_desc.stat_desc = &static_bl_desc; | |
| 392 | s->bl_desc.dyn_tree = s->bl_tree; | |
| 393 | s->bl_desc.stat_desc = &static_bl_desc; | |
| 394 | 394 | |
| 395 | s->bi_buf = 0; | |
| 396 | s->bi_valid = 0; | |
| 395 | s->bi_buf = 0; | |
| 396 | s->bi_valid = 0; | |
| 397 | 397 | #ifdef DEBUG |
| 398 | s->compressed_len = 0L; | |
| 399 | s->bits_sent = 0L; | |
| 398 | s->compressed_len = 0L; | |
| 399 | s->bits_sent = 0L; | |
| 400 | 400 | #endif |
| 401 | 401 | |
| 402 | /* Initialize the first block of the first file: */ | |
| 403 | init_block(s); | |
| 402 | /* Initialize the first block of the first file: */ | |
| 403 | init_block(s); | |
| 404 | 404 | } |
| 405 | 405 | |
| 406 | 406 | /* =========================================================================== |
| 407 | 407 | * Initialize a new block. |
| 408 | 408 | */ |
| 409 | 409 | local void init_block(s) |
| 410 | ||
| 410 | deflate_state *s; | |
| 411 | 411 | { |
| 412 | ||
| 412 | int n; /* iterates over tree elements */ | |
| 413 | 413 | |
| 414 | /* Initialize the trees. */ | |
| 415 | for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; | |
| 416 | for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; | |
| 417 | for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; | |
| 414 | /* Initialize the trees. */ | |
| 415 | for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; | |
| 416 | for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; | |
| 417 | for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; | |
| 418 | 418 | |
| 419 | s->dyn_ltree[END_BLOCK].Freq = 1; | |
| 420 | s->opt_len = s->static_len = 0L; | |
| 421 | s->last_lit = s->matches = 0; | |
| 419 | s->dyn_ltree[END_BLOCK].Freq = 1; | |
| 420 | s->opt_len = s->static_len = 0L; | |
| 421 | s->last_lit = s->matches = 0; | |
| 422 | 422 | } |
| 423 | 423 | |
| 424 | 424 | #define SMALLEST 1 |
| r25360 | r25361 | |
| 431 | 431 | */ |
| 432 | 432 | #define pqremove(s, tree, top) \ |
| 433 | 433 | {\ |
| 434 | top = s->heap[SMALLEST]; \ | |
| 435 | s->heap[SMALLEST] = s->heap[s->heap_len--]; \ | |
| 436 | pqdownheap(s, tree, SMALLEST); \ | |
| 434 | top = s->heap[SMALLEST]; \ | |
| 435 | s->heap[SMALLEST] = s->heap[s->heap_len--]; \ | |
| 436 | pqdownheap(s, tree, SMALLEST); \ | |
| 437 | 437 | } |
| 438 | 438 | |
| 439 | 439 | /* =========================================================================== |
| r25360 | r25361 | |
| 441 | 441 | * the subtrees have equal frequency. This minimizes the worst case length. |
| 442 | 442 | */ |
| 443 | 443 | #define smaller(tree, n, m, depth) \ |
| 444 | (tree[n].Freq < tree[m].Freq || \ | |
| 445 | (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) | |
| 444 | (tree[n].Freq < tree[m].Freq || \ | |
| 445 | (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) | |
| 446 | 446 | |
| 447 | 447 | /* =========================================================================== |
| 448 | 448 | * Restore the heap property by moving down the tree starting at node k, |
| r25360 | r25361 | |
| 451 | 451 | * two sons). |
| 452 | 452 | */ |
| 453 | 453 | local void pqdownheap(s, tree, k) |
| 454 | deflate_state *s; | |
| 455 | ct_data *tree; /* the tree to restore */ | |
| 456 | int k; /* node to move down */ | |
| 454 | deflate_state *s; | |
| 455 | ct_data *tree; /* the tree to restore */ | |
| 456 | int k; /* node to move down */ | |
| 457 | 457 | { |
| 458 | int v = s->heap[k]; | |
| 459 | int j = k << 1; /* left son of k */ | |
| 460 | while (j <= s->heap_len) { | |
| 461 | /* Set j to the smallest of the two sons: */ | |
| 462 | if (j < s->heap_len && | |
| 463 | smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { | |
| 464 | j++; | |
| 465 | } | |
| 466 | /* Exit if v is smaller than both sons */ | |
| 467 | if (smaller(tree, v, s->heap[j], s->depth)) break; | |
| 458 | int v = s->heap[k]; | |
| 459 | int j = k << 1; /* left son of k */ | |
| 460 | while (j <= s->heap_len) { | |
| 461 | /* Set j to the smallest of the two sons: */ | |
| 462 | if (j < s->heap_len && | |
| 463 | smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { | |
| 464 | j++; | |
| 465 | } | |
| 466 | /* Exit if v is smaller than both sons */ | |
| 467 | if (smaller(tree, v, s->heap[j], s->depth)) break; | |
| 468 | 468 | |
| 469 | /* Exchange v with the smallest son */ | |
| 470 | s->heap[k] = s->heap[j]; k = j; | |
| 469 | /* Exchange v with the smallest son */ | |
| 470 | s->heap[k] = s->heap[j]; k = j; | |
| 471 | 471 | |
| 472 | /* And continue down the tree, setting j to the left son of k */ | |
| 473 | j <<= 1; | |
| 474 | } | |
| 475 | s->heap[k] = v; | |
| 472 | /* And continue down the tree, setting j to the left son of k */ | |
| 473 | j <<= 1; | |
| 474 | } | |
| 475 | s->heap[k] = v; | |
| 476 | 476 | } |
| 477 | 477 | |
| 478 | 478 | /* =========================================================================== |
| r25360 | r25361 | |
| 486 | 486 | * not null. |
| 487 | 487 | */ |
| 488 | 488 | local void gen_bitlen(s, desc) |
| 489 | deflate_state *s; | |
| 490 | tree_desc *desc; /* the tree descriptor */ | |
| 489 | deflate_state *s; | |
| 490 | tree_desc *desc; /* the tree descriptor */ | |
| 491 | 491 | { |
| 492 | ct_data *tree = desc->dyn_tree; | |
| 493 | int max_code = desc->max_code; | |
| 494 | const ct_data *stree = desc->stat_desc->static_tree; | |
| 495 | const intf *extra = desc->stat_desc->extra_bits; | |
| 496 | int base = desc->stat_desc->extra_base; | |
| 497 | int max_length = desc->stat_desc->max_length; | |
| 498 | int h; /* heap index */ | |
| 499 | int n, m; /* iterate over the tree elements */ | |
| 500 | int bits; /* bit length */ | |
| 501 | int xbits; /* extra bits */ | |
| 502 | ush f; /* frequency */ | |
| 503 | int overflow = 0; /* number of elements with bit length too large */ | |
| 492 | ct_data *tree = desc->dyn_tree; | |
| 493 | int max_code = desc->max_code; | |
| 494 | const ct_data *stree = desc->stat_desc->static_tree; | |
| 495 | const intf *extra = desc->stat_desc->extra_bits; | |
| 496 | int base = desc->stat_desc->extra_base; | |
| 497 | int max_length = desc->stat_desc->max_length; | |
| 498 | int h; /* heap index */ | |
| 499 | int n, m; /* iterate over the tree elements */ | |
| 500 | int bits; /* bit length */ | |
| 501 | int xbits; /* extra bits */ | |
| 502 | ush f; /* frequency */ | |
| 503 | int overflow = 0; /* number of elements with bit length too large */ | |
| 504 | 504 | |
| 505 | ||
| 505 | for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; | |
| 506 | 506 | |
| 507 | /* In a first pass, compute the optimal bit lengths (which may | |
| 508 | * overflow in the case of the bit length tree). | |
| 509 | */ | |
| 510 | tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ | |
| 507 | /* In a first pass, compute the optimal bit lengths (which may | |
| 508 | * overflow in the case of the bit length tree). | |
| 509 | */ | |
| 510 | tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ | |
| 511 | 511 | |
| 512 | for (h = s->heap_max+1; h < HEAP_SIZE; h++) { | |
| 513 | n = s->heap[h]; | |
| 514 | bits = tree[tree[n].Dad].Len + 1; | |
| 515 | if (bits > max_length) bits = max_length, overflow++; | |
| 516 | tree[n].Len = (ush)bits; | |
| 517 | /* We overwrite tree[n].Dad which is no longer needed */ | |
| 512 | for (h = s->heap_max+1; h < HEAP_SIZE; h++) { | |
| 513 | n = s->heap[h]; | |
| 514 | bits = tree[tree[n].Dad].Len + 1; | |
| 515 | if (bits > max_length) bits = max_length, overflow++; | |
| 516 | tree[n].Len = (ush)bits; | |
| 517 | /* We overwrite tree[n].Dad which is no longer needed */ | |
| 518 | 518 | |
| 519 | ||
| 519 | if (n > max_code) continue; /* not a leaf node */ | |
| 520 | 520 | |
| 521 | s->bl_count[bits]++; | |
| 522 | xbits = 0; | |
| 523 | if (n >= base) xbits = extra[n-base]; | |
| 524 | f = tree[n].Freq; | |
| 525 | s->opt_len += (ulg)f * (bits + xbits); | |
| 526 | if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); | |
| 527 | } | |
| 528 | if (overflow == 0) return; | |
| 521 | s->bl_count[bits]++; | |
| 522 | xbits = 0; | |
| 523 | if (n >= base) xbits = extra[n-base]; | |
| 524 | f = tree[n].Freq; | |
| 525 | s->opt_len += (ulg)f * (bits + xbits); | |
| 526 | if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); | |
| 527 | } | |
| 528 | if (overflow == 0) return; | |
| 529 | 529 | |
| 530 | Trace((stderr,"\nbit length overflow\n")); | |
| 531 | /* This happens for example on obj2 and pic of the Calgary corpus */ | |
| 530 | Trace((stderr,"\nbit length overflow\n")); | |
| 531 | /* This happens for example on obj2 and pic of the Calgary corpus */ | |
| 532 | 532 | |
| 533 | /* Find the first bit length which could increase: */ | |
| 534 | do { | |
| 535 | bits = max_length-1; | |
| 536 | while (s->bl_count[bits] == 0) bits--; | |
| 537 | s->bl_count[bits]--; /* move one leaf down the tree */ | |
| 538 | s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ | |
| 539 | s->bl_count[max_length]--; | |
| 540 | /* The brother of the overflow item also moves one step up, | |
| 541 | * but this does not affect bl_count[max_length] | |
| 542 | */ | |
| 543 | overflow -= 2; | |
| 544 | } while (overflow > 0); | |
| 533 | /* Find the first bit length which could increase: */ | |
| 534 | do { | |
| 535 | bits = max_length-1; | |
| 536 | while (s->bl_count[bits] == 0) bits--; | |
| 537 | s->bl_count[bits]--; /* move one leaf down the tree */ | |
| 538 | s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ | |
| 539 | s->bl_count[max_length]--; | |
| 540 | /* The brother of the overflow item also moves one step up, | |
| 541 | * but this does not affect bl_count[max_length] | |
| 542 | */ | |
| 543 | overflow -= 2; | |
| 544 | } while (overflow > 0); | |
| 545 | 545 | |
| 546 | /* Now recompute all bit lengths, scanning in increasing frequency. | |
| 547 | * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all | |
| 548 | * lengths instead of fixing only the wrong ones. This idea is taken | |
| 549 | * from 'ar' written by Haruhiko Okumura.) | |
| 550 | */ | |
| 551 | for (bits = max_length; bits != 0; bits--) { | |
| 552 | n = s->bl_count[bits]; | |
| 553 | while (n != 0) { | |
| 554 | m = s->heap[--h]; | |
| 555 | if (m > max_code) continue; | |
| 556 | if ((unsigned) tree[m].Len != (unsigned) bits) { | |
| 557 | Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); | |
| 558 | s->opt_len += ((long)bits - (long)tree[m].Len) | |
| 559 | *(long)tree[m].Freq; | |
| 560 | tree[m].Len = (ush)bits; | |
| 561 | } | |
| 562 | n--; | |
| 563 | } | |
| 564 | } | |
| 546 | /* Now recompute all bit lengths, scanning in increasing frequency. | |
| 547 | * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all | |
| 548 | * lengths instead of fixing only the wrong ones. This idea is taken | |
| 549 | * from 'ar' written by Haruhiko Okumura.) | |
| 550 | */ | |
| 551 | for (bits = max_length; bits != 0; bits--) { | |
| 552 | n = s->bl_count[bits]; | |
| 553 | while (n != 0) { | |
| 554 | m = s->heap[--h]; | |
| 555 | if (m > max_code) continue; | |
| 556 | if ((unsigned) tree[m].Len != (unsigned) bits) { | |
| 557 | Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); | |
| 558 | s->opt_len += ((long)bits - (long)tree[m].Len) | |
| 559 | *(long)tree[m].Freq; | |
| 560 | tree[m].Len = (ush)bits; | |
| 561 | } | |
| 562 | n--; | |
| 563 | } | |
| 564 | } | |
| 565 | 565 | } |
| 566 | 566 | |
| 567 | 567 | /* =========================================================================== |
| r25360 | r25361 | |
| 573 | 573 | * zero code length. |
| 574 | 574 | */ |
| 575 | 575 | local void gen_codes (tree, max_code, bl_count) |
| 576 | ct_data *tree; /* the tree to decorate */ | |
| 577 | int max_code; /* largest code with non zero frequency */ | |
| 578 | ushf *bl_count; /* number of codes at each bit length */ | |
| 576 | ct_data *tree; /* the tree to decorate */ | |
| 577 | int max_code; /* largest code with non zero frequency */ | |
| 578 | ushf *bl_count; /* number of codes at each bit length */ | |
| 579 | 579 | { |
| 580 | ush next_code[MAX_BITS+1]; /* next code value for each bit length */ | |
| 581 | ush code = 0; /* running code value */ | |
| 582 | int bits; /* bit index */ | |
| 583 | int n; /* code index */ | |
| 580 | ush next_code[MAX_BITS+1]; /* next code value for each bit length */ | |
| 581 | ush code = 0; /* running code value */ | |
| 582 | int bits; /* bit index */ | |
| 583 | int n; /* code index */ | |
| 584 | 584 | |
| 585 | /* The distribution counts are first used to generate the code values | |
| 586 | * without bit reversal. | |
| 587 | */ | |
| 588 | for (bits = 1; bits <= MAX_BITS; bits++) { | |
| 589 | next_code[bits] = code = (code + bl_count[bits-1]) << 1; | |
| 590 | } | |
| 591 | /* Check that the bit counts in bl_count are consistent. The last code | |
| 592 | * must be all ones. | |
| 593 | */ | |
| 594 | Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1, | |
| 595 | "inconsistent bit counts"); | |
| 596 | Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); | |
| 585 | /* The distribution counts are first used to generate the code values | |
| 586 | * without bit reversal. | |
| 587 | */ | |
| 588 | for (bits = 1; bits <= MAX_BITS; bits++) { | |
| 589 | next_code[bits] = code = (code + bl_count[bits-1]) << 1; | |
| 590 | } | |
| 591 | /* Check that the bit counts in bl_count are consistent. The last code | |
| 592 | * must be all ones. | |
| 593 | */ | |
| 594 | Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1, | |
| 595 | "inconsistent bit counts"); | |
| 596 | Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); | |
| 597 | 597 | |
| 598 | for (n = 0; n <= max_code; n++) { | |
| 599 | int len = tree[n].Len; | |
| 600 | if (len == 0) continue; | |
| 601 | /* Now reverse the bits */ | |
| 602 | tree[n].Code = bi_reverse(next_code[len]++, len); | |
| 598 | for (n = 0; n <= max_code; n++) { | |
| 599 | int len = tree[n].Len; | |
| 600 | if (len == 0) continue; | |
| 601 | /* Now reverse the bits */ | |
| 602 | tree[n].Code = bi_reverse(next_code[len]++, len); | |
| 603 | 603 | |
| 604 | Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", | |
| 605 | n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); | |
| 606 | } | |
| 604 | Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", | |
| 605 | n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); | |
| 606 | } | |
| 607 | 607 | } |
| 608 | 608 | |
| 609 | 609 | /* =========================================================================== |
| r25360 | r25361 | |
| 615 | 615 | * also updated if stree is not null. The field max_code is set. |
| 616 | 616 | */ |
| 617 | 617 | local void build_tree(s, desc) |
| 618 | deflate_state *s; | |
| 619 | tree_desc *desc; /* the tree descriptor */ | |
| 618 | deflate_state *s; | |
| 619 | tree_desc *desc; /* the tree descriptor */ | |
| 620 | 620 | { |
| 621 | ct_data *tree = desc->dyn_tree; | |
| 622 | const ct_data *stree = desc->stat_desc->static_tree; | |
| 623 | int elems = desc->stat_desc->elems; | |
| 624 | int n, m; /* iterate over heap elements */ | |
| 625 | int max_code = -1; /* largest code with non zero frequency */ | |
| 626 | int node; /* new node being created */ | |
| 621 | ct_data *tree = desc->dyn_tree; | |
| 622 | const ct_data *stree = desc->stat_desc->static_tree; | |
| 623 | int elems = desc->stat_desc->elems; | |
| 624 | int n, m; /* iterate over heap elements */ | |
| 625 | int max_code = -1; /* largest code with non zero frequency */ | |
| 626 | int node; /* new node being created */ | |
| 627 | 627 | |
| 628 | /* Construct the initial heap, with least frequent element in | |
| 629 | * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. | |
| 630 | * heap[0] is not used. | |
| 631 | */ | |
| 632 | s->heap_len = 0, s->heap_max = HEAP_SIZE; | |
| 628 | /* Construct the initial heap, with least frequent element in | |
| 629 | * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. | |
| 630 | * heap[0] is not used. | |
| 631 | */ | |
| 632 | s->heap_len = 0, s->heap_max = HEAP_SIZE; | |
| 633 | 633 | |
| 634 | for (n = 0; n < elems; n++) { | |
| 635 | if (tree[n].Freq != 0) { | |
| 636 | s->heap[++(s->heap_len)] = max_code = n; | |
| 637 | s->depth[n] = 0; | |
| 638 | } else { | |
| 639 | tree[n].Len = 0; | |
| 640 | } | |
| 641 | } | |
| 634 | for (n = 0; n < elems; n++) { | |
| 635 | if (tree[n].Freq != 0) { | |
| 636 | s->heap[++(s->heap_len)] = max_code = n; | |
| 637 | s->depth[n] = 0; | |
| 638 | } else { | |
| 639 | tree[n].Len = 0; | |
| 640 | } | |
| 641 | } | |
| 642 | 642 | |
| 643 | /* The pkzip format requires that at least one distance code exists, | |
| 644 | * and that at least one bit should be sent even if there is only one | |
| 645 | * possible code. So to avoid special checks later on we force at least | |
| 646 | * two codes of non zero frequency. | |
| 647 | */ | |
| 648 | while (s->heap_len < 2) { | |
| 649 | node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); | |
| 650 | tree[node].Freq = 1; | |
| 651 | s->depth[node] = 0; | |
| 652 | s->opt_len--; if (stree) s->static_len -= stree[node].Len; | |
| 653 | /* node is 0 or 1 so it does not have extra bits */ | |
| 654 | } | |
| 655 | desc->max_code = max_code; | |
| 643 | /* The pkzip format requires that at least one distance code exists, | |
| 644 | * and that at least one bit should be sent even if there is only one | |
| 645 | * possible code. So to avoid special checks later on we force at least | |
| 646 | * two codes of non zero frequency. | |
| 647 | */ | |
| 648 | while (s->heap_len < 2) { | |
| 649 | node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); | |
| 650 | tree[node].Freq = 1; | |
| 651 | s->depth[node] = 0; | |
| 652 | s->opt_len--; if (stree) s->static_len -= stree[node].Len; | |
| 653 | /* node is 0 or 1 so it does not have extra bits */ | |
| 654 | } | |
| 655 | desc->max_code = max_code; | |
| 656 | 656 | |
| 657 | /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, | |
| 658 | * establish sub-heaps of increasing lengths: | |
| 659 | */ | |
| 660 | for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); | |
| 657 | /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, | |
| 658 | * establish sub-heaps of increasing lengths: | |
| 659 | */ | |
| 660 | for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); | |
| 661 | 661 | |
| 662 | /* Construct the Huffman tree by repeatedly combining the least two | |
| 663 | * frequent nodes. | |
| 664 | */ | |
| 665 | node = elems; /* next internal node of the tree */ | |
| 666 | do { | |
| 667 | pqremove(s, tree, n); /* n = node of least frequency */ | |
| 668 | m = s->heap[SMALLEST]; /* m = node of next least frequency */ | |
| 662 | /* Construct the Huffman tree by repeatedly combining the least two | |
| 663 | * frequent nodes. | |
| 664 | */ | |
| 665 | node = elems; /* next internal node of the tree */ | |
| 666 | do { | |
| 667 | pqremove(s, tree, n); /* n = node of least frequency */ | |
| 668 | m = s->heap[SMALLEST]; /* m = node of next least frequency */ | |
| 669 | 669 | |
| 670 | s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ | |
| 671 | s->heap[--(s->heap_max)] = m; | |
| 670 | s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ | |
| 671 | s->heap[--(s->heap_max)] = m; | |
| 672 | 672 | |
| 673 | /* Create a new node father of n and m */ | |
| 674 | tree[node].Freq = tree[n].Freq + tree[m].Freq; | |
| 675 | s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? | |
| 676 | s->depth[n] : s->depth[m]) + 1); | |
| 677 | tree[n].Dad = tree[m].Dad = (ush)node; | |
| 673 | /* Create a new node father of n and m */ | |
| 674 | tree[node].Freq = tree[n].Freq + tree[m].Freq; | |
| 675 | s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? | |
| 676 | s->depth[n] : s->depth[m]) + 1); | |
| 677 | tree[n].Dad = tree[m].Dad = (ush)node; | |
| 678 | 678 | #ifdef DUMP_BL_TREE |
| 679 | if (tree == s->bl_tree) { | |
| 680 | fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", | |
| 681 | node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); | |
| 682 | } | |
| 679 | if (tree == s->bl_tree) { | |
| 680 | fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", | |
| 681 | node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); | |
| 682 | } | |
| 683 | 683 | #endif |
| 684 | /* and insert the new node in the heap */ | |
| 685 | s->heap[SMALLEST] = node++; | |
| 686 | pqdownheap(s, tree, SMALLEST); | |
| 684 | /* and insert the new node in the heap */ | |
| 685 | s->heap[SMALLEST] = node++; | |
| 686 | pqdownheap(s, tree, SMALLEST); | |
| 687 | 687 | |
| 688 | ||
| 688 | } while (s->heap_len >= 2); | |
| 689 | 689 | |
| 690 | ||
| 690 | s->heap[--(s->heap_max)] = s->heap[SMALLEST]; | |
| 691 | 691 | |
| 692 | /* At this point, the fields freq and dad are set. We can now | |
| 693 | * generate the bit lengths. | |
| 694 | */ | |
| 695 | gen_bitlen(s, (tree_desc *)desc); | |
| 692 | /* At this point, the fields freq and dad are set. We can now | |
| 693 | * generate the bit lengths. | |
| 694 | */ | |
| 695 | gen_bitlen(s, (tree_desc *)desc); | |
| 696 | 696 | |
| 697 | /* The field len is now set, we can generate the bit codes */ | |
| 698 | gen_codes ((ct_data *)tree, max_code, s->bl_count); | |
| 697 | /* The field len is now set, we can generate the bit codes */ | |
| 698 | gen_codes ((ct_data *)tree, max_code, s->bl_count); | |
| 699 | 699 | } |
| 700 | 700 | |
| 701 | 701 | /* =========================================================================== |
| r25360 | r25361 | |
| 703 | 703 | * in the bit length tree. |
| 704 | 704 | */ |
| 705 | 705 | local void scan_tree (s, tree, max_code) |
| 706 | deflate_state *s; | |
| 707 | ct_data *tree; /* the tree to be scanned */ | |
| 708 | int max_code; /* and its largest code of non zero frequency */ | |
| 706 | deflate_state *s; | |
| 707 | ct_data *tree; /* the tree to be scanned */ | |
| 708 | int max_code; /* and its largest code of non zero frequency */ | |
| 709 | 709 | { |
| 710 | int n; /* iterates over all tree elements */ | |
| 711 | int prevlen = -1; /* last emitted length */ | |
| 712 | int curlen; /* length of current code */ | |
| 713 | int nextlen = tree[0].Len; /* length of next code */ | |
| 714 | int count = 0; /* repeat count of the current code */ | |
| 715 | int max_count = 7; /* max repeat count */ | |
| 716 | int min_count = 4; /* min repeat count */ | |
| 710 | int n; /* iterates over all tree elements */ | |
| 711 | int prevlen = -1; /* last emitted length */ | |
| 712 | int curlen; /* length of current code */ | |
| 713 | int nextlen = tree[0].Len; /* length of next code */ | |
| 714 | int count = 0; /* repeat count of the current code */ | |
| 715 | int max_count = 7; /* max repeat count */ | |
| 716 | int min_count = 4; /* min repeat count */ | |
| 717 | 717 | |
| 718 | if (nextlen == 0) max_count = 138, min_count = 3; | |
| 719 | tree[max_code+1].Len = (ush)0xffff; /* guard */ | |
| 718 | if (nextlen == 0) max_count = 138, min_count = 3; | |
| 719 | tree[max_code+1].Len = (ush)0xffff; /* guard */ | |
| 720 | 720 | |
| 721 | for (n = 0; n <= max_code; n++) { | |
| 722 | curlen = nextlen; nextlen = tree[n+1].Len; | |
| 723 | if (++count < max_count && curlen == nextlen) { | |
| 724 | continue; | |
| 725 | } else if (count < min_count) { | |
| 726 | s->bl_tree[curlen].Freq += count; | |
| 727 | } else if (curlen != 0) { | |
| 728 | if (curlen != prevlen) s->bl_tree[curlen].Freq++; | |
| 729 | s->bl_tree[REP_3_6].Freq++; | |
| 730 | } else if (count <= 10) { | |
| 731 | s->bl_tree[REPZ_3_10].Freq++; | |
| 732 | } else { | |
| 733 | s->bl_tree[REPZ_11_138].Freq++; | |
| 734 | } | |
| 735 | count = 0; prevlen = curlen; | |
| 736 | if (nextlen == 0) { | |
| 737 | max_count = 138, min_count = 3; | |
| 738 | } else if (curlen == nextlen) { | |
| 739 | max_count = 6, min_count = 3; | |
| 740 | } else { | |
| 741 | max_count = 7, min_count = 4; | |
| 742 | } | |
| 743 | } | |
| 721 | for (n = 0; n <= max_code; n++) { | |
| 722 | curlen = nextlen; nextlen = tree[n+1].Len; | |
| 723 | if (++count < max_count && curlen == nextlen) { | |
| 724 | continue; | |
| 725 | } else if (count < min_count) { | |
| 726 | s->bl_tree[curlen].Freq += count; | |
| 727 | } else if (curlen != 0) { | |
| 728 | if (curlen != prevlen) s->bl_tree[curlen].Freq++; | |
| 729 | s->bl_tree[REP_3_6].Freq++; | |
| 730 | } else if (count <= 10) { | |
| 731 | s->bl_tree[REPZ_3_10].Freq++; | |
| 732 | } else { | |
| 733 | s->bl_tree[REPZ_11_138].Freq++; | |
| 734 | } | |
| 735 | count = 0; prevlen = curlen; | |
| 736 | if (nextlen == 0) { | |
| 737 | max_count = 138, min_count = 3; | |
| 738 | } else if (curlen == nextlen) { | |
| 739 | max_count = 6, min_count = 3; | |
| 740 | } else { | |
| 741 | max_count = 7, min_count = 4; | |
| 742 | } | |
| 743 | } | |
| 744 | 744 | } |
| 745 | 745 | |
| 746 | 746 | /* =========================================================================== |
| r25360 | r25361 | |
| 748 | 748 | * bl_tree. |
| 749 | 749 | */ |
| 750 | 750 | local void send_tree (s, tree, max_code) |
| 751 | deflate_state *s; | |
| 752 | ct_data *tree; /* the tree to be scanned */ | |
| 753 | int max_code; /* and its largest code of non zero frequency */ | |
| 751 | deflate_state *s; | |
| 752 | ct_data *tree; /* the tree to be scanned */ | |
| 753 | int max_code; /* and its largest code of non zero frequency */ | |
| 754 | 754 | { |
| 755 | int n; /* iterates over all tree elements */ | |
| 756 | int prevlen = -1; /* last emitted length */ | |
| 757 | int curlen; /* length of current code */ | |
| 758 | int nextlen = tree[0].Len; /* length of next code */ | |
| 759 | int count = 0; /* repeat count of the current code */ | |
| 760 | int max_count = 7; /* max repeat count */ | |
| 761 | int min_count = 4; /* min repeat count */ | |
| 755 | int n; /* iterates over all tree elements */ | |
| 756 | int prevlen = -1; /* last emitted length */ | |
| 757 | int curlen; /* length of current code */ | |
| 758 | int nextlen = tree[0].Len; /* length of next code */ | |
| 759 | int count = 0; /* repeat count of the current code */ | |
| 760 | int max_count = 7; /* max repeat count */ | |
| 761 | int min_count = 4; /* min repeat count */ | |
| 762 | 762 | |
| 763 | /* tree[max_code+1].Len = -1; */ /* guard already set */ | |
| 764 | if (nextlen == 0) max_count = 138, min_count = 3; | |
| 763 | /* tree[max_code+1].Len = -1; */ /* guard already set */ | |
| 764 | if (nextlen == 0) max_count = 138, min_count = 3; | |
| 765 | 765 | |
| 766 | for (n = 0; n <= max_code; n++) { | |
| 767 | curlen = nextlen; nextlen = tree[n+1].Len; | |
| 768 | if (++count < max_count && curlen == nextlen) { | |
| 769 | continue; | |
| 770 | } else if (count < min_count) { | |
| 771 | do { send_code(s, curlen, s->bl_tree); } while (--count != 0); | |
| 766 | for (n = 0; n <= max_code; n++) { | |
| 767 | curlen = nextlen; nextlen = tree[n+1].Len; | |
| 768 | if (++count < max_count && curlen == nextlen) { | |
| 769 | continue; | |
| 770 | } else if (count < min_count) { | |
| 771 | do { send_code(s, curlen, s->bl_tree); } while (--count != 0); | |
| 772 | 772 | |
| 773 | } else if (curlen != 0) { | |
| 774 | if (curlen != prevlen) { | |
| 775 | send_code(s, curlen, s->bl_tree); count--; | |
| 776 | } | |
| 777 | Assert(count >= 3 && count <= 6, " 3_6?"); | |
| 778 | send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); | |
| 773 | } else if (curlen != 0) { | |
| 774 | if (curlen != prevlen) { | |
| 775 | send_code(s, curlen, s->bl_tree); count--; | |
| 776 | } | |
| 777 | Assert(count >= 3 && count <= 6, " 3_6?"); | |
| 778 | send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); | |
| 779 | 779 | |
| 780 | } else if (count <= 10) { | |
| 781 | send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); | |
| 780 | } else if (count <= 10) { | |
| 781 | send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); | |
| 782 | 782 | |
| 783 | } else { | |
| 784 | send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); | |
| 785 | } | |
| 786 | count = 0; prevlen = curlen; | |
| 787 | if (nextlen == 0) { | |
| 788 | max_count = 138, min_count = 3; | |
| 789 | } else if (curlen == nextlen) { | |
| 790 | max_count = 6, min_count = 3; | |
| 791 | } else { | |
| 792 | max_count = 7, min_count = 4; | |
| 793 | } | |
| 794 | } | |
| 783 | } else { | |
| 784 | send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); | |
| 785 | } | |
| 786 | count = 0; prevlen = curlen; | |
| 787 | if (nextlen == 0) { | |
| 788 | max_count = 138, min_count = 3; | |
| 789 | } else if (curlen == nextlen) { | |
| 790 | max_count = 6, min_count = 3; | |
| 791 | } else { | |
| 792 | max_count = 7, min_count = 4; | |
| 793 | } | |
| 794 | } | |
| 795 | 795 | } |
| 796 | 796 | |
| 797 | 797 | /* =========================================================================== |
| r25360 | r25361 | |
| 799 | 799 | * bl_order of the last bit length code to send. |
| 800 | 800 | */ |
| 801 | 801 | local int build_bl_tree(s) |
| 802 | ||
| 802 | deflate_state *s; | |
| 803 | 803 | { |
| 804 | ||
| 804 | int max_blindex; /* index of last bit length code of non zero freq */ | |
| 805 | 805 | |
| 806 | /* Determine the bit length frequencies for literal and distance trees */ | |
| 807 | scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); | |
| 808 | scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); | |
| 806 | /* Determine the bit length frequencies for literal and distance trees */ | |
| 807 | scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); | |
| 808 | scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); | |
| 809 | 809 | |
| 810 | /* Build the bit length tree: */ | |
| 811 | build_tree(s, (tree_desc *)(&(s->bl_desc))); | |
| 812 | /* opt_len now includes the length of the tree representations, except | |
| 813 | * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. | |
| 814 | */ | |
| 810 | /* Build the bit length tree: */ | |
| 811 | build_tree(s, (tree_desc *)(&(s->bl_desc))); | |
| 812 | /* opt_len now includes the length of the tree representations, except | |
| 813 | * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. | |
| 814 | */ | |
| 815 | 815 | |
| 816 | /* Determine the number of bit length codes to send. The pkzip format | |
| 817 | * requires that at least 4 bit length codes be sent. (appnote.txt says | |
| 818 | * 3 but the actual value used is 4.) | |
| 819 | */ | |
| 820 | for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { | |
| 821 | if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; | |
| 822 | } | |
| 823 | /* Update opt_len to include the bit length tree and counts */ | |
| 824 | s->opt_len += 3*(max_blindex+1) + 5+5+4; | |
| 825 | Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", | |
| 826 | s->opt_len, s->static_len)); | |
| 816 | /* Determine the number of bit length codes to send. The pkzip format | |
| 817 | * requires that at least 4 bit length codes be sent. (appnote.txt says | |
| 818 | * 3 but the actual value used is 4.) | |
| 819 | */ | |
| 820 | for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { | |
| 821 | if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; | |
| 822 | } | |
| 823 | /* Update opt_len to include the bit length tree and counts */ | |
| 824 | s->opt_len += 3*(max_blindex+1) + 5+5+4; | |
| 825 | Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", | |
| 826 | s->opt_len, s->static_len)); | |
| 827 | 827 | |
| 828 | ||
| 828 | return max_blindex; | |
| 829 | 829 | } |
| 830 | 830 | |
| 831 | 831 | /* =========================================================================== |
| r25360 | r25361 | |
| 834 | 834 | * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. |
| 835 | 835 | */ |
| 836 | 836 | local void send_all_trees(s, lcodes, dcodes, blcodes) |
| 837 | deflate_state *s; | |
| 838 | int lcodes, dcodes, blcodes; /* number of codes for each tree */ | |
| 837 | deflate_state *s; | |
| 838 | int lcodes, dcodes, blcodes; /* number of codes for each tree */ | |
| 839 | 839 | { |
| 840 | ||
| 840 | int rank; /* index in bl_order */ | |
| 841 | 841 | |
| 842 | Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); | |
| 843 | Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, | |
| 844 | "too many codes"); | |
| 845 | Tracev((stderr, "\nbl counts: ")); | |
| 846 | send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ | |
| 847 | send_bits(s, dcodes-1, 5); | |
| 848 | send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ | |
| 849 | for (rank = 0; rank < blcodes; rank++) { | |
| 850 | Tracev((stderr, "\nbl code %2d ", bl_order[rank])); | |
| 851 | send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); | |
| 852 | } | |
| 853 | Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); | |
| 842 | Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); | |
| 843 | Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, | |
| 844 | "too many codes"); | |
| 845 | Tracev((stderr, "\nbl counts: ")); | |
| 846 | send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ | |
| 847 | send_bits(s, dcodes-1, 5); | |
| 848 | send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ | |
| 849 | for (rank = 0; rank < blcodes; rank++) { | |
| 850 | Tracev((stderr, "\nbl code %2d ", bl_order[rank])); | |
| 851 | send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); | |
| 852 | } | |
| 853 | Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); | |
| 854 | 854 | |
| 855 | send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ | |
| 856 | Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); | |
| 855 | send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ | |
| 856 | Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); | |
| 857 | 857 | |
| 858 | send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ | |
| 859 | Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); | |
| 858 | send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ | |
| 859 | Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); | |
| 860 | 860 | } |
| 861 | 861 | |
| 862 | 862 | /* =========================================================================== |
| 863 | 863 | * Send a stored block |
| 864 | 864 | */ |
| 865 | 865 | void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) |
| 866 | deflate_state *s; | |
| 867 | charf *buf; /* input block */ | |
| 868 | ulg stored_len; /* length of input block */ | |
| 869 | int last; /* one if this is the last block for a file */ | |
| 866 | deflate_state *s; | |
| 867 | charf *buf; /* input block */ | |
| 868 | ulg stored_len; /* length of input block */ | |
| 869 | int last; /* one if this is the last block for a file */ | |
| 870 | 870 | { |
| 871 | ||
| 871 | send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */ | |
| 872 | 872 | #ifdef DEBUG |
| 873 | s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; | |
| 874 | s->compressed_len += (stored_len + 4) << 3; | |
| 873 | s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; | |
| 874 | s->compressed_len += (stored_len + 4) << 3; | |
| 875 | 875 | #endif |
| 876 | ||
| 876 | copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ | |
| 877 | 877 | } |
| 878 | 878 | |
| 879 | 879 | /* =========================================================================== |
| 880 | 880 | * Flush the bits in the bit buffer to pending output (leaves at most 7 bits) |
| 881 | 881 | */ |
| 882 | 882 | void ZLIB_INTERNAL _tr_flush_bits(s) |
| 883 | ||
| 883 | deflate_state *s; | |
| 884 | 884 | { |
| 885 | ||
| 885 | bi_flush(s); | |
| 886 | 886 | } |
| 887 | 887 | |
| 888 | 888 | /* =========================================================================== |
| r25360 | r25361 | |
| 890 | 890 | * This takes 10 bits, of which 7 may remain in the bit buffer. |
| 891 | 891 | */ |
| 892 | 892 | void ZLIB_INTERNAL _tr_align(s) |
| 893 | ||
| 893 | deflate_state *s; | |
| 894 | 894 | { |
| 895 | send_bits(s, STATIC_TREES<<1, 3); | |
| 896 | send_code(s, END_BLOCK, static_ltree); | |
| 895 | send_bits(s, STATIC_TREES<<1, 3); | |
| 896 | send_code(s, END_BLOCK, static_ltree); | |
| 897 | 897 | #ifdef DEBUG |
| 898 | ||
| 898 | s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ | |
| 899 | 899 | #endif |
| 900 | ||
| 900 | bi_flush(s); | |
| 901 | 901 | } |
| 902 | 902 | |
| 903 | 903 | /* =========================================================================== |
| r25360 | r25361 | |
| 905 | 905 | * trees or store, and output the encoded block to the zip file. |
| 906 | 906 | */ |
| 907 | 907 | void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) |
| 908 | deflate_state *s; | |
| 909 | charf *buf; /* input block, or NULL if too old */ | |
| 910 | ulg stored_len; /* length of input block */ | |
| 911 | int last; /* one if this is the last block for a file */ | |
| 908 | deflate_state *s; | |
| 909 | charf *buf; /* input block, or NULL if too old */ | |
| 910 | ulg stored_len; /* length of input block */ | |
| 911 | int last; /* one if this is the last block for a file */ | |
| 912 | 912 | { |
| 913 | ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ | |
| 914 | int max_blindex = 0; /* index of last bit length code of non zero freq */ | |
| 913 | ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ | |
| 914 | int max_blindex = 0; /* index of last bit length code of non zero freq */ | |
| 915 | 915 | |
| 916 | /* Build the Huffman trees unless a stored block is forced */ | |
| 917 | if (s->level > 0) { | |
| 916 | /* Build the Huffman trees unless a stored block is forced */ | |
| 917 | if (s->level > 0) { | |
| 918 | /* Check if the file is binary or text */ | |
| 919 | if (s->strm->data_type == Z_UNKNOWN) | |
| 920 | s->strm->data_type = detect_data_type(s); | |
| 918 | 921 | |
| 919 | /* Check if the file is binary or text */ | |
| 920 | if (s->strm->data_type == Z_UNKNOWN) | |
| 921 | s->strm->data_type = detect_data_type(s); | |
| 922 | /* Construct the literal and distance trees */ | |
| 923 | build_tree(s, (tree_desc *)(&(s->l_desc))); | |
| 924 | Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, | |
| 925 | s->static_len)); | |
| 922 | 926 | |
| 923 | /* Construct the literal and distance trees */ | |
| 924 | build_tree(s, (tree_desc *)(&(s->l_desc))); | |
| 925 | Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, | |
| 926 | s->static_len)); | |
| 927 | build_tree(s, (tree_desc *)(&(s->d_desc))); | |
| 928 | Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, | |
| 929 | s->static_len)); | |
| 930 | /* At this point, opt_len and static_len are the total bit lengths of | |
| 931 | * the compressed block data, excluding the tree representations. | |
| 932 | */ | |
| 927 | 933 | |
| 928 | build_tree(s, (tree_desc *)(&(s->d_desc))); | |
| 929 | Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, | |
| 930 | s->static_len)); | |
| 931 | /* At this point, opt_len and static_len are the total bit lengths of | |
| 932 | * the compressed block data, excluding the tree representations. | |
| 933 | */ | |
| 934 | /* Build the bit length tree for the above two trees, and get the index | |
| 935 | * in bl_order of the last bit length code to send. | |
| 936 | */ | |
| 937 | max_blindex = build_bl_tree(s); | |
| 934 | 938 | |
| 935 | /* Build the bit length tree for the above two trees, and get the index | |
| 936 | * in bl_order of the last bit length code to send. | |
| 937 | */ | |
| 938 | max_blindex = build_bl_tree(s); | |
| 939 | /* Determine the best encoding. Compute the block lengths in bytes. */ | |
| 940 | opt_lenb = (s->opt_len+3+7)>>3; | |
| 941 | static_lenb = (s->static_len+3+7)>>3; | |
| 939 | 942 | |
| 940 | /* Determine the best encoding. Compute the block lengths in bytes. */ | |
| 941 | opt_lenb = (s->opt_len+3+7)>>3; | |
| 942 | static_lenb = (s->static_len+3+7)>>3; | |
| 943 | Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", | |
| 944 | opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, | |
| 945 | s->last_lit)); | |
| 943 | 946 | |
| 944 | Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", | |
| 945 | opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, | |
| 946 | s->last_lit)); | |
| 947 | if (static_lenb <= opt_lenb) opt_lenb = static_lenb; | |
| 947 | 948 | |
| 948 | if (static_lenb <= opt_lenb) opt_lenb = static_lenb; | |
| 949 | } else { | |
| 950 | Assert(buf != (char*)0, "lost buf"); | |
| 951 | opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ | |
| 952 | } | |
| 949 | 953 | |
| 950 | } else { | |
| 951 | Assert(buf != (char*)0, "lost buf"); | |
| 952 | opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ | |
| 953 | } | |
| 954 | ||
| 955 | 954 | #ifdef FORCE_STORED |
| 956 | ||
| 955 | if (buf != (char*)0) { /* force stored block */ | |
| 957 | 956 | #else |
| 958 | if (stored_len+4 <= opt_lenb && buf != (char*)0) { | |
| 959 | /* 4: two words for the lengths */ | |
| 957 | if (stored_len+4 <= opt_lenb && buf != (char*)0) { | |
| 958 | /* 4: two words for the lengths */ | |
| 960 | 959 | #endif |
| 961 | /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. | |
| 962 | * Otherwise we can't have processed more than WSIZE input bytes since | |
| 963 | * the last block flush, because compression would have been | |
| 964 | * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to | |
| 965 | * transform a block into a stored block. | |
| 966 | */ | |
| 967 | _tr_stored_block(s, buf, stored_len, last); | |
| 960 | /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. | |
| 961 | * Otherwise we can't have processed more than WSIZE input bytes since | |
| 962 | * the last block flush, because compression would have been | |
| 963 | * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to | |
| 964 | * transform a block into a stored block. | |
| 965 | */ | |
| 966 | _tr_stored_block(s, buf, stored_len, last); | |
| 968 | 967 | |
| 969 | 968 | #ifdef FORCE_STATIC |
| 970 | ||
| 969 | } else if (static_lenb >= 0) { /* force static trees */ | |
| 971 | 970 | #else |
| 972 | ||
| 971 | } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { | |
| 973 | 972 | #endif |
| 974 | send_bits(s, (STATIC_TREES<<1)+last, 3); | |
| 975 | compress_block(s, (const ct_data *)static_ltree, | |
| 976 | (const ct_data *)static_dtree); | |
| 973 | send_bits(s, (STATIC_TREES<<1)+last, 3); | |
| 974 | compress_block(s, (const ct_data *)static_ltree, | |
| 975 | (const ct_data *)static_dtree); | |
| 977 | 976 | #ifdef DEBUG |
| 978 | ||
| 977 | s->compressed_len += 3 + s->static_len; | |
| 979 | 978 | #endif |
| 980 | } else { | |
| 981 | send_bits(s, (DYN_TREES<<1)+last, 3); | |
| 982 | send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, | |
| 983 | max_blindex+1); | |
| 984 | compress_block(s, (const ct_data *)s->dyn_ltree, | |
| 985 | (const ct_data *)s->dyn_dtree); | |
| 979 | } else { | |
| 980 | send_bits(s, (DYN_TREES<<1)+last, 3); | |
| 981 | send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, | |
| 982 | max_blindex+1); | |
| 983 | compress_block(s, (const ct_data *)s->dyn_ltree, | |
| 984 | (const ct_data *)s->dyn_dtree); | |
| 986 | 985 | #ifdef DEBUG |
| 987 | ||
| 986 | s->compressed_len += 3 + s->opt_len; | |
| 988 | 987 | #endif |
| 989 | } | |
| 990 | Assert (s->compressed_len == s->bits_sent, "bad compressed size"); | |
| 991 | /* The above check is made mod 2^32, for files larger than 512 MB | |
| 992 | * and uLong implemented on 32 bits. | |
| 993 | */ | |
| 994 | init_block(s); | |
| 988 | } | |
| 989 | Assert (s->compressed_len == s->bits_sent, "bad compressed size"); | |
| 990 | /* The above check is made mod 2^32, for files larger than 512 MB | |
| 991 | * and uLong implemented on 32 bits. | |
| 992 | */ | |
| 993 | init_block(s); | |
| 995 | 994 | |
| 996 | if (last) { | |
| 997 | bi_windup(s); | |
| 995 | if (last) { | |
| 996 | bi_windup(s); | |
| 998 | 997 | #ifdef DEBUG |
| 999 | ||
| 998 | s->compressed_len += 7; /* align on byte boundary */ | |
| 1000 | 999 | #endif |
| 1001 | } | |
| 1002 | Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, | |
| 1003 | s->compressed_len-7*last)); | |
| 1000 | } | |
| 1001 | Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, | |
| 1002 | s->compressed_len-7*last)); | |
| 1004 | 1003 | } |
| 1005 | 1004 | |
| 1006 | 1005 | /* =========================================================================== |
| r25360 | r25361 | |
| 1008 | 1007 | * the current block must be flushed. |
| 1009 | 1008 | */ |
| 1010 | 1009 | int ZLIB_INTERNAL _tr_tally (s, dist, lc) |
| 1011 | deflate_state *s; | |
| 1012 | unsigned dist; /* distance of matched string */ | |
| 1013 | unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ | |
| 1010 | deflate_state *s; | |
| 1011 | unsigned dist; /* distance of matched string */ | |
| 1012 | unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ | |
| 1014 | 1013 | { |
| 1015 | s->d_buf[s->last_lit] = (ush)dist; | |
| 1016 | s->l_buf[s->last_lit++] = (uch)lc; | |
| 1017 | if (dist == 0) { | |
| 1018 | /* lc is the unmatched char */ | |
| 1019 | s->dyn_ltree[lc].Freq++; | |
| 1020 | } else { | |
| 1021 | s->matches++; | |
| 1022 | /* Here, lc is the match length - MIN_MATCH */ | |
| 1023 | dist--; /* dist = match distance - 1 */ | |
| 1024 | Assert((ush)dist < (ush)MAX_DIST(s) && | |
| 1025 | (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && | |
| 1026 | (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); | |
| 1014 | s->d_buf[s->last_lit] = (ush)dist; | |
| 1015 | s->l_buf[s->last_lit++] = (uch)lc; | |
| 1016 | if (dist == 0) { | |
| 1017 | /* lc is the unmatched char */ | |
| 1018 | s->dyn_ltree[lc].Freq++; | |
| 1019 | } else { | |
| 1020 | s->matches++; | |
| 1021 | /* Here, lc is the match length - MIN_MATCH */ | |
| 1022 | dist--; /* dist = match distance - 1 */ | |
| 1023 | Assert((ush)dist < (ush)MAX_DIST(s) && | |
| 1024 | (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && | |
| 1025 | (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); | |
| 1027 | 1026 | |
| 1028 | s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; | |
| 1029 | s->dyn_dtree[d_code(dist)].Freq++; | |
| 1030 | } | |
| 1027 | s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; | |
| 1028 | s->dyn_dtree[d_code(dist)].Freq++; | |
| 1029 | } | |
| 1031 | 1030 | |
| 1032 | 1031 | #ifdef TRUNCATE_BLOCK |
| 1033 | /* Try to guess if it is profitable to stop the current block here */ | |
| 1034 | if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { | |
| 1035 | /* Compute an upper bound for the compressed length */ | |
| 1036 | ulg out_length = (ulg)s->last_lit*8L; | |
| 1037 | ulg in_length = (ulg)((long)s->strstart - s->block_start); | |
| 1038 | int dcode; | |
| 1039 | for (dcode = 0; dcode < D_CODES; dcode++) { | |
| 1040 | out_length += (ulg)s->dyn_dtree[dcode].Freq * | |
| 1041 | (5L+extra_dbits[dcode]); | |
| 1042 | } | |
| 1043 | out_length >>= 3; | |
| 1044 | Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", | |
| 1045 | s->last_lit, in_length, out_length, | |
| 1046 | 100L - out_length*100L/in_length)); | |
| 1047 | if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; | |
| 1048 | } | |
| 1032 | /* Try to guess if it is profitable to stop the current block here */ | |
| 1033 | if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { | |
| 1034 | /* Compute an upper bound for the compressed length */ | |
| 1035 | ulg out_length = (ulg)s->last_lit*8L; | |
| 1036 | ulg in_length = (ulg)((long)s->strstart - s->block_start); | |
| 1037 | int dcode; | |
| 1038 | for (dcode = 0; dcode < D_CODES; dcode++) { | |
| 1039 | out_length += (ulg)s->dyn_dtree[dcode].Freq * | |
| 1040 | (5L+extra_dbits[dcode]); | |
| 1041 | } | |
| 1042 | out_length >>= 3; | |
| 1043 | Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", | |
| 1044 | s->last_lit, in_length, out_length, | |
| 1045 | 100L - out_length*100L/in_length)); | |
| 1046 | if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; | |
| 1047 | } | |
| 1049 | 1048 | #endif |
| 1050 | return (s->last_lit == s->lit_bufsize-1); | |
| 1051 | /* We avoid equality with lit_bufsize because of wraparound at 64K | |
| 1052 | * on 16 bit machines and because stored blocks are restricted to | |
| 1053 | * 64K-1 bytes. | |
| 1054 | */ | |
| 1049 | return (s->last_lit == s->lit_bufsize-1); | |
| 1050 | /* We avoid equality with lit_bufsize because of wraparound at 64K | |
| 1051 | * on 16 bit machines and because stored blocks are restricted to | |
| 1052 | * 64K-1 bytes. | |
| 1053 | */ | |
| 1055 | 1054 | } |
| 1056 | 1055 | |
| 1057 | 1056 | /* =========================================================================== |
| 1058 | 1057 | * Send the block data compressed using the given Huffman trees |
| 1059 | 1058 | */ |
| 1060 | 1059 | local void compress_block(s, ltree, dtree) |
| 1061 | deflate_state *s; | |
| 1062 | const ct_data *ltree; /* literal tree */ | |
| 1063 | const ct_data *dtree; /* distance tree */ | |
| 1060 | deflate_state *s; | |
| 1061 | const ct_data *ltree; /* literal tree */ | |
| 1062 | const ct_data *dtree; /* distance tree */ | |
| 1064 | 1063 | { |
| 1065 | unsigned dist; /* distance of matched string */ | |
| 1066 | int lc; /* match length or unmatched char (if dist == 0) */ | |
| 1067 | unsigned lx = 0; /* running index in l_buf */ | |
| 1068 | unsigned code; /* the code to send */ | |
| 1069 | int extra; /* number of extra bits to send */ | |
| 1064 | unsigned dist; /* distance of matched string */ | |
| 1065 | int lc; /* match length or unmatched char (if dist == 0) */ | |
| 1066 | unsigned lx = 0; /* running index in l_buf */ | |
| 1067 | unsigned code; /* the code to send */ | |
| 1068 | int extra; /* number of extra bits to send */ | |
| 1070 | 1069 | |
| 1071 | if (s->last_lit != 0) do { | |
| 1072 | dist = s->d_buf[lx]; | |
| 1073 | lc = s->l_buf[lx++]; | |
| 1074 | if (dist == 0) { | |
| 1075 | send_code(s, lc, ltree); /* send a literal byte */ | |
| 1076 | Tracecv(isgraph(lc), (stderr," '%c' ", lc)); | |
| 1077 | } else { | |
| 1078 | /* Here, lc is the match length - MIN_MATCH */ | |
| 1079 | code = _length_code[lc]; | |
| 1080 | send_code(s, code+LITERALS+1, ltree); /* send the length code */ | |
| 1081 | extra = extra_lbits[code]; | |
| 1082 | if (extra != 0) { | |
| 1083 | lc -= base_length[code]; | |
| 1084 | send_bits(s, lc, extra); /* send the extra length bits */ | |
| 1085 | } | |
| 1086 | dist--; /* dist is now the match distance - 1 */ | |
| 1087 | code = d_code(dist); | |
| 1088 | Assert (code < D_CODES, "bad d_code"); | |
| 1070 | if (s->last_lit != 0) do { | |
| 1071 | dist = s->d_buf[lx]; | |
| 1072 | lc = s->l_buf[lx++]; | |
| 1073 | if (dist == 0) { | |
| 1074 | send_code(s, lc, ltree); /* send a literal byte */ | |
| 1075 | Tracecv(isgraph(lc), (stderr," '%c' ", lc)); | |
| 1076 | } else { | |
| 1077 | /* Here, lc is the match length - MIN_MATCH */ | |
| 1078 | code = _length_code[lc]; | |
| 1079 | send_code(s, code+LITERALS+1, ltree); /* send the length code */ | |
| 1080 | extra = extra_lbits[code]; | |
| 1081 | if (extra != 0) { | |
| 1082 | lc -= base_length[code]; | |
| 1083 | send_bits(s, lc, extra); /* send the extra length bits */ | |
| 1084 | } | |
| 1085 | dist--; /* dist is now the match distance - 1 */ | |
| 1086 | code = d_code(dist); | |
| 1087 | Assert (code < D_CODES, "bad d_code"); | |
| 1089 | 1088 | |
| 1090 | send_code(s, code, dtree); /* send the distance code */ | |
| 1091 | extra = extra_dbits[code]; | |
| 1092 | if (extra != 0) { | |
| 1093 | dist -= base_dist[code]; | |
| 1094 | send_bits(s, dist, extra); /* send the extra distance bits */ | |
| 1095 | } | |
| 1096 | } /* literal or match pair ? */ | |
| 1089 | send_code(s, code, dtree); /* send the distance code */ | |
| 1090 | extra = extra_dbits[code]; | |
| 1091 | if (extra != 0) { | |
| 1092 | dist -= base_dist[code]; | |
| 1093 | send_bits(s, dist, extra); /* send the extra distance bits */ | |
| 1094 | } | |
| 1095 | } /* literal or match pair ? */ | |
| 1097 | 1096 | |
| 1098 | /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ | |
| 1099 | Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, | |
| 1100 | "pendingBuf overflow"); | |
| 1097 | /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ | |
| 1098 | Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, | |
| 1099 | "pendingBuf overflow"); | |
| 1101 | 1100 | |
| 1102 | ||
| 1101 | } while (lx < s->last_lit); | |
| 1103 | 1102 | |
| 1104 | ||
| 1103 | send_code(s, END_BLOCK, ltree); | |
| 1105 | 1104 | } |
| 1106 | 1105 | |
| 1107 | 1106 | /* =========================================================================== |
| r25360 | r25361 | |
| 1118 | 1117 | * IN assertion: the fields Freq of dyn_ltree are set. |
| 1119 | 1118 | */ |
| 1120 | 1119 | local int detect_data_type(s) |
| 1121 | ||
| 1120 | deflate_state *s; | |
| 1122 | 1121 | { |
| 1123 | /* black_mask is the bit mask of black-listed bytes | |
| 1124 | * set bits 0..6, 14..25, and 28..31 | |
| 1125 | * 0xf3ffc07f = binary 11110011111111111100000001111111 | |
| 1126 | */ | |
| 1127 | unsigned long black_mask = 0xf3ffc07fUL; | |
| 1128 | int n; | |
| 1122 | /* black_mask is the bit mask of black-listed bytes | |
| 1123 | * set bits 0..6, 14..25, and 28..31 | |
| 1124 | * 0xf3ffc07f = binary 11110011111111111100000001111111 | |
| 1125 | */ | |
| 1126 | unsigned long black_mask = 0xf3ffc07fUL; | |
| 1127 | int n; | |
| 1129 | 1128 | |
| 1130 | /* Check for non-textual ("black-listed") bytes. */ | |
| 1131 | for (n = 0; n <= 31; n++, black_mask >>= 1) | |
| 1132 | if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0)) | |
| 1133 | return Z_BINARY; | |
| 1129 | /* Check for non-textual ("black-listed") bytes. */ | |
| 1130 | for (n = 0; n <= 31; n++, black_mask >>= 1) | |
| 1131 | if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0)) | |
| 1132 | return Z_BINARY; | |
| 1134 | 1133 | |
| 1135 | /* Check for textual ("white-listed") bytes. */ | |
| 1136 | if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 | |
| 1137 | || s->dyn_ltree[13].Freq != 0) | |
| 1138 | return Z_TEXT; | |
| 1139 | for (n = 32; n < LITERALS; n++) | |
| 1140 | if (s->dyn_ltree[n].Freq != 0) | |
| 1141 | return Z_TEXT; | |
| 1134 | /* Check for textual ("white-listed") bytes. */ | |
| 1135 | if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 | |
| 1136 | || s->dyn_ltree[13].Freq != 0) | |
| 1137 | return Z_TEXT; | |
| 1138 | for (n = 32; n < LITERALS; n++) | |
| 1139 | if (s->dyn_ltree[n].Freq != 0) | |
| 1140 | return Z_TEXT; | |
| 1142 | 1141 | |
| 1143 | /* There are no "black-listed" or "white-listed" bytes: | |
| 1144 | * this stream either is empty or has tolerated ("gray-listed") bytes only. | |
| 1145 | */ | |
| 1146 | return Z_BINARY; | |
| 1142 | /* There are no "black-listed" or "white-listed" bytes: | |
| 1143 | * this stream either is empty or has tolerated ("gray-listed") bytes only. | |
| 1144 | */ | |
| 1145 | return Z_BINARY; | |
| 1147 | 1146 | } |
| 1148 | 1147 | |
| 1149 | 1148 | /* =========================================================================== |
| r25360 | r25361 | |
| 1152 | 1151 | * IN assertion: 1 <= len <= 15 |
| 1153 | 1152 | */ |
| 1154 | 1153 | local unsigned bi_reverse(code, len) |
| 1155 | unsigned code; /* the value to invert */ | |
| 1156 | int len; /* its bit length */ | |
| 1154 | unsigned code; /* the value to invert */ | |
| 1155 | int len; /* its bit length */ | |
| 1157 | 1156 | { |
| 1158 | register unsigned res = 0; | |
| 1159 | do { | |
| 1160 | res |= code & 1; | |
| 1161 | code >>= 1, res <<= 1; | |
| 1162 | } while (--len > 0); | |
| 1163 | return res >> 1; | |
| 1157 | register unsigned res = 0; | |
| 1158 | do { | |
| 1159 | res |= code & 1; | |
| 1160 | code >>= 1, res <<= 1; | |
| 1161 | } while (--len > 0); | |
| 1162 | return res >> 1; | |
| 1164 | 1163 | } |
| 1165 | 1164 | |
| 1166 | 1165 | /* =========================================================================== |
| 1167 | 1166 | * Flush the bit buffer, keeping at most 7 bits in it. |
| 1168 | 1167 | */ |
| 1169 | 1168 | local void bi_flush(s) |
| 1170 | ||
| 1169 | deflate_state *s; | |
| 1171 | 1170 | { |
| 1172 | if (s->bi_valid == 16) { | |
| 1173 | put_short(s, s->bi_buf); | |
| 1174 | s->bi_buf = 0; | |
| 1175 | s->bi_valid = 0; | |
| 1176 | } else if (s->bi_valid >= 8) { | |
| 1177 | put_byte(s, (Byte)s->bi_buf); | |
| 1178 | s->bi_buf >>= 8; | |
| 1179 | s->bi_valid -= 8; | |
| 1180 | } | |
| 1171 | if (s->bi_valid == 16) { | |
| 1172 | put_short(s, s->bi_buf); | |
| 1173 | s->bi_buf = 0; | |
| 1174 | s->bi_valid = 0; | |
| 1175 | } else if (s->bi_valid >= 8) { | |
| 1176 | put_byte(s, (Byte)s->bi_buf); | |
| 1177 | s->bi_buf >>= 8; | |
| 1178 | s->bi_valid -= 8; | |
| 1179 | } | |
| 1181 | 1180 | } |
| 1182 | 1181 | |
| 1183 | 1182 | /* =========================================================================== |
| 1184 | 1183 | * Flush the bit buffer and align the output on a byte boundary |
| 1185 | 1184 | */ |
| 1186 | 1185 | local void bi_windup(s) |
| 1187 | ||
| 1186 | deflate_state *s; | |
| 1188 | 1187 | { |
| 1189 | if (s->bi_valid > 8) { | |
| 1190 | put_short(s, s->bi_buf); | |
| 1191 | } else if (s->bi_valid > 0) { | |
| 1192 | put_byte(s, (Byte)s->bi_buf); | |
| 1193 | } | |
| 1194 | s->bi_buf = 0; | |
| 1195 | s->bi_valid = 0; | |
| 1188 | if (s->bi_valid > 8) { | |
| 1189 | put_short(s, s->bi_buf); | |
| 1190 | } else if (s->bi_valid > 0) { | |
| 1191 | put_byte(s, (Byte)s->bi_buf); | |
| 1192 | } | |
| 1193 | s->bi_buf = 0; | |
| 1194 | s->bi_valid = 0; | |
| 1196 | 1195 | #ifdef DEBUG |
| 1197 | ||
| 1196 | s->bits_sent = (s->bits_sent+7) & ~7; | |
| 1198 | 1197 | #endif |
| 1199 | 1198 | } |
| 1200 | 1199 | |
| r25360 | r25361 | |
| 1203 | 1202 | * one's complement if requested. |
| 1204 | 1203 | */ |
| 1205 | 1204 | local void copy_block(s, buf, len, header) |
| 1206 | deflate_state *s; | |
| 1207 | charf *buf; /* the input data */ | |
| 1208 | unsigned len; /* its length */ | |
| 1209 | int header; /* true if block header must be written */ | |
| 1205 | deflate_state *s; | |
| 1206 | charf *buf; /* the input data */ | |
| 1207 | unsigned len; /* its length */ | |
| 1208 | int header; /* true if block header must be written */ | |
| 1210 | 1209 | { |
| 1211 | ||
| 1210 | bi_windup(s); /* align on byte boundary */ | |
| 1212 | 1211 | |
| 1213 | if (header) { | |
| 1214 | put_short(s, (ush)len); | |
| 1215 | put_short(s, (ush)~len); | |
| 1212 | if (header) { | |
| 1213 | put_short(s, (ush)len); | |
| 1214 | put_short(s, (ush)~len); | |
| 1216 | 1215 | #ifdef DEBUG |
| 1217 | ||
| 1216 | s->bits_sent += 2*16; | |
| 1218 | 1217 | #endif |
| 1219 | ||
| 1218 | } | |
| 1220 | 1219 | #ifdef DEBUG |
| 1221 | ||
| 1220 | s->bits_sent += (ulg)len<<3; | |
| 1222 | 1221 | #endif |
| 1223 | while (len--) { | |
| 1224 | put_byte(s, *buf++); | |
| 1225 | } | |
| 1222 | while (len--) { | |
| 1223 | put_byte(s, *buf++); | |
| 1224 | } | |
| 1226 | 1225 | } |
| r25360 | r25361 | |
|---|---|---|
| 94 | 94 | /* function prototypes */ |
| 95 | 95 | local void fixedtables OF((struct inflate_state FAR *state)); |
| 96 | 96 | local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, |
| 97 | ||
| 97 | unsigned copy)); | |
| 98 | 98 | #ifdef BUILDFIXED |
| 99 | ||
| 99 | void makefixed OF((void)); | |
| 100 | 100 | #endif |
| 101 | 101 | local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, |
| 102 | ||
| 102 | unsigned len)); | |
| 103 | 103 | |
| 104 | 104 | int ZEXPORT inflateResetKeep(strm) |
| 105 | 105 | z_streamp strm; |
| 106 | 106 | { |
| 107 | ||
| 107 | struct inflate_state FAR *state; | |
| 108 | 108 | |
| 109 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 110 | state = (struct inflate_state FAR *)strm->state; | |
| 111 | strm->total_in = strm->total_out = state->total = 0; | |
| 112 | strm->msg = Z_NULL; | |
| 113 | if (state->wrap) /* to support ill-conceived Java test suite */ | |
| 114 | strm->adler = state->wrap & 1; | |
| 115 | state->mode = HEAD; | |
| 116 | state->last = 0; | |
| 117 | state->havedict = 0; | |
| 118 | state->dmax = 32768U; | |
| 119 | state->head = Z_NULL; | |
| 120 | state->hold = 0; | |
| 121 | state->bits = 0; | |
| 122 | state->lencode = state->distcode = state->next = state->codes; | |
| 123 | state->sane = 1; | |
| 124 | state->back = -1; | |
| 125 | Tracev((stderr, "inflate: reset\n")); | |
| 126 | return Z_OK; | |
| 109 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 110 | state = (struct inflate_state FAR *)strm->state; | |
| 111 | strm->total_in = strm->total_out = state->total = 0; | |
| 112 | strm->msg = Z_NULL; | |
| 113 | if (state->wrap) /* to support ill-conceived Java test suite */ | |
| 114 | strm->adler = state->wrap & 1; | |
| 115 | state->mode = HEAD; | |
| 116 | state->last = 0; | |
| 117 | state->havedict = 0; | |
| 118 | state->dmax = 32768U; | |
| 119 | state->head = Z_NULL; | |
| 120 | state->hold = 0; | |
| 121 | state->bits = 0; | |
| 122 | state->lencode = state->distcode = state->next = state->codes; | |
| 123 | state->sane = 1; | |
| 124 | state->back = -1; | |
| 125 | Tracev((stderr, "inflate: reset\n")); | |
| 126 | return Z_OK; | |
| 127 | 127 | } |
| 128 | 128 | |
| 129 | 129 | int ZEXPORT inflateReset(strm) |
| 130 | 130 | z_streamp strm; |
| 131 | 131 | { |
| 132 | ||
| 132 | struct inflate_state FAR *state; | |
| 133 | 133 | |
| 134 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 135 | state = (struct inflate_state FAR *)strm->state; | |
| 136 | state->wsize = 0; | |
| 137 | state->whave = 0; | |
| 138 | state->wnext = 0; | |
| 139 | return inflateResetKeep(strm); | |
| 134 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 135 | state = (struct inflate_state FAR *)strm->state; | |
| 136 | state->wsize = 0; | |
| 137 | state->whave = 0; | |
| 138 | state->wnext = 0; | |
| 139 | return inflateResetKeep(strm); | |
| 140 | 140 | } |
| 141 | 141 | |
| 142 | 142 | int ZEXPORT inflateReset2(strm, windowBits) |
| 143 | 143 | z_streamp strm; |
| 144 | 144 | int windowBits; |
| 145 | 145 | { |
| 146 | int wrap; | |
| 147 | struct inflate_state FAR *state; | |
| 146 | int wrap; | |
| 147 | struct inflate_state FAR *state; | |
| 148 | 148 | |
| 149 | /* get the state */ | |
| 150 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 151 | state = (struct inflate_state FAR *)strm->state; | |
| 149 | /* get the state */ | |
| 150 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 151 | state = (struct inflate_state FAR *)strm->state; | |
| 152 | 152 | |
| 153 | /* extract wrap request from windowBits parameter */ | |
| 154 | if (windowBits < 0) { | |
| 155 | wrap = 0; | |
| 156 | windowBits = -windowBits; | |
| 157 | } | |
| 158 | else { | |
| 159 | wrap = (windowBits >> 4) + 1; | |
| 153 | /* extract wrap request from windowBits parameter */ | |
| 154 | if (windowBits < 0) { | |
| 155 | wrap = 0; | |
| 156 | windowBits = -windowBits; | |
| 157 | } | |
| 158 | else { | |
| 159 | wrap = (windowBits >> 4) + 1; | |
| 160 | 160 | #ifdef GUNZIP |
| 161 | if (windowBits < 48) | |
| 162 | windowBits &= 15; | |
| 161 | if (windowBits < 48) | |
| 162 | windowBits &= 15; | |
| 163 | 163 | #endif |
| 164 | ||
| 164 | } | |
| 165 | 165 | |
| 166 | /* set number of window bits, free window if different */ | |
| 167 | if (windowBits && (windowBits < 8 || windowBits > 15)) | |
| 168 | return Z_STREAM_ERROR; | |
| 169 | if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { | |
| 170 | ZFREE(strm, state->window); | |
| 171 | state->window = Z_NULL; | |
| 172 | } | |
| 166 | /* set number of window bits, free window if different */ | |
| 167 | if (windowBits && (windowBits < 8 || windowBits > 15)) | |
| 168 | return Z_STREAM_ERROR; | |
| 169 | if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { | |
| 170 | ZFREE(strm, state->window); | |
| 171 | state->window = Z_NULL; | |
| 172 | } | |
| 173 | 173 | |
| 174 | /* update state and reset the rest of it */ | |
| 175 | state->wrap = wrap; | |
| 176 | state->wbits = (unsigned)windowBits; | |
| 177 | return inflateReset(strm); | |
| 174 | /* update state and reset the rest of it */ | |
| 175 | state->wrap = wrap; | |
| 176 | state->wbits = (unsigned)windowBits; | |
| 177 | return inflateReset(strm); | |
| 178 | 178 | } |
| 179 | 179 | |
| 180 | 180 | int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) |
| r25360 | r25361 | |
| 183 | 183 | const char *version; |
| 184 | 184 | int stream_size; |
| 185 | 185 | { |
| 186 | int ret; | |
| 187 | struct inflate_state FAR *state; | |
| 186 | int ret; | |
| 187 | struct inflate_state FAR *state; | |
| 188 | 188 | |
| 189 | if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || | |
| 190 | stream_size != (int)(sizeof(z_stream))) | |
| 191 | return Z_VERSION_ERROR; | |
| 192 | if (strm == Z_NULL) return Z_STREAM_ERROR; | |
| 193 | strm->msg = Z_NULL; /* in case we return an error */ | |
| 194 | if (strm->zalloc == (alloc_func)0) { | |
| 189 | if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || | |
| 190 | stream_size != (int)(sizeof(z_stream))) | |
| 191 | return Z_VERSION_ERROR; | |
| 192 | if (strm == Z_NULL) return Z_STREAM_ERROR; | |
| 193 | strm->msg = Z_NULL; /* in case we return an error */ | |
| 194 | if (strm->zalloc == (alloc_func)0) { | |
| 195 | 195 | #ifdef Z_SOLO |
| 196 | ||
| 196 | return Z_STREAM_ERROR; | |
| 197 | 197 | #else |
| 198 | strm->zalloc = zcalloc; | |
| 199 | strm->opaque = (voidpf)0; | |
| 198 | strm->zalloc = zcalloc; | |
| 199 | strm->opaque = (voidpf)0; | |
| 200 | 200 | #endif |
| 201 | } | |
| 202 | if (strm->zfree == (free_func)0) | |
| 201 | } | |
| 202 | if (strm->zfree == (free_func)0) | |
| 203 | 203 | #ifdef Z_SOLO |
| 204 | ||
| 204 | return Z_STREAM_ERROR; | |
| 205 | 205 | #else |
| 206 | ||
| 206 | strm->zfree = zcfree; | |
| 207 | 207 | #endif |
| 208 | state = (struct inflate_state FAR *) | |
| 209 | ZALLOC(strm, 1, sizeof(struct inflate_state)); | |
| 210 | if (state == Z_NULL) return Z_MEM_ERROR; | |
| 211 | Tracev((stderr, "inflate: allocated\n")); | |
| 212 | strm->state = (struct internal_state FAR *)state; | |
| 213 | state->window = Z_NULL; | |
| 214 | ret = inflateReset2(strm, windowBits); | |
| 215 | if (ret != Z_OK) { | |
| 216 | ZFREE(strm, state); | |
| 217 | strm->state = Z_NULL; | |
| 218 | } | |
| 219 | return ret; | |
| 208 | state = (struct inflate_state FAR *) | |
| 209 | ZALLOC(strm, 1, sizeof(struct inflate_state)); | |
| 210 | if (state == Z_NULL) return Z_MEM_ERROR; | |
| 211 | Tracev((stderr, "inflate: allocated\n")); | |
| 212 | strm->state = (struct internal_state FAR *)state; | |
| 213 | state->window = Z_NULL; | |
| 214 | ret = inflateReset2(strm, windowBits); | |
| 215 | if (ret != Z_OK) { | |
| 216 | ZFREE(strm, state); | |
| 217 | strm->state = Z_NULL; | |
| 218 | } | |
| 219 | return ret; | |
| 220 | 220 | } |
| 221 | 221 | |
| 222 | 222 | int ZEXPORT inflateInit_(strm, version, stream_size) |
| r25360 | r25361 | |
| 224 | 224 | const char *version; |
| 225 | 225 | int stream_size; |
| 226 | 226 | { |
| 227 | ||
| 227 | return inflateInit2_(strm, DEF_WBITS, version, stream_size); | |
| 228 | 228 | } |
| 229 | 229 | |
| 230 | 230 | int ZEXPORT inflatePrime(strm, bits, value) |
| r25360 | r25361 | |
| 232 | 232 | int bits; |
| 233 | 233 | int value; |
| 234 | 234 | { |
| 235 | ||
| 235 | struct inflate_state FAR *state; | |
| 236 | 236 | |
| 237 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 238 | state = (struct inflate_state FAR *)strm->state; | |
| 239 | if (bits < 0) { | |
| 240 | state->hold = 0; | |
| 241 | state->bits = 0; | |
| 242 | return Z_OK; | |
| 243 | } | |
| 244 | if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; | |
| 245 | value &= (1L << bits) - 1; | |
| 246 | state->hold += value << state->bits; | |
| 247 | state->bits += bits; | |
| 248 | return Z_OK; | |
| 237 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 238 | state = (struct inflate_state FAR *)strm->state; | |
| 239 | if (bits < 0) { | |
| 240 | state->hold = 0; | |
| 241 | state->bits = 0; | |
| 242 | return Z_OK; | |
| 243 | } | |
| 244 | if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; | |
| 245 | value &= (1L << bits) - 1; | |
| 246 | state->hold += value << state->bits; | |
| 247 | state->bits += bits; | |
| 248 | return Z_OK; | |
| 249 | 249 | } |
| 250 | 250 | |
| 251 | 251 | /* |
| r25360 | r25361 | |
| 262 | 262 | struct inflate_state FAR *state; |
| 263 | 263 | { |
| 264 | 264 | #ifdef BUILDFIXED |
| 265 | static int virgin = 1; | |
| 266 | static code *lenfix, *distfix; | |
| 267 | static code fixed[544]; | |
| 265 | static int virgin = 1; | |
| 266 | static code *lenfix, *distfix; | |
| 267 | static code fixed[544]; | |
| 268 | 268 | |
| 269 | /* build fixed huffman tables if first call (may not be thread safe) */ | |
| 270 | if (virgin) { | |
| 271 | unsigned sym, bits; | |
| 272 | static code *next; | |
| 269 | /* build fixed huffman tables if first call (may not be thread safe) */ | |
| 270 | if (virgin) { | |
| 271 | unsigned sym, bits; | |
| 272 | static code *next; | |
| 273 | 273 | |
| 274 | /* literal/length table */ | |
| 275 | sym = 0; | |
| 276 | while (sym < 144) state->lens[sym++] = 8; | |
| 277 | while (sym < 256) state->lens[sym++] = 9; | |
| 278 | while (sym < 280) state->lens[sym++] = 7; | |
| 279 | while (sym < 288) state->lens[sym++] = 8; | |
| 280 | next = fixed; | |
| 281 | lenfix = next; | |
| 282 | bits = 9; | |
| 283 | inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); | |
| 274 | /* literal/length table */ | |
| 275 | sym = 0; | |
| 276 | while (sym < 144) state->lens[sym++] = 8; | |
| 277 | while (sym < 256) state->lens[sym++] = 9; | |
| 278 | while (sym < 280) state->lens[sym++] = 7; | |
| 279 | while (sym < 288) state->lens[sym++] = 8; | |
| 280 | next = fixed; | |
| 281 | lenfix = next; | |
| 282 | bits = 9; | |
| 283 | inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); | |
| 284 | 284 | |
| 285 | /* distance table */ | |
| 286 | sym = 0; | |
| 287 | while (sym < 32) state->lens[sym++] = 5; | |
| 288 | distfix = next; | |
| 289 | bits = 5; | |
| 290 | inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); | |
| 285 | /* distance table */ | |
| 286 | sym = 0; | |
| 287 | while (sym < 32) state->lens[sym++] = 5; | |
| 288 | distfix = next; | |
| 289 | bits = 5; | |
| 290 | inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); | |
| 291 | 291 | |
| 292 | /* do this just once */ | |
| 293 | virgin = 0; | |
| 294 | } | |
| 292 | /* do this just once */ | |
| 293 | virgin = 0; | |
| 294 | } | |
| 295 | 295 | #else /* !BUILDFIXED */ |
| 296 | 296 | # include "inffixed.h" |
| 297 | 297 | #endif /* BUILDFIXED */ |
| 298 | state->lencode = lenfix; | |
| 299 | state->lenbits = 9; | |
| 300 | state->distcode = distfix; | |
| 301 | state->distbits = 5; | |
| 298 | state->lencode = lenfix; | |
| 299 | state->lenbits = 9; | |
| 300 | state->distcode = distfix; | |
| 301 | state->distbits = 5; | |
| 302 | 302 | } |
| 303 | 303 | |
| 304 | 304 | #ifdef MAKEFIXED |
| r25360 | r25361 | |
| 324 | 324 | */ |
| 325 | 325 | void makefixed() |
| 326 | 326 | { |
| 327 | unsigned low, size; | |
| 328 | struct inflate_state state; | |
| 327 | unsigned low, size; | |
| 328 | struct inflate_state state; | |
| 329 | 329 | |
| 330 | fixedtables(&state); | |
| 331 | puts(" /* inffixed.h -- table for decoding fixed codes"); | |
| 332 | puts(" * Generated automatically by makefixed()."); | |
| 333 | puts(" */"); | |
| 334 | puts(""); | |
| 335 | puts(" /* WARNING: this file should *not* be used by applications."); | |
| 336 | puts(" It is part of the implementation of this library and is"); | |
| 337 | puts(" subject to change. Applications should only use zlib.h."); | |
| 338 | puts(" */"); | |
| 339 | puts(""); | |
| 340 | size = 1U << 9; | |
| 341 | printf(" static const code lenfix[%u] = {", size); | |
| 342 | low = 0; | |
| 343 | for (;;) { | |
| 344 | if ((low % 7) == 0) printf("\n "); | |
| 345 | printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, | |
| 346 | state.lencode[low].bits, state.lencode[low].val); | |
| 347 | if (++low == size) break; | |
| 348 | putchar(','); | |
| 349 | } | |
| 350 | puts("\n };"); | |
| 351 | size = 1U << 5; | |
| 352 | printf("\n static const code distfix[%u] = {", size); | |
| 353 | low = 0; | |
| 354 | for (;;) { | |
| 355 | if ((low % 6) == 0) printf("\n "); | |
| 356 | printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, | |
| 357 | state.distcode[low].val); | |
| 358 | if (++low == size) break; | |
| 359 | putchar(','); | |
| 360 | } | |
| 361 | puts("\n };"); | |
| 330 | fixedtables(&state); | |
| 331 | puts(" /* inffixed.h -- table for decoding fixed codes"); | |
| 332 | puts(" * Generated automatically by makefixed()."); | |
| 333 | puts(" */"); | |
| 334 | puts(""); | |
| 335 | puts(" /* WARNING: this file should *not* be used by applications."); | |
| 336 | puts(" It is part of the implementation of this library and is"); | |
| 337 | puts(" subject to change. Applications should only use zlib.h."); | |
| 338 | puts(" */"); | |
| 339 | puts(""); | |
| 340 | size = 1U << 9; | |
| 341 | printf(" static const code lenfix[%u] = {", size); | |
| 342 | low = 0; | |
| 343 | for (;;) { | |
| 344 | if ((low % 7) == 0) printf("\n "); | |
| 345 | printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, | |
| 346 | state.lencode[low].bits, state.lencode[low].val); | |
| 347 | if (++low == size) break; | |
| 348 | putchar(','); | |
| 349 | } | |
| 350 | puts("\n };"); | |
| 351 | size = 1U << 5; | |
| 352 | printf("\n static const code distfix[%u] = {", size); | |
| 353 | low = 0; | |
| 354 | for (;;) { | |
| 355 | if ((low % 6) == 0) printf("\n "); | |
| 356 | printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, | |
| 357 | state.distcode[low].val); | |
| 358 | if (++low == size) break; | |
| 359 | putchar(','); | |
| 360 | } | |
| 361 | puts("\n };"); | |
| 362 | 362 | } |
| 363 | 363 | #endif /* MAKEFIXED */ |
| 364 | 364 | |
| r25360 | r25361 | |
| 381 | 381 | const Bytef *end; |
| 382 | 382 | unsigned copy; |
| 383 | 383 | { |
| 384 | struct inflate_state FAR *state; | |
| 385 | unsigned dist; | |
| 384 | struct inflate_state FAR *state; | |
| 385 | unsigned dist; | |
| 386 | 386 | |
| 387 | ||
| 387 | state = (struct inflate_state FAR *)strm->state; | |
| 388 | 388 | |
| 389 | /* if it hasn't been done already, allocate space for the window */ | |
| 390 | if (state->window == Z_NULL) { | |
| 391 | state->window = (unsigned char FAR *) | |
| 392 | ZALLOC(strm, 1U << state->wbits, | |
| 393 | sizeof(unsigned char)); | |
| 394 | if (state->window == Z_NULL) return 1; | |
| 395 | } | |
| 389 | /* if it hasn't been done already, allocate space for the window */ | |
| 390 | if (state->window == Z_NULL) { | |
| 391 | state->window = (unsigned char FAR *) | |
| 392 | ZALLOC(strm, 1U << state->wbits, | |
| 393 | sizeof(unsigned char)); | |
| 394 | if (state->window == Z_NULL) return 1; | |
| 395 | } | |
| 396 | 396 | |
| 397 | /* if window not in use yet, initialize */ | |
| 398 | if (state->wsize == 0) { | |
| 399 | state->wsize = 1U << state->wbits; | |
| 400 | state->wnext = 0; | |
| 401 | state->whave = 0; | |
| 402 | } | |
| 397 | /* if window not in use yet, initialize */ | |
| 398 | if (state->wsize == 0) { | |
| 399 | state->wsize = 1U << state->wbits; | |
| 400 | state->wnext = 0; | |
| 401 | state->whave = 0; | |
| 402 | } | |
| 403 | 403 | |
| 404 | /* copy state->wsize or less output bytes into the circular window */ | |
| 405 | if (copy >= state->wsize) { | |
| 406 | zmemcpy(state->window, end - state->wsize, state->wsize); | |
| 407 | state->wnext = 0; | |
| 408 | state->whave = state->wsize; | |
| 409 | } | |
| 410 | else { | |
| 411 | dist = state->wsize - state->wnext; | |
| 412 | if (dist > copy) dist = copy; | |
| 413 | zmemcpy(state->window + state->wnext, end - copy, dist); | |
| 414 | copy -= dist; | |
| 415 | if (copy) { | |
| 416 | zmemcpy(state->window, end - copy, copy); | |
| 417 | state->wnext = copy; | |
| 418 | state->whave = state->wsize; | |
| 419 | } | |
| 420 | else { | |
| 421 | state->wnext += dist; | |
| 422 | if (state->wnext == state->wsize) state->wnext = 0; | |
| 423 | if (state->whave < state->wsize) state->whave += dist; | |
| 424 | } | |
| 425 | } | |
| 426 | return 0; | |
| 404 | /* copy state->wsize or less output bytes into the circular window */ | |
| 405 | if (copy >= state->wsize) { | |
| 406 | zmemcpy(state->window, end - state->wsize, state->wsize); | |
| 407 | state->wnext = 0; | |
| 408 | state->whave = state->wsize; | |
| 409 | } | |
| 410 | else { | |
| 411 | dist = state->wsize - state->wnext; | |
| 412 | if (dist > copy) dist = copy; | |
| 413 | zmemcpy(state->window + state->wnext, end - copy, dist); | |
| 414 | copy -= dist; | |
| 415 | if (copy) { | |
| 416 | zmemcpy(state->window, end - copy, copy); | |
| 417 | state->wnext = copy; | |
| 418 | state->whave = state->wsize; | |
| 419 | } | |
| 420 | else { | |
| 421 | state->wnext += dist; | |
| 422 | if (state->wnext == state->wsize) state->wnext = 0; | |
| 423 | if (state->whave < state->wsize) state->whave += dist; | |
| 424 | } | |
| 425 | } | |
| 426 | return 0; | |
| 427 | 427 | } |
| 428 | 428 | |
| 429 | 429 | /* Macros for inflate(): */ |
| r25360 | r25361 | |
| 431 | 431 | /* check function to use adler32() for zlib or crc32() for gzip */ |
| 432 | 432 | #ifdef GUNZIP |
| 433 | 433 | # define UPDATE(check, buf, len) \ |
| 434 | ||
| 434 | (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) | |
| 435 | 435 | #else |
| 436 | 436 | # define UPDATE(check, buf, len) adler32(check, buf, len) |
| 437 | 437 | #endif |
| r25360 | r25361 | |
| 439 | 439 | /* check macros for header crc */ |
| 440 | 440 | #ifdef GUNZIP |
| 441 | 441 | # define CRC2(check, word) \ |
| 442 | do { \ | |
| 443 | hbuf[0] = (unsigned char)(word); \ | |
| 444 | hbuf[1] = (unsigned char)((word) >> 8); \ | |
| 445 | check = crc32(check, hbuf, 2); \ | |
| 446 | } while (0) | |
| 442 | do { \ | |
| 443 | hbuf[0] = (unsigned char)(word); \ | |
| 444 | hbuf[1] = (unsigned char)((word) >> 8); \ | |
| 445 | check = crc32(check, hbuf, 2); \ | |
| 446 | } while (0) | |
| 447 | 447 | |
| 448 | 448 | # define CRC4(check, word) \ |
| 449 | do { \ | |
| 450 | hbuf[0] = (unsigned char)(word); \ | |
| 451 | hbuf[1] = (unsigned char)((word) >> 8); \ | |
| 452 | hbuf[2] = (unsigned char)((word) >> 16); \ | |
| 453 | hbuf[3] = (unsigned char)((word) >> 24); \ | |
| 454 | check = crc32(check, hbuf, 4); \ | |
| 455 | } while (0) | |
| 449 | do { \ | |
| 450 | hbuf[0] = (unsigned char)(word); \ | |
| 451 | hbuf[1] = (unsigned char)((word) >> 8); \ | |
| 452 | hbuf[2] = (unsigned char)((word) >> 16); \ | |
| 453 | hbuf[3] = (unsigned char)((word) >> 24); \ | |
| 454 | check = crc32(check, hbuf, 4); \ | |
| 455 | } while (0) | |
| 456 | 456 | #endif |
| 457 | 457 | |
| 458 | 458 | /* Load registers with state in inflate() for speed */ |
| 459 | 459 | #define LOAD() \ |
| 460 | do { \ | |
| 461 | put = strm->next_out; \ | |
| 462 | left = strm->avail_out; \ | |
| 463 | next = strm->next_in; \ | |
| 464 | have = strm->avail_in; \ | |
| 465 | hold = state->hold; \ | |
| 466 | bits = state->bits; \ | |
| 467 | } while (0) | |
| 460 | do { \ | |
| 461 | put = strm->next_out; \ | |
| 462 | left = strm->avail_out; \ | |
| 463 | next = strm->next_in; \ | |
| 464 | have = strm->avail_in; \ | |
| 465 | hold = state->hold; \ | |
| 466 | bits = state->bits; \ | |
| 467 | } while (0) | |
| 468 | 468 | |
| 469 | 469 | /* Restore state from registers in inflate() */ |
| 470 | 470 | #define RESTORE() \ |
| 471 | do { \ | |
| 472 | strm->next_out = put; \ | |
| 473 | strm->avail_out = left; \ | |
| 474 | strm->next_in = next; \ | |
| 475 | strm->avail_in = have; \ | |
| 476 | state->hold = hold; \ | |
| 477 | state->bits = bits; \ | |
| 478 | } while (0) | |
| 471 | do { \ | |
| 472 | strm->next_out = put; \ | |
| 473 | strm->avail_out = left; \ | |
| 474 | strm->next_in = next; \ | |
| 475 | strm->avail_in = have; \ | |
| 476 | state->hold = hold; \ | |
| 477 | state->bits = bits; \ | |
| 478 | } while (0) | |
| 479 | 479 | |
| 480 | 480 | /* Clear the input bit accumulator */ |
| 481 | 481 | #define INITBITS() \ |
| 482 | do { \ | |
| 483 | hold = 0; \ | |
| 484 | bits = 0; \ | |
| 485 | } while (0) | |
| 482 | do { \ | |
| 483 | hold = 0; \ | |
| 484 | bits = 0; \ | |
| 485 | } while (0) | |
| 486 | 486 | |
| 487 | 487 | /* Get a byte of input into the bit accumulator, or return from inflate() |
| 488 | 488 | if there is no input available. */ |
| 489 | 489 | #define PULLBYTE() \ |
| 490 | do { \ | |
| 491 | if (have == 0) goto inf_leave; \ | |
| 492 | have--; \ | |
| 493 | hold += (unsigned long)(*next++) << bits; \ | |
| 494 | bits += 8; \ | |
| 495 | } while (0) | |
| 490 | do { \ | |
| 491 | if (have == 0) goto inf_leave; \ | |
| 492 | have--; \ | |
| 493 | hold += (unsigned long)(*next++) << bits; \ | |
| 494 | bits += 8; \ | |
| 495 | } while (0) | |
| 496 | 496 | |
| 497 | 497 | /* Assure that there are at least n bits in the bit accumulator. If there is |
| 498 | 498 | not enough available input to do that, then return from inflate(). */ |
| 499 | 499 | #define NEEDBITS(n) \ |
| 500 | do { \ | |
| 501 | while (bits < (unsigned)(n)) \ | |
| 502 | PULLBYTE(); \ | |
| 503 | } while (0) | |
| 500 | do { \ | |
| 501 | while (bits < (unsigned)(n)) \ | |
| 502 | PULLBYTE(); \ | |
| 503 | } while (0) | |
| 504 | 504 | |
| 505 | 505 | /* Return the low n bits of the bit accumulator (n < 16) */ |
| 506 | 506 | #define BITS(n) \ |
| 507 | ||
| 507 | ((unsigned)hold & ((1U << (n)) - 1)) | |
| 508 | 508 | |
| 509 | 509 | /* Remove n bits from the bit accumulator */ |
| 510 | 510 | #define DROPBITS(n) \ |
| 511 | do { \ | |
| 512 | hold >>= (n); \ | |
| 513 | bits -= (unsigned)(n); \ | |
| 514 | } while (0) | |
| 511 | do { \ | |
| 512 | hold >>= (n); \ | |
| 513 | bits -= (unsigned)(n); \ | |
| 514 | } while (0) | |
| 515 | 515 | |
| 516 | 516 | /* Remove zero to seven bits as needed to go to a byte boundary */ |
| 517 | 517 | #define BYTEBITS() \ |
| 518 | do { \ | |
| 519 | hold >>= bits & 7; \ | |
| 520 | bits -= bits & 7; \ | |
| 521 | } while (0) | |
| 518 | do { \ | |
| 519 | hold >>= bits & 7; \ | |
| 520 | bits -= bits & 7; \ | |
| 521 | } while (0) | |
| 522 | 522 | |
| 523 | 523 | /* |
| 524 | 524 | inflate() uses a state machine to process as much input data and generate as |
| r25360 | r25361 | |
| 606 | 606 | z_streamp strm; |
| 607 | 607 | int flush; |
| 608 | 608 | { |
| 609 | struct inflate_state FAR *state; | |
| 610 | z_const unsigned char FAR *next; /* next input */ | |
| 611 | unsigned char FAR *put; /* next output */ | |
| 612 | unsigned have, left; /* available input and output */ | |
| 613 | unsigned long hold; /* bit buffer */ | |
| 614 | unsigned bits; /* bits in bit buffer */ | |
| 615 | unsigned in, out; /* save starting available input and output */ | |
| 616 | unsigned copy; /* number of stored or match bytes to copy */ | |
| 617 | unsigned char FAR *from; /* where to copy match bytes from */ | |
| 618 | code here; /* current decoding table entry */ | |
| 619 | code last; /* parent table entry */ | |
| 620 | unsigned len; /* length to copy for repeats, bits to drop */ | |
| 621 | int ret; /* return code */ | |
| 609 | struct inflate_state FAR *state; | |
| 610 | z_const unsigned char FAR *next; /* next input */ | |
| 611 | unsigned char FAR *put; /* next output */ | |
| 612 | unsigned have, left; /* available input and output */ | |
| 613 | unsigned long hold; /* bit buffer */ | |
| 614 | unsigned bits; /* bits in bit buffer */ | |
| 615 | unsigned in, out; /* save starting available input and output */ | |
| 616 | unsigned copy; /* number of stored or match bytes to copy */ | |
| 617 | unsigned char FAR *from; /* where to copy match bytes from */ | |
| 618 | code here; /* current decoding table entry */ | |
| 619 | code last; /* parent table entry */ | |
| 620 | unsigned len; /* length to copy for repeats, bits to drop */ | |
| 621 | int ret; /* return code */ | |
| 622 | 622 | #ifdef GUNZIP |
| 623 | ||
| 623 | unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ | |
| 624 | 624 | #endif |
| 625 | static const unsigned short order[19] = /* permutation of code lengths */ | |
| 626 | {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; | |
| 625 | static const unsigned short order[19] = /* permutation of code lengths */ | |
| 626 | {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; | |
| 627 | 627 | |
| 628 | if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || | |
| 629 | (strm->next_in == Z_NULL && strm->avail_in != 0)) | |
| 630 | return Z_STREAM_ERROR; | |
| 628 | if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || | |
| 629 | (strm->next_in == Z_NULL && strm->avail_in != 0)) | |
| 630 | return Z_STREAM_ERROR; | |
| 631 | 631 | |
| 632 | state = (struct inflate_state FAR *)strm->state; | |
| 633 | if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ | |
| 634 | LOAD(); | |
| 635 | in = have; | |
| 636 | out = left; | |
| 637 | ret = Z_OK; | |
| 638 | for (;;) | |
| 639 | switch (state->mode) { | |
| 640 | case HEAD: | |
| 641 | if (state->wrap == 0) { | |
| 642 | state->mode = TYPEDO; | |
| 643 | break; | |
| 644 | } | |
| 645 | NEEDBITS(16); | |
| 632 | state = (struct inflate_state FAR *)strm->state; | |
| 633 | if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ | |
| 634 | LOAD(); | |
| 635 | in = have; | |
| 636 | out = left; | |
| 637 | ret = Z_OK; | |
| 638 | for (;;) | |
| 639 | switch (state->mode) { | |
| 640 | case HEAD: | |
| 641 | if (state->wrap == 0) { | |
| 642 | state->mode = TYPEDO; | |
| 643 | break; | |
| 644 | } | |
| 645 | NEEDBITS(16); | |
| 646 | 646 | #ifdef GUNZIP |
| 647 | if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ | |
| 648 | state->check = crc32(0L, Z_NULL, 0); | |
| 649 | CRC2(state->check, hold); | |
| 650 | INITBITS(); | |
| 651 | state->mode = FLAGS; | |
| 652 | break; | |
| 653 | } | |
| 654 | state->flags = 0; /* expect zlib header */ | |
| 655 | if (state->head != Z_NULL) | |
| 656 | state->head->done = -1; | |
| 657 | if (!(state->wrap & 1) || /* check if zlib header allowed */ | |
| 647 | if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ | |
| 648 | state->check = crc32(0L, Z_NULL, 0); | |
| 649 | CRC2(state->check, hold); | |
| 650 | INITBITS(); | |
| 651 | state->mode = FLAGS; | |
| 652 | break; | |
| 653 | } | |
| 654 | state->flags = 0; /* expect zlib header */ | |
| 655 | if (state->head != Z_NULL) | |
| 656 | state->head->done = -1; | |
| 657 | if (!(state->wrap & 1) || /* check if zlib header allowed */ | |
| 658 | 658 | #else |
| 659 | ||
| 659 | if ( | |
| 660 | 660 | #endif |
| 661 | ((BITS(8) << 8) + (hold >> 8)) % 31) { | |
| 662 | strm->msg = (char *)"incorrect header check"; | |
| 663 | state->mode = BAD; | |
| 664 | break; | |
| 665 | } | |
| 666 | if (BITS(4) != Z_DEFLATED) { | |
| 667 | strm->msg = (char *)"unknown compression method"; | |
| 668 | state->mode = BAD; | |
| 669 | break; | |
| 670 | } | |
| 671 | DROPBITS(4); | |
| 672 | len = BITS(4) + 8; | |
| 673 | if (state->wbits == 0) | |
| 674 | state->wbits = len; | |
| 675 | else if (len > state->wbits) { | |
| 676 | strm->msg = (char *)"invalid window size"; | |
| 677 | state->mode = BAD; | |
| 678 | break; | |
| 679 | } | |
| 680 | state->dmax = 1U << len; | |
| 681 | Tracev((stderr, "inflate: zlib header ok\n")); | |
| 682 | strm->adler = state->check = adler32(0L, Z_NULL, 0); | |
| 683 | state->mode = hold & 0x200 ? DICTID : TYPE; | |
| 684 | INITBITS(); | |
| 685 | break; | |
| 661 | ((BITS(8) << 8) + (hold >> 8)) % 31) { | |
| 662 | strm->msg = (char *)"incorrect header check"; | |
| 663 | state->mode = BAD; | |
| 664 | break; | |
| 665 | } | |
| 666 | if (BITS(4) != Z_DEFLATED) { | |
| 667 | strm->msg = (char *)"unknown compression method"; | |
| 668 | state->mode = BAD; | |
| 669 | break; | |
| 670 | } | |
| 671 | DROPBITS(4); | |
| 672 | len = BITS(4) + 8; | |
| 673 | if (state->wbits == 0) | |
| 674 | state->wbits = len; | |
| 675 | else if (len > state->wbits) { | |
| 676 | strm->msg = (char *)"invalid window size"; | |
| 677 | state->mode = BAD; | |
| 678 | break; | |
| 679 | } | |
| 680 | state->dmax = 1U << len; | |
| 681 | Tracev((stderr, "inflate: zlib header ok\n")); | |
| 682 | strm->adler = state->check = adler32(0L, Z_NULL, 0); | |
| 683 | state->mode = hold & 0x200 ? DICTID : TYPE; | |
| 684 | INITBITS(); | |
| 685 | break; | |
| 686 | 686 | #ifdef GUNZIP |
| 687 | case FLAGS: | |
| 688 | NEEDBITS(16); | |
| 689 | state->flags = (int)(hold); | |
| 690 | if ((state->flags & 0xff) != Z_DEFLATED) { | |
| 691 | strm->msg = (char *)"unknown compression method"; | |
| 692 | state->mode = BAD; | |
| 693 | break; | |
| 694 | } | |
| 695 | if (state->flags & 0xe000) { | |
| 696 | strm->msg = (char *)"unknown header flags set"; | |
| 697 | state->mode = BAD; | |
| 698 | break; | |
| 699 | } | |
| 700 | if (state->head != Z_NULL) | |
| 701 | state->head->text = (int)((hold >> 8) & 1); | |
| 702 | if (state->flags & 0x0200) CRC2(state->check, hold); | |
| 703 | INITBITS(); | |
| 704 | state->mode = TIME; | |
| 705 | case TIME: | |
| 706 | NEEDBITS(32); | |
| 707 | if (state->head != Z_NULL) | |
| 708 | state->head->time = hold; | |
| 709 | if (state->flags & 0x0200) CRC4(state->check, hold); | |
| 710 | INITBITS(); | |
| 711 | state->mode = OS; | |
| 712 | case OS: | |
| 713 | NEEDBITS(16); | |
| 714 | if (state->head != Z_NULL) { | |
| 715 | state->head->xflags = (int)(hold & 0xff); | |
| 716 | state->head->os = (int)(hold >> 8); | |
| 717 | } | |
| 718 | if (state->flags & 0x0200) CRC2(state->check, hold); | |
| 719 | INITBITS(); | |
| 720 | state->mode = EXLEN; | |
| 721 | case EXLEN: | |
| 722 | if (state->flags & 0x0400) { | |
| 723 | NEEDBITS(16); | |
| 724 | state->length = (unsigned)(hold); | |
| 725 | if (state->head != Z_NULL) | |
| 726 | state->head->extra_len = (unsigned)hold; | |
| 727 | if (state->flags & 0x0200) CRC2(state->check, hold); | |
| 728 | INITBITS(); | |
| 729 | } | |
| 730 | else if (state->head != Z_NULL) | |
| 731 | state->head->extra = Z_NULL; | |
| 732 | state->mode = EXTRA; | |
| 733 | case EXTRA: | |
| 734 | if (state->flags & 0x0400) { | |
| 735 | copy = state->length; | |
| 736 | if (copy > have) copy = have; | |
| 737 | if (copy) { | |
| 738 | if (state->head != Z_NULL && | |
| 739 | state->head->extra != Z_NULL) { | |
| 740 | len = state->head->extra_len - state->length; | |
| 741 | zmemcpy(state->head->extra + len, next, | |
| 742 | len + copy > state->head->extra_max ? | |
| 743 | state->head->extra_max - len : copy); | |
| 744 | } | |
| 745 | if (state->flags & 0x0200) | |
| 746 | state->check = crc32(state->check, next, copy); | |
| 747 | have -= copy; | |
| 748 | next += copy; | |
| 749 | state->length -= copy; | |
| 750 | } | |
| 751 | if (state->length) goto inf_leave; | |
| 752 | } | |
| 753 | state->length = 0; | |
| 754 | state->mode = NAME; | |
| 755 | case NAME: | |
| 756 | if (state->flags & 0x0800) { | |
| 757 | if (have == 0) goto inf_leave; | |
| 758 | copy = 0; | |
| 759 | do { | |
| 760 | len = (unsigned)(next[copy++]); | |
| 761 | if (state->head != Z_NULL && | |
| 762 | state->head->name != Z_NULL && | |
| 763 | state->length < state->head->name_max) | |
| 764 | state->head->name[state->length++] = len; | |
| 765 | } while (len && copy < have); | |
| 766 | if (state->flags & 0x0200) | |
| 767 | state->check = crc32(state->check, next, copy); | |
| 768 | have -= copy; | |
| 769 | next += copy; | |
| 770 | if (len) goto inf_leave; | |
| 771 | } | |
| 772 | else if (state->head != Z_NULL) | |
| 773 | state->head->name = Z_NULL; | |
| 774 | state->length = 0; | |
| 775 | state->mode = COMMENT; | |
| 776 | case COMMENT: | |
| 777 | if (state->flags & 0x1000) { | |
| 778 | if (have == 0) goto inf_leave; | |
| 779 | copy = 0; | |
| 780 | do { | |
| 781 | len = (unsigned)(next[copy++]); | |
| 782 | if (state->head != Z_NULL && | |
| 783 | state->head->comment != Z_NULL && | |
| 784 | state->length < state->head->comm_max) | |
| 785 | state->head->comment[state->length++] = len; | |
| 786 | } while (len && copy < have); | |
| 787 | if (state->flags & 0x0200) | |
| 788 | state->check = crc32(state->check, next, copy); | |
| 789 | have -= copy; | |
| 790 | next += copy; | |
| 791 | if (len) goto inf_leave; | |
| 792 | } | |
| 793 | else if (state->head != Z_NULL) | |
| 794 | state->head->comment = Z_NULL; | |
| 795 | state->mode = HCRC; | |
| 796 | case HCRC: | |
| 797 | if (state->flags & 0x0200) { | |
| 798 | NEEDBITS(16); | |
| 799 | if (hold != (state->check & 0xffff)) { | |
| 800 | strm->msg = (char *)"header crc mismatch"; | |
| 801 | state->mode = BAD; | |
| 802 | break; | |
| 803 | } | |
| 804 | INITBITS(); | |
| 805 | } | |
| 806 | if (state->head != Z_NULL) { | |
| 807 | state->head->hcrc = (int)((state->flags >> 9) & 1); | |
| 808 | state->head->done = 1; | |
| 809 | } | |
| 810 | strm->adler = state->check = crc32(0L, Z_NULL, 0); | |
| 811 | state->mode = TYPE; | |
| 812 | break; | |
| 687 | case FLAGS: | |
| 688 | NEEDBITS(16); | |
| 689 | state->flags = (int)(hold); | |
| 690 | if ((state->flags & 0xff) != Z_DEFLATED) { | |
| 691 | strm->msg = (char *)"unknown compression method"; | |
| 692 | state->mode = BAD; | |
| 693 | break; | |
| 694 | } | |
| 695 | if (state->flags & 0xe000) { | |
| 696 | strm->msg = (char *)"unknown header flags set"; | |
| 697 | state->mode = BAD; | |
| 698 | break; | |
| 699 | } | |
| 700 | if (state->head != Z_NULL) | |
| 701 | state->head->text = (int)((hold >> 8) & 1); | |
| 702 | if (state->flags & 0x0200) CRC2(state->check, hold); | |
| 703 | INITBITS(); | |
| 704 | state->mode = TIME; | |
| 705 | case TIME: | |
| 706 | NEEDBITS(32); | |
| 707 | if (state->head != Z_NULL) | |
| 708 | state->head->time = hold; | |
| 709 | if (state->flags & 0x0200) CRC4(state->check, hold); | |
| 710 | INITBITS(); | |
| 711 | state->mode = OS; | |
| 712 | case OS: | |
| 713 | NEEDBITS(16); | |
| 714 | if (state->head != Z_NULL) { | |
| 715 | state->head->xflags = (int)(hold & 0xff); | |
| 716 | state->head->os = (int)(hold >> 8); | |
| 717 | } | |
| 718 | if (state->flags & 0x0200) CRC2(state->check, hold); | |
| 719 | INITBITS(); | |
| 720 | state->mode = EXLEN; | |
| 721 | case EXLEN: | |
| 722 | if (state->flags & 0x0400) { | |
| 723 | NEEDBITS(16); | |
| 724 | state->length = (unsigned)(hold); | |
| 725 | if (state->head != Z_NULL) | |
| 726 | state->head->extra_len = (unsigned)hold; | |
| 727 | if (state->flags & 0x0200) CRC2(state->check, hold); | |
| 728 | INITBITS(); | |
| 729 | } | |
| 730 | else if (state->head != Z_NULL) | |
| 731 | state->head->extra = Z_NULL; | |
| 732 | state->mode = EXTRA; | |
| 733 | case EXTRA: | |
| 734 | if (state->flags & 0x0400) { | |
| 735 | copy = state->length; | |
| 736 | if (copy > have) copy = have; | |
| 737 | if (copy) { | |
| 738 | if (state->head != Z_NULL && | |
| 739 | state->head->extra != Z_NULL) { | |
| 740 | len = state->head->extra_len - state->length; | |
| 741 | zmemcpy(state->head->extra + len, next, | |
| 742 | len + copy > state->head->extra_max ? | |
| 743 | state->head->extra_max - len : copy); | |
| 744 | } | |
| 745 | if (state->flags & 0x0200) | |
| 746 | state->check = crc32(state->check, next, copy); | |
| 747 | have -= copy; | |
| 748 | next += copy; | |
| 749 | state->length -= copy; | |
| 750 | } | |
| 751 | if (state->length) goto inf_leave; | |
| 752 | } | |
| 753 | state->length = 0; | |
| 754 | state->mode = NAME; | |
| 755 | case NAME: | |
| 756 | if (state->flags & 0x0800) { | |
| 757 | if (have == 0) goto inf_leave; | |
| 758 | copy = 0; | |
| 759 | do { | |
| 760 | len = (unsigned)(next[copy++]); | |
| 761 | if (state->head != Z_NULL && | |
| 762 | state->head->name != Z_NULL && | |
| 763 | state->length < state->head->name_max) | |
| 764 | state->head->name[state->length++] = len; | |
| 765 | } while (len && copy < have); | |
| 766 | if (state->flags & 0x0200) | |
| 767 | state->check = crc32(state->check, next, copy); | |
| 768 | have -= copy; | |
| 769 | next += copy; | |
| 770 | if (len) goto inf_leave; | |
| 771 | } | |
| 772 | else if (state->head != Z_NULL) | |
| 773 | state->head->name = Z_NULL; | |
| 774 | state->length = 0; | |
| 775 | state->mode = COMMENT; | |
| 776 | case COMMENT: | |
| 777 | if (state->flags & 0x1000) { | |
| 778 | if (have == 0) goto inf_leave; | |
| 779 | copy = 0; | |
| 780 | do { | |
| 781 | len = (unsigned)(next[copy++]); | |
| 782 | if (state->head != Z_NULL && | |
| 783 | state->head->comment != Z_NULL && | |
| 784 | state->length < state->head->comm_max) | |
| 785 | state->head->comment[state->length++] = len; | |
| 786 | } while (len && copy < have); | |
| 787 | if (state->flags & 0x0200) | |
| 788 | state->check = crc32(state->check, next, copy); | |
| 789 | have -= copy; | |
| 790 | next += copy; | |
| 791 | if (len) goto inf_leave; | |
| 792 | } | |
| 793 | else if (state->head != Z_NULL) | |
| 794 | state->head->comment = Z_NULL; | |
| 795 | state->mode = HCRC; | |
| 796 | case HCRC: | |
| 797 | if (state->flags & 0x0200) { | |
| 798 | NEEDBITS(16); | |
| 799 | if (hold != (state->check & 0xffff)) { | |
| 800 | strm->msg = (char *)"header crc mismatch"; | |
| 801 | state->mode = BAD; | |
| 802 | break; | |
| 803 | } | |
| 804 | INITBITS(); | |
| 805 | } | |
| 806 | if (state->head != Z_NULL) { | |
| 807 | state->head->hcrc = (int)((state->flags >> 9) & 1); | |
| 808 | state->head->done = 1; | |
| 809 | } | |
| 810 | strm->adler = state->check = crc32(0L, Z_NULL, 0); | |
| 811 | state->mode = TYPE; | |
| 812 | break; | |
| 813 | 813 | #endif |
| 814 | case DICTID: | |
| 815 | NEEDBITS(32); | |
| 816 | strm->adler = state->check = ZSWAP32(hold); | |
| 817 | INITBITS(); | |
| 818 | state->mode = DICT; | |
| 819 | case DICT: | |
| 820 | if (state->havedict == 0) { | |
| 821 | RESTORE(); | |
| 822 | return Z_NEED_DICT; | |
| 823 | } | |
| 824 | strm->adler = state->check = adler32(0L, Z_NULL, 0); | |
| 825 | state->mode = TYPE; | |
| 826 | case TYPE: | |
| 827 | if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; | |
| 828 | case TYPEDO: | |
| 829 | if (state->last) { | |
| 830 | BYTEBITS(); | |
| 831 | state->mode = CHECK; | |
| 832 | break; | |
| 833 | } | |
| 834 | NEEDBITS(3); | |
| 835 | state->last = BITS(1); | |
| 836 | DROPBITS(1); | |
| 837 | switch (BITS(2)) { | |
| 838 | case 0: /* stored block */ | |
| 839 | Tracev((stderr, "inflate: stored block%s\n", | |
| 840 | state->last ? " (last)" : "")); | |
| 841 | state->mode = STORED; | |
| 842 | break; | |
| 843 | case 1: /* fixed block */ | |
| 844 | fixedtables(state); | |
| 845 | Tracev((stderr, "inflate: fixed codes block%s\n", | |
| 846 | state->last ? " (last)" : "")); | |
| 847 | state->mode = LEN_; /* decode codes */ | |
| 848 | if (flush == Z_TREES) { | |
| 849 | DROPBITS(2); | |
| 850 | goto inf_leave; | |
| 851 | } | |
| 852 | break; | |
| 853 | case 2: /* dynamic block */ | |
| 854 | Tracev((stderr, "inflate: dynamic codes block%s\n", | |
| 855 | state->last ? " (last)" : "")); | |
| 856 | state->mode = TABLE; | |
| 857 | break; | |
| 858 | case 3: | |
| 859 | strm->msg = (char *)"invalid block type"; | |
| 860 | state->mode = BAD; | |
| 861 | } | |
| 862 | DROPBITS(2); | |
| 863 | break; | |
| 864 | case STORED: | |
| 865 | BYTEBITS(); /* go to byte boundary */ | |
| 866 | NEEDBITS(32); | |
| 867 | if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { | |
| 868 | strm->msg = (char *)"invalid stored block lengths"; | |
| 869 | state->mode = BAD; | |
| 870 | break; | |
| 871 | } | |
| 872 | state->length = (unsigned)hold & 0xffff; | |
| 873 | Tracev((stderr, "inflate: stored length %u\n", | |
| 874 | state->length)); | |
| 875 | INITBITS(); | |
| 876 | state->mode = COPY_; | |
| 877 | if (flush == Z_TREES) goto inf_leave; | |
| 878 | case COPY_: | |
| 879 | state->mode = COPY; | |
| 880 | case COPY: | |
| 881 | copy = state->length; | |
| 882 | if (copy) { | |
| 883 | if (copy > have) copy = have; | |
| 884 | if (copy > left) copy = left; | |
| 885 | if (copy == 0) goto inf_leave; | |
| 886 | zmemcpy(put, next, copy); | |
| 887 | have -= copy; | |
| 888 | next += copy; | |
| 889 | left -= copy; | |
| 890 | put += copy; | |
| 891 | state->length -= copy; | |
| 892 | break; | |
| 893 | } | |
| 894 | Tracev((stderr, "inflate: stored end\n")); | |
| 895 | state->mode = TYPE; | |
| 896 | break; | |
| 897 | case TABLE: | |
| 898 | NEEDBITS(14); | |
| 899 | state->nlen = BITS(5) + 257; | |
| 900 | DROPBITS(5); | |
| 901 | state->ndist = BITS(5) + 1; | |
| 902 | DROPBITS(5); | |
| 903 | state->ncode = BITS(4) + 4; | |
| 904 | DROPBITS(4); | |
| 814 | case DICTID: | |
| 815 | NEEDBITS(32); | |
| 816 | strm->adler = state->check = ZSWAP32(hold); | |
| 817 | INITBITS(); | |
| 818 | state->mode = DICT; | |
| 819 | case DICT: | |
| 820 | if (state->havedict == 0) { | |
| 821 | RESTORE(); | |
| 822 | return Z_NEED_DICT; | |
| 823 | } | |
| 824 | strm->adler = state->check = adler32(0L, Z_NULL, 0); | |
| 825 | state->mode = TYPE; | |
| 826 | case TYPE: | |
| 827 | if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; | |
| 828 | case TYPEDO: | |
| 829 | if (state->last) { | |
| 830 | BYTEBITS(); | |
| 831 | state->mode = CHECK; | |
| 832 | break; | |
| 833 | } | |
| 834 | NEEDBITS(3); | |
| 835 | state->last = BITS(1); | |
| 836 | DROPBITS(1); | |
| 837 | switch (BITS(2)) { | |
| 838 | case 0: /* stored block */ | |
| 839 | Tracev((stderr, "inflate: stored block%s\n", | |
| 840 | state->last ? " (last)" : "")); | |
| 841 | state->mode = STORED; | |
| 842 | break; | |
| 843 | case 1: /* fixed block */ | |
| 844 | fixedtables(state); | |
| 845 | Tracev((stderr, "inflate: fixed codes block%s\n", | |
| 846 | state->last ? " (last)" : "")); | |
| 847 | state->mode = LEN_; /* decode codes */ | |
| 848 | if (flush == Z_TREES) { | |
| 849 | DROPBITS(2); | |
| 850 | goto inf_leave; | |
| 851 | } | |
| 852 | break; | |
| 853 | case 2: /* dynamic block */ | |
| 854 | Tracev((stderr, "inflate: dynamic codes block%s\n", | |
| 855 | state->last ? " (last)" : "")); | |
| 856 | state->mode = TABLE; | |
| 857 | break; | |
| 858 | case 3: | |
| 859 | strm->msg = (char *)"invalid block type"; | |
| 860 | state->mode = BAD; | |
| 861 | } | |
| 862 | DROPBITS(2); | |
| 863 | break; | |
| 864 | case STORED: | |
| 865 | BYTEBITS(); /* go to byte boundary */ | |
| 866 | NEEDBITS(32); | |
| 867 | if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { | |
| 868 | strm->msg = (char *)"invalid stored block lengths"; | |
| 869 | state->mode = BAD; | |
| 870 | break; | |
| 871 | } | |
| 872 | state->length = (unsigned)hold & 0xffff; | |
| 873 | Tracev((stderr, "inflate: stored length %u\n", | |
| 874 | state->length)); | |
| 875 | INITBITS(); | |
| 876 | state->mode = COPY_; | |
| 877 | if (flush == Z_TREES) goto inf_leave; | |
| 878 | case COPY_: | |
| 879 | state->mode = COPY; | |
| 880 | case COPY: | |
| 881 | copy = state->length; | |
| 882 | if (copy) { | |
| 883 | if (copy > have) copy = have; | |
| 884 | if (copy > left) copy = left; | |
| 885 | if (copy == 0) goto inf_leave; | |
| 886 | zmemcpy(put, next, copy); | |
| 887 | have -= copy; | |
| 888 | next += copy; | |
| 889 | left -= copy; | |
| 890 | put += copy; | |
| 891 | state->length -= copy; | |
| 892 | break; | |
| 893 | } | |
| 894 | Tracev((stderr, "inflate: stored end\n")); | |
| 895 | state->mode = TYPE; | |
| 896 | break; | |
| 897 | case TABLE: | |
| 898 | NEEDBITS(14); | |
| 899 | state->nlen = BITS(5) + 257; | |
| 900 | DROPBITS(5); | |
| 901 | state->ndist = BITS(5) + 1; | |
| 902 | DROPBITS(5); | |
| 903 | state->ncode = BITS(4) + 4; | |
| 904 | DROPBITS(4); | |
| 905 | 905 | #ifndef PKZIP_BUG_WORKAROUND |
| 906 | if (state->nlen > 286 || state->ndist > 30) { | |
| 907 | strm->msg = (char *)"too many length or distance symbols"; | |
| 908 | state->mode = BAD; | |
| 909 | break; | |
| 910 | } | |
| 906 | if (state->nlen > 286 || state->ndist > 30) { | |
| 907 | strm->msg = (char *)"too many length or distance symbols"; | |
| 908 | state->mode = BAD; | |
| 909 | break; | |
| 910 | } | |
| 911 | 911 | #endif |
| 912 | Tracev((stderr, "inflate: table sizes ok\n")); | |
| 913 | state->have = 0; | |
| 914 | state->mode = LENLENS; | |
| 915 | case LENLENS: | |
| 916 | while (state->have < state->ncode) { | |
| 917 | NEEDBITS(3); | |
| 918 | state->lens[order[state->have++]] = (unsigned short)BITS(3); | |
| 919 | DROPBITS(3); | |
| 920 | } | |
| 921 | while (state->have < 19) | |
| 922 | state->lens[order[state->have++]] = 0; | |
| 923 | state->next = state->codes; | |
| 924 | state->lencode = (const code FAR *)(state->next); | |
| 925 | state->lenbits = 7; | |
| 926 | ret = inflate_table(CODES, state->lens, 19, &(state->next), | |
| 927 | &(state->lenbits), state->work); | |
| 928 | if (ret) { | |
| 929 | strm->msg = (char *)"invalid code lengths set"; | |
| 930 | state->mode = BAD; | |
| 931 | break; | |
| 932 | } | |
| 933 | Tracev((stderr, "inflate: code lengths ok\n")); | |
| 934 | state->have = 0; | |
| 935 | state->mode = CODELENS; | |
| 936 | case CODELENS: | |
| 937 | while (state->have < state->nlen + state->ndist) { | |
| 938 | for (;;) { | |
| 939 | here = state->lencode[BITS(state->lenbits)]; | |
| 940 | if ((unsigned)(here.bits) <= bits) break; | |
| 941 | PULLBYTE(); | |
| 942 | } | |
| 943 | if (here.val < 16) { | |
| 944 | DROPBITS(here.bits); | |
| 945 | state->lens[state->have++] = here.val; | |
| 946 | } | |
| 947 | else { | |
| 948 | if (here.val == 16) { | |
| 949 | NEEDBITS(here.bits + 2); | |
| 950 | DROPBITS(here.bits); | |
| 951 | if (state->have == 0) { | |
| 952 | strm->msg = (char *)"invalid bit length repeat"; | |
| 953 | state->mode = BAD; | |
| 954 | break; | |
| 955 | } | |
| 956 | len = state->lens[state->have - 1]; | |
| 957 | copy = 3 + BITS(2); | |
| 958 | DROPBITS(2); | |
| 959 | } | |
| 960 | else if (here.val == 17) { | |
| 961 | NEEDBITS(here.bits + 3); | |
| 962 | DROPBITS(here.bits); | |
| 963 | len = 0; | |
| 964 | copy = 3 + BITS(3); | |
| 965 | DROPBITS(3); | |
| 966 | } | |
| 967 | else { | |
| 968 | NEEDBITS(here.bits + 7); | |
| 969 | DROPBITS(here.bits); | |
| 970 | len = 0; | |
| 971 | copy = 11 + BITS(7); | |
| 972 | DROPBITS(7); | |
| 973 | } | |
| 974 | if (state->have + copy > state->nlen + state->ndist) { | |
| 975 | strm->msg = (char *)"invalid bit length repeat"; | |
| 976 | state->mode = BAD; | |
| 977 | break; | |
| 978 | } | |
| 979 | while (copy--) | |
| 980 | state->lens[state->have++] = (unsigned short)len; | |
| 981 | } | |
| 982 | } | |
| 912 | Tracev((stderr, "inflate: table sizes ok\n")); | |
| 913 | state->have = 0; | |
| 914 | state->mode = LENLENS; | |
| 915 | case LENLENS: | |
| 916 | while (state->have < state->ncode) { | |
| 917 | NEEDBITS(3); | |
| 918 | state->lens[order[state->have++]] = (unsigned short)BITS(3); | |
| 919 | DROPBITS(3); | |
| 920 | } | |
| 921 | while (state->have < 19) | |
| 922 | state->lens[order[state->have++]] = 0; | |
| 923 | state->next = state->codes; | |
| 924 | state->lencode = (const code FAR *)(state->next); | |
| 925 | state->lenbits = 7; | |
| 926 | ret = inflate_table(CODES, state->lens, 19, &(state->next), | |
| 927 | &(state->lenbits), state->work); | |
| 928 | if (ret) { | |
| 929 | strm->msg = (char *)"invalid code lengths set"; | |
| 930 | state->mode = BAD; | |
| 931 | break; | |
| 932 | } | |
| 933 | Tracev((stderr, "inflate: code lengths ok\n")); | |
| 934 | state->have = 0; | |
| 935 | state->mode = CODELENS; | |
| 936 | case CODELENS: | |
| 937 | while (state->have < state->nlen + state->ndist) { | |
| 938 | for (;;) { | |
| 939 | here = state->lencode[BITS(state->lenbits)]; | |
| 940 | if ((unsigned)(here.bits) <= bits) break; | |
| 941 | PULLBYTE(); | |
| 942 | } | |
| 943 | if (here.val < 16) { | |
| 944 | DROPBITS(here.bits); | |
| 945 | state->lens[state->have++] = here.val; | |
| 946 | } | |
| 947 | else { | |
| 948 | if (here.val == 16) { | |
| 949 | NEEDBITS(here.bits + 2); | |
| 950 | DROPBITS(here.bits); | |
| 951 | if (state->have == 0) { | |
| 952 | strm->msg = (char *)"invalid bit length repeat"; | |
| 953 | state->mode = BAD; | |
| 954 | break; | |
| 955 | } | |
| 956 | len = state->lens[state->have - 1]; | |
| 957 | copy = 3 + BITS(2); | |
| 958 | DROPBITS(2); | |
| 959 | } | |
| 960 | else if (here.val == 17) { | |
| 961 | NEEDBITS(here.bits + 3); | |
| 962 | DROPBITS(here.bits); | |
| 963 | len = 0; | |
| 964 | copy = 3 + BITS(3); | |
| 965 | DROPBITS(3); | |
| 966 | } | |
| 967 | else { | |
| 968 | NEEDBITS(here.bits + 7); | |
| 969 | DROPBITS(here.bits); | |
| 970 | len = 0; | |
| 971 | copy = 11 + BITS(7); | |
| 972 | DROPBITS(7); | |
| 973 | } | |
| 974 | if (state->have + copy > state->nlen + state->ndist) { | |
| 975 | strm->msg = (char *)"invalid bit length repeat"; | |
| 976 | state->mode = BAD; | |
| 977 | break; | |
| 978 | } | |
| 979 | while (copy--) | |
| 980 | state->lens[state->have++] = (unsigned short)len; | |
| 981 | } | |
| 982 | } | |
| 983 | 983 | |
| 984 | /* handle error breaks in while */ | |
| 985 | if (state->mode == BAD) break; | |
| 984 | /* handle error breaks in while */ | |
| 985 | if (state->mode == BAD) break; | |
| 986 | 986 | |
| 987 | /* check for end-of-block code (better have one) */ | |
| 988 | if (state->lens[256] == 0) { | |
| 989 | strm->msg = (char *)"invalid code -- missing end-of-block"; | |
| 990 | state->mode = BAD; | |
| 991 | break; | |
| 992 | } | |
| 987 | /* check for end-of-block code (better have one) */ | |
| 988 | if (state->lens[256] == 0) { | |
| 989 | strm->msg = (char *)"invalid code -- missing end-of-block"; | |
| 990 | state->mode = BAD; | |
| 991 | break; | |
| 992 | } | |
| 993 | 993 | |
| 994 | /* build code tables -- note: do not change the lenbits or distbits | |
| 995 | values here (9 and 6) without reading the comments in inftrees.h | |
| 996 | concerning the ENOUGH constants, which depend on those values */ | |
| 997 | state->next = state->codes; | |
| 998 | state->lencode = (const code FAR *)(state->next); | |
| 999 | state->lenbits = 9; | |
| 1000 | ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), | |
| 1001 | &(state->lenbits), state->work); | |
| 1002 | if (ret) { | |
| 1003 | strm->msg = (char *)"invalid literal/lengths set"; | |
| 1004 | state->mode = BAD; | |
| 1005 | break; | |
| 1006 | } | |
| 1007 | state->distcode = (const code FAR *)(state->next); | |
| 1008 | state->distbits = 6; | |
| 1009 | ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, | |
| 1010 | &(state->next), &(state->distbits), state->work); | |
| 1011 | if (ret) { | |
| 1012 | strm->msg = (char *)"invalid distances set"; | |
| 1013 | state->mode = BAD; | |
| 1014 | break; | |
| 1015 | } | |
| 1016 | Tracev((stderr, "inflate: codes ok\n")); | |
| 1017 | state->mode = LEN_; | |
| 1018 | if (flush == Z_TREES) goto inf_leave; | |
| 1019 | case LEN_: | |
| 1020 | state->mode = LEN; | |
| 1021 | case LEN: | |
| 1022 | if (have >= 6 && left >= 258) { | |
| 1023 | RESTORE(); | |
| 1024 | inflate_fast(strm, out); | |
| 1025 | LOAD(); | |
| 1026 | if (state->mode == TYPE) | |
| 1027 | state->back = -1; | |
| 1028 | break; | |
| 1029 | } | |
| 1030 | state->back = 0; | |
| 1031 | for (;;) { | |
| 1032 | here = state->lencode[BITS(state->lenbits)]; | |
| 1033 | if ((unsigned)(here.bits) <= bits) break; | |
| 1034 | PULLBYTE(); | |
| 1035 | } | |
| 1036 | if (here.op && (here.op & 0xf0) == 0) { | |
| 1037 | last = here; | |
| 1038 | for (;;) { | |
| 1039 | here = state->lencode[last.val + | |
| 1040 | (BITS(last.bits + last.op) >> last.bits)]; | |
| 1041 | if ((unsigned)(last.bits + here.bits) <= bits) break; | |
| 1042 | PULLBYTE(); | |
| 1043 | } | |
| 1044 | DROPBITS(last.bits); | |
| 1045 | state->back += last.bits; | |
| 1046 | } | |
| 1047 | DROPBITS(here.bits); | |
| 1048 | state->back += here.bits; | |
| 1049 | state->length = (unsigned)here.val; | |
| 1050 | if ((int)(here.op) == 0) { | |
| 1051 | Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? | |
| 1052 | "inflate: literal '%c'\n" : | |
| 1053 | "inflate: literal 0x%02x\n", here.val)); | |
| 1054 | state->mode = LIT; | |
| 1055 | break; | |
| 1056 | } | |
| 1057 | if (here.op & 32) { | |
| 1058 | Tracevv((stderr, "inflate: end of block\n")); | |
| 1059 | state->back = -1; | |
| 1060 | state->mode = TYPE; | |
| 1061 | break; | |
| 1062 | } | |
| 1063 | if (here.op & 64) { | |
| 1064 | strm->msg = (char *)"invalid literal/length code"; | |
| 1065 | state->mode = BAD; | |
| 1066 | break; | |
| 1067 | } | |
| 1068 | state->extra = (unsigned)(here.op) & 15; | |
| 1069 | state->mode = LENEXT; | |
| 1070 | case LENEXT: | |
| 1071 | if (state->extra) { | |
| 1072 | NEEDBITS(state->extra); | |
| 1073 | state->length += BITS(state->extra); | |
| 1074 | DROPBITS(state->extra); | |
| 1075 | state->back += state->extra; | |
| 1076 | } | |
| 1077 | Tracevv((stderr, "inflate: length %u\n", state->length)); | |
| 1078 | state->was = state->length; | |
| 1079 | state->mode = DIST; | |
| 1080 | case DIST: | |
| 1081 | for (;;) { | |
| 1082 | here = state->distcode[BITS(state->distbits)]; | |
| 1083 | if ((unsigned)(here.bits) <= bits) break; | |
| 1084 | PULLBYTE(); | |
| 1085 | } | |
| 1086 | if ((here.op & 0xf0) == 0) { | |
| 1087 | last = here; | |
| 1088 | for (;;) { | |
| 1089 | here = state->distcode[last.val + | |
| 1090 | (BITS(last.bits + last.op) >> last.bits)]; | |
| 1091 | if ((unsigned)(last.bits + here.bits) <= bits) break; | |
| 1092 | PULLBYTE(); | |
| 1093 | } | |
| 1094 | DROPBITS(last.bits); | |
| 1095 | state->back += last.bits; | |
| 1096 | } | |
| 1097 | DROPBITS(here.bits); | |
| 1098 | state->back += here.bits; | |
| 1099 | if (here.op & 64) { | |
| 1100 | strm->msg = (char *)"invalid distance code"; | |
| 1101 | state->mode = BAD; | |
| 1102 | break; | |
| 1103 | } | |
| 1104 | state->offset = (unsigned)here.val; | |
| 1105 | state->extra = (unsigned)(here.op) & 15; | |
| 1106 | state->mode = DISTEXT; | |
| 1107 | case DISTEXT: | |
| 1108 | if (state->extra) { | |
| 1109 | NEEDBITS(state->extra); | |
| 1110 | state->offset += BITS(state->extra); | |
| 1111 | DROPBITS(state->extra); | |
| 1112 | state->back += state->extra; | |
| 1113 | } | |
| 994 | /* build code tables -- note: do not change the lenbits or distbits | |
| 995 | values here (9 and 6) without reading the comments in inftrees.h | |
| 996 | concerning the ENOUGH constants, which depend on those values */ | |
| 997 | state->next = state->codes; | |
| 998 | state->lencode = (const code FAR *)(state->next); | |
| 999 | state->lenbits = 9; | |
| 1000 | ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), | |
| 1001 | &(state->lenbits), state->work); | |
| 1002 | if (ret) { | |
| 1003 | strm->msg = (char *)"invalid literal/lengths set"; | |
| 1004 | state->mode = BAD; | |
| 1005 | break; | |
| 1006 | } | |
| 1007 | state->distcode = (const code FAR *)(state->next); | |
| 1008 | state->distbits = 6; | |
| 1009 | ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, | |
| 1010 | &(state->next), &(state->distbits), state->work); | |
| 1011 | if (ret) { | |
| 1012 | strm->msg = (char *)"invalid distances set"; | |
| 1013 | state->mode = BAD; | |
| 1014 | break; | |
| 1015 | } | |
| 1016 | Tracev((stderr, "inflate: codes ok\n")); | |
| 1017 | state->mode = LEN_; | |
| 1018 | if (flush == Z_TREES) goto inf_leave; | |
| 1019 | case LEN_: | |
| 1020 | state->mode = LEN; | |
| 1021 | case LEN: | |
| 1022 | if (have >= 6 && left >= 258) { | |
| 1023 | RESTORE(); | |
| 1024 | inflate_fast(strm, out); | |
| 1025 | LOAD(); | |
| 1026 | if (state->mode == TYPE) | |
| 1027 | state->back = -1; | |
| 1028 | break; | |
| 1029 | } | |
| 1030 | state->back = 0; | |
| 1031 | for (;;) { | |
| 1032 | here = state->lencode[BITS(state->lenbits)]; | |
| 1033 | if ((unsigned)(here.bits) <= bits) break; | |
| 1034 | PULLBYTE(); | |
| 1035 | } | |
| 1036 | if (here.op && (here.op & 0xf0) == 0) { | |
| 1037 | last = here; | |
| 1038 | for (;;) { | |
| 1039 | here = state->lencode[last.val + | |
| 1040 | (BITS(last.bits + last.op) >> last.bits)]; | |
| 1041 | if ((unsigned)(last.bits + here.bits) <= bits) break; | |
| 1042 | PULLBYTE(); | |
| 1043 | } | |
| 1044 | DROPBITS(last.bits); | |
| 1045 | state->back += last.bits; | |
| 1046 | } | |
| 1047 | DROPBITS(here.bits); | |
| 1048 | state->back += here.bits; | |
| 1049 | state->length = (unsigned)here.val; | |
| 1050 | if ((int)(here.op) == 0) { | |
| 1051 | Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? | |
| 1052 | "inflate: literal '%c'\n" : | |
| 1053 | "inflate: literal 0x%02x\n", here.val)); | |
| 1054 | state->mode = LIT; | |
| 1055 | break; | |
| 1056 | } | |
| 1057 | if (here.op & 32) { | |
| 1058 | Tracevv((stderr, "inflate: end of block\n")); | |
| 1059 | state->back = -1; | |
| 1060 | state->mode = TYPE; | |
| 1061 | break; | |
| 1062 | } | |
| 1063 | if (here.op & 64) { | |
| 1064 | strm->msg = (char *)"invalid literal/length code"; | |
| 1065 | state->mode = BAD; | |
| 1066 | break; | |
| 1067 | } | |
| 1068 | state->extra = (unsigned)(here.op) & 15; | |
| 1069 | state->mode = LENEXT; | |
| 1070 | case LENEXT: | |
| 1071 | if (state->extra) { | |
| 1072 | NEEDBITS(state->extra); | |
| 1073 | state->length += BITS(state->extra); | |
| 1074 | DROPBITS(state->extra); | |
| 1075 | state->back += state->extra; | |
| 1076 | } | |
| 1077 | Tracevv((stderr, "inflate: length %u\n", state->length)); | |
| 1078 | state->was = state->length; | |
| 1079 | state->mode = DIST; | |
| 1080 | case DIST: | |
| 1081 | for (;;) { | |
| 1082 | here = state->distcode[BITS(state->distbits)]; | |
| 1083 | if ((unsigned)(here.bits) <= bits) break; | |
| 1084 | PULLBYTE(); | |
| 1085 | } | |
| 1086 | if ((here.op & 0xf0) == 0) { | |
| 1087 | last = here; | |
| 1088 | for (;;) { | |
| 1089 | here = state->distcode[last.val + | |
| 1090 | (BITS(last.bits + last.op) >> last.bits)]; | |
| 1091 | if ((unsigned)(last.bits + here.bits) <= bits) break; | |
| 1092 | PULLBYTE(); | |
| 1093 | } | |
| 1094 | DROPBITS(last.bits); | |
| 1095 | state->back += last.bits; | |
| 1096 | } | |
| 1097 | DROPBITS(here.bits); | |
| 1098 | state->back += here.bits; | |
| 1099 | if (here.op & 64) { | |
| 1100 | strm->msg = (char *)"invalid distance code"; | |
| 1101 | state->mode = BAD; | |
| 1102 | break; | |
| 1103 | } | |
| 1104 | state->offset = (unsigned)here.val; | |
| 1105 | state->extra = (unsigned)(here.op) & 15; | |
| 1106 | state->mode = DISTEXT; | |
| 1107 | case DISTEXT: | |
| 1108 | if (state->extra) { | |
| 1109 | NEEDBITS(state->extra); | |
| 1110 | state->offset += BITS(state->extra); | |
| 1111 | DROPBITS(state->extra); | |
| 1112 | state->back += state->extra; | |
| 1113 | } | |
| 1114 | 1114 | #ifdef INFLATE_STRICT |
| 1115 | if (state->offset > state->dmax) { | |
| 1116 | strm->msg = (char *)"invalid distance too far back"; | |
| 1117 | state->mode = BAD; | |
| 1118 | break; | |
| 1119 | } | |
| 1115 | if (state->offset > state->dmax) { | |
| 1116 | strm->msg = (char *)"invalid distance too far back"; | |
| 1117 | state->mode = BAD; | |
| 1118 | break; | |
| 1119 | } | |
| 1120 | 1120 | #endif |
| 1121 | Tracevv((stderr, "inflate: distance %u\n", state->offset)); | |
| 1122 | state->mode = MATCH; | |
| 1123 | case MATCH: | |
| 1124 | if (left == 0) goto inf_leave; | |
| 1125 | copy = out - left; | |
| 1126 | if (state->offset > copy) { /* copy from window */ | |
| 1127 | copy = state->offset - copy; | |
| 1128 | if (copy > state->whave) { | |
| 1129 | if (state->sane) { | |
| 1130 | strm->msg = (char *)"invalid distance too far back"; | |
| 1131 | state->mode = BAD; | |
| 1132 | break; | |
| 1133 | } | |
| 1121 | Tracevv((stderr, "inflate: distance %u\n", state->offset)); | |
| 1122 | state->mode = MATCH; | |
| 1123 | case MATCH: | |
| 1124 | if (left == 0) goto inf_leave; | |
| 1125 | copy = out - left; | |
| 1126 | if (state->offset > copy) { /* copy from window */ | |
| 1127 | copy = state->offset - copy; | |
| 1128 | if (copy > state->whave) { | |
| 1129 | if (state->sane) { | |
| 1130 | strm->msg = (char *)"invalid distance too far back"; | |
| 1131 | state->mode = BAD; | |
| 1132 | break; | |
| 1133 | } | |
| 1134 | 1134 | #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR |
| 1135 | Trace((stderr, "inflate.c too far\n")); | |
| 1136 | copy -= state->whave; | |
| 1137 | if (copy > state->length) copy = state->length; | |
| 1138 | if (copy > left) copy = left; | |
| 1139 | left -= copy; | |
| 1140 | state->length -= copy; | |
| 1141 | do { | |
| 1142 | *put++ = 0; | |
| 1143 | } while (--copy); | |
| 1144 | if (state->length == 0) state->mode = LEN; | |
| 1145 | break; | |
| 1135 | Trace((stderr, "inflate.c too far\n")); | |
| 1136 | copy -= state->whave; | |
| 1137 | if (copy > state->length) copy = state->length; | |
| 1138 | if (copy > left) copy = left; | |
| 1139 | left -= copy; | |
| 1140 | state->length -= copy; | |
| 1141 | do { | |
| 1142 | *put++ = 0; | |
| 1143 | } while (--copy); | |
| 1144 | if (state->length == 0) state->mode = LEN; | |
| 1145 | break; | |
| 1146 | 1146 | #endif |
| 1147 | } | |
| 1148 | if (copy > state->wnext) { | |
| 1149 | copy -= state->wnext; | |
| 1150 | from = state->window + (state->wsize - copy); | |
| 1151 | } | |
| 1152 | else | |
| 1153 | from = state->window + (state->wnext - copy); | |
| 1154 | if (copy > state->length) copy = state->length; | |
| 1155 | } | |
| 1156 | else { /* copy from output */ | |
| 1157 | from = put - state->offset; | |
| 1158 | copy = state->length; | |
| 1159 | } | |
| 1160 | if (copy > left) copy = left; | |
| 1161 | left -= copy; | |
| 1162 | state->length -= copy; | |
| 1163 | do { | |
| 1164 | *put++ = *from++; | |
| 1165 | } while (--copy); | |
| 1166 | if (state->length == 0) state->mode = LEN; | |
| 1167 | break; | |
| 1168 | case LIT: | |
| 1169 | if (left == 0) goto inf_leave; | |
| 1170 | *put++ = (unsigned char)(state->length); | |
| 1171 | left--; | |
| 1172 | state->mode = LEN; | |
| 1173 | break; | |
| 1174 | case CHECK: | |
| 1175 | if (state->wrap) { | |
| 1176 | NEEDBITS(32); | |
| 1177 | out -= left; | |
| 1178 | strm->total_out += out; | |
| 1179 | state->total += out; | |
| 1180 | if (out) | |
| 1181 | strm->adler = state->check = | |
| 1182 | UPDATE(state->check, put - out, out); | |
| 1183 | out = left; | |
| 1184 | if (( | |
| 1147 | } | |
| 1148 | if (copy > state->wnext) { | |
| 1149 | copy -= state->wnext; | |
| 1150 | from = state->window + (state->wsize - copy); | |
| 1151 | } | |
| 1152 | else | |
| 1153 | from = state->window + (state->wnext - copy); | |
| 1154 | if (copy > state->length) copy = state->length; | |
| 1155 | } | |
| 1156 | else { /* copy from output */ | |
| 1157 | from = put - state->offset; | |
| 1158 | copy = state->length; | |
| 1159 | } | |
| 1160 | if (copy > left) copy = left; | |
| 1161 | left -= copy; | |
| 1162 | state->length -= copy; | |
| 1163 | do { | |
| 1164 | *put++ = *from++; | |
| 1165 | } while (--copy); | |
| 1166 | if (state->length == 0) state->mode = LEN; | |
| 1167 | break; | |
| 1168 | case LIT: | |
| 1169 | if (left == 0) goto inf_leave; | |
| 1170 | *put++ = (unsigned char)(state->length); | |
| 1171 | left--; | |
| 1172 | state->mode = LEN; | |
| 1173 | break; | |
| 1174 | case CHECK: | |
| 1175 | if (state->wrap) { | |
| 1176 | NEEDBITS(32); | |
| 1177 | out -= left; | |
| 1178 | strm->total_out += out; | |
| 1179 | state->total += out; | |
| 1180 | if (out) | |
| 1181 | strm->adler = state->check = | |
| 1182 | UPDATE(state->check, put - out, out); | |
| 1183 | out = left; | |
| 1184 | if (( | |
| 1185 | 1185 | #ifdef GUNZIP |
| 1186 | ||
| 1186 | state->flags ? hold : | |
| 1187 | 1187 | #endif |
| 1188 | ZSWAP32(hold)) != state->check) { | |
| 1189 | strm->msg = (char *)"incorrect data check"; | |
| 1190 | state->mode = BAD; | |
| 1191 | break; | |
| 1192 | } | |
| 1193 | INITBITS(); | |
| 1194 | Tracev((stderr, "inflate: check matches trailer\n")); | |
| 1195 | } | |
| 1188 | ZSWAP32(hold)) != state->check) { | |
| 1189 | strm->msg = (char *)"incorrect data check"; | |
| 1190 | state->mode = BAD; | |
| 1191 | break; | |
| 1192 | } | |
| 1193 | INITBITS(); | |
| 1194 | Tracev((stderr, "inflate: check matches trailer\n")); | |
| 1195 | } | |
| 1196 | 1196 | #ifdef GUNZIP |
| 1197 | state->mode = LENGTH; | |
| 1198 | case LENGTH: | |
| 1199 | if (state->wrap && state->flags) { | |
| 1200 | NEEDBITS(32); | |
| 1201 | if (hold != (state->total & 0xffffffffUL)) { | |
| 1202 | strm->msg = (char *)"incorrect length check"; | |
| 1203 | state->mode = BAD; | |
| 1204 | break; | |
| 1205 | } | |
| 1206 | INITBITS(); | |
| 1207 | Tracev((stderr, "inflate: length matches trailer\n")); | |
| 1208 | } | |
| 1197 | state->mode = LENGTH; | |
| 1198 | case LENGTH: | |
| 1199 | if (state->wrap && state->flags) { | |
| 1200 | NEEDBITS(32); | |
| 1201 | if (hold != (state->total & 0xffffffffUL)) { | |
| 1202 | strm->msg = (char *)"incorrect length check"; | |
| 1203 | state->mode = BAD; | |
| 1204 | break; | |
| 1205 | } | |
| 1206 | INITBITS(); | |
| 1207 | Tracev((stderr, "inflate: length matches trailer\n")); | |
| 1208 | } | |
| 1209 | 1209 | #endif |
| 1210 | state->mode = DONE; | |
| 1211 | case DONE: | |
| 1212 | ret = Z_STREAM_END; | |
| 1213 | goto inf_leave; | |
| 1214 | case BAD: | |
| 1215 | ret = Z_DATA_ERROR; | |
| 1216 | goto inf_leave; | |
| 1217 | case MEM: | |
| 1218 | return Z_MEM_ERROR; | |
| 1219 | case SYNC: | |
| 1220 | default: | |
| 1221 | return Z_STREAM_ERROR; | |
| 1222 | } | |
| 1210 | state->mode = DONE; | |
| 1211 | case DONE: | |
| 1212 | ret = Z_STREAM_END; | |
| 1213 | goto inf_leave; | |
| 1214 | case BAD: | |
| 1215 | ret = Z_DATA_ERROR; | |
| 1216 | goto inf_leave; | |
| 1217 | case MEM: | |
| 1218 | return Z_MEM_ERROR; | |
| 1219 | case SYNC: | |
| 1220 | default: | |
| 1221 | return Z_STREAM_ERROR; | |
| 1222 | } | |
| 1223 | 1223 | |
| 1224 | /* | |
| 1225 | Return from inflate(), updating the total counts and the check value. | |
| 1226 | If there was no progress during the inflate() call, return a buffer | |
| 1227 | error. Call updatewindow() to create and/or update the window state. | |
| 1228 | Note: a memory error from inflate() is non-recoverable. | |
| 1229 | */ | |
| 1230 | inf_leave: | |
| 1231 | RESTORE(); | |
| 1232 | if (state->wsize || (out != strm->avail_out && state->mode < BAD && | |
| 1233 | (state->mode < CHECK || flush != Z_FINISH))) | |
| 1234 | if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { | |
| 1235 | state->mode = MEM; | |
| 1236 | return Z_MEM_ERROR; | |
| 1237 | } | |
| 1238 | in -= strm->avail_in; | |
| 1239 | out -= strm->avail_out; | |
| 1240 | strm->total_in += in; | |
| 1241 | strm->total_out += out; | |
| 1242 | state->total += out; | |
| 1243 | if (state->wrap && out) | |
| 1244 | strm->adler = state->check = | |
| 1245 | UPDATE(state->check, strm->next_out - out, out); | |
| 1246 | strm->data_type = state->bits + (state->last ? 64 : 0) + | |
| 1247 | (state->mode == TYPE ? 128 : 0) + | |
| 1248 | (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); | |
| 1249 | if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) | |
| 1250 | ret = Z_BUF_ERROR; | |
| 1251 | return ret; | |
| 1224 | /* | |
| 1225 | Return from inflate(), updating the total counts and the check value. | |
| 1226 | If there was no progress during the inflate() call, return a buffer | |
| 1227 | error. Call updatewindow() to create and/or update the window state. | |
| 1228 | Note: a memory error from inflate() is non-recoverable. | |
| 1229 | */ | |
| 1230 | inf_leave: | |
| 1231 | RESTORE(); | |
| 1232 | if (state->wsize || (out != strm->avail_out && state->mode < BAD && | |
| 1233 | (state->mode < CHECK || flush != Z_FINISH))) | |
| 1234 | if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { | |
| 1235 | state->mode = MEM; | |
| 1236 | return Z_MEM_ERROR; | |
| 1237 | } | |
| 1238 | in -= strm->avail_in; | |
| 1239 | out -= strm->avail_out; | |
| 1240 | strm->total_in += in; | |
| 1241 | strm->total_out += out; | |
| 1242 | state->total += out; | |
| 1243 | if (state->wrap && out) | |
| 1244 | strm->adler = state->check = | |
| 1245 | UPDATE(state->check, strm->next_out - out, out); | |
| 1246 | strm->data_type = state->bits + (state->last ? 64 : 0) + | |
| 1247 | (state->mode == TYPE ? 128 : 0) + | |
| 1248 | (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); | |
| 1249 | if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) | |
| 1250 | ret = Z_BUF_ERROR; | |
| 1251 | return ret; | |
| 1252 | 1252 | } |
| 1253 | 1253 | |
| 1254 | 1254 | int ZEXPORT inflateEnd(strm) |
| 1255 | 1255 | z_streamp strm; |
| 1256 | 1256 | { |
| 1257 | struct inflate_state FAR *state; | |
| 1258 | if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) | |
| 1259 | return Z_STREAM_ERROR; | |
| 1260 | state = (struct inflate_state FAR *)strm->state; | |
| 1261 | if (state->window != Z_NULL) ZFREE(strm, state->window); | |
| 1262 | ZFREE(strm, strm->state); | |
| 1263 | strm->state = Z_NULL; | |
| 1264 | Tracev((stderr, "inflate: end\n")); | |
| 1265 | return Z_OK; | |
| 1257 | struct inflate_state FAR *state; | |
| 1258 | if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) | |
| 1259 | return Z_STREAM_ERROR; | |
| 1260 | state = (struct inflate_state FAR *)strm->state; | |
| 1261 | if (state->window != Z_NULL) ZFREE(strm, state->window); | |
| 1262 | ZFREE(strm, strm->state); | |
| 1263 | strm->state = Z_NULL; | |
| 1264 | Tracev((stderr, "inflate: end\n")); | |
| 1265 | return Z_OK; | |
| 1266 | 1266 | } |
| 1267 | 1267 | |
| 1268 | 1268 | int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength) |
| r25360 | r25361 | |
| 1270 | 1270 | Bytef *dictionary; |
| 1271 | 1271 | uInt *dictLength; |
| 1272 | 1272 | { |
| 1273 | ||
| 1273 | struct inflate_state FAR *state; | |
| 1274 | 1274 | |
| 1275 | /* check state */ | |
| 1276 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 1277 | state = (struct inflate_state FAR *)strm->state; | |
| 1275 | /* check state */ | |
| 1276 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 1277 | state = (struct inflate_state FAR *)strm->state; | |
| 1278 | 1278 | |
| 1279 | /* copy dictionary */ | |
| 1280 | if (state->whave && dictionary != Z_NULL) { | |
| 1281 | zmemcpy(dictionary, state->window + state->wnext, | |
| 1282 | state->whave - state->wnext); | |
| 1283 | zmemcpy(dictionary + state->whave - state->wnext, | |
| 1284 | state->window, state->wnext); | |
| 1285 | } | |
| 1286 | if (dictLength != Z_NULL) | |
| 1287 | *dictLength = state->whave; | |
| 1288 | return Z_OK; | |
| 1279 | /* copy dictionary */ | |
| 1280 | if (state->whave && dictionary != Z_NULL) { | |
| 1281 | zmemcpy(dictionary, state->window + state->wnext, | |
| 1282 | state->whave - state->wnext); | |
| 1283 | zmemcpy(dictionary + state->whave - state->wnext, | |
| 1284 | state->window, state->wnext); | |
| 1285 | } | |
| 1286 | if (dictLength != Z_NULL) | |
| 1287 | *dictLength = state->whave; | |
| 1288 | return Z_OK; | |
| 1289 | 1289 | } |
| 1290 | 1290 | |
| 1291 | 1291 | int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) |
| r25360 | r25361 | |
| 1293 | 1293 | const Bytef *dictionary; |
| 1294 | 1294 | uInt dictLength; |
| 1295 | 1295 | { |
| 1296 | struct inflate_state FAR *state; | |
| 1297 | unsigned long dictid; | |
| 1298 | int ret; | |
| 1296 | struct inflate_state FAR *state; | |
| 1297 | unsigned long dictid; | |
| 1298 | int ret; | |
| 1299 | 1299 | |
| 1300 | /* check state */ | |
| 1301 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 1302 | state = (struct inflate_state FAR *)strm->state; | |
| 1303 | if (state->wrap != 0 && state->mode != DICT) | |
| 1304 | return Z_STREAM_ERROR; | |
| 1300 | /* check state */ | |
| 1301 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 1302 | state = (struct inflate_state FAR *)strm->state; | |
| 1303 | if (state->wrap != 0 && state->mode != DICT) | |
| 1304 | return Z_STREAM_ERROR; | |
| 1305 | 1305 | |
| 1306 | /* check for correct dictionary identifier */ | |
| 1307 | if (state->mode == DICT) { | |
| 1308 | dictid = adler32(0L, Z_NULL, 0); | |
| 1309 | dictid = adler32(dictid, dictionary, dictLength); | |
| 1310 | if (dictid != state->check) | |
| 1311 | return Z_DATA_ERROR; | |
| 1312 | } | |
| 1306 | /* check for correct dictionary identifier */ | |
| 1307 | if (state->mode == DICT) { | |
| 1308 | dictid = adler32(0L, Z_NULL, 0); | |
| 1309 | dictid = adler32(dictid, dictionary, dictLength); | |
| 1310 | if (dictid != state->check) | |
| 1311 | return Z_DATA_ERROR; | |
| 1312 | } | |
| 1313 | 1313 | |
| 1314 | /* copy dictionary to window using updatewindow(), which will amend the | |
| 1315 | existing dictionary if appropriate */ | |
| 1316 | ret = updatewindow(strm, dictionary + dictLength, dictLength); | |
| 1317 | if (ret) { | |
| 1318 | state->mode = MEM; | |
| 1319 | return Z_MEM_ERROR; | |
| 1320 | } | |
| 1321 | state->havedict = 1; | |
| 1322 | Tracev((stderr, "inflate: dictionary set\n")); | |
| 1323 | return Z_OK; | |
| 1314 | /* copy dictionary to window using updatewindow(), which will amend the | |
| 1315 | existing dictionary if appropriate */ | |
| 1316 | ret = updatewindow(strm, dictionary + dictLength, dictLength); | |
| 1317 | if (ret) { | |
| 1318 | state->mode = MEM; | |
| 1319 | return Z_MEM_ERROR; | |
| 1320 | } | |
| 1321 | state->havedict = 1; | |
| 1322 | Tracev((stderr, "inflate: dictionary set\n")); | |
| 1323 | return Z_OK; | |
| 1324 | 1324 | } |
| 1325 | 1325 | |
| 1326 | 1326 | int ZEXPORT inflateGetHeader(strm, head) |
| 1327 | 1327 | z_streamp strm; |
| 1328 | 1328 | gz_headerp head; |
| 1329 | 1329 | { |
| 1330 | ||
| 1330 | struct inflate_state FAR *state; | |
| 1331 | 1331 | |
| 1332 | /* check state */ | |
| 1333 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 1334 | state = (struct inflate_state FAR *)strm->state; | |
| 1335 | if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; | |
| 1332 | /* check state */ | |
| 1333 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 1334 | state = (struct inflate_state FAR *)strm->state; | |
| 1335 | if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; | |
| 1336 | 1336 | |
| 1337 | /* save header structure */ | |
| 1338 | state->head = head; | |
| 1339 | head->done = 0; | |
| 1340 | return Z_OK; | |
| 1337 | /* save header structure */ | |
| 1338 | state->head = head; | |
| 1339 | head->done = 0; | |
| 1340 | return Z_OK; | |
| 1341 | 1341 | } |
| 1342 | 1342 | |
| 1343 | 1343 | /* |
| r25360 | r25361 | |
| 1356 | 1356 | const unsigned char FAR *buf; |
| 1357 | 1357 | unsigned len; |
| 1358 | 1358 | { |
| 1359 | unsigned got; | |
| 1360 | unsigned next; | |
| 1359 | unsigned got; | |
| 1360 | unsigned next; | |
| 1361 | 1361 | |
| 1362 | got = *have; | |
| 1363 | next = 0; | |
| 1364 | while (next < len && got < 4) { | |
| 1365 | if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) | |
| 1366 | got++; | |
| 1367 | else if (buf[next]) | |
| 1368 | got = 0; | |
| 1369 | else | |
| 1370 | got = 4 - got; | |
| 1371 | next++; | |
| 1372 | } | |
| 1373 | *have = got; | |
| 1374 | return next; | |
| 1362 | got = *have; | |
| 1363 | next = 0; | |
| 1364 | while (next < len && got < 4) { | |
| 1365 | if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) | |
| 1366 | got++; | |
| 1367 | else if (buf[next]) | |
| 1368 | got = 0; | |
| 1369 | else | |
| 1370 | got = 4 - got; | |
| 1371 | next++; | |
| 1372 | } | |
| 1373 | *have = got; | |
| 1374 | return next; | |
| 1375 | 1375 | } |
| 1376 | 1376 | |
| 1377 | 1377 | int ZEXPORT inflateSync(strm) |
| 1378 | 1378 | z_streamp strm; |
| 1379 | 1379 | { |
| 1380 | unsigned len; /* number of bytes to look at or looked at */ | |
| 1381 | unsigned long in, out; /* temporary to save total_in and total_out */ | |
| 1382 | unsigned char buf[4]; /* to restore bit buffer to byte string */ | |
| 1383 | struct inflate_state FAR *state; | |
| 1380 | unsigned len; /* number of bytes to look at or looked at */ | |
| 1381 | unsigned long in, out; /* temporary to save total_in and total_out */ | |
| 1382 | unsigned char buf[4]; /* to restore bit buffer to byte string */ | |
| 1383 | struct inflate_state FAR *state; | |
| 1384 | 1384 | |
| 1385 | /* check parameters */ | |
| 1386 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 1387 | state = (struct inflate_state FAR *)strm->state; | |
| 1388 | if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; | |
| 1385 | /* check parameters */ | |
| 1386 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 1387 | state = (struct inflate_state FAR *)strm->state; | |
| 1388 | if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; | |
| 1389 | 1389 | |
| 1390 | /* if first time, start search in bit buffer */ | |
| 1391 | if (state->mode != SYNC) { | |
| 1392 | state->mode = SYNC; | |
| 1393 | state->hold <<= state->bits & 7; | |
| 1394 | state->bits -= state->bits & 7; | |
| 1395 | len = 0; | |
| 1396 | while (state->bits >= 8) { | |
| 1397 | buf[len++] = (unsigned char)(state->hold); | |
| 1398 | state->hold >>= 8; | |
| 1399 | state->bits -= 8; | |
| 1400 | } | |
| 1401 | state->have = 0; | |
| 1402 | syncsearch(&(state->have), buf, len); | |
| 1403 | } | |
| 1390 | /* if first time, start search in bit buffer */ | |
| 1391 | if (state->mode != SYNC) { | |
| 1392 | state->mode = SYNC; | |
| 1393 | state->hold <<= state->bits & 7; | |
| 1394 | state->bits -= state->bits & 7; | |
| 1395 | len = 0; | |
| 1396 | while (state->bits >= 8) { | |
| 1397 | buf[len++] = (unsigned char)(state->hold); | |
| 1398 | state->hold >>= 8; | |
| 1399 | state->bits -= 8; | |
| 1400 | } | |
| 1401 | state->have = 0; | |
| 1402 | syncsearch(&(state->have), buf, len); | |
| 1403 | } | |
| 1404 | 1404 | |
| 1405 | /* search available input */ | |
| 1406 | len = syncsearch(&(state->have), strm->next_in, strm->avail_in); | |
| 1407 | strm->avail_in -= len; | |
| 1408 | strm->next_in += len; | |
| 1409 | strm->total_in += len; | |
| 1405 | /* search available input */ | |
| 1406 | len = syncsearch(&(state->have), strm->next_in, strm->avail_in); | |
| 1407 | strm->avail_in -= len; | |
| 1408 | strm->next_in += len; | |
| 1409 | strm->total_in += len; | |
| 1410 | 1410 | |
| 1411 | /* return no joy or set up to restart inflate() on a new block */ | |
| 1412 | if (state->have != 4) return Z_DATA_ERROR; | |
| 1413 | in = strm->total_in; out = strm->total_out; | |
| 1414 | inflateReset(strm); | |
| 1415 | strm->total_in = in; strm->total_out = out; | |
| 1416 | state->mode = TYPE; | |
| 1417 | return Z_OK; | |
| 1411 | /* return no joy or set up to restart inflate() on a new block */ | |
| 1412 | if (state->have != 4) return Z_DATA_ERROR; | |
| 1413 | in = strm->total_in; out = strm->total_out; | |
| 1414 | inflateReset(strm); | |
| 1415 | strm->total_in = in; strm->total_out = out; | |
| 1416 | state->mode = TYPE; | |
| 1417 | return Z_OK; | |
| 1418 | 1418 | } |
| 1419 | 1419 | |
| 1420 | 1420 | /* |
| r25360 | r25361 | |
| 1428 | 1428 | int ZEXPORT inflateSyncPoint(strm) |
| 1429 | 1429 | z_streamp strm; |
| 1430 | 1430 | { |
| 1431 | ||
| 1431 | struct inflate_state FAR *state; | |
| 1432 | 1432 | |
| 1433 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 1434 | state = (struct inflate_state FAR *)strm->state; | |
| 1435 | return state->mode == STORED && state->bits == 0; | |
| 1433 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 1434 | state = (struct inflate_state FAR *)strm->state; | |
| 1435 | return state->mode == STORED && state->bits == 0; | |
| 1436 | 1436 | } |
| 1437 | 1437 | |
| 1438 | 1438 | int ZEXPORT inflateCopy(dest, source) |
| 1439 | 1439 | z_streamp dest; |
| 1440 | 1440 | z_streamp source; |
| 1441 | 1441 | { |
| 1442 | struct inflate_state FAR *state; | |
| 1443 | struct inflate_state FAR *copy; | |
| 1444 | unsigned char FAR *window; | |
| 1445 | unsigned wsize; | |
| 1442 | struct inflate_state FAR *state; | |
| 1443 | struct inflate_state FAR *copy; | |
| 1444 | unsigned char FAR *window; | |
| 1445 | unsigned wsize; | |
| 1446 | 1446 | |
| 1447 | /* check input */ | |
| 1448 | if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || | |
| 1449 | source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) | |
| 1450 | return Z_STREAM_ERROR; | |
| 1451 | state = (struct inflate_state FAR *)source->state; | |
| 1447 | /* check input */ | |
| 1448 | if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || | |
| 1449 | source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) | |
| 1450 | return Z_STREAM_ERROR; | |
| 1451 | state = (struct inflate_state FAR *)source->state; | |
| 1452 | 1452 | |
| 1453 | /* allocate space */ | |
| 1454 | copy = (struct inflate_state FAR *) | |
| 1455 | ZALLOC(source, 1, sizeof(struct inflate_state)); | |
| 1456 | if (copy == Z_NULL) return Z_MEM_ERROR; | |
| 1457 | window = Z_NULL; | |
| 1458 | if (state->window != Z_NULL) { | |
| 1459 | window = (unsigned char FAR *) | |
| 1460 | ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); | |
| 1461 | if (window == Z_NULL) { | |
| 1462 | ZFREE(source, copy); | |
| 1463 | return Z_MEM_ERROR; | |
| 1464 | } | |
| 1465 | } | |
| 1453 | /* allocate space */ | |
| 1454 | copy = (struct inflate_state FAR *) | |
| 1455 | ZALLOC(source, 1, sizeof(struct inflate_state)); | |
| 1456 | if (copy == Z_NULL) return Z_MEM_ERROR; | |
| 1457 | window = Z_NULL; | |
| 1458 | if (state->window != Z_NULL) { | |
| 1459 | window = (unsigned char FAR *) | |
| 1460 | ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); | |
| 1461 | if (window == Z_NULL) { | |
| 1462 | ZFREE(source, copy); | |
| 1463 | return Z_MEM_ERROR; | |
| 1464 | } | |
| 1465 | } | |
| 1466 | 1466 | |
| 1467 | /* copy state */ | |
| 1468 | zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); | |
| 1469 | zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); | |
| 1470 | if (state->lencode >= state->codes && | |
| 1471 | state->lencode <= state->codes + ENOUGH - 1) { | |
| 1472 | copy->lencode = copy->codes + (state->lencode - state->codes); | |
| 1473 | copy->distcode = copy->codes + (state->distcode - state->codes); | |
| 1474 | } | |
| 1475 | copy->next = copy->codes + (state->next - state->codes); | |
| 1476 | if (window != Z_NULL) { | |
| 1477 | wsize = 1U << state->wbits; | |
| 1478 | zmemcpy(window, state->window, wsize); | |
| 1479 | } | |
| 1480 | copy->window = window; | |
| 1481 | dest->state = (struct internal_state FAR *)copy; | |
| 1482 | return Z_OK; | |
| 1467 | /* copy state */ | |
| 1468 | zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); | |
| 1469 | zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); | |
| 1470 | if (state->lencode >= state->codes && | |
| 1471 | state->lencode <= state->codes + ENOUGH - 1) { | |
| 1472 | copy->lencode = copy->codes + (state->lencode - state->codes); | |
| 1473 | copy->distcode = copy->codes + (state->distcode - state->codes); | |
| 1474 | } | |
| 1475 | copy->next = copy->codes + (state->next - state->codes); | |
| 1476 | if (window != Z_NULL) { | |
| 1477 | wsize = 1U << state->wbits; | |
| 1478 | zmemcpy(window, state->window, wsize); | |
| 1479 | } | |
| 1480 | copy->window = window; | |
| 1481 | dest->state = (struct internal_state FAR *)copy; | |
| 1482 | return Z_OK; | |
| 1483 | 1483 | } |
| 1484 | 1484 | |
| 1485 | 1485 | int ZEXPORT inflateUndermine(strm, subvert) |
| 1486 | 1486 | z_streamp strm; |
| 1487 | 1487 | int subvert; |
| 1488 | 1488 | { |
| 1489 | ||
| 1489 | struct inflate_state FAR *state; | |
| 1490 | 1490 | |
| 1491 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 1492 | state = (struct inflate_state FAR *)strm->state; | |
| 1493 | state->sane = !subvert; | |
| 1491 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | |
| 1492 | state = (struct inflate_state FAR *)strm->state; | |
| 1493 | state->sane = !subvert; | |
| 1494 | 1494 | #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR |
| 1495 | ||
| 1495 | return Z_OK; | |
| 1496 | 1496 | #else |
| 1497 | state->sane = 1; | |
| 1498 | return Z_DATA_ERROR; | |
| 1497 | state->sane = 1; | |
| 1498 | return Z_DATA_ERROR; | |
| 1499 | 1499 | #endif |
| 1500 | 1500 | } |
| 1501 | 1501 | |
| 1502 | 1502 | long ZEXPORT inflateMark(strm) |
| 1503 | 1503 | z_streamp strm; |
| 1504 | 1504 | { |
| 1505 | ||
| 1505 | struct inflate_state FAR *state; | |
| 1506 | 1506 | |
| 1507 | if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16; | |
| 1508 | state = (struct inflate_state FAR *)strm->state; | |
| 1509 | return ((long)(state->back) << 16) + | |
| 1510 | (state->mode == COPY ? state->length : | |
| 1511 | (state->mode == MATCH ? state->was - state->length : 0)); | |
| 1507 | if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16; | |
| 1508 | state = (struct inflate_state FAR *)strm->state; | |
| 1509 | return ((long)(state->back) << 16) + | |
| 1510 | (state->mode == COPY ? state->length : | |
| 1511 | (state->mode == MATCH ? state->was - state->length : 0)); | |
| 1512 | 1512 | } |
| r25360 | r25361 | |
|---|---|---|
| 22 | 22 | buffer, or Z_DATA_ERROR if the input data was corrupted. |
| 23 | 23 | */ |
| 24 | 24 | int ZEXPORT uncompress (dest, destLen, source, sourceLen) |
| 25 | Bytef *dest; | |
| 26 | uLongf *destLen; | |
| 27 | const Bytef *source; | |
| 28 | uLong sourceLen; | |
| 25 | Bytef *dest; | |
| 26 | uLongf *destLen; | |
| 27 | const Bytef *source; | |
| 28 | uLong sourceLen; | |
| 29 | 29 | { |
| 30 | z_stream stream; | |
| 31 | int err; | |
| 30 | z_stream stream; | |
| 31 | int err; | |
| 32 | 32 | |
| 33 | stream.next_in = (z_const Bytef *)source; | |
| 34 | stream.avail_in = (uInt)sourceLen; | |
| 35 | /* Check for source > 64K on 16-bit machine: */ | |
| 36 | if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; | |
| 33 | stream.next_in = (z_const Bytef *)source; | |
| 34 | stream.avail_in = (uInt)sourceLen; | |
| 35 | /* Check for source > 64K on 16-bit machine: */ | |
| 36 | if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; | |
| 37 | 37 | |
| 38 | stream.next_out = dest; | |
| 39 | stream.avail_out = (uInt)*destLen; | |
| 40 | if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; | |
| 38 | stream.next_out = dest; | |
| 39 | stream.avail_out = (uInt)*destLen; | |
| 40 | if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; | |
| 41 | 41 | |
| 42 | stream.zalloc = (alloc_func)0; | |
| 43 | stream.zfree = (free_func)0; | |
| 42 | stream.zalloc = (alloc_func)0; | |
| 43 | stream.zfree = (free_func)0; | |
| 44 | 44 | |
| 45 | err = inflateInit(&stream); | |
| 46 | if (err != Z_OK) return err; | |
| 45 | err = inflateInit(&stream); | |
| 46 | if (err != Z_OK) return err; | |
| 47 | 47 | |
| 48 | err = inflate(&stream, Z_FINISH); | |
| 49 | if (err != Z_STREAM_END) { | |
| 50 | inflateEnd(&stream); | |
| 51 | if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) | |
| 52 | return Z_DATA_ERROR; | |
| 53 | return err; | |
| 54 | } | |
| 55 | *destLen = stream.total_out; | |
| 48 | err = inflate(&stream, Z_FINISH); | |
| 49 | if (err != Z_STREAM_END) { | |
| 50 | inflateEnd(&stream); | |
| 51 | if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) | |
| 52 | return Z_DATA_ERROR; | |
| 53 | return err; | |
| 54 | } | |
| 55 | *destLen = stream.total_out; | |
| 56 | 56 | |
| 57 | err = inflateEnd(&stream); | |
| 58 | return err; | |
| 57 | err = inflateEnd(&stream); | |
| 58 | return err; | |
| 59 | 59 | } |
| r25360 | r25361 | |
|---|---|---|
| 22 | 22 | of a literal, the base length or distance, or the offset from |
| 23 | 23 | the current table to the next table. Each entry is four bytes. */ |
| 24 | 24 | typedef struct { |
| 25 | unsigned char op; /* operation, extra bits, table bits */ | |
| 26 | unsigned char bits; /* bits in this part of the code */ | |
| 27 | unsigned short val; /* offset in table or code value */ | |
| 25 | unsigned char op; /* operation, extra bits, table bits */ | |
| 26 | unsigned char bits; /* bits in this part of the code */ | |
| 27 | unsigned short val; /* offset in table or code value */ | |
| 28 | 28 | } code; |
| 29 | 29 | |
| 30 | 30 | /* op values as set by inflate_table(): |
| r25360 | r25361 | |
| 52 | 52 | |
| 53 | 53 | /* Type of code to build for inflate_table() */ |
| 54 | 54 | typedef enum { |
| 55 | CODES, | |
| 56 | LENS, | |
| 57 | DISTS | |
| 55 | CODES, | |
| 56 | LENS, | |
| 57 | DISTS | |
| 58 | 58 | } codetype; |
| 59 | 59 | |
| 60 | 60 | int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, |
| 61 | unsigned codes, code FAR * FAR *table, | |
| 62 | unsigned FAR *bits, unsigned short FAR *work)); | |
| 61 | unsigned codes, code FAR * FAR *table, | |
| 62 | unsigned FAR *bits, unsigned short FAR *work)); |
| r25360 | r25361 | |
|---|---|---|
| 260 | 260 | for small objects. |
| 261 | 261 | */ |
| 262 | 262 | |
| 263 | ||
| 263 | /* Type declarations */ | |
| 264 | 264 | |
| 265 | 265 | #ifndef OF /* function prototypes */ |
| 266 | 266 | # ifdef STDC |
| r25360 | r25361 | |
| 286 | 286 | */ |
| 287 | 287 | #ifdef SYS16BIT |
| 288 | 288 | # if defined(M_I86SM) || defined(M_I86MM) |
| 289 | ||
| 289 | /* MSC small or medium model */ | |
| 290 | 290 | # define SMALL_MEDIUM |
| 291 | 291 | # ifdef _MSC_VER |
| 292 | 292 | # define FAR _far |
| r25360 | r25361 | |
| 295 | 295 | # endif |
| 296 | 296 | # endif |
| 297 | 297 | # if (defined(__SMALL__) || defined(__MEDIUM__)) |
| 298 | ||
| 298 | /* Turbo C small or medium model */ | |
| 299 | 299 | # define SMALL_MEDIUM |
| 300 | 300 | # ifdef __BORLANDC__ |
| 301 | 301 | # define FAR _far |
| r25360 | r25361 | |
| 306 | 306 | #endif |
| 307 | 307 | |
| 308 | 308 | #if defined(WINDOWS) || defined(WIN32) |
| 309 | /* If building or using zlib as a DLL, define ZLIB_DLL. | |
| 310 | * This is not mandatory, but it offers a little performance increase. | |
| 311 | */ | |
| 309 | /* If building or using zlib as a DLL, define ZLIB_DLL. | |
| 310 | * This is not mandatory, but it offers a little performance increase. | |
| 311 | */ | |
| 312 | 312 | # ifdef ZLIB_DLL |
| 313 | 313 | # if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) |
| 314 | 314 | # ifdef ZLIB_INTERNAL |
| r25360 | r25361 | |
| 318 | 318 | # endif |
| 319 | 319 | # endif |
| 320 | 320 | # endif /* ZLIB_DLL */ |
| 321 | /* If building or using zlib with the WINAPI/WINAPIV calling convention, | |
| 322 | * define ZLIB_WINAPI. | |
| 323 | * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. | |
| 324 | */ | |
| 321 | /* If building or using zlib with the WINAPI/WINAPIV calling convention, | |
| 322 | * define ZLIB_WINAPI. | |
| 323 | * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. | |
| 324 | */ | |
| 325 | 325 | # ifdef ZLIB_WINAPI |
| 326 | 326 | # ifdef FAR |
| 327 | 327 | # undef FAR |
| 328 | 328 | # endif |
| 329 | 329 | # include <windows.h> |
| 330 | /* No need for _export, use ZLIB.DEF instead. */ | |
| 331 | /* For complete Windows compatibility, use WINAPI, not __stdcall. */ | |
| 330 | /* No need for _export, use ZLIB.DEF instead. */ | |
| 331 | /* For complete Windows compatibility, use WINAPI, not __stdcall. */ | |
| 332 | 332 | # define ZEXPORT WINAPI |
| 333 | 333 | # ifdef WIN32 |
| 334 | 334 | # define ZEXPORTVA WINAPIV |
| r25360 | r25361 | |
| 371 | 371 | typedef unsigned long uLong; /* 32 bits or more */ |
| 372 | 372 | |
| 373 | 373 | #ifdef SMALL_MEDIUM |
| 374 | ||
| 374 | /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ | |
| 375 | 375 | # define Bytef Byte FAR |
| 376 | 376 | #else |
| 377 | ||
| 377 | typedef Byte FAR Bytef; | |
| 378 | 378 | #endif |
| 379 | 379 | typedef char FAR charf; |
| 380 | 380 | typedef int FAR intf; |
| r25360 | r25361 | |
| 382 | 382 | typedef uLong FAR uLongf; |
| 383 | 383 | |
| 384 | 384 | #ifdef STDC |
| 385 | typedef void const *voidpc; | |
| 386 | typedef void FAR *voidpf; | |
| 387 | typedef void *voidp; | |
| 385 | typedef void const *voidpc; | |
| 386 | typedef void FAR *voidpf; | |
| 387 | typedef void *voidp; | |
| 388 | 388 | #else |
| 389 | typedef Byte const *voidpc; | |
| 390 | typedef Byte FAR *voidpf; | |
| 391 | typedef Byte *voidp; | |
| 389 | typedef Byte const *voidpc; | |
| 390 | typedef Byte FAR *voidpf; | |
| 391 | typedef Byte *voidp; | |
| 392 | 392 | #endif |
| 393 | 393 | |
| 394 | 394 | #if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) |
| r25360 | r25361 | |
| 403 | 403 | #endif |
| 404 | 404 | |
| 405 | 405 | #ifdef Z_U4 |
| 406 | ||
| 406 | typedef Z_U4 z_crc_t; | |
| 407 | 407 | #else |
| 408 | ||
| 408 | typedef unsigned long z_crc_t; | |
| 409 | 409 | #endif |
| 410 | 410 | |
| 411 | 411 | #ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ |
| r25360 | r25361 | |
| 493 | 493 | |
| 494 | 494 | /* MVS linker does not support external names larger than 8 bytes */ |
| 495 | 495 | #if defined(__MVS__) |
| 496 | #pragma map(deflateInit_,"DEIN") | |
| 497 | #pragma map(deflateInit2_,"DEIN2") | |
| 498 | #pragma map(deflateEnd,"DEEND") | |
| 499 | #pragma map(deflateBound,"DEBND") | |
| 500 | #pragma map(inflateInit_,"ININ") | |
| 501 | #pragma map(inflateInit2_,"ININ2") | |
| 502 | #pragma map(inflateEnd,"INEND") | |
| 503 | #pragma map(inflateSync,"INSY") | |
| 504 | #pragma map(inflateSetDictionary,"INSEDI") | |
| 505 | #pragma map(compressBound,"CMBND") | |
| 506 | #pragma map(inflate_table,"INTABL") | |
| 507 | #pragma map(inflate_fast,"INFA") | |
| 508 | #pragma map(inflate_copyright,"INCOPY") | |
| 496 | #pragma map(deflateInit_,"DEIN") | |
| 497 | #pragma map(deflateInit2_,"DEIN2") | |
| 498 | #pragma map(deflateEnd,"DEEND") | |
| 499 | #pragma map(deflateBound,"DEBND") | |
| 500 | #pragma map(inflateInit_,"ININ") | |
| 501 | #pragma map(inflateInit2_,"ININ2") | |
| 502 | #pragma map(inflateEnd,"INEND") | |
| 503 | #pragma map(inflateSync,"INSY") | |
| 504 | #pragma map(inflateSetDictionary,"INSEDI") | |
| 505 | #pragma map(compressBound,"CMBND") | |
| 506 | #pragma map(inflate_table,"INTABL") | |
| 507 | #pragma map(inflate_fast,"INFA") | |
| 508 | #pragma map(inflate_copyright,"INCOPY") | |
| 509 | 509 | #endif |
| 510 | 510 | |
| 511 | 511 | #endif /* ZCONF_H */ |
| r25360 | r25361 | |
|---|---|---|
| 1466 | 1466 | if(cur_live.bit_counter & 15) |
| 1467 | 1467 | break; |
| 1468 | 1468 | int slot = (cur_live.bit_counter >> 4)-1; |
| 1469 | // | |
| 1469 | // fprintf(stderr, "%s: slot[%d] = %02x crc = %04x\n", tts(cur_live.tm).cstr(), slot, cur_live.data_reg, cur_live.crc); | |
| 1470 | 1470 | cur_live.idbuf[slot] = cur_live.data_reg; |
| 1471 | 1471 | if(slot == 5) { |
| 1472 | 1472 | live_delay(IDLE); |
| r25360 | r25361 | |
|---|---|---|
| 558 | 558 | |
| 559 | 559 | // legacy |
| 560 | 560 | INTERRUPT_GEN( irq2_line_hold ) { device->machine().driver_data()->irq2_line_hold(*device); } |
| 561 |
| r25360 | r25361 | |
|---|---|---|
| 37 | 37 | |
| 38 | 38 | **************************************************************************** |
| 39 | 39 | |
| 40 | Serial EEPROMs generally work the same across manufacturers and models, | |
| 41 | varying largely by the size of the EEPROM and the packaging details. | |
| 42 | ||
| 43 | At a basic level, there are 5 signals involved: | |
| 44 | ||
| 45 | * CS = chip select | |
| 46 | * CLK = serial data clock | |
| 47 | * DI = serial data in | |
| 48 | * DO = serial data out | |
| 49 | * RDY/BUSY = ready (1) or busy (0) status | |
| 50 | ||
| 51 | Data is read or written via serial commands. A command is begun on a | |
| 52 | low-to-high transition of the CS line, following by clocking a start | |
| 53 | bit (1) on the DI line. After the start bit, subsequent clocks | |
| 54 | assemble one of the following commands: | |
| 55 | ||
| 56 | Start Opcode Address Data | |
| 57 | 1 01 aaaaaaaaa ddddddd WRITE data | |
| 58 | 1 10 aaaaaaaaa READ data | |
| 59 | 1 11 aaaaaaaaa ERASE data | |
| 60 | 1 00 00xxxxxxx WREN = WRite ENable | |
| 61 | 1 00 01xxxxxxx ddddddd WRAL = WRite ALl cells | |
| 62 | 1 00 10xxxxxxx ERAL = ERase ALl cells | |
| 63 | 1 00 11xxxxxxx WRDS = WRite DiSable | |
| 40 | Serial EEPROMs generally work the same across manufacturers and models, | |
| 41 | varying largely by the size of the EEPROM and the packaging details. | |
| 64 | 42 | |
| 65 | The number of address bits (a) clocked varies based on the size of the | |
| 66 | chip, though it does not always map 1:1 with the size of the chip. | |
| 67 | For example, the 93C06 has 16 cells, which only needs 4 address bits; | |
| 68 | but commands to the 93C06 require 6 address bits (the top two must | |
| 69 | be 0). | |
| 70 | ||
| 71 | The number of data bits (d) clocked varies based on the chip and at | |
| 72 | times on the state of a pin on the chip which selects between multiple | |
| 73 | sizes (e.g., 8-bit versus 16-bit). | |
| 74 | ||
| 43 | At a basic level, there are 5 signals involved: | |
| 44 | ||
| 45 | * CS = chip select | |
| 46 | * CLK = serial data clock | |
| 47 | * DI = serial data in | |
| 48 | * DO = serial data out | |
| 49 | * RDY/BUSY = ready (1) or busy (0) status | |
| 50 | ||
| 51 | Data is read or written via serial commands. A command is begun on a | |
| 52 | low-to-high transition of the CS line, following by clocking a start | |
| 53 | bit (1) on the DI line. After the start bit, subsequent clocks | |
| 54 | assemble one of the following commands: | |
| 55 | ||
| 56 | Start Opcode Address Data | |
| 57 | 1 01 aaaaaaaaa ddddddd WRITE data | |
| 58 | 1 10 aaaaaaaaa READ data | |
| 59 | 1 11 aaaaaaaaa ERASE data | |
| 60 | 1 00 00xxxxxxx WREN = WRite ENable | |
| 61 | 1 00 01xxxxxxx ddddddd WRAL = WRite ALl cells | |
| 62 | 1 00 10xxxxxxx ERAL = ERase ALl cells | |
| 63 | 1 00 11xxxxxxx WRDS = WRite DiSable | |
| 64 | ||
| 65 | The number of address bits (a) clocked varies based on the size of the | |
| 66 | chip, though it does not always map 1:1 with the size of the chip. | |
| 67 | For example, the 93C06 has 16 cells, which only needs 4 address bits; | |
| 68 | but commands to the 93C06 require 6 address bits (the top two must | |
| 69 | be 0). | |
| 70 | ||
| 71 | The number of data bits (d) clocked varies based on the chip and at | |
| 72 | times on the state of a pin on the chip which selects between multiple | |
| 73 | sizes (e.g., 8-bit versus 16-bit). | |
| 74 | ||
| 75 | 75 | **************************************************************************** |
| 76 | 76 | |
| 77 | Most EEPROMs are based on the 93Cxx design (and have similar part | |
| 78 | designations): | |
| 79 | ||
| 80 | +--v--+ | |
| 81 | CS |1 8| Vcc | |
| 82 | CLK |2 7| NC | |
| 83 | DI |3 6| NC | |
| 84 | DO |4 5| GND | |
| 85 | +-----+ | |
| 86 | ||
| 87 | Note the lack of a READY/BUSY pin. On the 93Cxx series, the DO pin | |
| 88 | serves double-duty, returning READY/BUSY during a write/erase cycle, | |
| 89 | and outputting data during a read cycle. | |
| 90 | ||
| 91 | Some manufacturers have released "enhanced" versions with additional | |
| 92 | features: | |
| 93 | ||
| 94 | * Several manufacturers (ST) map pin 6 to "ORG", specifying the | |
| 95 | logical organization of the data. Connecting ORG to ground | |
| 96 | makes the EEPROM work as an 8-bit device, while connecting it | |
| 97 | to Vcc makes it work as a 16-bit device with one less | |
| 98 | address bit. | |
| 99 | ||
| 100 | * Other manufacturers (ST) have enhanced the read operations to | |
| 101 | allow serially streaming more than one cell. Essentially, after | |
| 102 | reading the first cell, keep CS high and keep clocking, and | |
| 103 | data from following cells will be read as well. | |
| 77 | Most EEPROMs are based on the 93Cxx design (and have similar part | |
| 78 | designations): | |
| 104 | 79 | |
| 105 | The ER5911 is only slightly different: | |
| 106 | ||
| 107 | +--v--+ | |
| 108 | CS |1 8| Vcc | |
| 109 | CLK |2 7| RDY/BUSY | |
| 110 | DI |3 6| ORG | |
| 111 | DO |4 5| GND | |
| 112 | +-----+ | |
| 113 | ||
| 114 | Here we have an explicit RDY/BUSY signal, and the ORG flag as described | |
| 115 | above. | |
| 80 | +--v--+ | |
| 81 | CS |1 8| Vcc | |
| 82 | CLK |2 7| NC | |
| 83 | DI |3 6| NC | |
| 84 | DO |4 5| GND | |
| 85 | +-----+ | |
| 116 | 86 | |
| 117 | From a command perspective, the ER5911 is also slightly different: | |
| 118 | ||
| 119 | 93Cxx has ERASE command; this maps to WRITE on ER5911 | |
| 120 | 93Cxx has WRITEALL command; no equivalent on ER5911 | |
| 87 | Note the lack of a READY/BUSY pin. On the 93Cxx series, the DO pin | |
| 88 | serves double-duty, returning READY/BUSY during a write/erase cycle, | |
| 89 | and outputting data during a read cycle. | |
| 121 | 90 | |
| 91 | Some manufacturers have released "enhanced" versions with additional | |
| 92 | features: | |
| 93 | ||
| 94 | * Several manufacturers (ST) map pin 6 to "ORG", specifying the | |
| 95 | logical organization of the data. Connecting ORG to ground | |
| 96 | makes the EEPROM work as an 8-bit device, while connecting it | |
| 97 | to Vcc makes it work as a 16-bit device with one less | |
| 98 | address bit. | |
| 99 | ||
| 100 | * Other manufacturers (ST) have enhanced the read operations to | |
| 101 | allow serially streaming more than one cell. Essentially, after | |
| 102 | reading the first cell, keep CS high and keep clocking, and | |
| 103 | data from following cells will be read as well. | |
| 104 | ||
| 105 | The ER5911 is only slightly different: | |
| 106 | ||
| 107 | +--v--+ | |
| 108 | CS |1 8| Vcc | |
| 109 | CLK |2 7| RDY/BUSY | |
| 110 | DI |3 6| ORG | |
| 111 | DO |4 5| GND | |
| 112 | +-----+ | |
| 113 | ||
| 114 | Here we have an explicit RDY/BUSY signal, and the ORG flag as described | |
| 115 | above. | |
| 116 | ||
| 117 | From a command perspective, the ER5911 is also slightly different: | |
| 118 | ||
| 119 | 93Cxx has ERASE command; this maps to WRITE on ER5911 | |
| 120 | 93Cxx has WRITEALL command; no equivalent on ER5911 | |
| 121 | ||
| 122 | 122 | **************************************************************************** |
| 123 | 123 | |
| 124 | Issues with: | |
| 125 | ||
| 126 | kickgoal.c - code seems wrong, clock logic writes 0-0-0 instead of 0-1-0 as expected | |
| 127 | overdriv.c - drops CS, raises CS, keeps DI=1, triggering extraneous start bit | |
| 128 | ||
| 124 | Issues with: | |
| 125 | ||
| 126 | kickgoal.c - code seems wrong, clock logic writes 0-0-0 instead of 0-1-0 as expected | |
| 127 | overdriv.c - drops CS, raises CS, keeps DI=1, triggering extraneous start bit | |
| 128 | ||
| 129 | 129 | ***************************************************************************/ |
| 130 | 130 | |
| 131 | 131 | #include "emu.h" |
| r25360 | r25361 | |
| 138 | 138 | //************************************************************************** |
| 139 | 139 | |
| 140 | 140 | // logging levels: |
| 141 | // 0 = errors and warnings only | |
| 142 | // 1 = commands | |
| 143 | // 2 = state machine | |
| 144 | // 3 = DI/DO/READY reads & writes | |
| 145 | // 4 = all reads & writes | |
| 141 | // 0 = errors and warnings only | |
| 142 | // 1 = commands | |
| 143 | // 2 = state machine | |
| 144 | // 3 = DI/DO/READY reads & writes | |
| 145 | // 4 = all reads & writes | |
| 146 | 146 | |
| 147 | 147 | #define VERBOSE_PRINTF 0 |
| 148 | 148 | #define VERBOSE_LOGERROR 0 |
| r25360 | r25361 | |
| 195 | 195 | //------------------------------------------------- |
| 196 | 196 | // static_set_address_bits - configuration helper |
| 197 | 197 | // to set the number of address bits in the |
| 198 | // | |
| 198 | // serial commands | |
| 199 | 199 | //------------------------------------------------- |
| 200 | 200 | |
| 201 | 201 | void eeprom_serial_base_device::static_set_address_bits(device_t &device, int addrbits) |
| r25360 | r25361 | |
| 227 | 227 | |
| 228 | 228 | // start the base class |
| 229 | 229 | eeprom_base_device::device_start(); |
| 230 | ||
| 230 | ||
| 231 | 231 | // save the current state |
| 232 | 232 | save_item(NAME(m_state)); |
| 233 | 233 | save_item(NAME(m_cs_state)); |
| r25360 | r25361 | |
| 269 | 269 | //************************************************************************** |
| 270 | 270 | |
| 271 | 271 | //------------------------------------------------- |
| 272 | // base_cs_write - set the state of the chip | |
| 273 | // select (CS) line | |
| 272 | // base_cs_write - set the state of the chip | |
| 273 | // select (CS) line | |
| 274 | 274 | //------------------------------------------------- |
| 275 | 275 | |
| 276 | 276 | void eeprom_serial_base_device::base_cs_write(int state) |
| r25360 | r25361 | |
| 280 | 280 | if (state == m_cs_state) |
| 281 | 281 | return; |
| 282 | 282 | |
| 283 | // set the new state | |
| 283 | // set the new state | |
| 284 | 284 | LOG4((" cs_write(%d)\n", state)); |
| 285 | 285 | m_cs_state = state; |
| 286 | ||
| 286 | ||
| 287 | 287 | // remember the rising edge time so we don't process CLK signals at the same time |
| 288 | 288 | if (state == ASSERT_LINE) |
| 289 | 289 | m_last_cs_rising_edge_time = machine().time(); |
| r25360 | r25361 | |
| 292 | 292 | |
| 293 | 293 | |
| 294 | 294 | //------------------------------------------------- |
| 295 | // base_clk_write - set the state of the clock | |
| 295 | // base_clk_write - set the state of the clock | |
| 296 | 296 | // (CLK) line |
| 297 | 297 | //------------------------------------------------- |
| 298 | 298 | |
| r25360 | r25361 | |
| 303 | 303 | if (state == m_clk_state) |
| 304 | 304 | return; |
| 305 | 305 | |
| 306 | // set the new state | |
| 306 | // set the new state | |
| 307 | 307 | LOG4((" clk_write(%d)\n", state)); |
| 308 | 308 | m_clk_state = state; |
| 309 | 309 | handle_event((m_clk_state == ASSERT_LINE) ? EVENT_CLK_RISING_EDGE : EVENT_CLK_FALLING_EDGE); |
| r25360 | r25361 | |
| 311 | 311 | |
| 312 | 312 | |
| 313 | 313 | //------------------------------------------------- |
| 314 | // base_di_write - set the state of the data input | |
| 315 | // (DI) line | |
| 314 | // base_di_write - set the state of the data input | |
| 315 | // (DI) line | |
| 316 | 316 | //------------------------------------------------- |
| 317 | 317 | |
| 318 | 318 | void eeprom_serial_base_device::base_di_write(int state) |
| r25360 | r25361 | |
| 325 | 325 | |
| 326 | 326 | |
| 327 | 327 | //------------------------------------------------- |
| 328 | // base_do_read - read the state of the data | |
| 328 | // base_do_read - read the state of the data | |
| 329 | 329 | // output (DO) line |
| 330 | 330 | //------------------------------------------------- |
| 331 | 331 | |
| r25360 | r25361 | |
| 341 | 341 | |
| 342 | 342 | |
| 343 | 343 | //------------------------------------------------- |
| 344 | // base_ready_read - read the state of the | |
| 344 | // base_ready_read - read the state of the | |
| 345 | 345 | // READY/BUSY line |
| 346 | 346 | //------------------------------------------------- |
| 347 | 347 | |
| r25360 | r25361 | |
| 390 | 390 | |
| 391 | 391 | //------------------------------------------------- |
| 392 | 392 | // handle_event - handle an event via the state |
| 393 | // | |
| 393 | // machine | |
| 394 | 394 | //------------------------------------------------- |
| 395 | 395 | |
| 396 | 396 | void eeprom_serial_base_device::handle_event(eeprom_event event) |
| r25360 | r25361 | |
| 421 | 421 | if (event == EVENT_CS_RISING_EDGE) |
| 422 | 422 | set_state(STATE_WAIT_FOR_START_BIT); |
| 423 | 423 | break; |
| 424 | ||
| 424 | ||
| 425 | 425 | // CS is asserted; wait for rising clock with a 1 start bit; falling CS will reset us |
| 426 | 426 | // note that because each bit is written independently, it is possible for us to receive |
| 427 | 427 | // a false rising CLK edge at the exact same time as a rising CS edge; it appears we |
| r25360 | r25361 | |
| 435 | 435 | else if (event == EVENT_CS_FALLING_EDGE) |
| 436 | 436 | set_state(STATE_IN_RESET); |
| 437 | 437 | break; |
| 438 | ||
| 438 | ||
| 439 | 439 | // CS is asserted; wait for a command to come through; falling CS will reset us |
| 440 | 440 | case STATE_WAIT_FOR_COMMAND: |
| 441 | 441 | if (event == EVENT_CLK_RISING_EDGE) |
| r25360 | r25361 | |
| 448 | 448 | else if (event == EVENT_CS_FALLING_EDGE) |
| 449 | 449 | set_state(STATE_IN_RESET); |
| 450 | 450 | break; |
| 451 | ||
| 451 | ||
| 452 | 452 | // CS is asserted; reading data, clock the shift register; falling CS will reset us |
| 453 | 453 | case STATE_READING_DATA: |
| 454 | 454 | if (event == EVENT_CLK_RISING_EDGE) |
| 455 | 455 | { |
| 456 | 456 | int bit_index = m_bits_accum++; |
| 457 | ||
| 457 | ||
| 458 | 458 | // wrapping the address on multi-read is required by pacslot(cave.c) |
| 459 | 459 | if (bit_index % m_data_bits == 0 && (bit_index == 0 || m_streaming_enabled)) |
| 460 | 460 | m_shift_register = read((m_address + m_bits_accum / m_data_bits) & ((1 << m_address_bits) - 1)) << (32 - m_data_bits); |
| r25360 | r25361 | |
| 474 | 474 | LOG0(("EEPROM: CS deasserted in READING_DATA after %d bits\n", m_bits_accum)); |
| 475 | 475 | } |
| 476 | 476 | break; |
| 477 | ||
| 477 | ||
| 478 | 478 | // CS is asserted; waiting for data; clock data through until we accumulate enough; falling CS will reset us |
| 479 | 479 | case STATE_WAIT_FOR_DATA: |
| 480 | 480 | if (event == EVENT_CLK_RISING_EDGE) |
| r25360 | r25361 | |
| 489 | 489 | LOG0(("EEPROM: CS deasserted in STATE_WAIT_FOR_DATA after %d bits\n", m_bits_accum)); |
| 490 | 490 | } |
| 491 | 491 | break; |
| 492 | ||
| 492 | ||
| 493 | 493 | // CS is asserted; waiting for completion; watch for CS falling |
| 494 | 494 | case STATE_WAIT_FOR_COMPLETION: |
| 495 | 495 | if (event == EVENT_CS_FALLING_EDGE) |
| r25360 | r25361 | |
| 501 | 501 | |
| 502 | 502 | //------------------------------------------------- |
| 503 | 503 | // execute_command - execute a command once we |
| 504 | // | |
| 504 | // have enough bits for one | |
| 505 | 505 | //------------------------------------------------- |
| 506 | 506 | |
| 507 | 507 | void eeprom_serial_base_device::execute_command() |
| r25360 | r25361 | |
| 509 | 509 | // parse into a generic command and reset the accumulator count |
| 510 | 510 | parse_command_and_address(); |
| 511 | 511 | m_bits_accum = 0; |
| 512 | ||
| 512 | ||
| 513 | 513 | #if (VERBOSE_PRINTF > 0 || VERBOSE_LOGERROR > 0) |
| 514 | 514 | // for debugging purposes |
| 515 | 515 | static const struct { eeprom_command command; const char *string; } s_command_names[] = |
| r25360 | r25361 | |
| 540 | 540 | m_shift_register = 0; |
| 541 | 541 | set_state(STATE_READING_DATA); |
| 542 | 542 | break; |
| 543 | ||
| 543 | ||
| 544 | 544 | // reset the shift register and wait for enough data to be clocked through |
| 545 | 545 | case COMMAND_WRITE: |
| 546 | 546 | case COMMAND_WRITEALL: |
| 547 | 547 | m_shift_register = 0; |
| 548 | 548 | set_state(STATE_WAIT_FOR_DATA); |
| 549 | 549 | break; |
| 550 | ||
| 550 | ||
| 551 | 551 | // erase the parsed address (unless locked) and wait for it to complete |
| 552 | 552 | case COMMAND_ERASE: |
| 553 | 553 | if (m_locked) |
| r25360 | r25361 | |
| 559 | 559 | erase(m_address); |
| 560 | 560 | set_state(STATE_WAIT_FOR_COMPLETION); |
| 561 | 561 | break; |
| 562 | ||
| 562 | ||
| 563 | 563 | // lock the chip; return to IN_RESET state |
| 564 | 564 | case COMMAND_LOCK: |
| 565 | 565 | m_locked = true; |
| 566 | 566 | set_state(STATE_IN_RESET); |
| 567 | 567 | break; |
| 568 | ||
| 568 | ||
| 569 | 569 | // unlock the chip; return to IN_RESET state |
| 570 | 570 | case COMMAND_UNLOCK: |
| 571 | 571 | m_locked = false; |
| 572 | 572 | set_state(STATE_IN_RESET); |
| 573 | 573 | break; |
| 574 | ||
| 574 | ||
| 575 | 575 | // erase the entire chip (unless locked) and wait for it to complete |
| 576 | 576 | case COMMAND_ERASEALL: |
| 577 | 577 | if (m_locked) |
| r25360 | r25361 | |
| 583 | 583 | erase_all(); |
| 584 | 584 | set_state(STATE_WAIT_FOR_COMPLETION); |
| 585 | 585 | break; |
| 586 | ||
| 586 | ||
| 587 | 587 | default: |
| 588 | 588 | throw emu_fatalerror("execute_command called with invalid command %d\n", m_command); |
| 589 | 589 | } |
| r25360 | r25361 | |
| 591 | 591 | |
| 592 | 592 | |
| 593 | 593 | //------------------------------------------------- |
| 594 | // execute_write_command - execute a write | |
| 595 | // command after receiving the data bits | |
| 594 | // execute_write_command - execute a write | |
| 595 | // command after receiving the data bits | |
| 596 | 596 | //------------------------------------------------- |
| 597 | 597 | |
| 598 | 598 | void eeprom_serial_base_device::execute_write_command() |
| r25360 | r25361 | |
| 627 | 627 | break; |
| 628 | 628 | |
| 629 | 629 | // write the entire EEPROM with the same data; ERASEALL is required before so we |
| 630 | // AND against the already-present data | |
| 630 | // AND against the already-present data | |
| 631 | 631 | case COMMAND_WRITEALL: |
| 632 | 632 | if (m_locked) |
| 633 | 633 | { |
| r25360 | r25361 | |
| 638 | 638 | write_all(m_shift_register); |
| 639 | 639 | set_state(STATE_WAIT_FOR_COMPLETION); |
| 640 | 640 | break; |
| 641 | ||
| 641 | ||
| 642 | 642 | default: |
| 643 | 643 | throw emu_fatalerror("execute_write_command called with invalid command %d\n", m_command); |
| 644 | 644 | } |
| r25360 | r25361 | |
| 661 | 661 | |
| 662 | 662 | |
| 663 | 663 | //------------------------------------------------- |
| 664 | // parse_command_and_address - extract the | |
| 665 | // command and address from a bitstream | |
| 664 | // parse_command_and_address - extract the | |
| 665 | // command and address from a bitstream | |
| 666 | 666 | //------------------------------------------------- |
| 667 | 667 | |
| 668 | 668 | void eeprom_serial_93cxx_device::parse_command_and_address() |
| r25360 | r25361 | |
| 670 | 670 | // set the defaults |
| 671 | 671 | m_command = COMMAND_INVALID; |
| 672 | 672 | m_address = m_command_address_accum & ((1 << m_command_address_bits) - 1); |
| 673 | ||
| 673 | ||
| 674 | 674 | // extract the command portion and handle it |
| 675 | 675 | switch (m_command_address_accum >> m_command_address_bits) |
| 676 | 676 | { |
| r25360 | r25361 | |
| 678 | 678 | case 0: |
| 679 | 679 | switch (m_address >> (m_command_address_bits - 2)) |
| 680 | 680 | { |
| 681 | case 0: m_command = COMMAND_LOCK; break; | |
| 682 | case 1: m_command = COMMAND_WRITEALL; break; | |
| 683 | case 2: m_command = COMMAND_ERASEALL; break; | |
| 684 | case 3: m_command = COMMAND_UNLOCK; break; | |
| 681 | case 0: m_command = COMMAND_LOCK; break; | |
| 682 | case 1: m_command = COMMAND_WRITEALL; break; | |
| 683 | case 2: m_command = COMMAND_ERASEALL; break; | |
| 684 | case 3: m_command = COMMAND_UNLOCK; break; | |
| 685 | 685 | } |
| 686 | 686 | m_address = 0; |
| 687 | 687 | break; |
| 688 | case 1: m_command = COMMAND_WRITE; break; | |
| 689 | case 2: m_command = COMMAND_READ; break; | |
| 690 | case 3: m_command = COMMAND_ERASE; break; | |
| 688 | case 1: m_command = COMMAND_WRITE; break; | |
| 689 | case 2: m_command = COMMAND_READ; break; | |
| 690 | case 3: m_command = COMMAND_ERASE; break; | |
| 691 | 691 | } |
| 692 | 692 | |
| 693 | 693 | // warn about out-of-range addresses |
| r25360 | r25361 | |
| 728 | 728 | |
| 729 | 729 | |
| 730 | 730 | //------------------------------------------------- |
| 731 | // parse_command_and_address - extract the | |
| 732 | // command and address from a bitstream | |
| 731 | // parse_command_and_address - extract the | |
| 732 | // command and address from a bitstream | |
| 733 | 733 | //------------------------------------------------- |
| 734 | 734 | |
| 735 | 735 | void eeprom_serial_er5911_device::parse_command_and_address() |
| r25360 | r25361 | |
| 737 | 737 | // set the defaults |
| 738 | 738 | m_command = COMMAND_INVALID; |
| 739 | 739 | m_address = m_command_address_accum & ((1 << m_command_address_bits) - 1); |
| 740 | ||
| 740 | ||
| 741 | 741 | // extract the command portion and handle it |
| 742 | 742 | switch (m_command_address_accum >> m_command_address_bits) |
| 743 | 743 | { |
| r25360 | r25361 | |
| 745 | 745 | case 0: |
| 746 | 746 | switch (m_address >> (m_command_address_bits - 2)) |
| 747 | 747 | { |
| 748 | case 0: m_command = COMMAND_LOCK; break; | |
| 749 | case 1: m_command = COMMAND_INVALID; break; // not on ER5911 | |
| 750 | case 2: m_command = COMMAND_ERASEALL; break; | |
| 751 | case 3: m_command = COMMAND_UNLOCK; break; | |
| 748 | case 0: m_command = COMMAND_LOCK; break; | |
| 749 | case 1: m_command = COMMAND_INVALID; break; // not on ER5911 | |
| 750 | case 2: m_command = COMMAND_ERASEALL; break; | |
| 751 | case 3: m_command = COMMAND_UNLOCK; break; | |
| 752 | 752 | } |
| 753 | 753 | m_address = 0; |
| 754 | 754 | break; |
| 755 | case 1: m_command = COMMAND_WRITE; break; | |
| 756 | case 2: m_command = COMMAND_READ; break; | |
| 757 | case 3: m_command = COMMAND_WRITE; break; // WRITE instead of ERASE on ER5911 | |
| 755 | case 1: m_command = COMMAND_WRITE; break; | |
| 756 | case 2: m_command = COMMAND_READ; break; | |
| 757 | case 3: m_command = COMMAND_WRITE; break; // WRITE instead of ERASE on ER5911 | |
| 758 | 758 | } |
| 759 | 759 | |
| 760 | 760 | // warn about out-of-range addresses |
| r25360 | r25361 | |
| 793 | 793 | static_set_size(*this, _cells, _bits); \ |
| 794 | 794 | static_set_address_bits(*this, _addrbits); \ |
| 795 | 795 | }; \ |
| 796 | const device_type EEPROM_SERIAL_##_uppercase##_##_bits##BIT = &device_creator<eeprom_serial_##_lowercase##_##_bits##bit_device>; \ | |
| 797 | ||
| 796 | const device_type EEPROM_SERIAL_##_uppercase##_##_bits##BIT = &device_creator<eeprom_serial_##_lowercase##_##_bits##bit_device>; | |
| 798 | 797 | // standard 93CX6 class of 16-bit EEPROMs |
| 799 | 798 | DEFINE_SERIAL_EEPROM_DEVICE(93cxx, 93c06, 93C06, 16, 16, 6) |
| 800 | 799 | DEFINE_SERIAL_EEPROM_DEVICE(93cxx, 93c46, 93C46, 16, 64, 6) |
| r25360 | r25361 | |
|---|---|---|
| 87 | 87 | |
| 88 | 88 | // optional enable for streaming reads |
| 89 | 89 | #define MCFG_EEPROM_SERIAL_ENABLE_STREAMING() \ |
| 90 | eeprom_serial_base_device::static_enable_streaming(*device); \ | |
| 91 | ||
| 90 | eeprom_serial_base_device::static_enable_streaming(*device); | |
| 92 | 91 | // pass-throughs to the base class for setting default data |
| 93 | 92 | #define MCFG_EEPROM_SERIAL_DATA MCFG_EEPROM_DATA |
| 94 | 93 | #define MCFG_EEPROM_SERIAL_DEFAULT_VALUE MCFG_EEPROM_DEFAULT_VALUE |
| r25360 | r25361 | |
| 112 | 111 | // inline configuration helpers |
| 113 | 112 | static void static_set_address_bits(device_t &device, int addrbits); |
| 114 | 113 | static void static_enable_streaming(device_t &device); |
| 115 | ||
| 114 | ||
| 116 | 115 | protected: |
| 117 | 116 | // device-level overrides |
| 118 | 117 | virtual void device_start(); |
| 119 | 118 | virtual void device_reset(); |
| 120 | ||
| 119 | ||
| 121 | 120 | // read interfaces differ between implementations |
| 122 | ||
| 121 | ||
| 123 | 122 | // commands |
| 124 | 123 | enum eeprom_command |
| 125 | 124 | { |
| r25360 | r25361 | |
| 143 | 142 | STATE_WAIT_FOR_DATA, |
| 144 | 143 | STATE_WAIT_FOR_COMPLETION |
| 145 | 144 | }; |
| 146 | ||
| 145 | ||
| 147 | 146 | // events |
| 148 | 147 | enum eeprom_event |
| 149 | 148 | { |
| r25360 | r25361 | |
| 158 | 157 | void handle_event(eeprom_event event); |
| 159 | 158 | void execute_command(); |
| 160 | 159 | void execute_write_command(); |
| 161 | ||
| 160 | ||
| 162 | 161 | // subclass helpers |
| 163 | 162 | void base_cs_write(int state); |
| 164 | 163 | void base_clk_write(int state); |
| 165 | 164 | void base_di_write(int state); |
| 166 | 165 | int base_do_read(); |
| 167 | 166 | int base_ready_read(); |
| 168 | ||
| 167 | ||
| 169 | 168 | // subclass overrides |
| 170 | 169 | virtual void parse_command_and_address() = 0; |
| 171 | 170 | |
| 172 | 171 | // configuration state |
| 173 | UINT8 m_command_address_bits; // number of address bits in a command | |
| 174 | bool m_streaming_enabled; // true if streaming is enabled | |
| 172 | UINT8 m_command_address_bits; // number of address bits in a command | |
| 173 | bool m_streaming_enabled; // true if streaming is enabled | |
| 175 | 174 | |
| 176 | 175 | // runtime state |
| 177 | eeprom_state m_state; // current internal state | |
| 178 | UINT8 m_cs_state; // state of the CS line | |
| 179 | attotime m_last_cs_rising_edge_time; // time of the last CS rising edge | |
| 180 | UINT8 m_oe_state; // state of the OE line | |
| 181 | UINT8 m_clk_state; // state of the CLK line | |
| 182 | UINT8 m_di_state; // state of the DI line | |
| 183 | bool m_locked; // are we locked against writes? | |
| 184 | UINT32 m_bits_accum; // number of bits accumulated | |
| 185 | UINT32 m_command_address_accum; // accumulator of command+address bits | |
| 186 | eeprom_command m_command; // current command | |
| 187 | UINT32 m_address; // current address extracted from command | |
| 188 | UINT32 m_shift_register; // holds data coming in/going out | |
| 176 | eeprom_state m_state; // current internal state | |
| 177 | UINT8 m_cs_state; // state of the CS line | |
| 178 | attotime m_last_cs_rising_edge_time; // time of the last CS rising edge | |
| 179 | UINT8 m_oe_state; // state of the OE line | |
| 180 | UINT8 m_clk_state; // state of the CLK line | |
| 181 | UINT8 m_di_state; // state of the DI line | |
| 182 | bool m_locked; // are we locked against writes? | |
| 183 | UINT32 m_bits_accum; // number of bits accumulated | |
| 184 | UINT32 m_command_address_accum; // accumulator of command+address bits | |
| 185 | eeprom_command m_command; // current command | |
| 186 | UINT32 m_address; // current address extracted from command | |
| 187 | UINT32 m_shift_register; // holds data coming in/going out | |
| 189 | 188 | }; |
| 190 | 189 | |
| 191 | 190 | |
| r25360 | r25361 | |
| 200 | 199 | |
| 201 | 200 | public: |
| 202 | 201 | // read handlers |
| 203 | DECLARE_READ_LINE_MEMBER(do_read); | |
| 202 | DECLARE_READ_LINE_MEMBER(do_read); // combined DO+READY/BUSY | |
| 204 | 203 | |
| 205 | 204 | // write handlers |
| 206 | DECLARE_WRITE_LINE_MEMBER(cs_write); // CS signal (active high) | |
| 207 | DECLARE_WRITE_LINE_MEMBER(clk_write); // CLK signal (active high) | |
| 208 | DECLARE_WRITE_LINE_MEMBER(di_write); // DI | |
| 205 | DECLARE_WRITE_LINE_MEMBER(cs_write); // CS signal (active high) | |
| 206 | DECLARE_WRITE_LINE_MEMBER(clk_write); // CLK signal (active high) | |
| 207 | DECLARE_WRITE_LINE_MEMBER(di_write); // DI | |
| 209 | 208 | |
| 210 | 209 | protected: |
| 211 | 210 | // subclass overrides |
| r25360 | r25361 | |
| 223 | 222 | |
| 224 | 223 | public: |
| 225 | 224 | // read handlers |
| 226 | DECLARE_READ_LINE_MEMBER(do_read); // DO | |
| 227 | DECLARE_READ_LINE_MEMBER(ready_read); // READY/BUSY only | |
| 225 | DECLARE_READ_LINE_MEMBER(do_read); // DO | |
| 226 | DECLARE_READ_LINE_MEMBER(ready_read); // READY/BUSY only | |
| 228 | 227 | |
| 229 | 228 | // write handlers |
| 230 | DECLARE_WRITE_LINE_MEMBER(cs_write); // CS signal (active high) | |
| 231 | DECLARE_WRITE_LINE_MEMBER(clk_write); // CLK signal (active high) | |
| 232 | DECLARE_WRITE_LINE_MEMBER(di_write); // DI | |
| 229 | DECLARE_WRITE_LINE_MEMBER(cs_write); // CS signal (active high) | |
| 230 | DECLARE_WRITE_LINE_MEMBER(clk_write); // CLK signal (active high) | |
| 231 | DECLARE_WRITE_LINE_MEMBER(di_write); // DI | |
| 233 | 232 | |
| 234 | 233 | protected: |
| 235 | 234 | // subclass overrides |
| r25360 | r25361 | |
| 249 | 248 | public: \ |
| 250 | 249 | eeprom_serial_##_lowercase##_##_bits##bit_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); \ |
| 251 | 250 | }; \ |
| 252 | extern const device_type EEPROM_SERIAL_##_uppercase##_##_bits##BIT; \ | |
| 253 | ||
| 251 | extern const device_type EEPROM_SERIAL_##_uppercase##_##_bits##BIT; | |
| 254 | 252 | // standard 93CX6 class of 16-bit EEPROMs |
| 255 | 253 | DECLARE_SERIAL_EEPROM_DEVICE(93cxx, 93c06, 93C06, 16) |
| 256 | 254 | DECLARE_SERIAL_EEPROM_DEVICE(93cxx, 93c46, 93C46, 16) |
| r25360 | r25361 | |
|---|---|---|
| 37 | 37 | |
| 38 | 38 | cmos_40105_device::cmos_40105_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 39 | 39 | : device_t(mconfig, CMOS_40105, "40105", tag, owner, clock, "40105", __FILE__), |
| 40 | m_write_dir(*this), | |
| 41 | m_write_dor(*this) | |
| 40 | m_write_dir(*this), | |
| 41 | m_write_dor(*this) | |
| 42 | 42 | { |
| 43 | 43 | } |
| 44 | 44 |
| r25360 | r25361 | |
|---|---|---|
| 48 | 48 | |
| 49 | 49 | DECLARE_WRITE_LINE_MEMBER( si_w ); |
| 50 | 50 | DECLARE_WRITE_LINE_MEMBER( so_w ); |
| 51 | ||
| 51 | ||
| 52 | 52 | DECLARE_READ_LINE_MEMBER( dir_r ); |
| 53 | 53 | DECLARE_READ_LINE_MEMBER( dor_r ); |
| 54 | 54 |
| r25360 | r25361 | |
|---|---|---|
| 35 | 35 | |
| 36 | 36 | DECLARE_READ16_MEMBER( read ); |
| 37 | 37 | DECLARE_WRITE16_MEMBER( write ); |
| 38 | ||
| 38 | ||
| 39 | 39 | protected: |
| 40 | 40 | // device-level overrides |
| 41 | 41 | virtual void device_config_complete(); |
| 42 | 42 | virtual void device_start(); |
| 43 | 43 | virtual void device_reset(); |
| 44 | ||
| 44 | ||
| 45 | 45 | private: |
| 46 | 46 | // internal state |
| 47 | 47 | smc91c9x_irq_func m_irq_handler; |
| r25360 | r25361 | |
| 64 | 64 | /* counters */ |
| 65 | 65 | UINT32 m_sent; |
| 66 | 66 | UINT32 m_recd; |
| 67 | ||
| 67 | ||
| 68 | 68 | void update_ethernet_irq(); |
| 69 | 69 | void update_stats(); |
| 70 | 70 | void finish_enqueue(int param); |
| r25360 | r25361 | |
|---|---|---|
| 87 | 87 | m_completion_time(attotime::zero) |
| 88 | 88 | { |
| 89 | 89 | // a 2ms write time is too long for rfjetsa |
| 90 | m_operation_time[WRITE_TIME] = attotime::from_usec(1750); | |
| 91 | m_operation_time[WRITE_ALL_TIME] = attotime::from_usec(8000); | |
| 92 | m_operation_time[ERASE_TIME] = attotime::from_usec(1000); | |
| 93 | m_operation_time[ERASE_ALL_TIME] = attotime::from_usec(8000); | |
| 90 | m_operation_time[WRITE_TIME] = attotime::from_usec(1750); | |
| 91 | m_operation_time[WRITE_ALL_TIME] = attotime::from_usec(8000); | |
| 92 | m_operation_time[ERASE_TIME] = attotime::from_usec(1000); | |
| 93 | m_operation_time[ERASE_ALL_TIME] = attotime::from_usec(8000); | |
| 94 | 94 | } |
| 95 | 95 | |
| 96 | 96 | |
| r25360 | r25361 | |
| 195 | 195 | |
| 196 | 196 | //------------------------------------------------- |
| 197 | 197 | // write_all - write data at all addresses |
| 198 | // (assumes an erase has previously been | |
| 199 | // performed) | |
| 198 | // (assumes an erase has previously been | |
| 199 | // performed) | |
| 200 | 200 | //------------------------------------------------- |
| 201 | 201 | |
| 202 | 202 | void eeprom_base_device::write_all(UINT32 data) |
| r25360 | r25361 | |
| 308 | 308 | if (m_default_data.u8 != NULL) |
| 309 | 309 | { |
| 310 | 310 | mame_printf_verbose("Warning: Driver-specific EEPROM defaults are going away soon.\n"); |
| 311 | for (offs_t offs = 0; offs < m_default_data_size; offs++) | |
| 311 | for (offs_t offs = 0; offs < m_default_data_size; offs++) | |
| 312 | 312 | { |
| 313 | 313 | if (m_data_bits == 8) |
| 314 | 314 | m_addrspace[0]->write_byte(offs, m_default_data.u8[offs]); |
| r25360 | r25361 | |
| 385 | 385 | |
| 386 | 386 | |
| 387 | 387 | //------------------------------------------------- |
| 388 | // internal_write - write data at the given | |
| 389 | // address | |
| 388 | // internal_write - write data at the given | |
| 389 | // address | |
| 390 | 390 | //------------------------------------------------- |
| 391 | 391 | |
| 392 | 392 | void eeprom_base_device::internal_write(offs_t address, UINT32 data) |
| r25360 | r25361 | |
|---|---|---|
| 72 | 72 | |
| 73 | 73 | // ======================> eeprom_base_device |
| 74 | 74 | |
| 75 | class eeprom_base_device : | |
| 75 | class eeprom_base_device : public device_t, | |
| 76 | 76 | public device_memory_interface, |
| 77 | 77 | public device_nvram_interface |
| 78 | 78 | { |
| r25360 | r25361 | |
| 84 | 84 | // timing constants |
| 85 | 85 | enum timing_type |
| 86 | 86 | { |
| 87 | WRITE_TIME, // default = 2ms | |
| 88 | WRITE_ALL_TIME, // default = 8ms | |
| 89 | ERASE_TIME, // default = 1ms | |
| 90 | ERASE_ALL_TIME, // default = 8ms | |
| 87 | WRITE_TIME, // default = 2ms | |
| 88 | WRITE_ALL_TIME, // default = 8ms | |
| 89 | ERASE_TIME, // default = 1ms | |
| 90 | ERASE_ALL_TIME, // default = 8ms | |
| 91 | 91 | TIMING_COUNT |
| 92 | 92 | }; |
| 93 | 93 | |
| r25360 | r25361 | |
| 104 | 104 | void write_all(UINT32 data); |
| 105 | 105 | void erase(offs_t address); |
| 106 | 106 | void erase_all(); |
| 107 | ||
| 107 | ||
| 108 | 108 | // status |
| 109 | 109 | bool ready() const { return machine().time() >= m_completion_time; } |
| 110 | ||
| 110 | ||
| 111 | 111 | protected: |
| 112 | 112 | // device-level overrides |
| 113 | 113 | virtual void device_validity_check(validity_checker &valid) const; |
| r25360 | r25361 | |
| 127 | 127 | void internal_write(offs_t address, UINT32 data); |
| 128 | 128 | |
| 129 | 129 | // configuration state |
| 130 | UINT32 m_cells; | |
| 131 | UINT8 m_address_bits; | |
| 132 | UINT8 m_data_bits; | |
| 130 | UINT32 m_cells; | |
| 131 | UINT8 m_address_bits; | |
| 132 | UINT8 m_data_bits; | |
| 133 | 133 | address_space_config m_space_config; |
| 134 | 134 | generic_ptr m_default_data; |
| 135 | 135 | UINT32 m_default_data_size; |
| 136 | 136 | UINT32 m_default_value; |
| 137 | 137 | bool m_default_value_set; |
| 138 | attotime | |
| 138 | attotime m_operation_time[TIMING_COUNT]; | |
| 139 | 139 | |
| 140 | 140 | // live state |
| 141 | attotime | |
| 141 | attotime m_completion_time; | |
| 142 | 142 | }; |
| 143 | 143 | |
| 144 | 144 |
| r25360 | r25361 | |
|---|---|---|
| 52 | 52 | m_input_lines[1][1] = 0; |
| 53 | 53 | m_input_lines[1][2] = 0; |
| 54 | 54 | m_input_lines[1][3] = 0; |
| 55 | ||
| 55 | ||
| 56 | 56 | for (int i = 0; i < 2; i++) |
| 57 | 57 | m_enable[i] = 0; |
| 58 | ||
| 58 | ||
| 59 | 59 | for (int i = 0; i < 2; i++) |
| 60 | 60 | m_output[i] = 0; |
| 61 | ||
| 61 | ||
| 62 | 62 | for (int i = 0; i < 2; i++) |
| 63 | 63 | m_last_output[i] = 0; |
| 64 | 64 | } |
| r25360 | r25361 | |
| 75 | 75 | const ttl74153_config *intf = reinterpret_cast<const ttl74153_config *>(static_config()); |
| 76 | 76 | if (intf != NULL) |
| 77 | 77 | *static_cast<ttl74153_config *>(this) = *intf; |
| 78 | ||
| 78 | ||
| 79 | 79 | // or initialize to defaults if none provided |
| 80 | 80 | else |
| 81 | 81 | { |
| r25360 | r25361 | |
|---|---|---|
| 59 | 59 | void input_line_w(int section, int input_line, int data); |
| 60 | 60 | void enable_w(int section, int data); |
| 61 | 61 | int output_r(int section); |
| 62 | ||
| 62 | ||
| 63 | 63 | protected: |
| 64 | 64 | // device-level overrides |
| 65 | 65 | virtual void device_config_complete(); |
| 66 | 66 | virtual void device_start(); |
| 67 | 67 | virtual void device_reset(); |
| 68 | ||
| 68 | ||
| 69 | 69 | private: |
| 70 | 70 | // internal state |
| 71 | 71 |
| r25360 | r25361 | |
|---|---|---|
| 239 | 239 | m_identify_buffer[word] |= 0x100 << (m_sector_count & 7); |
| 240 | 240 | return true; |
| 241 | 241 | } |
| 242 | ||
| 242 | ||
| 243 | 243 | return false; |
| 244 | 244 | } |
| 245 | 245 |
| r25360 | r25361 | |
|---|---|---|
| 44 | 44 | Range from 100 to 0. (100 = 0dB; 50 = -6dB; 0 = -infinity) |
| 45 | 45 | This function is designed for use with MAME mixer_xxx() functions. */ |
| 46 | 46 | int gain_percent_r(int channel); |
| 47 | ||
| 47 | ||
| 48 | 48 | void gain_recalc(); |
| 49 | 49 | |
| 50 | 50 | protected: |
| r25360 | r25361 | |
| 52 | 52 | virtual void device_config_complete(); |
| 53 | 53 | virtual void device_start(); |
| 54 | 54 | virtual void device_reset(); |
| 55 | ||
| 55 | ||
| 56 | 56 | private: |
| 57 | 57 | // internal state |
| 58 | 58 | int m_gain[4]; /* gain index 0-63,64,65 */ |
| r25360 | r25361 | |
|---|---|---|
| 141 | 141 | if (m_slot[i]->dev() != NULL) |
| 142 | 142 | result &= m_slot[i]->dev()->read_cs0(space, offset, mem_mask); |
| 143 | 143 | |
| 144 | // | |
| 144 | // { static int last_status = -1; if (offset == 7 ) { if( result == last_status ) return last_status; last_status = result; } else last_status = -1; } | |
| 145 | 145 | |
| 146 | 146 | // printf( "read cs0 %04x %04x %04x\n", offset, result, mem_mask ); |
| 147 | 147 |
| r25360 | r25361 | |
|---|---|---|
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | |
| 3 | ||
| 3 | AICA-RTC sub-device | |
| 4 | 4 | |
| 5 | TODO: | |
| 6 | - move this inside AICA sound core once that'll get modernized | |
| 5 | TODO: | |
| 6 | - move this inside AICA sound core once that'll get modernized | |
| 7 | 7 | |
| 8 | 8 | ***************************************************************************/ |
| 9 | 9 |
| r25360 | r25361 | |
|---|---|---|
| 25 | 25 | // ======================> aicartc_device |
| 26 | 26 | |
| 27 | 27 | class aicartc_device : public device_t, |
| 28 | ||
| 28 | public device_rtc_interface | |
| 29 | 29 | { |
| 30 | 30 | public: |
| 31 | 31 | // construction/destruction |
| r25360 | r25361 | |
|---|---|---|
| 143 | 143 | save_pointer(NAME(m_work_ram), m_work_ram_size); |
| 144 | 144 | save_item(NAME(*m_bitmap)); |
| 145 | 145 | save_item(NAME(*m_collision_bitmap)); |
| 146 | ||
| 147 | ||
| 146 | ||
| 147 | ||
| 148 | 148 | m_channel = machine().sound().stream_alloc(*this, 0, 1, machine().sample_rate(), this); |
| 149 | 149 | save_item(NAME(m_size)); |
| 150 | 150 | save_item(NAME(m_pos)); |
| 151 | 151 | save_item(NAME(m_level)); |
| 152 | ||
| 152 | ||
| 153 | 153 | for (int i = 0; i < 1; i++) |
| 154 | 154 | save_item(NAME(m_reg[i]), i); |
| 155 | 155 | } |
| r25360 | r25361 | |
|---|---|---|
| 47 | 47 | bitmap_ind16 &update( const rectangle &cliprect ); |
| 48 | 48 | DECLARE_WRITE8_MEMBER( work_ram_w ); |
| 49 | 49 | DECLARE_READ8_MEMBER( work_ram_r ); |
| 50 | ||
| 50 | ||
| 51 | 51 | void soundport_w (int mode, int data); |
| 52 | 52 | |
| 53 | 53 | protected: |
| 54 | 54 | // device-level overrides |
| 55 | 55 | virtual void device_config_complete(); |
| 56 | 56 | virtual void device_start(); |
| 57 | ||
| 57 | ||
| 58 | 58 | // sound stream update overrides |
| 59 | 59 | virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); |
| 60 | 60 | |
| r25360 | r25361 | |
| 63 | 63 | UINT8 *m_work_ram; |
| 64 | 64 | bitmap_ind16 *m_bitmap; |
| 65 | 65 | bitmap_ind16 *m_collision_bitmap; |
| 66 | ||
| 66 | ||
| 67 | 67 | sound_stream *m_channel; |
| 68 | 68 | UINT8 m_reg[1]; |
| 69 | 69 | int m_size; |
| 70 | 70 | int m_pos; |
| 71 | 71 | unsigned m_level; |
| 72 | ||
| 72 | ||
| 73 | 73 | int check_collision( int spriteno1, int spriteno2, const rectangle &cliprect ); |
| 74 | 74 | }; |
| 75 | 75 |
| r25360 | r25361 | |
|---|---|---|
| 19 | 19 | //************************************************************************** |
| 20 | 20 | |
| 21 | 21 | #define MCFG_TTL74181_ADD(_tag) \ |
| 22 | MCFG_DEVICE_ADD(_tag, TTL74181, 0) | |
| 22 | MCFG_DEVICE_ADD(_tag, TTL74181, 0) | |
| 23 | 23 | |
| 24 | ||
| 25 | 24 | //************************************************************************** |
| 26 | 25 | // TYPE DEFINITIONS |
| 27 | 26 | //************************************************************************** |
| r25360 | r25361 | |
|---|---|---|
| 37 | 37 | |
| 38 | 38 | **************************************************************************** |
| 39 | 39 | |
| 40 | Parallel EEPROMs are generally simpler than serial EEPROMs, though | |
| 41 | they require more pins to provide the full set of address and data | |
| 42 | lines necessary. They also require more pins the larger the EEPROM | |
| 43 | is, whereas serial EEPROMs all share the same pinout regardless of | |
| 44 | size. | |
| 45 | ||
| 46 | At a basic level, there are 5 sets of signals involved: | |
| 47 | ||
| 48 | * /CE = chip enable | |
| 49 | * /OE = output enable | |
| 50 | * /WE = write enable | |
| 51 | * D0-Dn = data lines | |
| 52 | * A0-An = address lines | |
| 40 | Parallel EEPROMs are generally simpler than serial EEPROMs, though | |
| 41 | they require more pins to provide the full set of address and data | |
| 42 | lines necessary. They also require more pins the larger the EEPROM | |
| 43 | is, whereas serial EEPROMs all share the same pinout regardless of | |
| 44 | size. | |
| 53 | 45 | |
| 54 | To access the chip, the various enable states must be asserted or | |
| 55 | cleared. Note that these are generally active-low, so asserted means | |
| 56 | pulled to GND, and cleared means pulled to Vcc: | |
| 57 | ||
| 58 | /CE /OE /WE Action | |
| 59 | ASSERT ASSERT CLEAR Read (D0-Dn contain output data) | |
| 60 | ASSERT CLEAR ASSERT Write/Erase (D0-Dn are input data) | |
| 61 | ||
| 62 | Erase is performed by doing a write with D0-Dn all set to 1. | |
| 63 | ||
| 64 | In general, it is slow to write or erase (9ms is quoted in the 2816A | |
| 65 | datasheet, for example), and the /WE must be held low for the entire | |
| 66 | write/erase duration in order to guarantee the data is written. | |
| 46 | At a basic level, there are 5 sets of signals involved: | |
| 67 | 47 | |
| 48 | * /CE = chip enable | |
| 49 | * /OE = output enable | |
| 50 | * /WE = write enable | |
| 51 | * D0-Dn = data lines | |
| 52 | * A0-An = address lines | |
| 53 | ||
| 54 | To access the chip, the various enable states must be asserted or | |
| 55 | cleared. Note that these are generally active-low, so asserted means | |
| 56 | pulled to GND, and cleared means pulled to Vcc: | |
| 57 | ||
| 58 | /CE /OE /WE Action | |
| 59 | ASSERT ASSERT CLEAR Read (D0-Dn contain output data) | |
| 60 | ASSERT CLEAR ASSERT Write/Erase (D0-Dn are input data) | |
| 61 | ||
| 62 | Erase is performed by doing a write with D0-Dn all set to 1. | |
| 63 | ||
| 64 | In general, it is slow to write or erase (9ms is quoted in the 2816A | |
| 65 | datasheet, for example), and the /WE must be held low for the entire | |
| 66 | write/erase duration in order to guarantee the data is written. | |
| 67 | ||
| 68 | 68 | ***************************************************************************/ |
| 69 | 69 | |
| 70 | 70 | #include "emu.h" |
| r25360 | r25361 | |
| 150 | 150 | { \ |
| 151 | 151 | static_set_size(*this, _cells, _bits); \ |
| 152 | 152 | }; \ |
| 153 | const device_type EEPROM_PARALLEL_##_uppercase = &device_creator<eeprom_parallel_##_lowercase##_device>; \ | |
| 154 | ||
| 153 | const device_type EEPROM_PARALLEL_##_uppercase = &device_creator<eeprom_parallel_##_lowercase##_device>; | |
| 155 | 154 | // standard 28XX class of 8-bit EEPROMs |
| 156 | 155 | DEFINE_PARALLEL_EEPROM_DEVICE(28xx, 2804, 2804, 8, 512) |
| 157 | 156 | DEFINE_PARALLEL_EEPROM_DEVICE(28xx, 2816, 2816, 8, 2048) |
| r25360 | r25361 | |
|---|---|---|
| 120 | 120 | public: \ |
| 121 | 121 | eeprom_parallel_##_lowercase##_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); \ |
| 122 | 122 | }; \ |
| 123 | extern const device_type EEPROM_PARALLEL_##_uppercase; \ | |
| 124 | ||
| 123 | extern const device_type EEPROM_PARALLEL_##_uppercase; | |
| 125 | 124 | // standard 28XX class of 8-bit EEPROMs |
| 126 | 125 | DECLARE_PARALLEL_EEPROM_DEVICE(28xx, 2804, 2804) |
| 127 | 126 | DECLARE_PARALLEL_EEPROM_DEVICE(28xx, 2816, 2816) |
| r25360 | r25361 | |
|---|---|---|
| 70 | 70 | const ttl74148_config *intf = reinterpret_cast<const ttl74148_config *>(static_config()); |
| 71 | 71 | if (intf != NULL) |
| 72 | 72 | *static_cast<ttl74148_config *>(this) = *intf; |
| 73 | ||
| 73 | ||
| 74 | 74 | // or initialize to defaults if none provided |
| 75 | 75 | else |
| 76 | 76 | { |
| 77 | 77 | } |
| 78 | ||
| 78 | ||
| 79 | 79 | } |
| 80 | 80 | |
| 81 | 81 | //------------------------------------------------- |
| r25360 | r25361 | |
| 100 | 100 | |
| 101 | 101 | void ttl74148_device::device_reset() |
| 102 | 102 | { |
| 103 | ||
| 104 | 103 | m_enable_input = 1; |
| 105 | 104 | m_input_lines[0] = 1; |
| 106 | 105 | m_input_lines[1] = 1; |
| r25360 | r25361 | |
|---|---|---|
| 37 | 37 | |
| 38 | 38 | **************************************************************************** |
| 39 | 39 | |
| 40 | A memory array in this case is an array of 8, 16, or 32-bit data | |
| 41 | arranged logically. | |
| 42 | ||
| 43 | A memory array is stored in "natural" order, i.e., read/writes to it | |
| 44 | are done via AM_RAM, or standard COMBINE_DATA, even if the width of | |
| 45 | the CPU is different from the array width. | |
| 46 | ||
| 47 | The read_entry/write_entry functions serve to read/write entries of | |
| 48 | the configured size regardless of the underlay width of the CPU's | |
| 49 | memory system. | |
| 40 | A memory array in this case is an array of 8, 16, or 32-bit data | |
| 41 | arranged logically. | |
| 50 | 42 | |
| 43 | A memory array is stored in "natural" order, i.e., read/writes to it | |
| 44 | are done via AM_RAM, or standard COMBINE_DATA, even if the width of | |
| 45 | the CPU is different from the array width. | |
| 46 | ||
| 47 | The read_entry/write_entry functions serve to read/write entries of | |
| 48 | the configured size regardless of the underlay width of the CPU's | |
| 49 | memory system. | |
| 50 | ||
| 51 | 51 | ***************************************************************************/ |
| 52 | 52 | |
| 53 | 53 | #pragma once |
| r25360 | r25361 | |
|---|---|---|
| 104 | 104 | if (screen == NULL) |
| 105 | 105 | mame_printf_error("Screen '%s' not found, explicitly set for device '%s'", m_screen_tag, device().tag()); |
| 106 | 106 | } |
| 107 | ||
| 107 | ||
| 108 | 108 | // otherwise, look for a single match |
| 109 | 109 | else |
| 110 | 110 | { |
| r25360 | r25361 | |
| 138 | 138 | if (m_screen == NULL) |
| 139 | 139 | throw emu_fatalerror("Screen '%s' not found, explicitly set for device '%s'", m_screen_tag, device().tag()); |
| 140 | 140 | } |
| 141 | ||
| 141 | ||
| 142 | 142 | // otherwise, look for a single match |
| 143 | 143 | else |
| 144 | 144 | { |
| r25360 | r25361 | |
|---|---|---|
| 119 | 119 | |
| 120 | 120 | // getters |
| 121 | 121 | bool enabled() const |
| 122 | { | |
| 122 | { | |
| 123 | 123 | #ifndef MAME_DEBUG_FAST |
| 124 | 124 | return m_filoptr != NULL; |
| 125 | 125 | #else |
| r25360 | r25361 | |
|---|---|---|
| 81 | 81 | // optional operation overrides |
| 82 | 82 | virtual void interface_validity_check(validity_checker &valid) const; |
| 83 | 83 | virtual void interface_pre_start(); |
| 84 | ||
| 84 | ||
| 85 | 85 | // configuration state |
| 86 | bool m_screen_required; // is a screen required? | |
| 87 | const char * m_screen_tag; // configured tag for the target screen | |
| 86 | bool m_screen_required; // is a screen required? | |
| 87 | const char * m_screen_tag; // configured tag for the target screen | |
| 88 | 88 | |
| 89 | 89 | // internal state |
| 90 | screen_device * | |
| 90 | screen_device * m_screen; // pointer to the screen device | |
| 91 | 91 | }; |
| 92 | 92 | |
| 93 | 93 | // iterator |
| r25360 | r25361 | |
|---|---|---|
| 619 | 619 | |
| 620 | 620 | // sort them by tag |
| 621 | 621 | qsort(&device_list[0], device_list.count(), sizeof(device_list[0]), compare_devices); |
| 622 | ||
| 622 | ||
| 623 | 623 | // dump the results |
| 624 | 624 | for (int index = 0; index < device_list.count(); index++) |
| 625 | 625 | { |
| r25360 | r25361 | |
| 629 | 629 | const char *tag = device->tag(); |
| 630 | 630 | if (*tag == ':') |
| 631 | 631 | tag++; |
| 632 | ||
| 632 | ||
| 633 | 633 | // determine the depth |
| 634 | 634 | int depth = 1; |
| 635 | 635 | if (*tag == 0) |
| r25360 | r25361 | |
|---|---|---|
| 80 | 80 | public: |
| 81 | 81 | // construction/destruction |
| 82 | 82 | breakpoint(device_debug* debugInterface, |
| 83 | symbol_table &symbols, | |
| 84 | int index, | |
| 85 | offs_t address, | |
| 86 | const char *condition = NULL, | |
| 87 | const char *action = NULL); | |
| 83 | symbol_table &symbols, | |
| 84 | int index, | |
| 85 | offs_t address, | |
| 86 | const char *condition = NULL, | |
| 87 | const char *action = NULL); | |
| 88 | 88 | |
| 89 | 89 | // getters |
| 90 | 90 | const device_debug *debugInterface() const { return m_debugInterface; } |
| r25360 | r25361 | |
| 119 | 119 | public: |
| 120 | 120 | // construction/destruction |
| 121 | 121 | watchpoint(device_debug* debugInterface, |
| 122 | symbol_table &symbols, | |
| 123 | int index, | |
| 124 | address_space &space, | |
| 125 | int type, | |
| 126 | offs_t address, | |
| 127 | offs_t length, | |
| 128 | const char *condition = NULL, | |
| 129 | const char *action = NULL); | |
| 122 | symbol_table &symbols, | |
| 123 | int index, | |
| 124 | address_space &space, | |
| 125 | int type, | |
| 126 | offs_t address, | |
| 127 | offs_t length, | |
| 128 | const char *condition = NULL, | |
| 129 | const char *action = NULL); | |
| 130 | 130 | |
| 131 | 131 | // getters |
| 132 | 132 | const device_debug *debugInterface() const { return m_debugInterface; } |
| r25360 | r25361 | |
|---|---|---|
| 1495 | 1495 | { |
| 1496 | 1496 | static const char *const types[] = { "unkn ", "read ", "write", "r/w " }; |
| 1497 | 1497 | |
| 1498 | debug_console_printf(machine, "Device '%s' %s space watchpoints:\n", device->tag(), | |
| 1499 | device->debug()->watchpoint_first(spacenum)->space().name()); | |
| 1498 | debug_console_printf(machine, "Device '%s' %s space watchpoints:\n", device->tag(), | |
| 1499 | device->debug()->watchpoint_first(spacenum)->space().name()); | |
| 1500 | 1500 | |
| 1501 | 1501 | /* loop over the watchpoints */ |
| 1502 | 1502 | for (device_debug::watchpoint *wp = device->debug()->watchpoint_first(spacenum); wp != NULL; wp = wp->next()) |
| r25360 | r25361 | |
|---|---|---|
| 496 | 496 | pad_astring_to_length(buffer, tableBreaks[2]); |
| 497 | 497 | buffer.catprintf("%s", wp->space().name()); |
| 498 | 498 | pad_astring_to_length(buffer, tableBreaks[3]); |
| 499 | buffer.catprintf("%s-%s", | |
| 500 | core_i64_hex_format(wp->space().byte_to_address(wp->address()), wp->space().addrchars()), | |
| 501 | core_i64_hex_format(wp->space().byte_to_address_end(wp->address() + wp->length()) - 1, wp->space().addrchars())); | |
| 499 | buffer.catprintf("%s-%s", | |
| 500 | core_i64_hex_format(wp->space().byte_to_address(wp->address()), wp->space().addrchars()), | |
| 501 | core_i64_hex_format(wp->space().byte_to_address_end(wp->address() + wp->length()) - 1, wp->space().addrchars())); | |
| 502 | 502 | pad_astring_to_length(buffer, tableBreaks[4]); |
| 503 | 503 | buffer.catprintf("%s", types[wp->type() & 3]); |
| 504 | 504 | pad_astring_to_length(buffer, tableBreaks[5]); |
| r25360 | r25361 | |
|---|---|---|
| 3279 | 3279 | //------------------------------------------------- |
| 3280 | 3280 | |
| 3281 | 3281 | device_debug::breakpoint::breakpoint(device_debug* debugInterface, |
| 3282 | symbol_table &symbols, | |
| 3283 | int index, | |
| 3284 | offs_t address, | |
| 3285 | const char *condition, | |
| 3286 | const char *action) | |
| 3282 | symbol_table &symbols, | |
| 3283 | int index, | |
| 3284 | offs_t address, | |
| 3285 | const char *condition, | |
| 3286 | const char *action) | |
| 3287 | 3287 | : m_debugInterface(debugInterface), |
| 3288 | m_next(NULL), | |
| 3289 | m_index(index), | |
| 3290 | m_enabled(true), | |
| 3291 | m_address(address), | |
| 3292 | m_condition(&symbols, (condition != NULL) ? condition : "1"), | |
| 3293 | m_action((action != NULL) ? action : "") | |
| 3288 | m_next(NULL), | |
| 3289 | m_index(index), | |
| 3290 | m_enabled(true), | |
| 3291 | m_address(address), | |
| 3292 | m_condition(&symbols, (condition != NULL) ? condition : "1"), | |
| 3293 | m_action((action != NULL) ? action : "") | |
| 3294 | 3294 | { |
| 3295 | 3295 | } |
| 3296 | 3296 | |
| r25360 | r25361 | |
| 3335 | 3335 | // watchpoint - constructor |
| 3336 | 3336 | //------------------------------------------------- |
| 3337 | 3337 | |
| 3338 | device_debug::watchpoint::watchpoint(device_debug* debugInterface, | |
| 3339 | symbol_table &symbols, | |
| 3340 | int index, | |
| 3341 | address_space &space, | |
| 3342 | int type, | |
| 3343 | offs_t address, | |
| 3344 | offs_t length, | |
| 3345 | const char *condition, | |
| 3346 | const char *action) | |
| 3338 | device_debug::watchpoint::watchpoint(device_debug* debugInterface, | |
| 3339 | symbol_table &symbols, | |
| 3340 | int index, | |
| 3341 | address_space &space, | |
| 3342 | int type, | |
| 3343 | offs_t address, | |
| 3344 | offs_t length, | |
| 3345 | const char *condition, | |
| 3346 | const char *action) | |
| 3347 | 3347 | : m_debugInterface(debugInterface), |
| 3348 | m_next(NULL), | |
| 3349 | m_space(space), | |
| 3350 | m_index(index), | |
| 3351 | m_enabled(true), | |
| 3352 | m_type(type), | |
| 3353 | m_address(space.address_to_byte(address) & space.bytemask()), | |
| 3354 | m_length(space.address_to_byte(length)), | |
| 3355 | m_condition(&symbols, (condition != NULL) ? condition : "1"), | |
| 3356 | m_action((action != NULL) ? action : "") | |
| 3348 | m_next(NULL), | |
| 3349 | m_space(space), | |
| 3350 | m_index(index), | |
| 3351 | m_enabled(true), | |
| 3352 | m_type(type), | |
| 3353 | m_address(space.address_to_byte(address) & space.bytemask()), | |
| 3354 | m_length(space.address_to_byte(length)), | |
| 3355 | m_condition(&symbols, (condition != NULL) ? condition : "1"), | |
| 3356 | m_action((action != NULL) ? action : "") | |
| 3357 | 3357 | { |
| 3358 | 3358 | } |
| 3359 | 3359 |
| r25360 | r25361 | |
|---|---|---|
| 703 | 703 | const pic16c5x_device::pic16c5x_opcode pic16c5x_device::s_opcode_main[256]= |
| 704 | 704 | { |
| 705 | 705 | /*00*/ {1, &pic16c5x_device::nop },{0, &pic16c5x_device::illegal },{1, &pic16c5x_device::movwf },{1, &pic16c5x_device::movwf }, |
| 706 | ||
| 706 | {1, &pic16c5x_device::clrw },{0, &pic16c5x_device::illegal },{1, &pic16c5x_device::clrf },{1, &pic16c5x_device::clrf }, | |
| 707 | 707 | /*08*/ {1, &pic16c5x_device::subwf },{1, &pic16c5x_device::subwf },{1, &pic16c5x_device::subwf },{1, &pic16c5x_device::subwf }, |
| 708 | ||
| 708 | {1, &pic16c5x_device::decf },{1, &pic16c5x_device::decf },{1, &pic16c5x_device::decf },{1, &pic16c5x_device::decf }, | |
| 709 | 709 | /*10*/ {1, &pic16c5x_device::iorwf },{1, &pic16c5x_device::iorwf },{1, &pic16c5x_device::iorwf },{1, &pic16c5x_device::iorwf }, |
| 710 | ||
| 710 | {1, &pic16c5x_device::andwf },{1, &pic16c5x_device::andwf },{1, &pic16c5x_device::andwf },{1, &pic16c5x_device::andwf }, | |
| 711 | 711 | /*18*/ {1, &pic16c5x_device::xorwf },{1, &pic16c5x_device::xorwf },{1, &pic16c5x_device::xorwf },{1, &pic16c5x_device::xorwf }, |
| 712 | ||
| 712 | {1, &pic16c5x_device::addwf },{1, &pic16c5x_device::addwf },{1, &pic16c5x_device::addwf },{1, &pic16c5x_device::addwf }, | |
| 713 | 713 | /*20*/ {1, &pic16c5x_device::movf },{1, &pic16c5x_device::movf },{1, &pic16c5x_device::movf },{1, &pic16c5x_device::movf }, |
| 714 | ||
| 714 | {1, &pic16c5x_device::comf },{1, &pic16c5x_device::comf },{1, &pic16c5x_device::comf },{1, &pic16c5x_device::comf }, | |
| 715 | 715 | /*28*/ {1, &pic16c5x_device::incf },{1, &pic16c5x_device::incf },{1, &pic16c5x_device::incf },{1, &pic16c5x_device::incf }, |
| 716 | ||
| 716 | {1, &pic16c5x_device::decfsz },{1, &pic16c5x_device::decfsz },{1, &pic16c5x_device::decfsz },{1, &pic16c5x_device::decfsz }, | |
| 717 | 717 | /*30*/ {1, &pic16c5x_device::rrf },{1, &pic16c5x_device::rrf },{1, &pic16c5x_device::rrf },{1, &pic16c5x_device::rrf }, |
| 718 | ||
| 718 | {1, &pic16c5x_device::rlf },{1, &pic16c5x_device::rlf },{1, &pic16c5x_device::rlf },{1, &pic16c5x_device::rlf }, | |
| 719 | 719 | /*38*/ {1, &pic16c5x_device::swapf },{1, &pic16c5x_device::swapf },{1, &pic16c5x_device::swapf },{1, &pic16c5x_device::swapf }, |
| 720 | ||
| 720 | {1, &pic16c5x_device::incfsz },{1, &pic16c5x_device::incfsz },{1, &pic16c5x_device::incfsz },{1, &pic16c5x_device::incfsz }, | |
| 721 | 721 | /*40*/ {1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf }, |
| 722 | ||
| 722 | {1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf }, | |
| 723 | 723 | /*48*/ {1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf }, |
| 724 | ||
| 724 | {1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf }, | |
| 725 | 725 | /*50*/ {1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf }, |
| 726 | ||
| 726 | {1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf }, | |
| 727 | 727 | /*58*/ {1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf }, |
| 728 | ||
| 728 | {1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf }, | |
| 729 | 729 | /*60*/ {1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc }, |
| 730 | ||
| 730 | {1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc }, | |
| 731 | 731 | /*68*/ {1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc }, |
| 732 | ||
| 732 | {1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc }, | |
| 733 | 733 | /*70*/ {1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss }, |
| 734 | ||
| 734 | {1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss }, | |
| 735 | 735 | /*78*/ {1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss }, |
| 736 | ||
| 736 | {1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss }, | |
| 737 | 737 | /*80*/ {2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw }, |
| 738 | ||
| 738 | {2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw }, | |
| 739 | 739 | /*88*/ {2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw }, |
| 740 | ||
| 740 | {2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw }, | |
| 741 | 741 | /*90*/ {2, &pic16c5x_device::call },{2, &pic16c5x_device::call },{2, &pic16c5x_device::call },{2, &pic16c5x_device::call }, |
| 742 | ||
| 742 | {2, &pic16c5x_device::call },{2, &pic16c5x_device::call },{2, &pic16c5x_device::call },{2, &pic16c5x_device::call }, | |
| 743 | 743 | /*98*/ {2, &pic16c5x_device::call },{2, &pic16c5x_device::call },{2, &pic16c5x_device::call },{2, &pic16c5x_device::call }, |
| 744 | ||
| 744 | {2, &pic16c5x_device::call },{2, &pic16c5x_device::call },{2, &pic16c5x_device::call },{2, &pic16c5x_device::call }, | |
| 745 | 745 | /*A0*/ {2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op }, |
| 746 | ||
| 746 | {2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op }, | |
| 747 | 747 | /*A8*/ {2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op }, |
| 748 | ||
| 748 | {2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op }, | |
| 749 | 749 | /*B0*/ {2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op }, |
| 750 | ||
| 750 | {2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op }, | |
| 751 | 751 | /*B8*/ {2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op }, |
| 752 | ||
| 752 | {2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op }, | |
| 753 | 753 | /*C0*/ {1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw }, |
| 754 | ||
| 754 | {1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw }, | |
| 755 | 755 | /*C8*/ {1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw }, |
| 756 | ||
| 756 | {1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw }, | |
| 757 | 757 | /*D0*/ {1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw }, |
| 758 | ||
| 758 | {1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw }, | |
| 759 | 759 | /*D8*/ {1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw }, |
| 760 | ||
| 760 | {1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw }, | |
| 761 | 761 | /*E0*/ {1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw }, |
| 762 | ||
| 762 | {1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw }, | |
| 763 | 763 | /*E8*/ {1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw }, |
| 764 | ||
| 764 | {1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw }, | |
| 765 | 765 | /*F0*/ {1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw }, |
| 766 | ||
| 766 | {1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw }, | |
| 767 | 767 | /*F8*/ {1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw }, |
| 768 | ||
| 768 | {1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw } | |
| 769 | 769 | }; |
| 770 | 770 | |
| 771 | 771 | |
| 772 | 772 | const pic16c5x_device::pic16c5x_opcode pic16c5x_device::s_opcode_00x[16]= |
| 773 | 773 | { |
| 774 | 774 | /*00*/ {1, &pic16c5x_device::nop },{0, &pic16c5x_device::illegal },{1, &pic16c5x_device::option },{1, &pic16c5x_device::sleepic }, |
| 775 | ||
| 775 | {1, &pic16c5x_device::clrwdt },{1, &pic16c5x_device::tris },{1, &pic16c5x_device::tris },{1, &pic16c5x_device::tris }, | |
| 776 | 776 | /*08*/ {0, &pic16c5x_device::illegal },{0, &pic16c5x_device::illegal },{0, &pic16c5x_device::illegal },{0, &pic16c5x_device::illegal }, |
| 777 | ||
| 777 | {0, &pic16c5x_device::illegal },{0, &pic16c5x_device::illegal },{0, &pic16c5x_device::illegal },{0, &pic16c5x_device::illegal } | |
| 778 | 778 | }; |
| 779 | 779 | |
| 780 | 780 | |
| r25360 | r25361 | |
| 1102 | 1102 | |
| 1103 | 1103 | } while (m_icount > 0); |
| 1104 | 1104 | } |
| 1105 |
| r25360 | r25361 | |
|---|---|---|
| 1284 | 1284 | update_interrupt_state(); |
| 1285 | 1285 | } |
| 1286 | 1286 | |
| 1287 | // dma->finish_timer->adjust(attotime::from_hz(clock()/8), 0); | |
| 1288 | // dma->drq_delay = true; | |
| 1287 | // dma->finish_timer->adjust(attotime::from_hz(clock()/8), 0); | |
| 1288 | // dma->drq_delay = true; | |
| 1289 | 1289 | } |
| 1290 | 1290 | |
| 1291 | 1291 | READ16_MEMBER(i80186_cpu_device::internal_port_r) |
| r25360 | r25361 | |
|---|---|---|
| 1956 | 1956 | throw TRAP(trap, 0); |
| 1957 | 1957 | } |
| 1958 | 1958 | } |
| 1959 |
| r25360 | r25361 | |
|---|---|---|
| 7 | 7 | extern const device_type I80286; |
| 8 | 8 | |
| 9 | 9 | enum |
| 10 | { | |
| 10 | { // same order as I8086 registers | |
| 11 | 11 | I286_PC = 0, |
| 12 | 12 | |
| 13 | 13 | I286_IP, |
| r25360 | r25361 | |
|---|---|---|
| 416 | 416 | FLAGS & 0x0008 ? 'I':'.', |
| 417 | 417 | FLAGS & 0x0004 ? 'N':'.', |
| 418 | 418 | FLAGS & 0x0002 ? 'C':'.', |
| 419 | FLAGS & 0x0001 ? 'Z':'.'); | |
| 419 | FLAGS & 0x0001 ? 'Z':'.'); | |
| 420 | 420 | break; |
| 421 | 421 | } |
| 422 | 422 | } |
| r25360 | r25361 | |
| 1447 | 1447 | extern CPU_DISASSEMBLE( jaguardsp ); |
| 1448 | 1448 | return CPU_DISASSEMBLE_NAME(jaguardsp)(this, buffer, pc, oprom, opram, options); |
| 1449 | 1449 | } |
| 1450 |
| r25360 | r25361 | |
|---|---|---|
| 1842 | 1842 | } |
| 1843 | 1843 | |
| 1844 | 1844 | const device_type TMS34020 = &legacy_device_creator<tms34020_device>; |
| 1845 |
| r25360 | r25361 | |
|---|---|---|
| 210 | 210 | public: |
| 211 | 211 | tms34010_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock); |
| 212 | 212 | tms34010_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, cpu_get_info_func get_info); |
| 213 | ||
| 213 | ||
| 214 | 214 | UINT32 tms340x0_ind16(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); |
| 215 | 215 | UINT32 tms340x0_rgb32(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); |
| 216 | }; | |
| 216 | }; | |
| 217 | 217 | |
| 218 | 218 | extern const device_type TMS34010; |
| 219 | 219 |
| r25360 | r25361 | |
|---|---|---|
| 158 | 158 | class mb8841_cpu_device : public mb88_cpu_device |
| 159 | 159 | { |
| 160 | 160 | public: |
| 161 | // construction/destruction | |
| 162 | mb8841_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); | |
| 161 | // construction/destruction | |
| 162 | mb8841_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); | |
| 163 | 163 | }; |
| 164 | 164 | |
| 165 | 165 | |
| 166 | 166 | class mb8842_cpu_device : public mb88_cpu_device |
| 167 | 167 | { |
| 168 | 168 | public: |
| 169 | // construction/destruction | |
| 170 | mb8842_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); | |
| 169 | // construction/destruction | |
| 170 | mb8842_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); | |
| 171 | 171 | }; |
| 172 | 172 | |
| 173 | 173 | |
| 174 | 174 | class mb8843_cpu_device : public mb88_cpu_device |
| 175 | 175 | { |
| 176 | 176 | public: |
| 177 | // construction/destruction | |
| 178 | mb8843_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); | |
| 177 | // construction/destruction | |
| 178 | mb8843_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); | |
| 179 | 179 | }; |
| 180 | 180 | |
| 181 | 181 | |
| 182 | 182 | class mb8844_cpu_device : public mb88_cpu_device |
| 183 | 183 | { |
| 184 | 184 | public: |
| 185 | // construction/destruction | |
| 186 | mb8844_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); | |
| 185 | // construction/destruction | |
| 186 | mb8844_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); | |
| 187 | 187 | }; |
| 188 | 188 | |
| 189 | 189 |
| r25360 | r25361 | |
|---|---|---|
| 114 | 114 | |
| 115 | 115 | |
| 116 | 116 | mb8841_cpu_device::mb8841_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 117 | ||
| 117 | : mb88_cpu_device(mconfig, MB8841, "MB8841", tag, owner, clock, "mb8841", __FILE__, 11, 7) | |
| 118 | 118 | { |
| 119 | 119 | } |
| 120 | 120 | |
| 121 | 121 | |
| 122 | 122 | mb8842_cpu_device::mb8842_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 123 | ||
| 123 | : mb88_cpu_device(mconfig, MB8842, "MB8842", tag, owner, clock, "mb8842", __FILE__, 11, 7) | |
| 124 | 124 | { |
| 125 | 125 | } |
| 126 | 126 | |
| 127 | 127 | |
| 128 | 128 | mb8843_cpu_device::mb8843_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 129 | ||
| 129 | : mb88_cpu_device(mconfig, MB8843, "MB8843", tag, owner, clock, "mb8843", __FILE__, 10, 6) | |
| 130 | 130 | { |
| 131 | 131 | } |
| 132 | 132 | |
| 133 | 133 | |
| 134 | 134 | mb8844_cpu_device::mb8844_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 135 | ||
| 135 | : mb88_cpu_device(mconfig, MB8844, "MB8844", tag, owner, clock, "mb8844", __FILE__, 10, 6) | |
| 136 | 136 | { |
| 137 | 137 | } |
| 138 | 138 | |
| r25360 | r25361 | |
| 946 | 946 | update_pio(oc); |
| 947 | 947 | } |
| 948 | 948 | } |
| 949 |
| r25360 | r25361 | |
|---|---|---|
| 2168 | 2168 | } |
| 2169 | 2169 | m_check_irqs = 1; |
| 2170 | 2170 | } |
| 2171 |
| r25360 | r25361 | |
|---|---|---|
| 6167 | 6167 | } |
| 6168 | 6168 | |
| 6169 | 6169 | DEFINE_LEGACY_CPU_DEVICE(RSP_DRC, rsp_drc); |
| 6170 |
| r25360 | r25361 | |
|---|---|---|
| 111 | 111 | |
| 112 | 112 | |
| 113 | 113 | cquestlin_cpu_device::cquestlin_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 114 | : cpu_device(mconfig, CQUESTLIN, "Cube Quest Line CPU", tag, owner, clock, "cquestlin", __FILE__) | |
| 115 | , m_program_config("program", ENDIANNESS_BIG, 64, 8, -3) | |
| 114 | : cpu_device(mconfig, CQUESTLIN, "Cube Quest Line CPU", tag, owner, clock, "cquestlin", __FILE__) | |
| 115 | , m_program_config("program", ENDIANNESS_BIG, 64, 8, -3) | |
| 116 | 116 | , m_linedata_r(*this) |
| 117 | 117 | , m_flags(0) |
| 118 | 118 | , m_curpc(0) |
| r25360 | r25361 | |
| 358 | 358 | { |
| 359 | 359 | case STATE_GENFLAGS: |
| 360 | 360 | string.printf( "%c%c%c", m_cflag ? 'C' : '.', |
| 361 | m_vflag ? 'V' : '.', | |
| 362 | m_f ? '.' : 'Z'); | |
| 361 | m_vflag ? 'V' : '.', | |
| 362 | m_f ? '.' : 'Z'); | |
| 363 | 363 | break; |
| 364 | 364 | } |
| 365 | 365 | } |
| r25360 | r25361 | |
| 488 | 488 | { |
| 489 | 489 | case STATE_GENFLAGS: |
| 490 | 490 | string.printf( "%c%c%c|%cG", m_cflag ? 'C' : '.', |
| 491 | m_vflag ? 'V' : '.', | |
| 492 | m_f ? '.' : 'Z', | |
| 493 | ( m_clkcnt & 3 ) ? 'B' : 'F'); | |
| 491 | m_vflag ? 'V' : '.', | |
| 492 | m_f ? '.' : 'Z', | |
| 493 | ( m_clkcnt & 3 ) ? 'B' : 'F'); | |
| 494 | 494 | break; |
| 495 | 495 | } |
| 496 | 496 | } |
| r25360 | r25361 | |
| 1551 | 1551 | m_clkcnt++; |
| 1552 | 1552 | } while (m_icount > 0); |
| 1553 | 1553 | } |
| 1554 |
| r25360 | r25361 | |
|---|---|---|
| 1708 | 1708 | } |
| 1709 | 1709 | } |
| 1710 | 1710 | |
| 1711 | void m6801_cpu_device::m6801_clock_serial() | |
| 1712 | { | |
| 1711 | void m6801_cpu_device::m6801_clock_serial() | |
| 1712 | { | |
| 1713 | 1713 | if (m_use_ext_serclock) |
| 1714 | 1714 | { |
| 1715 | m_ext_serclock++; | |
| 1715 | m_ext_serclock++; | |
| 1716 | 1716 | |
| 1717 | 1717 | if (m_ext_serclock >= 8) |
| 1718 | { | |
| 1719 | m_ext_serclock = 0; | |
| 1720 | serial_transmit(); | |
| 1721 | serial_receive(); | |
| 1718 | { | |
| 1719 | m_ext_serclock = 0; | |
| 1720 | serial_transmit(); | |
| 1721 | serial_receive(); | |
| 1722 | 1722 | } |
| 1723 | 1723 | } |
| 1724 | 1724 | } |
| r25360 | r25361 | |
| 1777 | 1777 | extern CPU_DISASSEMBLE( nsc8105 ); |
| 1778 | 1778 | return CPU_DISASSEMBLE_NAME(nsc8105)(this, buffer, pc, oprom, opram, options); |
| 1779 | 1779 | } |
| 1780 |
| r25360 | r25361 | |
|---|---|---|
| 139 | 139 | int m_clock_divider; |
| 140 | 140 | UINT8 m_trcsr, m_rmcr, m_rdr, m_tdr, m_rsr, m_tsr; |
| 141 | 141 | int m_rxbits, m_txbits, m_txstate, m_trcsr_read_tdre, m_trcsr_read_orfe, m_trcsr_read_rdrf, m_tx, m_ext_serclock; |
| 142 | bool | |
| 142 | bool m_use_ext_serclock; | |
| 143 | 143 | int m_port2_written; |
| 144 | 144 | |
| 145 | 145 | int m_icount; |
| r25360 | r25361 | |
|---|---|---|
| 65 | 65 | UINT16 root_current( int n_counter ); |
| 66 | 66 | int root_target( int n_counter ); |
| 67 | 67 | void root_timer_adjust( int n_counter ); |
| 68 | ||
| 68 | ||
| 69 | 69 | devcb2_write_line m_irq0_handler; |
| 70 | 70 | devcb2_write_line m_irq1_handler; |
| 71 | 71 | devcb2_write_line m_irq2_handler; |
| r25360 | r25361 | |
|---|---|---|
| 236 | 236 | extern CPU_DISASSEMBLE( minx ); |
| 237 | 237 | return CPU_DISASSEMBLE_NAME(minx)(this, buffer, pc, oprom, opram, options); |
| 238 | 238 | } |
| 239 |
| r25360 | r25361 | |
|---|---|---|
| 880 | 880 | static const op_func insnminx_CE[256]; |
| 881 | 881 | static const int insnminx_cycles_CE[256]; |
| 882 | 882 | |
| 883 | static const op_func insnminx_CF[256]; | |
| 884 | static const int insnminx_cycles_CF[256]; | |
| 883 | static const op_func insnminx_CF[256]; | |
| 884 | static const int insnminx_cycles_CF[256]; | |
| 885 | 885 | |
| 886 | 886 | }; |
| 887 | 887 |
| r25360 | r25361 | |
|---|---|---|
| 1601 | 1601 | m_irq_vector = 0; |
| 1602 | 1602 | memset(m_r, 0, sizeof(m_r)); |
| 1603 | 1603 | m_irq_request = 0; |
| 1604 | ||
| 1604 | ||
| 1605 | 1605 | m_w&=~I; |
| 1606 | 1606 | |
| 1607 | 1607 | /* save PC0 to PC1 and reset PC0 */ |
| r25360 | r25361 | |
| 2054 | 2054 | { |
| 2055 | 2055 | case STATE_GENFLAGS: |
| 2056 | 2056 | string.printf("%c%c%c%c%c", |
| 2057 | m_w & 0x10 ? 'I':'.', | |
| 2058 | m_w & 0x08 ? 'O':'.', | |
| 2059 | m_w & 0x04 ? 'Z':'.', | |
| 2060 | m_w & 0x02 ? 'C':'.', | |
| 2061 | m_w & 0x01 ? 'S':'.'); | |
| 2057 | m_w & 0x10 ? 'I':'.', | |
| 2058 | m_w & 0x08 ? 'O':'.', | |
| 2059 | m_w & 0x04 ? 'Z':'.', | |
| 2060 | m_w & 0x02 ? 'C':'.', | |
| 2061 | m_w & 0x01 ? 'S':'.'); | |
| 2062 | 2062 | break; |
| 2063 | 2063 | } |
| 2064 | 2064 | } |
| r25360 | r25361 | |
| 2075 | 2075 | { |
| 2076 | 2076 | m_irq_request = state; |
| 2077 | 2077 | } |
| 2078 | ||
| 2079 |
| r25360 | r25361 | |
|---|---|---|
| 227 | 227 | class pic16cr620a_device : public pic16c62x_device |
| 228 | 228 | { |
| 229 | 229 | public: |
| 230 | // construction/destruction | |
| 231 | pic16cr620a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); | |
| 230 | // construction/destruction | |
| 231 | pic16cr620a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); | |
| 232 | 232 | }*/; |
| 233 | 233 | |
| 234 | 234 | class pic16c621_device : public pic16c62x_device |
| r25360 | r25361 | |
|---|---|---|
| 1176 | 1176 | pic16c62x_reset_regs(); |
| 1177 | 1177 | SET(STATUS, (TO_FLAG | PD_FLAG)); |
| 1178 | 1178 | } |
| 1179 |
| r25360 | r25361 | |
|---|---|---|
| 285 | 285 | |
| 286 | 286 | int i860_cpu_device::has_delay_slot(UINT32 insn) |
| 287 | 287 | { |
| 288 | int opc = (insn >> 26) & 0x3f; | |
| 289 | if (opc == 0x10 || opc == 0x1a || opc == 0x1b || opc == 0x1d || | |
| 290 | opc == 0x1f || opc == 0x2d || (opc == 0x13 && (insn & 3) == 2)) | |
| 291 | return 1; | |
| 292 | return 0; | |
| 288 | int opc = (insn >> 26) & 0x3f; | |
| 289 | if (opc == 0x10 || opc == 0x1a || opc == 0x1b || opc == 0x1d || | |
| 290 | opc == 0x1f || opc == 0x2d || (opc == 0x13 && (insn & 3) == 2)) | |
| 291 | return 1; | |
| 292 | return 0; | |
| 293 | 293 | } |
| 294 | 294 | |
| 295 | 295 | /* This is the external interface for asserting/deasserting pins on |
| r25360 | r25361 | |
|---|---|---|
| 139 | 139 | void i860_cpu_device::state_import(const device_state_entry &entry) |
| 140 | 140 | { |
| 141 | 141 | #define I860_SET_INFO_F(fnum) m_frg[0+(4*fnum)] = (m_freg[fnum] & 0x000000ff); \ |
| 142 | m_frg[1+(4*fnum)] = (m_freg[fnum] & 0x0000ff00) >> 8; \ | |
| 143 | m_frg[2+(4*fnum)] = (m_freg[fnum] & 0x00ff0000) >> 16; \ | |
| 144 | m_frg[3+(4*fnum)] = (m_freg[fnum] & 0xff000000) >> 24; | |
| 142 | m_frg[1+(4*fnum)] = (m_freg[fnum] & 0x0000ff00) >> 8; \ | |
| 143 | m_frg[2+(4*fnum)] = (m_freg[fnum] & 0x00ff0000) >> 16; \ | |
| 144 | m_frg[3+(4*fnum)] = (m_freg[fnum] & 0xff000000) >> 24; | |
| 145 | 145 | |
| 146 | 146 | switch (entry.index()) |
| 147 | 147 | { |
| r25360 | r25361 | |
| 238 | 238 | * The actual decode and execute code. |
| 239 | 239 | **************************************************************************/ |
| 240 | 240 | #include "i860dec.c" |
| 241 |
| r25360 | r25361 | |
|---|---|---|
| 595 | 595 | (this->*hc11_optable[op])(); |
| 596 | 596 | } |
| 597 | 597 | } |
| 598 |
| r25360 | r25361 | |
|---|---|---|
| 760 | 760 | |
| 761 | 761 | return false; |
| 762 | 762 | } |
| 763 |
| r25360 | r25361 | |
|---|---|---|
| 17 | 17 | |
| 18 | 18 | INLINE sh2_state *GET_SH2(device_t *dev) |
| 19 | 19 | { |
| 20 | ||
| 20 | if (dev->machine().options().drc()) { | |
| 21 | 21 | return *(sh2_state **)downcast<legacy_cpu_device *>(dev)->token(); |
| 22 | ||
| 22 | } else { | |
| 23 | 23 | return (sh2_state *)downcast<legacy_cpu_device *>(dev)->token(); |
| 24 | ||
| 24 | } | |
| 25 | 25 | } |
| 26 | 26 | |
| 27 | 27 | static const int div_tab[4] = { 3, 5, 7, 0 }; |
| r25360 | r25361 | |
| 844 | 844 | sh2_exception(sh2, "Set IRQ line", 16); |
| 845 | 845 | |
| 846 | 846 | if (sh2->isdrc) |
| 847 | sh2->pending_nmi = 1; | |
| 847 | sh2->pending_nmi = 1; | |
| 848 | 848 | } |
| 849 | 849 | } |
| 850 | 850 | else |
| r25360 | r25361 | |
|---|---|---|
| 117 | 117 | UINT32 irqsr; // IRQ-time old SR for DRC |
| 118 | 118 | UINT32 target; // target for jmp/jsr/etc so the delay slot can't kill it |
| 119 | 119 | irq_entry irq_queue[16]; |
| 120 | ||
| 120 | ||
| 121 | 121 | bool isdrc; |
| 122 | 122 | |
| 123 | 123 | int pcfsel; // last pcflush entry set |
| r25360 | r25361 | |
|---|---|---|
| 2436 | 2436 | extern CPU_DISASSEMBLE( mn10200 ); |
| 2437 | 2437 | return CPU_DISASSEMBLE_NAME(mn10200)(this, buffer, pc, oprom, opram, options); |
| 2438 | 2438 | } |
| 2439 | ||
| 2440 |
| r25360 | r25361 | |
|---|---|---|
| 1330 | 1330 | break; |
| 1331 | 1331 | } |
| 1332 | 1332 | } |
| 1333 |
| r25360 | r25361 | |
|---|---|---|
| 484 | 484 | i8021_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 485 | 485 | |
| 486 | 486 | protected: |
| 487 | // device_execute_interface overrides | |
| 488 | virtual UINT64 execute_clocks_to_cycles(UINT64 clocks) const { return (clocks + 30 - 1) / 30; } | |
| 489 | virtual UINT64 execute_cycles_to_clocks(UINT64 cycles) const { return (cycles * 30); } | |
| 487 | // device_execute_interface overrides | |
| 488 | virtual UINT64 execute_clocks_to_cycles(UINT64 clocks) const { return (clocks + 30 - 1) / 30; } | |
| 489 | virtual UINT64 execute_cycles_to_clocks(UINT64 cycles) const { return (cycles * 30); } | |
| 490 | 490 | }; |
| 491 | 491 | |
| 492 | 492 | class i8022_device : public mcs48_cpu_device |
| r25360 | r25361 | |
| 496 | 496 | i8022_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 497 | 497 | |
| 498 | 498 | protected: |
| 499 | // device_execute_interface overrides | |
| 500 | virtual UINT64 execute_clocks_to_cycles(UINT64 clocks) const { return (clocks + 30 - 1) / 30; } | |
| 501 | virtual UINT64 execute_cycles_to_clocks(UINT64 cycles) const { return (cycles * 30); } | |
| 499 | // device_execute_interface overrides | |
| 500 | virtual UINT64 execute_clocks_to_cycles(UINT64 clocks) const { return (clocks + 30 - 1) / 30; } | |
| 501 | virtual UINT64 execute_cycles_to_clocks(UINT64 cycles) const { return (cycles * 30); } | |
| 502 | 502 | }; |
| 503 | 503 | |
| 504 | 504 | class i8035_device : public mcs48_cpu_device |
| r25360 | r25361 | |
|---|---|---|
| 22 | 22 | |
| 23 | 23 | // internal memory map |
| 24 | 24 | static ADDRESS_MAP_START(mp_internal_map, AS_PROGRAM, 32, tms32082_mp_device) |
| 25 | AM_RANGE(0x00000000, 0x00000fff) AM_RAM | |
| 25 | AM_RANGE(0x00000000, 0x00000fff) AM_RAM AM_SHARE("pp0_data0") | |
| 26 | 26 | AM_RANGE(0x00001000, 0x00001fff) AM_RAM AM_SHARE("pp1_data0") |
| 27 | 27 | AM_RANGE(0x00008000, 0x00008fff) AM_RAM AM_SHARE("pp0_data1") |
| 28 | 28 | AM_RANGE(0x00009000, 0x00009fff) AM_RAM AM_SHARE("pp1_data1") |
| r25360 | r25361 | |
| 141 | 141 | save_item(NAME(m_fetchpc)); |
| 142 | 142 | save_item(NAME(m_reg)); |
| 143 | 143 | save_item(NAME(m_acc)); |
| 144 | ||
| 144 | ||
| 145 | 145 | save_item(NAME(m_in0p)); |
| 146 | 146 | save_item(NAME(m_in1p)); |
| 147 | 147 | save_item(NAME(m_outp)); |
| r25360 | r25361 | |
| 256 | 256 | printf("Task "); |
| 257 | 257 | if (command & 0x00002000) |
| 258 | 258 | printf("Msg "); |
| 259 | ||
| 259 | ||
| 260 | 260 | printf("to: "); |
| 261 | 261 | |
| 262 | 262 | if (command & 0x00000400) |
| r25360 | r25361 | |
| 300 | 300 | { |
| 301 | 301 | switch (reg) |
| 302 | 302 | { |
| 303 | case 0x0: | |
| 303 | case 0x0: // EPC | |
| 304 | 304 | return m_epc; |
| 305 | 305 | |
| 306 | case 0x1: | |
| 306 | case 0x1: // EIP | |
| 307 | 307 | return m_eip; |
| 308 | 308 | |
| 309 | case 0x4: | |
| 309 | case 0x4: // INTPEN | |
| 310 | 310 | return m_intpen; |
| 311 | 311 | |
| 312 | case 0x6: | |
| 312 | case 0x6: // IE | |
| 313 | 313 | return m_ie; |
| 314 | 314 | |
| 315 | 315 | case 0xa: // PPERROR |
| 316 | 316 | return 0xe0000; |
| 317 | 317 | |
| 318 | case 0x4000: | |
| 318 | case 0x4000: // IN0P | |
| 319 | 319 | return m_in0p; |
| 320 | 320 | |
| 321 | case 0x4001: | |
| 321 | case 0x4001: // IN1P | |
| 322 | 322 | return m_in1p; |
| 323 | 323 | |
| 324 | case 0x4002: | |
| 324 | case 0x4002: // OUTP | |
| 325 | 325 | return m_outp; |
| 326 | 326 | |
| 327 | 327 | default: |
| r25360 | r25361 | |
| 335 | 335 | { |
| 336 | 336 | switch (reg) |
| 337 | 337 | { |
| 338 | case 0x0: | |
| 338 | case 0x0: // EPC | |
| 339 | 339 | m_epc = data; |
| 340 | 340 | break; |
| 341 | 341 | |
| 342 | case 0x1: | |
| 342 | case 0x1: // EIP | |
| 343 | 343 | m_eip = data; |
| 344 | 344 | break; |
| 345 | 345 | |
| 346 | case 0x4: | |
| 346 | case 0x4: // INTPEN | |
| 347 | 347 | { |
| 348 | 348 | for (int i=0; i < 32; i++) |
| 349 | 349 | { |
| r25360 | r25361 | |
| 353 | 353 | break; |
| 354 | 354 | } |
| 355 | 355 | |
| 356 | case 0x6: | |
| 356 | case 0x6: // IE | |
| 357 | 357 | m_ie = data; |
| 358 | 358 | printf("IE = %08X\n", data); |
| 359 | 359 | break; |
| 360 | 360 | |
| 361 | case 0x4000: | |
| 361 | case 0x4000: // IN0P | |
| 362 | 362 | m_in0p = data; |
| 363 | 363 | break; |
| 364 | 364 | |
| 365 | case 0x4001: | |
| 365 | case 0x4001: // IN1P | |
| 366 | 366 | m_in1p = data; |
| 367 | 367 | break; |
| 368 | 368 | |
| 369 | case 0x4002: | |
| 369 | case 0x4002: // OUTP | |
| 370 | 370 | m_outp = data; |
| 371 | 371 | break; |
| 372 | 372 | |
| r25360 | r25361 | |
| 378 | 378 | |
| 379 | 379 | void tms32082_mp_device::check_interrupts() |
| 380 | 380 | { |
| 381 | if (m_ie & 1) | |
| 381 | if (m_ie & 1) // global interrupt mask | |
| 382 | 382 | { |
| 383 | 383 | for (int i=1; i < 32; i++) |
| 384 | 384 | { |
| 385 | 385 | if (m_ie & m_intpen & (1 << i)) |
| 386 | 386 | { |
| 387 | 387 | m_epc = (m_fetchpc & ~3); |
| 388 | m_epc |= (m_ie & 1); | |
| 388 | m_epc |= (m_ie & 1); // save global interrupt mask | |
| 389 | 389 | // TODO: user mode bit to EPC |
| 390 | 390 | |
| 391 | 391 | m_eip = m_pc; |
| 392 | 392 | |
| 393 | m_ie &= ~1; | |
| 393 | m_ie &= ~1; // clear global interrupt mask | |
| 394 | 394 | |
| 395 | 395 | // get new pc from vector table |
| 396 | 396 | m_fetchpc = m_pc = m_program->read_dword(0x01010180 + (i * 4)); |
| r25360 | r25361 | |
| 445 | 445 | while (m_icount > 0) |
| 446 | 446 | { |
| 447 | 447 | m_pc = m_fetchpc; |
| 448 | ||
| 448 | ||
| 449 | 449 | check_interrupts(); |
| 450 | 450 | |
| 451 | 451 | debugger_instruction_hook(this, m_pc); |
| r25360 | r25361 | |
| 466 | 466 | |
| 467 | 467 | // internal memory map |
| 468 | 468 | static ADDRESS_MAP_START(pp_internal_map, AS_PROGRAM, 32, tms32082_pp_device) |
| 469 | AM_RANGE(0x00000000, 0x00000fff) AM_RAM | |
| 469 | AM_RANGE(0x00000000, 0x00000fff) AM_RAM AM_SHARE("pp0_data0") | |
| 470 | 470 | AM_RANGE(0x00001000, 0x00001fff) AM_RAM AM_SHARE("pp1_data0") |
| 471 | 471 | AM_RANGE(0x00008000, 0x00008fff) AM_RAM AM_SHARE("pp0_data1") |
| 472 | 472 | AM_RANGE(0x00009000, 0x00009fff) AM_RAM AM_SHARE("pp1_data1") |
| r25360 | r25361 | |
| 528 | 528 | m_icount = 0; |
| 529 | 529 | |
| 530 | 530 | return; |
| 531 | } | |
| No newline at end of file | ||
| 531 | } |
| r25360 | r25361 | |
|---|---|---|
| 58 | 58 | |
| 59 | 59 | enum |
| 60 | 60 | { |
| 61 | INPUT_X1 = 1, | |
| 62 | INPUT_X2 = 2, | |
| 63 | INPUT_X3 = 3, | |
| 64 | INPUT_X4 = 4, | |
| 61 | INPUT_X1 = 1, | |
| 62 | INPUT_X2 = 2, | |
| 63 | INPUT_X3 = 3, | |
| 64 | INPUT_X4 = 4, | |
| 65 | 65 | }; |
| 66 | 66 | |
| 67 | 67 | DECLARE_READ32_MEMBER(mp_param_r); |
| r25360 | r25361 | |
|---|---|---|
| 16 | 16 | |
| 17 | 17 | static const char *BITNUM_CONDITION[32] = |
| 18 | 18 | { |
| 19 | "eq.b", "ne.b", "gt.b", "le.b", "lt.b", "ge.b", "hi.b", "ls.b", | |
| 20 | "lo.b", "hs.b", "eq.h", "ne.h", "gt.h", "le.h", "lt.h", "ge.h", | |
| 21 | "hi.h", "ls.h", "lo.h", "hs.h", "eq.w", "ne.w", "gt.w", "le.w", | |
| 22 | "lt.w", "ge.w", "hi.w", "ls.w", "lo.w", "hs.w", "?", "?", | |
| 19 | "eq.b", "ne.b", "gt.b", "le.b", "lt.b", "ge.b", "hi.b", "ls.b", | |
| 20 | "lo.b", "hs.b", "eq.h", "ne.h", "gt.h", "le.h", "lt.h", "ge.h", | |
| 21 | "hi.h", "ls.h", "lo.h", "hs.h", "eq.w", "ne.w", "gt.w", "le.w", | |
| 22 | "lt.w", "ge.w", "hi.w", "ls.w", "lo.w", "hs.w", "?", "?", | |
| 23 | 23 | }; |
| 24 | 24 | |
| 25 | 25 | static const char *MEMOP_S[2] = |
| r25360 | r25361 | |
| 156 | 156 | b += sprintf(b, "vrnd.%s%s 0x%08X, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[pd4], imm32, rs); |
| 157 | 157 | break; |
| 158 | 158 | |
| 159 | case 0xca: b += sprintf(b, "vrnd.%s%s R%d, R%d", FLOATOP_PRECISION[2 + p1], FLOATOP_PRECISION[pd2],src1, rs); break; | |
| 160 | case 0xcb: b += sprintf(b, "vrnd.%s%s 0x%08X, R%d", FLOATOP_PRECISION[2 + p1], FLOATOP_PRECISION[pd2], imm32, rs); break; | |
| 159 | case 0xca: b += sprintf(b, "vrnd.%s%s R%d, R%d", FLOATOP_PRECISION[2 + p1], FLOATOP_PRECISION[pd2],src1, rs); break; | |
| 160 | case 0xcb: b += sprintf(b, "vrnd.%s%s 0x%08X, R%d", FLOATOP_PRECISION[2 + p1], FLOATOP_PRECISION[pd2], imm32, rs); break; | |
| 161 | 161 | |
| 162 | 162 | case 0xcc: case 0xdc: |
| 163 | 163 | b += sprintf(b, "vmac.ss%s R%d, R%d, %s, %s", FLOATOP_PRECISION[(op >> 9) & 1], src1, rs, z ? "0" : ACC_SEL[acc], (regdest && rd == 0) ? ACC_SEL[acc] : dest); |
| r25360 | r25361 | |
| 172 | 172 | b += sprintf(b, "vmsc.ss%s 0x%08X, R%d, %s, %s", FLOATOP_PRECISION[(op >> 9) & 1], imm32, rs, z ? "0" : ACC_SEL[acc], (regdest && rd == 0) ? ACC_SEL[acc] : dest); |
| 173 | 173 | break; |
| 174 | 174 | |
| 175 | default: | |
| 175 | default: b += sprintf(b, "?"); break; | |
| 176 | 176 | } |
| 177 | 177 | |
| 178 | 178 | // align the line end |
| r25360 | r25361 | |
| 183 | 183 | { |
| 184 | 184 | b += sprintf(b, " "); |
| 185 | 185 | } |
| 186 | } | |
| 186 | } | |
| 187 | 187 | |
| 188 | 188 | // optional load/store op |
| 189 | 189 | switch (vector_ls_bits) |
| 190 | 190 | { |
| 191 | case 0x01: b += sprintf(b, "|| vst.s R%d", rd); break; | |
| 192 | case 0x03: b += sprintf(b, "|| vst.d R%d", rd); break; | |
| 193 | case 0x04: b += sprintf(b, "|| vld0.s R%d", rd); break; | |
| 194 | case 0x05: b += sprintf(b, "|| vld1.s R%d", rd); break; | |
| 195 | case 0x06: b += sprintf(b, "|| vld0.d R%d", rd); break; | |
| 196 | case 0x07: b += sprintf(b, "|| vld1.d R%d", rd); break; | |
| 191 | case 0x01: b += sprintf(b, "|| vst.s R%d", rd); break; | |
| 192 | case 0x03: b += sprintf(b, "|| vst.d R%d", rd); break; | |
| 193 | case 0x04: b += sprintf(b, "|| vld0.s R%d", rd); break; | |
| 194 | case 0x05: b += sprintf(b, "|| vld1.s R%d", rd); break; | |
| 195 | case 0x06: b += sprintf(b, "|| vld0.d R%d", rd); break; | |
| 196 | case 0x07: b += sprintf(b, "|| vld1.d R%d", rd); break; | |
| 197 | 197 | } |
| 198 | 198 | |
| 199 | 199 | return buffer; |
| r25360 | r25361 | |
| 226 | 226 | |
| 227 | 227 | switch (subop) |
| 228 | 228 | { |
| 229 | case 0x00: print("illop0 "); break; | |
| 230 | case 0x01: print("trap %d", UIMM15(uimm15)); break; | |
| 231 | case 0x02: print("cmnd 0x%04X", UIMM15(uimm15)); break; | |
| 232 | case 0x04: print("rdcr %s, R%d", get_creg_name(UIMM15(uimm15)), rd); break; | |
| 233 | case 0x05: print("swcr R%d, %s, R%d", rd, get_creg_name(UIMM15(uimm15)), rs); break; | |
| 234 | case 0x06: print("brcr %s", get_creg_name(UIMM15(uimm15))); break; | |
| 235 | case 0x08: print("shift%s.dz %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; | |
| 236 | case 0x09: print("shift%s.dm %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; | |
| 237 | case 0x0a: print("shift%s.ds %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; | |
| 238 | case 0x0b: print("shift%s.ez %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; | |
| 239 | case 0x0c: print("shift%s.em %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; | |
| 240 | case 0x0d: print("shift%s.es %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; | |
| 241 | case 0x0e: print("shift%s.iz %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; | |
| 242 | case 0x0f: print("shift%s.im %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; | |
| 243 | case 0x11: print("and 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break; | |
| 244 | case 0x12: print("and.tf 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break; | |
| 245 | case 0x14: print("and.ft 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break; | |
| 246 | case 0x16: print("xor 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break; | |
| 247 | case 0x17: print("or 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break; | |
| 248 | case 0x18: print("and.ff 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break; | |
| 249 | case 0x19: print("xnor 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break; | |
| 250 | case 0x1b: print("or.tf 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break; | |
| 251 | case 0x1d: print("or.ft 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break; | |
| 252 | case 0x1e: print("or.ff 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break; | |
| 229 | case 0x00: print("illop0 "); break; | |
| 230 | case 0x01: print("trap %d", UIMM15(uimm15)); break; | |
| 231 | case 0x02: print("cmnd 0x%04X", UIMM15(uimm15)); break; | |
| 232 | case 0x04: print("rdcr %s, R%d", get_creg_name(UIMM15(uimm15)), rd); break; | |
| 233 | case 0x05: print("swcr R%d, %s, R%d", rd, get_creg_name(UIMM15(uimm15)), rs); break; | |
| 234 | case 0x06: print("brcr %s", get_creg_name(UIMM15(uimm15))); break; | |
| 235 | case 0x08: print("shift%s.dz %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; | |
| 236 | case 0x09: print("shift%s.dm %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; | |
| 237 | case 0x0a: print("shift%s.ds %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; | |
| 238 | case 0x0b: print("shift%s.ez %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; | |
| 239 | case 0x0c: print("shift%s.em %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; | |
| 240 | case 0x0d: print("shift%s.es %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; | |
| 241 | case 0x0e: print("shift%s.iz %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; | |
| 242 | case 0x0f: print("shift%s.im %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; | |
| 243 | case 0x11: print("and 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break; | |
| 244 | case 0x12: print("and.tf 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break; | |
| 245 | case 0x14: print("and.ft 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break; | |
| 246 | case 0x16: print("xor 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break; | |
| 247 | case 0x17: print("or 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break; | |
| 248 | case 0x18: print("and.ff 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break; | |
| 249 | case 0x19: print("xnor 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break; | |
| 250 | case 0x1b: print("or.tf 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break; | |
| 251 | case 0x1d: print("or.ft 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break; | |
| 252 | case 0x1e: print("or.ff 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break; | |
| 253 | 253 | |
| 254 | 254 | case 0x24: case 0x20: |
| 255 | 255 | print("ld.b 0x%04X(R%d%s), R%d", UIMM15(uimm15), rs, MEMOP_M[m], rd); |
| r25360 | r25361 | |
| 283 | 283 | print("st.d R%d, 0x%04X(R%d%s)", rd, UIMM15(uimm15), rs, MEMOP_M[m]); |
| 284 | 284 | break; |
| 285 | 285 | |
| 286 | case 0x40: print("bsr 0x%08X, R%d", pc + (SIMM15(uimm15) * 4), link); break; | |
| 287 | case 0x41: print("bsr.a 0x%08X, R%d", pc + (SIMM15(uimm15) * 4), link); break; | |
| 288 | case 0x44: print("jsr 0x%04X(R%d), R%d", SIMM15(uimm15), rs, link); break; | |
| 289 | case 0x45: print("jsr.a 0x%04X(R%d), R%d", SIMM15(uimm15), rs, link); break; | |
| 290 | case 0x48: print("bbz 0x%08X, R%d, %s (%d)", pc + (SIMM15(uimm15) * 4), rs, BITNUM_CONDITION[bitnum], bitnum); break; | |
| 291 | case 0x49: print("bbz.a 0x%08X, R%d, %s (%d)", pc + (SIMM15(uimm15) * 4), rs, BITNUM_CONDITION[bitnum], bitnum); break; | |
| 292 | case 0x4a: print("bbo 0x%08X, R%d, %s (%d)", pc + (SIMM15(uimm15) * 4), rs, BITNUM_CONDITION[bitnum], bitnum); break; | |
| 293 | case 0x4b: print("bbo.a 0x%08X, R%d, %s (%d)", pc + (SIMM15(uimm15) * 4), rs, BITNUM_CONDITION[bitnum], bitnum); break; | |
| 294 | case 0x4c: print("bcnd 0x%08X, R%d, %s", pc + (SIMM15(uimm15) * 4), rs, BCND_CONDITION[rd]); break; | |
| 295 | case 0x4d: print("bcnd.a 0x%08X, R%d, %s", pc + (SIMM15(uimm15) * 4), rs, BCND_CONDITION[rd]); break; | |
| 296 | case 0x50: print("cmp 0x%08X, R%d, R%d", SIMM15(uimm15), rs, rd); break; | |
| 297 | case 0x58: print("add 0x%08X, R%d, R%d", SIMM15(uimm15), rs, rd); break; | |
| 298 | case 0x59: print("addu 0x%08X, R%d, R%d", SIMM15(uimm15), rs, rd); break; | |
| 299 | case 0x5a: print("sub 0x%08X, R%d, R%d", SIMM15(uimm15), rs, rd); break; | |
| 300 | case 0x5b: print("subu 0x%08X, R%d, R%d", SIMM15(uimm15), rs, rd); break; | |
| 286 | case 0x40: print("bsr 0x%08X, R%d", pc + (SIMM15(uimm15) * 4), link); break; | |
| 287 | case 0x41: print("bsr.a 0x%08X, R%d", pc + (SIMM15(uimm15) * 4), link); break; | |
| 288 | case 0x44: print("jsr 0x%04X(R%d), R%d", SIMM15(uimm15), rs, link); break; | |
| 289 | case 0x45: print("jsr.a 0x%04X(R%d), R%d", SIMM15(uimm15), rs, link); break; | |
| 290 | case 0x48: print("bbz 0x%08X, R%d, %s (%d)", pc + (SIMM15(uimm15) * 4), rs, BITNUM_CONDITION[bitnum], bitnum); break; | |
| 291 | case 0x49: print("bbz.a 0x%08X, R%d, %s (%d)", pc + (SIMM15(uimm15) * 4), rs, BITNUM_CONDITION[bitnum], bitnum); break; | |
| 292 | case 0x4a: print("bbo 0x%08X, R%d, %s (%d)", pc + (SIMM15(uimm15) * 4), rs, BITNUM_CONDITION[bitnum], bitnum); break; | |
| 293 | case 0x4b: print("bbo.a 0x%08X, R%d, %s (%d)", pc + (SIMM15(uimm15) * 4), rs, BITNUM_CONDITION[bitnum], bitnum); break; | |
| 294 | case 0x4c: print("bcnd 0x%08X, R%d, %s", pc + (SIMM15(uimm15) * 4), rs, BCND_CONDITION[rd]); break; | |
| 295 | case 0x4d: print("bcnd.a 0x%08X, R%d, %s", pc + (SIMM15(uimm15) * 4), rs, BCND_CONDITION[rd]); break; | |
| 296 | case 0x50: print("cmp 0x%08X, R%d, R%d", SIMM15(uimm15), rs, rd); break; | |
| 297 | case 0x58: print("add 0x%08X, R%d, R%d", SIMM15(uimm15), rs, rd); break; | |
| 298 | case 0x59: print("addu 0x%08X, R%d, R%d", SIMM15(uimm15), rs, rd); break; | |
| 299 | case 0x5a: print("sub 0x%08X, R%d, R%d", SIMM15(uimm15), rs, rd); break; | |
| 300 | case 0x5b: print("subu 0x%08X, R%d, R%d", SIMM15(uimm15), rs, rd); break; | |
| 301 | 301 | |
| 302 | default: | |
| 302 | default: print("?"); break; | |
| 303 | 303 | } |
| 304 | 304 | break; |
| 305 | 305 | } |
| r25360 | r25361 | |
| 324 | 324 | |
| 325 | 325 | switch (subop) |
| 326 | 326 | { |
| 327 | case 0x02: print("trap %d", src1); break; | |
| 328 | case 0x03: print("trap %d", imm32); break; | |
| 329 | case 0x04: print("cmnd R%d", src1); break; | |
| 330 | case 0x05: print("cmnd 0x%08X", imm32); break; | |
| 331 | case 0x08: print("rdcr R%d, R%d,", src1, rd); break; | |
| 332 | case 0x09: print("rdcr %s, R%d", get_creg_name(imm32), rd); break; | |
| 333 | case 0x0a: print("swcr R%d, R%d, R%d", rd, src1, rs); break; | |
| 334 | case 0x0b: print("swcr R%d, %s, R%d", rd, get_creg_name(imm32), rs); break; | |
| 335 | case 0x0c: print("brcr R%d", src1); break; | |
| 336 | case 0x0d: print("brcr %s", get_creg_name(imm32)); break; | |
| 327 | case 0x02: print("trap %d", src1); break; | |
| 328 | case 0x03: print("trap %d", imm32); break; | |
| 329 | case 0x04: print("cmnd R%d", src1); break; | |
| 330 | case 0x05: print("cmnd 0x%08X", imm32); break; | |
| 331 | case 0x08: print("rdcr R%d, R%d,", src1, rd); break; | |
| 332 | case 0x09: print("rdcr %s, R%d", get_creg_name(imm32), rd); break; | |
| 333 | case 0x0a: print("swcr R%d, R%d, R%d", rd, src1, rs); break; | |
| 334 | case 0x0b: print("swcr R%d, %s, R%d", rd, get_creg_name(imm32), rs); break; | |
| 335 | case 0x0c: print("brcr R%d", src1); break; | |
| 336 | case 0x0d: print("brcr %s", get_creg_name(imm32)); break; | |
| 337 | 337 | |
| 338 | 338 | case 0x10: print("shift%s.dz %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; |
| 339 | 339 | case 0x12: print("shift%s.dm %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; |
| r25360 | r25361 | |
| 434 | 434 | print("dcache 0x%08X(R%d)", imm32, rs); |
| 435 | 435 | break; |
| 436 | 436 | |
| 437 | case 0x80: print("bsr R%d, R%d", src1, link); break; | |
| 438 | case 0x81: print("bsr 0x%08X, R%d", imm32, link); break; | |
| 439 | case 0x82: print("bsr.a R%d, R%d", src1, rd); break; | |
| 440 | case 0x83: print("bsr.a 0x%08X, R%d", imm32, link); break; | |
| 441 | case 0x88: print("jsr R%d, R%d", src1, link); break; | |
| 442 | case 0x89: print("jsr 0x%08X, R%d", imm32, link); break; | |
| 443 | case 0x8a: print("jsr.a R%d, R%d", src1, link); break; | |
| 444 | case 0x8b: print("jsr.a 0x%08X, R%d", imm32, link); break; | |
| 445 | case 0x90: print("bbz R%d, R%d, %s (%d)", src1, rs, BITNUM_CONDITION[bitnum], bitnum); break; | |
| 446 | case 0x91: print("bbz 0x%08X, R%d, %s (%d)", imm32, rs, BITNUM_CONDITION[bitnum], bitnum); break; | |
| 447 | case 0x92: print("bbz.a R%d, R%d, %s (%d)", src1, rs, BITNUM_CONDITION[bitnum], bitnum); break; | |
| 448 | case 0x93: print("bbz.a 0x%08X, R%d, %s (%d)", imm32, rs, BITNUM_CONDITION[bitnum], bitnum); break; | |
| 449 | case 0x94: print("bbo R%d, R%d, %s (%d)", src1, rs, BITNUM_CONDITION[bitnum], bitnum); break; | |
| 450 | case 0x95: print("bbo 0x%08X, R%d, %s (%d)", imm32, rs, BITNUM_CONDITION[bitnum], bitnum); break; | |
| 451 | case 0x96: print("bbo.a R%d, R%d, %s (%d)", src1, rs, BITNUM_CONDITION[bitnum], bitnum); break; | |
| 452 | case 0x97: print("bbo.a 0x%08X, R%d, %s (%d)", imm32, rs, BITNUM_CONDITION[bitnum], bitnum); break; | |
| 453 | case 0x98: print("bcnd R%d, R%d, %s", src1, rs, BCND_CONDITION[rd]); break; | |
| 454 | case 0x99: print("bcnd 0x%08X, R%d, %s", imm32, rs, BCND_CONDITION[rd]); break; | |
| 455 | case 0x9a: print("bcnd.a R%d, R%d, %s", src1, rs, BCND_CONDITION[rd]); break; | |
| 456 | case 0x9b: print("bcnd.a 0x%08X, R%d, %s", imm32, rs, BCND_CONDITION[rd]); break; | |
| 457 | case 0xa0: print("cmp R%d, R%d, R%d", src1, rs, rd); break; | |
| 458 | case 0xa1: print("cmp 0x%08X, R%d, R%d", imm32, rs, rd); break; | |
| 459 | case 0xb0: print("add R%d, R%d, R%d", src1, rs, rd); break; | |
| 460 | case 0xb1: print("add 0x%08X, R%d, R%d", imm32, rs, rd); break; | |
| 461 | case 0xb2: print("addu R%d, R%d, R%d", src1, rs, rd); break; | |
| 462 | case 0xb3: print("addu 0x%08X, R%d, R%d", imm32, rs, rd); break; | |
| 463 | case 0xb4: print("sub R%d, R%d, R%d", src1, rs, rd); break; | |
| 464 | case 0xb5: print("sub 0x%08X, R%d, R%d", imm32, rs, rd); break; | |
| 465 | case 0xb6: print("subu R%d, R%d, R%d", src1, rs, rd); break; | |
| 466 | case 0xb7: print("subu 0x%08X, R%d, R%d", imm32, rs, rd); break; | |
| 437 | case 0x80: print("bsr R%d, R%d", src1, link); break; | |
| 438 | case 0x81: print("bsr 0x%08X, R%d", imm32, link); break; | |
| 439 | case 0x82: print("bsr.a R%d, R%d", src1, rd); break; | |
| 440 | case 0x83: print("bsr.a 0x%08X, R%d", imm32, link); break; | |
| 441 | case 0x88: print("jsr R%d, R%d", src1, link); break; | |
| 442 | case 0x89: print("jsr 0x%08X, R%d", imm32, link); break; | |
| 443 | case 0x8a: print("jsr.a R%d, R%d", src1, link); break; | |
| 444 | case 0x8b: print("jsr.a 0x%08X, R%d", imm32, link); break; | |
| 445 | case 0x90: print("bbz R%d, R%d, %s (%d)", src1, rs, BITNUM_CONDITION[bitnum], bitnum); break; | |
| 446 | case 0x91: print("bbz 0x%08X, R%d, %s (%d)", imm32, rs, BITNUM_CONDITION[bitnum], bitnum); break; | |
| 447 | case 0x92: print("bbz.a R%d, R%d, %s (%d)", src1, rs, BITNUM_CONDITION[bitnum], bitnum); break; | |
| 448 | case 0x93: print("bbz.a 0x%08X, R%d, %s (%d)", imm32, rs, BITNUM_CONDITION[bitnum], bitnum); break; | |
| 449 | case 0x94: print("bbo R%d, R%d, %s (%d)", src1, rs, BITNUM_CONDITION[bitnum], bitnum); break; | |
| 450 | case 0x95: print("bbo 0x%08X, R%d, %s (%d)", imm32, rs, BITNUM_CONDITION[bitnum], bitnum); break; | |
| 451 | case 0x96: print("bbo.a R%d, R%d, %s (%d)", src1, rs, BITNUM_CONDITION[bitnum], bitnum); break; | |
| 452 | case 0x97: print("bbo.a 0x%08X, R%d, %s (%d)", imm32, rs, BITNUM_CONDITION[bitnum], bitnum); break; | |
| 453 | case 0x98: print("bcnd R%d, R%d, %s", src1, rs, BCND_CONDITION[rd]); break; | |
| 454 | case 0x99: print("bcnd 0x%08X, R%d, %s", imm32, rs, BCND_CONDITION[rd]); break; | |
| 455 | case 0x9a: print("bcnd.a R%d, R%d, %s", src1, rs, BCND_CONDITION[rd]); break; | |
| 456 | case 0x9b: print("bcnd.a 0x%08X, R%d, %s", imm32, rs, BCND_CONDITION[rd]); break; | |
| 457 | case 0xa0: print("cmp R%d, R%d, R%d", src1, rs, rd); break; | |
| 458 | case 0xa1: print("cmp 0x%08X, R%d, R%d", imm32, rs, rd); break; | |
| 459 | case 0xb0: print("add R%d, R%d, R%d", src1, rs, rd); break; | |
| 460 | case 0xb1: print("add 0x%08X, R%d, R%d", imm32, rs, rd); break; | |
| 461 | case 0xb2: print("addu R%d, R%d, R%d", src1, rs, rd); break; | |
| 462 | case 0xb3: print("addu 0x%08X, R%d, R%d", imm32, rs, rd); break; | |
| 463 | case 0xb4: print("sub R%d, R%d, R%d", src1, rs, rd); break; | |
| 464 | case 0xb5: print("sub 0x%08X, R%d, R%d", imm32, rs, rd); break; | |
| 465 | case 0xb6: print("subu R%d, R%d, R%d", src1, rs, rd); break; | |
| 466 | case 0xb7: print("subu 0x%08X, R%d, R%d", imm32, rs, rd); break; | |
| 467 | 467 | |
| 468 | 468 | case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: |
| 469 | 469 | case 0xc6: case 0xd6: case 0xc7: case 0xd7: case 0xc8: case 0xd8: case 0xc9: case 0xd9: |
| 470 | case 0xca: case 0xcb: case 0xcc: case 0xdc: case 0xcd: case 0xdd: case 0xce: case 0xde: | |
| 470 | case 0xca: case 0xcb: case 0xcc: case 0xdc: case 0xcd: case 0xdd: case 0xce: case 0xde: | |
| 471 | 471 | case 0xcf: case 0xdf: |
| 472 | 472 | { |
| 473 | 473 | print("%s", format_vector_op(op, imm32)); |
| 474 | 474 | break; |
| 475 | 475 | } |
| 476 | 476 | |
| 477 | case 0xe0: print("fadd.%s%s%s R%d, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], src1, rs, rd); break; | |
| 478 | case 0xe1: print("fadd.%s%s%s 0x%08X, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], imm32, rs, rd); break; | |
| 479 | case 0xe2: print("fsub.%s%s%s R%d, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], src1, rs, rd); break; | |
| 480 | case 0xe3: print("fsub.%s%s%s 0x%08X, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], imm32, rs, rd); break; | |
| 481 | case 0xe4: print("fmpy.%s%s%s R%d, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], src1, rs, rd); break; | |
| 482 | case 0xe5: print("fmpy.%s%s%s 0x%08X, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], imm32, rs, rd); break; | |
| 483 | case 0xe6: print("fdiv.%s%s%s R%d, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], src1, rs, rd); break; | |
| 484 | case 0xe7: print("fdiv.%s%s%s 0x%08X, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], imm32, rs, rd); break; | |
| 485 | case 0xe8: print("frnd%s.%s%s R%d, R%d", FLOATOP_ROUND[rndmode], FLOATOP_PRECISION[p1], FLOATOP_PRECISION[pd], src1, rd); break; | |
| 486 | case 0xe9: print("frnd%s.%s%s 0x%08X, R%d", FLOATOP_ROUND[rndmode], FLOATOP_PRECISION[p1], FLOATOP_PRECISION[pd], imm32, rd); break; | |
| 487 | case 0xea: print("fcmp R%d, R%d, R%d", src1, rs, rd); break; | |
| 488 | case 0xeb: print("fcmp 0x%08X, R%d, R%d", imm32, rs, rd); break; | |
| 489 | case 0xee: print("fsqrt R%d, R%d", src1, rd); break; | |
| 490 | case 0xef: print("fsqrt 0x%08X, R%d", imm32, rd); break; | |
| 491 | case 0xf0: print("lmo R%d, R%d", rs, rd); break; | |
| 492 | case 0xf2: print("rmo R%d, R%d", rs, rd); break; | |
| 493 | case 0xfc: print("estop "); break; | |
| 494 | ||
| 477 | case 0xe0: print("fadd.%s%s%s R%d, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], src1, rs, rd); break; | |
| 478 | case 0xe1: print("fadd.%s%s%s 0x%08X, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], imm32, rs, rd); break; | |
| 479 | case 0xe2: print("fsub.%s%s%s R%d, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], src1, rs, rd); break; | |
| 480 | case 0xe3: print("fsub.%s%s%s 0x%08X, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], imm32, rs, rd); break; | |
| 481 | case 0xe4: print("fmpy.%s%s%s R%d, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], src1, rs, rd); break; | |
| 482 | case 0xe5: print("fmpy.%s%s%s 0x%08X, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], imm32, rs, rd); break; | |
| 483 | case 0xe6: print("fdiv.%s%s%s R%d, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], src1, rs, rd); break; | |
| 484 | case 0xe7: print("fdiv.%s%s%s 0x%08X, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], imm32, rs, rd); break; | |
| 485 | case 0xe8: print("frnd%s.%s%s R%d, R%d", FLOATOP_ROUND[rndmode], FLOATOP_PRECISION[p1], FLOATOP_PRECISION[pd], src1, rd); break; | |
| 486 | case 0xe9: print("frnd%s.%s%s 0x%08X, R%d", FLOATOP_ROUND[rndmode], FLOATOP_PRECISION[p1], FLOATOP_PRECISION[pd], imm32, rd); break; | |
| 487 | case 0xea: print("fcmp R%d, R%d, R%d", src1, rs, rd); break; | |
| 488 | case 0xeb: print("fcmp 0x%08X, R%d, R%d", imm32, rs, rd); break; | |
| 489 | case 0xee: print("fsqrt R%d, R%d", src1, rd); break; | |
| 490 | case 0xef: print("fsqrt 0x%08X, R%d", imm32, rd); break; | |
| 491 | case 0xf0: print("lmo R%d, R%d", rs, rd); break; | |
| 492 | case 0xf2: print("rmo R%d, R%d", rs, rd); break; | |
| 493 | case 0xfc: print("estop "); break; | |
| 494 | ||
| 495 | 495 | case 0xfe: case 0xff: |
| 496 | 496 | print("illopF "); |
| 497 | 497 | break; |
| 498 | 498 | |
| 499 | default: | |
| 499 | default: print("?"); break; | |
| 500 | 500 | } |
| 501 | 501 | break; |
| 502 | 502 | } |
| r25360 | r25361 | |
|---|---|---|
| 32 | 32 | #define SIGN16(x) (((x) & 0x8000) ? 1 : 0) |
| 33 | 33 | #define SIGN8(x) (((x) & 0x80) ? 1 : 0) |
| 34 | 34 | |
| 35 | #define SIGN_EXTEND(x, r) | |
| 35 | #define SIGN_EXTEND(x, r) ((x) | (((x) & (0x80000000 >> r)) ? ((INT32)(0x80000000) >> r) : 0)) | |
| 36 | 36 | |
| 37 | 37 | |
| 38 | 38 | |
| r25360 | r25361 | |
| 95 | 95 | |
| 96 | 96 | UINT32 flags = 0; |
| 97 | 97 | // 32-bits (bits 20-29) |
| 98 | flags |= ((~c32) & 1) << 29; // higher than or same (C) | |
| 99 | flags |= ((c32) & 1) << 28; // lower than (~C) | |
| 100 | flags |= ((c32|z32) & 1) << 27; // lower than or same (~C|Z) | |
| 101 | flags |= ((~c32&~z32) & 1) << 26; // higher than (C&~Z) | |
| 102 | flags |= (((n32&v32)|(~n32&~v32)) & 1) << 25; // greater than or equal (N&V)|(~N&~V) | |
| 103 | flags |= (((n32&~v32)|(~n32&v32)) & 1) << 24; // less than (N&~V)|(~N&V) | |
| 104 | flags |= (((n32&~v32)|(~n32&v32)|(z32)) & 1) << 23; // less than or equal (N&~V)|(~N&V)|Z | |
| 105 | flags |= (((n32&v32&~z32)|(~n32&~v32&~z32)) & 1) << 22; // greater than (N&V&~Z)|(~N&~V&~Z) | |
| 106 | flags |= ((~z32) & 1) << 21; // not equal (~Z) | |
| 107 | flags |= ((z32) & 1) << 20; // equal (Z) | |
| 98 | flags |= ((~c32) & 1) << 29; // higher than or same (C) | |
| 99 | flags |= ((c32) & 1) << 28; // lower than (~C) | |
| 100 | flags |= ((c32|z32) & 1) << 27; // lower than or same (~C|Z) | |
| 101 | flags |= ((~c32&~z32) & 1) << 26; // higher than (C&~Z) | |
| 102 | flags |= (((n32&v32)|(~n32&~v32)) & 1) << 25; // greater than or equal (N&V)|(~N&~V) | |
| 103 | flags |= (((n32&~v32)|(~n32&v32)) & 1) << 24; // less than (N&~V)|(~N&V) | |
| 104 | flags |= (((n32&~v32)|(~n32&v32)|(z32)) & 1) << 23; // less than or equal (N&~V)|(~N&V)|Z | |
| 105 | flags |= (((n32&v32&~z32)|(~n32&~v32&~z32)) & 1) << 22; // greater than (N&V&~Z)|(~N&~V&~Z) | |
| 106 | flags |= ((~z32) & 1) << 21; // not equal (~Z) | |
| 107 | flags |= ((z32) & 1) << 20; // equal (Z) | |
| 108 | 108 | // 16-bits (bits 10-19) |
| 109 | flags |= ((~c16) & 1) << 19; // higher than or same (C) | |
| 110 | flags |= ((c16) & 1) << 18; // lower than (~C) | |
| 111 | flags |= ((c16|z16) & 1) << 17; // lower than or same (~C|Z) | |
| 112 | flags |= ((~c16&~z16) & 1) << 16; // higher than (C&~Z) | |
| 113 | flags |= (((n16&v16)|(~n16&~v16)) & 1) << 15; // greater than or equal (N&V)|(~N&~V) | |
| 114 | flags |= (((n16&~v16)|(~n16&v16)) & 1) << 14; // less than (N&~V)|(~N&V) | |
| 115 | flags |= (((n16&~v16)|(~n16&v16)|(z16)) & 1) << 13; // less than or equal (N&~V)|(~N&V)|Z | |
| 116 | flags |= (((n16&v16&~z16)|(~n16&~v16&~z16)) & 1) << 12; // greater than (N&V&~Z)|(~N&~V&~Z) | |
| 117 | flags |= ((~z16) & 1) << 11; // not equal (~Z) | |
| 118 | flags |= ((z16) & 1) << 10; // equal (Z) | |
| 109 | flags |= ((~c16) & 1) << 19; // higher than or same (C) | |
| 110 | flags |= ((c16) & 1) << 18; // lower than (~C) | |
| 111 | flags |= ((c16|z16) & 1) << 17; // lower than or same (~C|Z) | |
| 112 | flags |= ((~c16&~z16) & 1) << 16; // higher than (C&~Z) | |
| 113 | flags |= (((n16&v16)|(~n16&~v16)) & 1) << 15; // greater than or equal (N&V)|(~N&~V) | |
| 114 | flags |= (((n16&~v16)|(~n16&v16)) & 1) << 14; // less than (N&~V)|(~N&V) | |
| 115 | flags |= (((n16&~v16)|(~n16&v16)|(z16)) & 1) << 13; // less than or equal (N&~V)|(~N&V)|Z | |
| 116 | flags |= (((n16&v16&~z16)|(~n16&~v16&~z16)) & 1) << 12; // greater than (N&V&~Z)|(~N&~V&~Z) | |
| 117 | flags |= ((~z16) & 1) << 11; // not equal (~Z) | |
| 118 | flags |= ((z16) & 1) << 10; // equal (Z) | |
| 119 | 119 | // 8-bits (bits 0-9) |
| 120 | flags |= ((~c8) & 1) << 9; // higher than or same (C) | |
| 121 | flags |= ((c8) & 1) << 8; // lower than (~C) | |
| 122 | flags |= ((c8|z8) & 1) << 7; // lower than or same (~C|Z) | |
| 123 | flags |= ((~c8&~z8) & 1) << 6; // higher than (C&~Z) | |
| 124 | flags |= (((n8&v8)|(~n8&~v8)) & 1) << 5; // greater than or equal (N&V)|(~N&~V) | |
| 125 | flags |= (((n8&~v8)|(~n8&v8)) & 1) << 4; // less than (N&~V)|(~N&V) | |
| 126 | flags |= (((n8&~v8)|(~n8&v8)|(z8)) & 1) << 3; // less than or equal (N&~V)|(~N&V)|Z | |
| 127 | flags |= (((n8&v8&~z8)|(~n8&~v8&~z8)) & 1) << 2; // greater than (N&V&~Z)|(~N&~V&~Z) | |
| 128 | flags |= ((~z8) & 1) << 1; // not equal (~Z) | |
| 129 | flags |= ((z8) & 1) << 0; // equal (Z) | |
| 120 | flags |= ((~c8) & 1) << 9; // higher than or same (C) | |
| 121 | flags |= ((c8) & 1) << 8; // lower than (~C) | |
| 122 | flags |= ((c8|z8) & 1) << 7; // lower than or same (~C|Z) | |
| 123 | flags |= ((~c8&~z8) & 1) << 6; // higher than (C&~Z) | |
| 124 | flags |= (((n8&v8)|(~n8&~v8)) & 1) << 5; // greater than or equal (N&V)|(~N&~V) | |
| 125 | flags |= (((n8&~v8)|(~n8&v8)) & 1) << 4; // less than (N&~V)|(~N&V) | |
| 126 | flags |= (((n8&~v8)|(~n8&v8)|(z8)) & 1) << 3; // less than or equal (N&~V)|(~N&V)|Z | |
| 127 | flags |= (((n8&v8&~z8)|(~n8&~v8&~z8)) & 1) << 2; // greater than (N&V&~Z)|(~N&~V&~Z) | |
| 128 | flags |= ((~z8) & 1) << 1; // not equal (~Z) | |
| 129 | flags |= ((z8) & 1) << 0; // equal (Z) | |
| 130 | 130 | |
| 131 | 131 | return flags; |
| 132 | 132 | } |
| r25360 | r25361 | |
| 138 | 138 | |
| 139 | 139 | switch (vector_ls_bits) |
| 140 | 140 | { |
| 141 | case 0x01: | |
| 141 | case 0x01: // vst.s | |
| 142 | 142 | { |
| 143 | 143 | m_program->write_dword(m_outp, m_reg[rd]); |
| 144 | 144 | m_outp += 4; |
| 145 | 145 | break; |
| 146 | 146 | } |
| 147 | case 0x03: | |
| 147 | case 0x03: // vst.d | |
| 148 | 148 | { |
| 149 | 149 | UINT64 data = m_fpair[rd >> 1]; |
| 150 | 150 | m_program->write_qword(m_outp, data); |
| 151 | 151 | m_outp += 8; |
| 152 | 152 | break; |
| 153 | 153 | } |
| 154 | case 0x04: | |
| 154 | case 0x04: // vld0.s | |
| 155 | 155 | { |
| 156 | 156 | m_reg[rd] = m_program->read_dword(m_in0p); |
| 157 | 157 | m_in0p += 4; |
| 158 | 158 | break; |
| 159 | 159 | } |
| 160 | case 0x05: | |
| 160 | case 0x05: // vld1.s | |
| 161 | 161 | { |
| 162 | 162 | m_reg[rd] = m_program->read_dword(m_in1p); |
| 163 | 163 | m_in1p += 4; |
| 164 | 164 | break; |
| 165 | 165 | } |
| 166 | case 0x06: | |
| 166 | case 0x06: // vld0.d | |
| 167 | 167 | { |
| 168 | 168 | m_fpair[rd >> 1] = m_program->read_qword(m_in0p); |
| 169 | 169 | m_in0p += 8; |
| 170 | 170 | break; |
| 171 | 171 | } |
| 172 | case 0x07: | |
| 172 | case 0x07: // vld1.d | |
| 173 | 173 | { |
| 174 | 174 | m_fpair[rd >> 1] = m_program->read_qword(m_in1p); |
| 175 | 175 | m_in1p += 8; |
| r25360 | r25361 | |
| 186 | 186 | { |
| 187 | 187 | switch ((m_ir >> 15) & 0x7f) |
| 188 | 188 | { |
| 189 | case 0x02: | |
| 189 | case 0x02: // cmnd | |
| 190 | 190 | { |
| 191 | 191 | UINT32 data = OP_UIMM15(); |
| 192 | 192 | |
| r25360 | r25361 | |
| 220 | 220 | break; |
| 221 | 221 | } |
| 222 | 222 | |
| 223 | case 0x06: | |
| 223 | case 0x06: // brcr | |
| 224 | 224 | { |
| 225 | 225 | int cr = OP_UIMM15(); |
| 226 | 226 | |
| r25360 | r25361 | |
| 233 | 233 | UINT32 data = read_creg(cr); |
| 234 | 234 | |
| 235 | 235 | m_fetchpc = data & ~3; |
| 236 | m_ie = (m_ie & ~1) | (data & 1); | |
| 236 | m_ie = (m_ie & ~1) | (data & 1); // global interrupt mask from creg | |
| 237 | 237 | // TODO: user/supervisor latch from creg |
| 238 | 238 | } |
| 239 | 239 | break; |
| 240 | 240 | } |
| 241 | 241 | |
| 242 | case 0x08: | |
| 242 | case 0x08: // shift.dz | |
| 243 | 243 | { |
| 244 | 244 | int r = (m_ir & (1 << 10)); |
| 245 | 245 | int inv = (m_ir & (1 << 11)); |
| r25360 | r25361 | |
| 251 | 251 | UINT32 endmask = SHIFT_MASK[end ? end : 32]; |
| 252 | 252 | if (inv) endmask = ~endmask; |
| 253 | 253 | |
| 254 | UINT32 compmask = endmask; | |
| 254 | UINT32 compmask = endmask; // shiftmask == 0xffffffff | |
| 255 | 255 | |
| 256 | 256 | UINT32 res = 0; |
| 257 | if (r) | |
| 257 | if (r) // right | |
| 258 | 258 | { |
| 259 | 259 | res = ROTATE_R(source, rot) & compmask; |
| 260 | 260 | } |
| 261 | else | |
| 261 | else // left | |
| 262 | 262 | { |
| 263 | 263 | res = ROTATE_L(source, rot) & compmask; |
| 264 | 264 | } |
| r25360 | r25361 | |
| 268 | 268 | break; |
| 269 | 269 | } |
| 270 | 270 | |
| 271 | case 0x0a: | |
| 271 | case 0x0a: // shift.ds | |
| 272 | 272 | { |
| 273 | 273 | int r = (m_ir & (1 << 10)); |
| 274 | 274 | int inv = (m_ir & (1 << 11)); |
| r25360 | r25361 | |
| 280 | 280 | UINT32 endmask = SHIFT_MASK[end ? end : 32]; |
| 281 | 281 | if (inv) endmask = ~endmask; |
| 282 | 282 | |
| 283 | UINT32 compmask = endmask; | |
| 283 | UINT32 compmask = endmask; // shiftmask == 0xffffffff | |
| 284 | 284 | |
| 285 | 285 | UINT32 res = 0; |
| 286 | if (r) | |
| 286 | if (r) // right | |
| 287 | 287 | { |
| 288 | 288 | res = ROTATE_R(source, rot) & compmask; |
| 289 | 289 | res = SIGN_EXTEND(res, rot); |
| 290 | 290 | } |
| 291 | else | |
| 291 | else // left | |
| 292 | 292 | { |
| 293 | 293 | res = ROTATE_L(source, rot) & compmask; |
| 294 | 294 | // sign extend makes no sense to left.. |
| r25360 | r25361 | |
| 299 | 299 | break; |
| 300 | 300 | } |
| 301 | 301 | |
| 302 | case 0x0b: | |
| 302 | case 0x0b: // shift.ez | |
| 303 | 303 | { |
| 304 | 304 | int r = (m_ir & (1 << 10)); |
| 305 | 305 | int inv = (m_ir & (1 << 11)); |
| r25360 | r25361 | |
| 330 | 330 | break; |
| 331 | 331 | } |
| 332 | 332 | |
| 333 | case 0x0c: | |
| 333 | case 0x0c: // shift.em | |
| 334 | 334 | { |
| 335 | 335 | int r = (m_ir & (1 << 10)); |
| 336 | 336 | int inv = (m_ir & (1 << 11)); |
| r25360 | r25361 | |
| 346 | 346 | UINT32 compmask = endmask & shiftmask; |
| 347 | 347 | |
| 348 | 348 | UINT32 res = 0; |
| 349 | if (r) | |
| 349 | if (r) // right | |
| 350 | 350 | { |
| 351 | 351 | res = (ROTATE_R(source, rot) & compmask) | (m_reg[rd] & ~compmask); |
| 352 | 352 | } |
| 353 | else | |
| 353 | else // left | |
| 354 | 354 | { |
| 355 | 355 | res = (ROTATE_L(source, rot) & compmask) | (m_reg[rd] & ~compmask); |
| 356 | 356 | } |
| r25360 | r25361 | |
| 360 | 360 | break; |
| 361 | 361 | } |
| 362 | 362 | |
| 363 | case 0x0d: | |
| 363 | case 0x0d: // shift.es | |
| 364 | 364 | { |
| 365 | 365 | int r = (m_ir & (1 << 10)); |
| 366 | 366 | int inv = (m_ir & (1 << 11)); |
| r25360 | r25361 | |
| 371 | 371 | |
| 372 | 372 | UINT32 endmask = SHIFT_MASK[end ? end : 32]; |
| 373 | 373 | if (inv) endmask = ~endmask; |
| 374 | ||
| 374 | ||
| 375 | 375 | int shift = r ? 32-rot : rot; |
| 376 | 376 | UINT32 shiftmask = SHIFT_MASK[shift ? shift : 32]; |
| 377 | 377 | UINT32 compmask = endmask & shiftmask; |
| 378 | 378 | |
| 379 | 379 | UINT32 res = 0; |
| 380 | if (r) | |
| 380 | if (r) // right | |
| 381 | 381 | { |
| 382 | 382 | res = ROTATE_R(source, rot) & compmask; |
| 383 | 383 | res = SIGN_EXTEND(res, rot); |
| 384 | 384 | } |
| 385 | else | |
| 385 | else // left | |
| 386 | 386 | { |
| 387 | 387 | res = ROTATE_L(source, rot) & compmask; |
| 388 | 388 | // sign extend makes no sense to left.. |
| r25360 | r25361 | |
| 393 | 393 | break; |
| 394 | 394 | } |
| 395 | 395 | |
| 396 | case 0x0e: | |
| 396 | case 0x0e: // shift.iz | |
| 397 | 397 | { |
| 398 | 398 | int r = (m_ir & (1 << 10)); |
| 399 | 399 | int inv = (m_ir & (1 << 11)); |
| r25360 | r25361 | |
| 423 | 423 | break; |
| 424 | 424 | } |
| 425 | 425 | |
| 426 | case 0x0f: | |
| 426 | case 0x0f: // shift.im | |
| 427 | 427 | { |
| 428 | 428 | int r = (m_ir & (1 << 10)); |
| 429 | 429 | int inv = (m_ir & (1 << 11)); |
| r25360 | r25361 | |
| 439 | 439 | UINT32 compmask = endmask & ~shiftmask; |
| 440 | 440 | |
| 441 | 441 | UINT32 res = 0; |
| 442 | if (r) | |
| 442 | if (r) // right | |
| 443 | 443 | { |
| 444 | 444 | res = (ROTATE_R(source, rot) & compmask) | (m_reg[rd] & ~compmask); |
| 445 | 445 | } |
| 446 | else | |
| 446 | else // left | |
| 447 | 447 | { |
| 448 | 448 | res = (ROTATE_L(source, rot) & compmask) | (m_reg[rd] & ~compmask); |
| 449 | 449 | } |
| r25360 | r25361 | |
| 453 | 453 | break; |
| 454 | 454 | } |
| 455 | 455 | |
| 456 | case 0x11: | |
| 456 | case 0x11: // and | |
| 457 | 457 | { |
| 458 | 458 | int rd = OP_RD(); |
| 459 | 459 | int rs = OP_RS(); |
| r25360 | r25361 | |
| 464 | 464 | break; |
| 465 | 465 | } |
| 466 | 466 | |
| 467 | case 0x14: | |
| 467 | case 0x14: // and.ft | |
| 468 | 468 | { |
| 469 | 469 | int rd = OP_RD(); |
| 470 | 470 | int rs = OP_RS(); |
| r25360 | r25361 | |
| 475 | 475 | break; |
| 476 | 476 | } |
| 477 | 477 | |
| 478 | case 0x17: | |
| 478 | case 0x17: // or | |
| 479 | 479 | { |
| 480 | 480 | int rd = OP_RD(); |
| 481 | 481 | int rs = OP_RS(); |
| r25360 | r25361 | |
| 486 | 486 | break; |
| 487 | 487 | } |
| 488 | 488 | |
| 489 | case 0x1d: | |
| 489 | case 0x1d: // or.ft | |
| 490 | 490 | { |
| 491 | 491 | int rd = OP_RD(); |
| 492 | 492 | int rs = OP_RS(); |
| r25360 | r25361 | |
| 498 | 498 | } |
| 499 | 499 | |
| 500 | 500 | case 0x24: |
| 501 | case 0x20: | |
| 501 | case 0x20: // ld.b | |
| 502 | 502 | { |
| 503 | 503 | int rd = OP_RD(); |
| 504 | 504 | int base = OP_BASE(); |
| r25360 | r25361 | |
| 517 | 517 | } |
| 518 | 518 | |
| 519 | 519 | case 0x25: |
| 520 | case 0x21: | |
| 520 | case 0x21: // ld.h | |
| 521 | 521 | { |
| 522 | 522 | int rd = OP_RD(); |
| 523 | 523 | int base = OP_BASE(); |
| r25360 | r25361 | |
| 536 | 536 | } |
| 537 | 537 | |
| 538 | 538 | case 0x26: |
| 539 | case 0x22: | |
| 539 | case 0x22: // ld | |
| 540 | 540 | { |
| 541 | 541 | int rd = OP_RD(); |
| 542 | 542 | int base = OP_BASE(); |
| r25360 | r25361 | |
| 554 | 554 | } |
| 555 | 555 | |
| 556 | 556 | case 0x27: |
| 557 | case 0x23: | |
| 557 | case 0x23: // ld.d | |
| 558 | 558 | { |
| 559 | 559 | int rd = OP_RD(); |
| 560 | 560 | int base = OP_BASE(); |
| r25360 | r25361 | |
| 576 | 576 | } |
| 577 | 577 | |
| 578 | 578 | case 0x28: |
| 579 | case 0x2c: | |
| 579 | case 0x2c: // ld.ub | |
| 580 | 580 | { |
| 581 | 581 | int rd = OP_RD(); |
| 582 | 582 | int base = OP_BASE(); |
| r25360 | r25361 | |
| 594 | 594 | } |
| 595 | 595 | |
| 596 | 596 | case 0x2d: |
| 597 | case 0x29: | |
| 597 | case 0x29: // ld.uh | |
| 598 | 598 | { |
| 599 | 599 | int rd = OP_RD(); |
| 600 | 600 | int base = OP_BASE(); |
| r25360 | r25361 | |
| 612 | 612 | } |
| 613 | 613 | |
| 614 | 614 | case 0x34: |
| 615 | case 0x30: | |
| 615 | case 0x30: // st.b | |
| 616 | 616 | { |
| 617 | 617 | int rd = OP_RD(); |
| 618 | 618 | int base = OP_BASE(); |
| r25360 | r25361 | |
| 629 | 629 | } |
| 630 | 630 | |
| 631 | 631 | case 0x35: |
| 632 | case 0x31: | |
| 632 | case 0x31: // st.h | |
| 633 | 633 | { |
| 634 | 634 | int rd = OP_RD(); |
| 635 | 635 | int base = OP_BASE(); |
| r25360 | r25361 | |
| 663 | 663 | } |
| 664 | 664 | |
| 665 | 665 | case 0x37: |
| 666 | case 0x33: | |
| 666 | case 0x33: // st.d | |
| 667 | 667 | { |
| 668 | 668 | int rd = OP_RD(); |
| 669 | 669 | int base = OP_BASE(); |
| r25360 | r25361 | |
| 679 | 679 | m_reg[base] = address; |
| 680 | 680 | break; |
| 681 | 681 | } |
| 682 | ||
| 683 | case 0x48: // bbz | |
| 682 | ||
| 683 | case 0x48: // bbz | |
| 684 | 684 | { |
| 685 | 685 | int bitnum = OP_BITNUM() ^ 0x1f; |
| 686 | 686 | INT32 offset = OP_SIMM15(); |
| r25360 | r25361 | |
| 698 | 698 | break; |
| 699 | 699 | } |
| 700 | 700 | |
| 701 | case 0x49: | |
| 701 | case 0x49: // bbz.a | |
| 702 | 702 | { |
| 703 | 703 | int bitnum = OP_BITNUM() ^ 0x1f; |
| 704 | 704 | INT32 offset = OP_SIMM15(); |
| r25360 | r25361 | |
| 711 | 711 | break; |
| 712 | 712 | } |
| 713 | 713 | |
| 714 | case 0x4a: | |
| 714 | case 0x4a: // bbo | |
| 715 | 715 | { |
| 716 | 716 | int bitnum = OP_BITNUM() ^ 0x1f; |
| 717 | 717 | INT32 offset = OP_SIMM15(); |
| r25360 | r25361 | |
| 742 | 742 | break; |
| 743 | 743 | } |
| 744 | 744 | |
| 745 | case 0x4c: | |
| 745 | case 0x4c: // bcnd | |
| 746 | 746 | { |
| 747 | 747 | INT32 offset = OP_SIMM15(); |
| 748 | 748 | int code = OP_RD(); |
| r25360 | r25361 | |
| 760 | 760 | break; |
| 761 | 761 | } |
| 762 | 762 | |
| 763 | case 0x4d: | |
| 763 | case 0x4d: // bcnd.a | |
| 764 | 764 | { |
| 765 | 765 | INT32 offset = OP_SIMM15(); |
| 766 | 766 | int code = OP_RD(); |
| r25360 | r25361 | |
| 784 | 784 | break; |
| 785 | 785 | } |
| 786 | 786 | |
| 787 | case 0x58: | |
| 787 | case 0x58: // add | |
| 788 | 788 | { |
| 789 | 789 | INT32 imm = OP_SIMM15(); |
| 790 | 790 | int rd = OP_RD(); |
| r25360 | r25361 | |
| 808 | 808 | break; |
| 809 | 809 | } |
| 810 | 810 | |
| 811 | case 0x5a: | |
| 811 | case 0x5a: // sub | |
| 812 | 812 | { |
| 813 | 813 | INT32 imm = OP_SIMM15(); |
| 814 | 814 | int rd = OP_RD(); |
| r25360 | r25361 | |
| 821 | 821 | break; |
| 822 | 822 | } |
| 823 | 823 | |
| 824 | case 0x5b: | |
| 824 | case 0x5b: // subu | |
| 825 | 825 | { |
| 826 | 826 | INT32 imm = OP_SIMM15(); |
| 827 | 827 | int rd = OP_RD(); |
| r25360 | r25361 | |
| 887 | 887 | break; |
| 888 | 888 | } |
| 889 | 889 | |
| 890 | case 0x1c: | |
| 890 | case 0x1c: // shift.iz | |
| 891 | 891 | { |
| 892 | 892 | int r = (m_ir & (1 << 10)); |
| 893 | 893 | int inv = (m_ir & (1 << 11)); |
| r25360 | r25361 | |
| 919 | 919 | } |
| 920 | 920 | |
| 921 | 921 | case 0x22: |
| 922 | case 0x23: | |
| 922 | case 0x23: // and | |
| 923 | 923 | { |
| 924 | 924 | int rd = OP_RD(); |
| 925 | 925 | int rs = OP_RS(); |
| r25360 | r25361 | |
| 943 | 943 | } |
| 944 | 944 | |
| 945 | 945 | case 0x2c: |
| 946 | case 0x2d: | |
| 946 | case 0x2d: // xor | |
| 947 | 947 | { |
| 948 | 948 | int rd = OP_RD(); |
| 949 | 949 | int rs = OP_RS(); |
| r25360 | r25361 | |
| 967 | 967 | case 0x40: |
| 968 | 968 | case 0x41: |
| 969 | 969 | case 0x48: |
| 970 | case 0x49: | |
| 970 | case 0x49: // ld.b | |
| 971 | 971 | { |
| 972 | 972 | int m = m_ir & (1 << 15); |
| 973 | 973 | |
| r25360 | r25361 | |
| 977 | 977 | UINT32 address = m_reg[base] + (has_imm ? imm32 : m_reg[OP_SRC1()]); |
| 978 | 978 | UINT32 r = m_program->read_byte(address); |
| 979 | 979 | if (r & 0x80) r |= 0xffffff00; |
| 980 | ||
| 980 | ||
| 981 | 981 | if (rd) |
| 982 | 982 | m_reg[rd] = r; |
| 983 | 983 | |
| r25360 | r25361 | |
| 989 | 989 | case 0x42: |
| 990 | 990 | case 0x4a: |
| 991 | 991 | case 0x43: |
| 992 | case 0x4b: | |
| 992 | case 0x4b: // ld.h | |
| 993 | 993 | { |
| 994 | 994 | int shift = (m_ir & (1 << 11)) ? 1 : 0; |
| 995 | 995 | int m = m_ir & (1 << 15); |
| r25360 | r25361 | |
| 1012 | 1012 | case 0x4c: |
| 1013 | 1013 | case 0x44: |
| 1014 | 1014 | case 0x4d: |
| 1015 | case 0x45: | |
| 1015 | case 0x45: // ld | |
| 1016 | 1016 | { |
| 1017 | 1017 | int shift = (m_ir & (1 << 11)) ? 2 : 0; |
| 1018 | 1018 | int m = m_ir & (1 << 15); |
| r25360 | r25361 | |
| 1033 | 1033 | case 0x4e: |
| 1034 | 1034 | case 0x4f: |
| 1035 | 1035 | case 0x46: |
| 1036 | case 0x47: | |
| 1036 | case 0x47: // ld.d | |
| 1037 | 1037 | { |
| 1038 | 1038 | int shift = (m_ir & (1 << 11)) ? 3 : 0; |
| 1039 | 1039 | int m = m_ir & (1 << 15); |
| r25360 | r25361 | |
| 1054 | 1054 | case 0x58: |
| 1055 | 1055 | case 0x59: |
| 1056 | 1056 | case 0x50: |
| 1057 | case 0x51: | |
| 1057 | case 0x51: // ld.ub | |
| 1058 | 1058 | { |
| 1059 | 1059 | int m = m_ir & (1 << 15); |
| 1060 | 1060 | int base = OP_BASE(); |
| r25360 | r25361 | |
| 1074 | 1074 | case 0x5a: |
| 1075 | 1075 | case 0x5b: |
| 1076 | 1076 | case 0x52: |
| 1077 | case 0x53: | |
| 1077 | case 0x53: // ld.uh | |
| 1078 | 1078 | { |
| 1079 | 1079 | int shift = (m_ir & (1 << 11)) ? 1 : 0; |
| 1080 | 1080 | int m = m_ir & (1 << 15); |
| r25360 | r25361 | |
| 1095 | 1095 | case 0x60: |
| 1096 | 1096 | case 0x61: |
| 1097 | 1097 | case 0x68: |
| 1098 | case 0x69: | |
| 1098 | case 0x69: // st.b | |
| 1099 | 1099 | { |
| 1100 | 1100 | int m = m_ir & (1 << 15); |
| 1101 | 1101 | |
| r25360 | r25361 | |
| 1112 | 1112 | case 0x62: |
| 1113 | 1113 | case 0x63: |
| 1114 | 1114 | case 0x6a: |
| 1115 | case 0x6b: | |
| 1115 | case 0x6b: // st.h | |
| 1116 | 1116 | { |
| 1117 | 1117 | int shift = (m_ir & (1 << 11)) ? 1 : 0; |
| 1118 | 1118 | int m = m_ir & (1 << 15); |
| r25360 | r25361 | |
| 1130 | 1130 | case 0x6c: |
| 1131 | 1131 | case 0x6d: |
| 1132 | 1132 | case 0x64: |
| 1133 | case 0x65: | |
| 1133 | case 0x65: // st | |
| 1134 | 1134 | { |
| 1135 | 1135 | int shift = (m_ir & (1 << 11)) ? 2 : 0; |
| 1136 | 1136 | int m = m_ir & (1 << 15); |
| r25360 | r25361 | |
| 1177 | 1177 | } |
| 1178 | 1178 | |
| 1179 | 1179 | case 0xa0: |
| 1180 | case 0xa1: | |
| 1180 | case 0xa1: // cmp | |
| 1181 | 1181 | { |
| 1182 | 1182 | int rd = OP_RD(); |
| 1183 | 1183 | UINT32 src1 = has_imm ? imm32 : m_reg[OP_SRC1()]; |
| r25360 | r25361 | |
| 1200 | 1200 | } |
| 1201 | 1201 | |
| 1202 | 1202 | case 0xb4: |
| 1203 | case 0xb5: | |
| 1203 | case 0xb5: // sub | |
| 1204 | 1204 | { |
| 1205 | 1205 | int rd = OP_RD(); |
| 1206 | 1206 | int rs = OP_RS(); |
| r25360 | r25361 | |
| 1213 | 1213 | } |
| 1214 | 1214 | |
| 1215 | 1215 | case 0xb6: |
| 1216 | case 0xb7: | |
| 1216 | case 0xb7: // subu | |
| 1217 | 1217 | { |
| 1218 | 1218 | int rd = OP_RD(); |
| 1219 | 1219 | int rs = OP_RS(); |
| r25360 | r25361 | |
| 1226 | 1226 | case 0xc4: |
| 1227 | 1227 | case 0xd4: |
| 1228 | 1228 | case 0xc5: |
| 1229 | case 0xd5: | |
| 1229 | case 0xd5: // vmpy | |
| 1230 | 1230 | { |
| 1231 | 1231 | int p1 = m_ir & (1 << 5); |
| 1232 | 1232 | int pd = m_ir & (1 << 7); |
| r25360 | r25361 | |
| 1262 | 1262 | case 0xc8: |
| 1263 | 1263 | case 0xd8: |
| 1264 | 1264 | case 0xc9: |
| 1265 | case 0xd9: | |
| 1265 | case 0xd9: // vrnd | |
| 1266 | 1266 | { |
| 1267 | 1267 | int acc = OP_ACC(); |
| 1268 | 1268 | int p1 = m_ir & (1 << 5); |
| r25360 | r25361 | |
| 1282 | 1282 | case 0: |
| 1283 | 1283 | m_reg[rd] = f2u((float)source); |
| 1284 | 1284 | break; |
| 1285 | case 1: | |
| 1285 | case 1: | |
| 1286 | 1286 | m_fpair[rd >> 1] = d2u(source); |
| 1287 | 1287 | break; |
| 1288 | 1288 | case 2: |
| r25360 | r25361 | |
| 1313 | 1313 | case 0xcc: |
| 1314 | 1314 | case 0xdc: |
| 1315 | 1315 | case 0xcd: |
| 1316 | case 0xdd: | |
| 1316 | case 0xdd: // vmac | |
| 1317 | 1317 | { |
| 1318 | 1318 | int acc = OP_ACC(); |
| 1319 | 1319 | int z = m_ir & (1 << 8); |
| r25360 | r25361 | |
| 1356 | 1356 | case 0xce: |
| 1357 | 1357 | case 0xde: |
| 1358 | 1358 | case 0xcf: |
| 1359 | case 0xdf: | |
| 1359 | case 0xdf: // vmsc | |
| 1360 | 1360 | { |
| 1361 | 1361 | int acc = OP_ACC(); |
| 1362 | 1362 | int z = m_ir & (1 << 8); |
| r25360 | r25361 | |
| 1397 | 1397 | } |
| 1398 | 1398 | |
| 1399 | 1399 | case 0xe0: |
| 1400 | case 0xe1: | |
| 1400 | case 0xe1: // fadd | |
| 1401 | 1401 | { |
| 1402 | 1402 | int rd = OP_RD(); |
| 1403 | 1403 | int rs = OP_RS(); |
| 1404 | 1404 | int src1 = OP_SRC1(); |
| 1405 | 1405 | int precision = (m_ir >> 5) & 0x3f; |
| 1406 | 1406 | |
| 1407 | if (rd) | |
| 1407 | if (rd) // only calculate if destination register is valid | |
| 1408 | 1408 | { |
| 1409 | 1409 | switch (precision) |
| 1410 | 1410 | { |
| 1411 | case 0x00: | |
| 1411 | case 0x00: // SP - SP -> SP | |
| 1412 | 1412 | { |
| 1413 | 1413 | float s1 = u2f(has_imm ? imm32 : m_reg[src1]); |
| 1414 | 1414 | float s2 = u2f(m_reg[rs]); |
| 1415 | 1415 | m_reg[rd] = f2u(s1 + s2); |
| 1416 | 1416 | break; |
| 1417 | 1417 | } |
| 1418 | case 0x10: | |
| 1418 | case 0x10: // SP - SP -> DP | |
| 1419 | 1419 | { |
| 1420 | 1420 | float s1 = u2f(has_imm ? imm32 : m_reg[src1]); |
| 1421 | 1421 | float s2 = u2f(m_reg[rs]); |
| r25360 | r25361 | |
| 1423 | 1423 | m_fpair[rd >> 1] = res; |
| 1424 | 1424 | break; |
| 1425 | 1425 | } |
| 1426 | case 0x14: | |
| 1426 | case 0x14: // SP - DP -> DP | |
| 1427 | 1427 | { |
| 1428 | 1428 | float s1 = u2f(has_imm ? imm32 : m_reg[src1]); |
| 1429 | 1429 | double s2 = u2d(m_fpair[rs >> 1]); |
| r25360 | r25361 | |
| 1431 | 1431 | m_fpair[rd >> 1] = res; |
| 1432 | 1432 | break; |
| 1433 | 1433 | } |
| 1434 | case 0x11: | |
| 1434 | case 0x11: // DP - SP -> DP | |
| 1435 | 1435 | { |
| 1436 | 1436 | double s1 = u2d(m_fpair[src1 >> 1]); |
| 1437 | 1437 | float s2 = u2f(m_reg[rs]); |
| r25360 | r25361 | |
| 1439 | 1439 | m_fpair[rd >> 1] = res; |
| 1440 | 1440 | break; |
| 1441 | 1441 | } |
| 1442 | case 0x15: | |
| 1442 | case 0x15: // DP - DP -> DP | |
| 1443 | 1443 | { |
| 1444 | 1444 | double s1 = u2d(m_fpair[src1 >> 1]); |
| 1445 | 1445 | double s2 = u2d(m_fpair[rs >> 1]); |
| r25360 | r25361 | |
| 1455 | 1455 | } |
| 1456 | 1456 | |
| 1457 | 1457 | case 0xe2: |
| 1458 | case 0xe3: | |
| 1458 | case 0xe3: // fsub | |
| 1459 | 1459 | { |
| 1460 | 1460 | int rd = OP_RD(); |
| 1461 | 1461 | int rs = OP_RS(); |
| 1462 | 1462 | int src1 = OP_SRC1(); |
| 1463 | 1463 | int precision = (m_ir >> 5) & 0x3f; |
| 1464 | 1464 | |
| 1465 | if (rd) | |
| 1465 | if (rd) // only calculate if destination register is valid | |
| 1466 | 1466 | { |
| 1467 | 1467 | switch (precision) |
| 1468 | 1468 | { |
| 1469 | case 0x00: | |
| 1469 | case 0x00: // SP - SP -> SP | |
| 1470 | 1470 | { |
| 1471 | 1471 | float s1 = u2f(has_imm ? imm32 : m_reg[src1]); |
| 1472 | 1472 | float s2 = u2f(m_reg[rs]); |
| 1473 | 1473 | m_reg[rd] = f2u(s1 - s2); |
| 1474 | 1474 | break; |
| 1475 | 1475 | } |
| 1476 | case 0x10: | |
| 1476 | case 0x10: // SP - SP -> DP | |
| 1477 | 1477 | { |
| 1478 | 1478 | float s1 = u2f(has_imm ? imm32 : m_reg[src1]); |
| 1479 | 1479 | float s2 = u2f(m_reg[rs]); |
| r25360 | r25361 | |
| 1481 | 1481 | m_fpair[rd >> 1] = res; |
| 1482 | 1482 | break; |
| 1483 | 1483 | } |
| 1484 | case 0x14: | |
| 1484 | case 0x14: // SP - DP -> DP | |
| 1485 | 1485 | { |
| 1486 | 1486 | float s1 = u2f(has_imm ? imm32 : m_reg[src1]); |
| 1487 | 1487 | double s2 = u2d(m_fpair[rs >> 1]); |
| r25360 | r25361 | |
| 1489 | 1489 | m_fpair[rd >> 1] = res; |
| 1490 | 1490 | break; |
| 1491 | 1491 | } |
| 1492 | case 0x11: | |
| 1492 | case 0x11: // DP - SP -> DP | |
| 1493 | 1493 | { |
| 1494 | 1494 | double s1 = u2d(m_fpair[src1 >> 1]); |
| 1495 | 1495 | float s2 = u2f(m_reg[rs]); |
| r25360 | r25361 | |
| 1497 | 1497 | m_fpair[rd >> 1] = res; |
| 1498 | 1498 | break; |
| 1499 | 1499 | } |
| 1500 | case 0x15: | |
| 1500 | case 0x15: // DP - DP -> DP | |
| 1501 | 1501 | { |
| 1502 | 1502 | double s1 = u2d(m_fpair[src1 >> 1]); |
| 1503 | 1503 | double s2 = u2d(m_fpair[rs >> 1]); |
| r25360 | r25361 | |
| 1513 | 1513 | } |
| 1514 | 1514 | |
| 1515 | 1515 | case 0xe4: |
| 1516 | case 0xe5: | |
| 1516 | case 0xe5: // fmpy | |
| 1517 | 1517 | { |
| 1518 | 1518 | int rd = OP_RD(); |
| 1519 | 1519 | int rs = OP_RS(); |
| 1520 | 1520 | int src1 = OP_SRC1(); |
| 1521 | 1521 | int precision = (m_ir >> 5) & 0x3f; |
| 1522 | 1522 | |
| 1523 | if (rd) | |
| 1523 | if (rd) // only calculate if destination register is valid | |
| 1524 | 1524 | { |
| 1525 | 1525 | switch (precision) |
| 1526 | 1526 | { |
| 1527 | case 0x00: | |
| 1527 | case 0x00: // SP x SP -> SP | |
| 1528 | 1528 | { |
| 1529 | 1529 | float s1 = u2f(has_imm ? imm32 : m_reg[src1]); |
| 1530 | 1530 | float s2 = u2f(m_reg[rs]); |
| 1531 | 1531 | m_reg[rd] = f2u(s1 * s2); |
| 1532 | 1532 | break; |
| 1533 | 1533 | } |
| 1534 | case 0x10: | |
| 1534 | case 0x10: // SP x SP -> DP | |
| 1535 | 1535 | { |
| 1536 | 1536 | float s1 = u2f(has_imm ? imm32 : m_reg[src1]); |
| 1537 | 1537 | float s2 = u2f(m_reg[rs]); |
| r25360 | r25361 | |
| 1539 | 1539 | m_fpair[rd >> 1] = res; |
| 1540 | 1540 | break; |
| 1541 | 1541 | } |
| 1542 | case 0x14: | |
| 1542 | case 0x14: // SP x DP -> DP | |
| 1543 | 1543 | { |
| 1544 | 1544 | float s1 = u2f(has_imm ? imm32 : m_reg[src1]); |
| 1545 | 1545 | double s2 = u2d(m_fpair[rs >> 1]); |
| r25360 | r25361 | |
| 1547 | 1547 | m_fpair[rd >> 1] = res; |
| 1548 | 1548 | break; |
| 1549 | 1549 | } |
| 1550 | case 0x11: | |
| 1550 | case 0x11: // DP x SP -> DP | |
| 1551 | 1551 | { |
| 1552 | 1552 | double s1 = u2d(m_fpair[src1 >> 1]); |
| 1553 | 1553 | float s2 = u2f(m_reg[rs]); |
| r25360 | r25361 | |
| 1555 | 1555 | m_fpair[rd >> 1] = res; |
| 1556 | 1556 | break; |
| 1557 | 1557 | } |
| 1558 | case 0x15: | |
| 1558 | case 0x15: // DP x DP -> DP | |
| 1559 | 1559 | { |
| 1560 | 1560 | double s1 = u2d(m_fpair[src1 >> 1]); |
| 1561 | 1561 | double s2 = u2d(m_fpair[rs >> 1]); |
| r25360 | r25361 | |
| 1563 | 1563 | m_fpair[rd >> 1] = res; |
| 1564 | 1564 | break; |
| 1565 | 1565 | } |
| 1566 | case 0x2a: | |
| 1566 | case 0x2a: // I x I -> I | |
| 1567 | 1567 | { |
| 1568 | 1568 | m_reg[rd] = (INT32)(m_reg[rs]) * (INT32)(has_imm ? imm32 : m_reg[OP_SRC1()]); |
| 1569 | 1569 | break; |
| 1570 | 1570 | } |
| 1571 | case 0x3f: | |
| 1571 | case 0x3f: // U x U -> U | |
| 1572 | 1572 | { |
| 1573 | 1573 | m_reg[rd] = (UINT32)(m_reg[rs]) * (UINT32)(has_imm ? imm32 : m_reg[OP_SRC1()]); |
| 1574 | 1574 | break; |
| r25360 | r25361 | |
| 1581 | 1581 | } |
| 1582 | 1582 | |
| 1583 | 1583 | case 0xe6: |
| 1584 | case 0xe7: | |
| 1584 | case 0xe7: // fdiv | |
| 1585 | 1585 | { |
| 1586 | 1586 | int rd = OP_RD(); |
| 1587 | 1587 | int p1 = m_ir & (1 << 5); |
| r25360 | r25361 | |
| 1606 | 1606 | } |
| 1607 | 1607 | |
| 1608 | 1608 | case 0xe8: |
| 1609 | case 0xe9: | |
| 1609 | case 0xe9: // frnd | |
| 1610 | 1610 | { |
| 1611 | 1611 | //int mode = (m_ir >> 7) & 3; |
| 1612 | 1612 | int p1 = (m_ir >> 5) & 3; |
| r25360 | r25361 | |
| 1654 | 1654 | } |
| 1655 | 1655 | break; |
| 1656 | 1656 | } |
| 1657 | ||
| 1657 | ||
| 1658 | 1658 | case 0xea: |
| 1659 | case 0xeb: | |
| 1659 | case 0xeb: // fcmp | |
| 1660 | 1660 | { |
| 1661 | 1661 | int rd = OP_RD(); |
| 1662 | 1662 | int p1 = m_ir & (1 << 5); |
| r25360 | r25361 | |
| 1689 | 1689 | } |
| 1690 | 1690 | |
| 1691 | 1691 | case 0xee: |
| 1692 | case 0xef: | |
| 1692 | case 0xef: // fsqrt | |
| 1693 | 1693 | { |
| 1694 | 1694 | int rd = OP_RD(); |
| 1695 | 1695 | int src1 = OP_SRC1(); |
| r25360 | r25361 | |
| 1709 | 1709 | break; |
| 1710 | 1710 | } |
| 1711 | 1711 | |
| 1712 | case 0xf2: | |
| 1712 | case 0xf2: // rmo | |
| 1713 | 1713 | { |
| 1714 | 1714 | UINT32 source = m_reg[OP_RS()]; |
| 1715 | 1715 | int rd = OP_RD(); |
| r25360 | r25361 | |
|---|---|---|
| 6 | 6 | static const char *REG_NAMES[128] = |
| 7 | 7 | { |
| 8 | 8 | // 0 - 15 |
| 9 | "a0", "a1", "a2", "a3", "a4", "???", "a6", "a7", | |
| 10 | "a8", "a9", "a10", "a11", "a12", "???", "a14", "a15", | |
| 9 | "a0", "a1", "a2", "a3", "a4", "???", "a6", "a7", | |
| 10 | "a8", "a9", "a10", "a11", "a12", "???", "a14", "a15", | |
| 11 | 11 | // 16 - 31 |
| 12 | "x0", "x1", "x2", "???", "???", "???", "???", "???", | |
| 13 | "x8", "x9", "x10", "???", "???", "???", "???", "???", | |
| 12 | "x0", "x1", "x2", "???", "???", "???", "???", "???", | |
| 13 | "x8", "x9", "x10", "???", "???", "???", "???", "???", | |
| 14 | 14 | // 32 - 47 |
| 15 | "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", | |
| 16 | "???", "sr", "mf", "???", "???", "???", "???", "???", | |
| 15 | "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", | |
| 16 | "???", "sr", "mf", "???", "???", "???", "???", "???", | |
| 17 | 17 | // 48 - 63 |
| 18 | "???", "???", "???", "???", "???", "???", "???", "???", | |
| 19 | "pc/call", "ipa/br", "ipe", "iprs", "inten", "intflg", "comm", "lctl", | |
| 18 | "???", "???", "???", "???", "???", "???", "???", "???", | |
| 19 | "pc/call", "ipa/br", "ipe", "iprs", "inten", "intflg", "comm", "lctl", | |
| 20 | 20 | // 64 - 79 |
| 21 | "???", "???", "???", "???", "???", "???", "???", "???", | |
| 22 | "???", "???", "???", "???", "???", "???", "???", "???", | |
| 21 | "???", "???", "???", "???", "???", "???", "???", "???", | |
| 22 | "???", "???", "???", "???", "???", "???", "???", "???", | |
| 23 | 23 | // 80 - 95 |
| 24 | "???", "???", "???", "???", "???", "???", "???", "???", | |
| 25 | "???", "???", "???", "???", "???", "???", "???", "???", | |
| 24 | "???", "???", "???", "???", "???", "???", "???", "???", | |
| 25 | "???", "???", "???", "???", "???", "???", "???", "???", | |
| 26 | 26 | // 96 - 111 |
| 27 | "lc0", "lc1", "lc2", "???", "lr0", "lr1", "lr2", "???", | |
| 28 | "lrse0", "lrse1", "lrse2", "???", "lrs0", "lrs1", "lrs2", "???", | |
| 27 | "lc0", "lc1", "lc2", "???", "lr0", "lr1", "lr2", "???", | |
| 28 | "lrse0", "lrse1", "lrse2", "???", "lrs0", "lrs1", "lrs2", "???", | |
| 29 | 29 | // 112 - 127 |
| 30 | "ls0", "ls1", "ls2", "???", "le0", "le1", "le2", "???", | |
| 31 | "???", "???", "???", "???", "tag0", "tag1", "tag2", "tag3" | |
| 30 | "ls0", "ls1", "ls2", "???", "le0", "le1", "le2", "???", | |
| 31 | "???", "???", "???", "???", "tag0", "tag1", "tag2", "tag3" | |
| 32 | 32 | }; |
| 33 | 33 | |
| 34 | 34 | static const char *CONDITION_CODES[16] = |
| 35 | 35 | { |
| 36 | "", "[p] ", "[ls] ", "[hi] ", | |
| 37 | "[lt] ", "[le] ", "[ge] ", "[gt] ", | |
| 38 | "[hs] ", "[lo] ", "[eq] ", "[ne] ", | |
| 39 | "[v] ", "[nv] ", "[n] ", "[nn] " | |
| 36 | "", "[p] ", "[ls] ", "[hi] ", | |
| 37 | "[lt] ", "[le] ", "[ge] ", "[gt] ", | |
| 38 | "[hs] ", "[lo] ", "[eq] ", "[ne] ", | |
| 39 | "[v] ", "[nv] ", "[n] ", "[nn] " | |
| 40 | 40 | }; |
| 41 | 41 | |
| 42 | 42 | static const char *TRANSFER_SIZE[4] = |
| r25360 | r25361 | |
| 103 | 103 | |
| 104 | 104 | switch (gmode) |
| 105 | 105 | { |
| 106 | case 0x00: | |
| 106 | case 0x00: // Format 7: Conditional DU || Conditional Move | |
| 107 | 107 | { |
| 108 | 108 | int dstbank = (op >> 18) & 0xf; |
| 109 | 109 | int srcbank = (op >> 6) & 0xf; |
| r25360 | r25361 | |
| 117 | 117 | b += sprintf(b, "%s = %s", REG_NAMES[dreg], REG_NAMES[sreg]); |
| 118 | 118 | break; |
| 119 | 119 | } |
| 120 | case 0x01: | |
| 120 | case 0x01: // Format 8: Conditional DU ||Conditional Field Move | |
| 121 | 121 | { |
| 122 | 122 | int dstbank = (op >> 18) & 0xf; |
| 123 | 123 | int src = (op >> 10) & 0x7; |
| 124 | 124 | int dst = (op >> 3) & 0x7; |
| 125 | 125 | int itm = (op >> 22) & 0x3; |
| 126 | 126 | int size = (op >> 7) & 0x3; |
| 127 | // | |
| 127 | // int e = (op & (1 << 9)); | |
| 128 | 128 | |
| 129 | 129 | int dreg = (dstbank << 3) | dst; |
| 130 | 130 | int sreg = (4 << 3) | src; |
| r25360 | r25361 | |
| 133 | 133 | b += sprintf(b, "%s = [%s%d]%s", REG_NAMES[dreg], TRANSFER_SIZE[size], itm, REG_NAMES[sreg]); |
| 134 | 134 | break; |
| 135 | 135 | } |
| 136 | case 0x02: case 0x03: | |
| 136 | case 0x02: case 0x03: // Format 10: Conditional Non-D Data Unit | |
| 137 | 137 | { |
| 138 | 138 | int as1bank = (op >> 6) & 0xf; |
| 139 | 139 | int adstbank = (op >> 18) & 0xf; |
| r25360 | r25361 | |
| 156 | 156 | } |
| 157 | 157 | default: |
| 158 | 158 | { |
| 159 | if (op & 0x4) | |
| 159 | if (op & 0x4) // Format 9: Conditional DU || Conditional Global | |
| 160 | 160 | { |
| 161 | 161 | int bank = (op >> 18) & 0xf; |
| 162 | 162 | int le = ((op >> 16) & 2) | ((op >> 9) & 1); |
| r25360 | r25361 | |
| 178 | 178 | case 3: b += sprintf(b, "%s = &%s%s", REG_NAMES[greg], TRANSFER_SIZE[size], format_address_mode(gmode, ga, s, gimx)); break; |
| 179 | 179 | } |
| 180 | 180 | } |
| 181 | else | |
| 181 | else // Format 5: Global (Long Offset) | |
| 182 | 182 | { |
| 183 | 183 | int bank = (op >> 18) & 0xf; |
| 184 | 184 | int le = ((op >> 16) & 2) | ((op >> 9) & 1); |
| r25360 | r25361 | |
| 194 | 194 | // sign extend offset |
| 195 | 195 | if (s && (offset & 0x4000)) |
| 196 | 196 | offset |= 0xffffc000; |
| 197 | ||
| 197 | ||
| 198 | 198 | switch (le) |
| 199 | 199 | { |
| 200 | 200 | case 0: b += sprintf(b, "&%s%s = %s", TRANSFER_SIZE[size], format_address_mode(gmode, ga, s, offset), REG_NAMES[greg]); break; |
| r25360 | r25361 | |
| 215 | 215 | |
| 216 | 216 | switch (mode) |
| 217 | 217 | { |
| 218 | case 0x00: | |
| 218 | case 0x00: // Format 2: Move || Local | |
| 219 | 219 | { |
| 220 | 220 | b += sprintf(b, "move||local <TODO>"); |
| 221 | 221 | break; |
| 222 | 222 | } |
| 223 | case 0x01: | |
| 223 | case 0x01: // Format 3: Field Move || Local | |
| 224 | 224 | { |
| 225 | 225 | b += sprintf(b, "field move||local <TODO>"); |
| 226 | 226 | break; |
| 227 | 227 | } |
| 228 | case 0x02: case 0x03: | |
| 228 | case 0x02: case 0x03: // Format 6: Non-D DU || Local | |
| 229 | 229 | { |
| 230 | 230 | int d = (op >> 32) & 0x7; |
| 231 | 231 | int s = (op & (1 << 28)); |
| r25360 | r25361 | |
| 245 | 245 | } |
| 246 | 246 | break; |
| 247 | 247 | } |
| 248 | case 0x10: case 0x11: case 0x12: case 0x13: | |
| 248 | case 0x10: case 0x11: case 0x12: case 0x13: // Format 4: Local (Long Offset) | |
| 249 | 249 | { |
| 250 | 250 | int d = (op >> 32) & 0x7; |
| 251 | 251 | int bank = (op >> 18) & 0xf; |
| r25360 | r25361 | |
| 277 | 277 | } |
| 278 | 278 | break; |
| 279 | 279 | } |
| 280 | case 0x14: case 0x15: case 0x16: case 0x17: | |
| 280 | case 0x14: case 0x15: case 0x16: case 0x17: // Format 1: Double Parallel | |
| 281 | 281 | case 0x18: case 0x19: case 0x1a: case 0x1b: |
| 282 | 282 | case 0x1c: case 0x1d: case 0x1e: case 0x1f: |
| 283 | 283 | { |
| r25360 | r25361 | |
| 329 | 329 | |
| 330 | 330 | static void format_alu_op(int aluop, int a, const char *dst_text, const char *a_text, const char *b_text, const char *c_text) |
| 331 | 331 | { |
| 332 | if (a) | |
| 332 | if (a) // arithmetic | |
| 333 | 333 | { |
| 334 | 334 | int bits = (aluop & 1) | ((aluop >> 1) & 2) | ((aluop >> 2) & 4) | ((aluop >> 3) & 8); |
| 335 | 335 | switch (bits) |
| 336 | 336 | { |
| 337 | case 1: print("%s = %s - %s<1<", dst_text, a_text, b_text); break; | |
| 338 | case 2: print("%s = %s + %s<0<", dst_text, a_text, b_text); break; | |
| 339 | case 3: print("%s = %s - %s", dst_text, a_text, c_text); break; | |
| 340 | case 4: print("%s = %s - %s>1>", dst_text, a_text, b_text); break; | |
| 341 | case 5: print("%s = %s - %s", dst_text, a_text, b_text); break; | |
| 342 | case 6: print("?"); break; | |
| 343 | case 7: print("%s = %s - %s>0>", dst_text, a_text, b_text); break; | |
| 344 | case 8: print("%s = %s + %s>0>", dst_text, a_text, b_text); break; | |
| 345 | case 9: print("?"); break; | |
| 346 | case 10: print("%s = %s + %s", dst_text, a_text, b_text); break; | |
| 347 | case 11: print("%s = %s + %s>1>", dst_text, a_text, b_text); break; | |
| 348 | case 12: print("%s = %s + %s", dst_text, a_text, c_text); break; | |
| 349 | case 13: print("%s = %s - %s<0<", dst_text, a_text, b_text); break; | |
| 350 | case 14: print("%s = %s + %s<1<", dst_text, a_text, b_text); break; | |
| 351 | case 15: print("%s = field %s + %s", dst_text, a_text, b_text); break; | |
| 337 | case 1: print("%s = %s - %s<1<", dst_text, a_text, b_text); break; | |
| 338 | case 2: print("%s = %s + %s<0<", dst_text, a_text, b_text); break; | |
| 339 | case 3: print("%s = %s - %s", dst_text, a_text, c_text); break; | |
| 340 | case 4: print("%s = %s - %s>1>", dst_text, a_text, b_text); break; | |
| 341 | case 5: print("%s = %s - %s", dst_text, a_text, b_text); break; | |
| 342 | case 6: print("?"); break; | |
| 343 | case 7: print("%s = %s - %s>0>", dst_text, a_text, b_text); break; | |
| 344 | case 8: print("%s = %s + %s>0>", dst_text, a_text, b_text); break; | |
| 345 | case 9: print("?"); break; | |
| 346 | case 10: print("%s = %s + %s", dst_text, a_text, b_text); break; | |
| 347 | case 11: print("%s = %s + %s>1>", dst_text, a_text, b_text); break; | |
| 348 | case 12: print("%s = %s + %s", dst_text, a_text, c_text); break; | |
| 349 | case 13: print("%s = %s - %s<0<", dst_text, a_text, b_text); break; | |
| 350 | case 14: print("%s = %s + %s<1<", dst_text, a_text, b_text); break; | |
| 351 | case 15: print("%s = field %s + %s", dst_text, a_text, b_text); break; | |
| 352 | 352 | } |
| 353 | 353 | } |
| 354 | else | |
| 354 | else // boolean | |
| 355 | 355 | { |
| 356 | 356 | switch (aluop) |
| 357 | 357 | { |
| 358 | case 0xaa: | |
| 358 | case 0xaa: // A & B & C | A & ~B & C | A & B & ~C | A & ~B & ~C = A | |
| 359 | 359 | print("%s = %s", dst_text, a_text); |
| 360 | 360 | break; |
| 361 | 361 | |
| 362 | case 0x55: | |
| 362 | case 0x55: // ~A & B & C | ~A & ~B & C | ~A & B & ~C | ~A & ~B & ~C = ~A | |
| 363 | 363 | print("%s = ~%s", dst_text, a_text); |
| 364 | 364 | break; |
| 365 | 365 | |
| 366 | case 0xcc: | |
| 366 | case 0xcc: // A & B & C | ~A & B & C | A & B & ~C | ~A & B & ~C = B | |
| 367 | 367 | print("%s = %s", dst_text, b_text); |
| 368 | 368 | break; |
| 369 | 369 | |
| 370 | case 0x33: | |
| 370 | case 0x33: // A & ~B & C | ~A & ~B & C | A & ~B & ~C | ~A & ~B & ~C = ~B | |
| 371 | 371 | print("%s = %s", dst_text, b_text); |
| 372 | 372 | break; |
| 373 | 373 | |
| 374 | case 0xf0: | |
| 374 | case 0xf0: // A & B & C | ~A & B & C | A & ~B & C | ~A & ~B & C = C | |
| 375 | 375 | print("%s = %s", dst_text, c_text); |
| 376 | 376 | break; |
| 377 | 377 | |
| 378 | case 0x0f: | |
| 378 | case 0x0f: // A & B & ~C | ~A & B & ~C | A & ~B & ~C | ~A & ~B & ~C = ~C | |
| 379 | 379 | print("%s = ~%s", dst_text, c_text); |
| 380 | 380 | break; |
| 381 | 381 | |
| 382 | case 0x80: | |
| 382 | case 0x80: // A & B & C | |
| 383 | 383 | print("%s = %s & %s & %s", dst_text, a_text, b_text, c_text); |
| 384 | 384 | break; |
| 385 | 385 | |
| 386 | case 0x88: | |
| 386 | case 0x88: // A & B & C | A & B & ~C = A & B | |
| 387 | 387 | print("%s = %s & %s", dst_text, a_text, b_text); |
| 388 | 388 | break; |
| 389 | 389 | |
| 390 | case 0xa0: | |
| 390 | case 0xa0: // A & B & C | A & ~B & C = A & C | |
| 391 | 391 | print("%s = %s & %s", dst_text, a_text, c_text); |
| 392 | 392 | break; |
| 393 | 393 | |
| 394 | case 0xc0: | |
| 394 | case 0xc0: // A & B & C | ~A & B & C = B & C | |
| 395 | 395 | print("%s = %s & %s", dst_text, b_text, c_text); |
| 396 | 396 | break; |
| 397 | 397 | |
| 398 | case 0xea: | |
| 398 | case 0xea: // A & B & C | ~A & B & C | A & ~B & C | | |
| 399 | 399 | // A & B & ~C | A & ~B & ~C = A | C |
| 400 | 400 | print("%s = %s | %s", dst_text, a_text, c_text); |
| 401 | 401 | break; |
| 402 | 402 | |
| 403 | case 0xee: | |
| 403 | case 0xee: // A & B & C | ~A & B & C | A & ~B & C | | |
| 404 | 404 | // A & B & ~C | ~A & B & ~C | A & ~B & ~C = A | B |
| 405 | 405 | print("%s = %s | %s", dst_text, a_text, b_text); |
| 406 | 406 | break; |
| 407 | 407 | |
| 408 | case 0x44: | |
| 408 | case 0x44: // ~A & B & C | ~A & B & ~C = ~A & B | |
| 409 | 409 | print("%s = ~%s & %s", dst_text, a_text, b_text); |
| 410 | 410 | break; |
| 411 | 411 | |
| r25360 | r25361 | |
| 420 | 420 | { |
| 421 | 421 | output = buffer; |
| 422 | 422 | UINT32 flags = 0; |
| 423 | ||
| 423 | ||
| 424 | 424 | UINT64 op = ((UINT64)(oprom[0]) << 56) | ((UINT64)(oprom[1]) << 48) | ((UINT64)(oprom[2]) << 40) | ((UINT64)(oprom[3]) << 32) | |
| 425 | 425 | ((UINT64)(oprom[4]) << 24) | ((UINT64)(oprom[5]) << 16) | ((UINT64)(oprom[6]) << 8) | ((UINT64)(oprom[7])); |
| 426 | 426 | |
| 427 | 427 | switch (op >> 60) |
| 428 | 428 | { |
| 429 | 429 | case 0x6: |
| 430 | case 0x7: | |
| 430 | case 0x7: // Six-operand | |
| 431 | 431 | { |
| 432 | 432 | print("A: six operand <TODO>"); |
| 433 | 433 | break; |
| r25360 | r25361 | |
| 452 | 452 | case 0x00: print("nop"); break; |
| 453 | 453 | case 0x02: print("eint"); break; |
| 454 | 454 | case 0x03: print("dint"); break; |
| 455 | default: print("<reserved>"); break; | |
| 455 | default: print("<reserved>"); break; | |
| 456 | 456 | } |
| 457 | 457 | |
| 458 | 458 | format_transfer(parallel_xfer); |
| r25360 | r25361 | |
| 467 | 467 | switch ((op >> 43) & 3) |
| 468 | 468 | { |
| 469 | 469 | case 0: |
| 470 | case 1: | |
| 470 | case 1: // Base set ALU (5-bit immediate) | |
| 471 | 471 | { |
| 472 | 472 | UINT64 parallel_xfer = (op & U64(0x0000007fffffffff)); |
| 473 | 473 | |
| r25360 | r25361 | |
| 545 | 545 | format_transfer(parallel_xfer); |
| 546 | 546 | break; |
| 547 | 547 | } |
| 548 | ||
| 549 | case 2: // Base set ALU (reg src2) | |
| 548 | ||
| 549 | case 2: // Base set ALU (reg src2) | |
| 550 | 550 | { |
| 551 | 551 | UINT64 parallel_xfer = (op & U64(0x0000007fffffffff)); |
| 552 | 552 | |
| r25360 | r25361 | |
| 625 | 625 | format_transfer(parallel_xfer); |
| 626 | 626 | break; |
| 627 | 627 | } |
| 628 | ||
| 629 | case 3: // Base set ALU (32-bit immediate) | |
| 628 | ||
| 629 | case 3: // Base set ALU (32-bit immediate) | |
| 630 | 630 | { |
| 631 | 631 | int dst = (op >> 48) & 7; |
| 632 | 632 | int src1 = (op >> 45) & 7; |
| r25360 | r25361 | |
| 709 | 709 | CPU_DISASSEMBLE(tms32082_pp) |
| 710 | 710 | { |
| 711 | 711 | return tms32082_disasm_pp(buffer, pc, oprom); |
| 712 | } | |
| No newline at end of file | ||
| 712 | } |
| r25360 | r25361 | |
|---|---|---|
| 711 | 711 | case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &nec_state->icount; break; |
| 712 | 712 | |
| 713 | 713 | /* --- the following bits of info are returned as NULL-terminated strings --- */ |
| 714 | case CPUINFO_STR_NAME: strcpy(info->s, "NEC"); break; | |
| 714 | case CPUINFO_STR_NAME: strcpy(info->s, "NEC"); break; | |
| 715 | 715 | case CPUINFO_STR_FAMILY: strcpy(info->s, "NEC V-Series"); break; |
| 716 | 716 | case CPUINFO_STR_VERSION: strcpy(info->s, "2.0"); break; |
| 717 | 717 | case CPUINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; |
| r25360 | r25361 | |
|---|---|---|
| 1564 | 1564 | } |
| 1565 | 1565 | } while( m_icount > 0 ); |
| 1566 | 1566 | } |
| 1567 |
| r25360 | r25361 | |
|---|---|---|
| 264 | 264 | extern CPU_DISASSEMBLE( lh5801 ); |
| 265 | 265 | return CPU_DISASSEMBLE_NAME(lh5801)(this, buffer, pc, oprom, opram, options); |
| 266 | 266 | } |
| 267 |
| r25360 | r25361 | |
|---|---|---|
| 168 | 168 | instr_latch = 0; |
| 169 | 169 | ram_sel = 0; |
| 170 | 170 | host_control = 0; |
| 171 | ||
| 171 | ||
| 172 | 172 | pc = 0; |
| 173 | 173 | memset(&alu, 0, sizeof(alu)); |
| 174 | 174 | memset(&mulacc, 0, sizeof(mulacc)); |
| r25360 | r25361 | |
| 606 | 606 | is_written[i] = is_read[i] = false; |
| 607 | 607 | name[i][0] = '\0'; |
| 608 | 608 | } |
| 609 | ||
| 609 | ||
| 610 | 610 | for (addr = 0; addr < 0xa0; addr++) { |
| 611 | 611 | DESCRIBE_INSTR(buf, instr[addr], gpr[addr], NULL, NULL, NULL, NULL); |
| 612 | 612 | UINT64 inst = instr[addr]; |
| r25360 | r25361 | |
| 621 | 621 | } |
| 622 | 622 | |
| 623 | 623 | UINT8 operandSelect = (UINT8)((inst >> 8) & 0x0f); |
| 624 | const op_select_t &opSelect = OPERAND_SELECT[operandSelect]; | |
| 624 | const op_select_t &opSelect = OPERAND_SELECT[operandSelect]; | |
| 625 | 625 | |
| 626 | 626 | if (opSelect.mac_src == SRC_DST_REG) { |
| 627 | 627 | is_read[cReg] = true; |
| r25360 | r25361 | |
| 630 | 630 | if (opSelect.mac_dst != SRC_DST_DELAY) { // either REG or BOTH |
| 631 | 631 | is_written[cReg] = true; |
| 632 | 632 | } |
| 633 | ||
| 633 | ||
| 634 | 634 | alu_op_t aluOp = ALU_OPS[alu_op]; |
| 635 | 635 | if (aluOp.operands == 1) { |
| 636 | 636 | if (opSelect.alu_src == SRC_DST_REG) { |
| r25360 | r25361 | |
| 663 | 663 | for (int i = 0xc0; i < 0x100; i++) { |
| 664 | 664 | name[i][0] = 0; |
| 665 | 665 | } |
| 666 | ||
| 666 | ||
| 667 | 667 | for (addr = 0; addr < 0xa0; addr++) { |
| 668 | 668 | UINT8 aReg = (UINT8)((instr[addr] >> 16) & 0xff); |
| 669 | 669 | UINT8 bReg = (UINT8)((instr[addr] >> 24) & 0xff); |
| r25360 | r25361 | |
| 830 | 830 | // *** T2, clock high |
| 831 | 831 | |
| 832 | 832 | LOG_EXEC(("- T2.1\n")); |
| 833 | ||
| 833 | ||
| 834 | 834 | // --- Write ALU Result N-1 |
| 835 | 835 | LOG_EXEC((". write ALU:\n")); |
| 836 | 836 | if (alu.write_result) { |
| r25360 | r25361 | |
|---|---|---|
| 152 | 152 | INT16 ser2l; |
| 153 | 153 | INT16 ser3r; |
| 154 | 154 | INT16 ser3l; |
| 155 | INT64 machl; // 48 bits, right justified and sign extended | |
| 156 | bool mac_overflow; // whether reading the MAC register should return a saturated replacement value | |
| 155 | INT64 machl; // 48 bits, right justified and sign extended | |
| 156 | bool mac_overflow; // whether reading the MAC register should return a saturated replacement value | |
| 157 | 157 | INT32 dil; |
| 158 | 158 | INT32 memsiz; |
| 159 | 159 | INT32 memmask; |
| r25360 | r25361 | |
| 165 | 165 | INT32 dbase; |
| 166 | 166 | INT32 sigreg; |
| 167 | 167 | int mulshift; |
| 168 | INT8 ccr; // really, 5 bits, left justified | |
| 169 | INT8 cmr; // really, 6 bits, left justified | |
| 168 | INT8 ccr; // really, 5 bits, left justified | |
| 169 | INT8 cmr; // really, 6 bits, left justified | |
| 170 | 170 | INT32 dol[2]; |
| 171 | 171 | int dol_count; |
| 172 | 172 |
| r25360 | r25361 | |
|---|---|---|
| 4781 | 4781 | /* --- the following bits of info are returned as NULL-terminated strings --- */ |
| 4782 | 4782 | case CPUINFO_STR_NAME: strcpy(info->s, TMS99XX_device_get_name); break; |
| 4783 | 4783 | case CPUINFO_STR_SHORTNAME: strcpy(info->s, TMS99XX_device_get_shortname); break; |
| 4784 | ||
| 4784 | ||
| 4785 | 4785 | case CPUINFO_STR_FAMILY: strcpy(info->s, "Texas Instruments 9900L"); break; |
| 4786 | 4786 | case CPUINFO_STR_VERSION: strcpy(info->s, "2.0"); break; |
| 4787 | 4787 | case CPUINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; |
| r25360 | r25361 | |
|---|---|---|
| 2506 | 2506 | extern CPU_DISASSEMBLE( ds5002fp ); |
| 2507 | 2507 | return CPU_DISASSEMBLE_NAME(ds5002fp)(this, buffer, pc, oprom, opram, options); |
| 2508 | 2508 | } |
| 2509 |
| r25360 | r25361 | |
|---|---|---|
| 3897 | 3897 | { |
| 3898 | 3898 | UINT32 ea = M68KMAKE_GET_EA_AY_8; |
| 3899 | 3899 | |
| 3900 | if(CPU_TYPE_IS_010_LESS((mc68kcpu)->cpu_type)) | |
| 3900 | if(CPU_TYPE_IS_010_LESS((mc68kcpu)->cpu_type)) | |
| 3901 | 3901 | { |
| 3902 | m68ki_read_8((mc68kcpu), ea); | |
| 3902 | m68ki_read_8((mc68kcpu), ea); /* the 68000 (and 010?) does a dummy read, the value is discarded */ | |
| 3903 | 3903 | } |
| 3904 | 3904 | |
| 3905 | 3905 | m68ki_write_8((mc68kcpu), ea, 0); |
| r25360 | r25361 | |
| 3926 | 3926 | { |
| 3927 | 3927 | UINT32 ea = M68KMAKE_GET_EA_AY_16; |
| 3928 | 3928 | |
| 3929 | if(CPU_TYPE_IS_010_LESS((mc68kcpu)->cpu_type)) | |
| 3929 | if(CPU_TYPE_IS_010_LESS((mc68kcpu)->cpu_type)) | |
| 3930 | 3930 | { |
| 3931 | m68ki_read_16((mc68kcpu), ea); | |
| 3931 | m68ki_read_16((mc68kcpu), ea); /* the 68000 (and 010?) does a dummy read, the value is discarded */ | |
| 3932 | 3932 | } |
| 3933 | 3933 | |
| 3934 | 3934 | m68ki_write_16((mc68kcpu), ea, 0); |
| r25360 | r25361 | |
| 3955 | 3955 | { |
| 3956 | 3956 | UINT32 ea = M68KMAKE_GET_EA_AY_32; |
| 3957 | 3957 | |
| 3958 | if(CPU_TYPE_IS_010_LESS((mc68kcpu)->cpu_type)) | |
| 3958 | if(CPU_TYPE_IS_010_LESS((mc68kcpu)->cpu_type)) | |
| 3959 | 3959 | { |
| 3960 | m68ki_read_32((mc68kcpu), ea); | |
| 3960 | m68ki_read_32((mc68kcpu), ea); /* the 68000 (and 010?) does a dummy read, the value is discarded */ | |
| 3961 | 3961 | } |
| 3962 | 3962 | |
| 3963 | 3963 | m68ki_write_32((mc68kcpu), ea, 0); |
| r25360 | r25361 | |
|---|---|---|
| 161 | 161 | address_space *m_program; |
| 162 | 162 | address_space *m_io; |
| 163 | 163 | UINT32 m_stopped; /* Sets how the CPU is stopped */ |
| 164 | ||
| 164 | ||
| 165 | 165 | // on-board peripheral stuff |
| 166 | 166 | UINT8 m_m37710_regs[128]; |
| 167 | 167 | attotime m_reload[8]; |
| r25360 | r25361 | |
|---|---|---|
| 96 | 96 | m_fifo_read_cb.resolve_safe(0); |
| 97 | 97 | m_fifo_read_ok_cb.resolve_safe(0); |
| 98 | 98 | m_fifo_write_cb.resolve_safe(); |
| 99 | ||
| 99 | ||
| 100 | 100 | m_program = &space(AS_PROGRAM); |
| 101 | 101 | m_direct = &m_program->direct(); |
| 102 | 102 | |
| r25360 | r25361 | |
| 1582 | 1582 | } |
| 1583 | 1583 | } |
| 1584 | 1584 | } |
| 1585 |
| r25360 | r25361 | |
|---|---|---|
| 3934 | 3934 | /* --- the following bits of info are returned as NULL-terminated strings --- */ |
| 3935 | 3935 | case CPUINFO_STR_NAME: strcpy(info->s, "R4700 (little) DRC"); break; |
| 3936 | 3936 | case CPUINFO_STR_SHORTNAME: strcpy(info->s, "r4700le_drc"); break; |
| 3937 | ||
| 3937 | ||
| 3938 | 3938 | /* --- everything else is handled generically --- */ |
| 3939 | 3939 | default: CPU_GET_INFO_CALL(mips3); break; |
| 3940 | 3940 | } |
| r25360 | r25361 | |
| 4124 | 4124 | |
| 4125 | 4125 | DEFINE_LEGACY_CPU_DEVICE(RM7000BE_DRC, rm7000be_drc); |
| 4126 | 4126 | DEFINE_LEGACY_CPU_DEVICE(RM7000LE_DRC, rm7000le_drc); |
| 4127 |
| r25360 | r25361 | |
|---|---|---|
| 1133 | 1133 | extern CPU_DISASSEMBLE( i8085 ); |
| 1134 | 1134 | return CPU_DISASSEMBLE_NAME(i8085)(this, buffer, pc, oprom, opram, options); |
| 1135 | 1135 | } |
| 1136 |
| r25360 | r25361 | |
|---|---|---|
| 2 | 2 | |
| 3 | 3 | Intel 8089 I/O Processor |
| 4 | 4 | |
| 5 | ||
| 5 | Opcode implementations | |
| 6 | 6 | |
| 7 | 7 | ***************************************************************************/ |
| 8 | 8 |
| r25360 | r25361 | |
|---|---|---|
| 121 | 121 | SOC, |
| 122 | 122 | DIVIDER1, |
| 123 | 123 | CH1_GA, CH1_GB, CH1_GC, |
| 124 | CH1_TP, CH1_BC, CH1_IX, | |
| 125 | CH1_CC, CH1_MC, CH1_CP, | |
| 126 | CH1_PP, CH1_PSW, | |
| 124 | CH1_TP, CH1_BC, CH1_IX, | |
| 125 | CH1_CC, CH1_MC, CH1_CP, | |
| 126 | CH1_PP, CH1_PSW, | |
| 127 | 127 | DIVIDER2, |
| 128 | CH2_GA, CH2_GB, CH2_GC, | |
| 129 | CH2_TP, CH2_BC, CH2_IX, | |
| 130 | CH2_CC, CH2_MC, CH2_CP, | |
| 131 | CH2_PP, CH2_PSW | |
| 128 | CH2_GA, CH2_GB, CH2_GC, | |
| 129 | CH2_TP, CH2_BC, CH2_IX, | |
| 130 | CH2_CC, CH2_MC, CH2_CP, | |
| 131 | CH2_PP, CH2_PSW | |
| 132 | 132 | }; |
| 133 | 133 | |
| 134 | 134 | // system configuration |
| r25360 | r25361 | |
|---|---|---|
| 19 | 19 | #define VERBOSE_DMA 1 |
| 20 | 20 | |
| 21 | 21 | // channel control register fields |
| 22 | #define CC_TMC ((m_r[CC].w >> 0) & 0x07) // terminate on masked compare | |
| 23 | #define CC_TBC ((m_r[CC].w >> 3) & 0x03) // terminate on byte count | |
| 24 | #define CC_TX ((m_r[CC].w >> 5) & 0x03) // terminate on external signal | |
| 25 | #define CC_TS ((m_r[CC].w >> 7) & 0x01) // terminate on single transfer | |
| 26 | #define CC_CHAIN ((m_r[CC].w >> 8) & 0x01) // chaining | |
| 27 | #define CC_LOCK ((m_r[CC].w >> 9) & 0x01) // actuate lock | |
| 28 | #define CC_SOURCE ((m_r[CC].w >> 10) & 0x01) // source register | |
| 29 | #define CC_SYNC ((m_r[CC].w >> 11) & 0x03) // synchronization | |
| 30 | #define CC_TRANS ((m_r[CC].w >> 13) & 0x01) // translation | |
| 31 | #define CC_FUNC ((m_r[CC].w >> 14) & 0x03) // function | |
| 22 | #define CC_TMC ((m_r[CC].w >> 0) & 0x07) // terminate on masked compare | |
| 23 | #define CC_TBC ((m_r[CC].w >> 3) & 0x03) // terminate on byte count | |
| 24 | #define CC_TX ((m_r[CC].w >> 5) & 0x03) // terminate on external signal | |
| 25 | #define CC_TS ((m_r[CC].w >> 7) & 0x01) // terminate on single transfer | |
| 26 | #define CC_CHAIN ((m_r[CC].w >> 8) & 0x01) // chaining | |
| 27 | #define CC_LOCK ((m_r[CC].w >> 9) & 0x01) // actuate lock | |
| 28 | #define CC_SOURCE ((m_r[CC].w >> 10) & 0x01) // source register | |
| 29 | #define CC_SYNC ((m_r[CC].w >> 11) & 0x03) // synchronization | |
| 30 | #define CC_TRANS ((m_r[CC].w >> 13) & 0x01) // translation | |
| 31 | #define CC_FUNC ((m_r[CC].w >> 14) & 0x03) // function | |
| 32 | 32 | |
| 33 | 33 | |
| 34 | 34 | //************************************************************************** |
| r25360 | r25361 | |
|---|---|---|
| 367 | 367 | m_SB.d = 0; |
| 368 | 368 | m_B.d = 0; |
| 369 | 369 | } |
| 370 |
| r25360 | r25361 | |
|---|---|---|
| 2077 | 2077 | |
| 2078 | 2078 | void i960_cpu_device::state_string_export(const device_state_entry &entry, astring &string) |
| 2079 | 2079 | { |
| 2080 | ||
| 2081 | 2080 | static const char *const conditions[8] = |
| 2082 | 2081 | { |
| 2083 | 2082 | "no", "g", "e", "ge", "l", "ne", "le", "o" |
| r25360 | r25361 | |
| 2116 | 2115 | extern CPU_DISASSEMBLE( i960 ); |
| 2117 | 2116 | return CPU_DISASSEMBLE_NAME(i960)(this, buffer, pc, oprom, opram, options); |
| 2118 | 2117 | } |
| 2119 |
| r25360 | r25361 | |
|---|---|---|
| 726 | 726 | ifneq ($(filter I8089,$(CPUS)),) |
| 727 | 727 | OBJDIRS += $(CPUOBJ)/i8089 |
| 728 | 728 | CPUOBJS += $(CPUOBJ)/i8089/i8089.o \ |
| 729 | $(CPUOBJ)/i8089/i8089_channel.o \ | |
| 730 | $(CPUOBJ)/i8089/i8089_ops.o | |
| 729 | $(CPUOBJ)/i8089/i8089_channel.o \ | |
| 730 | $(CPUOBJ)/i8089/i8089_ops.o | |
| 731 | 731 | DASMOBJS += $(CPUOBJ)/i8089/i8089_dasm.o |
| 732 | 732 | endif |
| 733 | 733 |
| r25360 | r25361 | |
|---|---|---|
| 50 | 50 | downcast<i8275x_device *>(device)->set_drq_callback(DEVCB2_##_drq); |
| 51 | 51 | |
| 52 | 52 | #define MCFG_I8275_IRQ_CALLBACK(_irq) \ |
| 53 | downcast<i8275x_device *>(device)->set_irq_callback(DEVCB2_##_irq); \ | |
| 54 | ||
| 53 | downcast<i8275x_device *>(device)->set_irq_callback(DEVCB2_##_irq); | |
| 55 | 54 | #define MCFG_I8275_HRTC_CALLBACK(_hrtc) \ |
| 56 | downcast<i8275x_device *>(device)->set_hrtc_callback(DEVCB2_##_hrtc); \ | |
| 57 | ||
| 55 | downcast<i8275x_device *>(device)->set_hrtc_callback(DEVCB2_##_hrtc); | |
| 58 | 56 | #define MCFG_I8275_VRTC_CALLBACK(_vrtc) \ |
| 59 | 57 | downcast<i8275x_device *>(device)->set_vrtc_callback(DEVCB2_##_vrtc); |
| 60 | 58 |
| r25360 | r25361 | |
|---|---|---|
| 59 | 59 | }; |
| 60 | 60 | |
| 61 | 61 | |
| 62 | class i8275_device : | |
| 62 | class i8275_device : public device_t, | |
| 63 | 63 | public device_video_interface, |
| 64 | 64 | public i8275_interface |
| 65 | 65 | { |
| r25360 | r25361 | |
|---|---|---|
| 62 | 62 | |
| 63 | 63 | |
| 64 | 64 | huc6260_device::huc6260_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 65 | : | |
| 65 | : device_t(mconfig, HUC6260, "HuC6260", tag, owner, clock, "huc6260", __FILE__), | |
| 66 | 66 | device_video_interface(mconfig, *this) |
| 67 | 67 | { |
| 68 | 68 | } |
| r25360 | r25361 | |
|---|---|---|
| 48 | 48 | virtual void device_config_complete(); |
| 49 | 49 | virtual void device_start(); |
| 50 | 50 | virtual void device_reset(); |
| 51 | ||
| 51 | ||
| 52 | 52 | private: |
| 53 | 53 | // internal state |
| 54 | 54 | UINT16 * m_ram; |
| r25360 | r25361 | |
| 64 | 64 | INT16 m_cpx, m_cpy; |
| 65 | 65 | |
| 66 | 66 | int m_regno; |
| 67 | ||
| 67 | ||
| 68 | 68 | void doclr16( int opcode, UINT16 fill, int *dst, INT16 _ax, INT16 _ay ); |
| 69 | 69 | void docpy16( int opcode, int src, int *dst, INT16 _ax, INT16 _ay ); |
| 70 | 70 | int org_first_pixel( int _org_dpd ); |
| r25360 | r25361 | |
| 76 | 76 | void line( INT16 sx, INT16 sy, INT16 ex, INT16 ey, INT16 col ); |
| 77 | 77 | void circle( INT16 sx, INT16 sy, UINT16 r, INT16 col ); |
| 78 | 78 | void paint( int sx, int sy, int col ); |
| 79 | ||
| 79 | ||
| 80 | 80 | void command_w(UINT16 cmd); |
| 81 | ||
| 81 | ||
| 82 | 82 | }; |
| 83 | 83 | |
| 84 | 84 | extern ATTR_DEPRECATED const device_type HD63484; |
| r25360 | r25361 | |
|---|---|---|
| 76 | 76 | DECLARE_WRITE8_MEMBER( register_write ); |
| 77 | 77 | DECLARE_READ8_MEMBER( vcount_read ); |
| 78 | 78 | DECLARE_READ8_MEMBER( hcount_read ); |
| 79 | ||
| 79 | ||
| 80 | 80 | DECLARE_PALETTE_INIT( sega315_5124 ); |
| 81 | 81 | |
| 82 | 82 | void hcount_latch() { hcount_latch_at_hpos( m_screen->hpos() ); }; |
| r25360 | r25361 | |
|---|---|---|
| 55 | 55 | |
| 56 | 56 | // ======================> v99x8_device |
| 57 | 57 | |
| 58 | class v99x8_device : | |
| 58 | class v99x8_device : public device_t, | |
| 59 | 59 | public device_memory_interface, |
| 60 | 60 | public device_video_interface |
| 61 | 61 | { |
| r25360 | r25361 | |
| 77 | 77 | |
| 78 | 78 | DECLARE_READ8_MEMBER( read ); |
| 79 | 79 | DECLARE_WRITE8_MEMBER( write ); |
| 80 | ||
| 80 | ||
| 81 | 81 | DECLARE_PALETTE_INIT(v9938); |
| 82 | ||
| 82 | ||
| 83 | 83 | UINT8 vram_r(); |
| 84 | 84 | UINT8 status_r(); |
| 85 | 85 | void palette_w(UINT8 data); |
| r25360 | r25361 | |
| 245 | 245 | { |
| 246 | 246 | public: |
| 247 | 247 | v9938_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 248 | ||
| 248 | ||
| 249 | 249 | protected: |
| 250 | 250 | virtual machine_config_constructor device_mconfig_additions() const; |
| 251 | 251 | }; |
| r25360 | r25361 | |
| 254 | 254 | { |
| 255 | 255 | public: |
| 256 | 256 | v9958_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 257 | ||
| 258 | DECLARE_PALETTE_INIT(v9958); | |
| 259 | ||
| 257 | ||
| 258 | DECLARE_PALETTE_INIT(v9958); | |
| 259 | ||
| 260 | 260 | protected: |
| 261 | 261 | virtual machine_config_constructor device_mconfig_additions() const; |
| 262 | 262 | }; |
| r25360 | r25361 | |
|---|---|---|
| 38 | 38 | |
| 39 | 39 | |
| 40 | 40 | huc6261_device::huc6261_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 41 | : | |
| 41 | : device_t(mconfig, HUC6261, "HuC6261", tag, owner, clock, "huc6261", __FILE__), | |
| 42 | 42 | device_video_interface(mconfig, *this) |
| 43 | 43 | { |
| 44 | 44 | // Set up UV lookup table |
| r25360 | r25361 | |
|---|---|---|
| 249 | 249 | |
| 250 | 250 | // queue management |
| 251 | 251 | running_machine & m_machine; |
| 252 | screen_device * | |
| 252 | screen_device * m_screen; | |
| 253 | 253 | osd_work_queue * m_queue; // work queue |
| 254 | 254 | |
| 255 | 255 | // arrays |
| r25360 | r25361 | |
|---|---|---|
| 139 | 139 | save_item(NAME(m_cursor_enable)); |
| 140 | 140 | save_item(NAME(m_write_enable)); |
| 141 | 141 | save_item(NAME(m_digit_ram)); |
| 142 | ||
| 142 | ||
| 143 | 143 | m_update_func.resolve(m_update, *this); |
| 144 | 144 | } |
| 145 | 145 |
| r25360 | r25361 | |
|---|---|---|
| 189 | 189 | |
| 190 | 190 | // misc options |
| 191 | 191 | { NULL, NULL, OPTION_HEADER, "CORE MISC OPTIONS" }, |
| 192 | { OPTION_DRC, "1", OPTION_BOOLEAN, "enable DRC cpu core if available" }, | |
| 193 | { OPTION_DRC_USE_C, "0", OPTION_BOOLEAN, "force DRC use C backend" }, | |
| 192 | { OPTION_DRC, "1", OPTION_BOOLEAN, "enable DRC cpu core if available" }, | |
| 193 | { OPTION_DRC_USE_C, "0", OPTION_BOOLEAN, "force DRC use C backend" }, | |
| 194 | 194 | { OPTION_BIOS, NULL, OPTION_STRING, "select the system BIOS to use" }, |
| 195 | 195 | { OPTION_CHEAT ";c", "0", OPTION_BOOLEAN, "enable cheat subsystem" }, |
| 196 | 196 | { OPTION_SKIP_GAMEINFO, "0", OPTION_BOOLEAN, "skip displaying the information screen at startup" }, |
| r25360 | r25361 | |
| 202 | 202 | { OPTION_AUTOBOOT_DELAY, "2", OPTION_INTEGER, "timer delay in sec to trigger command execution on autoboot" }, |
| 203 | 203 | { OPTION_AUTOBOOT_SCRIPT ";script", NULL, OPTION_STRING, "lua script to execute after machine boot" }, |
| 204 | 204 | { OPTION_HTTP, "0", OPTION_BOOLEAN, "enable local http server" }, |
| 205 | { OPTION_HTTP_PORT, "8080", OPTION_INTEGER, "http server listener port" }, | |
| 206 | { OPTION_HTTP_PATH, "web", OPTION_STRING, "path to web files" }, | |
| 205 | { OPTION_HTTP_PORT, "8080", OPTION_INTEGER, "http server listener port" }, | |
| 206 | { OPTION_HTTP_PATH, "web", OPTION_STRING, "path to web files" }, | |
| 207 | 207 | { NULL } |
| 208 | 208 | }; |
| 209 | 209 |
| r25360 | r25361 | |
|---|---|---|
| 599 | 599 | // blitting parameters for rendering |
| 600 | 600 | struct blit_parameters |
| 601 | 601 | { |
| 602 | bitmap_ind8 * | |
| 602 | bitmap_ind8 * priority; | |
| 603 | 603 | rectangle cliprect; |
| 604 | 604 | UINT32 tilemap_priority_code; |
| 605 | 605 | UINT8 mask; |
| r25360 | r25361 | |
|---|---|---|
| 206 | 206 | #define OPTION_AUTOBOOT_DELAY "autoboot_delay" |
| 207 | 207 | #define OPTION_AUTOBOOT_SCRIPT "autoboot_script" |
| 208 | 208 | |
| 209 | #define OPTION_HTTP "http" | |
| 210 | #define OPTION_HTTP_PORT "http_port" | |
| 211 | #define OPTION_HTTP_PATH "http_path" | |
| 209 | #define OPTION_HTTP "http" | |
| 210 | #define OPTION_HTTP_PORT "http_port" | |
| 211 | #define OPTION_HTTP_PATH "http_path" | |
| 212 | 212 | |
| 213 | 213 | //************************************************************************** |
| 214 | 214 | // TYPE DEFINITIONS |
| r25360 | r25361 | |
| 369 | 369 | const char *autoboot_command() const { return value(OPTION_AUTOBOOT_COMMAND); } |
| 370 | 370 | int autoboot_delay() const { return int_value(OPTION_AUTOBOOT_DELAY); } |
| 371 | 371 | const char *autoboot_script() const { return value(OPTION_AUTOBOOT_SCRIPT); } |
| 372 | ||
| 372 | ||
| 373 | 373 | bool http() const { return bool_value(OPTION_HTTP); } |
| 374 | 374 | const char *http_port() const { return value(OPTION_HTTP_PORT); } |
| 375 | 375 | const char *http_path() const { return value(OPTION_HTTP_PATH); } |
| r25360 | r25361 | |
|---|---|---|
| 147 | 147 | // loop across multiple hard resets |
| 148 | 148 | bool exit_pending = false; |
| 149 | 149 | int error = MAMERR_NONE; |
| 150 | ||
| 150 | ||
| 151 | 151 | web_engine web(options); |
| 152 | ||
| 152 | ||
| 153 | 153 | while (error == MAMERR_NONE && !exit_pending) |
| 154 | 154 | { |
| 155 | 155 | // if no driver, use the internal empty driver |
| r25360 | r25361 | |
| 187 | 187 | |
| 188 | 188 | // looooong term: remove this |
| 189 | 189 | global_machine = &machine; |
| 190 | ||
| 190 | ||
| 191 | 191 | web.set_machine(machine); |
| 192 | web.push_message("update_machine"); | |
| 192 | web.push_message("update_machine"); | |
| 193 | 193 | // run the machine |
| 194 | 194 | error = machine.run(firstrun); |
| 195 | 195 | firstrun = false; |
| r25360 | r25361 | |
|---|---|---|
| 394 | 394 | bool settingsloaded = config_load_settings(*this); |
| 395 | 395 | nvram_load(*this); |
| 396 | 396 | sound().ui_mute(false); |
| 397 | ||
| 397 | ||
| 398 | 398 | // initialize ui lists |
| 399 | 399 | ui_initialize(*this); |
| 400 | 400 |
| r25360 | r25361 | |
|---|---|---|
| 94 | 94 | //I include these in the chip because they depend on the chip clock |
| 95 | 95 | unsigned int m_ARStep[0x40], m_DRStep[0x40]; //Envelope step table |
| 96 | 96 | unsigned int m_FNS_Table[0x400]; //Frequency step table |
| 97 | ||
| 97 | ||
| 98 | 98 | void EG_Calc(SLOT *slot); |
| 99 | 99 | void LFO_ComputeStep(LFO_t *LFO,UINT32 LFOF,UINT32 LFOS,int ALFO); |
| 100 | 100 | void WriteSlot(SLOT *slot,int reg,unsigned char data); |
| r25360 | r25361 | |
|---|---|---|
| 52 | 52 | { |
| 53 | 53 | m_fifo[i] = 0; |
| 54 | 54 | } |
| 55 | ||
| 55 | ||
| 56 | 56 | for (int i = 0; i < 6; i++) |
| 57 | 57 | { |
| 58 | 58 | m_filter[i].F = 0; |
| r25360 | r25361 | |
| 88 | 88 | void sp0250_device::device_start() |
| 89 | 89 | { |
| 90 | 90 | const sp0250_interface *intf = reinterpret_cast<const sp0250_interface *>(static_config()); |
| 91 | ||
| 91 | ||
| 92 | 92 | m_RNG = 1; |
| 93 | 93 | m_drq = ( intf!= NULL) ? m_drq_callback : NULL; |
| 94 | 94 | if (m_drq != NULL) |
| r25360 | r25361 | |
| 98 | 98 | } |
| 99 | 99 | |
| 100 | 100 | m_stream = machine().sound().stream_alloc(*this, 0, 1, clock() / CLOCK_DIVIDER, this); |
| 101 | ||
| 101 | ||
| 102 | 102 | save_item(NAME(m_amp)); |
| 103 | 103 | save_item(NAME(m_pitch)); |
| 104 | 104 | save_item(NAME(m_repeat)); |
| r25360 | r25361 | |
|---|---|---|
| 19 | 19 | |
| 20 | 20 | DECLARE_WRITE8_MEMBER( write ); |
| 21 | 21 | UINT8 drq_r(); |
| 22 | ||
| 22 | ||
| 23 | 23 | protected: |
| 24 | 24 | // device-level overrides |
| 25 | 25 | virtual void device_config_complete(); |
| r25360 | r25361 | |
| 27 | 27 | |
| 28 | 28 | // sound stream update overrides |
| 29 | 29 | virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); |
| 30 | ||
| 30 | ||
| 31 | 31 | private: |
| 32 | 32 | // internal state |
| 33 | 33 | INT16 m_amp; |
| r25360 | r25361 | |
| 47 | 47 | INT16 F, B; |
| 48 | 48 | INT16 z1, z2; |
| 49 | 49 | } m_filter[6]; |
| 50 | ||
| 50 | ||
| 51 | 51 | void load_values(); |
| 52 | 52 | TIMER_CALLBACK_MEMBER( timer_tick ); |
| 53 | 53 | }; |
| r25360 | r25361 | |
|---|---|---|
| 734 | 734 | |
| 735 | 735 | //case 0x0c: |
| 736 | 736 | //case 0x0d: |
| 737 | // printf("%04x\n",AICA->udata.data[0xc/2]); | |
| 738 | // break; | |
| 737 | // printf("%04x\n",AICA->udata.data[0xc/2]); | |
| 738 | // break; | |
| 739 | 739 | |
| 740 | 740 | case 0x12: |
| 741 | 741 | case 0x13: |
| r25360 | r25361 | |
|---|---|---|
| 20 | 20 | |
| 21 | 21 | /* TODO: unknown exact size */ |
| 22 | 22 | static ADDRESS_MAP_START( upd7752_ram, AS_0, 8, upd7752_device ) |
| 23 | // | |
| 23 | // AM_RANGE(0x0000, 0x7fff) AM_ROM | |
| 24 | 24 | AM_RANGE(0x0000, 0xffff) AM_RAM |
| 25 | 25 | ADDRESS_MAP_END |
| 26 | 26 | |
| r25360 | r25361 | |
| 34 | 34 | |
| 35 | 35 | upd7752_device::upd7752_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 36 | 36 | : device_t(mconfig, UPD7752, "uPD7752", tag, owner, clock, "upd7752", __FILE__), |
| 37 | device_sound_interface(mconfig, *this), | |
| 38 | device_memory_interface(mconfig, *this), | |
| 39 | m_space_config("ram", ENDIANNESS_LITTLE, 8, 16, 0, NULL, *ADDRESS_MAP_NAME(upd7752_ram)) | |
| 37 | device_sound_interface(mconfig, *this), | |
| 38 | device_memory_interface(mconfig, *this), | |
| 39 | m_space_config("ram", ENDIANNESS_LITTLE, 8, 16, 0, NULL, *ADDRESS_MAP_NAME(upd7752_ram)) | |
| 40 | 40 | { |
| 41 | 41 | } |
| 42 | 42 | |
| r25360 | r25361 | |
| 80 | 80 | |
| 81 | 81 | void upd7752_device::device_stop() |
| 82 | 82 | { |
| 83 | ||
| 84 | 83 | } |
| 85 | 84 | |
| 86 | 85 | //------------------------------------------------- |
| r25360 | r25361 | |
| 155 | 154 | [1] xxxx ---- amp Voice source amplitude |
| 156 | 155 | ---- x--- Fricative Voice data |
| 157 | 156 | ---- -xxx Pitch |
| 158 | | |
| 157 | (repeat for N1 times) | |
| 159 | 158 | if [0] & 0xf8 == 0 then command stop |
| 160 | 159 | */ |
| 161 | 160 | writebyte(m_ram_addr++,data); |
| r25360 | r25361 | |
|---|---|---|
| 30 | 30 | // ======================> upd7752_device |
| 31 | 31 | |
| 32 | 32 | class upd7752_device : public device_t, |
| 33 | public device_sound_interface, | |
| 34 | public device_memory_interface | |
| 33 | public device_sound_interface, | |
| 34 | public device_memory_interface | |
| 35 | 35 | { |
| 36 | 36 | public: |
| 37 | 37 | // construction/destruction |
| r25360 | r25361 | |
|---|---|---|
| 65 | 65 | // ======================> t6721a_device |
| 66 | 66 | |
| 67 | 67 | class t6721a_device : public device_t, |
| 68 | | |
| 68 | public device_sound_interface | |
| 69 | 69 | { |
| 70 | 70 | public: |
| 71 | 71 | t6721a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| r25360 | r25361 | |
|---|---|---|
| 158 | 158 | TIMER_DMA, |
| 159 | 159 | TIMER_HSYNC |
| 160 | 160 | }; |
| 161 | ||
| 161 | ||
| 162 | 162 | void initialize_palette(); |
| 163 | 163 | |
| 164 | 164 | static const int bckgnd[]; |
| r25360 | r25361 | |
|---|---|---|
| 727 | 727 | |
| 728 | 728 | |
| 729 | 729 | #------------------------------------------------- |
| 730 | # NEC uPD7752 | |
| 730 | # NEC uPD7752 | |
| 731 | 731 | #@src/emu/sound/upd7752.h,SOUNDS += UPD7752 |
| 732 | 732 | #------------------------------------------------- |
| 733 | 733 |
| r25360 | r25361 | |
|---|---|---|
| 120 | 120 | 01 7 0#3 4 5 6 7 0#3 4 5 6 7 0#3 4 5 |
| 121 | 121 | 10 7 0#5 6 7 0#5 6 7 0#5 6 7 0#5 6 7 |
| 122 | 122 | 11 7 0#7 0#7 0#7 0#7 0#7 0#7 0#7 0#7 |
| 123 | ||
| 123 | Based on the behavior tested on the CD2501ECD this is assumed to be the same for that chip as well. | |
| 124 | 124 | |
| 125 | 125 | Most of the following is based on figure 8c of 4,331,836, which is the |
| 126 | 126 | TMS5100/TMC0280 patent, but the same information applies to the TMS52xx |
| r25360 | r25361 | |
| 219 | 219 | synthesizer (early cards only) |
| 220 | 220 | |
| 221 | 221 | CD2501ECD: (1983) |
| 222 | ||
| 222 | Home computer: TI 99/8 (prototypes only) | |
| 223 | 223 | |
| 224 | 224 | TMS5220: (mostly on things made between 1981 and 1984-1985) |
| 225 | 225 | Arcade: Bally/Midway's 'NFL Football'; Atari's 'Star Wars', |
| r25360 | r25361 | |
|---|---|---|
| 36 | 36 | |
| 37 | 37 | void set_frequency(int frequency); |
| 38 | 38 | |
| 39 | ||
| 39 | ||
| 40 | 40 | protected: |
| 41 | 41 | // device-level overrides |
| 42 | 42 | virtual void device_config_complete(); |
| r25360 | r25361 | |
| 66 | 66 | UINT8 m_st_pulses; /* Keep track of attenuation */ |
| 67 | 67 | UINT8 m_ch2_update; /* Pulse shape */ |
| 68 | 68 | UINT8 m_st_update; |
| 69 | ||
| 69 | ||
| 70 | 70 | void oki_process(int channel, int command); |
| 71 | 71 | void generate_adpcm(struct ADPCMVoice *voice, INT16 *buffer, int samples,int channel); |
| 72 | 72 | void postload(); |
| r25360 | r25361 | |
|---|---|---|
| 1 | 1 | /*************************************************************************** |
| 2 | ||
| 2 | ||
| 3 | 3 | esqpump.c - Ensoniq 5505/5506 to 5510 interface. |
| 4 | ||
| 4 | ||
| 5 | 5 | By Christian Brunschen |
| 6 | ||
| 6 | ||
| 7 | 7 | ***************************************************************************/ |
| 8 | 8 | |
| 9 | 9 | #include "sound/esqpump.h" |
| r25360 | r25361 | |
| 70 | 70 | for (int i = 0; i < samples; i++) |
| 71 | 71 | { |
| 72 | 72 | #define SAMPLE_SHIFT 4 |
| 73 | | |
| 73 | // anything for the 'aux' output? | |
| 74 | 74 | INT16 l = inputs[0][i] >> SAMPLE_SHIFT; |
| 75 | 75 | INT16 r = inputs[1][i] >> SAMPLE_SHIFT; |
| 76 | 76 | |
| r25360 | r25361 | |
| 108 | 108 | INT32 er = (inputs[3][i]) + (inputs[5][i]) + (inputs[7][i]); |
| 109 | 109 | INT32 e_next = el + er; |
| 110 | 110 | e[(ei + 0x1d0f) % 0x4000] = e_next; |
| 111 | ||
| 111 | ||
| 112 | 112 | if (l != e[ei]) { |
| 113 | 113 | fprintf(stderr, "expected (%d) but have (%d)\n", e[ei], l); |
| 114 | 114 | } |
| r25360 | r25361 | |
| 166 | 166 | // ecery time there's a new sample period, update the stream! |
| 167 | 167 | m_stream->update(); |
| 168 | 168 | } |
| 169 |
| r25360 | r25361 | |
|---|---|---|
| 24 | 24 | m_esp_halted = esp_halted; |
| 25 | 25 | logerror("ESP-halted -> %d\n", m_esp_halted); |
| 26 | 26 | if (!esp_halted) { |
| 27 | ||
| 28 | 27 | #if PUMP_REPLACE_ESP_PROGRAM |
| 29 | 28 | m_esp->write_reg(245, 0x1d0f << 8); // dlength = 0x3fff, 16-sample delay |
| 30 | ||
| 29 | ||
| 31 | 30 | int pc = 0; |
| 32 | 31 | for (pc = 0; pc < 0xc0; pc++) { |
| 33 | 32 | m_esp->write_reg(pc, 0); |
| r25360 | r25361 | |
| 41 | 40 | m_esp->_instr(pc++) = 0xffffeea00000; // ADD SER2R, gpr_a0 > gpr_a0 |
| 42 | 41 | |
| 43 | 42 | m_esp->_instr(pc ) = 0xffffefa00000; // ADD SER2L, gpr_a0 > gpr_a0; prepare to read from delay 2 instructions from now, offset = 0 |
| 44 | ||
| 43 | m_esp->write_reg(pc++, 0); //offset into delay | |
| 45 | 44 | |
| 46 | 45 | m_esp->_instr(pc ) = 0xffffa0a09508; // MOV gpr_a0 > delay + offset |
| 47 | 46 | m_esp->write_reg(pc++, 1 << 8); // offset into delay - -1 samples |
| r25360 | r25361 | |
|---|---|---|
| 24 | 24 | |
| 25 | 25 | // sound stream update overrides |
| 26 | 26 | virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); |
| 27 | ||
| 27 | ||
| 28 | 28 | private: |
| 29 | 29 | // internal state |
| 30 | 30 | sound_stream * m_stream; |
| r25360 | r25361 | |
| 50 | 50 | UINT8 *m_SpeechRom; // array to hold rom contents, mame will not need this, will use a pointer |
| 51 | 51 | INT16 m_filtervals[8]; |
| 52 | 52 | UINT8 m_VSU1000_amp; // amplitude setting on VSU-1000 board |
| 53 | ||
| 53 | ||
| 54 | 54 | INT16 audiofilter(); |
| 55 | 55 | void shiftIntoFilter(INT16 inputvalue); |
| 56 | 56 | void PostPhoneme(); |
| r25360 | r25361 | |
|---|---|---|
| 355 | 355 | // SCREEN DEVICE CONFIGURATION MACROS |
| 356 | 356 | //************************************************************************** |
| 357 | 357 | |
| 358 | ||
| 358 | // legacy | |
| 359 | 359 | #define SCREEN_UPDATE_NAME(name) screen_update_##name |
| 360 | 360 | #define SCREEN_UPDATE_IND16(name) UINT32 SCREEN_UPDATE_NAME(name)(device_t *, screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) |
| 361 | 361 | #define SCREEN_UPDATE_RGB32(name) UINT32 SCREEN_UPDATE_NAME(name)(device_t *, screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) |
| 362 | 362 | |
| 363 | ||
| 363 | // legacy | |
| 364 | 364 | #define SCREEN_VBLANK_NAME(name) screen_vblank_##name |
| 365 | 365 | #define SCREEN_VBLANK(name) void SCREEN_VBLANK_NAME(name)(device_t *, screen_device &screen, bool vblank_on) |
| 366 | 366 |
| r25360 | r25361 | |
|---|---|---|
| 48 | 48 | // WEB ENGINE |
| 49 | 49 | //************************************************************************** |
| 50 | 50 | |
| 51 | void web_engine::websocket_ready_handler(struct mg_connection *conn) { | |
| 51 | void web_engine::websocket_ready_handler(struct mg_connection *conn) { | |
| 52 | 52 | static const char *message = "update_machine"; |
| 53 | 53 | mg_websocket_write(conn, WEBSOCKET_OPCODE_TEXT, message, strlen(message)); |
| 54 | 54 | m_websockets.append(*global_alloc(simple_list_wrapper<mg_connection>(conn))); |
| 55 | } | |
| 55 | } | |
| 56 | 56 | |
| 57 | 57 | // Arguments: |
| 58 | 58 | // flags: first byte of websocket frame, see websocket RFC, |
| 59 | 59 | // http://tools.ietf.org/html/rfc6455, section 5.2 |
| 60 | 60 | // data, data_len: payload data. Mask, if any, is already applied. |
| 61 | 61 | int web_engine::websocket_data_handler(struct mg_connection *conn, int flags, |
| 62 | ||
| 62 | char *data, size_t data_len) | |
| 63 | 63 | { |
| 64 | 64 | // just Echo example for now |
| 65 | 65 | if ((flags & 0x0f) == WEBSOCKET_OPCODE_TEXT) |
| r25360 | r25361 | |
| 68 | 68 | // Returning zero means stoping websocket conversation. |
| 69 | 69 | // Close the conversation if client has sent us "exit" string. |
| 70 | 70 | return memcmp(data, "exit", 4); |
| 71 | } | |
| 71 | } | |
| 72 | 72 | |
| 73 | 73 | static void get_qsvar(const struct mg_request_info *request_info, |
| 74 | const char *name, char *dst, size_t dst_len) { | |
| 75 | const char *qs = request_info->query_string; | |
| 76 | mg_get_var(qs, strlen(qs == NULL ? "" : qs), name, dst, dst_len); | |
| 74 | const char *name, char *dst, size_t dst_len) { | |
| 75 | const char *qs = request_info->query_string; | |
| 76 | mg_get_var(qs, strlen(qs == NULL ? "" : qs), name, dst, dst_len); | |
| 77 | 77 | } |
| 78 | 78 | |
| 79 | int web_engine::json_game_handler(struct mg_connection *conn) | |
| 79 | int web_engine::json_game_handler(struct mg_connection *conn) | |
| 80 | 80 | { |
| 81 | 81 | Json::Value data; |
| 82 | 82 | data["name"] = m_machine->system().name; |
| r25360 | r25361 | |
| 103 | 103 | return 1; |
| 104 | 104 | } |
| 105 | 105 | |
| 106 | int web_engine::json_slider_handler(struct mg_connection *conn) | |
| 106 | int web_engine::json_slider_handler(struct mg_connection *conn) | |
| 107 | 107 | { |
| 108 | 108 | const slider_state *curslider; |
| 109 | 109 | astring tempstring; |
| 110 | 110 | Json::Value array(Json::arrayValue); |
| 111 | ||
| 111 | ||
| 112 | 112 | /* add all sliders */ |
| 113 | 113 | for (curslider = ui_get_slider_list(); curslider != NULL; curslider = curslider->next) |
| 114 | 114 | { |
| r25360 | r25361 | |
| 151 | 151 | } |
| 152 | 152 | |
| 153 | 153 | // This function will be called by mongoose on every new request. |
| 154 | int web_engine::begin_request_handler(struct mg_connection *conn) | |
| 154 | int web_engine::begin_request_handler(struct mg_connection *conn) | |
| 155 | 155 | { |
| 156 | 156 | const struct mg_request_info *request_info = mg_get_request_info(conn); |
| 157 | if (!strncmp(request_info->uri, "/json/",6)) | |
| 157 | if (!strncmp(request_info->uri, "/json/",6)) | |
| 158 | 158 | { |
| 159 | if (!strcmp(request_info->uri, "/json/game")) | |
| 159 | if (!strcmp(request_info->uri, "/json/game")) | |
| 160 | 160 | { |
| 161 | 161 | return json_game_handler(conn); |
| 162 | } | |
| 163 | if (!strcmp(request_info->uri, "/json/slider")) | |
| 162 | } | |
| 163 | if (!strcmp(request_info->uri, "/json/slider")) | |
| 164 | 164 | { |
| 165 | 165 | return json_slider_handler(conn); |
| 166 | } | |
| 166 | } | |
| 167 | 167 | } |
| 168 | else if (!strncmp(request_info->uri, "/cmd",4)) | |
| 168 | else if (!strncmp(request_info->uri, "/cmd",4)) | |
| 169 | 169 | { |
| 170 | 170 | char cmd_name[64]; |
| 171 | 171 | get_qsvar(request_info, "name", cmd_name, sizeof(cmd_name)); |
| 172 | ||
| 172 | ||
| 173 | 173 | if(!strcmp(cmd_name,"softreset")) |
| 174 | 174 | { |
| 175 | 175 | m_machine->schedule_soft_reset(); |
| 176 | } | |
| 176 | } | |
| 177 | 177 | else if(!strcmp(cmd_name,"hardreset")) |
| 178 | 178 | { |
| 179 | 179 | m_machine->schedule_hard_reset(); |
| r25360 | r25361 | |
| 181 | 181 | else if(!strcmp(cmd_name,"exit")) |
| 182 | 182 | { |
| 183 | 183 | m_machine->schedule_exit(); |
| 184 | } | |
| 185 | ||
| 184 | } | |
| 185 | ||
| 186 | 186 | // Send HTTP reply to the client |
| 187 | 187 | mg_printf(conn, |
| 188 | 188 | "HTTP/1.1 200 OK\r\n" |
| r25360 | r25361 | |
| 195 | 195 | // the client, and mongoose should not send client any more data. |
| 196 | 196 | return 1; |
| 197 | 197 | } |
| 198 | else if (!strncmp(request_info->uri, "/slider",7)) | |
| 198 | else if (!strncmp(request_info->uri, "/slider",7)) | |
| 199 | 199 | { |
| 200 | 200 | char cmd_id[64]; |
| 201 | 201 | char cmd_val[64]; |
| r25360 | r25361 | |
| 206 | 206 | const slider_state *curslider; |
| 207 | 207 | for (curslider = ui_get_slider_list(); curslider != NULL; curslider = curslider->next) |
| 208 | 208 | { |
| 209 | if (cnt==id) | |
| 209 | if (cnt==id) | |
| 210 | 210 | (*curslider->update)(machine(), curslider->arg, NULL, atoi(cmd_val)); |
| 211 | 211 | cnt++; |
| 212 | 212 | } |
| 213 | 213 | for (curslider = (slider_state*)machine().osd().get_slider_list(); curslider != NULL; curslider = curslider->next) |
| 214 | 214 | { |
| 215 | if (cnt==id) | |
| 215 | if (cnt==id) | |
| 216 | 216 | (*curslider->update)(machine(), curslider->arg, NULL, atoi(cmd_val)); |
| 217 | 217 | cnt++; |
| 218 | 218 | } |
| 219 | ||
| 219 | ||
| 220 | 220 | // Send HTTP reply to the client |
| 221 | 221 | mg_printf(conn, |
| 222 | 222 | "HTTP/1.1 200 OK\r\n" |
| r25360 | r25361 | |
| 229 | 229 | // the client, and mongoose should not send client any more data. |
| 230 | 230 | return 1; |
| 231 | 231 | } |
| 232 | else if (!strncmp(request_info->uri, "/screenshot.png",15)) | |
| 232 | else if (!strncmp(request_info->uri, "/screenshot.png",15)) | |
| 233 | 233 | { |
| 234 | 234 | screen_device_iterator iter(m_machine->root_device()); |
| 235 | 235 | screen_device *screen = iter.first(); |
| r25360 | r25361 | |
| 251 | 251 | m_machine->video().save_snapshot(screen, file); |
| 252 | 252 | astring fullpath(file.fullpath()); |
| 253 | 253 | file.close(); |
| 254 | ||
| 254 | ||
| 255 | 255 | mg_send_file(conn,fullpath); |
| 256 | 256 | return 1; |
| 257 | 257 | } |
| 258 | 258 | return 0; |
| 259 | } | |
| 259 | } | |
| 260 | 260 | |
| 261 | 261 | |
| 262 | void *web_engine::websocket_keepalive() | |
| 262 | void *web_engine::websocket_keepalive() | |
| 263 | 263 | { |
| 264 | while(!m_exiting_core) | |
| 264 | while(!m_exiting_core) | |
| 265 | 265 | { |
| 266 | osd_ticks_t curtime = osd_ticks(); | |
| 266 | osd_ticks_t curtime = osd_ticks(); | |
| 267 | 267 | if ((curtime - m_lastupdatetime) > osd_ticks_per_second() * 5) |
| 268 | 268 | { |
| 269 | 269 | m_lastupdatetime = curtime; |
| 270 | 270 | for (simple_list_wrapper<mg_connection> *curitem = m_websockets.first(); curitem != NULL; curitem = curitem->next()) |
| 271 | 271 | { |
| 272 | int status = mg_websocket_write(curitem->object(), WEBSOCKET_OPCODE_PING, NULL, 0); | |
| 272 | int status = mg_websocket_write(curitem->object(), WEBSOCKET_OPCODE_PING, NULL, 0); | |
| 273 | 273 | if (status==0) m_websockets.detach(*curitem); // remove inactive clients |
| 274 | 274 | } |
| 275 | 275 | } |
| r25360 | r25361 | |
| 284 | 284 | static void websocket_ready_handler_static(struct mg_connection *conn) |
| 285 | 285 | { |
| 286 | 286 | const struct mg_request_info *request_info = mg_get_request_info(conn); |
| 287 | ||
| 287 | web_engine *engine = static_cast<web_engine *>(request_info->user_data); | |
| 288 | 288 | engine->websocket_ready_handler(conn); |
| 289 | 289 | } |
| 290 | 290 | |
| 291 | 291 | static int websocket_data_handler_static(struct mg_connection *conn, int flags, |
| 292 | ||
| 292 | char *data, size_t data_len) | |
| 293 | 293 | { |
| 294 | 294 | const struct mg_request_info *request_info = mg_get_request_info(conn); |
| 295 | ||
| 295 | web_engine *engine = static_cast<web_engine *>(request_info->user_data); | |
| 296 | 296 | return engine->websocket_data_handler(conn, flags, data, data_len); |
| 297 | 297 | } |
| 298 | 298 | |
| 299 | static int begin_request_handler_static(struct mg_connection *conn) | |
| 299 | static int begin_request_handler_static(struct mg_connection *conn) | |
| 300 | 300 | { |
| 301 | const struct mg_request_info *request_info = mg_get_request_info(conn); | |
| 302 | web_engine *engine = static_cast<web_engine *>(request_info->user_data); | |
| 301 | const struct mg_request_info *request_info = mg_get_request_info(conn); | |
| 302 | web_engine *engine = static_cast<web_engine *>(request_info->user_data); | |
| 303 | 303 | return engine->begin_request_handler(conn); |
| 304 | 304 | } |
| 305 | 305 | |
| 306 | static void *websocket_keepalive_static(void *thread_func_param) | |
| 306 | static void *websocket_keepalive_static(void *thread_func_param) | |
| 307 | 307 | { |
| 308 | 308 | web_engine *engine = static_cast<web_engine *>(thread_func_param); |
| 309 | 309 | return engine->websocket_keepalive(); |
| r25360 | r25361 | |
| 315 | 315 | |
| 316 | 316 | web_engine::web_engine(emu_options &options) |
| 317 | 317 | : m_options(options), |
| 318 | m_machine(NULL), | |
| 319 | m_ctx(NULL), | |
| 320 | m_lastupdatetime(0), | |
| 321 | m_exiting_core(false) | |
| 322 | ||
| 318 | m_machine(NULL), | |
| 319 | m_ctx(NULL), | |
| 320 | m_lastupdatetime(0), | |
| 321 | m_exiting_core(false) | |
| 322 | ||
| 323 | 323 | { |
| 324 | ||
| 325 | 324 | struct mg_callbacks callbacks; |
| 326 | 325 | |
| 327 | 326 | // List of options. Last element must be NULL. |
| 328 | 327 | const char *web_options[] = { |
| 329 | "listening_ports", options.http_port(), | |
| 328 | "listening_ports", options.http_port(), | |
| 330 | 329 | "document_root", options.http_path(), |
| 331 | 330 | NULL |
| 332 | 331 | }; |
| 333 | 332 | |
| 334 | // Prepare callbacks structure. | |
| 333 | // Prepare callbacks structure. | |
| 335 | 334 | memset(&callbacks, 0, sizeof(callbacks)); |
| 336 | 335 | callbacks.begin_request = begin_request_handler_static; |
| 337 | callbacks.websocket_ready = websocket_ready_handler_static; | |
| 338 | callbacks.websocket_data = websocket_data_handler_static; | |
| 336 | callbacks.websocket_ready = websocket_ready_handler_static; | |
| 337 | callbacks.websocket_data = websocket_data_handler_static; | |
| 339 | 338 | |
| 340 | 339 | // Start the web server. |
| 341 | 340 | if (m_options.http()) { |
| 342 | 341 | m_ctx = mg_start(&callbacks, this, web_options); |
| 343 | ||
| 342 | ||
| 344 | 343 | mg_start_thread(websocket_keepalive_static, this); |
| 345 | 344 | } |
| 346 | ||
| 345 | ||
| 347 | 346 | } |
| 348 | 347 | |
| 349 | 348 | //------------------------------------------------- |
| r25360 | r25361 | |
| 368 | 367 | { |
| 369 | 368 | mg_websocket_write(curitem->object(), WEBSOCKET_OPCODE_CONNECTION_CLOSE, NULL, 0); |
| 370 | 369 | } |
| 371 | // Stop the server. | |
| 370 | // Stop the server. | |
| 372 | 371 | mg_stop(m_ctx); |
| 373 | 372 | } |
| 374 | 373 | |
| r25360 | r25361 | |
| 376 | 375 | void web_engine::push_message(const char *message) |
| 377 | 376 | { |
| 378 | 377 | for (simple_list_wrapper<mg_connection> *curitem = m_websockets.first(); curitem != NULL; curitem = curitem->next()) |
| 379 | { | |
| 378 | { | |
| 380 | 379 | int status = mg_websocket_write(curitem->object(), WEBSOCKET_OPCODE_TEXT, message, strlen(message)); |
| 381 | 380 | if (status==0) m_websockets.detach(*curitem); // remove inactive clients |
| 382 | 381 | } |
| r25360 | r25361 | |
|---|---|---|
| 55 | 55 | void push_message(const char *message); |
| 56 | 56 | void close(); |
| 57 | 57 | |
| 58 | void set_machine(running_machine &machine) { m_machine = &machine; } | |
| 59 | ||
| 58 | void set_machine(running_machine &machine) { m_machine = &machine; } | |
| 59 | ||
| 60 | 60 | void websocket_ready_handler(struct mg_connection *conn); |
| 61 | 61 | int websocket_data_handler(struct mg_connection *conn, int flags, char *data, size_t data_len); |
| 62 | int begin_request_handler(struct mg_connection *conn); | |
| 63 | void *websocket_keepalive(); | |
| 62 | int begin_request_handler(struct mg_connection *conn); | |
| 63 | void *websocket_keepalive(); | |
| 64 | 64 | protected: |
| 65 | 65 | // getters |
| 66 | 66 | running_machine &machine() const { return *m_machine; } |
| 67 | ||
| 67 | ||
| 68 | 68 | int json_game_handler(struct mg_connection *conn); |
| 69 | 69 | int json_slider_handler(struct mg_connection *conn); |
| 70 | 70 | private: |
| 71 | 71 | // internal state |
| 72 | emu_options & m_options; | |
| 73 | running_machine * m_machine; | |
| 72 | emu_options & m_options; | |
| 73 | running_machine * m_machine; | |
| 74 | 74 | struct mg_context * m_ctx; |
| 75 | osd_ticks_t m_lastupdatetime; | |
| 76 | bool m_exiting_core; | |
| 75 | osd_ticks_t m_lastupdatetime; | |
| 76 | bool m_exiting_core; | |
| 77 | 77 | simple_list<simple_list_wrapper<mg_connection> > m_websockets; |
| 78 | 78 | }; |
| 79 | 79 |
| r25360 | r25361 | |
|---|---|---|
| 9 | 9 | dc_cons_state(const machine_config &mconfig, device_type type, const char *tag) |
| 10 | 10 | : dc_state(mconfig, type, tag), |
| 11 | 11 | m_ata(*this, "ata") |
| 12 | // | |
| 12 | // m_dcflash(*this, "dcflash") | |
| 13 | 13 | { } |
| 14 | 14 | |
| 15 | 15 | required_device<ata_interface_device> m_ata; |
| 16 | // | |
| 16 | // required_device<macronix_29lv160tmc_device> m_dcflash; | |
| 17 | 17 | |
| 18 | 18 | DECLARE_DRIVER_INIT(dc); |
| 19 | 19 | DECLARE_DRIVER_INIT(dcus); |
| r25360 | r25361 | |
| 36 | 36 | void dreamcast_atapi_init(); |
| 37 | 37 | DECLARE_READ32_MEMBER( dc_mess_g1_ctrl_r ); |
| 38 | 38 | DECLARE_WRITE32_MEMBER( dc_mess_g1_ctrl_w ); |
| 39 | // DECLARE_READ8_MEMBER( dc_flash_r ); | |
| 40 | // DECLARE_WRITE8_MEMBER( dc_flash_w ); | |
| 39 | // DECLARE_READ8_MEMBER( dc_flash_r ); | |
| 40 | // DECLARE_WRITE8_MEMBER( dc_flash_w ); | |
| 41 | 41 | |
| 42 | 42 | private: |
| 43 | 43 | UINT64 PDTRA, PCTRA; |
| r25360 | r25361 | |
|---|---|---|
| 26 | 26 | DECLARE_MACHINE_START( ms_megadriv ); // setup ioport_port + install cartslot handlers |
| 27 | 27 | DECLARE_MACHINE_RESET( ms_megadriv ); |
| 28 | 28 | }; |
| 29 | ||
| 30 |
| r25360 | r25361 | |
|---|---|---|
| 79 | 79 | required_shared_ptr<UINT8> m_color1_ram; |
| 80 | 80 | |
| 81 | 81 | DECLARE_WRITE8_MEMBER( dma_w ); |
| 82 | ||
| 82 | ||
| 83 | 83 | DECLARE_DEVICE_IMAGE_LOAD_MEMBER( visicom_cart_load ); |
| 84 | 84 | }; |
| 85 | 85 |
| r25360 | r25361 | |
|---|---|---|
| 74 | 74 | /* floppy state */ |
| 75 | 75 | int m_fdc_index; |
| 76 | 76 | DECLARE_WRITE_LINE_MEMBER(osi470_index_callback); |
| 77 | ||
| 77 | ||
| 78 | 78 | DECLARE_PALETTE_INIT(osi630); |
| 79 | 79 | |
| 80 | 80 | required_device<cpu_device> m_maincpu; |
| r25360 | r25361 | |
|---|---|---|
| 411 | 411 | required_device<ram_device> m_ram; |
| 412 | 412 | |
| 413 | 413 | UINT32 m_debug_machine; |
| 414 | // | |
| 414 | // i186_state m_i186; | |
| 415 | 415 | keyboard_t m_keyboard; |
| 416 | 416 | nimbus_drives_t m_nimbus_drives; |
| 417 | 417 | ipc_interface_t m_ipc_interface; |
| r25360 | r25361 | |
| 429 | 429 | UINT8 m_hs_count; |
| 430 | 430 | UINT32 m_debug_video; |
| 431 | 431 | UINT8 m_vector; |
| 432 | // DECLARE_READ16_MEMBER(nimbus_i186_internal_port_r); | |
| 433 | // DECLARE_WRITE16_MEMBER(nimbus_i186_internal_port_w); | |
| 432 | // DECLARE_READ16_MEMBER(nimbus_i186_internal_port_r); | |
| 433 | // DECLARE_WRITE16_MEMBER(nimbus_i186_internal_port_w); | |
| 434 | 434 | DECLARE_READ8_MEMBER(nimbus_mcu_r); |
| 435 | 435 | DECLARE_WRITE8_MEMBER(nimbus_mcu_w); |
| 436 | 436 | DECLARE_READ16_MEMBER(nimbus_io_r); |
| r25360 | r25361 | |
| 461 | 461 | virtual void palette_init(); |
| 462 | 462 | UINT32 screen_update_nimbus(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); |
| 463 | 463 | void screen_eof_nimbus(screen_device &screen, bool state); |
| 464 | // TIMER_CALLBACK_MEMBER(internal_timer_int); | |
| 465 | // TIMER_CALLBACK_MEMBER(dma_timer_callback); | |
| 464 | // TIMER_CALLBACK_MEMBER(internal_timer_int); | |
| 465 | // TIMER_CALLBACK_MEMBER(dma_timer_callback); | |
| 466 | 466 | TIMER_CALLBACK_MEMBER(keyscan_callback); |
| 467 | 467 | TIMER_CALLBACK_MEMBER(mouse_callback); |
| 468 | 468 | DECLARE_WRITE_LINE_MEMBER(sio_interrupt); |
| r25360 | r25361 | |
| 502 | 502 | void write_reg_01E(); |
| 503 | 503 | void write_reg_026(); |
| 504 | 504 | void change_palette(UINT8 bank, UINT16 colours, UINT8 regno); |
| 505 | // void update_interrupt_state(); | |
| 506 | // void handle_eoi(int data); | |
| 505 | // void update_interrupt_state(); | |
| 506 | // void handle_eoi(int data); | |
| 507 | 507 | void external_int(UINT16 intno, UINT8 vector); |
| 508 | 508 | DECLARE_READ8_MEMBER(cascade_callback); |
| 509 | // void nimbus_recalculate_ints(); | |
| 510 | // void internal_timer_sync(int which); | |
| 511 | // void internal_timer_update(int which,int new_count,int new_maxA,int new_maxB,int new_control); | |
| 512 | // void update_dma_control(int which, int new_control); | |
| 513 | // void drq_callback(int which); | |
| 514 | // void nimbus_cpu_init(); | |
| 515 | // void nimbus_cpu_reset(); | |
| 509 | // void nimbus_recalculate_ints(); | |
| 510 | // void internal_timer_sync(int which); | |
| 511 | // void internal_timer_update(int which,int new_count,int new_maxA,int new_maxB,int new_control); | |
| 512 | // void update_dma_control(int which, int new_control); | |
| 513 | // void drq_callback(int which); | |
| 514 | // void nimbus_cpu_init(); | |
| 515 | // void nimbus_cpu_reset(); | |
| 516 | 516 | void *get_dssi_ptr(address_space &space, UINT16 ds, UINT16 si); |
| 517 | 517 | void nimbus_bank_memory(); |
| 518 | 518 | void memory_reset(); |
| r25360 | r25361 | |
|---|---|---|
| 18 | 18 | m_lpt1(*this, "lpt_1"), |
| 19 | 19 | m_lpt2(*this, "lpt_2") |
| 20 | 20 | { m_mouse.x =0; m_mouse.y=0;} |
| 21 | ||
| 21 | ||
| 22 | 22 | required_device<pc_lpt_device> m_lpt1; |
| 23 | 23 | required_device<pc_lpt_device> m_lpt2; |
| 24 | ||
| 24 | ||
| 25 | 25 | DECLARE_READ8_MEMBER( pc1640_port60_r ); |
| 26 | 26 | DECLARE_WRITE8_MEMBER( pc1640_port60_w ); |
| 27 | 27 |
| r25360 | r25361 | |
|---|---|---|
| 77 | 77 | DECLARE_WRITE16_MEMBER(aim65_update_ds3); |
| 78 | 78 | DECLARE_WRITE16_MEMBER(aim65_update_ds4); |
| 79 | 79 | DECLARE_WRITE16_MEMBER(aim65_update_ds5); |
| 80 | ||
| 80 | ||
| 81 | 81 | void dl1416_update(dl1416_device *device, int index); |
| 82 | 82 | |
| 83 | 83 | DECLARE_DEVICE_IMAGE_LOAD_MEMBER(aim65_cart); |
| r25360 | r25361 | |
|---|---|---|
| 6 | 6 | 01/05/2009 Initial implementation [Miodrag Milanovic] |
| 7 | 7 | Sept. 2013 portions by Karl-Ludwig Deisenhofer. |
| 8 | 8 | |
| 9 | STATE OF DEC-100 VIDEO AS OF SEPTEMBER 2013 | |
| 10 | ------------------------------------------- | |
| 11 | - FURTHER TESTING: do line and character attributes match real hardware? Does soft scrolling work? | |
| 12 | - LIKELY INCORRECT : implementation of double size attribute in 132 columns mode (additional case) | |
| 9 | STATE OF DEC-100 VIDEO AS OF SEPTEMBER 2013 | |
| 10 | ------------------------------------------- | |
| 11 | - FURTHER TESTING: do line and character attributes match real hardware? Does soft scrolling work? | |
| 12 | - LIKELY INCORRECT : implementation of double size attribute in 132 columns mode (additional case) | |
| 13 | 13 | |
| 14 | - MISSING: undocumented features of DC011 / DC012 - see public domain SQUEEZE.COM pokes: | |
| 15 | 0f00 => PORT 0C; | |
| 16 | 0b00 => PORT 0C; | |
| 17 | 1000 => PORT 04 | |
| 18 | (SQUEEZE compresses the display in X and Y direction on a real DEC-100 B) | |
| 14 | - MISSING: undocumented features of DC011 / DC012 - see public domain SQUEEZE.COM pokes: | |
| 15 | 0f00 => PORT 0C; | |
| 16 | 0b00 => PORT 0C; | |
| 17 | 1000 => PORT 04 | |
| 18 | (SQUEEZE compresses the display in X and Y direction on a real DEC-100 B) | |
| 19 | 19 | |
| 20 | - IMPROVEMENTS: | |
| 21 | - find a more realistic approach for intensity control (bold attribute) | |
| 22 | - correct phosphor colors (green, white and amber monitors were common) | |
| 20 | - IMPROVEMENTS: | |
| 21 | - find a more realistic approach for intensity control (bold attribute) | |
| 22 | - correct phosphor colors (green, white and amber monitors were common) | |
| 23 | 23 | |
| 24 | 24 | Copyright MESS Team. |
| 25 | 25 | Visit http://mamedev.org for licensing and usage restrictions. |
| r25360 | r25361 | |
| 122 | 122 | { |
| 123 | 123 | palette_set_color_rgb(machine(), 0, 0x00, 0x00, 0x00); // black |
| 124 | 124 | palette_set_color_rgb(machine(), 1, 0xff, 0xff, 0xff); // white |
| 125 | ||
| 125 | ||
| 126 | 126 | m_height = 25; |
| 127 | 127 | m_height_MAX = 25; |
| 128 | 128 | |
| r25360 | r25361 | |
| 149 | 149 | |
| 150 | 150 | m_height = 24; // <---- DEC-100 |
| 151 | 151 | m_height_MAX = 48; |
| 152 | ||
| 152 | ||
| 153 | 153 | m_lba7 = 0; |
| 154 | 154 | |
| 155 | 155 | m_scroll_latch = 0; |
| r25360 | r25361 | |
| 181 | 181 | } else { |
| 182 | 182 | horiz_pix_total = m_columns * 10; // normal 80 character mode. |
| 183 | 183 | } |
| 184 | ||
| 184 | ||
| 185 | 185 | visarea.set(0, horiz_pix_total - 1, 0, vert_pix_total - 1); |
| 186 | 186 | |
| 187 | 187 | m_screen->configure(horiz_pix_total, vert_pix_total, visarea, m_screen->frame_period().attoseconds); |
| r25360 | r25361 | |
| 238 | 238 | // set basic attribute to reverse video / blink flip-flop off |
| 239 | 239 | m_basic_attribute = 1; |
| 240 | 240 | m_blink_flip_flop = 0; |
| 241 | ||
| 242 | if (m_height_MAX == 25) break; // VT 100. | |
| 243 | 241 | |
| 244 | if (m_height != 24) | |
| 242 | if (m_height_MAX == 25) break; // VT 100. | |
| 243 | ||
| 244 | if (m_height != 24) | |
| 245 | 245 | { |
| 246 | m_height = 24; // (DEC Rainbow 100) : 24 line display | |
| 246 | m_height = 24; // (DEC Rainbow 100) : 24 line display | |
| 247 | 247 | recompute_parameters(); |
| 248 | | |
| 248 | } | |
| 249 | 249 | break; |
| 250 | 250 | |
| 251 | 251 | case 0x0e: |
| 252 | | |
| 252 | break; // (DC12) : 'not supported' | |
| 253 | 253 | |
| 254 | 254 | case 0x0f: |
| 255 | 255 | // (DEC Rainbow 100) : set basic attribute to reverse video / blink flip-flop off |
| 256 | 256 | m_basic_attribute = 1; |
| 257 | 257 | m_blink_flip_flop = 0; |
| 258 | 258 | |
| 259 | if (m_height_MAX == 25) break; // VT 100. | |
| 259 | if (m_height_MAX == 25) break; // VT 100. | |
| 260 | 260 | |
| 261 | 261 | if (m_height != 48) |
| 262 | 262 | { |
| 263 | m_height = 48; // (DEC Rainbow 100) : 48 line display | |
| 263 | m_height = 48; // (DEC Rainbow 100) : 48 line display | |
| 264 | 264 | recompute_parameters(); |
| 265 | | |
| 265 | } | |
| 266 | 266 | break; |
| 267 | 267 | } |
| 268 | 268 | } |
| r25360 | r25361 | |
| 440 | 440 | { |
| 441 | 441 | UINT8 xsize, d_xsize; |
| 442 | 442 | if (m_columns == 132) |
| 443 | { xsize = 9; | |
| 444 | d_xsize = 18; | |
| 443 | { xsize = 9; | |
| 444 | d_xsize = 18; | |
| 445 | 445 | } else |
| 446 | 446 | { |
| 447 | xsize = 10; | |
| 448 | d_xsize = 20; | |
| 447 | xsize = 10; | |
| 448 | d_xsize = 20; | |
| 449 | 449 | } |
| 450 | 450 | |
| 451 | 451 | UINT8 line = 0; |
| r25360 | r25361 | |
| 475 | 475 | |
| 476 | 476 | line = m_gfx[code * 16 + j]; |
| 477 | 477 | |
| 478 | if ( i == 8 ) | |
| 479 | { | |
| 480 | if ( underline != 0 ) line = 0xff; | |
| 478 | if ( i == 8 ) | |
| 479 | { | |
| 480 | if ( underline != 0 ) line = 0xff; | |
| 481 | 481 | } |
| 482 | 482 | |
| 483 | 483 | // Code to handle basic attribute from VT-100 |
| 484 | if ( m_basic_attribute == 1 ) | |
| 484 | if ( m_basic_attribute == 1 ) | |
| 485 | 485 | { |
| 486 | 486 | if ((code & 0x80) == 0x80) |
| 487 | 487 | invert = 1; |
| r25360 | r25361 | |
| 489 | 489 | invert = 0; |
| 490 | 490 | } |
| 491 | 491 | |
| 492 | ||
| 492 | if (m_blink_flip_flop > 0) | |
| 493 | 493 | { |
| 494 | if ( blink != 0 ) | |
| 495 | { | |
| 496 | line = line ^ 0xff; | |
| 497 | } | |
| 494 | if ( blink != 0 ) | |
| 495 | { | |
| 496 | line = line ^ 0xff; | |
| 497 | } | |
| 498 | 498 | } |
| 499 | if (invert != 0) | |
| 500 | line = line ^ 0xff; | |
| 499 | if (invert != 0) | |
| 500 | line = line ^ 0xff; | |
| 501 | 501 | |
| 502 | 502 | for (int b = 0; b < 8; b++) |
| 503 | 503 | { |
| r25360 | r25361 | |
| 519 | 519 | { |
| 520 | 520 | bitmap.pix16(y * 10 + i, x * d_xsize + 16) = bit; |
| 521 | 521 | bitmap.pix16(y * 10 + i, x * d_xsize + 17) = bit; |
| 522 | bitmap.pix16(y * 10 + i, x * d_xsize + 18) = bit; | |
| 522 | bitmap.pix16(y * 10 + i, x * d_xsize + 18) = bit; | |
| 523 | 523 | bitmap.pix16(y * 10 + i, x * d_xsize + 19) = bit; |
| 524 | 524 | } |
| 525 | 525 | else |
| r25360 | r25361 | |
| 567 | 567 | addr = (temp) & 0x0fff; |
| 568 | 568 | attr_addr = ((temp) & 0x1fff) - 2; |
| 569 | 569 | |
| 570 | // No AVO here. | |
| 571 | attr_addr |= 0x1000; | |
| 570 | // No AVO here. | |
| 571 | attr_addr |= 0x1000; | |
| 572 | 572 | if (attr_addr > 0x2000) // Ignore attributes beyond 8192 byte limit (SRAM). |
| 573 | 573 | { |
| 574 | 574 | scroll_region = 1; // binary 1 <- SET DEFAULTS |
| 575 | 575 | display_type = 3; // binary 111 |
| 576 | } else | |
| 577 | { | |
| 576 | } else | |
| 577 | { | |
| 578 | 578 | temp = m_in_ram_func(attr_addr); |
| 579 | 579 | scroll_region = (temp) & 1; |
| 580 | 580 | display_type = (temp >> 1) & 3; |
| r25360 | r25361 | |
| 589 | 589 | } |
| 590 | 590 | else |
| 591 | 591 | { |
| 592 | // display regular char | |
| 592 | // display regular char | |
| 593 | 593 | if (line >= m_skip_lines) |
| 594 | 594 | { |
| 595 | 595 | attr_addr = 0x1000 | ( (addr + xpos) & 0x0fff ); |
| 596 | 596 | temp = m_in_ram_func(attr_addr); // get character attribute |
| 597 | 597 | |
| 598 | // TODO: check if reverse bit is treated the same way on real hardware | |
| 598 | // TODO: check if reverse bit is treated the same way on real hardware | |
| 599 | 599 | // 1 = display char. in REVERSE (encoded as 8) |
| 600 | 600 | // 0 = display char. in BOLD (encoded as 16) |
| 601 | 601 | // 0 = display char. w. BLINK (encoded as 32) |
| 602 | // 0 = display char. w. UNDERLINE (encoded as 64). | |
| 602 | // 0 = display char. w. UNDERLINE (encoded as 64). | |
| 603 | 603 | display_char(bitmap, code, xpos, ypos, scroll_region, display_type | ( ( (temp & 1)) << 3 ) |
| 604 | | ( (2-(temp & 2)) << 3 ) | |
| 605 | | ( (4-(temp & 4)) << 3 ) | |
| 606 | | ( (8-(temp & 8)) << 3 ) | |
| 607 | ); | |
| 604 | | ( (2-(temp & 2)) << 3 ) | |
| 605 | | ( (4-(temp & 4)) << 3 ) | |
| 606 | | ( (8-(temp & 8)) << 3 ) | |
| 607 | ); | |
| 608 | 608 | } |
| 609 | 609 | xpos++; |
| 610 | 610 | if (xpos > m_columns) |
| r25360 | r25361 | |
|---|---|---|
| 27 | 27 | DECLARE_WRITE8_MEMBER( reg_write ); |
| 28 | 28 | DECLARE_READ8_MEMBER( vram_read ); |
| 29 | 29 | DECLARE_WRITE8_MEMBER( vram_write ); |
| 30 | ||
| 30 | ||
| 31 | 31 | DECLARE_PALETTE_INIT(k1ge); |
| 32 | ||
| 32 | ||
| 33 | 33 | void update( bitmap_ind16 &bitmap, const rectangle &cliprect ); |
| 34 | 34 | |
| 35 | 35 | // Static methods |
| r25360 | r25361 | |
| 66 | 66 | { |
| 67 | 67 | public: |
| 68 | 68 | k2ge_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 69 | ||
| 69 | ||
| 70 | 70 | DECLARE_PALETTE_INIT(k2ge); |
| 71 | 71 | protected: |
| 72 | 72 | virtual machine_config_constructor device_mconfig_additions() const; |
| r25360 | r25361 | |
|---|---|---|
| 36 | 36 | }; |
| 37 | 37 | |
| 38 | 38 | |
| 39 | class gb_lcd_device : | |
| 39 | class gb_lcd_device : public device_t, | |
| 40 | 40 | public device_video_interface |
| 41 | 41 | { |
| 42 | 42 | public: |
| r25360 | r25361 | |
|---|---|---|
| 9 | 9 | |
| 10 | 10 | /* |
| 11 | 11 | |
| 12 | ||
| 12 | TODO: | |
| 13 | 13 | |
| 14 | - portrait/landscape detection is broken | |
| 15 | - bottom border is not respected | |
| 14 | - portrait/landscape detection is broken | |
| 15 | - bottom border is not respected | |
| 16 | 16 | |
| 17 | 17 | */ |
| 18 | 18 | |
| r25360 | r25361 | |
| 257 | 257 | |
| 258 | 258 | abc1600_mover_device::abc1600_mover_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 259 | 259 | : device_t(mconfig, ABC1600_MOVER, "ABC 1600 Mover", tag, owner, clock, "abc1600mover", __FILE__), |
| 260 | device_memory_interface(mconfig, *this), | |
| 261 | m_space_config("vram", ENDIANNESS_BIG, 16, 18, -1, *ADDRESS_MAP_NAME(mover_map)), | |
| 262 | m_crtc(*this, SY6845E_TAG), | |
| 263 | m_wrmsk_rom(*this, "wrmsk"), | |
| 264 | m_shinf_rom(*this, "shinf"), | |
| 265 | m_drmsk_rom(*this, "drmsk") | |
| 260 | device_memory_interface(mconfig, *this), | |
| 261 | m_space_config("vram", ENDIANNESS_BIG, 16, 18, -1, *ADDRESS_MAP_NAME(mover_map)), | |
| 262 | m_crtc(*this, SY6845E_TAG), | |
| 263 | m_wrmsk_rom(*this, "wrmsk"), | |
| 264 | m_shinf_rom(*this, "shinf"), | |
| 265 | m_drmsk_rom(*this, "drmsk") | |
| 266 | 266 | { |
| 267 | 267 | } |
| 268 | 268 |
| r25360 | r25361 | |
|---|---|---|
| 36 | 36 | // ======================> abc1600_mover_device |
| 37 | 37 | |
| 38 | 38 | class abc1600_mover_device : public device_t, |
| 39 | | |
| 39 | public device_memory_interface | |
| 40 | 40 | { |
| 41 | 41 | public: |
| 42 | 42 | // construction/destruction |
| r25360 | r25361 | |
|---|---|---|
| 332 | 332 | } |
| 333 | 333 | else |
| 334 | 334 | { |
| 335 | // | |
| 335 | // printf("procolor816_r: @ %x, mask %08x [PC=%x]\n", offset, mem_mask, machine().device("maincpu")->safe_pc()); | |
| 336 | 336 | } |
| 337 | 337 | |
| 338 | 338 | return 0; |
| r25360 | r25361 | |
|---|---|---|
| 281 | 281 | break; |
| 282 | 282 | |
| 283 | 283 | default: |
| 284 | // | |
| 284 | // printf("m2video_w: %08x @ %x, mask %08x (PC=%x)\n", data, offset, mem_mask, space.device().safe_pc()); | |
| 285 | 285 | break; |
| 286 | 286 | } |
| 287 | 287 | } |
| r25360 | r25361 | |
| 295 | 295 | } |
| 296 | 296 | else |
| 297 | 297 | { |
| 298 | // | |
| 298 | // printf("m2video_r: @ %x, mask %08x (PC=%x)\n", offset, mem_mask, space.device().safe_pc()); | |
| 299 | 299 | } |
| 300 | 300 | |
| 301 | 301 | return 0; |
| r25360 | r25361 | |
|---|---|---|
| 24 | 24 | ~asr733_device() { global_free(m_token); } |
| 25 | 25 | |
| 26 | 26 | DECLARE_PALETTE_INIT(asr733); |
| 27 | ||
| 27 | ||
| 28 | 28 | // access to legacy token |
| 29 | 29 | void *token() const { assert(m_token != NULL); return m_token; } |
| 30 | 30 | protected: |
| r25360 | r25361 | |
|---|---|---|
| 22 | 22 | |
| 23 | 23 | virtual UINT32 pci_read(pci_bus_device *pcibus, int function, int offset, UINT32 mem_mask); |
| 24 | 24 | virtual void pci_write(pci_bus_device *pcibus, int function, int offset, UINT32 data, UINT32 mem_mask); |
| 25 | ||
| 25 | ||
| 26 | 26 | DECLARE_WRITE8_MEMBER( cirrus_42E8_w ); |
| 27 | 27 | |
| 28 | 28 | protected: |
| r25360 | r25361 | |
|---|---|---|
| 48 | 48 | ~vdt911_device() { global_free(m_token); } |
| 49 | 49 | |
| 50 | 50 | DECLARE_PALETTE_INIT(vdt911); |
| 51 | ||
| 51 | ||
| 52 | 52 | // access to legacy token |
| 53 | 53 | void *token() const { assert(m_token != NULL); return m_token; } |
| 54 | 54 | protected: |
| r25360 | r25361 | |
|---|---|---|
| 102 | 102 | pico // 1994 Sega Pico (Europe) |
| 103 | 103 | picou // 1994 Sega Pico (USA) |
| 104 | 104 | picoj // 1993 Sega Pico (Japan) |
| 105 | copera | |
| 105 | copera // 1993 Sega / Yamaha | |
| 106 | 106 | segacd // 1992 Sega Sega CD (USA) |
| 107 | 107 | megacd // 1993 Sega Mega-CD (Europe) |
| 108 | 108 | megacda // 1993 Sega Mega-CD (Asia) |
| r25360 | r25361 | |
|---|---|---|
| 8 | 8 | </disk> |
| 9 | 9 | </element> |
| 10 | 10 | |
| 11 | ||
| 11 | ||
| 12 | 12 | <element name="DRIVE0"> |
| 13 | 13 | <text string="A"> |
| 14 | 14 | <color red="1.0" green="1.0" blue="1.0" /> |
| r25360 | r25361 | |
| 87 | 87 | <bezel name="led21" element="led"> |
| 88 | 88 | <bounds x="15" y="18" width="10" height="10" /> |
| 89 | 89 | </bezel> |
| 90 | ||
| 90 | ||
| 91 | 91 | <bezel name="led1" element="led"> |
| 92 | 92 | <bounds x="15" y="43" width="10" height="10" /> |
| 93 | 93 | </bezel> |
| r25360 | r25361 | |
| 121 | 121 | <bezel name="led11" element="led"> |
| 122 | 122 | <bounds x="15" y="252" width="10" height="10" /> |
| 123 | 123 | </bezel> |
| 124 | ||
| 124 | ||
| 125 | 125 | <bezel name="label20" element="DRIVE0"> |
| 126 | 126 | <bounds x="0" y="0" width="15" height="16" /> |
| 127 | 127 | </bezel> |
| r25360 | r25361 | |
|---|---|---|
| 249 | 249 | ADDRESS_MAP_END |
| 250 | 250 | |
| 251 | 251 | //static ADDRESS_MAP_START(c8002_data, AS_DATA, 16, onyx_state) |
| 252 | // AM_RANGE(0x00000, 0x00fff) AM_ROM AM_SHARE("share0") | |
| 253 | // AM_RANGE(0x01000, 0x07fff) AM_RAM AM_SHARE("share1") | |
| 254 | // AM_RANGE(0x08000, 0xfffff) AM_RAM AM_SHARE("share2") | |
| 252 | // AM_RANGE(0x00000, 0x00fff) AM_ROM AM_SHARE("share0") | |
| 253 | // AM_RANGE(0x01000, 0x07fff) AM_RAM AM_SHARE("share1") | |
| 254 | // AM_RANGE(0x08000, 0xfffff) AM_RAM AM_SHARE("share2") | |
| 255 | 255 | //ADDRESS_MAP_END |
| 256 | 256 | |
| 257 | 257 | static ADDRESS_MAP_START(c8002_io, AS_IO, 8, onyx_state) |
| r25360 | r25361 | |
|---|---|---|
| 93 | 93 | |
| 94 | 94 | /* |
| 95 | 95 | |
| 96 | Using the hard disk | |
| 97 | ------------------- | |
| 96 | Using the hard disk | |
| 97 | ------------------- | |
| 98 | 98 | |
| 99 | ||
| 99 | Use the chdman utility to create a Tandon TM501 (5MB) or CMI CM-5412 (10MB) hard disk image: | |
| 100 | 100 | |
| 101 | 101 | $ chdman createhd -chs 306,2,32 -ss 256 -o tm501.chd |
| 102 | ||
| 102 | $ chdman createhd -chs 306,4,32 -ss 256 -o cm5412.chd | |
| 103 | 103 | |
| 104 | ||
| 104 | Start the Visual 1050 emulator with the floppy and hard disk images mounted: | |
| 105 | 105 | |
| 106 | ||
| 106 | $??mess v1050 -flop1 cpm3:flop2 -hard cm5412.chd | |
| 107 | 107 | |
| 108 | ||
| 108 | Start the Winchester Format Program from the CP/M prompt: | |
| 109 | 109 | |
| 110 | ||
| 110 | A>fmtwinch | |
| 111 | 111 | |
| 112 | Enter Y to continue. | |
| 113 | Ener A for 5MB, or B for 10MB hard disk. | |
| 114 | Enter C to start formatting. | |
| 112 | Enter Y to continue. | |
| 113 | Ener A for 5MB, or B for 10MB hard disk. | |
| 114 | Enter C to start formatting. | |
| 115 | 115 | |
| 116 | ||
| 116 | Once the formatting is complete, the CP/M system files need to be copied over to the hard disk: | |
| 117 | 117 | |
| 118 | ||
| 118 | A>copysys | |
| 119 | 119 | |
| 120 | Enter source drive name "a" and press RETURN. | |
| 121 | Enter target drive name "c" and press RETURN. | |
| 122 | Enter "y" at the prompt for CPM3.SYS. | |
| 123 | Enter "y" at the prompt for CCP.COM. | |
| 124 | Press RETURN to return to CP/M. | |
| 120 | Enter source drive name "a" and press RETURN. | |
| 121 | Enter target drive name "c" and press RETURN. | |
| 122 | Enter "y" at the prompt for CPM3.SYS. | |
| 123 | Enter "y" at the prompt for CCP.COM. | |
| 124 | Press RETURN to return to CP/M. | |
| 125 | 125 | |
| 126 | ||
| 126 | The hard disk can now be booted from with the following command line: | |
| 127 | 127 | |
| 128 | ||
| 128 | $ mess v1050 -hard cm5412.chd | |
| 129 | 129 | |
| 130 | 130 | */ |
| 131 | 131 |
| r25360 | r25361 | |
|---|---|---|
| 1130 | 1130 | AM_RANGE( 0xe90000, 0xe9001f ) AM_READWRITE( supracan_sound_r, supracan_sound_w ) |
| 1131 | 1131 | AM_RANGE( 0xe90020, 0xe9002f ) AM_WRITE( supracan_dma_channel0_w ) |
| 1132 | 1132 | AM_RANGE( 0xe90030, 0xe9003f ) AM_WRITE( supracan_dma_channel1_w ) |
| 1133 | ||
| 1133 | ||
| 1134 | 1134 | AM_RANGE( 0xf00000, 0xf001ff ) AM_READWRITE( supracan_video_r, supracan_video_w ) |
| 1135 | 1135 | AM_RANGE( 0xf00200, 0xf003ff ) AM_RAM AM_WRITE(paletteram_xBBBBBGGGGGRRRRR_word_w) AM_SHARE("paletteram") |
| 1136 | 1136 | AM_RANGE( 0xf40000, 0xf5ffff ) AM_READWRITE(supracan_vram_r, supracan_vram_w) |
| r25360 | r25361 | |
| 1743 | 1743 | verboselog("maincpu", 0, "supracan_video_w: Unknown register: %08x = %04x & %04x\n", 0xf00000 + (offset << 1), data, mem_mask); |
| 1744 | 1744 | break; |
| 1745 | 1745 | } |
| 1746 | // | |
| 1746 | // m_video_regs[offset] = data; | |
| 1747 | 1747 | } |
| 1748 | 1748 | |
| 1749 | 1749 |
| r25360 | r25361 | |
|---|---|---|
| 154 | 154 | Crystals: |
| 155 | 155 | X1: 19.968Mhz, used by GA2 (plus a PLL to multiply by 2?), and divide by 4 for |
| 156 | 156 | cpuclk, divide by 8 for 2.5mhz and divide by 5.5 for 3.63mhz (is this |
| 157 | ||
| 157 | suposed to be divide by 6? there may not be a pll if it is...) | |
| 158 | 158 | X2: 3.579545Mhz, used by the DTMF generator chip AMI S2579 at IC40 |
| 159 | 159 | X3: 2.4576Mhz, used by the modem chip AMI S35213 at IC37 |
| 160 | 160 | |
| r25360 | r25361 | |
| 183 | 183 | | TMS4256 74F153 "VIDEO 2B" .----------. J4 | K = |
| 184 | 184 | | | AM27256 | 74HC02 74HC374 || | O = |
| 185 | 185 | | TMS4256 74F153 74LS393 |__________| || UM95089 Y2 | U = |
| 186 | |_____________________________________(j9)________________________________________________________|_T___= | |
| 186 | |_____________________________________(j9)________________________________________________________|_T___= | |
| 187 | 187 | |
| 188 | 188 | "TIMING B" - AMPAL16R4APC (marked on silkscreen "TIMING PAL") |
| 189 | 189 | "DECODE E" - AMPAL16L8PC (marked on silkscreen "DECODE PAL") |
| r25360 | r25361 | |
|---|---|---|
| 342 | 342 | //************************************************************************** |
| 343 | 343 | |
| 344 | 344 | static ADDRESS_MAP_START( apricot_mem, AS_PROGRAM, 16, apricot_state ) |
| 345 | // AM_RANGE(0x00000, 0x3ffff) AM_RAMBANK("standard_ram") | |
| 346 | // AM_RANGE(0x40000, 0xeffff) AM_RAMBANK("expansion_ram") | |
| 345 | // AM_RANGE(0x00000, 0x3ffff) AM_RAMBANK("standard_ram") | |
| 346 | // AM_RANGE(0x40000, 0xeffff) AM_RAMBANK("expansion_ram") | |
| 347 | 347 | AM_RANGE(0xf0000, 0xf0fff) AM_MIRROR(0x7000) AM_RAM AM_SHARE("screen_buffer") |
| 348 | 348 | AM_RANGE(0xfc000, 0xfffff) AM_MIRROR(0x4000) AM_ROM AM_REGION("bootstrap", 0) |
| 349 | 349 | ADDRESS_MAP_END |
| r25360 | r25361 | |
|---|---|---|
| 175 | 175 | ************************************************************/ |
| 176 | 176 | |
| 177 | 177 | //FLOPPY_FORMATS_MEMBER( kaypro_state::kayproii_floppy_formats ) |
| 178 | // | |
| 178 | // FLOPPY_KAYPROII_FORMAT | |
| 179 | 179 | //FLOPPY_FORMATS_END |
| 180 | 180 | |
| 181 | 181 | //FLOPPY_FORMATS_MEMBER( kaypro_state::kaypro2x_floppy_formats ) |
| 182 | // | |
| 182 | // FLOPPY_KAYPRO2X_FORMAT | |
| 183 | 183 | //FLOPPY_FORMATS_END |
| 184 | 184 | |
| 185 | 185 | static SLOT_INTERFACE_START( kaypro_floppies ) |
| r25360 | r25361 | |
|---|---|---|
| 21 | 21 | | | | +-+ | |
| 22 | 22 | | | | +--+ |B| +-+ | |
| 23 | 23 | | | | |A3| +-+ | | | |
| 24 | | +------------------------------+ +--+ |C| +-| | |
| 24 | | +------------------------------+ +--+ |C| +-| | |
| 25 | 25 | | | | | | |
| 26 | 26 | | GCMK-C2X +-+ | --> PEN |
| 27 | | +-----+ +--+ +-| | |
| 28 | | | | |A3| +--------+ | | |
| 29 | | | A1 | +--+ | | +---------+ | | |
| 27 | | +-----+ +--+ +-| | |
| 28 | | | | |A3| +--------+ | | |
| 29 | | | A1 | +--+ | | +---------+ | | |
| 30 | 30 | | SEGA | | | A2 | |HM53861J | | |
| 31 | | 1994 837-10846 +-----+ | | | | | | |
| 32 | | IAC MAIN PAL +--------+ +---------+ | | |
| 31 | | 1994 837-10846 +-----+ | | | | | | |
| 32 | | IAC MAIN PAL +--------+ +---------+ | | |
| 33 | 33 | | MADE IN JAPAN +----+ | |
| 34 | | VA0 +----------+ |XTAL| +--+ | |
| 35 | | | SEGA | +---------+ | | | <-- VCC IN | |
| 34 | | VA0 +----------+ |XTAL| +--+ | |
| 35 | | | SEGA | +---------+ | | | <-- VCC IN | |
| 36 | 36 | | | 315-5640 | |MC68HC000| |53.2| +--+ |
| 37 | | | 9434 W51 | |FN8-A | +----+ |00 | +----------+ | | |
| 38 | | | | | | | | +----+ | SEGA | | | |
| 39 | | | | | 2B89N | | | | 315-5313A| | | |
| 40 | | | | |S0AH9425A| | A4 | | F1001 | +--| | |
| 41 | | +----------+ +---------+ | | | | | | | |
| 37 | | | 9434 W51 | |FN8-A | +----+ |00 | +----------+ | | |
| 38 | | | | | | | | +----+ | SEGA | | | |
| 39 | | | | | 2B89N | | | | 315-5313A| | | |
| 40 | | | | |S0AH9425A| | A4 | | F1001 | +--| | |
| 41 | | +----------+ +---------+ | | | | | | | |
| 42 | 42 | | | | |9428 LAGG | | --> VIDEO OUT |
| 43 | 43 | | | | | | | | |
| 44 | | +----+ +----------+ +--| | |
| 44 | | +----+ +----------+ +--| | |
| 45 | 45 | | | |
| 46 | 46 | | +----------------------------+ | |
| 47 | 47 | | ||||||CARTRIDGE CONNECTOR||||| | |
| 48 | 48 | | +----------------------------+ | |
| 49 | | | | |
| 49 | | | | |
| 50 | 50 | +------------------------------------------------------------------------------------------------------------+ |
| 51 | 51 | |
| 52 | 52 | A1 = SEGA / 315-5641 / D77591 / 9442CA010 |
| r25360 | r25361 | |
| 130 | 130 | { |
| 131 | 131 | public: |
| 132 | 132 | pico_base_state(const machine_config &mconfig, device_type type, const char *tag) |
| 133 | : md_cons_state(mconfig, type, tag), | |
| 133 | : md_cons_state(mconfig, type, tag), | |
| 134 | 134 | m_upd7759(*this, "7759") { } |
| 135 | 135 | |
| 136 | 136 | optional_device<upd7759_device> m_upd7759; |
| r25360 | r25361 | |
| 271 | 271 | static void sound_cause_irq( device_t *device, int chip ) |
| 272 | 272 | { |
| 273 | 273 | pico_base_state *state = device->machine().driver_data<pico_base_state>(); |
| 274 | // | |
| 274 | // printf("sound irq\n"); | |
| 275 | 275 | /* upd7759 callback */ |
| 276 | 276 | state->m_maincpu->set_input_line(3, HOLD_LINE); |
| 277 | 277 | } |
| r25360 | r25361 | |
| 285 | 285 | |
| 286 | 286 | WRITE16_MEMBER(pico_base_state::pico_68k_io_write ) |
| 287 | 287 | { |
| 288 | // | |
| 288 | // printf("pico_68k_io_write %04x %04x %04x\n", offset*2, data, mem_mask); | |
| 289 | 289 | |
| 290 | 290 | switch (offset) |
| 291 | 291 | { |
| 292 | ||
| 293 | 292 | case 0x12/2: // guess |
| 294 | 293 | m_upd7759->reset_w(0); |
| 295 | 294 | m_upd7759->start_w(0); |
| r25360 | r25361 | |
| 471 | 470 | | |FL-1| |FL-1| | | | E | |
| 472 | 471 | | |0 | |0 | | | | D | |
| 473 | 472 | | | | | | | | | | |
| 474 | |--+ +----+ +----+ +-------------+ | | | |
| 473 | |--+ +----+ +----+ +-------------+ | | | |
| 475 | 474 | +-- | | C | |
| 476 | 475 | | |--+ | O | |
| 477 | 476 | S-AUDIO <-| | +-----------+ +-------+ | N | |
| 478 | | |--+ | SEGA | | SEGA | +-----------+ | N | | |
| 477 | | |--+ | SEGA | | SEGA | +-----------+ | N | | |
| 479 | 478 | +-- | | 315-5640 | |315-564| | 3D4 UA | | E | |
| 480 | 479 | |--+ | 9333 W26 | |1 | |HD68HC000CP| | C | |
| 481 | 480 | | | | |D77591 | |8 | | T | |
| r25360 | r25361 | |
|---|---|---|
| 23 | 23 | with Z80 or 8080. There was also LSI ELSIE system, a concurrent DOS. Last British LSI machines were 386 computers |
| 24 | 24 | which could be used as servers for Octopus computers. |
| 25 | 25 | |
| 26 | Manufacturer | |
| 26 | Manufacturer Hilger Analytical / LSI Computers Ltd. | |
| 27 | 27 | |
| 28 | Origin UK | |
| 29 | Year of unit 1986? | |
| 30 | Year of introduction 1985 | |
| 31 | End of production ? | |
| 32 | CPU Z80, 8088 | |
| 33 | Speed ?? | |
| 34 | RAM 256kB | |
| 35 | ROM 16kB (Basic) | |
| 36 | Colors: ?? | |
| 37 | Sound: Speaker. Beeps :) | |
| 38 | OS: CP/M 80 or 86 | |
| 28 | Origin UK | |
| 29 | Year of unit 1986? | |
| 30 | Year of introduction 1985 | |
| 31 | End of production ? | |
| 32 | CPU Z80, 8088 | |
| 33 | Speed ?? | |
| 34 | RAM 256kB | |
| 35 | ROM 16kB (Basic) | |
| 36 | Colors: ?? | |
| 37 | Sound: Speaker. Beeps :) | |
| 38 | OS: CP/M 80 or 86 | |
| 39 | 39 | MP/M 80 o 86 |
| 40 | 40 | Concurrent CP/M |
| 41 | 41 | LSI ELSIE |
| 42 | 42 | MS-DOS |
| 43 | Display modes: Text: ?? | |
| 44 | Graphics: ?? | |
| 45 | ||
| 46 | Media: Two internal 5.25" floppy disk drives, DS DD, 96tpi. | |
| 47 | Probably hard disk | |
| 43 | Display modes: Text: ?? | |
| 44 | Graphics: ?? | |
| 48 | 45 | |
| 46 | Media: Two internal 5.25" floppy disk drives, DS DD, 96tpi. | |
| 47 | Probably hard disk | |
| 48 | ||
| 49 | 49 | Power supply: |
| 50 | 50 | Built-in switching power supply. |
| 51 | 51 | |
| 52 | I/O: | |
| 52 | I/O: Serial port | |
| 53 | 53 | 2 parallel ports |
| 54 | 54 | |
| 55 | 55 | Video TTL Output |
| 56 | 56 | Composite video output |
| 57 | ||
| 58 | Possible upgrades: Many | |
| 59 | ||
| 57 | ||
| 58 | Possible upgrades: Many | |
| 59 | ||
| 60 | 60 | Software accessibility: |
| 61 | 61 | Dedicated: Impossible. |
| 62 | 62 | CP/M - Good |
| 63 | 63 | DOS - Good. |
| 64 | ||
| 64 | ||
| 65 | 65 | It won't take XT nor AT keyboard, but pinout is quite similar. UPDATE: I saw a few photos of keyboard. |
| 66 | 66 | It's another Z80 computer! It has an EPROM, simple memory and CPU. |
| 67 | 67 | |
| r25360 | r25361 | |
| 100 | 100 | This information was gained by studying boot ROM of the machine. |
| 101 | 101 | |
| 102 | 102 | It's a very rare computer. It has 2 processors, Z80 and 8088, so it seems that it may run CP/M and DOS. |
| 103 | Its BIOS performs POST and halts as there's no keyboard. | |
| 103 | Its BIOS performs POST and halts as there's no keyboard. | |
| 104 | 104 | |
| 105 | 105 | ****************************************************************************/ |
| 106 | 106 |
| r25360 | r25361 | |
|---|---|---|
| 5 | 5 | Driver-in-progress by R. Belmont and Miodrag Milanovic with additions by Karl-Ludwig Deisenhofer. |
| 6 | 6 | |
| 7 | 7 | STATE AS OF SEPTEMBER 2013 |
| 8 | -------------------------- | |
| 9 | - FATAL: keyboard emulation needs love (inhibits the system from booting with ERROR 50 on cold or ERROR 13 on warm boot). | |
| 10 | - NOT WORKING: serial (ERROR 60) | |
| 11 | - NOT WORKING: printer interface (ERROR 40). | |
| 8 | -------------------------- | |
| 9 | - FATAL: keyboard emulation needs love (inhibits the system from booting with ERROR 50 on cold or ERROR 13 on warm boot). | |
| 10 | - NOT WORKING: serial (ERROR 60) | |
| 11 | - NOT WORKING: printer interface (ERROR 40). | |
| 12 | 12 | |
| 13 | - NON-CRITICAL: NVRAM currently saves changes instantly. A switch to EEPROM (load, store...) might be in order. | |
| 14 | - NON-CRITICAL: no code for W18 (DSR) jumper. | |
| 15 | - NON-CRITICAL: watchdog logic not implemented. MHFLU - ERROR 16 indicated hardware problems or (most often) software crashes on real hardware. | |
| 13 | - NON-CRITICAL: NVRAM currently saves changes instantly. A switch to EEPROM (load, store...) might be in order. | |
| 14 | - NON-CRITICAL: no code for W18 (DSR) jumper. | |
| 15 | - NON-CRITICAL: watchdog logic not implemented. MHFLU - ERROR 16 indicated hardware problems or (most often) software crashes on real hardware. | |
| 16 | 16 | |
| 17 | - FUTURE IMPROVEMENTS (=> DIP switches currently disabled): | |
| 18 | * Color graphics option (NEC 7220) | |
| 19 | * Extended communication option ( = Bundle option ?) | |
| 20 | ||
| 17 | - FUTURE IMPROVEMENTS (=> DIP switches currently disabled): | |
| 18 | * Color graphics option (NEC 7220) | |
| 19 | * Extended communication option ( = Bundle option ?) | |
| 21 | 20 | |
| 21 | ||
| 22 | 22 | Meaning of Diagnostics LEDs (from PC100ESV1.PDF found, e.g., |
| 23 | 23 | on ftp://ftp.update.uu.se/pub/rainbow/doc/rainbow-docs/ |
| 24 | 24 | |
| 25 | Internal Diagnostic Messages F | |
| 25 | Internal Diagnostic Messages F | |
| 26 | 26 | Msg Message Lights Display A |
| 27 | 27 | No. * = on o = off T |
| 28 | 28 | - = on or off A |
| 29 | 1 2 3 4 5 6 7 L | |
| 29 | 1 2 3 4 5 6 7 L | |
| 30 | 30 | -------------------------------------------------------------- |
| 31 | 31 | 1 Main Board (Video) o * * o * o * Yes |
| 32 | 32 | 2 Main Board* (unsolicited interrupt) * * * * o * o Yes |
| r25360 | r25361 | |
| 74 | 74 | PCB layout |
| 75 | 75 | ---------- |
| 76 | 76 | |
| 77 | DEC-100 model B | |
| 77 | DEC-100 model B | |
| 78 | 78 | |
| 79 | 79 | PCB # 5416206 / 5016205-01C1: |
| 80 | 80 | |
| r25360 | r25361 | |
| 125 | 125 | |
| 126 | 126 | #include "rainbow.lh" // BEZEL - LAYOUT with LEDs for diag 1-7, keyboard 8-11 and floppy 20-21 |
| 127 | 127 | |
| 128 | #define DEC_B_NVMEM_SIZE (256) | |
| 128 | #define DEC_B_NVMEM_SIZE (256) | |
| 129 | 129 | |
| 130 | 130 | class rainbow_state : public driver_device |
| 131 | 131 | { |
| r25360 | r25361 | |
| 161 | 161 | required_ioport m_inp6; |
| 162 | 162 | required_ioport m_inp7; |
| 163 | 163 | required_ioport m_inp8; |
| 164 | ||
| 165 | required_device<beep_device> m_beep; | |
| 166 | 164 | |
| 165 | required_device<beep_device> m_beep; | |
| 166 | ||
| 167 | 167 | required_device<rainbow_video_device> m_crtc; |
| 168 | 168 | required_device<cpu_device> m_i8088; |
| 169 | 169 | required_device<cpu_device> m_z80; |
| r25360 | r25361 | |
| 185 | 185 | |
| 186 | 186 | DECLARE_READ8_MEMBER(comm_control_r); |
| 187 | 187 | DECLARE_WRITE8_MEMBER(comm_control_w); |
| 188 | ||
| 188 | ||
| 189 | 189 | DECLARE_READ8_MEMBER(share_z80_r); |
| 190 | 190 | DECLARE_WRITE8_MEMBER(share_z80_w); |
| 191 | 191 | |
| r25360 | r25361 | |
| 193 | 193 | DECLARE_WRITE8_MEMBER(floating_bus_w); |
| 194 | 194 | |
| 195 | 195 | // EMULATOR TRAP TO INTERCEPT KEYBOARD cmd in AH and PARAMETER in AL (port 90 = AL / port 91 = AH) |
| 196 | ||
| 196 | // TODO: beeper and led handling should better be handled by LK201 code. | |
| 197 | 197 | DECLARE_WRITE8_MEMBER(PORT90_W); |
| 198 | 198 | DECLARE_WRITE8_MEMBER(PORT91_W); |
| 199 | ||
| 199 | ||
| 200 | 200 | DECLARE_READ8_MEMBER(i8088_latch_r); |
| 201 | 201 | DECLARE_WRITE8_MEMBER(i8088_latch_w); |
| 202 | 202 | DECLARE_READ8_MEMBER(z80_latch_r); |
| r25360 | r25361 | |
| 204 | 204 | |
| 205 | 205 | DECLARE_WRITE8_MEMBER(z80_diskdiag_read_w); |
| 206 | 206 | DECLARE_WRITE8_MEMBER(z80_diskdiag_write_w); |
| 207 | ||
| 207 | ||
| 208 | 208 | DECLARE_WRITE8_MEMBER(z80_diskcontrol_write_w); |
| 209 | 209 | DECLARE_READ8_MEMBER(system_parameter_r); |
| 210 | ||
| 210 | ||
| 211 | 211 | DECLARE_READ_LINE_MEMBER(kbd_rx); |
| 212 | 212 | DECLARE_WRITE_LINE_MEMBER(kbd_tx); |
| 213 | 213 | DECLARE_WRITE_LINE_MEMBER(kbd_rxready_w); |
| r25360 | r25361 | |
| 218 | 218 | bool m_zflip; // Z80 alternate memory map with A15 inverted |
| 219 | 219 | bool m_z80_halted; |
| 220 | 220 | bool m_kbd_tx_ready, m_kbd_rx_ready; |
| 221 | ||
| 221 | ||
| 222 | 222 | int m_KBD; |
| 223 | 223 | int m_beep_counter; |
| 224 | 224 | |
| r25360 | r25361 | |
| 236 | 236 | }; |
| 237 | 237 | |
| 238 | 238 | void rainbow_state::machine_start() |
| 239 | { | |
| 239 | { m_COLDBOOT = true; | |
| 240 | 240 | |
| 241 | 241 | save_item(NAME(m_z80_private)); |
| 242 | 242 | save_item(NAME(m_z80_mailbox)); |
| r25360 | r25361 | |
| 249 | 249 | |
| 250 | 250 | // Enables PORT90_W + PORT91_W via BIOS call (offset +$21 in HIGH ROM) |
| 251 | 251 | // F8 / FC ROM REGION (CHECK + PATCH) |
| 252 | if(rom[0xfc000 + 0x0022] == 0x22 && rom[0xfc000 + 0x0023] == 0x28) | |
| 252 | if(rom[0xfc000 + 0x0022] == 0x22 && rom[0xfc000 + 0x0023] == 0x28) | |
| 253 | 253 | { |
| 254 | 254 | rom[0xf4303]=0x00; // Disable CRC CHECK (F0 / F4 ROM) |
| 255 | 255 | |
| 256 | 256 | rom[0xfc000 + 0x0022] =0xe2; // jmp to offset $3906 |
| 257 | 257 | rom[0xfc000 + 0x0023] =0x38; |
| 258 | ||
| 258 | ||
| 259 | 259 | rom[0xfc000 + 0x3906] =0xe6; // out 90,al |
| 260 | 260 | rom[0xfc000 + 0x3907] =0x90; |
| 261 | ||
| 261 | ||
| 262 | 262 | rom[0xfc000 + 0x3908] =0x86; // xchg al,ah |
| 263 | 263 | rom[0xfc000 + 0x3909] =0xc4; |
| 264 | 264 | |
| 265 | 265 | rom[0xfc000 + 0x390a] =0xe6; // out 91,al |
| 266 | 266 | rom[0xfc000 + 0x390b] =0x91; |
| 267 | ||
| 267 | ||
| 268 | 268 | rom[0xfc000 + 0x390c] =0x86; // xchg al,ah |
| 269 | 269 | rom[0xfc000 + 0x390d] =0xc4; |
| 270 | ||
| 270 | ||
| 271 | 271 | rom[0xfc000 + 0x390e] =0xe9; // jmp (original jump offset $2846) |
| 272 | 272 | rom[0xfc000 + 0x390f] =0x35; |
| 273 | 273 | rom[0xfc000 + 0x3910] =0xef; |
| r25360 | r25361 | |
| 279 | 279 | AM_RANGE(0x00000, 0x0ffff) AM_RAM AM_SHARE("sh_ram") |
| 280 | 280 | AM_RANGE(0x10000, 0x1ffff) AM_RAM |
| 281 | 281 | |
| 282 | // test at f4e00 - f4e1c | |
| 283 | AM_RANGE(0x20000, 0xdffff) AM_READWRITE(floating_bus_r,floating_bus_w) | |
| 284 | AM_RANGE(0x20000, 0xdffff) AM_RAM | |
| 282 | // test at f4e00 - f4e1c | |
| 283 | AM_RANGE(0x20000, 0xdffff) AM_READWRITE(floating_bus_r,floating_bus_w) | |
| 284 | AM_RANGE(0x20000, 0xdffff) AM_RAM | |
| 285 | 285 | |
| 286 | 286 | // TODO: handle shadowing 100% correctly. |
| 287 | 287 | // PDF says there is a 256 x 4 bit NVRAM from 0xed000 to 0xed040. |
| 288 | ||
| 288 | // * SHOULD * be shadowed from $ec00 - $ecfff AND FROM $ed040 - $edfff. | |
| 289 | 289 | // "address bits 8-12 are not decoded when accessing the NVM" |
| 290 | 290 | |
| 291 | 291 | // ROM code gives an error if NVRAM isn't 256 x 8 bit |
| 292 | 292 | // with address bits 8-12 ignored, so do that. |
| 293 | AM_RANGE(0xec000, 0xec0ff) AM_MIRROR(0x1f00) AM_RAM AM_SHARE("nvram") | |
| 293 | AM_RANGE(0xec000, 0xec0ff) AM_MIRROR(0x1f00) AM_RAM AM_SHARE("nvram") | |
| 294 | 294 | |
| 295 | 295 | AM_RANGE(0xee000, 0xeffff) AM_RAM AM_SHARE("p_ram") |
| 296 | 296 | AM_RANGE(0xf0000, 0xfffff) AM_ROM |
| r25360 | r25361 | |
| 300 | 300 | ADDRESS_MAP_UNMAP_HIGH |
| 301 | 301 | ADDRESS_MAP_GLOBAL_MASK(0xff) |
| 302 | 302 | AM_RANGE (0x00, 0x00) AM_READWRITE(i8088_latch_r, i8088_latch_w) |
| 303 | ||
| 303 | ||
| 304 | 304 | // 0x02 Communication status / control register (8088) |
| 305 | 305 | AM_RANGE (0x02, 0x02) AM_READWRITE(comm_control_r, comm_control_w) |
| 306 | 306 | |
| 307 | 307 | // 0x04 Video processor DC011 |
| 308 | 308 | AM_RANGE (0x04, 0x04) AM_DEVWRITE("vt100_video", rainbow_video_device, dc011_w) |
| 309 | ||
| 309 | ||
| 310 | 310 | AM_RANGE (0x08, 0x08) AM_READ(system_parameter_r) |
| 311 | ||
| 311 | ||
| 312 | 312 | AM_RANGE (0x0a, 0x0a) AM_READWRITE(diagnostic_r, diagnostic_w) |
| 313 | 313 | // 0x0C Video processor DC012 |
| 314 | 314 | AM_RANGE (0x0c, 0x0c) AM_DEVWRITE("vt100_video", rainbow_video_device, dc012_w) |
| 315 | 315 | |
| 316 | 316 | AM_RANGE(0x10, 0x10) AM_DEVREADWRITE("kbdser", i8251_device, data_r, data_w) |
| 317 | 317 | AM_RANGE(0x11, 0x11) AM_DEVREADWRITE("kbdser", i8251_device, status_r, control_w) |
| 318 | ||
| 318 | ||
| 319 | 319 | AM_RANGE (0x90, 0x90) AM_WRITE(PORT90_W) |
| 320 | 320 | AM_RANGE (0x91, 0x91) AM_WRITE(PORT91_W) |
| 321 | 321 | ADDRESS_MAP_END |
| r25360 | r25361 | |
| 340 | 340 | |
| 341 | 341 | /* Input ports */ |
| 342 | 342 | static INPUT_PORTS_START( rainbow ) |
| 343 | PORT_START("FLOPPY CONTROLLER") | |
| 344 | PORT_DIPNAME( 0x02, 0x02, "FLOPPY CONTROLLER") PORT_TOGGLE | |
| 343 | PORT_START("FLOPPY CONTROLLER") | |
| 344 | PORT_DIPNAME( 0x02, 0x02, "FLOPPY CONTROLLER") PORT_TOGGLE | |
| 345 | 345 | PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) |
| 346 | 346 | PORT_DIPSETTING( 0x02, DEF_STR( On ) ) |
| 347 | 347 | |
| 348 | 348 | PORT_START("MEMORY PRESENT") |
| 349 | | |
| 349 | PORT_DIPNAME( 0xF000, 0x2000, "MEMORY PRESENT") | |
| 350 | 350 | PORT_DIPSETTING( 0x2000, "128 K (BOARD DEFAULT)" ) // NOTE: 0x2000 hard coded in 'system_parameter_r' |
| 351 | 351 | PORT_DIPSETTING( 0x3000, "192 K (MEMORY OPTION)" ) |
| 352 | 352 | PORT_DIPSETTING( 0x4000, "256 K (MEMORY OPTION)" ) |
| r25360 | r25361 | |
| 361 | 361 | PORT_DIPSETTING( 0xD000, "832 K (MEMORY OPTION)" ) |
| 362 | 362 | PORT_DIPSETTING( 0xE000, "896 K (MEMORY OPTION)" ) |
| 363 | 363 | |
| 364 | PORT_START("GRAPHICS OPTION") | |
| 365 | PORT_DIPNAME( 0x00, 0x00, "GRAPHICS OPTION") PORT_TOGGLE | |
| 364 | PORT_START("GRAPHICS OPTION") | |
| 365 | PORT_DIPNAME( 0x00, 0x00, "GRAPHICS OPTION") PORT_TOGGLE | |
| 366 | 366 | PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) |
| 367 | 367 | PORT_DIPSETTING( 0x04, DEF_STR( On ) ) |
| 368 | PORT_START("BUNDLE OPTION") | |
| 369 | PORT_DIPNAME( 0x00, 0x00, "BUNDLE OPTION") PORT_TOGGLE | |
| 368 | PORT_START("BUNDLE OPTION") | |
| 369 | PORT_DIPNAME( 0x00, 0x00, "BUNDLE OPTION") PORT_TOGGLE | |
| 370 | 370 | PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) |
| 371 | 371 | PORT_DIPSETTING( 0x01, DEF_STR( On ) ) |
| 372 | ||
| 372 | ||
| 373 | 373 | PORT_START("W13") |
| 374 | | |
| 374 | PORT_DIPNAME( 0x02, 0x02, "W13") PORT_TOGGLE | |
| 375 | 375 | PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) |
| 376 | 376 | PORT_DIPSETTING( 0x00, DEF_STR( On ) ) |
| 377 | 377 | PORT_START("W14") |
| 378 | | |
| 378 | PORT_DIPNAME( 0x04, 0x04, "W14") PORT_TOGGLE | |
| 379 | 379 | PORT_DIPSETTING( 0x04, DEF_STR( Off ) ) |
| 380 | 380 | PORT_DIPSETTING( 0x00, DEF_STR( On ) ) |
| 381 | 381 | PORT_START("W15") |
| 382 | | |
| 382 | PORT_DIPNAME( 0x08, 0x08, "W15") PORT_TOGGLE | |
| 383 | 383 | PORT_DIPSETTING( 0x08, DEF_STR( Off ) ) |
| 384 | 384 | PORT_DIPSETTING( 0x00, DEF_STR( On ) ) |
| 385 | 385 | PORT_START("W18") |
| 386 | | |
| 386 | PORT_DIPNAME( 0x00, 0x04, "W18") PORT_TOGGLE | |
| 387 | 387 | PORT_DIPSETTING( 0x04, DEF_STR( Off ) ) |
| 388 | 388 | PORT_DIPSETTING( 0x00, DEF_STR( On ) ) |
| 389 | 389 | INPUT_PORTS_END |
| r25360 | r25361 | |
| 398 | 398 | m_kbd_tx_ready = m_kbd_rx_ready = false; |
| 399 | 399 | |
| 400 | 400 | m_kbd8251->input_callback(SERIAL_STATE_CTS); // raise clear to send |
| 401 | ||
| 402 | m_KBD = 0; | |
| 403 | 401 | |
| 402 | m_KBD = 0; | |
| 403 | ||
| 404 | 404 | m_beep->set_frequency(2000); |
| 405 | m_beep->set_state(0); | |
| 406 | ||
| 405 | m_beep->set_state(0); | |
| 406 | ||
| 407 | 407 | // RESET ALL LEDs |
| 408 | 408 | output_set_value("led1", 1); |
| 409 | 409 | output_set_value("led2", 1); |
| r25360 | r25361 | |
| 416 | 416 | output_set_value("led9", 1); |
| 417 | 417 | output_set_value("led10", 1); |
| 418 | 418 | output_set_value("led11", 1); |
| 419 | ||
| 419 | ||
| 420 | 420 | output_set_value("led20", 1); // DRIVE 0 (A) |
| 421 | 421 | output_set_value("led21", 1); // DRIVE 1 (B) |
| 422 | 422 | } |
| r25360 | r25361 | |
| 431 | 431 | // WANTED: is a cleaner, more compatible way feasible? |
| 432 | 432 | READ8_MEMBER(rainbow_state::floating_bus_r) |
| 433 | 433 | { |
| 434 | if ( m_maincpu->state_int(I8086_CS) != 0xF400) | |
| 435 | return space.read_byte(offset); | |
| 434 | if ( m_maincpu->state_int(I8086_CS) != 0xF400) | |
| 435 | return space.read_byte(offset); | |
| 436 | 436 | |
| 437 | if ( m_maincpu->state_int(I8086_DS) < m_inp8->read() ) | |
| 438 | { | |
| 439 | return space.read_byte(offset); | |
| 440 | } else | |
| 441 | { | |
| 442 | return (offset>>16) + 2; | |
| 443 | } | |
| 437 | if ( m_maincpu->state_int(I8086_DS) < m_inp8->read() ) | |
| 438 | { | |
| 439 | return space.read_byte(offset); | |
| 440 | } else | |
| 441 | { | |
| 442 | return (offset>>16) + 2; | |
| 443 | } | |
| 444 | 444 | } |
| 445 | 445 | |
| 446 | 446 | WRITE8_MEMBER(rainbow_state::floating_bus_w) |
| 447 | 447 | { |
| 448 | ||
| 448 | space.write_byte(offset,data); | |
| 449 | 449 | } |
| 450 | 450 | |
| 451 | 451 | |
| r25360 | r25361 | |
| 507 | 507 | |
| 508 | 508 | READ8_MEMBER(rainbow_state::system_parameter_r) |
| 509 | 509 | { |
| 510 | /* | |
| 510 | /* Info about option boards is in bits 0 - 3: | |
| 511 | 511 | Bundle card (1) | Floppy (2) | Graphics (4) | Memory option (8) |
| 512 | 512 | |
| 513 | ||
| 513 | 0 1 2 3 4 5 6 7 | |
| 514 | 514 | B F G M |
| 515 | 515 | ( 1 means NOT present ) |
| 516 | 516 | */ |
| 517 | 517 | // Hard coded value 0x2000 - see DIP switch setup! |
| 518 | return 0x0f - m_inp5->read() - m_inp6->read() - m_inp7->read() - ( | |
| 519 | (m_inp8->read() > 0x2000) ? 8 : 0 | |
| 520 | ); | |
| 518 | return 0x0f - m_inp5->read() - m_inp6->read() - m_inp7->read() - ( | |
| 519 | (m_inp8->read() > 0x2000) ? 8 : 0 | |
| 520 | ); | |
| 521 | 521 | } |
| 522 | 522 | |
| 523 | 523 | READ8_MEMBER(rainbow_state::comm_control_r) |
| 524 | 524 | { |
| 525 | ||
| 525 | // Our simple COLDBOOT flag is adequate for the initial MHFU test (at BIOS location 00A8). | |
| 526 | 526 | |
| 527 | // TODO: on real hardware, MHFU detection is disabled BY WRITING TO 0x10c (=> BIOS assumes power-up reset) | |
| 528 | // MHFU is enabled by writing to 0x0c. | |
| 529 | if (m_COLDBOOT) | |
| 530 | { m_COLDBOOT = 0; | |
| 531 | return ( 0x20 ); // bit 5 = watchdog detect. | |
| 532 | } else { | |
| 533 | return ( 0x00 ); // ERROR 16 is displayed = watchdog triggered | |
| 534 | } | |
| 527 | // TODO: on real hardware, MHFU detection is disabled BY WRITING TO 0x10c (=> BIOS assumes power-up reset) | |
| 528 | // MHFU is enabled by writing to 0x0c. | |
| 529 | if (m_COLDBOOT) | |
| 530 | { m_COLDBOOT = 0; | |
| 531 | return ( 0x20 ); // bit 5 = watchdog detect. | |
| 532 | } else { | |
| 533 | return ( 0x00 ); // ERROR 16 is displayed = watchdog triggered | |
| 534 | } | |
| 535 | 535 | } |
| 536 | 536 | |
| 537 | 537 | WRITE8_MEMBER(rainbow_state::comm_control_w) |
| r25360 | r25361 | |
| 544 | 544 | -4--5--6--7- <- NUMBERS EMBOSSED ON BACK OF PLASTIC HOUSING (see error chart) |
| 545 | 545 | */ |
| 546 | 546 | output_set_value("led4", BIT(data, 5)); // LED "D6" |
| 547 | output_set_value("led5", BIT(data, 7)); // LED "D5" | |
| 547 | output_set_value("led5", BIT(data, 7)); // LED "D5" | |
| 548 | 548 | output_set_value("led6", BIT(data, 6)); // LED "D4" |
| 549 | output_set_value("led7", BIT(data, 4)); // LED "D3" | |
| 549 | output_set_value("led7", BIT(data, 4)); // LED "D3" | |
| 550 | 550 | |
| 551 | 551 | // printf("%02x to COMM.CONTROL REGISTER\n", data); |
| 552 | 552 | } |
| r25360 | r25361 | |
| 554 | 554 | // EMULATOR TRAP (patched into ROM @ machine_start) via BIOS : call / offset +$21 (AL / AH) |
| 555 | 555 | WRITE8_MEMBER(rainbow_state::PORT90_W) |
| 556 | 556 | { |
| 557 | //printf("KBD COMMAND : %02x to AL (90)\n", data); | |
| 558 | ||
| 557 | //printf("KBD COMMAND : %02x to AL (90)\n", data); | |
| 558 | ||
| 559 | 559 | m_KBD = 0; // reset previous command. |
| 560 | 560 | |
| 561 | if (data == 0xfd) { // Powerup (beep) | |
| 562 | m_beep->set_state(1); | |
| 563 | m_beep_counter=600; // BELL = 125 ms | |
| 561 | if (data == 0xfd) { // Powerup (beep) | |
| 562 | m_beep->set_state(1); | |
| 563 | m_beep_counter=600; // BELL = 125 ms | |
| 564 | 564 | } |
| 565 | 565 | |
| 566 | if (data == 0xa7) { | |
| 567 | m_beep->set_state(1); | |
| 568 | m_beep_counter=600; // BELL = 125 ms | |
| 566 | if (data == 0xa7) { | |
| 567 | m_beep->set_state(1); | |
| 568 | m_beep_counter=600; // BELL = 125 ms | |
| 569 | 569 | } |
| 570 | 570 | |
| 571 | 571 | if (data == 0x9f) { // emit a keyclick (2ms) |
| 572 | m_beep->set_state(1); | |
| 572 | m_beep->set_state(1); | |
| 573 | 573 | m_beep_counter=25; // longer than calculated ( 9,6 ) |
| 574 | 574 | } |
| 575 | 575 | |
| 576 | if (data == 0x13) { // light LEDs - | |
| 577 | m_KBD = 0x13; | |
| 576 | if (data == 0x13) { // light LEDs - | |
| 577 | m_KBD = 0x13; | |
| 578 | 578 | } |
| 579 | if (data == 0x11) { // switch off LEDs - | |
| 580 | m_KBD = 0x11; | |
| 579 | if (data == 0x11) { // switch off LEDs - | |
| 580 | m_KBD = 0x11; | |
| 581 | 581 | } |
| 582 | 582 | } |
| 583 | 583 | |
| 584 | 584 | WRITE8_MEMBER(rainbow_state::PORT91_W) |
| 585 | 585 | { |
| 586 | //printf("KBD PARAM %02x to AH (91) \n", data); | |
| 587 | ||
| 588 | // 4 leds, represented in the low 4 bits of a byte | |
| 589 | if (m_KBD == 0x13) { // light LEDs - | |
| 590 | if (data & 1) { output_set_value("led8", 0); } // KEYBOARD : "Wait" LED | |
| 586 | //printf("KBD PARAM %02x to AH (91) \n", data); | |
| 587 | ||
| 588 | // 4 leds, represented in the low 4 bits of a byte | |
| 589 | if (m_KBD == 0x13) { // light LEDs - | |
| 590 | if (data & 1) { output_set_value("led8", 0); } // KEYBOARD : "Wait" LED | |
| 591 | 591 | if (data & 2) { output_set_value("led9", 0); } // KEYBOARD : "Compose" LED |
| 592 | 592 | if (data & 4) { output_set_value("led10", 0); } // KEYBOARD : "Lock" LED |
| 593 | 593 | if (data & 8) { output_set_value("led11", 0); } // KEYBOARD : "Hold" LED |
| 594 | 594 | m_KBD = 0; // reset previous command. |
| 595 | 595 | } |
| 596 | if (m_KBD == 0x11) { // switch off LEDs - | |
| 597 | if (data & 1) { output_set_value("led8", 1); } // KEYBOARD : "Wait" LED | |
| 596 | if (m_KBD == 0x11) { // switch off LEDs - | |
| 597 | if (data & 1) { output_set_value("led8", 1); } // KEYBOARD : "Wait" LED | |
| 598 | 598 | if (data & 2) { output_set_value("led9", 1); } // KEYBOARD : "Compose" LED |
| 599 | 599 | if (data & 4) { output_set_value("led10", 1); } // KEYBOARD : "Lock" LED |
| 600 | 600 | if (data & 8) { output_set_value("led11", 1); } // KEYBOARD : "Hold" LED |
| 601 | 601 | m_KBD = 0; // reset previous command. |
| 602 | 602 | } |
| 603 | ||
| 603 | ||
| 604 | 604 | if (m_KBD == 0x1b) { /* enable the keyclick */ |
| 605 | 605 | /* max volume is 0, lowest is 0x7 */ |
| 606 | 606 | m_KBD = 0; // reset previous command. |
| r25360 | r25361 | |
| 644 | 644 | { |
| 645 | 645 | /* Z80 LEDs: |
| 646 | 646 | 4 5 6 <- bit # |
| 647 | D11 D10 -D9 <- INTERNAL LED NUMBER (see PDF) | |
| 648 | -1 --2-- 3 <- NUMBERS EMBOSSED ON BACK OF PLASTIC HOUSING (see error chart) | |
| 647 | D11 D10 -D9 <- INTERNAL LED NUMBER (see PDF) | |
| 648 | -1 --2-- 3 <- NUMBERS EMBOSSED ON BACK OF PLASTIC HOUSING (see error chart) | |
| 649 | 649 | */ |
| 650 | 650 | output_set_value("led1", BIT(data, 4)); // LED "D11" |
| 651 | 651 | output_set_value("led2", BIT(data, 5)); // LED "D10" |
| r25360 | r25361 | |
| 656 | 656 | |
| 657 | 657 | WRITE8_MEMBER(rainbow_state::z80_diskcontrol_write_w) |
| 658 | 658 | { |
| 659 | ||
| 659 | //printf("%02x to z80 DISK CONTROL (W)\n", data); | |
| 660 | 660 | |
| 661 | // TODO: this logic is a bit primitive. According to the spec, the RX-50 drive LED only turns on if | |
| 661 | // TODO: this logic is a bit primitive. According to the spec, the RX-50 drive LED only turns on if | |
| 662 | 662 | // (a) spindle motor runs (b) disk is in drive (c) door closed (d) drive side is selected |
| 663 | if ( (data & 1) && (data & 8) ) | |
| 664 | output_set_value("led20", 0); // DISKETTE 0 SELECTED & MOTOR 0 ON => LIGHT "DRIVE A" | |
| 663 | if ( (data & 1) && (data & 8) ) | |
| 664 | output_set_value("led20", 0); // DISKETTE 0 SELECTED & MOTOR 0 ON => LIGHT "DRIVE A" | |
| 665 | 665 | else |
| 666 | | |
| 666 | output_set_value("led20", 1); | |
| 667 | 667 | |
| 668 | if ( (data & 2) && (data & 8) ) | |
| 669 | output_set_value("led21", 0); // DISKETTE 1 SELECTED & MOTOR 0 ON => LIGHT "DRIVE B" | |
| 668 | if ( (data & 2) && (data & 8) ) | |
| 669 | output_set_value("led21", 0); // DISKETTE 1 SELECTED & MOTOR 0 ON => LIGHT "DRIVE B" | |
| 670 | 670 | else |
| 671 | | |
| 671 | output_set_value("led21", 1); | |
| 672 | 672 | } |
| 673 | 673 | |
| 674 | 674 | READ8_MEMBER( rainbow_state::read_video_ram_r ) |
| r25360 | r25361 | |
| 691 | 691 | // printf("%02x DIP value ORed to diagnostic\n", ( m_inp1->read() | m_inp2->read() | m_inp3->read() ) ); |
| 692 | 692 | |
| 693 | 693 | return ( (m_diagnostic & (0xf1)) | ( m_inp1->read() | |
| 694 | m_inp2->read() | | |
| 695 | m_inp3->read() ) | |
| 696 | ); | |
| 694 | m_inp2->read() | | |
| 695 | m_inp3->read() ) | |
| 696 | ); | |
| 697 | 697 | } |
| 698 | 698 | |
| 699 | 699 | WRITE8_MEMBER( rainbow_state::diagnostic_w ) |
| r25360 | r25361 | |
| 758 | 758 | { |
| 759 | 759 | m_kbd8251->transmit_clock(); |
| 760 | 760 | m_kbd8251->receive_clock(); |
| 761 | ||
| 762 | if (m_beep_counter > 1) | |
| 763 | m_beep_counter--; | |
| 764 | else | |
| 765 | if ( m_beep_counter == 1 ) | |
| 761 | ||
| 762 | if (m_beep_counter > 1) | |
| 763 | m_beep_counter--; | |
| 764 | else | |
| 765 | if ( m_beep_counter == 1 ) | |
| 766 | 766 | { m_beep->set_state(0); |
| 767 | m_beep_counter = 0; | |
| 768 | } | |
| 767 | m_beep_counter = 0; | |
| 768 | } | |
| 769 | 769 | } |
| 770 | 770 | |
| 771 | 771 | static const vt_video_interface video_interface = |
| r25360 | r25361 | |
| 852 | 852 | MCFG_PALETTE_LENGTH(3) |
| 853 | 853 | MCFG_PALETTE_INIT_OVERRIDE(driver_device, monochrome_amber) |
| 854 | 854 | MCFG_RAINBOW_VIDEO_ADD("vt100_video", video_interface) |
| 855 | ||
| 855 | ||
| 856 | 856 | /* sound hardware */ |
| 857 | 857 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 858 | 858 | MCFG_SOUND_ADD("beeper", BEEP, 0) |
| r25360 | r25361 | |
|---|---|---|
| 960 | 960 | MCFG_VIA6522_ADD("via6522_0", 1000000, mac_via6522_intf) |
| 961 | 961 | |
| 962 | 962 | MCFG_MACKBD_ADD() |
| 963 | ||
| 963 | MCFG_MACKBD_CLKOUT_HANDLER(WRITELINE(mac_state, mac_kbd_clk_in)) | |
| 964 | 964 | |
| 965 | 965 | /* internal ram */ |
| 966 | 966 | MCFG_RAM_ADD(RAM_TAG) |
| r25360 | r25361 | |
|---|---|---|
| 24 | 24 | - Carrier: Jaleco logo uses YUV, but y size is halved? |
| 25 | 25 | - Close To: Hangs at FMV |
| 26 | 26 | - F355 Challenge: black screen after Sega logo; |
| 27 | - Gundam - Side Story 0079: currently hangs at Bandai logo (regression) | |
| 28 | - Idol Janshi wo Tsukucchaou: pixel aspect is way wrong (stretched and offsetted horizontally) | |
| 29 | - Power Stone: hangs at Capcom logo; | |
| 30 | - Sega GT: no cursor on main menu; | |
| 31 | - Tetris 4D: hangs at BPS FMV (bp 0C0B0C4E) | |
| 27 | - Gundam - Side Story 0079: currently hangs at Bandai logo (regression) | |
| 28 | - Idol Janshi wo Tsukucchaou: pixel aspect is way wrong (stretched and offsetted horizontally) | |
| 29 | - Power Stone: hangs at Capcom logo; | |
| 30 | - Sega GT: no cursor on main menu; | |
| 31 | - Tetris 4D: hangs at BPS FMV (bp 0C0B0C4E) | |
| 32 | 32 | |
| 33 | Notes: | |
| 34 | - DC US and DC PAL flash ROMs are definitely hacked, they are set to have Chinese instead of Japanese. | |
| 35 | - 0x1a002 of flash ROM returns the region type (0x30=Japan, 0x31=USA, 0x32=Europe). Amusingly, if the value | |
| 36 | on a non-jp console is different than these ones, the system shows a black swirl (and nothing boots). | |
| 37 | - gdi file for DCLP (a Dreamcast tester) doesn't have first two tracks info, they are: | |
| 38 | 1 0 4 2048 FILE0001.DUP 0 | |
| 33 | Notes: | |
| 34 | - DC US and DC PAL flash ROMs are definitely hacked, they are set to have Chinese instead of Japanese. | |
| 35 | - 0x1a002 of flash ROM returns the region type (0x30=Japan, 0x31=USA, 0x32=Europe). Amusingly, if the value | |
| 36 | on a non-jp console is different than these ones, the system shows a black swirl (and nothing boots). | |
| 37 | - gdi file for DCLP (a Dreamcast tester) doesn't have first two tracks info, they are: | |
| 38 | 1 0 4 2048 FILE0001.DUP 0 | |
| 39 | 39 | 2 1798 0 2352 FILE0002.DUP 0 |
| 40 | serial i/o also fails on that, work ram addresses that needs to be patched with 0x0009 (nop) are: | |
| 41 | 0xc0196da | |
| 42 | 0xc0196ec | |
| 43 | SH4 TEST: | |
| 44 | UBC test (0101): | |
| 45 | ok | |
| 46 | FPU test (0201): | |
| 47 | NG | |
| 48 | 0xc03fe24 work ram flag check (1=error, 0=ok) | |
| 49 | Cache test (03xx): | |
| 50 | Cache Read/Write test (0301) | |
| 51 | NG | |
| 52 | Cache RAM mode Check (0305) | |
| 53 | NG | |
| 54 | MMU test (04xx): | |
| 55 | asserts | |
| 56 | TMU test (0501): | |
| 57 | *_reg check -> ok | |
| 58 | TCNT* reload -> NG | |
| 59 | TCNT* underflow irq -> NG | |
| 60 | MULT test (0601) | |
| 61 | ok | |
| 62 | DIVU test (0701) | |
| 63 | ok | |
| 64 | Store Queue test (0801): | |
| 65 | ok | |
| 66 | SCIF test (0901) | |
| 67 | NG | |
| 68 | Private Instruction test (0a01) | |
| 69 | NG | |
| 70 | Critical test (0dxx) | |
| 71 | Critical (Store Queue) test (0d01): | |
| 72 | ok | |
| 73 | Critical (Write back) test (0d02): | |
| 74 | ok | |
| 75 | Critical (ADD,CMP/EQ) test (0d03): | |
| 76 | ok | |
| 77 | Critical (OC_OIX) test (0d04): | |
| 78 | NG | |
| 79 | Critical (MAX current) test (0d05): | |
| 80 | ok (very slow!) | |
| 81 | Critical (IC Cross Talk) test (0d06): | |
| 82 | NG | |
| 83 | Critical (Cache D-array) test (0d07): | |
| 84 | NG | |
| 85 | SH-4 BUG (0exx) | |
| 86 | SH4_BUG 64bit FMOV | |
| 87 | ok | |
| 88 | SH4 BUG FIX (64bitFMOV) | |
| 89 | ok | |
| 90 | MEM TEST: | |
| 91 | AICA (0102) | |
| 92 | ok | |
| 93 | Work RAM (0204): | |
| 94 | ok | |
| 95 | PV64 area (0303): | |
| 96 | ok | |
| 97 | PV32 area (0403): | |
| 98 | ok | |
| 99 | CLX TEST: | |
| 100 | CLX internal RAM (0101): | |
| 101 | ok | |
| 102 | <Torus> check (0401): | |
| 103 | (sets up RGB888 mode 2, assuming it's critically failed) | |
| 104 | TA TEST: | |
| 105 | TA_YUVINT (0101): | |
| 106 | ok -> IST_EOXFER_YUV | |
| 107 | TA_OENDINT (0102): | |
| 108 | ok -> IST_EOXFER_OPLST | |
| 109 | TA_OMENDINT (0103): | |
| 110 | ok -> IST_EOXFER_OPMV | |
| 111 | TA_TENDINT (0104): | |
| 112 | ok -> IST_EOXFER_TRLST | |
| 113 | TA_TMENDINT (0105): | |
| 114 | ok -> IST_EOXFER_TRMV | |
| 115 | TA_PTENDINT (0106): | |
| 116 | ok -> IST_EOXFER_PTLST | |
| 117 | TA_ISPINT (0107): | |
| 118 | NG -> ISP/TSP Parameter Overflow (error) | |
| 119 | TA_OBJINT (0108): | |
| 120 | NG -> OBJect list pointer Overflow (error) | |
| 121 | TA_IPINT (0109): | |
| 122 | NG -> TA: Illegal parameter (error) | |
| 123 | YUV Converter (0201): | |
| 124 | ok | |
| 125 | DDT i/f TEST: | |
| 126 | Sort, Normal DMA (1) (0101) | |
| 127 | hangs (wants Sort DMA irq, of course) | |
| 128 | Sort, Normal DMA (2) | |
| 129 | ... | |
| 130 | Through | |
| 131 | NG, hangs again | |
| 132 | DC_DEINT (0201) | |
| 133 | ok | |
| 134 | DC_SDTEINT (0202) | |
| 135 | ok | |
| 136 | DC_SDTERINT (0203) | |
| 137 | ok (but returns error count ++, think it's a bug in the SW) | |
| 138 | G2 TEST | |
| 139 | DMA (0101): | |
| 140 | G2 EXT AREA DETECT: | |
| 141 | "!!!! ch00 ERROR DETECT !!!!" | |
| 142 | Interrupt (0301): | |
| 143 | G2 EXT AREA DETECT | |
| 144 | DMA END INT | |
| 145 | hangs | |
| 146 | Ext Interrupt (06xx) | |
| 147 | AICA INT (0601) | |
| 148 | error detect | |
| 149 | Modem INT (0602) | |
| 150 | error detect | |
| 151 | AICA TEST | |
| 152 | Sound RAM (01xx) | |
| 153 | Pattern R/W check (0101) | |
| 154 | ok | |
| 155 | Register (02xx) | |
| 156 | CH Data (0201) | |
| 157 | ok | |
| 158 | EXT Input (0202) | |
| 159 | ok | |
| 160 | DSP Data (0203) | |
| 161 | ok | |
| 162 | S_Clock (03xx) | |
| 163 | 50MSEC (0301) | |
| 164 | NG -> ~0xa58 in 0x702814, must be > 0x889 and < 0x8b0 | |
| 165 | 25MSEC (0302) | |
| 166 | NG -> ~0x372 in 0x702814, must be > 0x443 and < 0x45a | |
| 167 | Timer (04xx) | |
| 168 | Timer A (0401) | |
| 169 | NG | |
| 170 | Timer B (0402) | |
| 171 | NG | |
| 172 | Timer C (0403) | |
| 173 | NG | |
| 174 | DMA (05xx) | |
| 175 | SRAM -> CH Reg (0501) | |
| 176 | ok | |
| 177 | SRAM -> Comm Reg (0502) | |
| 178 | ok | |
| 179 | SRAM -> DSP Reg (0503) | |
| 180 | ok | |
| 181 | CH Reg -> SRAM (0504) | |
| 182 | ok | |
| 183 | Comm Reg -> SRAM (0505) | |
| 184 | ok | |
| 185 | DSP Reg -> SRAM (0506) | |
| 186 | ok | |
| 187 | Clear SRAM (0507) | |
| 188 | ok | |
| 189 | Clear CH Reg (0508) | |
| 190 | ok | |
| 191 | Clear Comm Reg (0509) | |
| 192 | ok | |
| 193 | Clear DSP Reg (050a) | |
| 194 | ok | |
| 195 | Interrupt (06xx) | |
| 196 | Sampling clock (0601) | |
| 197 | NG (irq 0x400) | |
| 198 | Timer A (0602) | |
| 199 | randomly NG/ok | |
| 200 | Timer B (0603) | |
| 201 | ok | |
| 202 | Timer C (0604) | |
| 203 | ok | |
| 204 | DMA End (0605) | |
| 205 | ok | |
| 206 | Midi Out (0606) | |
| 207 | NG | |
| 208 | Main CPU (0607) | |
| 209 | ok | |
| 210 | RTC (07xx) | |
| 211 | Write Protect (0701) | |
| 212 | ok | |
| 213 | RW Comp (0702) | |
| 214 | ok | |
| 215 | Clock (0703) | |
| 216 | NG | |
| 217 | ARM7 (08xx) | |
| 218 | Load & Start (0801) | |
| 219 | NG | |
| 220 | Timer & Intr (0802) | |
| 221 | NG | |
| 222 | DMA (0803) | |
| 223 | NG | |
| 224 | Ch-Reg R/W (0804) | |
| 225 | ok | |
| 226 | SRAM incr (0805) | |
| 227 | NG | |
| 228 | SRAM pattern (0806) | |
| 229 | ok | |
| 230 | EG (09xx) | |
| 231 | LSA-Reg Left (0901) | |
| 232 | ok/NG | |
| 233 | LSA-Reg Right (0902) | |
| 234 | ok/NG | |
| 235 | LSA-Reg Left & Right (0903) | |
| 236 | ok/NG | |
| 237 | MIDI (0axx) | |
| 238 | OEMP bit (0a01) | |
| 239 | NG | |
| 240 | OFLL bit (0a02) | |
| 241 | NG | |
| 242 | PVRi/f test | |
| 243 | DMA (01xx) | |
| 244 | CPU trig (0101) | |
| 245 | ok | |
| 246 | INT trig | |
| 247 | ok | |
| 248 | Interrupt (02xx) | |
| 249 | PVR DMA end Int (0201) | |
| 250 | ok | |
| 251 | PVR DMA IA Int (0202) | |
| 252 | NG | |
| 253 | PVR DMA end (0203) | |
| 254 | NG | |
| 255 | Flash test: | |
| 256 | (SH-4 jumps to la la land as soon as this is started) | |
| 40 | serial i/o also fails on that, work ram addresses that needs to be patched with 0x0009 (nop) are: | |
| 41 | 0xc0196da | |
| 42 | 0xc0196ec | |
| 43 | SH4 TEST: | |
| 44 | UBC test (0101): | |
| 45 | ok | |
| 46 | FPU test (0201): | |
| 47 | NG | |
| 48 | 0xc03fe24 work ram flag check (1=error, 0=ok) | |
| 49 | Cache test (03xx): | |
| 50 | Cache Read/Write test (0301) | |
| 51 | NG | |
| 52 | Cache RAM mode Check (0305) | |
| 53 | NG | |
| 54 | MMU test (04xx): | |
| 55 | asserts | |
| 56 | TMU test (0501): | |
| 57 | *_reg check -> ok | |
| 58 | TCNT* reload -> NG | |
| 59 | TCNT* underflow irq -> NG | |
| 60 | MULT test (0601) | |
| 61 | ok | |
| 62 | DIVU test (0701) | |
| 63 | ok | |
| 64 | Store Queue test (0801): | |
| 65 | ok | |
| 66 | SCIF test (0901) | |
| 67 | NG | |
| 68 | Private Instruction test (0a01) | |
| 69 | NG | |
| 70 | Critical test (0dxx) | |
| 71 | Critical (Store Queue) test (0d01): | |
| 72 | ok | |
| 73 | Critical (Write back) test (0d02): | |
| 74 | ok | |
| 75 | Critical (ADD,CMP/EQ) test (0d03): | |
| 76 | ok | |
| 77 | Critical (OC_OIX) test (0d04): | |
| 78 | NG | |
| 79 | Critical (MAX current) test (0d05): | |
| 80 | ok (very slow!) | |
| 81 | Critical (IC Cross Talk) test (0d06): | |
| 82 | NG | |
| 83 | Critical (Cache D-array) test (0d07): | |
| 84 | NG | |
| 85 | SH-4 BUG (0exx) | |
| 86 | SH4_BUG 64bit FMOV | |
| 87 | ok | |
| 88 | SH4 BUG FIX (64bitFMOV) | |
| 89 | ok | |
| 90 | MEM TEST: | |
| 91 | AICA (0102) | |
| 92 | ok | |
| 93 | Work RAM (0204): | |
| 94 | ok | |
| 95 | PV64 area (0303): | |
| 96 | ok | |
| 97 | PV32 area (0403): | |
| 98 | ok | |
| 99 | CLX TEST: | |
| 100 | CLX internal RAM (0101): | |
| 101 | ok | |
| 102 | <Torus> check (0401): | |
| 103 | (sets up RGB888 mode 2, assuming it's critically failed) | |
| 104 | TA TEST: | |
| 105 | TA_YUVINT (0101): | |
| 106 | ok -> IST_EOXFER_YUV | |
| 107 | TA_OENDINT (0102): | |
| 108 | ok -> IST_EOXFER_OPLST | |
| 109 | TA_OMENDINT (0103): | |
| 110 | ok -> IST_EOXFER_OPMV | |
| 111 | TA_TENDINT (0104): | |
| 112 | ok -> IST_EOXFER_TRLST | |
| 113 | TA_TMENDINT (0105): | |
| 114 | ok -> IST_EOXFER_TRMV | |
| 115 | TA_PTENDINT (0106): | |
| 116 | ok -> IST_EOXFER_PTLST | |
| 117 | TA_ISPINT (0107): | |
| 118 | NG -> ISP/TSP Parameter Overflow (error) | |
| 119 | TA_OBJINT (0108): | |
| 120 | NG -> OBJect list pointer Overflow (error) | |
| 121 | TA_IPINT (0109): | |
| 122 | NG -> TA: Illegal parameter (error) | |
| 123 | YUV Converter (0201): | |
| 124 | ok | |
| 125 | DDT i/f TEST: | |
| 126 | Sort, Normal DMA (1) (0101) | |
| 127 | hangs (wants Sort DMA irq, of course) | |
| 128 | Sort, Normal DMA (2) | |
| 129 | ... | |
| 130 | Through | |
| 131 | NG, hangs again | |
| 132 | DC_DEINT (0201) | |
| 133 | ok | |
| 134 | DC_SDTEINT (0202) | |
| 135 | ok | |
| 136 | DC_SDTERINT (0203) | |
| 137 | ok (but returns error count ++, think it's a bug in the SW) | |
| 138 | G2 TEST | |
| 139 | DMA (0101): | |
| 140 | G2 EXT AREA DETECT: | |
| 141 | "!!!! ch00 ERROR DETECT !!!!" | |
| 142 | Interrupt (0301): | |
| 143 | G2 EXT AREA DETECT | |
| 144 | DMA END INT | |
| 145 | hangs | |
| 146 | Ext Interrupt (06xx) | |
| 147 | AICA INT (0601) | |
| 148 | error detect | |
| 149 | Modem INT (0602) | |
| 150 | error detect | |
| 151 | AICA TEST | |
| 152 | Sound RAM (01xx) | |
| 153 | Pattern R/W check (0101) | |
| 154 | ok | |
| 155 | Register (02xx) | |
| 156 | CH Data (0201) | |
| 157 | ok | |
| 158 | EXT Input (0202) | |
| 159 | ok | |
| 160 | DSP Data (0203) | |
| 161 | ok | |
| 162 | S_Clock (03xx) | |
| 163 | 50MSEC (0301) | |
| 164 | NG -> ~0xa58 in 0x702814, must be > 0x889 and < 0x8b0 | |
| 165 | 25MSEC (0302) | |
| 166 | NG -> ~0x372 in 0x702814, must be > 0x443 and < 0x45a | |
| 167 | Timer (04xx) | |
| 168 | Timer A (0401) | |
| 169 | NG | |
| 170 | Timer B (0402) | |
| 171 | NG | |
| 172 | Timer C (0403) | |
| 173 | NG | |
| 174 | DMA (05xx) | |
| 175 | SRAM -> CH Reg (0501) | |
| 176 | ok | |
| 177 | SRAM -> Comm Reg (0502) | |
| 178 | ok | |
| 179 | SRAM -> DSP Reg (0503) | |
| 180 | ok | |
| 181 | CH Reg -> SRAM (0504) | |
| 182 | ok | |
| 183 | Comm Reg -> SRAM (0505) | |
| 184 | ok | |
| 185 | DSP Reg -> SRAM (0506) | |
| 186 | ok | |
| 187 | Clear SRAM (0507) | |
| 188 | ok | |
| 189 | Clear CH Reg (0508) | |
| 190 | ok | |
| 191 | Clear Comm Reg (0509) | |
| 192 | ok | |
| 193 | Clear DSP Reg (050a) | |
| 194 | ok | |
| 195 | Interrupt (06xx) | |
| 196 | Sampling clock (0601) | |
| 197 | NG (irq 0x400) | |
| 198 | Timer A (0602) | |
| 199 | randomly NG/ok | |
| 200 | Timer B (0603) | |
| 201 | ok | |
| 202 | Timer C (0604) | |
| 203 | ok | |
| 204 | DMA End (0605) | |
| 205 | ok | |
| 206 | Midi Out (0606) | |
| 207 | NG | |
| 208 | Main CPU (0607) | |
| 209 | ok | |
| 210 | RTC (07xx) | |
| 211 | Write Protect (0701) | |
| 212 | ok | |
| 213 | RW Comp (0702) | |
| 214 | ok | |
| 215 | Clock (0703) | |
| 216 | NG | |
| 217 | ARM7 (08xx) | |
| 218 | Load & Start (0801) | |
| 219 | NG | |
| 220 | Timer & Intr (0802) | |
| 221 | NG | |
| 222 | DMA (0803) | |
| 223 | NG | |
| 224 | Ch-Reg R/W (0804) | |
| 225 | ok | |
| 226 | SRAM incr (0805) | |
| 227 | NG | |
| 228 | SRAM pattern (0806) | |
| 229 | ok | |
| 230 | EG (09xx) | |
| 231 | LSA-Reg Left (0901) | |
| 232 | ok/NG | |
| 233 | LSA-Reg Right (0902) | |
| 234 | ok/NG | |
| 235 | LSA-Reg Left & Right (0903) | |
| 236 | ok/NG | |
| 237 | MIDI (0axx) | |
| 238 | OEMP bit (0a01) | |
| 239 | NG | |
| 240 | OFLL bit (0a02) | |
| 241 | NG | |
| 242 | PVRi/f test | |
| 243 | DMA (01xx) | |
| 244 | CPU trig (0101) | |
| 245 | ok | |
| 246 | INT trig | |
| 247 | ok | |
| 248 | Interrupt (02xx) | |
| 249 | PVR DMA end Int (0201) | |
| 250 | ok | |
| 251 | PVR DMA IA Int (0202) | |
| 252 | NG | |
| 253 | PVR DMA end (0203) | |
| 254 | NG | |
| 255 | Flash test: | |
| 256 | (SH-4 jumps to la la land as soon as this is started) | |
| 257 | 257 | |
| 258 | 258 | |
| 259 | 259 | */ |
| r25360 | r25361 | |
| 275 | 275 | READ64_MEMBER(dc_cons_state::dcus_idle_skip_r ) |
| 276 | 276 | { |
| 277 | 277 | //if (space.device().safe_pc()==0xc0ba52a) |
| 278 | // | |
| 278 | // space.device().execute().spin_until_time(attotime::from_usec(2500)); | |
| 279 | 279 | // device_spinuntil_int(&space.device()); |
| 280 | 280 | |
| 281 | 281 | return dc_ram[0x2303b0/8]; |
| r25360 | r25361 | |
| 284 | 284 | READ64_MEMBER(dc_cons_state::dcjp_idle_skip_r ) |
| 285 | 285 | { |
| 286 | 286 | //if (space.device().safe_pc()==0xc0bac62) |
| 287 | // | |
| 287 | // space.device().execute().spin_until_time(attotime::from_usec(2500)); | |
| 288 | 288 | // device_spinuntil_int(&space.device()); |
| 289 | 289 | |
| 290 | 290 | return dc_ram[0x2302f8/8]; |
| r25360 | r25361 | |
| 384 | 384 | AM_RANGE(0x00800000, 0x009fffff) AM_READWRITE(dc_arm_r, dc_arm_w ) |
| 385 | 385 | // AM_RANGE(0x01000000, 0x01ffffff) G2 Ext Device #1 |
| 386 | 386 | // AM_RANGE(0x02700000, 0x02707fff) AICA reg mirror |
| 387 | // | |
| 387 | // AM_RANGE(0x02800000, 0x02ffffff) AICA wave mem mirror | |
| 388 | 388 | |
| 389 | 389 | // AM_RANGE(0x03000000, 0x03ffffff) G2 Ext Device #2 |
| 390 | 390 | |
| r25360 | r25361 | |
| 627 | 627 | |
| 628 | 628 | MCFG_MACHINE_RESET_OVERRIDE(dc_cons_state,dc_console ) |
| 629 | 629 | |
| 630 | // | |
| 630 | // MCFG_MACRONIX_29LV160TMC_ADD("dcflash") | |
| 631 | 631 | |
| 632 | 632 | MCFG_MAPLE_DC_ADD( "maple_dc", "maincpu", dc_maple_irq ) |
| 633 | 633 | MCFG_DC_CONTROLLER_ADD("dcctrl0", "maple_dc", 0, ":P1:0", ":P1:1", ":P1:A0", ":P1:A1", ":P1:A2", ":P1:A3", ":P1:A4", ":P1:A5") |
| r25360 | r25361 | |
|---|---|---|
| 83 | 83 | - Bishoujo Shanshinkan: has white rectangles all over the place; |
| 84 | 84 | - Bishoujo Tsuushin: hangs with a beep while writing some intro text; |
| 85 | 85 | |
| 86 | - Bomber Quest: beeps when speech is supposed to be played (0->1 to i/o port 0xfe8e?) | |
| 87 | - Deflektor: no sound, moans about a DIP-sw during loading, very slow on non-pc9801rs machines; | |
| 86 | - Bomber Quest: beeps when speech is supposed to be played (0->1 to i/o port 0xfe8e?) | |
| 87 | - Deflektor: no sound, moans about a DIP-sw during loading, very slow on non-pc9801rs machines; | |
| 88 | 88 | - Dragon Buster: slight issue with window masking; |
| 89 | 89 | - Far Side Moon: doesn't detect sound board (tied to 0x00ec ports) |
| 90 | 90 | - Jan Borg Suzume: gets stuck at a pic8259 read; |
| r25360 | r25361 | |
| 92 | 92 | - Lovely Horror: Doesn't show kanji, tries to read it thru the 0xa9 port; |
| 93 | 93 | - Madou Monogatari 1/2/3: doesn't display bitmap gfxs during gameplay; |
| 94 | 94 | - Quarth: should do a split screen effect, it doesn't hence there are broken gfxs |
| 95 | | |
| 95 | - Princess Maker 2: mouse is buggy; | |
| 96 | 96 | - Princess Maker 2: screen transitions are very ugly (btanb?) |
| 97 | - Puyo Puyo: beeps out when it's supposed to play samples, Not supposed to use ADPCM, is it a PIT issue? | |
| 98 | - Puzznic: trips illegal irq 0x41 (?), prints an error on screen. (PC-9801RS only, writes an 1 to 0x69d2f for whatever reason, almost surely a btanb) | |
| 99 | - Runner's High: wrong double height on the title screen; | |
| 100 | - Sokoban Perfect: hangs at title screen, after loading the menu; | |
| 97 | - Puyo Puyo: beeps out when it's supposed to play samples, Not supposed to use ADPCM, is it a PIT issue? | |
| 98 | - Puzznic: trips illegal irq 0x41 (?), prints an error on screen. (PC-9801RS only, writes an 1 to 0x69d2f for whatever reason, almost surely a btanb) | |
| 99 | - Runner's High: wrong double height on the title screen; | |
| 100 | - Sokoban Perfect: hangs at title screen, after loading the menu; | |
| 101 | 101 | - Sorcerian, Twilight Zone 3: Fails initial booting, issue with 2dd irq? |
| 102 | ||
| 102 | - The Incredible Machine: hangs at main menu (YM mis-fires irq?) | |
| 103 | 103 | - Uchiyama Aki no Chou Bangai: keyboard irq is fussy (sometimes it doesn't register a key press); |
| 104 | 104 | - Uno: uses EGC |
| 105 | ||
| 105 | - Viper V16 Demo: moans with a JP message; | |
| 106 | 106 | |
| 107 | 107 | per-game TODO (PC-9821): |
| 108 | 108 | - Battle Skin Panic: gfx bugs at the Gainax logo, it crashes after it; |
| r25360 | r25361 | |
| 323 | 323 | 0x432: IDE drive switch |
| 324 | 324 | 0x435: <unknown> |
| 325 | 325 | |
| 326 | ||
| 326 | (ISA correlated i/o) | |
| 327 | 327 | ---------------------------------------------------------- |
| 328 | 328 | 0x0640 |WORD|R/W|Data Register |01F0h |
| 329 | 329 | 0x0642 |BYTE| R |Error Register |01F1h |
| r25360 | r25361 | |
| 2291 | 2291 | /* |
| 2292 | 2292 | [0x430] |
| 2293 | 2293 | [Read/write] |
| 2294 | bit 7-0: unknown | |
| 2295 | 00 h = IDE Bank # 1 | |
| 2296 | 01 h = IDE Bank # 2 | |
| 2294 | bit 7-0: unknown | |
| 2295 | 00 h = IDE Bank # 1 | |
| 2296 | 01 h = IDE Bank # 2 | |
| 2297 | 2297 | |
| 2298 | 2298 | [0x432] |
| 2299 | bit 7-0: Bank select | |
| 2300 | 80 h = readout for dummy (only [WRITE]) | |
| 2301 | 00 h = IDE Bank # 1 choice | |
| 2302 | 01 h = IDE Bank # 2 selection | |
| 2299 | bit 7-0: Bank select | |
| 2300 | 80 h = readout for dummy (only [WRITE]) | |
| 2301 | 00 h = IDE Bank # 1 choice | |
| 2302 | 01 h = IDE Bank # 2 selection | |
| 2303 | 2303 | */ |
| 2304 | 2304 | |
| 2305 | 2305 | printf("IDE w %02x %02x\n",offset,data); |
| r25360 | r25361 | |
| 3828 | 3828 | MCFG_80286_A20(pc9801_state, pc9801_286_a20) |
| 3829 | 3829 | MCFG_CPU_VBLANK_INT_DRIVER("screen", pc9801_state, pc9801_vrtc_irq) |
| 3830 | 3830 | |
| 3831 | // | |
| 3831 | // MCFG_I8237_REPLACE("i8237", 10000000, pc9801rs_dmac_intf) // unknown clock | |
| 3832 | 3832 | MACHINE_CONFIG_END |
| 3833 | 3833 | |
| 3834 | 3834 | static MACHINE_CONFIG_DERIVED( pc9801bx2, pc9801rs ) |
| r25360 | r25361 | |
|---|---|---|
| 456 | 456 | The following roms are available should they be considered useful: |
| 457 | 457 | |
| 458 | 458 | ROM_START( mtx_roms ) |
| 459 | ROM_LOAD( "assem.rom", CRC(599d5b6b) SHA1(3ec1f7f476a21ca3206012ded22198c020b47f7d) ) | |
| 460 | ROM_LOAD( "basic.rom", CRC(d1e9ff36) SHA1(e89ae3a627716e6cee7e35054be8a2472bdd49d4) ) | |
| 461 | ROM_LOAD( "boot.rom", CRC(ed98d6dd) SHA1(4671ee49bb96262b0468f7122a49bf2588170903) ) | |
| 462 | ROM_LOAD( "mtx3-an.rom", CRC(54c9eca2) SHA1(3e628beaa360e635264c8c2c3a5b8312951a220b) ) | |
| 463 | ROM_LOAD( "nboot.rom", CRC(9caea81c) SHA1(93fca6e7ffbc7ae3283b8bda9f01c36b2bed1c54) ) | |
| 459 | ROM_LOAD( "assem.rom", CRC(599d5b6b) SHA1(3ec1f7f476a21ca3206012ded22198c020b47f7d) ) | |
| 460 | ROM_LOAD( "basic.rom", CRC(d1e9ff36) SHA1(e89ae3a627716e6cee7e35054be8a2472bdd49d4) ) | |
| 461 | ROM_LOAD( "boot.rom", CRC(ed98d6dd) SHA1(4671ee49bb96262b0468f7122a49bf2588170903) ) | |
| 462 | ROM_LOAD( "mtx3-an.rom", CRC(54c9eca2) SHA1(3e628beaa360e635264c8c2c3a5b8312951a220b) ) | |
| 463 | ROM_LOAD( "nboot.rom", CRC(9caea81c) SHA1(93fca6e7ffbc7ae3283b8bda9f01c36b2bed1c54) ) | |
| 464 | 464 | ROM_END |
| 465 | 465 | |
| 466 | BASIC.ROM this contains the monitor ROM plus the BASIC ROM. | |
| 467 | It's good to view them as one, because the monitor | |
| 468 | ROM contains a good deal of BASIC code and the machine | |
| 469 | code just runs from the monitor ROM into the BASIC ROM. | |
| 470 | It's also handy if you want to disassemble it (which | |
| 471 | you don't need because it's already done). | |
| 466 | BASIC.ROM this contains the monitor ROM plus the BASIC ROM. | |
| 467 | It's good to view them as one, because the monitor | |
| 468 | ROM contains a good deal of BASIC code and the machine | |
| 469 | code just runs from the monitor ROM into the BASIC ROM. | |
| 470 | It's also handy if you want to disassemble it (which | |
| 471 | you don't need because it's already done). | |
| 472 | 472 | |
| 473 | MTX3-AN.ROM the monitor ROM, but slightly modified | |
| 474 | While detecting memory size, the startup code destroys | |
| 475 | RAM content. When you have a lot of RAM it is convenient | |
| 476 | to have a ramdisk for CP/M, but it is a nuisance if the | |
| 477 | ramdisk is trashed at each reset. The modification simply | |
| 478 | prevents RAM trashing. | |
| 473 | MTX3-AN.ROM the monitor ROM, but slightly modified | |
| 474 | While detecting memory size, the startup code destroys | |
| 475 | RAM content. When you have a lot of RAM it is convenient | |
| 476 | to have a ramdisk for CP/M, but it is a nuisance if the | |
| 477 | ramdisk is trashed at each reset. The modification simply | |
| 478 | prevents RAM trashing. | |
| 479 | 479 | |
| 480 | ASSEM.ROM | |
| 480 | ASSEM.ROM assembler ROM | |
| 481 | 481 | |
| 482 | BOOT.ROM | |
| 482 | BOOT.ROM FDX floppy boot ROM | |
| 483 | 483 | |
| 484 | NBOOT.ROM replacement FDX boot ROM written by M. Kessler (supports | |
| 485 | booting from different disk formats and different drives) | |
| 484 | NBOOT.ROM replacement FDX boot ROM written by M. Kessler (supports | |
| 485 | booting from different disk formats and different drives) | |
| 486 | 486 | */ |
| r25360 | r25361 | |
|---|---|---|
| 1654 | 1654 | /* System Drivers */ |
| 1655 | 1655 | |
| 1656 | 1656 | /* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME */ |
| 1657 | COMP( 1983, kc85, 0, 0, kc85, kc85, driver_device, 0, "Kyosei", "Kyotronic 85 (Japan)", 0 ) | |
| 1658 | COMP( 1983, m10, kc85, 0, kc85, olivm10, driver_device, 0, "Olivetti", "M-10", 0 ) | |
| 1659 | //COMP( 1983, m10m, kc85, 0, kc85, olivm10, driver_device, 0, "Olivetti", "M-10 Modem (US)", 0 ) | |
| 1660 | COMP( 1983, trsm100, 0, 0, trsm100, kc85, driver_device, 0, "Tandy Radio Shack", "TRS-80 Model 100", 0 ) | |
| 1661 | COMP( 1986, tandy102, trsm100,0, tandy102, kc85, driver_device, 0, "Tandy Radio Shack", "Tandy 102", 0 ) | |
| 1662 | COMP( 1983, pc8201, 0, 0, pc8201, pc8201, driver_device, 0, "Nippon Electronic Company", "PC-8201 (Japan)", GAME_NOT_WORKING ) // keyboard layout wrong | |
| 1663 | COMP( 1983, pc8201a, pc8201, 0, pc8201, pc8201a, driver_device, 0, "Nippon Electronic Company", "PC-8201A", 0 ) | |
| 1664 | COMP( 1987, npc8300, pc8201, 0, pc8300, pc8201a, driver_device, 0, "Nippon Electronic Company", "PC-8300", GAME_NOT_WORKING ) | |
| 1665 | COMP( 1984, tandy200, 0, 0, tandy200, kc85, driver_device, 0, "Tandy Radio Shack", "Tandy 200", 0 ) | |
| 1657 | COMP( 1983, kc85, 0, 0, kc85, kc85, driver_device, 0, "Kyosei", "Kyotronic 85 (Japan)", 0 ) | |
| 1658 | COMP( 1983, m10, kc85, 0, kc85, olivm10, driver_device, 0, "Olivetti", "M-10", 0 ) | |
| 1659 | //COMP( 1983, m10m, kc85, 0, kc85, olivm10, driver_device, 0, "Olivetti", "M-10 Modem (US)", 0 ) | |
| 1660 | COMP( 1983, trsm100, 0, 0, trsm100, kc85, driver_device, 0, "Tandy Radio Shack", "TRS-80 Model 100", 0 ) | |
| 1661 | COMP( 1986, tandy102, trsm100,0, tandy102, kc85, driver_device, 0, "Tandy Radio Shack", "Tandy 102", 0 ) | |
| 1662 | COMP( 1983, pc8201, 0, 0, pc8201, pc8201, driver_device, 0, "Nippon Electronic Company", "PC-8201 (Japan)", GAME_NOT_WORKING ) // keyboard layout wrong | |
| 1663 | COMP( 1983, pc8201a, pc8201, 0, pc8201, pc8201a, driver_device, 0, "Nippon Electronic Company", "PC-8201A", 0 ) | |
| 1664 | COMP( 1987, npc8300, pc8201, 0, pc8300, pc8201a, driver_device, 0, "Nippon Electronic Company", "PC-8300", GAME_NOT_WORKING ) | |
| 1665 | COMP( 1984, tandy200, 0, 0, tandy200, kc85, driver_device, 0, "Tandy Radio Shack", "Tandy 200", 0 ) |
| r25360 | r25361 | |
|---|---|---|
| 478 | 478 | AM_RANGE(0x1ff300, 0x1ff300) AM_MIRROR(0xff) AM_DEVREADWRITE_LEGACY(Z8410AB1_0_TAG, z80dma_r, z80dma_w) |
| 479 | 479 | AM_RANGE(0x1ff400, 0x1ff400) AM_MIRROR(0xff) AM_DEVREADWRITE_LEGACY(Z8410AB1_1_TAG, z80dma_r, z80dma_w) |
| 480 | 480 | AM_RANGE(0x1ff500, 0x1ff500) AM_MIRROR(0xff) AM_DEVREADWRITE_LEGACY(Z8410AB1_2_TAG, z80dma_r, z80dma_w) |
| 481 | AM_RANGE(0x1ff600, 0x1ff607) AM_MIRROR(0xf8) AM_READWRITE(scc_r, scc_w) | |
| 482 | AM_RANGE(0x1ff700, 0x1ff707) AM_MIRROR(0xf8) AM_READWRITE(cio_r, cio_w) | |
| 481 | AM_RANGE(0x1ff600, 0x1ff607) AM_MIRROR(0xf8) AM_READWRITE(scc_r, scc_w) | |
| 482 | AM_RANGE(0x1ff700, 0x1ff707) AM_MIRROR(0xf8) AM_READWRITE(cio_r, cio_w) | |
| 483 | 483 | AM_RANGE(0x1ff800, 0x1ffaff) AM_DEVICE(ABC1600_MOVER_TAG, abc1600_mover_device, io_map) |
| 484 | 484 | AM_RANGE(0x1ffb00, 0x1ffb00) AM_MIRROR(0x7e) AM_WRITE(fw0_w) |
| 485 | 485 | AM_RANGE(0x1ffb01, 0x1ffb01) AM_MIRROR(0x7e) AM_WRITE(fw1_w) |
| r25360 | r25361 | |
|---|---|---|
| 49 | 49 | |
| 50 | 50 | 2013/08/04 Robert Tuccitto Green miscalculated proportions fixed. |
| 51 | 51 | |
| 52 | 2013/08/13 Robert Tuccitto Normalized contrast and brightness, | |
| 52 | 2013/08/13 Robert Tuccitto Normalized contrast and brightness, | |
| 53 | 53 | providing a standardize grayscale and adjusted color values. |
| 54 | 54 | |
| 55 | 2013/09/02 Robert Tuccitto Stored data for 26.7 & 27.7 phase shifts | |
| 55 | 2013/09/02 Robert Tuccitto Stored data for 26.7 & 27.7 phase shifts | |
| 56 | 56 | with corrections and label for 25.7 values. Made 26.7 |
| 57 | (medium) default. Phase shifting falls outside the realm of | |
| 58 | video controls and hope to implement a selectable toggle | |
| 57 | (medium) default. Phase shifting falls outside the realm of | |
| 58 | video controls and hope to implement a selectable toggle | |
| 59 | 59 | hardware option similar to Donkey Kong TKG02/TKG04. |
| 60 | 60 | ***************************************************************************/ |
| 61 | 61 | |
| r25360 | r25361 | |
| 286 | 286 | |
| 287 | 287 | |
| 288 | 288 | define NTSC_GREY |
| 289 | MAKE_RGB(0x00,0x00,0x00), MAKE_RGB(0x11,0x11,0x11), MAKE_RGB(0x22,0x22,0x22), MAKE_RGB(0x33,0x33,0x33), \ | |
| 290 | MAKE_RGB(0x44,0x44,0x44), MAKE_RGB(0x55,0x55,0x55), MAKE_RGB(0x66,0x66,0x66), MAKE_RGB(0x77,0x77,0x77), \ | |
| 291 | MAKE_RGB(0x88,0x88,0x88), MAKE_RGB(0x99,0x99,0x99), MAKE_RGB(0xAA,0xAA,0xAA), MAKE_RGB(0xBB,0xBB,0xBB), \ | |
| 292 | MAKE_RGB(0xCC,0xCC,0xCC), MAKE_RGB(0xDD,0xDD,0xDD), MAKE_RGB(0xEE,0xEE,0xEE), MAKE_RGB(0xFF,0xFF,0xFF ) | |
| 289 | MAKE_RGB(0x00,0x00,0x00), MAKE_RGB(0x11,0x11,0x11), MAKE_RGB(0x22,0x22,0x22), MAKE_RGB(0x33,0x33,0x33), \ | |
| 290 | MAKE_RGB(0x44,0x44,0x44), MAKE_RGB(0x55,0x55,0x55), MAKE_RGB(0x66,0x66,0x66), MAKE_RGB(0x77,0x77,0x77), \ | |
| 291 | MAKE_RGB(0x88,0x88,0x88), MAKE_RGB(0x99,0x99,0x99), MAKE_RGB(0xAA,0xAA,0xAA), MAKE_RGB(0xBB,0xBB,0xBB), \ | |
| 292 | MAKE_RGB(0xCC,0xCC,0xCC), MAKE_RGB(0xDD,0xDD,0xDD), MAKE_RGB(0xEE,0xEE,0xEE), MAKE_RGB(0xFF,0xFF,0xFF ) | |
| 293 | 293 | |
| 294 | 294 | define NTSC_GOLD |
| 295 | MAKE_RGB(0x1A,0x07,0x00), MAKE_RGB(0x2B,0x18,0x00), MAKE_RGB(0x3C,0x29,0x00), MAKE_RGB(0x4D,0x3A,0x00), \ | |
| 296 | MAKE_RGB(0x5E,0x4B,0x00), MAKE_RGB(0x6F,0x5C,0x00), MAKE_RGB(0x80,0x6D,0x00), MAKE_RGB(0x91,0x7E,0x09), \ | |
| 297 | MAKE_RGB(0xA2,0x8F,0x1A), MAKE_RGB(0xB3,0xA0,0x2B), MAKE_RGB(0xC4,0xB1,0x3C), MAKE_RGB(0xD5,0xC2,0x4D), \ | |
| 298 | MAKE_RGB(0xE6,0xD3,0x5E), MAKE_RGB(0xF7,0xE4,0x6F), MAKE_RGB(0xFF,0xF5,0x83), MAKE_RGB(0xFF,0xF7,0x97 ) | |
| 295 | MAKE_RGB(0x1A,0x07,0x00), MAKE_RGB(0x2B,0x18,0x00), MAKE_RGB(0x3C,0x29,0x00), MAKE_RGB(0x4D,0x3A,0x00), \ | |
| 296 | MAKE_RGB(0x5E,0x4B,0x00), MAKE_RGB(0x6F,0x5C,0x00), MAKE_RGB(0x80,0x6D,0x00), MAKE_RGB(0x91,0x7E,0x09), \ | |
| 297 | MAKE_RGB(0xA2,0x8F,0x1A), MAKE_RGB(0xB3,0xA0,0x2B), MAKE_RGB(0xC4,0xB1,0x3C), MAKE_RGB(0xD5,0xC2,0x4D), \ | |
| 298 | MAKE_RGB(0xE6,0xD3,0x5E), MAKE_RGB(0xF7,0xE4,0x6F), MAKE_RGB(0xFF,0xF5,0x83), MAKE_RGB(0xFF,0xF7,0x97 ) | |
| 299 | 299 | |
| 300 | 300 | define NTSC_ORANGE |
| 301 | MAKE_RGB(0x31,0x00,0x00), MAKE_RGB(0x42,0x06,0x00), MAKE_RGB(0x53,0x17,0x00), MAKE_RGB(0x64,0x28,0x00), \ | |
| 302 | MAKE_RGB(0x75,0x39,0x00), MAKE_RGB(0x86,0X4A,0x00), MAKE_RGB(0x97,0x5B,0x0A), MAKE_RGB(0xA8,0x6C,0x1B), \ | |
| 303 | MAKE_RGB(0xB9,0x7D,0x2C), MAKE_RGB(0xCA,0x8E,0x3D), MAKE_RGB(0xDB,0x9F,0x4E), MAKE_RGB(0xEC,0xB0,0x5F), \ | |
| 304 | MAKE_RGB(0xFD,0xC1,0x70), MAKE_RGB(0xFF,0xD2,0x85), MAKE_RGB(0xFF,0xE3,0x9C), MAKE_RGB(0xFF,0xF4,0xB2 ) | |
| 301 | MAKE_RGB(0x31,0x00,0x00), MAKE_RGB(0x42,0x06,0x00), MAKE_RGB(0x53,0x17,0x00), MAKE_RGB(0x64,0x28,0x00), \ | |
| 302 | MAKE_RGB(0x75,0x39,0x00), MAKE_RGB(0x86,0X4A,0x00), MAKE_RGB(0x97,0x5B,0x0A), MAKE_RGB(0xA8,0x6C,0x1B), \ | |
| 303 | MAKE_RGB(0xB9,0x7D,0x2C), MAKE_RGB(0xCA,0x8E,0x3D), MAKE_RGB(0xDB,0x9F,0x4E), MAKE_RGB(0xEC,0xB0,0x5F), \ | |
| 304 | MAKE_RGB(0xFD,0xC1,0x70), MAKE_RGB(0xFF,0xD2,0x85), MAKE_RGB(0xFF,0xE3,0x9C), MAKE_RGB(0xFF,0xF4,0xB2 ) | |
| 305 | 305 | |
| 306 | 306 | define NTSC_RED_ORANGE |
| 307 | MAKE_RGB(0x3E,0x00,0x00), MAKE_RGB(0x4F,0x00,0x00), MAKE_RGB(0x60,0x08,0x00), MAKE_RGB(0x71,0x19,0x00), \ | |
| 308 | MAKE_RGB(0x82,0x2A,0x0D), MAKE_RGB(0x93,0x3B,0x1E), MAKE_RGB(0xA4,0x4C,0x2F), MAKE_RGB(0xB5,0x5D,0x40), \ | |
| 309 | MAKE_RGB(0xC6,0x6E,0x51), MAKE_RGB(0xD7,0x7F,0x62), MAKE_RGB(0xE8,0x90,0x73), MAKE_RGB(0xF9,0xA1,0x83), \ | |
| 310 | MAKE_RGB(0xFF,0xB2,0x98), MAKE_RGB(0xFF,0xC3,0xAE), MAKE_RGB(0xFF,0xD4,0xC4), MAKE_RGB(0xFF,0xE5,0xDA ) | |
| 307 | MAKE_RGB(0x3E,0x00,0x00), MAKE_RGB(0x4F,0x00,0x00), MAKE_RGB(0x60,0x08,0x00), MAKE_RGB(0x71,0x19,0x00), \ | |
| 308 | MAKE_RGB(0x82,0x2A,0x0D), MAKE_RGB(0x93,0x3B,0x1E), MAKE_RGB(0xA4,0x4C,0x2F), MAKE_RGB(0xB5,0x5D,0x40), \ | |
| 309 | MAKE_RGB(0xC6,0x6E,0x51), MAKE_RGB(0xD7,0x7F,0x62), MAKE_RGB(0xE8,0x90,0x73), MAKE_RGB(0xF9,0xA1,0x83), \ | |
| 310 | MAKE_RGB(0xFF,0xB2,0x98), MAKE_RGB(0xFF,0xC3,0xAE), MAKE_RGB(0xFF,0xD4,0xC4), MAKE_RGB(0xFF,0xE5,0xDA ) | |
| 311 | 311 | |
| 312 | 312 | define NTSC_PINK |
| 313 | MAKE_RGB(0x3F,0x00,0x03), MAKE_RGB(0x50,0x00,0x0F), MAKE_RGB(0x61,0x00,0x1B), MAKE_RGB(0x72,0x0F,0x2B), \ | |
| 314 | MAKE_RGB(0x83,0x20,0x3C), MAKE_RGB(0x94,0x31,0x4D), MAKE_RGB(0xA5,0x42,0x5E), MAKE_RGB(0xB6,0x53,0x6F), \ | |
| 315 | MAKE_RGB(0xC7,0x64,0x80), MAKE_RGB(0xD8,0x75,0x91), MAKE_RGB(0xE9,0x86,0xA2), MAKE_RGB(0xFA,0x97,0xB3), \ | |
| 316 | MAKE_RGB(0xFF,0xA8,0xC8), MAKE_RGB(0xFF,0xB9,0xDE), MAKE_RGB(0xFF,0xCA,0xEF), MAKE_RGB(0xFF,0xDB,0xF4 ) | |
| 313 | MAKE_RGB(0x3F,0x00,0x03), MAKE_RGB(0x50,0x00,0x0F), MAKE_RGB(0x61,0x00,0x1B), MAKE_RGB(0x72,0x0F,0x2B), \ | |
| 314 | MAKE_RGB(0x83,0x20,0x3C), MAKE_RGB(0x94,0x31,0x4D), MAKE_RGB(0xA5,0x42,0x5E), MAKE_RGB(0xB6,0x53,0x6F), \ | |
| 315 | MAKE_RGB(0xC7,0x64,0x80), MAKE_RGB(0xD8,0x75,0x91), MAKE_RGB(0xE9,0x86,0xA2), MAKE_RGB(0xFA,0x97,0xB3), \ | |
| 316 | MAKE_RGB(0xFF,0xA8,0xC8), MAKE_RGB(0xFF,0xB9,0xDE), MAKE_RGB(0xFF,0xCA,0xEF), MAKE_RGB(0xFF,0xDB,0xF4 ) | |
| 317 | 317 | |
| 318 | 318 | define NTSC_PURPLE |
| 319 | MAKE_RGB(0x33,0x00,0x35), MAKE_RGB(0x44,0x00,0x41), MAKE_RGB(0x55,0x00,0x4C), MAKE_RGB(0x66,0x0C,0x5C), \ | |
| 320 | MAKE_RGB(0x77,0x1D,0x6D), MAKE_RGB(0x88,0x2E,0x7E), MAKE_RGB(0x99,0x3F,0x8F), MAKE_RGB(0xAA,0x50,0xA0), \ | |
| 321 | MAKE_RGB(0xBB,0x61,0xB1), MAKE_RGB(0xCC,0x72,0xC2), MAKE_RGB(0xDD,0x83,0xD3), MAKE_RGB(0xEE,0x94,0xE4), \ | |
| 322 | MAKE_RGB(0xFF,0xA5,0xE4), MAKE_RGB(0xFF,0xB6,0xE9), MAKE_RGB(0xFF,0xC7,0xEE), MAKE_RGB(0xFF,0xD8,0xF3 ) | |
| 319 | MAKE_RGB(0x33,0x00,0x35), MAKE_RGB(0x44,0x00,0x41), MAKE_RGB(0x55,0x00,0x4C), MAKE_RGB(0x66,0x0C,0x5C), \ | |
| 320 | MAKE_RGB(0x77,0x1D,0x6D), MAKE_RGB(0x88,0x2E,0x7E), MAKE_RGB(0x99,0x3F,0x8F), MAKE_RGB(0xAA,0x50,0xA0), \ | |
| 321 | MAKE_RGB(0xBB,0x61,0xB1), MAKE_RGB(0xCC,0x72,0xC2), MAKE_RGB(0xDD,0x83,0xD3), MAKE_RGB(0xEE,0x94,0xE4), \ | |
| 322 | MAKE_RGB(0xFF,0xA5,0xE4), MAKE_RGB(0xFF,0xB6,0xE9), MAKE_RGB(0xFF,0xC7,0xEE), MAKE_RGB(0xFF,0xD8,0xF3 ) | |
| 323 | 323 | |
| 324 | 324 | define NTSC_PURPLE_BLUE |
| 325 | MAKE_RGB(0x1D,0x00,0x5C), MAKE_RGB(0x2E,0x00,0x68), MAKE_RGB(0x40,0x00,0x74), MAKE_RGB(0x51,0x10,0x84), \ | |
| 326 | MAKE_RGB(0x62,0x21,0x95), MAKE_RGB(0x73,0x32,0xA6), MAKE_RGB(0x84,0x43,0xB7), MAKE_RGB(0x95,0x54,0xC8), \ | |
| 327 | MAKE_RGB(0xA6,0x65,0xD9), MAKE_RGB(0xB7,0x76,0xEA), MAKE_RGB(0xC8,0x87,0xEB), MAKE_RGB(0xD9,0x98,0xEB), \ | |
| 328 | MAKE_RGB(0xE9,0xA9,0xEC), MAKE_RGB(0xFB,0xBA,0xEB), MAKE_RGB(0xFF,0xCB,0xEF), MAKE_RGB(0xFF,0xDC,0xF4 ) | |
| 325 | MAKE_RGB(0x1D,0x00,0x5C), MAKE_RGB(0x2E,0x00,0x68), MAKE_RGB(0x40,0x00,0x74), MAKE_RGB(0x51,0x10,0x84), \ | |
| 326 | MAKE_RGB(0x62,0x21,0x95), MAKE_RGB(0x73,0x32,0xA6), MAKE_RGB(0x84,0x43,0xB7), MAKE_RGB(0x95,0x54,0xC8), \ | |
| 327 | MAKE_RGB(0xA6,0x65,0xD9), MAKE_RGB(0xB7,0x76,0xEA), MAKE_RGB(0xC8,0x87,0xEB), MAKE_RGB(0xD9,0x98,0xEB), \ | |
| 328 | MAKE_RGB(0xE9,0xA9,0xEC), MAKE_RGB(0xFB,0xBA,0xEB), MAKE_RGB(0xFF,0xCB,0xEF), MAKE_RGB(0xFF,0xDC,0xF4 ) | |
| 329 | 329 | |
| 330 | 330 | define NTSC_BLUE1 |
| 331 | MAKE_RGB(0x02,0x00,0x71), MAKE_RGB(0x13,0x00,0x7D), MAKE_RGB(0x24,0x0B,0x8C), MAKE_RGB(0x35,0x1C,0x9D), \ | |
| 332 | MAKE_RGB(0x46,0x2D,0xAE), MAKE_RGB(0x57,0x3E,0xBF), MAKE_RGB(0x68,0x4F,0xD0), MAKE_RGB(0x79,0x60,0xE1), \ | |
| 333 | MAKE_RGB(0x8A,0x71,0xF2), MAKE_RGB(0x9B,0x82,0xF7), MAKE_RGB(0xAC,0x93,0xF7), MAKE_RGB(0xBD,0xA4,0xF7), \ | |
| 334 | MAKE_RGB(0xCE,0xB5,0xF7), MAKE_RGB(0xDF,0xC6,0xF7), MAKE_RGB(0xF0,0xD7,0xF7), MAKE_RGB(0xFF,0xE8,0xF8 ) | |
| 331 | MAKE_RGB(0x02,0x00,0x71), MAKE_RGB(0x13,0x00,0x7D), MAKE_RGB(0x24,0x0B,0x8C), MAKE_RGB(0x35,0x1C,0x9D), \ | |
| 332 | MAKE_RGB(0x46,0x2D,0xAE), MAKE_RGB(0x57,0x3E,0xBF), MAKE_RGB(0x68,0x4F,0xD0), MAKE_RGB(0x79,0x60,0xE1), \ | |
| 333 | MAKE_RGB(0x8A,0x71,0xF2), MAKE_RGB(0x9B,0x82,0xF7), MAKE_RGB(0xAC,0x93,0xF7), MAKE_RGB(0xBD,0xA4,0xF7), \ | |
| 334 | MAKE_RGB(0xCE,0xB5,0xF7), MAKE_RGB(0xDF,0xC6,0xF7), MAKE_RGB(0xF0,0xD7,0xF7), MAKE_RGB(0xFF,0xE8,0xF8 ) | |
| 335 | 335 | |
| 336 | 336 | define NTSC_BLUE2 |
| 337 | MAKE_RGB(0x00,0x00,0x68), MAKE_RGB(0x00,0x0A,0x7C), MAKE_RGB(0x08,0x1B,0x90), MAKE_RGB(0x19,0x2C,0xA1), \ | |
| 338 | MAKE_RGB(0x2A,0x3D,0xB2), MAKE_RGB(0x3B,0x4E,0xC3), MAKE_RGB(0x4C,0x5F,0xD4), MAKE_RGB(0x5D,0x70,0xE5), \ | |
| 339 | MAKE_RGB(0x6E,0x81,0xF6), MAKE_RGB(0x7F,0x92,0xFF), MAKE_RGB(0x90,0xA3,0xFF), MAKE_RGB(0xA1,0xB4,0xFF), \ | |
| 340 | MAKE_RGB(0xB2,0xC5,0xFF), MAKE_RGB(0xC3,0xD6,0xFF), MAKE_RGB(0xD4,0xE7,0xFF), MAKE_RGB(0xE5,0xF8,0xFF ) | |
| 337 | MAKE_RGB(0x00,0x00,0x68), MAKE_RGB(0x00,0x0A,0x7C), MAKE_RGB(0x08,0x1B,0x90), MAKE_RGB(0x19,0x2C,0xA1), \ | |
| 338 | MAKE_RGB(0x2A,0x3D,0xB2), MAKE_RGB(0x3B,0x4E,0xC3), MAKE_RGB(0x4C,0x5F,0xD4), MAKE_RGB(0x5D,0x70,0xE5), \ | |
| 339 | MAKE_RGB(0x6E,0x81,0xF6), MAKE_RGB(0x7F,0x92,0xFF), MAKE_RGB(0x90,0xA3,0xFF), MAKE_RGB(0xA1,0xB4,0xFF), \ | |
| 340 | MAKE_RGB(0xB2,0xC5,0xFF), MAKE_RGB(0xC3,0xD6,0xFF), MAKE_RGB(0xD4,0xE7,0xFF), MAKE_RGB(0xE5,0xF8,0xFF ) | |
| 341 | 341 | |
| 342 | 342 | define NTSC_LIGHT_BLUE |
| 343 | MAKE_RGB(0x00,0x0A,0x4D), MAKE_RGB(0x00,0x1B,0x63), MAKE_RGB(0x00,0x2C,0x79), MAKE_RGB(0x02,0x3D,0x8F), \ | |
| 344 | MAKE_RGB(0x13,0x4E,0xA0), MAKE_RGB(0x24,0x5F,0xB1), MAKE_RGB(0x35,0x70,0xC2), MAKE_RGB(0x46,0x81,0xD3), \ | |
| 345 | MAKE_RGB(0x57,0x92,0xE4), MAKE_RGB(0x68,0xA3,0xF5), MAKE_RGB(0x79,0xB4,0xFF), MAKE_RGB(0x8A,0xC5,0xFF), \ | |
| 346 | MAKE_RGB(0x9B,0xD6,0xFF), MAKE_RGB(0xAC,0xE7,0xFF), MAKE_RGB(0xBD,0xF8,0xFF), MAKE_RGB(0xCE,0xFF,0xFF ) | |
| 343 | MAKE_RGB(0x00,0x0A,0x4D), MAKE_RGB(0x00,0x1B,0x63), MAKE_RGB(0x00,0x2C,0x79), MAKE_RGB(0x02,0x3D,0x8F), \ | |
| 344 | MAKE_RGB(0x13,0x4E,0xA0), MAKE_RGB(0x24,0x5F,0xB1), MAKE_RGB(0x35,0x70,0xC2), MAKE_RGB(0x46,0x81,0xD3), \ | |
| 345 | MAKE_RGB(0x57,0x92,0xE4), MAKE_RGB(0x68,0xA3,0xF5), MAKE_RGB(0x79,0xB4,0xFF), MAKE_RGB(0x8A,0xC5,0xFF), \ | |
| 346 | MAKE_RGB(0x9B,0xD6,0xFF), MAKE_RGB(0xAC,0xE7,0xFF), MAKE_RGB(0xBD,0xF8,0xFF), MAKE_RGB(0xCE,0xFF,0xFF ) | |
| 347 | 347 | |
| 348 | 348 | define NTSC_TURQUOISE |
| 349 | MAKE_RGB(0x00,0x1A,0x26), MAKE_RGB(0x00,0x2B,0x3C), MAKE_RGB(0x00,0x3C,0x52), MAKE_RGB(0x00,0x4D,0x68), \ | |
| 350 | MAKE_RGB(0x06,0x5E,0x7C), MAKE_RGB(0x17,0x6F,0x8D), MAKE_RGB(0x28,0x80,0x9E), MAKE_RGB(0x39,0x91,0xAF), \ | |
| 351 | MAKE_RGB(0x4A,0xA2,0xC0), MAKE_RGB(0x5B,0xB3,0xD1), MAKE_RGB(0x6C,0xC4,0xE2), MAKE_RGB(0x7D,0xD5,0xF3), \ | |
| 352 | MAKE_RGB(0x8E,0xE6,0xFF), MAKE_RGB(0x9F,0xF7,0xFF), MAKE_RGB(0xB0,0xFF,0xFF), MAKE_RGB(0xC1,0xFF,0xFF ) | |
| 349 | MAKE_RGB(0x00,0x1A,0x26), MAKE_RGB(0x00,0x2B,0x3C), MAKE_RGB(0x00,0x3C,0x52), MAKE_RGB(0x00,0x4D,0x68), \ | |
| 350 | MAKE_RGB(0x06,0x5E,0x7C), MAKE_RGB(0x17,0x6F,0x8D), MAKE_RGB(0x28,0x80,0x9E), MAKE_RGB(0x39,0x91,0xAF), \ | |
| 351 | MAKE_RGB(0x4A,0xA2,0xC0), MAKE_RGB(0x5B,0xB3,0xD1), MAKE_RGB(0x6C,0xC4,0xE2), MAKE_RGB(0x7D,0xD5,0xF3), \ | |
| 352 | MAKE_RGB(0x8E,0xE6,0xFF), MAKE_RGB(0x9F,0xF7,0xFF), MAKE_RGB(0xB0,0xFF,0xFF), MAKE_RGB(0xC1,0xFF,0xFF ) | |
| 353 | 353 | |
| 354 | 354 | define NTSC_GREEN_BLUE |
| 355 | MAKE_RGB(0x00,0x24,0x0B), MAKE_RGB(0x00,0x35,0x10), MAKE_RGB(0x00,0x46,0x22), MAKE_RGB(0x00,0x57,0x38), \ | |
| 356 | MAKE_RGB(0x05,0x68,0x4D), MAKE_RGB(0x16,0x79,0x5E), MAKE_RGB(0x27,0x8A,0x6F), MAKE_RGB(0x38,0x9B,0x80), \ | |
| 357 | MAKE_RGB(0x49,0xAC,0x91), MAKE_RGB(0x5A,0xBD,0xA2), MAKE_RGB(0x6B,0xCE,0xB3), MAKE_RGB(0x7C,0xDF,0xC4), \ | |
| 358 | MAKE_RGB(0x8D,0xF0,0xD5), MAKE_RGB(0x9E,0xFF,0xE5), MAKE_RGB(0xAF,0xFF,0xF1), MAKE_RGB(0xC0,0xFF,0xFD ) | |
| 355 | MAKE_RGB(0x00,0x24,0x0B), MAKE_RGB(0x00,0x35,0x10), MAKE_RGB(0x00,0x46,0x22), MAKE_RGB(0x00,0x57,0x38), \ | |
| 356 | MAKE_RGB(0x05,0x68,0x4D), MAKE_RGB(0x16,0x79,0x5E), MAKE_RGB(0x27,0x8A,0x6F), MAKE_RGB(0x38,0x9B,0x80), \ | |
| 357 | MAKE_RGB(0x49,0xAC,0x91), MAKE_RGB(0x5A,0xBD,0xA2), MAKE_RGB(0x6B,0xCE,0xB3), MAKE_RGB(0x7C,0xDF,0xC4), \ | |
| 358 | MAKE_RGB(0x8D,0xF0,0xD5), MAKE_RGB(0x9E,0xFF,0xE5), MAKE_RGB(0xAF,0xFF,0xF1), MAKE_RGB(0xC0,0xFF,0xFD ) | |
| 359 | 359 | |
| 360 | 360 | define NTSC_GREEN |
| 361 | MAKE_RGB(0x00,0x27,0x0C), MAKE_RGB(0x00,0x38,0x11), MAKE_RGB(0x00,0x49,0x16), MAKE_RGB(0x00,0x5A,0x1B), \ | |
| 362 | MAKE_RGB(0x10,0x6B,0x1B), MAKE_RGB(0x21,0x7C,0x2C), MAKE_RGB(0x32,0x8D,0x3D), MAKE_RGB(0x43,0x9E,0x4E), \ | |
| 363 | MAKE_RGB(0x54,0xAF,0x5F), MAKE_RGB(0x65,0xC0,0x70), MAKE_RGB(0x76,0xD1,0x81), MAKE_RGB(0x87,0xE2,0x92), \ | |
| 364 | MAKE_RGB(0x98,0xF3,0xA3), MAKE_RGB(0xA9,0xFF,0xB3), MAKE_RGB(0xBA,0xFF,0xBF), MAKE_RGB(0xCB,0xFF,0xCB ) | |
| 361 | MAKE_RGB(0x00,0x27,0x0C), MAKE_RGB(0x00,0x38,0x11), MAKE_RGB(0x00,0x49,0x16), MAKE_RGB(0x00,0x5A,0x1B), \ | |
| 362 | MAKE_RGB(0x10,0x6B,0x1B), MAKE_RGB(0x21,0x7C,0x2C), MAKE_RGB(0x32,0x8D,0x3D), MAKE_RGB(0x43,0x9E,0x4E), \ | |
| 363 | MAKE_RGB(0x54,0xAF,0x5F), MAKE_RGB(0x65,0xC0,0x70), MAKE_RGB(0x76,0xD1,0x81), MAKE_RGB(0x87,0xE2,0x92), \ | |
| 364 | MAKE_RGB(0x98,0xF3,0xA3), MAKE_RGB(0xA9,0xFF,0xB3), MAKE_RGB(0xBA,0xFF,0xBF), MAKE_RGB(0xCB,0xFF,0xCB ) | |
| 365 | 365 | |
| 366 | 366 | define NTSC_YELLOW_GREEN |
| 367 | MAKE_RGB(0x00,0x23,0x0A), MAKE_RGB(0x00,0x34,0x10), MAKE_RGB(0x04,0x45,0x13), MAKE_RGB(0x15,0x56,0x13), \ | |
| 368 | MAKE_RGB(0x26,0x67,0x13), MAKE_RGB(0x37,0x78,0x13), MAKE_RGB(0x48,0x89,0x14), MAKE_RGB(0x59,0x9A,0x25), \ | |
| 369 | MAKE_RGB(0x6A,0xAB,0x36), MAKE_RGB(0x7B,0xBC,0x47), MAKE_RGB(0x8C,0xCD,0x58), MAKE_RGB(0x9D,0xDE,0x69), \ | |
| 370 | MAKE_RGB(0xAE,0xEF,0x7A), MAKE_RGB(0xBF,0xFF,0x8B), MAKE_RGB(0xD0,0xFF,0x97), MAKE_RGB(0xE1,0xFF,0xA3 ) | |
| 367 | MAKE_RGB(0x00,0x23,0x0A), MAKE_RGB(0x00,0x34,0x10), MAKE_RGB(0x04,0x45,0x13), MAKE_RGB(0x15,0x56,0x13), \ | |
| 368 | MAKE_RGB(0x26,0x67,0x13), MAKE_RGB(0x37,0x78,0x13), MAKE_RGB(0x48,0x89,0x14), MAKE_RGB(0x59,0x9A,0x25), \ | |
| 369 | MAKE_RGB(0x6A,0xAB,0x36), MAKE_RGB(0x7B,0xBC,0x47), MAKE_RGB(0x8C,0xCD,0x58), MAKE_RGB(0x9D,0xDE,0x69), \ | |
| 370 | MAKE_RGB(0xAE,0xEF,0x7A), MAKE_RGB(0xBF,0xFF,0x8B), MAKE_RGB(0xD0,0xFF,0x97), MAKE_RGB(0xE1,0xFF,0xA3 ) | |
| 371 | 371 | |
| 372 | 372 | define NTSC_ORANGE_GREEN |
| 373 | MAKE_RGB(0x00,0x17,0x07), MAKE_RGB(0x0E,0x28,0x08), MAKE_RGB(0x1F,0x39,0x08), MAKE_RGB(0x30,0x4A,0x08), \ | |
| 374 | MAKE_RGB(0x41,0x5B,0x08), MAKE_RGB(0x52,0x6C,0x08), MAKE_RGB(0x63,0x7D,0x08), MAKE_RGB(0x74,0x8E,0x0D), \ | |
| 375 | MAKE_RGB(0x85,0x9F,0x1E), MAKE_RGB(0x96,0xB0,0x2F), MAKE_RGB(0xA7,0xC1,0x40), MAKE_RGB(0xB8,0xD2,0x51), \ | |
| 376 | MAKE_RGB(0xC9,0xE3,0x62), MAKE_RGB(0xDA,0xF4,0x73), MAKE_RGB(0xEB,0xFF,0x82), MAKE_RGB(0xFC,0xFF,0x8E ) | |
| 373 | MAKE_RGB(0x00,0x17,0x07), MAKE_RGB(0x0E,0x28,0x08), MAKE_RGB(0x1F,0x39,0x08), MAKE_RGB(0x30,0x4A,0x08), \ | |
| 374 | MAKE_RGB(0x41,0x5B,0x08), MAKE_RGB(0x52,0x6C,0x08), MAKE_RGB(0x63,0x7D,0x08), MAKE_RGB(0x74,0x8E,0x0D), \ | |
| 375 | MAKE_RGB(0x85,0x9F,0x1E), MAKE_RGB(0x96,0xB0,0x2F), MAKE_RGB(0xA7,0xC1,0x40), MAKE_RGB(0xB8,0xD2,0x51), \ | |
| 376 | MAKE_RGB(0xC9,0xE3,0x62), MAKE_RGB(0xDA,0xF4,0x73), MAKE_RGB(0xEB,0xFF,0x82), MAKE_RGB(0xFC,0xFF,0x8E ) | |
| 377 | 377 | |
| 378 | 378 | define NTSC_LIGHT_ORANGE |
| 379 | MAKE_RGB(0x19,0x07,0x00), MAKE_RGB(0x2A,0x18,0x00), MAKE_RGB(0x3B,0x29,0x00), MAKE_RGB(0x4C,0x3A,0x00), \ | |
| 380 | MAKE_RGB(0x5D,0x4B,0x00), MAKE_RGB(0x6E,0x5C,0x00), MAKE_RGB(0x7F,0x6D,0x00), MAKE_RGB(0x90,0x7E,0x09), \ | |
| 381 | MAKE_RGB(0xA1,0x8F,0x1A), MAKE_RGB(0xB2,0xA0,0x2B), MAKE_RGB(0xC3,0xB1,0x3C), MAKE_RGB(0xD4,0xC2,0x4D), \ | |
| 382 | MAKE_RGB(0xE5,0xD3,0x5E), MAKE_RGB(0xF6,0xE4,0x6F), MAKE_RGB(0xFF,0xF5,0x82), MAKE_RGB(0xFF,0xFF,0x96 ) | |
| 379 | MAKE_RGB(0x19,0x07,0x00), MAKE_RGB(0x2A,0x18,0x00), MAKE_RGB(0x3B,0x29,0x00), MAKE_RGB(0x4C,0x3A,0x00), \ | |
| 380 | MAKE_RGB(0x5D,0x4B,0x00), MAKE_RGB(0x6E,0x5C,0x00), MAKE_RGB(0x7F,0x6D,0x00), MAKE_RGB(0x90,0x7E,0x09), \ | |
| 381 | MAKE_RGB(0xA1,0x8F,0x1A), MAKE_RGB(0xB2,0xA0,0x2B), MAKE_RGB(0xC3,0xB1,0x3C), MAKE_RGB(0xD4,0xC2,0x4D), \ | |
| 382 | MAKE_RGB(0xE5,0xD3,0x5E), MAKE_RGB(0xF6,0xE4,0x6F), MAKE_RGB(0xFF,0xF5,0x82), MAKE_RGB(0xFF,0xFF,0x96 ) | |
| 383 | 383 | ***************************************************************************/ |
| 384 | 384 | |
| 385 | 385 | |
| r25360 | r25361 | |
| 388 | 388 | |
| 389 | 389 | |
| 390 | 390 | define NTSC_GREY |
| 391 | MAKE_RGB(0x00,0x00,0x00), MAKE_RGB(0x11,0x11,0x11), MAKE_RGB(0x22,0x22,0x22), MAKE_RGB(0x33,0x33,0x33), \ | |
| 392 | MAKE_RGB(0x44,0x44,0x44), MAKE_RGB(0x55,0x55,0x55), MAKE_RGB(0x66,0x66,0x66), MAKE_RGB(0x77,0x77,0x77), \ | |
| 393 | MAKE_RGB(0x88,0x88,0x88), MAKE_RGB(0x99,0x99,0x99), MAKE_RGB(0xAA,0xAA,0xAA), MAKE_RGB(0xBB,0xBB,0xBB), \ | |
| 394 | MAKE_RGB(0xCC,0xCC,0xCC), MAKE_RGB(0xDD,0xDD,0xDD), MAKE_RGB(0xEE,0xEE,0xEE), MAKE_RGB(0xFF,0xFF,0xFF ) | |
| 391 | MAKE_RGB(0x00,0x00,0x00), MAKE_RGB(0x11,0x11,0x11), MAKE_RGB(0x22,0x22,0x22), MAKE_RGB(0x33,0x33,0x33), \ | |
| 392 | MAKE_RGB(0x44,0x44,0x44), MAKE_RGB(0x55,0x55,0x55), MAKE_RGB(0x66,0x66,0x66), MAKE_RGB(0x77,0x77,0x77), \ | |
| 393 | MAKE_RGB(0x88,0x88,0x88), MAKE_RGB(0x99,0x99,0x99), MAKE_RGB(0xAA,0xAA,0xAA), MAKE_RGB(0xBB,0xBB,0xBB), \ | |
| 394 | MAKE_RGB(0xCC,0xCC,0xCC), MAKE_RGB(0xDD,0xDD,0xDD), MAKE_RGB(0xEE,0xEE,0xEE), MAKE_RGB(0xFF,0xFF,0xFF ) | |
| 395 | 395 | |
| 396 | 396 | define NTSC_GOLD |
| 397 | MAKE_RGB(0x1A,0x07,0x00), MAKE_RGB(0x2B,0x18,0x00), MAKE_RGB(0x3C,0x29,0x00), MAKE_RGB(0x4D,0x3A,0x00), \ | |
| 398 | MAKE_RGB(0x5E,0x4B,0x00), MAKE_RGB(0x6F,0x5C,0x00), MAKE_RGB(0x80,0x6D,0x00), MAKE_RGB(0x91,0x7E,0x09), \ | |
| 399 | MAKE_RGB(0xA2,0x8F,0x1A), MAKE_RGB(0xB3,0xA0,0x2B), MAKE_RGB(0xC4,0xB1,0x3C), MAKE_RGB(0xD5,0xC2,0x4D), \ | |
| 400 | MAKE_RGB(0xE6,0xD3,0x5E), MAKE_RGB(0xF7,0xE4,0x6F), MAKE_RGB(0xFF,0xF5,0x83), MAKE_RGB(0xFF,0xFF,0x97 ) | |
| 397 | MAKE_RGB(0x1A,0x07,0x00), MAKE_RGB(0x2B,0x18,0x00), MAKE_RGB(0x3C,0x29,0x00), MAKE_RGB(0x4D,0x3A,0x00), \ | |
| 398 | MAKE_RGB(0x5E,0x4B,0x00), MAKE_RGB(0x6F,0x5C,0x00), MAKE_RGB(0x80,0x6D,0x00), MAKE_RGB(0x91,0x7E,0x09), \ | |
| 399 | MAKE_RGB(0xA2,0x8F,0x1A), MAKE_RGB(0xB3,0xA0,0x2B), MAKE_RGB(0xC4,0xB1,0x3C), MAKE_RGB(0xD5,0xC2,0x4D), \ | |
| 400 | MAKE_RGB(0xE6,0xD3,0x5E), MAKE_RGB(0xF7,0xE4,0x6F), MAKE_RGB(0xFF,0xF5,0x83), MAKE_RGB(0xFF,0xFF,0x97 ) | |
| 401 | 401 | |
| 402 | 402 | define NTSC_ORANGE |
| 403 | MAKE_RGB(0x32,0x00,0x00), MAKE_RGB(0x43,0x05,0x00), MAKE_RGB(0x54,0x16,0x00), MAKE_RGB(0x65,0x27,0x00), \ | |
| 404 | MAKE_RGB(0x76,0x38,0x00), MAKE_RGB(0x87,0x49,0x00), MAKE_RGB(0x98,0x5A,0x0C), MAKE_RGB(0xA9,0x6B,0x1D), \ | |
| 405 | MAKE_RGB(0xBA,0x7C,0x2E), MAKE_RGB(0xCB,0x8D,0x3F), MAKE_RGB(0xDC,0x9E,0x50), MAKE_RGB(0xED,0xAF,0x61), \ | |
| 406 | MAKE_RGB(0xFE,0xC0,0x72), MAKE_RGB(0xFF,0xD1,0x88), MAKE_RGB(0xFF,0xE2,0x9E), MAKE_RGB(0xFF,0xF3,0xB4 ) | |
| 403 | MAKE_RGB(0x32,0x00,0x00), MAKE_RGB(0x43,0x05,0x00), MAKE_RGB(0x54,0x16,0x00), MAKE_RGB(0x65,0x27,0x00), \ | |
| 404 | MAKE_RGB(0x76,0x38,0x00), MAKE_RGB(0x87,0x49,0x00), MAKE_RGB(0x98,0x5A,0x0C), MAKE_RGB(0xA9,0x6B,0x1D), \ | |
| 405 | MAKE_RGB(0xBA,0x7C,0x2E), MAKE_RGB(0xCB,0x8D,0x3F), MAKE_RGB(0xDC,0x9E,0x50), MAKE_RGB(0xED,0xAF,0x61), \ | |
| 406 | MAKE_RGB(0xFE,0xC0,0x72), MAKE_RGB(0xFF,0xD1,0x88), MAKE_RGB(0xFF,0xE2,0x9E), MAKE_RGB(0xFF,0xF3,0xB4 ) | |
| 407 | 407 | |
| 408 | 408 | define NTSC_RED_ORANGE |
| 409 | MAKE_RGB(0x3F,0x00,0x00), MAKE_RGB(0x50,0x00,0x00), MAKE_RGB(0x61,0x06,0x00), MAKE_RGB(0x72,0x17,0x03), \ | |
| 410 | MAKE_RGB(0x83,0x28,0x14), MAKE_RGB(0x94,0x39,0x25), MAKE_RGB(0xA5,0x4A,0x36), MAKE_RGB(0xB6,0x5B,0x47), \ | |
| 411 | MAKE_RGB(0xC7,0x6C,0x58), MAKE_RGB(0xD8,0x7D,0x69), MAKE_RGB(0xE9,0x8E,0x7A), MAKE_RGB(0xFA,0x9F,0x8B), \ | |
| 412 | MAKE_RGB(0xFF,0xB0,0x9F), MAKE_RGB(0xFF,0xC1,0xB5), MAKE_RGB(0xFF,0xD2,0xCB), MAKE_RGB(0xFF,0xE3,0xE1 ) | |
| 409 | MAKE_RGB(0x3F,0x00,0x00), MAKE_RGB(0x50,0x00,0x00), MAKE_RGB(0x61,0x06,0x00), MAKE_RGB(0x72,0x17,0x03), \ | |
| 410 | MAKE_RGB(0x83,0x28,0x14), MAKE_RGB(0x94,0x39,0x25), MAKE_RGB(0xA5,0x4A,0x36), MAKE_RGB(0xB6,0x5B,0x47), \ | |
| 411 | MAKE_RGB(0xC7,0x6C,0x58), MAKE_RGB(0xD8,0x7D,0x69), MAKE_RGB(0xE9,0x8E,0x7A), MAKE_RGB(0xFA,0x9F,0x8B), \ | |
| 412 | MAKE_RGB(0xFF,0xB0,0x9F), MAKE_RGB(0xFF,0xC1,0xB5), MAKE_RGB(0xFF,0xD2,0xCB), MAKE_RGB(0xFF,0xE3,0xE1 ) | |
| 413 | 413 | |
| 414 | 414 | define NTSC_PINK |
| 415 | MAKE_RGB(0x3D,0x00,0x10), MAKE_RGB(0x4E,0x00,0x1C), MAKE_RGB(0x5F,0x00,0x27), MAKE_RGB(0x70,0x0D,0x37), \ | |
| 416 | MAKE_RGB(0x81,0x1E,0x48), MAKE_RGB(0x92,0x2F,0x59), MAKE_RGB(0xA3,0x40,0x6A), MAKE_RGB(0xB4,0x51,0x7B), \ | |
| 417 | MAKE_RGB(0xC5,0x62,0x8C), MAKE_RGB(0xD6,0x73,0x9D), MAKE_RGB(0xE7,0x84,0xAE), MAKE_RGB(0xF8,0x95,0xBF), \ | |
| 418 | MAKE_RGB(0xFF,0xA6,0xD3), MAKE_RGB(0xFF,0xB7,0xE9), MAKE_RGB(0xFF,0xC8,0xEE), MAKE_RGB(0xFF,0xD9,0xF4 ) | |
| 415 | MAKE_RGB(0x3D,0x00,0x10), MAKE_RGB(0x4E,0x00,0x1C), MAKE_RGB(0x5F,0x00,0x27), MAKE_RGB(0x70,0x0D,0x37), \ | |
| 416 | MAKE_RGB(0x81,0x1E,0x48), MAKE_RGB(0x92,0x2F,0x59), MAKE_RGB(0xA3,0x40,0x6A), MAKE_RGB(0xB4,0x51,0x7B), \ | |
| 417 | MAKE_RGB(0xC5,0x62,0x8C), MAKE_RGB(0xD6,0x73,0x9D), MAKE_RGB(0xE7,0x84,0xAE), MAKE_RGB(0xF8,0x95,0xBF), \ | |
| 418 | MAKE_RGB(0xFF,0xA6,0xD3), MAKE_RGB(0xFF,0xB7,0xE9), MAKE_RGB(0xFF,0xC8,0xEE), MAKE_RGB(0xFF,0xD9,0xF4 ) | |
| 419 | 419 | |
| 420 | 420 | define NTSC_PURPLE |
| 421 | MAKE_RGB(0x2D,0x00,0x42), MAKE_RGB(0x3E,0x00,0x4E), MAKE_RGB(0x4F,0x00,0x5A), MAKE_RGB(0x60,0x0C,0x6A), \ | |
| 422 | MAKE_RGB(0x71,0x1D,0x7B), MAKE_RGB(0x82,0x2E,0x8C), MAKE_RGB(0x93,0x3F,0x9D), MAKE_RGB(0xA4,0x50,0xAE), \ | |
| 423 | MAKE_RGB(0xB5,0x61,0xBF), MAKE_RGB(0xC6,0x72,0xD0), MAKE_RGB(0xD7,0x83,0xE1), MAKE_RGB(0xE8,0x94,0xE6), \ | |
| 424 | MAKE_RGB(0xF9,0xA5,0xE6), MAKE_RGB(0xFF,0xB6,0xE9), MAKE_RGB(0xFF,0xC7,0xEE), MAKE_RGB(0xFF,0xD8,0xF3 ) | |
| 421 | MAKE_RGB(0x2D,0x00,0x42), MAKE_RGB(0x3E,0x00,0x4E), MAKE_RGB(0x4F,0x00,0x5A), MAKE_RGB(0x60,0x0C,0x6A), \ | |
| 422 | MAKE_RGB(0x71,0x1D,0x7B), MAKE_RGB(0x82,0x2E,0x8C), MAKE_RGB(0x93,0x3F,0x9D), MAKE_RGB(0xA4,0x50,0xAE), \ | |
| 423 | MAKE_RGB(0xB5,0x61,0xBF), MAKE_RGB(0xC6,0x72,0xD0), MAKE_RGB(0xD7,0x83,0xE1), MAKE_RGB(0xE8,0x94,0xE6), \ | |
| 424 | MAKE_RGB(0xF9,0xA5,0xE6), MAKE_RGB(0xFF,0xB6,0xE9), MAKE_RGB(0xFF,0xC7,0xEE), MAKE_RGB(0xFF,0xD8,0xF3 ) | |
| 425 | 425 | |
| 426 | 426 | define NTSC_PURPLE_BLUE |
| 427 | MAKE_RGB(0x13,0x00,0x67), MAKE_RGB(0x24,0x00,0x73), MAKE_RGB(0x35,0x03,0x80), MAKE_RGB(0x46,0x14,0x91), \ | |
| 428 | MAKE_RGB(0x57,0x25,0xA2), MAKE_RGB(0x68,0x36,0xB3), MAKE_RGB(0x79,0x47,0xC4), MAKE_RGB(0x8A,0x58,0xD5), \ | |
| 429 | MAKE_RGB(0x9B,0x69,0xE6), MAKE_RGB(0xAC,0x7A,0xF0), MAKE_RGB(0xBD,0x8B,0xF0), MAKE_RGB(0xCE,0x9C,0xF0), \ | |
| 430 | MAKE_RGB(0xDF,0xAD,0xF0), MAKE_RGB(0xF0,0xBE,0xF0), MAKE_RGB(0xFF,0xCF,0xF1), MAKE_RGB(0xFF,0xE0,0xF6 ) | |
| 427 | MAKE_RGB(0x13,0x00,0x67), MAKE_RGB(0x24,0x00,0x73), MAKE_RGB(0x35,0x03,0x80), MAKE_RGB(0x46,0x14,0x91), \ | |
| 428 | MAKE_RGB(0x57,0x25,0xA2), MAKE_RGB(0x68,0x36,0xB3), MAKE_RGB(0x79,0x47,0xC4), MAKE_RGB(0x8A,0x58,0xD5), \ | |
| 429 | MAKE_RGB(0x9B,0x69,0xE6), MAKE_RGB(0xAC,0x7A,0xF0), MAKE_RGB(0xBD,0x8B,0xF0), MAKE_RGB(0xCE,0x9C,0xF0), \ | |
| 430 | MAKE_RGB(0xDF,0xAD,0xF0), MAKE_RGB(0xF0,0xBE,0xF0), MAKE_RGB(0xFF,0xCF,0xF1), MAKE_RGB(0xFF,0xE0,0xF6 ) | |
| 431 | 431 | |
| 432 | 432 | define NTSC_BLUE1 |
| 433 | MAKE_RGB(0x00,0x00,0x70), MAKE_RGB(0x05,0x01,0x80), MAKE_RGB(0x16,0x12,0x91), MAKE_RGB(0x27,0x23,0xA2), \ | |
| 434 | MAKE_RGB(0x38,0x34,0xB3), MAKE_RGB(0x49,0x45,0xC4), MAKE_RGB(0x5A,0x56,0xD5), MAKE_RGB(0x6B,0x67,0xE6), \ | |
| 435 | MAKE_RGB(0x7C,0x78,0xF7), MAKE_RGB(0x8D,0x89,0xFE), MAKE_RGB(0x9E,0x9A,0xFE), MAKE_RGB(0xAF,0xAB,0xFE), \ | |
| 436 | MAKE_RGB(0xC0,0xBC,0xFE), MAKE_RGB(0xD1,0xCD,0xFE), MAKE_RGB(0xE2,0xDE,0xFE), MAKE_RGB(0xF3,0xEF,0xFE ) | |
| 433 | MAKE_RGB(0x00,0x00,0x70), MAKE_RGB(0x05,0x01,0x80), MAKE_RGB(0x16,0x12,0x91), MAKE_RGB(0x27,0x23,0xA2), \ | |
| 434 | MAKE_RGB(0x38,0x34,0xB3), MAKE_RGB(0x49,0x45,0xC4), MAKE_RGB(0x5A,0x56,0xD5), MAKE_RGB(0x6B,0x67,0xE6), \ | |
| 435 | MAKE_RGB(0x7C,0x78,0xF7), MAKE_RGB(0x8D,0x89,0xFE), MAKE_RGB(0x9E,0x9A,0xFE), MAKE_RGB(0xAF,0xAB,0xFE), \ | |
| 436 | MAKE_RGB(0xC0,0xBC,0xFE), MAKE_RGB(0xD1,0xCD,0xFE), MAKE_RGB(0xE2,0xDE,0xFE), MAKE_RGB(0xF3,0xEF,0xFE ) | |
| 437 | 437 | |
| 438 | 438 | define NTSC_BLUE2 |
| 439 | MAKE_RGB(0x00,0x03,0x5B), MAKE_RGB(0x00,0x14,0x71), MAKE_RGB(0x00,0x25,0x87), MAKE_RGB(0x0C,0x36,0x9A), \ | |
| 440 | MAKE_RGB(0x1D,0x47,0xAB), MAKE_RGB(0x2E,0x58,0xBC), MAKE_RGB(0x3F,0x69,0xCD), MAKE_RGB(0x50,0x7A,0xDE), \ | |
| 441 | MAKE_RGB(0x61,0x8B,0xEF), MAKE_RGB(0x72,0x9C,0xFF), MAKE_RGB(0x83,0xAD,0xFF), MAKE_RGB(0x94,0xBE,0xFF), \ | |
| 442 | MAKE_RGB(0xA5,0xCF,0xFF), MAKE_RGB(0xB6,0xE0,0xFF), MAKE_RGB(0xC7,0xF1,0xFF), MAKE_RGB(0xD8,0xFF,0xFF ) | |
| 439 | MAKE_RGB(0x00,0x03,0x5B), MAKE_RGB(0x00,0x14,0x71), MAKE_RGB(0x00,0x25,0x87), MAKE_RGB(0x0C,0x36,0x9A), \ | |
| 440 | MAKE_RGB(0x1D,0x47,0xAB), MAKE_RGB(0x2E,0x58,0xBC), MAKE_RGB(0x3F,0x69,0xCD), MAKE_RGB(0x50,0x7A,0xDE), \ | |
| 441 | MAKE_RGB(0x61,0x8B,0xEF), MAKE_RGB(0x72,0x9C,0xFF), MAKE_RGB(0x83,0xAD,0xFF), MAKE_RGB(0x94,0xBE,0xFF), \ | |
| 442 | MAKE_RGB(0xA5,0xCF,0xFF), MAKE_RGB(0xB6,0xE0,0xFF), MAKE_RGB(0xC7,0xF1,0xFF), MAKE_RGB(0xD8,0xFF,0xFF ) | |
| 443 | 443 | |
| 444 | 444 | define NTSC_LIGHT_BLUE |
| 445 | MAKE_RGB(0x00,0x15,0x35), MAKE_RGB(0x00,0x26,0x4B), MAKE_RGB(0x00,0x37,0x61), MAKE_RGB(0x00,0x48,0x78), \ | |
| 446 | MAKE_RGB(0x0A,0x59,0x8B), MAKE_RGB(0x1B,0x6A,0x9C), MAKE_RGB(0x2C,0x7B,0xAD), MAKE_RGB(0x3D,0x8C,0xBE), \ | |
| 447 | MAKE_RGB(0x4E,0x9D,0xCF), MAKE_RGB(0x5F,0xAE,0xE0), MAKE_RGB(0x70,0xBF,0xF1), MAKE_RGB(0x81,0xD0,0xFF), \ | |
| 448 | MAKE_RGB(0x92,0xE1,0xFF), MAKE_RGB(0xA3,0xF2,0xFF), MAKE_RGB(0xB4,0xFF,0xFF), MAKE_RGB(0xC5,0xFF,0xFF ) | |
| 445 | MAKE_RGB(0x00,0x15,0x35), MAKE_RGB(0x00,0x26,0x4B), MAKE_RGB(0x00,0x37,0x61), MAKE_RGB(0x00,0x48,0x78), \ | |
| 446 | MAKE_RGB(0x0A,0x59,0x8B), MAKE_RGB(0x1B,0x6A,0x9C), MAKE_RGB(0x2C,0x7B,0xAD), MAKE_RGB(0x3D,0x8C,0xBE), \ | |
| 447 | MAKE_RGB(0x4E,0x9D,0xCF), MAKE_RGB(0x5F,0xAE,0xE0), MAKE_RGB(0x70,0xBF,0xF1), MAKE_RGB(0x81,0xD0,0xFF), \ | |
| 448 | MAKE_RGB(0x92,0xE1,0xFF), MAKE_RGB(0xA3,0xF2,0xFF), MAKE_RGB(0xB4,0xFF,0xFF), MAKE_RGB(0xC5,0xFF,0xFF ) | |
| 449 | 449 | |
| 450 | 450 | define NTSC_TURQUOISE |
| 451 | MAKE_RGB(0x00,0x22,0x0A), MAKE_RGB(0x00,0x33,0x19), MAKE_RGB(0x00,0x44,0x2F), MAKE_RGB(0x00,0x55,0x45), \ | |
| 452 | MAKE_RGB(0x04,0x66,0x5A), MAKE_RGB(0x15,0x77,0x6B), MAKE_RGB(0x26,0x88,0x7C), MAKE_RGB(0x37,0x99,0x8D), \ | |
| 453 | MAKE_RGB(0x48,0xAA,0x9E), MAKE_RGB(0x59,0xBB,0xAF), MAKE_RGB(0x6A,0xCC,0xC0), MAKE_RGB(0x7B,0xDD,0xD1), \ | |
| 454 | MAKE_RGB(0x8C,0xEE,0xE2), MAKE_RGB(0x9D,0xFF,0xF3), MAKE_RGB(0xAE,0xFF,0xFF), MAKE_RGB(0xBF,0xFF,0xFF ) | |
| 451 | MAKE_RGB(0x00,0x22,0x0A), MAKE_RGB(0x00,0x33,0x19), MAKE_RGB(0x00,0x44,0x2F), MAKE_RGB(0x00,0x55,0x45), \ | |
| 452 | MAKE_RGB(0x04,0x66,0x5A), MAKE_RGB(0x15,0x77,0x6B), MAKE_RGB(0x26,0x88,0x7C), MAKE_RGB(0x37,0x99,0x8D), \ | |
| 453 | MAKE_RGB(0x48,0xAA,0x9E), MAKE_RGB(0x59,0xBB,0xAF), MAKE_RGB(0x6A,0xCC,0xC0), MAKE_RGB(0x7B,0xDD,0xD1), \ | |
| 454 | MAKE_RGB(0x8C,0xEE,0xE2), MAKE_RGB(0x9D,0xFF,0xF3), MAKE_RGB(0xAE,0xFF,0xFF), MAKE_RGB(0xBF,0xFF,0xFF ) | |
| 455 | 455 | |
| 456 | 456 | define NTSC_GREEN_BLUE |
| 457 | MAKE_RGB(0x00,0x27,0x0C), MAKE_RGB(0x00,0x38,0x11), MAKE_RGB(0x00,0x49,0x16), MAKE_RGB(0x00,0x5A,0x1B), \ | |
| 458 | MAKE_RGB(0x0D,0x6B,0x25), MAKE_RGB(0x1E,0x7C,0x36), MAKE_RGB(0x2F,0x8D,0x47), MAKE_RGB(0x40,0x9E,0x58), \ | |
| 459 | MAKE_RGB(0x51,0xAF,0x69), MAKE_RGB(0x62,0xC0,0x7A), MAKE_RGB(0x73,0xD1,0x8B), MAKE_RGB(0x84,0xE2,0x9C), \ | |
| 460 | MAKE_RGB(0x95,0xF3,0xAD), MAKE_RGB(0xA6,0xFF,0xBD), MAKE_RGB(0xB7,0xFF,0xC9), MAKE_RGB(0xC8,0xFF,0xD4 ) | |
| 457 | MAKE_RGB(0x00,0x27,0x0C), MAKE_RGB(0x00,0x38,0x11), MAKE_RGB(0x00,0x49,0x16), MAKE_RGB(0x00,0x5A,0x1B), \ | |
| 458 | MAKE_RGB(0x0D,0x6B,0x25), MAKE_RGB(0x1E,0x7C,0x36), MAKE_RGB(0x2F,0x8D,0x47), MAKE_RGB(0x40,0x9E,0x58), \ | |
| 459 | MAKE_RGB(0x51,0xAF,0x69), MAKE_RGB(0x62,0xC0,0x7A), MAKE_RGB(0x73,0xD1,0x8B), MAKE_RGB(0x84,0xE2,0x9C), \ | |
| 460 | MAKE_RGB(0x95,0xF3,0xAD), MAKE_RGB(0xA6,0xFF,0xBD), MAKE_RGB(0xB7,0xFF,0xC9), MAKE_RGB(0xC8,0xFF,0xD4 ) | |
| 461 | 461 | |
| 462 | 462 | define NTSC_GREEN |
| 463 | MAKE_RGB(0x00,0x24,0x0B), MAKE_RGB(0x00,0x35,0x10), MAKE_RGB(0x01,0x46,0x15), MAKE_RGB(0x12,0x57,0x15), \ | |
| 464 | MAKE_RGB(0x23,0x68,0x15), MAKE_RGB(0x34,0x79,0x15), MAKE_RGB(0x45,0x8A,0x19), MAKE_RGB(0x56,0x9B,0x2A), \ | |
| 465 | MAKE_RGB(0x67,0xAC,0x3B), MAKE_RGB(0x78,0xBD,0x4C), MAKE_RGB(0x89,0xCE,0x5D), MAKE_RGB(0x9A,0xDF,0x6E), \ | |
| 466 | MAKE_RGB(0xAB,0xF0,0x7F), MAKE_RGB(0xBC,0xFF,0x8F), MAKE_RGB(0xCD,0xFF,0x9B), MAKE_RGB(0xDE,0xFF,0xA7 ) | |
| 463 | MAKE_RGB(0x00,0x24,0x0B), MAKE_RGB(0x00,0x35,0x10), MAKE_RGB(0x01,0x46,0x15), MAKE_RGB(0x12,0x57,0x15), \ | |
| 464 | MAKE_RGB(0x23,0x68,0x15), MAKE_RGB(0x34,0x79,0x15), MAKE_RGB(0x45,0x8A,0x19), MAKE_RGB(0x56,0x9B,0x2A), \ | |
| 465 | MAKE_RGB(0x67,0xAC,0x3B), MAKE_RGB(0x78,0xBD,0x4C), MAKE_RGB(0x89,0xCE,0x5D), MAKE_RGB(0x9A,0xDF,0x6E), \ | |
| 466 | MAKE_RGB(0xAB,0xF0,0x7F), MAKE_RGB(0xBC,0xFF,0x8F), MAKE_RGB(0xCD,0xFF,0x9B), MAKE_RGB(0xDE,0xFF,0xA7 ) | |
| 467 | 467 | |
| 468 | 468 | define NTSC_YELLOW_GREEN |
| 469 | MAKE_RGB(0x00,0x18,0x07), MAKE_RGB(0x00,0x29,0x0C), MAKE_RGB(0x1E,0x3A,0x08), MAKE_RGB(0x2F,0x4B,0x08), \ | |
| 470 | MAKE_RGB(0x40,0x5C,0x08), MAKE_RGB(0x51,0x6D,0x08), MAKE_RGB(0x62,0x7E,0x08), MAKE_RGB(0x73,0x8F,0x0D), \ | |
| 471 | MAKE_RGB(0x84,0xA0,0x1E), MAKE_RGB(0x95,0xB1,0x2F), MAKE_RGB(0xA6,0xC2,0x40), MAKE_RGB(0xB7,0xD3,0x51), \ | |
| 472 | MAKE_RGB(0xC8,0xE4,0x62), MAKE_RGB(0xD9,0xF5,0x73), MAKE_RGB(0xEA,0xFF,0x82), MAKE_RGB(0xFB,0xFF,0x8E ) | |
| 469 | MAKE_RGB(0x00,0x18,0x07), MAKE_RGB(0x00,0x29,0x0C), MAKE_RGB(0x1E,0x3A,0x08), MAKE_RGB(0x2F,0x4B,0x08), \ | |
| 470 | MAKE_RGB(0x40,0x5C,0x08), MAKE_RGB(0x51,0x6D,0x08), MAKE_RGB(0x62,0x7E,0x08), MAKE_RGB(0x73,0x8F,0x0D), \ | |
| 471 | MAKE_RGB(0x84,0xA0,0x1E), MAKE_RGB(0x95,0xB1,0x2F), MAKE_RGB(0xA6,0xC2,0x40), MAKE_RGB(0xB7,0xD3,0x51), \ | |
| 472 | MAKE_RGB(0xC8,0xE4,0x62), MAKE_RGB(0xD9,0xF5,0x73), MAKE_RGB(0xEA,0xFF,0x82), MAKE_RGB(0xFB,0xFF,0x8E ) | |
| 473 | 473 | |
| 474 | 474 | define NTSC_ORANGE_GREEN |
| 475 | MAKE_RGB(0x1B,0x07,0x00), MAKE_RGB(0x2C,0x18,0x00), MAKE_RGB(0x3D,0x29,0x00), MAKE_RGB(0x4E,0x3A,0x00), \ | |
| 476 | MAKE_RGB(0x5F,0x4B,0x00), MAKE_RGB(0x70,0x5C,0x00), MAKE_RGB(0x81,0x6D,0x00), MAKE_RGB(0x92,0x7E,0x09), \ | |
| 477 | MAKE_RGB(0xA3,0x8F,0x1A), MAKE_RGB(0xB4,0xA0,0x2B), MAKE_RGB(0xC5,0xB1,0x3C), MAKE_RGB(0xD6,0xC2,0x4D), \ | |
| 478 | MAKE_RGB(0xE7,0xD3,0x5E), MAKE_RGB(0xF8,0xE4,0x6F), MAKE_RGB(0xFF,0xF5,0x83), MAKE_RGB(0xFF,0xFF,0x97 ) | |
| 475 | MAKE_RGB(0x1B,0x07,0x00), MAKE_RGB(0x2C,0x18,0x00), MAKE_RGB(0x3D,0x29,0x00), MAKE_RGB(0x4E,0x3A,0x00), \ | |
| 476 | MAKE_RGB(0x5F,0x4B,0x00), MAKE_RGB(0x70,0x5C,0x00), MAKE_RGB(0x81,0x6D,0x00), MAKE_RGB(0x92,0x7E,0x09), \ | |
| 477 | MAKE_RGB(0xA3,0x8F,0x1A), MAKE_RGB(0xB4,0xA0,0x2B), MAKE_RGB(0xC5,0xB1,0x3C), MAKE_RGB(0xD6,0xC2,0x4D), \ | |
| 478 | MAKE_RGB(0xE7,0xD3,0x5E), MAKE_RGB(0xF8,0xE4,0x6F), MAKE_RGB(0xFF,0xF5,0x83), MAKE_RGB(0xFF,0xFF,0x97 ) | |
| 479 | 479 | |
| 480 | 480 | define NTSC_LIGHT_ORANGE |
| 481 | MAKE_RGB(0x33,0x00,0x00), MAKE_RGB(0x44,0x05,0x00), MAKE_RGB(0x55,0x16,0x00), MAKE_RGB(0x66,0x27,0x00), \ | |
| 482 | MAKE_RGB(0x77,0x38,0x00), MAKE_RGB(0x88,0x49,0x00), MAKE_RGB(0x99,0x5A,0x0D), MAKE_RGB(0xAA,0x6B,0x1E), \ | |
| 483 | MAKE_RGB(0xBB,0x7C,0x2F), MAKE_RGB(0xCC,0x8D,0x40), MAKE_RGB(0xDD,0x9E,0x51), MAKE_RGB(0xEE,0xAF,0x62), \ | |
| 484 | MAKE_RGB(0xFF,0xC0,0x73), MAKE_RGB(0xFF,0xD1,0x89), MAKE_RGB(0xFF,0xE2,0x9F), MAKE_RGB(0xFF,0xF3,0xB5 ) | |
| 481 | MAKE_RGB(0x33,0x00,0x00), MAKE_RGB(0x44,0x05,0x00), MAKE_RGB(0x55,0x16,0x00), MAKE_RGB(0x66,0x27,0x00), \ | |
| 482 | MAKE_RGB(0x77,0x38,0x00), MAKE_RGB(0x88,0x49,0x00), MAKE_RGB(0x99,0x5A,0x0D), MAKE_RGB(0xAA,0x6B,0x1E), \ | |
| 483 | MAKE_RGB(0xBB,0x7C,0x2F), MAKE_RGB(0xCC,0x8D,0x40), MAKE_RGB(0xDD,0x9E,0x51), MAKE_RGB(0xEE,0xAF,0x62), \ | |
| 484 | MAKE_RGB(0xFF,0xC0,0x73), MAKE_RGB(0xFF,0xD1,0x89), MAKE_RGB(0xFF,0xE2,0x9F), MAKE_RGB(0xFF,0xF3,0xB5 ) | |
| 485 | 485 | ***************************************************************************/ |
| 486 | 486 | |
| 487 | 487 | /* Initialise the palette */ |
| r25360 | r25361 | |
|---|---|---|
| 77 | 77 | { |
| 78 | 78 | membank("read")->set_entry(data & 1); |
| 79 | 79 | } |
| 80 | ||
| 80 | ||
| 81 | 81 | READ8_MEMBER( dsb46_state::port01_r ) |
| 82 | 82 | { |
| 83 | 83 | return (m_term_data) ? 5 : 4; |
| r25360 | r25361 | |
|---|---|---|
| 1 | 1 | /**************************************************************************************************************************************** |
| 2 | 2 | |
| 3 | ||
| 3 | Sharp Zaurus PDA skeleton driver (SL, ARM/Linux based, 4th generation) | |
| 4 | 4 | |
| 5 | TODO: | |
| 6 | - PXA-255 ID opcode fails on this | |
| 7 | - ARM TLB look-up errors? | |
| 8 | - RTC irq doesn't fire? | |
| 9 | - For whatever reason, after RTC check ARM executes invalid code at 0-0x200 | |
| 10 | - Dumps are questionable to say the least | |
| 5 | TODO: | |
| 6 | - PXA-255 ID opcode fails on this | |
| 7 | - ARM TLB look-up errors? | |
| 8 | - RTC irq doesn't fire? | |
| 9 | - For whatever reason, after RTC check ARM executes invalid code at 0-0x200 | |
| 10 | - Dumps are questionable to say the least | |
| 11 | 11 | |
| 12 | 12 | ========================================================================================================================================= |
| 13 | 13 | Sharp Zaurus |
| r25360 | r25361 | |
| 1472 | 1472 | |
| 1473 | 1473 | UINT32 zaurus_state::screen_update( screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect ) |
| 1474 | 1474 | { |
| 1475 | ||
| 1476 | ||
| 1477 | 1475 | return 0; |
| 1478 | 1476 | } |
| 1479 | 1477 | |
| r25360 | r25361 | |
| 1501 | 1499 | { |
| 1502 | 1500 | PXA255_OSTMR_Regs *ostimer_regs = &m_ostimer_regs; |
| 1503 | 1501 | |
| 1504 | // | |
| 1502 | // logerror("%08x OStimer irq check\n",ostimer_regs->oier); | |
| 1505 | 1503 | |
| 1506 | 1504 | pxa255_set_irq_line(PXA255_INT_OSTIMER0, (ostimer_regs->oier & PXA255_OIER_E0) ? ((ostimer_regs->ossr & PXA255_OSSR_M0) ? 1 : 0) : 0); |
| 1507 | 1505 | //pxa255_set_irq_line(PXA255_INT_OSTIMER1, (ostimer_regs->oier & PXA255_OIER_E1) ? ((ostimer_regs->ossr & PXA255_OSSR_M1) ? 1 : 0) : 0); |
| r25360 | r25361 | |
| 1784 | 1782 | /* was labeled SL-C500 */ |
| 1785 | 1783 | ROM_START( zsl5500 ) |
| 1786 | 1784 | ROM_REGION32_LE( 0x200000, "firmware", ROMREGION_ERASE00 ) |
| 1787 | ||
| 1785 | ROM_LOAD( "sl-c500 v1.20 (zimage).bin", 0x000000, 0x13c000, BAD_DUMP CRC(dc1c259f) SHA1(8150744196a72821ae792462d0381182274c2ce0) ) | |
| 1788 | 1786 | ROM_END |
| 1789 | 1787 | |
| 1790 | 1788 | ROM_START( zsl5600 ) |
| r25360 | r25361 | |
| 1794 | 1792 | |
| 1795 | 1793 | ROM_START( zslc750 ) |
| 1796 | 1794 | ROM_REGION32_LE( 0x200000, "firmware", ROMREGION_ERASE00 ) |
| 1797 | ||
| 1795 | ROM_LOAD( "zaurus sl-c750 (zimage).bin", 0x000000, 0x121544, BAD_DUMP CRC(56353f4d) SHA1(8e1fff6e93d560bd6572c5c163bbd81378693f68) ) | |
| 1798 | 1796 | ROM_END |
| 1799 | 1797 | |
| 1800 | 1798 | ROM_START( zslc760 ) |
| r25360 | r25361 | |
| 1804 | 1802 | |
| 1805 | 1803 | ROM_START( zslc3000 ) |
| 1806 | 1804 | ROM_REGION32_LE( 0x200000, "firmware", ROMREGION_ERASE00 ) |
| 1807 | ||
| 1805 | ROM_LOAD( "openzaurus 3.5.3 - zimage-sharp sl-c3000-20050428091110.bin", 0x000000, 0x12828c, BAD_DUMP CRC(fd94510d) SHA1(901f8154b4228a448f5551f0c9f21c2153e1e3a1) ) | |
| 1808 | 1806 | ROM_END |
| 1809 | 1807 | |
| 1810 | 1808 | ROM_START( zslc1000 ) |
| 1811 | 1809 | ROM_REGION32_LE( 0x200000, "firmware", ROMREGION_ERASE00 ) |
| 1812 | ||
| 1810 | ROM_LOAD( "openzaurus 3.5.3 - zimage-sharp sl-c1000-20050427214434.bin", 0x000000, 0x128980, BAD_DUMP CRC(1e1a9279) SHA1(909ac3f00385eced55822d6a155b79d9d25f43b3) ) | |
| 1813 | 1811 | ROM_END |
| 1814 | 1812 | |
| 1815 | 1813 | GAME( 2002, zsl5500, 0, zaurus, zaurus, driver_device, 0, ROT0, "Sharp", "Zaurus SL-5500 \"Collie\"", GAME_IS_SKELETON ) |
| r25360 | r25361 | |
|---|---|---|
| 107 | 107 | 5 = Volume Slider |
| 108 | 108 | 6 = Battery |
| 109 | 109 | 7 = Voltage Reference |
| 110 | ||
| 110 | ||
| 111 | 111 | SQ-1: |
| 112 | 112 | 4 = second digit of patch # becomes 2 |
| 113 | 113 | 5 = first digit of patch # becomes 2 |
| r25360 | r25361 | |
| 117 | 117 | 12 = patch -1 |
| 118 | 118 | 13 = patch +1 |
| 119 | 119 | 14 = second digit of patch # becomes 5 |
| 120 | 15 = first digit of patch # becomes 5 | |
| 120 | 15 = first digit of patch # becomes 5 | |
| 121 | 121 | 20 = select sound? |
| 122 | 22 = second digit of patch # becomes 6 | |
| 123 | 23 = first digit of patch # becomes 6 | |
| 124 | ||
| 122 | 22 = second digit of patch # becomes 6 | |
| 123 | 23 = first digit of patch # becomes 6 | |
| 124 | ||
| 125 | 125 | ***************************************************************************/ |
| 126 | 126 | |
| 127 | 127 | #include <cstdio> |
| r25360 | r25361 | |
| 843 | 843 | |
| 844 | 844 | ROM_START( sd1 ) |
| 845 | 845 | ROM_REGION(0x40000, "osrom", 0) |
| 846 | ROM_LOAD16_BYTE( "sd1_21_300b_lower.bin", 0x000000, 0x020000, CRC(a1358a0c) SHA1(64ac5358aa46da37ca4195002cf358554e00878a) ) | |
| 847 | ROM_LOAD16_BYTE( "sd1_21_300b_upper.bin", 0x000001, 0x010000, CRC(465ba463) SHA1(899b0e83d0788c8d49c7b09ccf0b4a92b528c6e9) ) | |
| 846 | ROM_LOAD16_BYTE( "sd1_21_300b_lower.bin", 0x000000, 0x020000, CRC(a1358a0c) SHA1(64ac5358aa46da37ca4195002cf358554e00878a) ) | |
| 847 | ROM_LOAD16_BYTE( "sd1_21_300b_upper.bin", 0x000001, 0x010000, CRC(465ba463) SHA1(899b0e83d0788c8d49c7b09ccf0b4a92b528c6e9) ) | |
| 848 | 848 | |
| 849 | 849 | ROM_REGION(0x200000, "waverom", ROMREGION_ERASE00) // BS=0 region (12-bit) |
| 850 | 850 | ROM_LOAD16_BYTE( "u34.bin", 0x000001, 0x080000, CRC(85592299) SHA1(1aa7cf612f91972baeba15991d9686ccde01599c) ) |
| r25360 | r25361 | |
| 865 | 865 | ROM_LOAD16_BYTE_BIOS(0, "sd1_410_lo.bin", 0x000000, 0x020000, CRC(faa613a6) SHA1(60066765cddfa9d3b5d09057d8f83fb120f4e65e) ) |
| 866 | 866 | ROM_LOAD16_BYTE_BIOS(0, "sd1_410_hi.bin", 0x000001, 0x010000, CRC(618c0aa8) SHA1(74acf458aa1d04a0a7a0cd5855c49e6855dbd301) ) |
| 867 | 867 | ROM_SYSTEM_BIOS(1, "402", "SD-1 v4.02") |
| 868 | ROM_LOAD16_BYTE_BIOS(1, "sd1_32_402_lo.bin", 0x000000, 0x020000, CRC(5da2572b) SHA1(cb6ddd637ed13bfeb40a99df56000479e63fc8ec) ) | |
| 869 | ROM_LOAD16_BYTE_BIOS(1, "sd1_32_402_hi.bin", 0x000001, 0x010000, CRC(fc45c210) SHA1(23b81ebd9176112e6eae0c7c75b39fcb1656c953) ) | |
| 868 | ROM_LOAD16_BYTE_BIOS(1, "sd1_32_402_lo.bin", 0x000000, 0x020000, CRC(5da2572b) SHA1(cb6ddd637ed13bfeb40a99df56000479e63fc8ec) ) | |
| 869 | ROM_LOAD16_BYTE_BIOS(1, "sd1_32_402_hi.bin", 0x000001, 0x010000, CRC(fc45c210) SHA1(23b81ebd9176112e6eae0c7c75b39fcb1656c953) ) | |
| 870 | 870 | |
| 871 | 871 | ROM_REGION(0x200000, "waverom", ROMREGION_ERASE00) // BS=0 region (12-bit) |
| 872 | 872 | ROM_LOAD16_BYTE( "u34.bin", 0x000001, 0x080000, CRC(85592299) SHA1(1aa7cf612f91972baeba15991d9686ccde01599c) ) |
| r25360 | r25361 | |
| 964 | 964 | CONS( 1988, eps, 0, 0, eps, vfx, esq5505_state, eps, "Ensoniq", "EPS", GAME_NOT_WORKING ) // custom VFD: one alphanumeric 22-char row, one graphics-capable row (alpha row can also do bar graphs) |
| 965 | 965 | CONS( 1989, vfx, 0, 0, vfx, vfx, esq5505_state, denib, "Ensoniq", "VFX", GAME_NOT_WORKING ) // 2x40 VFD |
| 966 | 966 | CONS( 1989, vfxsd, 0, 0, vfxsd, vfx, esq5505_state, denib, "Ensoniq", "VFX-SD", GAME_NOT_WORKING ) // 2x40 VFD |
| 967 | CONS( 1990, sd1, 0, 0, vfxsd, vfx, esq5505_state, denib, "Ensoniq", "SD-1 (21 voice)", GAME_NOT_WORKING ) // 2x40 VFD | |
| 968 | CONS( 1990, sd132, sd1,0, vfx32, vfx, esq5505_state, denib, "Ensoniq", "SD-1 (32 voice)", GAME_NOT_WORKING ) // 2x40 VFD | |
| 967 | CONS( 1990, sd1, 0, 0, vfxsd, vfx, esq5505_state, denib, "Ensoniq", "SD-1 (21 voice)", GAME_NOT_WORKING ) // 2x40 VFD | |
| 968 | CONS( 1990, sd132, sd1,0, vfx32, vfx, esq5505_state, denib, "Ensoniq", "SD-1 (32 voice)", GAME_NOT_WORKING ) // 2x40 VFD | |
| 969 | 969 | CONS( 1990, sq1, 0, 0, sq1, vfx, esq5505_state, sq1, "Ensoniq", "SQ-1", GAME_NOT_WORKING ) // 2x16 LCD |
| 970 | 970 | CONS( 1990, sqrack,sq1, 0, sq1, vfx, esq5505_state, sq1, "Ensoniq", "SQ-Rack", GAME_NOT_WORKING ) // 2x16 LCD |
| r25360 | r25361 | |
|---|---|---|
| 69 | 69 | WRITE8_MEMBER( cosmicos_state::write ) |
| 70 | 70 | { |
| 71 | 71 | if (m_boot) offset |= 0xc0c0; |
| 72 | ||
| 72 | ||
| 73 | 73 | if (offset < 0xc000) |
| 74 | 74 | { |
| 75 | 75 | // TODO |
| r25360 | r25361 | |
| 77 | 77 | else if (!m_ram_disable && !m_ram_protect && (offset >= 0xff00)) |
| 78 | 78 | { |
| 79 | 79 | m_ram->pointer()[offset & 0xff] = data; |
| 80 | } | |
| 80 | } | |
| 81 | 81 | } |
| 82 | 82 | |
| 83 | 83 | READ8_MEMBER( cosmicos_state::video_off_r ) |
| r25360 | r25361 | |
|---|---|---|
| 1 | 1 | /*************************************************************************** |
| 2 | ||
| 3 | Lola 8A | |
| 4 | ||
| 5 | Ivo Lola Ribar Institute | |
| 6 | 2 | |
| 3 | Lola 8A | |
| 4 | ||
| 5 | Ivo Lola Ribar Institute | |
| 6 | ||
| 7 | 7 | 2013-08-28 Skeleton driver. |
| 8 | 8 | |
| 9 | 9 | |
| 10 | BASIC commands : | |
| 11 | ||
| 12 | LET NEXT IF GOTO GOSUB RETURN READ DATA FOR CLS INPUT DIM STOP END RESTORE | |
| 13 | REM CLEAR PUSH POKE PRINT OUT ERROR USR CURSOR NORMAL INVERSE PLOT UNPLOT | |
| 14 | ELSE WIPE COLOUR CENTRE RANGE DRAW CIRCLE LOAD SAVE VERIFY HLOAD HSAVE HVERIFY | |
| 15 | DLOAD DSAVE DVERIFY MERGE CAT RUN NEW ON LIST DEF MON GWIND TWIND UNDER | |
| 16 | SPC OFF TAB THEN TO STEP AND OR XOR NOT ABS LEN SQR INT ASC CHR VAL STR MID | |
| 17 | ARG CALL RND LEFT RIGHT DOT SGN SIN FREE PI FN TAN COS POP PEEK INP LN EXP ATN | |
| 10 | BASIC commands : | |
| 11 | ||
| 12 | LET NEXT IF GOTO GOSUB RETURN READ DATA FOR CLS INPUT DIM STOP END RESTORE | |
| 13 | REM CLEAR PUSH POKE PRINT OUT ERROR USR CURSOR NORMAL INVERSE PLOT UNPLOT | |
| 14 | ELSE WIPE COLOUR CENTRE RANGE DRAW CIRCLE LOAD SAVE VERIFY HLOAD HSAVE HVERIFY | |
| 15 | DLOAD DSAVE DVERIFY MERGE CAT RUN NEW ON LIST DEF MON GWIND TWIND UNDER | |
| 16 | SPC OFF TAB THEN TO STEP AND OR XOR NOT ABS LEN SQR INT ASC CHR VAL STR MID | |
| 17 | ARG CALL RND LEFT RIGHT DOT SGN SIN FREE PI FN TAN COS POP PEEK INP LN EXP ATN | |
| 18 | 18 | ****************************************************************************/ |
| 19 | 19 | |
| 20 | 20 | #include "emu.h" |
| r25360 | r25361 | |
| 38 | 38 | { } |
| 39 | 39 | |
| 40 | 40 | required_device<cpu_device> m_maincpu; |
| 41 | ||
| 42 | virtual void palette_init(); | |
| 41 | ||
| 42 | virtual void palette_init(); | |
| 43 | 43 | virtual void machine_reset() { m_maincpu->set_pc(0x8000); } |
| 44 | ||
| 44 | ||
| 45 | 45 | DECLARE_READ8_MEMBER(lola8a_port_a_r); |
| 46 | 46 | DECLARE_WRITE8_MEMBER(lola8a_port_b_w); |
| 47 | 47 | DECLARE_WRITE_LINE_MEMBER(crtc_vsync); |
| 48 | 48 | DECLARE_READ_LINE_MEMBER(cass_r); |
| 49 | 49 | DECLARE_WRITE_LINE_MEMBER(cass_w); |
| 50 | ||
| 50 | ||
| 51 | 51 | DECLARE_READ8_MEMBER(keyboard_r); |
| 52 | ||
| 53 | private: | |
| 52 | ||
| 53 | private: | |
| 54 | 54 | UINT8 m_portb; |
| 55 | 55 | required_device<cassette_image_device> m_cass; |
| 56 | 56 | }; |
| r25360 | r25361 | |
| 58 | 58 | static ADDRESS_MAP_START(lola8a_mem, AS_PROGRAM, 8, lola8a_state) |
| 59 | 59 | ADDRESS_MAP_UNMAP_HIGH |
| 60 | 60 | AM_RANGE( 0x0000, 0x1fff ) AM_RAM // 6264 at G45 |
| 61 | AM_RANGE( 0x2000, 0x3fff ) AM_RAM // 6264 at F45 | |
| 62 | // empty place for 6264 at E45 | |
| 63 | // empty place for 6264 at D45 | |
| 61 | AM_RANGE( 0x2000, 0x3fff ) AM_RAM // 6264 at F45 | |
| 62 | // empty place for 6264 at E45 | |
| 63 | // empty place for 6264 at D45 | |
| 64 | 64 | AM_RANGE( 0x8000, 0x9fff ) AM_ROM // 2764A at B45 |
| 65 | 65 | AM_RANGE( 0xa000, 0xbfff ) AM_ROM // 2764A at C45 |
| 66 | AM_RANGE( 0xc000, 0xdfff ) AM_ROM // 2764A at H67 | |
| 66 | AM_RANGE( 0xc000, 0xdfff ) AM_ROM // 2764A at H67 | |
| 67 | 67 | AM_RANGE( 0xe000, 0xffff ) AM_RAM // 6264 at G67 |
| 68 | 68 | ADDRESS_MAP_END |
| 69 | 69 | |
| 70 | 70 | static ADDRESS_MAP_START(lola8a_io, AS_IO, 8, lola8a_state) |
| 71 | 71 | ADDRESS_MAP_UNMAP_HIGH |
| 72 | 72 | AM_RANGE(0x80, 0x80) AM_DEVWRITE(AY8910_TAG, ay8910_device, address_w) |
| 73 | AM_RANGE(0x84, 0x84) AM_DEVREADWRITE(AY8910_TAG, ay8910_device, data_r, data_w) | |
| 74 | AM_RANGE(0x88, 0x88) AM_READ(keyboard_r) | |
| 75 | ||
| 73 | AM_RANGE(0x84, 0x84) AM_DEVREADWRITE(AY8910_TAG, ay8910_device, data_r, data_w) | |
| 74 | AM_RANGE(0x88, 0x88) AM_READ(keyboard_r) | |
| 75 | ||
| 76 | 76 | AM_RANGE(0x90, 0x90) AM_DEVREADWRITE(HD46505SP_TAG, mc6845_device, status_r, address_w) |
| 77 | 77 | AM_RANGE(0x92, 0x92) AM_DEVREADWRITE(HD46505SP_TAG, mc6845_device, register_r, register_w) |
| 78 | ||
| 78 | ||
| 79 | 79 | ADDRESS_MAP_END |
| 80 | 80 | |
| 81 | 81 | /* Input ports */ |
| r25360 | r25361 | |
| 99 | 99 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) |
| 100 | 100 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) |
| 101 | 101 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) |
| 102 | ||
| 103 | PORT_START("line_2") | |
| 102 | ||
| 103 | PORT_START("line_2") | |
| 104 | 104 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) |
| 105 | 105 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) |
| 106 | 106 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) |
| r25360 | r25361 | |
| 109 | 109 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) |
| 110 | 110 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) |
| 111 | 111 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) |
| 112 | ||
| 113 | PORT_START("line_3") | |
| 112 | ||
| 113 | PORT_START("line_3") | |
| 114 | 114 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) |
| 115 | 115 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) |
| 116 | 116 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) |
| r25360 | r25361 | |
| 119 | 119 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) |
| 120 | 120 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) |
| 121 | 121 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) |
| 122 | ||
| 123 | PORT_START("line_4") | |
| 122 | ||
| 123 | PORT_START("line_4") | |
| 124 | 124 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) |
| 125 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) | |
| 125 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) | |
| 126 | 126 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) |
| 127 | 127 | PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) |
| 128 | 128 | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) |
| 129 | 129 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) |
| 130 | 130 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) |
| 131 | 131 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) |
| 132 | ||
| 133 | PORT_START("line_5") | |
| 132 | ||
| 133 | PORT_START("line_5") | |
| 134 | 134 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) |
| 135 | 135 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) |
| 136 | 136 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) |
| r25360 | r25361 | |
| 139 | 139 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) |
| 140 | 140 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) |
| 141 | 141 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) |
| 142 | ||
| 143 | PORT_START("line_6") | |
| 142 | ||
| 143 | PORT_START("line_6") | |
| 144 | 144 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH)// Z" |
| 145 | 145 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) |
| 146 | 146 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) |
| r25360 | r25361 | |
| 149 | 149 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) |
| 150 | 150 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) |
| 151 | 151 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) |
| 152 | ||
| 153 | PORT_START("line_7") | |
| 152 | ||
| 153 | PORT_START("line_7") | |
| 154 | 154 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) // C" |
| 155 | 155 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) |
| 156 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) // = | |
| 156 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) // = | |
| 157 | 157 | PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED) // S" |
| 158 | 158 | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) // C' |
| 159 | 159 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED) // ; |
| 160 | 160 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) |
| 161 | 161 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) |
| 162 | ||
| 163 | PORT_START("line_8") | |
| 162 | ||
| 163 | PORT_START("line_8") | |
| 164 | 164 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH)// / |
| 165 | 165 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN) |
| 166 | 166 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED) // ???? |
| 167 | 167 | PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) |
| 168 | 168 | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_UP) |
| 169 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED) // : | |
| 169 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED) // : | |
| 170 | 170 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) |
| 171 | 171 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) |
| 172 | ||
| 173 | PORT_START("line_9") | |
| 172 | ||
| 173 | PORT_START("line_9") | |
| 174 | 174 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) // return |
| 175 | 175 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED) // ???? |
| 176 | 176 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED) // ???? |
| r25360 | r25361 | |
| 187 | 187 | int i; |
| 188 | 188 | |
| 189 | 189 | for(i=0;i<8;i++) { |
| 190 | palette_set_color_rgb(machine(), i, pal1bit(i >> 1),pal1bit(i >> 2),pal1bit(i >> 0)); | |
| 190 | palette_set_color_rgb(machine(), i, pal1bit(i >> 1),pal1bit(i >> 2),pal1bit(i >> 0)); | |
| 191 | 191 | } |
| 192 | 192 | } |
| 193 | 193 | |
| r25360 | r25361 | |
| 201 | 201 | { |
| 202 | 202 | UINT16 addr = 0xa000 + sx*8 + ra + ma * 8; |
| 203 | 203 | UINT8 code = program.read_byte(addr); |
| 204 | ||
| 204 | ||
| 205 | 205 | for (int x = 0; x <= 8; x++) |
| 206 | 206 | { |
| 207 | 207 | int color = BIT(code, 7-x) ? 7 : 0; |
| r25360 | r25361 | |
| 241 | 241 | "line_8", "line_9", NULL, NULL, |
| 242 | 242 | NULL,NULL,NULL,NULL |
| 243 | 243 | }; |
| 244 | ||
| 245 | if( keynames[m_portb & 0x0f]) | |
| 244 | ||
| 245 | if( keynames[m_portb & 0x0f]) | |
| 246 | 246 | return ioport(keynames[m_portb & 0x0f])->read(); |
| 247 | 247 | return 0xff; |
| 248 | 248 | } |
| 249 | 249 | |
| 250 | 250 | WRITE_LINE_MEMBER(lola8a_state::crtc_vsync) |
| 251 | 251 | { |
| 252 | m_maincpu->set_input_line(I8085_RST75_LINE, state? ASSERT_LINE : CLEAR_LINE); | |
| 252 | m_maincpu->set_input_line(I8085_RST75_LINE, state? ASSERT_LINE : CLEAR_LINE); | |
| 253 | 253 | } |
| 254 | 254 | |
| 255 | 255 | static MC6845_INTERFACE( hd46505sp_intf ) |
| r25360 | r25361 | |
| 283 | 283 | MCFG_CPU_IO_MAP(lola8a_io) |
| 284 | 284 | MCFG_I8085A_SID(READLINE(lola8a_state, cass_r)) |
| 285 | 285 | MCFG_I8085A_SOD(WRITELINE(lola8a_state, cass_w)) |
| 286 | ||
| 286 | ||
| 287 | 287 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 288 | 288 | MCFG_SOUND_ADD(AY8910_TAG, AY8910, XTAL_4_9152MHz / 4) |
| 289 | 289 | MCFG_SOUND_CONFIG(psg_intf) |
| 290 | 290 | MCFG_SOUND_ROUTE(ALL_OUTPUTS,"mono",1.0) |
| 291 | ||
| 291 | ||
| 292 | 292 | /* video hardware */ |
| 293 | 293 | MCFG_SCREEN_ADD("screen", RASTER) |
| 294 | 294 | MCFG_SCREEN_REFRESH_RATE(50) |
| r25360 | r25361 | |
| 297 | 297 | MCFG_SCREEN_SIZE(640, 480) |
| 298 | 298 | MCFG_SCREEN_VISIBLE_AREA(0, 640-1, 0, 480-1) |
| 299 | 299 | MCFG_MC6845_ADD(HD46505SP_TAG, HD6845, "screen", XTAL_8MHz / 8, hd46505sp_intf) // HD6845 == HD46505S |
| 300 | ||
| 300 | MCFG_PALETTE_LENGTH(8) | |
| 301 | 301 | |
| 302 | 302 | /* Cassette */ |
| 303 | 303 | MCFG_CASSETTE_ADD( "cassette", default_cassette_interface ) |
| r25360 | r25361 | |
| 315 | 315 | |
| 316 | 316 | /* Driver */ |
| 317 | 317 | |
| 318 | /* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */ | |
| 319 | COMP( 1986, lola8a, 0, 0, lola8a, lola8a, driver_device, 0, "Institut Ivo Lola Ribar", "Lola 8A", GAME_NOT_WORKING) | |
| 320 | ||
| 318 | /* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */ | |
| 319 | COMP( 1986, lola8a, 0, 0, lola8a, lola8a, driver_device, 0, "Institut Ivo Lola Ribar", "Lola 8A", GAME_NOT_WORKING) |
| r25360 | r25361 | |
|---|---|---|
| 284 | 284 | MCFG_CPU_PROGRAM_MAP(sbc6510_mem) |
| 285 | 285 | |
| 286 | 286 | MCFG_CPU_ADD("videocpu",ATMEGA88, XTAL_16MHz) |
| 287 | // | |
| 287 | // MCFG_DEVICE_DISABLE() // trips SLEEP opcode, needs to be emulated | |
| 288 | 288 | MCFG_CPU_AVR8_CONFIG(atmega88_config) |
| 289 | 289 | MCFG_CPU_PROGRAM_MAP(sbc6510_video_mem) |
| 290 | 290 | MCFG_CPU_DATA_MAP(sbc6510_video_data) |
| r25360 | r25361 | |
|---|---|---|
| 639 | 639 | SLOT_INTERFACE("zipdrive", A2BUS_ZIPDRIVE) /* ZIP Technologies IDE card */ |
| 640 | 640 | SLOT_INTERFACE("echoiiplus", A2BUS_ECHOPLUS) /* Street Electronics Echo Plus (Echo II + Mockingboard clone) */ |
| 641 | 641 | SLOT_INTERFACE("scsi", A2BUS_SCSI) /* Apple II SCSI Card */ |
| 642 | SLOT_INTERFACE("applicard", A2BUS_APPLICARD) | |
| 642 | SLOT_INTERFACE("applicard", A2BUS_APPLICARD) /* PCPI Applicard */ | |
| 643 | 643 | SLOT_INTERFACE_END |
| 644 | 644 | |
| 645 | 645 | static SLOT_INTERFACE_START(apple2eaux_cards) |
| r25360 | r25361 | |
| 1150 | 1150 | #if 0 |
| 1151 | 1151 | ROM_START(laba2p) /* II Plus clone with on-board Disk II controller and Videx-compatible 80-column card, supposedly from lab equipment */ |
| 1152 | 1152 | ROM_REGION(0x1000,"gfx1",0) |
| 1153 | ROM_LOAD( "char.u30", 0x0000, 0x1000, CRC(2dbaef88) SHA1(9834842796132a11facd57923326d6954bcb609f) ) | |
| 1153 | ROM_LOAD( "char.u30", 0x0000, 0x1000, CRC(2dbaef88) SHA1(9834842796132a11facd57923326d6954bcb609f) ) | |
| 1154 | 1154 | |
| 1155 | 1155 | ROM_REGION(0x4700,"maincpu",0) |
| 1156 | ROM_LOAD( "maind0.u35", 0x1000, 0x1000, CRC(24d73c7b) SHA1(d17a15868dc875c67061c95ec53a6b2699d3a425) ) | |
| 1157 | ROM_LOAD( "maine0.u34", 0x2000, 0x2000, CRC(314462ca) SHA1(5a23616dca14e59b4aca8ff6cfa0d98592a78a79) ) | |
| 1156 | ROM_LOAD( "maind0.u35", 0x1000, 0x1000, CRC(24d73c7b) SHA1(d17a15868dc875c67061c95ec53a6b2699d3a425) ) | |
| 1157 | ROM_LOAD( "maine0.u34", 0x2000, 0x2000, CRC(314462ca) SHA1(5a23616dca14e59b4aca8ff6cfa0d98592a78a79) ) | |
| 1158 | 1158 | |
| 1159 | 1159 | ROM_REGION(0x1000, "fw80col", 0) |
| 1160 | ROM_LOAD( "80cfw.u3", 0x0000, 0x1000, CRC(92d2b8b0) SHA1(5149483eb3e550ece1584e85fc821bb04d068dec) ) | |
| 1160 | ROM_LOAD( "80cfw.u3", 0x0000, 0x1000, CRC(92d2b8b0) SHA1(5149483eb3e550ece1584e85fc821bb04d068dec) ) // firmware for on-board Videx | |
| 1161 | 1161 | |
| 1162 | 1162 | ROM_REGION(0x1000, "cg80col", 0) |
| 1163 | ROM_LOAD( "80ccgv80.u25", 0x0000, 0x1000, CRC(6d5e2707) SHA1(c56f76e8a366fee7374eb09f4866435c692490b2) ) | |
| 1163 | ROM_LOAD( "80ccgv80.u25", 0x0000, 0x1000, CRC(6d5e2707) SHA1(c56f76e8a366fee7374eb09f4866435c692490b2) ) // character generator for on-board Videx | |
| 1164 | 1164 | |
| 1165 | 1165 | ROM_REGION(0x800, "diskii", 0) |
| 1166 | ROM_LOAD( "diskfw.u7", 0x0000, 0x0800, CRC(9207ef4e) SHA1(5fcffa4c68b16a7ef2f62651d4c7470400e5bd35) ) | |
| 1166 | ROM_LOAD( "diskfw.u7", 0x0000, 0x0800, CRC(9207ef4e) SHA1(5fcffa4c68b16a7ef2f62651d4c7470400e5bd35) ) // firmware for on-board Disk II | |
| 1167 | 1167 | |
| 1168 | 1168 | ROM_REGION(0x800, "unknown", 0) |
| 1169 | ROM_LOAD( "unk.u5", 0x0000, 0x0800, CRC(240a1774) SHA1(e6aeb0702dc99d76fd8c5a642fdfbe9ab896acd4) ) | |
| 1169 | ROM_LOAD( "unk.u5", 0x0000, 0x0800, CRC(240a1774) SHA1(e6aeb0702dc99d76fd8c5a642fdfbe9ab896acd4) ) // unknown ROM | |
| 1170 | 1170 | ROM_END |
| 1171 | 1171 | #endif |
| 1172 | 1172 | |
| r25360 | r25361 | |
| 1197 | 1197 | COMP( 1985, space84, apple2, 0, space84, apple2p, driver_device, 0, "ComputerTechnik/IBS", "Space 84", GAME_NOT_WORKING ) |
| 1198 | 1198 | COMP( 1985, am64, apple2, 0, space84, apple2p, driver_device, 0, "ASEM", "AM 64", GAME_SUPPORTS_SAVE ) |
| 1199 | 1199 | //COMP( 19??, laba2p, apple2, 0, laba2p, apple2p, driver_device, 0, "<unknown>", "Lab equipment Apple II Plus clone", GAME_SUPPORTS_SAVE ) |
| 1200 |
| r25360 | r25361 | |
|---|---|---|
| 860 | 860 | CONS( 1994, cdx, 0, 0, genesis_scd, md, md_cons_state, genesis, "Sega", "CDX (USA, NTSC)", GAME_NOT_WORKING ) |
| 861 | 861 | CONS( 1994, multmega, cdx, 0, md_scd, md, md_cons_state, md_eur, "Sega", "Multi-Mega (Europe, PAL)", GAME_NOT_WORKING ) |
| 862 | 862 | CONS( 1994, 32x_scd, 0, 0, genesis_32x_scd, md, md_cons_state, genesis, "Sega", "Sega CD (USA, NTSC, w/32X)", GAME_NOT_WORKING ) |
| 863 |
| r25360 | r25361 | |
|---|---|---|
| 434 | 434 | { |
| 435 | 435 | int sx = m_screen->hpos() + 4; |
| 436 | 436 | int y = m_screen->vpos(); |
| 437 | ||
| 437 | ||
| 438 | 438 | UINT8 addr = offset & 0xff; |
| 439 | 439 | UINT8 color0 = m_color0_ram[addr]; |
| 440 | 440 | UINT8 color1 = m_color1_ram[addr]; |
| r25360 | r25361 | |
| 695 | 695 | |
| 696 | 696 | /* Game Drivers */ |
| 697 | 697 | |
| 698 | // YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS | |
| 699 | CONS( 1977, studio2, 0, 0, studio2, studio2, studio2_state, studio2, "RCA", "Studio II", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) | |
| 700 | CONS( 1978, visicom, studio2,0, visicom, studio2, studio2_state, studio2, "Toshiba", "Visicom COM-100 (Japan)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) | |
| 701 | CONS( 1978, mpt02, studio2,0, mpt02, studio2, studio2_state, studio2, "Soundic", "Victory MPT-02 Home TV Programmer (Austria)", GAME_SUPPORTS_SAVE ) | |
| 702 | CONS( 1978, mpt02h, studio2,0, mpt02, studio2, studio2_state, studio2, "Hanimex", "MPT-02 Jeu TV Programmable (France)", GAME_SUPPORTS_SAVE ) | |
| 703 | CONS( 1978, mtc9016, studio2,0, mpt02, studio2, studio2_state, studio2, "Mustang", "9016 Telespiel Computer (Germany)", GAME_SUPPORTS_SAVE ) | |
| 704 | CONS( 1978, shmc1200, studio2,0, mpt02, studio2, studio2_state, studio2, "Sheen", "1200 Micro Computer (Australia)", GAME_SUPPORTS_SAVE ) | |
| 705 | CONS( 1978, cm1200, studio2,0, mpt02, studio2, studio2_state, studio2, "Conic", "M-1200 (?)", GAME_SUPPORTS_SAVE ) | |
| 706 | CONS( 1978, apollo80, studio2,0, mpt02, studio2, studio2_state, studio2, "Academy", "Apollo 80 (Germany)", GAME_SUPPORTS_SAVE ) | |
| 698 | // YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS | |
| 699 | CONS( 1977, studio2, 0, 0, studio2, studio2, studio2_state, studio2, "RCA", "Studio II", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) | |
| 700 | CONS( 1978, visicom, studio2,0, visicom, studio2, studio2_state, studio2, "Toshiba", "Visicom COM-100 (Japan)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) | |
| 701 | CONS( 1978, mpt02, studio2,0, mpt02, studio2, studio2_state, studio2, "Soundic", "Victory MPT-02 Home TV Programmer (Austria)", GAME_SUPPORTS_SAVE ) | |
| 702 | CONS( 1978, mpt02h, studio2,0, mpt02, studio2, studio2_state, studio2, "Hanimex", "MPT-02 Jeu TV Programmable (France)", GAME_SUPPORTS_SAVE ) | |
| 703 | CONS( 1978, mtc9016, studio2,0, mpt02, studio2, studio2_state, studio2, "Mustang", "9016 Telespiel Computer (Germany)", GAME_SUPPORTS_SAVE ) | |
| 704 | CONS( 1978, shmc1200, studio2,0, mpt02, studio2, studio2_state, studio2, "Sheen", "1200 Micro Computer (Australia)", GAME_SUPPORTS_SAVE ) | |
| 705 | CONS( 1978, cm1200, studio2,0, mpt02, studio2, studio2_state, studio2, "Conic", "M-1200 (?)", GAME_SUPPORTS_SAVE ) | |
| 706 | CONS( 1978, apollo80, studio2,0, mpt02, studio2, studio2_state, studio2, "Academy", "Apollo 80 (Germany)", GAME_SUPPORTS_SAVE ) |
| r25360 | r25361 | |
|---|---|---|
| 11 | 11 | |
| 12 | 12 | LA05-123 Pinout |
| 13 | 13 | --------------- |
| 14 | _____ _____ | |
| 15 | NEXTP 1 |* \_/ | 28 +5V | |
| 16 | PD0 2 | | 27 _ROML2 | |
| 17 | PD1 3 | | 26 _ROML | |
| 18 | PD2 4 | | 25 _I/O2 | |
| 19 | PD3 5 | | 24 _GAME | |
| 20 | CLEAR 6 | | 23 PHI2 | |
| 14 | _____ _____ | |
| 15 | NEXTP 1 |* \_/ | 28 +5V | |
| 16 | PD0 2 | | 27 _ROML2 | |
| 17 | PD1 3 | | 26 _ROML | |
| 18 | PD2 4 | | 25 _I/O2 | |
| 19 | PD3 5 | | 24 _GAME | |
| 20 | CLEAR 6 | | 23 PHI2 | |
| 21 | 21 | _RAM/EPROM 7 | LA05-123 | 22 _ROMH2 |
| 22 | PB5 8 | LA05-124 | 21 _ROMH | |
| 23 | PB6 9 | | 20 CLOCK | |
| 24 | _6525 10 | | 19 SDO | |
| 25 | _EPROM 11 | | 18 NEXTS | |
| 26 | CA12 12 | | 17 _DA/CA | |
| 27 | CA14 13 | | 16 CA15 | |
| 28 | GND 14 |_____________| 15 CA13 | |
| 22 | PB5 8 | LA05-124 | 21 _ROMH | |
| 23 | PB6 9 | | 20 CLOCK | |
| 24 | _6525 10 | | 19 SDO | |
| 25 | _EPROM 11 | | 18 NEXTS | |
| 26 | CA12 12 | | 17 _DA/CA | |
| 27 | CA14 13 | | 16 CA15 | |
| 28 | GND 14 |_____________| 15 CA13 | |
| 29 | 29 | |
| 30 | 30 | |
| 31 | 31 | http://www.stefan-uhlmann.de/cbm/MVM/index.html |
| r25360 | r25361 | |
| 34 | 34 | |
| 35 | 35 | /* |
| 36 | 36 | |
| 37 | ||
| 37 | TODO: | |
| 38 | 38 | |
| 39 | ||
| 39 | - T6721A speech synthesis | |
| 40 | 40 | |
| 41 | 41 | */ |
| 42 | 42 | |
| r25360 | r25361 | |
| 48 | 48 | // MACROS / CONSTANTS |
| 49 | 49 | //************************************************************************** |
| 50 | 50 | |
| 51 | #define T6721A_TAG "u5" | |
| 52 | #define MOS6525_TAG "u2" | |
| 53 | #define CMOS40105_TAG "u1" | |
| 51 | #define T6721A_TAG "u5" | |
| 52 | #define MOS6525_TAG "u2" | |
| 53 | #define CMOS40105_TAG "u1" | |
| 54 | 54 | |
| 55 | #define A12 BIT(offset, 12) | |
| 56 | #define A13 BIT(offset, 13) | |
| 57 | #define A14 BIT(offset, 14) | |
| 58 | #define A15 BIT(offset, 15) | |
| 55 | #define A12 BIT(offset, 12) | |
| 56 | #define A13 BIT(offset, 13) | |
| 57 | #define A14 BIT(offset, 14) | |
| 58 | #define A15 BIT(offset, 15) | |
| 59 | 59 | #define PB5 BIT(m_tpi_pb, 5) |
| 60 | 60 | #define PB6 BIT(m_tpi_pb, 6) |
| 61 | 61 | |
| r25360 | r25361 | |
| 80 | 80 | READ8_MEMBER( c64_magic_voice_cartridge_device::tpi_pa_r ) |
| 81 | 81 | { |
| 82 | 82 | /* |
| 83 | ||
| 83 | ||
| 84 | 84 | bit description |
| 85 | ||
| 86 | 0 | |
| 87 | 1 | |
| 88 | 2 | |
| 89 | 3 | |
| 90 | 4 | |
| 85 | ||
| 86 | 0 | |
| 87 | 1 | |
| 88 | 2 | |
| 89 | 3 | |
| 90 | 4 | |
| 91 | 91 | 5 J1 _GAME |
| 92 | 92 | 6 T6721 _EOS |
| 93 | 93 | 7 FIFO DIR |
| 94 | ||
| 94 | ||
| 95 | 95 | */ |
| 96 | 96 | |
| 97 | 97 | UINT8 data = 0; |
| r25360 | r25361 | |
| 106 | 106 | WRITE8_MEMBER( c64_magic_voice_cartridge_device::tpi_pa_w ) |
| 107 | 107 | { |
| 108 | 108 | /* |
| 109 | ||
| 109 | ||
| 110 | 110 | bit description |
| 111 | ||
| 111 | ||
| 112 | 112 | 0 FIFO D0 |
| 113 | 113 | 1 FIFO D1 |
| 114 | 114 | 2 FIFO D2 |
| 115 | 115 | 3 FIFO D3 |
| 116 | 116 | 4 FIFO SI |
| 117 | 5 | |
| 118 | 6 | |
| 119 | 7 | |
| 120 | ||
| 117 | 5 | |
| 118 | 6 | |
| 119 | 7 | |
| 120 | ||
| 121 | 121 | */ |
| 122 | 122 | |
| 123 | 123 | m_fifo->write(data & 0x0f); |
| r25360 | r25361 | |
| 127 | 127 | READ8_MEMBER( c64_magic_voice_cartridge_device::tpi_pb_r ) |
| 128 | 128 | { |
| 129 | 129 | /* |
| 130 | ||
| 130 | ||
| 131 | 131 | bit description |
| 132 | ||
| 133 | 0 | |
| 134 | 1 | |
| 135 | 2 | |
| 136 | 3 | |
| 137 | 4 | |
| 138 | 5 | |
| 139 | 6 | |
| 132 | ||
| 133 | 0 | |
| 134 | 1 | |
| 135 | 2 | |
| 136 | 3 | |
| 137 | 4 | |
| 138 | 5 | |
| 139 | 6 | |
| 140 | 140 | 7 J1 _EXROM |
| 141 | ||
| 141 | ||
| 142 | 142 | */ |
| 143 | 143 | |
| 144 | 144 | UINT8 data = 0; |
| r25360 | r25361 | |
| 151 | 151 | WRITE8_MEMBER( c64_magic_voice_cartridge_device::tpi_pb_w ) |
| 152 | 152 | { |
| 153 | 153 | /* |
| 154 | ||
| 154 | ||
| 155 | 155 | bit description |
| 156 | ||
| 156 | ||
| 157 | 157 | 0 T6721 D0 |
| 158 | 158 | 1 T6721 D1 |
| 159 | 159 | 2 T6721 D2 |
| r25360 | r25361 | |
| 161 | 161 | 4 T6721 _WR |
| 162 | 162 | 5 LA05-124 pin 8 (DA/CA) |
| 163 | 163 | 6 LA05-124 pin 9 (passthru) |
| 164 | 7 | |
| 165 | ||
| 164 | 7 | |
| 165 | ||
| 166 | 166 | */ |
| 167 | 167 | |
| 168 | 168 | if (!BIT(m_tpi_pb, 4) && BIT(data, 4)) |
| r25360 | r25361 | |
| 208 | 208 | m_vslsi->di_w(m_pd & 0x01); |
| 209 | 209 | |
| 210 | 210 | m_pd >>= 1; |
| 211 | } | |
| 211 | } | |
| 212 | 212 | } |
| 213 | 213 | |
| 214 | 214 | WRITE_LINE_MEMBER( c64_magic_voice_cartridge_device::dtrd_w ) |
| r25360 | r25361 | |
|---|---|---|
| 28 | 28 | // ======================> c64_magic_voice_cartridge_device |
| 29 | 29 | |
| 30 | 30 | class c64_magic_voice_cartridge_device : public device_t, |
| 31 | | |
| 31 | public device_c64_expansion_card_interface | |
| 32 | 32 | { |
| 33 | 33 | public: |
| 34 | 34 | // construction/destruction |
| r25360 | r25361 | |
|---|---|---|
| 25 | 25 | // ======================> c64_music64_cartridge_device |
| 26 | 26 | |
| 27 | 27 | class c64_music64_cartridge_device : public device_t, |
| 28 | | |
| 28 | public device_c64_expansion_card_interface | |
| 29 | 29 | { |
| 30 | 30 | public: |
| 31 | 31 | // construction/destruction |
| r25360 | r25361 | |
|---|---|---|
| 757 | 757 | if (m_side != side) |
| 758 | 758 | { |
| 759 | 759 | m_side = side; |
| 760 | ||
| 760 | ||
| 761 | 761 | // read new track data |
| 762 | 762 | read_current_track(); |
| 763 | 763 | } |
| r25360 | r25361 | |
|---|---|---|
| 3 | 3 | Roland MPU-401 core |
| 4 | 4 | |
| 5 | 5 | This emulates the MPU-401 external box with the 6801, ASIC, and RAM in it. |
| 6 | ||
| 6 | ||
| 7 | 7 | We do it this way to facilitate the various PC, Apple II, C64, and other |
| 8 | 8 | possible hookups. |
| 9 | ||
| 9 | ||
| 10 | 10 | 6801 GPIO port hookups (from the schematics) |
| 11 | ||
| 11 | ||
| 12 | 12 | P10 / P11 / P12: drive the metronome and speaker |
| 13 | 13 | P13 / P14 / P15: drive 3 pins on the SYNC OUT connector |
| 14 | 14 | P16: to DSRD on gate array |
| 15 | 15 | P17: to DRRD on gate array |
| 16 | ||
| 16 | ||
| 17 | 17 | P20: to SYC OUT on gate array |
| 18 | 18 | P21: to SYC IN on gate array, pulled up to Vcc via 4.7K resistor |
| 19 | ||
| 19 | programmed as output of timer (OLVL) | |
| 20 | 20 | P22: to SRCK on gate array, inverted |
| 21 | 21 | P23: MIDI IN serial data (SCI in) |
| 22 | 22 | P24: MIDI OUT serial data (SCI out) |
| 23 | ||
| 23 | ||
| 24 | 24 | ASIC addresses from the 6801: |
| 25 | 25 | 0x20: (r) read pending byte from the PC (w) apparently nothing |
| 26 | 26 | 0x21: (r) ASIC status, see STAT_xxx bits below (w) send new byte to PC data port |
| 27 | ||
| 27 | ||
| 28 | 28 | Theory of operation: 6801's timer/counter is set up to drive a pulse stream |
| 29 | 29 | out P21 to the ASIC's SYC IN pin. The ASIC in turn generates the MIDI baud |
| 30 | 30 | rate (times 8) and returns that on pin P22. |
| 31 | ||
| 31 | ||
| 32 | 32 | The 6801 is believed to run in mode 2, based on a combination of the |
| 33 | 33 | schematics and the behavior (ie, internal RAM from 80-FF is clearly |
| 34 | 34 | present from the program's behavior, and ports 3/4 are obviously external |
| r25360 | r25361 | |
| 38 | 38 | |
| 39 | 39 | #include "machine/mpu401.h" |
| 40 | 40 | |
| 41 | #define M6801_TAG "mpu6801" | |
| 42 | #define ROM_TAG "mpurom" | |
| 43 | #define MIDIIN_TAG "mdin" | |
| 44 | #define MIDIOUT_TAG "mdout" | |
| 41 | #define M6801_TAG "mpu6801" | |
| 42 | #define ROM_TAG "mpurom" | |
| 43 | #define MIDIIN_TAG "mdin" | |
| 44 | #define MIDIOUT_TAG "mdout" | |
| 45 | 45 | |
| 46 | #define P2_SYNC_OUT (0x01) | |
| 47 | #define P2_SYNC_IN (0x02) | |
| 48 | #define P2_SRCK_OUT (0x04) | |
| 49 | #define P2_MIDI_IN (0x08) | |
| 50 | #define P2_MIDI_OUT (0x10) | |
| 46 | #define P2_SYNC_OUT (0x01) | |
| 47 | #define P2_SYNC_IN (0x02) | |
| 48 | #define P2_SRCK_OUT (0x04) | |
| 49 | #define P2_MIDI_IN (0x08) | |
| 50 | #define P2_MIDI_OUT (0x10) | |
| 51 | 51 | |
| 52 | #define STAT_CMD_PORT (0x01) // set if the new byte indicated by TX FULL was written to the command port, clear for data port | |
| 53 | #define STAT_TX_FULL (0x40) // indicates the PC has written a new byte we haven't read yet | |
| 54 | #define STAT_RX_EMPTY (0x80) // indicates we've written a new byte the PC hasn't read yet | |
| 52 | #define STAT_CMD_PORT (0x01) // set if the new byte indicated by TX FULL was written to the command port, clear for data port | |
| 53 | #define STAT_TX_FULL (0x40) // indicates the PC has written a new byte we haven't read yet | |
| 54 | #define STAT_RX_EMPTY (0x80) // indicates we've written a new byte the PC hasn't read yet | |
| 55 | 55 | |
| 56 | 56 | static ADDRESS_MAP_START( mpu401_map, AS_PROGRAM, 8, mpu401_device ) |
| 57 | 57 | AM_RANGE(0x0000, 0x001f) AM_READWRITE(regs_mode2_r, regs_mode2_w) |
| 58 | 58 | AM_RANGE(0x0020, 0x0021) AM_READWRITE(asic_r, asic_w) |
| 59 | AM_RANGE(0x0080, 0x00ff) AM_RAM // on-chip RAM | |
| 60 | AM_RANGE(0x0800, 0x0fff) AM_RAM // external RAM | |
| 59 | AM_RANGE(0x0080, 0x00ff) AM_RAM // on-chip RAM | |
| 60 | AM_RANGE(0x0800, 0x0fff) AM_RAM // external RAM | |
| 61 | 61 | AM_RANGE(0xf000, 0xffff) AM_ROM AM_REGION(ROM_TAG, 0) |
| 62 | 62 | ADDRESS_MAP_END |
| 63 | 63 | |
| r25360 | r25361 | |
| 85 | 85 | }; |
| 86 | 86 | |
| 87 | 87 | MACHINE_CONFIG_FRAGMENT( mpu401 ) |
| 88 | MCFG_CPU_ADD(M6801_TAG, M6801, 4000000) | |
| 88 | MCFG_CPU_ADD(M6801_TAG, M6801, 4000000) /* 4 MHz as per schematics */ | |
| 89 | 89 | MCFG_CPU_PROGRAM_MAP(mpu401_map) |
| 90 | 90 | MCFG_CPU_IO_MAP(mpu401_io_map) |
| 91 | 91 | MCFG_M6801_SER_TX(WRITELINE(mpu401_device, mpu401_midi_tx)) |
| r25360 | r25361 | |
| 96 | 96 | |
| 97 | 97 | ROM_START( mpu401 ) |
| 98 | 98 | ROM_REGION(0x1000, ROM_TAG, 0) |
| 99 | ROM_LOAD( "roland_6801v0b55p.bin", 0x000000, 0x001000, CRC(65d3a151) SHA1(00efbfb96aeb997b69bb16981c6751d3c784bb87) ) | |
| 99 | ROM_LOAD( "roland_6801v0b55p.bin", 0x000000, 0x001000, CRC(65d3a151) SHA1(00efbfb96aeb997b69bb16981c6751d3c784bb87) ) | |
| 100 | 100 | ROM_END |
| 101 | 101 | |
| 102 | 102 | //************************************************************************** |
| r25360 | r25361 | |
| 156 | 156 | |
| 157 | 157 | void mpu401_device::device_reset() |
| 158 | 158 | { |
| 159 | m_port2 = 0xff & ~(P2_SRCK_OUT | P2_MIDI_IN); | |
| 159 | m_port2 = 0xff & ~(P2_SRCK_OUT | P2_MIDI_IN); // prevent spurious reception | |
| 160 | 160 | m_command = 0; |
| 161 | 161 | m_mpudata = 0; |
| 162 | 162 | m_gatearrstat = 0; |
| r25360 | r25361 | |
| 182 | 182 | case 6: |
| 183 | 183 | case 7: |
| 184 | 184 | case 0xf: |
| 185 | // | |
| 185 | // printf("MPU401: read @ unk %x (PC=%x)\n", offset, space.device().safe_pc()); | |
| 186 | 186 | break; |
| 187 | 187 | |
| 188 | 188 | default: |
| r25360 | r25361 | |
| 201 | 201 | case 6: |
| 202 | 202 | case 7: |
| 203 | 203 | case 0xf: |
| 204 | // | |
| 204 | // printf("MPU401: %02x @ unk %x (PC=%x)\n", data, offset, space.device().safe_pc()); | |
| 205 | 205 | break; |
| 206 | 206 | |
| 207 | 207 | default: |
| r25360 | r25361 | |
| 216 | 216 | |
| 217 | 217 | WRITE8_MEMBER(mpu401_device::port1_w) |
| 218 | 218 | { |
| 219 | // | |
| 219 | // printf("port1_w: %02x met %x syncout %x DSRD %d DRRD %d\n", data, data & 3, (data>>3) & 3, (data>>6) & 1, (data>>7) & 1); | |
| 220 | 220 | } |
| 221 | 221 | |
| 222 | 222 | READ8_MEMBER(mpu401_device::port2_r) |
| 223 | 223 | { |
| 224 | // | |
| 224 | // printf("Read P2 (PC=%x)\n", space.device().safe_pc()); | |
| 225 | 225 | return m_port2; |
| 226 | 226 | } |
| 227 | 227 | |
| 228 | 228 | WRITE8_MEMBER(mpu401_device::port2_w) |
| 229 | 229 | { |
| 230 | // | |
| 230 | // printf("port2_w: %02x SYCOUT %d SYCIN %d SRCK %d MIDI OUT %d\n", data, (data & 1), (data>>1) & 1, (data>>2) & 1, (data>>4) & 1); | |
| 231 | 231 | } |
| 232 | 232 | |
| 233 | 233 | READ8_MEMBER(mpu401_device::mpu_r) |
| 234 | 234 | { |
| 235 | // | |
| 235 | // printf("mpu_r @ %d\n", offset); | |
| 236 | 236 | |
| 237 | if (offset == 1) | |
| 237 | if (offset == 1) // status | |
| 238 | 238 | { |
| 239 | 239 | return m_gatearrstat; |
| 240 | 240 | } |
| 241 | else | |
| 241 | else // data | |
| 242 | 242 | { |
| 243 | 243 | write_irq(CLEAR_LINE); |
| 244 | 244 | m_gatearrstat |= STAT_RX_EMPTY; |
| r25360 | r25361 | |
| 248 | 248 | |
| 249 | 249 | WRITE8_MEMBER(mpu401_device::mpu_w) |
| 250 | 250 | { |
| 251 | // | |
| 251 | // printf("%02x to MPU-401 @ %d\n", data, offset); | |
| 252 | 252 | m_command = data; |
| 253 | 253 | m_gatearrstat |= STAT_TX_FULL; |
| 254 | 254 | |
| r25360 | r25361 | |
| 269 | 269 | m_gatearrstat &= ~STAT_TX_FULL; |
| 270 | 270 | return m_command; |
| 271 | 271 | } |
| 272 | else if (offset == 1) | |
| 272 | else if (offset == 1) | |
| 273 | 273 | { |
| 274 | 274 | return m_gatearrstat; |
| 275 | 275 | } |
| r25360 | r25361 | |
| 279 | 279 | |
| 280 | 280 | WRITE8_MEMBER(mpu401_device::asic_w) |
| 281 | 281 | { |
| 282 | // | |
| 282 | // printf("MPU401: %02x to gate array @ %d\n", data, offset); | |
| 283 | 283 | |
| 284 | 284 | if (offset == 1) |
| 285 | 285 | { |
| r25360 | r25361 | |
| 307 | 307 | { |
| 308 | 308 | m_mdout->tx(state); |
| 309 | 309 | } |
| 310 |
| r25360 | r25361 | |
|---|---|---|
| 73 | 73 | extern const device_type MPU401; |
| 74 | 74 | |
| 75 | 75 | #endif /* __MPU401_H__ */ |
| 76 | ||
| 77 |
| r25360 | r25361 | |
|---|---|---|
| 48 | 48 | |
| 49 | 49 | isa8_wd1002a_wx1_device::isa8_wd1002a_wx1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 50 | 50 | : device_t(mconfig, ISA8_WD1002A_WX1, "WD1002A-WX1", tag, owner, clock, "wd1002a_wx1", __FILE__), |
| 51 | | |
| 51 | device_isa8_card_interface( mconfig, *this ) | |
| 52 | 52 | { |
| 53 | 53 | } |
| 54 | 54 |
| r25360 | r25361 | |
|---|---|---|
| 505 | 505 | PB0 DEVICE NUMBER SELECTION |
| 506 | 506 | PB1 DEVICE NUMBER SELECTION |
| 507 | 507 | PB2 DEVICE NUMBER SELECTION |
| 508 | PB3 | |
| 509 | PB4 | |
| 510 | PB5 | |
| 508 | PB3 | |
| 509 | PB4 | |
| 510 | PB5 | |
| 511 | 511 | PB6 DACI |
| 512 | 512 | PB7 RFDI |
| 513 | 513 | |
| r25360 | r25361 | |
| 533 | 533 | |
| 534 | 534 | bit description |
| 535 | 535 | |
| 536 | PB0 | |
| 537 | PB1 | |
| 538 | PB2 | |
| 536 | PB0 | |
| 537 | PB1 | |
| 538 | PB2 | |
| 539 | 539 | PB3 ACT LED 1 |
| 540 | 540 | PB4 ACT LED 0 |
| 541 | 541 | PB5 ERR LED |
| 542 | PB6 | |
| 543 | PB7 | |
| 542 | PB6 | |
| 543 | PB7 | |
| 544 | 544 | |
| 545 | 545 | */ |
| 546 | 546 |
| r25360 | r25361 | |
|---|---|---|
| 40 | 40 | DECLARE_READ8_MEMBER( status_r ); |
| 41 | 41 | DECLARE_READ8_MEMBER( control_r ); |
| 42 | 42 | DECLARE_WRITE8_MEMBER( control_w ); |
| 43 | ||
| 43 | ||
| 44 | 44 | DECLARE_WRITE_LINE_MEMBER( ack_w ); |
| 45 | ||
| 45 | ||
| 46 | 46 | protected: |
| 47 | 47 | // device-level overrides |
| 48 | 48 | virtual void device_config_complete(); |
| r25360 | r25361 | |
|---|---|---|
| 42 | 42 | |
| 43 | 43 | ti_sound_sn94624_device::ti_sound_sn94624_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 44 | 44 | : ti_sound_system_device(mconfig, TISOUND_94624, tag, "Onboard sound (SN94624)", owner, clock, "ti_sound_sn94624", __FILE__) |
| 45 | { | |
| 45 | { | |
| 46 | 46 | } |
| 47 | 47 | |
| 48 | 48 | ti_sound_sn76496_device::ti_sound_sn76496_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 49 | 49 | : ti_sound_system_device(mconfig, TISOUND_76496, tag, "Onboard sound (SN76496)", owner, clock, "ti_sound_sn76496", __FILE__) |
| 50 | { | |
| 50 | { | |
| 51 | 51 | } |
| 52 | 52 | |
| 53 | 53 | /*****************************************************************************/ |
| r25360 | r25361 | |
|---|---|---|
| 8 | 8 | speech synthesizer must be moved into the Peripheral Box. |
| 9 | 9 | |
| 10 | 10 | The Speech Synthesizer used for the TI was the CD2501E, AKA TMS5200, |
| 11 | (internal name TMC0285), a predecessor of the TMS5220 which was used in | |
| 12 | other commercial products. | |
| 11 | (internal name TMC0285), a predecessor of the TMS5220 which was used in | |
| 12 | other commercial products. | |
| 13 | 13 | |
| 14 | 14 | Note that this adapter also contains the speech roms. |
| 15 | 15 |
| r25360 | r25361 | |
|---|---|---|
| 98 | 98 | #define AUDIO_IS_CLASSIC (m_model <= MODEL_MAC_CLASSIC) |
| 99 | 99 | #define MAC_HAS_VIA2 ((m_model >= MODEL_MAC_II) && (m_model != MODEL_MAC_IIFX)) |
| 100 | 100 | |
| 101 | #define INTS_RBV ((m_model >= MODEL_MAC_IICI) && (m_model <= MODEL_MAC_IIVI)) || ((m_model >= MODEL_MAC_LC) && (m_model <= MODEL_MAC_LC_580)) | |
| 101 | #define INTS_RBV ((m_model >= MODEL_MAC_IICI) && (m_model <= MODEL_MAC_IIVI)) || ((m_model >= MODEL_MAC_LC) && (m_model <= MODEL_MAC_LC_580)) | |
| 102 | 102 | |
| 103 | 103 | #ifdef MAME_DEBUG |
| 104 | 104 | #define LOG_ADB 0 |
| r25360 | r25361 | |
| 673 | 673 | |
| 674 | 674 | WRITE_LINE_MEMBER(mac_state::mac_kbd_clk_in) |
| 675 | 675 | { |
| 676 | printf("CLK: %d\n", state^1); | |
| 677 | m_via1->write_cb1(state ? 0 : 1); | |
| 676 | printf("CLK: %d\n", state^1); | |
| 677 | m_via1->write_cb1(state ? 0 : 1); | |
| 678 | 678 | } |
| 679 | 679 | |
| 680 | 680 | #ifdef MAC_USE_EMULATED_KBD |
| 681 | 681 | READ8_MEMBER(mac_state::mac_via_in_cb2) |
| 682 | 682 | { |
| 683 | printf("Read %d from keyboard (PC=%x)\n", (m_mackbd->data_r() == ASSERT_LINE) ? 1 : 0, m_maincpu->pc()); | |
| 684 | return (m_mackbd->data_r() == ASSERT_LINE) ? 1 : 0; | |
| 683 | printf("Read %d from keyboard (PC=%x)\n", (m_mackbd->data_r() == ASSERT_LINE) ? 1 : 0, m_maincpu->pc()); | |
| 684 | return (m_mackbd->data_r() == ASSERT_LINE) ? 1 : 0; | |
| 685 | 685 | } |
| 686 | 686 | |
| 687 | 687 | WRITE8_MEMBER(mac_state::mac_via_out_cb2) |
| 688 | 688 | { |
| 689 | printf("Sending %d to kbd (PC=%x)\n", data, m_maincpu->pc()); | |
| 690 | m_mackbd->data_w((data & 1) ? ASSERT_LINE : CLEAR_LINE); | |
| 689 | printf("Sending %d to kbd (PC=%x)\n", data, m_maincpu->pc()); | |
| 690 | m_mackbd->data_w((data & 1) ? ASSERT_LINE : CLEAR_LINE); | |
| 691 | 691 | } |
| 692 | 692 | |
| 693 | #else | |
| 693 | #else // keyboard HLE | |
| 694 | 694 | |
| 695 | 695 | TIMER_CALLBACK_MEMBER(mac_state::kbd_clock) |
| 696 | 696 | { |
| r25360 | r25361 | |
|---|---|---|
| 1 | 1 | /**************************************************************************** |
| 2 | 2 | |
| 3 | ||
| 3 | SSE HardBox emulation | |
| 4 | 4 | |
| 5 | Copyright MESS Team. | |
| 6 | Visit http://mamedev.org for licensing and usage restrictions. | |
| 5 | Copyright MESS Team. | |
| 6 | Visit http://mamedev.org for licensing and usage restrictions. | |
| 7 | 7 | |
| 8 | 8 | ****************************************************************************/ |
| 9 | 9 | |
| 10 | 10 | /* |
| 11 | ||
| 11 | http://mikenaberezny.com/hardware/pet-cbm/sse-hardbox-corvus-interface/ | |
| 12 | 12 | |
| 13 | The HardBox provides a CBM DOS interface for a Corvus hard disk. Before | |
| 14 | it can be used, a hard disk image must first be created and formatted. | |
| 15 | Use the CHDMAN utility to create a 20MB image: | |
| 13 | The HardBox provides a CBM DOS interface for a Corvus hard disk. Before | |
| 14 | it can be used, a hard disk image must first be created and formatted. | |
| 15 | Use the CHDMAN utility to create a 20MB image: | |
| 16 | 16 | |
| 17 | ||
| 17 | $ chdman createhd -o /path/to/corvus20mb.chd -chs 388,5,20 -ss 512 | |
| 18 | 18 | |
| 19 | Start the pet8032 emulator with the HardBox attached as device 9, | |
| 20 | with the new CHD and the utilities floppy mounted: | |
| 19 | Start the pet8032 emulator with the HardBox attached as device 9, | |
| 20 | with the new CHD and the utilities floppy mounted: | |
| 21 | 21 | |
| 22 | $ mess pet8032 -ieee9 hardbox \ | |
| 23 | -hard1 /path/to/corvus20mb.chd \ | |
| 24 | -flop1 /path/to/hardbox-utils.d80 | |
| 25 | ||
| 26 | Load and run the "configure" program from the floppy. When prompted | |
| 27 | for the HardBox device number, enter "9". | |
| 22 | $ mess pet8032 -ieee9 hardbox \ | |
| 23 | -hard1 /path/to/corvus20mb.chd \ | |
| 24 | -flop1 /path/to/hardbox-utils.d80 | |
| 28 | 25 | |
| 29 | Select "q" for quick configure at the menu. It will present a default | |
| 30 | drive size and ask if you want to alter it. If the size is not 20, | |
| 31 | change it to 20. | |
| 26 | Load and run the "configure" program from the floppy. When prompted | |
| 27 | for the HardBox device number, enter "9". | |
| 32 | 28 | |
| 33 | After accepting the drive size, it will prompt if you want to perform | |
| 34 | a format check. This requires uploading code into the Corvus, which | |
| 35 | the high level emulation of the Corvus does not support. Enter "n" | |
| 36 | to skip the format check. | |
| 29 | Select "q" for quick configure at the menu. It will present a default | |
| 30 | drive size and ask if you want to alter it. If the size is not 20, | |
| 31 | change it to 20. | |
| 37 | 32 | |
| 38 | Enter "y" to proceed with the format. After it has completed, the | |
| 39 | program will exit back to BASIC. The drive should now be usable. | |
| 33 | After accepting the drive size, it will prompt if you want to perform | |
| 34 | a format check. This requires uploading code into the Corvus, which | |
| 35 | the high level emulation of the Corvus does not support. Enter "n" | |
| 36 | to skip the format check. | |
| 37 | ||
| 38 | Enter "y" to proceed with the format. After it has completed, the | |
| 39 | program will exit back to BASIC. The drive should now be usable. | |
| 40 | 40 | */ |
| 41 | 41 | |
| 42 | 42 | |
| r25360 | r25361 | |
| 136 | 136 | { |
| 137 | 137 | UINT8 data = ioport("SW1")->read(); |
| 138 | 138 | |
| 139 | /* DIP switches on PC1,PC2,PC3 configure the IEEE-488 primary address. | |
| 139 | /* DIP switches on PC1,PC2,PC3 configure the IEEE-488 primary address. | |
| 140 | 140 | We get the address from m_address instead. */ |
| 141 | 141 | data |= ((m_slot->get_address() - 8) << 1) ^ 0xff; |
| 142 | 142 | |
| r25360 | r25361 | |
| 373 | 373 | // reset that must happen after child devices |
| 374 | 374 | // have performed their resets |
| 375 | 375 | //------------------------------------------------- |
| 376 | ||
| 376 | ||
| 377 | 377 | void hardbox_device::device_reset_after_children() |
| 378 | 378 | { |
| 379 | 379 | /* The Z80 starts at address 0x0000 but the HardBox has RAM there and |
| r25360 | r25361 | |
| 381 | 381 | 74S287 PROM that temporarily changes the memory map so that the |
| 382 | 382 | IC3 EPROM at 0xe000 is mapped to 0x0000 for the first instruction |
| 383 | 383 | fetch only. The instruction normally at 0xe000 is an absolute jump |
| 384 | into the ROM. On reset, the Z80 will fetch it from 0x0000 and set | |
| 384 | into the ROM. On reset, the Z80 will fetch it from 0x0000 and set | |
| 385 | 385 | its PC, then the normal map will be restored before the next |
| 386 | instruction fetch. Here we just set the PC to 0xe000 after the Z80 | |
| 386 | instruction fetch. Here we just set the PC to 0xe000 after the Z80 | |
| 387 | 387 | resets, which has the same effect. */ |
| 388 | 388 | |
| 389 | 389 | m_maincpu->set_state_int(Z80_PC, 0xe000); |
| r25360 | r25361 | |
| 403 | 403 | |
| 404 | 404 | m_ifc = state; |
| 405 | 405 | } |
| 406 |
| r25360 | r25361 | |
|---|---|---|
| 68 | 68 | |
| 69 | 69 | required_device<cpu_device> m_maincpu; |
| 70 | 70 | |
| 71 | ||
| 71 | int m_ifc; // Tracks previous state of IEEE-488 IFC line | |
| 72 | 72 | }; |
| 73 | 73 | |
| 74 | 74 | // device type definition |
| r25360 | r25361 | |
|---|---|---|
| 151 | 151 | /* 12x * 75 Hz = 0,00(1) secs per sector */ |
| 152 | 152 | /* TODO: make DMA to be single step */ |
| 153 | 153 | atapi_timer->adjust(attotime::from_usec(1111*atapi_xferlen/2048)); |
| 154 | // | |
| 154 | // atapi_regs[ATAPI_REG_SAMTAG] = GDROM_PAUSE_STATE | 0x80; | |
| 155 | 155 | } |
| 156 | 156 | break; |
| 157 | 157 | |
| r25360 | r25361 | |
| 163 | 163 | case GD_UNLOCK: |
| 164 | 164 | if (data==0 || data==0x001fffff || data==0x42fe) |
| 165 | 165 | { |
| 166 | // | |
| 166 | // atapi_regs[ATAPI_REG_SAMTAG] = GDROM_PAUSE_STATE | 0x80; | |
| 167 | 167 | printf("Unlocking GD-ROM! %x\n", data); |
| 168 | 168 | } |
| 169 | 169 | break; |
| r25360 | r25361 | |
|---|---|---|
| 222 | 222 | ROMX_LOAD( "ide_xt.bin(v1.1.5)", 0x000000, 0x002000, CRC(33a7e0ee) SHA1(b610fd8ea31f5b0568b8b3f2c3ef682be4897a3d), ROM_BIOS(14) ) |
| 223 | 223 | |
| 224 | 224 | ROM_SYSTEM_BIOS( 14, "xub115xtp", "XTIDE_Universal_BIOS_v1.1.3 (XT 80186+)" ) |
| 225 | ROMX_LOAD( "ide_xtp.bin(v1.1.5)", 0x000000, 0x002000, CRC(44ad9ee9) SHA1(9cd275469703cadb85b6654c56e421a151324ac0), ROM_BIOS(15) ) | |
| 225 | ROMX_LOAD( "ide_xtp.bin(v1.1.5)", 0x000000, 0x002000, CRC(44ad9ee9) SHA1(9cd275469703cadb85b6654c56e421a151324ac0), ROM_BIOS(15) ) | |
| 226 | 226 | |
| 227 | 227 | ROM_SYSTEM_BIOS( 15, "xub115at", "XTIDE_Universal_BIOS_v1.1.5 (AT)" ) |
| 228 | 228 | ROMX_LOAD( "ide_at.bin(v1.1.5)", 0x000000, 0x002000, CRC(434286ce) SHA1(3fc07d174924e7c48b4758a7ba76ecd5362bd75b), ROM_BIOS(16) ) |
| 229 | 229 | |
| 230 | 230 | ROM_SYSTEM_BIOS( 16, "xub200b1xt", "XTIDE_Universal_BIOS_v2.0.0_beta1 (XT)" ) |
| 231 | 231 | ROMX_LOAD( "ide_xt.bin(v2.0.0_beta1)", 0x000000, 0x002000, CRC(379579e7) SHA1(da5ee7b9c43a55592fe909451d31a6766d0ab977), ROM_BIOS(17) ) |
| 232 | ||
| 232 | ||
| 233 | 233 | ROM_SYSTEM_BIOS( 17, "xub200b1xtp", "XTIDE_Universal_BIOS_v2.0.0_beta1 (XT 80186+)" ) |
| 234 | 234 | ROMX_LOAD( "ide_xtp.bin(v2.0.0_beta1)", 0x000000, 0x002000, CRC(a887ed63) SHA1(fb33d9e8e8824f61a8d247610d7bd215b7e306b4), ROM_BIOS(18) ) |
| 235 | 235 |
| r25360 | r25361 | |
|---|---|---|
| 57 | 57 | // MACROS / CONSTANTS |
| 58 | 58 | //************************************************************************** |
| 59 | 59 | |
| 60 | #define MACKBD_CPU_TAG | |
| 60 | #define MACKBD_CPU_TAG "mackbd" | |
| 61 | 61 | |
| 62 | 62 | //************************************************************************** |
| 63 | 63 | // DEVICE DEFINITIONS |
| r25360 | r25361 | |
| 94 | 94 | //------------------------------------------------- |
| 95 | 95 | |
| 96 | 96 | static MACHINE_CONFIG_FRAGMENT( mackbd ) |
| 97 | MCFG_CPU_ADD(MACKBD_CPU_TAG, I8021, 3000000) | |
| 97 | MCFG_CPU_ADD(MACKBD_CPU_TAG, I8021, 3000000) // "the approximate clock rate of the MPU is 3 MHz" | |
| 98 | 98 | MCFG_CPU_PROGRAM_MAP(mackbd_map) |
| 99 | 99 | MCFG_CPU_IO_MAP(mackbd_io_map) |
| 100 | 100 | MACHINE_CONFIG_END |
| r25360 | r25361 | |
| 135 | 135 | PORT_START("COL4") |
| 136 | 136 | PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') |
| 137 | 137 | PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') |
| 138 | PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) | |
| 138 | PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_') | |
| 139 | 139 | PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') |
| 140 | 140 | PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') |
| 141 | 141 | PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+') |
| r25360 | r25361 | |
| 143 | 143 | PORT_START("COL5") |
| 144 | 144 | PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') |
| 145 | 145 | PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') |
| 146 | PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) | |
| 146 | PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{') | |
| 147 | 147 | PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') |
| 148 | 148 | PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') |
| 149 | 149 | PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}') |
| 150 | 150 | |
| 151 | 151 | PORT_START("COL6") |
| 152 | PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) | |
| 152 | PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':') | |
| 153 | 153 | PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') |
| 154 | PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) | |
| 154 | PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"') | |
| 155 | 155 | PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') |
| 156 | 156 | PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') |
| 157 | 157 | PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR('\r') PORT_NAME("Return") |
| r25360 | r25361 | |
| 167 | 167 | PORT_START("COL8") |
| 168 | 168 | PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_UNKNOWN) |
| 169 | 169 | PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_UNKNOWN) |
| 170 | PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) | |
| 170 | PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) | |
| 171 | 171 | PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~') |
| 172 | 172 | PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') |
| 173 | 173 | PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR('\t') |
| r25360 | r25361 | |
| 208 | 208 | //------------------------------------------------- |
| 209 | 209 | |
| 210 | 210 | mackbd_device::mackbd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 211 | ||
| 211 | : device_t(mconfig, MACKBD, "Macintosh keyboard", tag, owner, clock, "mackbd", __FILE__), | |
| 212 | 212 | m_maincpu(*this, MACKBD_CPU_TAG), |
| 213 | 213 | m_clkout_handler(*this) |
| 214 | 214 | { |
| r25360 | r25361 | |
| 278 | 278 | else |
| 279 | 279 | { |
| 280 | 280 | m_clkout_handler(CLEAR_LINE); |
| 281 | // | |
| 281 | // machine().scheduler().boost_interleave(attotime::zero, attotime::from_usec(10)); | |
| 282 | 282 | } |
| 283 | 283 | } |
| 284 | 284 | |
| r25360 | r25361 | |
| 311 | 311 | if (m_maincpu->pc() != 0x19e && m_maincpu->pc() != 0x1a3) |
| 312 | 312 | { |
| 313 | 313 | data_to_mac = data_from_mac = (data & 1); |
| 314 | // | |
| 314 | // printf("data to/from mac = %d (PC=%x)\n", data_to_mac, m_maincpu->pc()); | |
| 315 | 315 | } |
| 316 | 316 | } |
| 317 | 317 | |
| r25360 | r25361 | |
| 329 | 329 | { |
| 330 | 330 | data_from_mac = (state == ASSERT_LINE) ? 1 : 0; |
| 331 | 331 | } |
| 332 |
| r25360 | r25361 | |
|---|---|---|
| 11 | 11 | // MACROS / CONSTANTS |
| 12 | 12 | //************************************************************************** |
| 13 | 13 | |
| 14 | #define MACKBD_TAG | |
| 14 | #define MACKBD_TAG "mackbd" | |
| 15 | 15 | |
| 16 | 16 | //************************************************************************** |
| 17 | 17 | // INTERFACE CONFIGURATION MACROS |
| 18 | 18 | //************************************************************************** |
| 19 | 19 | |
| 20 | 20 | #define MCFG_MACKBD_ADD() \ |
| 21 | ||
| 21 | MCFG_DEVICE_ADD(MACKBD_TAG, MACKBD, 0) | |
| 22 | 22 | |
| 23 | 23 | #define MCFG_MACKBD_REPLACE() \ |
| 24 | ||
| 24 | MCFG_DEVICE_REPLACE(MACKBD_TAG, MACKBD, 0) | |
| 25 | 25 | |
| 26 | 26 | #define MCFG_MACKBD_REMOVE() \ |
| 27 | ||
| 27 | MCFG_DEVICE_REMOVE(MACKBD_TAG) | |
| 28 | 28 | |
| 29 | 29 | #define MCFG_MACKBD_CLKOUT_HANDLER(_devcb) \ |
| 30 | 30 | devcb = &mackbd_device::set_clkout_handler(*device, DEVCB2_##_devcb); |
| r25360 | r25361 | |
| 42 | 42 | template<class _Object> static devcb2_base &set_clkout_handler(device_t &device, _Object object) { return downcast<mackbd_device &>(device).m_clkout_handler.set_callback(object); } |
| 43 | 43 | |
| 44 | 44 | // construction/destruction |
| 45 | ||
| 45 | mackbd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); | |
| 46 | 46 | |
| 47 | 47 | DECLARE_READ8_MEMBER(p0_r); |
| 48 | 48 | DECLARE_WRITE8_MEMBER(p0_w); |
| r25360 | r25361 | |
| 56 | 56 | DECLARE_WRITE_LINE_MEMBER(data_w); |
| 57 | 57 | |
| 58 | 58 | protected: |
| 59 | // device-level overrides | |
| 60 | virtual void device_start(); | |
| 61 | virtual void device_reset(); | |
| 62 | virtual machine_config_constructor device_mconfig_additions() const; | |
| 63 | virtual const rom_entry *device_rom_region() const; | |
| 59 | // device-level overrides | |
| 60 | virtual void device_start(); | |
| 61 | virtual void device_reset(); | |
| 62 | virtual machine_config_constructor device_mconfig_additions() const; | |
| 63 | virtual const rom_entry *device_rom_region() const; | |
| 64 | 64 | virtual ioport_constructor device_input_ports() const; |
| 65 | 65 | |
| 66 | ||
| 66 | required_device<cpu_device> m_maincpu; | |
| 67 | 67 | |
| 68 | 68 | private: |
| 69 | 69 | UINT8 p0, p1, p2, data_from_mac, data_to_mac; |
| r25360 | r25361 | |
|---|---|---|
| 1230 | 1230 | void rmnimbus_state::machine_reset() |
| 1231 | 1231 | { |
| 1232 | 1232 | /* CPU */ |
| 1233 | // | |
| 1233 | // nimbus_cpu_reset(); | |
| 1234 | 1234 | iou_reset(); |
| 1235 | 1235 | fdc_reset(); |
| 1236 | 1236 | hdc_reset(); |
| r25360 | r25361 | |
| 1248 | 1248 | void rmnimbus_state::machine_start() |
| 1249 | 1249 | { |
| 1250 | 1250 | /* init cpu */ |
| 1251 | // | |
| 1251 | // nimbus_cpu_init(); | |
| 1252 | 1252 | |
| 1253 | 1253 | m_keyboard.keyscan_timer=machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(rmnimbus_state::keyscan_callback),this)); |
| 1254 | 1254 | m_nimbus_mouse.m_mouse_timer=machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(rmnimbus_state::mouse_callback),this)); |
| r25360 | r25361 | |
|---|---|---|
| 134 | 134 | m_in_dden_func.resolve(m_in_dden_cb, *this); |
| 135 | 135 | m_out_intrq_func.resolve(m_out_intrq_cb, *this); |
| 136 | 136 | m_out_drq_func.resolve(m_out_drq_cb, *this); |
| 137 | ||
| 137 | ||
| 138 | 138 | save_item(NAME(m_data)); |
| 139 | 139 | save_item(NAME(m_drive_num)); |
| 140 | 140 | save_item(NAME(m_track)); |
| r25360 | r25361 | |
|---|---|---|
| 36 | 36 | public: |
| 37 | 37 | micropolis_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 38 | 38 | ~micropolis_device() {} |
| 39 | ||
| 39 | ||
| 40 | 40 | void set_drive(UINT8 drive); // set current drive (0-3) |
| 41 | 41 | |
| 42 | 42 | DECLARE_READ8_MEMBER( status_r ); |
| r25360 | r25361 | |
| 53 | 53 | virtual void device_config_complete(); |
| 54 | 54 | virtual void device_start(); |
| 55 | 55 | virtual void device_reset(); |
| 56 | ||
| 56 | ||
| 57 | 57 | private: |
| 58 | 58 | // internal state |
| 59 | ||
| 59 | ||
| 60 | 60 | devcb_resolved_read_line m_in_dden_func; |
| 61 | 61 | devcb_resolved_write_line m_out_intrq_func; |
| 62 | 62 | devcb_resolved_write_line m_out_drq_func; |
| 63 | ||
| 63 | ||
| 64 | 64 | /* register */ |
| 65 | 65 | UINT8 m_data; |
| 66 | 66 | UINT8 m_drive_num; |
| r25360 | r25361 | |
| 79 | 79 | |
| 80 | 80 | /* this is the drive currently selected */ |
| 81 | 81 | device_t *m_drive; |
| 82 | ||
| 82 | ||
| 83 | 83 | void read_sector(); |
| 84 | 84 | void write_sector(); |
| 85 | 85 | }; |
| r25360 | r25361 | |
|---|---|---|
| 24 | 24 | // ======================> c64_nl10_interface_device |
| 25 | 25 | |
| 26 | 26 | class c64_nl10_interface_device : public device_t, |
| 27 | | |
| 27 | public device_cbm_iec_interface | |
| 28 | 28 | { |
| 29 | 29 | public: |
| 30 | 30 | // construction/destruction |
| r25360 | r25361 | |
|---|---|---|
| 241 | 241 | { |
| 242 | 242 | int nonx = 0, wp = 0; |
| 243 | 243 | offs_t virtual_offset = translate_address(offset, &nonx, &wp); |
| 244 | ||
| 244 | ||
| 245 | 245 | return space().read_byte(virtual_offset); |
| 246 | 246 | } |
| 247 | 247 |
| r25360 | r25361 | |
|---|---|---|
| 3 | 3 | a2applicard.c |
| 4 | 4 | |
| 5 | 5 | Implementation of the PCPI AppliCard Z-80 card |
| 6 | ||
| 6 | ||
| 7 | 7 | Unlike the SoftCard and clones, this has its own 64k of RAM on board |
| 8 | 8 | and the Z80 runs completely independently of the host's 6502. |
| 9 | ||
| 9 | ||
| 10 | 10 | *********************************************************************/ |
| 11 | 11 | |
| 12 | 12 | #include "a2applicard.h" |
| r25360 | r25361 | |
| 25 | 25 | const device_type A2BUS_APPLICARD = &device_creator<a2bus_applicard_device>; |
| 26 | 26 | |
| 27 | 27 | #define Z80_TAG "z80" |
| 28 | #define Z80_ROM_REGION | |
| 28 | #define Z80_ROM_REGION "z80_rom" | |
| 29 | 29 | |
| 30 | 30 | static ADDRESS_MAP_START( z80_mem, AS_PROGRAM, 8, a2bus_applicard_device ) |
| 31 | 31 | AM_RANGE(0x0000, 0xffff) AM_READWRITE(dma_r, dma_w) |
| r25360 | r25361 | |
| 36 | 36 | ADDRESS_MAP_END |
| 37 | 37 | |
| 38 | 38 | MACHINE_CONFIG_FRAGMENT( a2applicard ) |
| 39 | MCFG_CPU_ADD(Z80_TAG, Z80, 6000000) | |
| 39 | MCFG_CPU_ADD(Z80_TAG, Z80, 6000000) // Z80 runs at 6 MHz | |
| 40 | 40 | MCFG_CPU_PROGRAM_MAP(z80_mem) |
| 41 | 41 | MCFG_CPU_IO_MAP(z80_io) |
| 42 | 42 | MACHINE_CONFIG_END |
| r25360 | r25361 | |
| 147 | 147 | m_z80->reset(); |
| 148 | 148 | break; |
| 149 | 149 | |
| 150 | case 6: | |
| 150 | case 6: // IRQ on Z80 via CTC channel 3 (CP/M doesn't use the CTC or IRQs) | |
| 151 | 151 | fatalerror("Applicard: Z80 IRQ not supported yet\n"); |
| 152 | 152 | break; |
| 153 | 153 | |
| r25360 | r25361 | |
| 163 | 163 | { |
| 164 | 164 | switch (offset & 0xf) |
| 165 | 165 | { |
| 166 | case 0: | |
| 166 | case 0: // are these legal to write? | |
| 167 | 167 | case 2: |
| 168 | 168 | case 3: |
| 169 | 169 | break; |
| r25360 | r25361 | |
| 176 | 176 | case 5: |
| 177 | 177 | case 6: |
| 178 | 178 | case 7: |
| 179 | read_c0nx(space, offset); | |
| 179 | read_c0nx(space, offset); // let the read handler take care of these | |
| 180 | 180 | break; |
| 181 | 181 | } |
| 182 | 182 | } |
| r25360 | r25361 | |
| 206 | 206 | return tmp; |
| 207 | 207 | |
| 208 | 208 | case 0x60: |
| 209 | break; | |
| 209 | break; | |
| 210 | 210 | } |
| 211 | return 0xff; | |
| 211 | return 0xff; | |
| 212 | 212 | } |
| 213 | 213 | |
| 214 | 214 | WRITE8_MEMBER( a2bus_applicard_device::z80_io_w ) |
| r25360 | r25361 | |
| 254 | 254 | { |
| 255 | 255 | return m_z80ram[offset]; |
| 256 | 256 | } |
| 257 | return 0xff; | |
| 257 | return 0xff; | |
| 258 | 258 | } |
| 259 | 259 | |
| 260 | 260 |
| r25360 | r25361 | |
|---|---|---|
| 43 | 43 | // ======================> abc1600_mac_device |
| 44 | 44 | |
| 45 | 45 | class abc1600_mac_device : public device_t, |
| 46 | | |
| 46 | public device_memory_interface | |
| 47 | 47 | { |
| 48 | 48 | public: |
| 49 | 49 | abc1600_mac_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| r25360 | r25361 | |
|---|---|---|
| 44 | 44 | |
| 45 | 45 | /* |
| 46 | 46 | |
| 47 | ||
| 47 | TODO: | |
| 48 | 48 | |
| 49 | ||
| 49 | - floppy broken (wd1770 digital PLL FM mode incomplete) | |
| 50 | 50 | |
| 51 | 51 | */ |
| 52 | 52 |
| r25360 | r25361 | |
|---|---|---|
| 29 | 29 | m_pf_motor(0), |
| 30 | 30 | m_cr_motor(0) |
| 31 | 31 | { |
| 32 | ||
| 33 | 32 | } |
| 34 | 33 | |
| 35 | 34 | //------------------------------------------------- |
| r25360 | r25361 | |
|---|---|---|
| 49 | 49 | virtual void device_config_complete(); |
| 50 | 50 | virtual void device_start(); |
| 51 | 51 | virtual void device_reset(); |
| 52 | ||
| 52 | ||
| 53 | 53 | private: |
| 54 | 54 | // internal state |
| 55 | ||
| 55 | ||
| 56 | 56 | /* 24-bit shift register, port 0x00, 0x01 and 0x02 */ |
| 57 | 57 | UINT32 m_shift; |
| 58 | 58 |
| r25360 | r25361 | |
|---|---|---|
| 72 | 72 | |
| 73 | 73 | DRIVER_INIT_MEMBER(stfight_state,cshooter) |
| 74 | 74 | { |
| 75 | ||
| 76 | ||
| 77 | 75 | } |
| 78 | 76 | |
| 79 | 77 | void stfight_state::machine_reset() |
| r25360 | r25361 | |
|---|---|---|
| 338 | 338 | |
| 339 | 339 | decocpu_type1_device::decocpu_type1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 340 | 340 | : device_t(mconfig, DECOCPU1, "Data East Pinball CPU Board Type 1", tag, owner, clock, "decocpu1", __FILE__), |
| 341 | m_cpu(*this,"maincpu"), | |
| 342 | m_pia21(*this, "pia21"), | |
| 343 | m_pia24(*this, "pia24"), | |
| 344 | m_pia28(*this, "pia28"), | |
| 345 | m_pia2c(*this, "pia2c"), | |
| 346 | m_pia30(*this, "pia30"), | |
| 347 | m_pia34(*this, "pia34"), | |
| 348 | m_read_display(*this), | |
| 349 | m_write_display(*this), | |
| 350 | m_read_dmdstatus(*this), | |
| 351 | m_write_soundlatch(*this), | |
| 352 | m_read_switch(*this), | |
| 353 | m_write_switch(*this), | |
| 354 | m_write_lamp(*this), | |
| 355 | m_write_solenoid(*this) | |
| 341 | m_cpu(*this,"maincpu"), | |
| 342 | m_pia21(*this, "pia21"), | |
| 343 | m_pia24(*this, "pia24"), | |
| 344 | m_pia28(*this, "pia28"), | |
| 345 | m_pia2c(*this, "pia2c"), | |
| 346 | m_pia30(*this, "pia30"), | |
| 347 | m_pia34(*this, "pia34"), | |
| 348 | m_read_display(*this), | |
| 349 | m_write_display(*this), | |
| 350 | m_read_dmdstatus(*this), | |
| 351 | m_write_soundlatch(*this), | |
| 352 | m_read_switch(*this), | |
| 353 | m_write_switch(*this), | |
| 354 | m_write_lamp(*this), | |
| 355 | m_write_solenoid(*this) | |
| 356 | 356 | {} |
| 357 | 357 | |
| 358 | 358 | decocpu_type1_device::decocpu_type1_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) |
| r25360 | r25361 | |
|---|---|---|
| 18 | 18 | |
| 19 | 19 | DECLARE_READ8_MEMBER( read ); |
| 20 | 20 | DECLARE_WRITE8_MEMBER( write ); |
| 21 | ||
| 21 | ||
| 22 | 22 | protected: |
| 23 | 23 | // device-level overrides |
| 24 | 24 | virtual void device_start(); |
| 25 | 25 | virtual const rom_entry *device_rom_region() const; |
| 26 | 26 | virtual machine_config_constructor device_mconfig_additions() const; |
| 27 | ||
| 27 | ||
| 28 | 28 | private: |
| 29 | 29 | // internal state |
| 30 | 30 | device_t* m_cpu; |
| r25360 | r25361 | |
|---|---|---|
| 186 | 186 | UINT16 param = mode >> 8; |
| 187 | 187 | UINT16 *PROTROM = (UINT16*)memregion("user1")->base(); |
| 188 | 188 | |
| 189 | // | |
| 189 | // logerror ("mode: %2.2x, src: %4.4x, dst: %4.4x, size: %4.4x, data: %4.4x\n", (mode &0xf), src, dst, size, mode); | |
| 190 | 190 | |
| 191 | 191 | mode &= 0x0f; |
| 192 | 192 | |
| r25360 | r25361 | |
| 214 | 214 | if (mode==0) dat2 = 0x4e75; // hack |
| 215 | 215 | if (mode==1) dat2 = ((dat2 & 0xf000) >> 12) | ((dat2 & 0x0f00) >> 4) | ((dat2 & 0x00f0) << 4) | ((dat2 & 0x000f) << 12); |
| 216 | 216 | if (mode==2) dat2 ^= extraxor; |
| 217 | // | |
| 217 | // if (mode==5) dat2 = dat2; | |
| 218 | 218 | if (mode==6) dat2 += extraxor; |
| 219 | 219 | |
| 220 | 220 | if (mode==2 || mode==6) dat2 = (dat2<<8)|(dat2>>8); |
| r25360 | r25361 | |
| 224 | 224 | } |
| 225 | 225 | break; |
| 226 | 226 | |
| 227 | // default: | |
| 228 | // logerror ("DMA mode unknown!!!\nsrc:%4.4x, dst: %4.4x, size: %4.4x, mode: %4.4x\n", src, dst, size, mode); | |
| 227 | // default: | |
| 228 | // logerror ("DMA mode unknown!!!\nsrc:%4.4x, dst: %4.4x, size: %4.4x, mode: %4.4x\n", src, dst, size, mode); | |
| 229 | 229 | } |
| 230 | 230 | } |
| 231 | 231 | |
| r25360 | r25361 | |
| 304 | 304 | |
| 305 | 305 | case 0x64: // incomplete? |
| 306 | 306 | { |
| 307 | UINT16 p1 = m_sharedprotram[0x3050 / 2]; | |
| 308 | UINT16 p2 = m_sharedprotram[0x3082 / 2]; | |
| 309 | UINT16 p3 = m_sharedprotram[0x3054 / 2]; | |
| 310 | UINT16 p4 = m_sharedprotram[0x3088 / 2]; | |
| 307 | UINT16 p1 = m_sharedprotram[0x3050 / 2]; | |
| 308 | UINT16 p2 = m_sharedprotram[0x3082 / 2]; | |
| 309 | UINT16 p3 = m_sharedprotram[0x3054 / 2]; | |
| 310 | UINT16 p4 = m_sharedprotram[0x3088 / 2]; | |
| 311 | 311 | |
| 312 | if (p2 == 0x02) | |
| 313 | olds_write_reg(p1, olds_read_reg(p1) + 0x10000); | |
| 312 | if (p2 == 0x02) | |
| 313 | olds_write_reg(p1, olds_read_reg(p1) + 0x10000); | |
| 314 | 314 | |
| 315 | switch (p4) | |
| 316 | { | |
| 317 | case 0xd: | |
| 318 | olds_write_reg(p1,olds_read_reg(p3)); | |
| 319 | break; | |
| 320 | case 0x0: | |
| 321 | olds_write_reg(p3,(olds_read_reg(p2))^(olds_read_reg(p1))); | |
| 322 | break; | |
| 323 | case 0xe: | |
| 324 | olds_write_reg(p3,olds_read_reg(p3)+0x10000); | |
| 325 | break; | |
| 326 | case 0x2: | |
| 327 | olds_write_reg(p1,(olds_read_reg(p2))+(olds_read_reg(p3))); | |
| 328 | break; | |
| 329 | case 0x6: | |
| 330 | olds_write_reg(p3,(olds_read_reg(p2))&(olds_read_reg(p1))); | |
| 331 | break; | |
| 332 | case 0x1: | |
| 333 | olds_write_reg(p2,olds_read_reg(p1)+0x10000); | |
| 334 | break; | |
| 335 | case 0x7: | |
| 336 | olds_write_reg(p3,olds_read_reg(p1)); | |
| 337 | break; | |
| 338 | default: | |
| 339 | break; | |
| 340 | } | |
| 315 | switch (p4) | |
| 316 | { | |
| 317 | case 0xd: | |
| 318 | olds_write_reg(p1,olds_read_reg(p3)); | |
| 319 | break; | |
| 320 | case 0x0: | |
| 321 | olds_write_reg(p3,(olds_read_reg(p2))^(olds_read_reg(p1))); | |
| 322 | break; | |
| 323 | case 0xe: | |
| 324 | olds_write_reg(p3,olds_read_reg(p3)+0x10000); | |
| 325 | break; | |
| 326 | case 0x2: | |
| 327 | olds_write_reg(p1,(olds_read_reg(p2))+(olds_read_reg(p3))); | |
| 328 | break; | |
| 329 | case 0x6: | |
| 330 | olds_write_reg(p3,(olds_read_reg(p2))&(olds_read_reg(p1))); | |
| 331 | break; | |
| 332 | case 0x1: | |
| 333 | olds_write_reg(p2,olds_read_reg(p1)+0x10000); | |
| 334 | break; | |
| 335 | case 0x7: | |
| 336 | olds_write_reg(p3,olds_read_reg(p1)); | |
| 337 | break; | |
| 338 | default: | |
| 339 | break; | |
| 340 | } | |
| 341 | 341 | } |
| 342 | 342 | break; |
| 343 | 343 | |
| r25360 | r25361 | |
| 365 | 365 | olds_protection_calculate_hold(m_olds_cmd & 0x0f, data & 0xff); |
| 366 | 366 | break; |
| 367 | 367 | |
| 368 | // default: | |
| 369 | // logerror ("unemulated write mode!\n"); | |
| 368 | // default: | |
| 369 | // logerror ("unemulated write mode!\n"); | |
| 370 | 370 | } |
| 371 | 371 | } |
| 372 | 372 | } |
| r25360 | r25361 | |
| 420 | 420 | { |
| 421 | 421 | MACHINE_RESET_CALL_MEMBER(pgm); |
| 422 | 422 | |
| 423 | // written by protection device | |
| 424 | // there seems to be an auto-dma that writes from $401000-402573? | |
| 423 | // written by protection device | |
| 424 | // there seems to be an auto-dma that writes from $401000-402573? | |
| 425 | 425 | m_sharedprotram[0x1000/2] = 0x4749; // 'IGS.28' |
| 426 | 426 | m_sharedprotram[0x1002/2] = 0x2E53; |
| 427 | 427 | m_sharedprotram[0x1004/2] = 0x3832; |
| r25360 | r25361 | |
|---|---|---|
| 454 | 454 | m_status &= ~GAELCOSER_STATUS_SEND; |
| 455 | 455 | |
| 456 | 456 | shmem_unlock(m_shmem); |
| 457 | } | |
| No newline at end of file | ||
| 457 | } |
| r25360 | r25361 | |
|---|---|---|
| 89 | 89 | |
| 90 | 90 | /* only used in radikalb, set at beginning of receive isr, cleared at end */ |
| 91 | 91 | DECLARE_WRITE8_MEMBER( irq_enable ); |
| 92 | ||
| 92 | ||
| 93 | 93 | protected: |
| 94 | 94 | // device-level overrides |
| 95 | 95 | virtual void device_config_complete(); |
| 96 | 96 | virtual void device_start(); |
| 97 | 97 | virtual void device_stop(); |
| 98 | 98 | virtual void device_reset(); |
| 99 | ||
| 99 | ||
| 100 | 100 | private: |
| 101 | 101 | // internal state |
| 102 | 102 | devcb_resolved_write_line m_irq_func; |
| r25360 | r25361 | |
| 111 | 111 | buf_t *m_out_ptr; |
| 112 | 112 | osd_shared_mem *m_os_shmem; |
| 113 | 113 | shmem_t *m_shmem; |
| 114 | ||
| 114 | ||
| 115 | 115 | TIMER_CALLBACK_MEMBER( set_status_cb ); |
| 116 | 116 | TIMER_CALLBACK_MEMBER( link_cb ); |
| 117 | 117 | void set_status(UINT8 mask, UINT8 set, int wait); |
| r25360 | r25361 | |
|---|---|---|
| 4 | 4 | (a variation on the Deco 146 protection, see deco146.c for notes) |
| 5 | 5 | |
| 6 | 6 | Emulation by David Haywood |
| 7 | ||
| 7 | based on findings by Charles MacDonald | |
| 8 | 8 | |
| 9 | ||
| 9 | previous protection simulations by Bryan McPhail | |
| 10 | 10 | |
| 11 | 11 | |
| 12 | 12 | ***************************************************************************/ |
| r25360 | r25361 | |
| 20 | 20 | |
| 21 | 21 | |
| 22 | 22 | deco146port_xx port104_table[] = { |
| 23 | /* 0x000 */ { 0x04, { NIB3__, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 24 | /* 0x002 */ { 0x2a, { NIB1__, NIB3__, NIB0__, NIB2__ } , 0, 1 }, | |
| 25 | /* 0x004 */ { 0x5e, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 26 | /* 0x006 */ { 0x98, { NIB0__, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 27 | /* 0x008 */ { 0x94, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 28 | /* 0x00a */ { 0xbe, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 1 }, | |
| 29 | /* 0x00c */ { 0xd6, { NIB1__, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 30 | /* 0x00e */ { 0xe4, { NIB0__, NIB3__, NIB1__, NIB2__ } , 0, 1 }, | |
| 31 | /* 0x010 */ { 0x90, { NIB3__, NIB2__, NIB0__, NIB1__ } , 1, 1 }, | |
| 32 | /* 0x012 */ { 0xa8, { NIB3__, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 33 | /* 0x014 */ { 0x24, { NIB2__, NIB1__, NIB3__, BLANK_ } , 0, 1 }, | |
| 34 | /* 0x016 */ { 0xfc, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 35 | /* 0x018 */ { 0x08, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 36 | /* 0x01a */ { INPUT_PORT_C , { NIB1__, NIB0__, NIB2__, NIB3__ } , 0, 0 }, // dc.w $001A ; 0x0010 | |
| 37 | /* 0x01c */ { 0x72, { NIB2__, NIB1__, NIB3__, BLANK_ } , 1, 0 }, | |
| 38 | /* 0x01e */ { 0xc4, { NIB0__, NIB1__, NIB3__, NIB2__ } , 1, 1 }, | |
| 39 | /* 0x020 */ { 0xd0, { NIB2__, NIB1__, NIB3__, NIB0__ } , 0, 1 }, | |
| 40 | /* 0x022 */ { 0x66, { NIB1__, NIB2__, NIB0__, NIB3__ } , 1, 1 }, | |
| 41 | /* 0x024 */ { 0x8c, { NIB3__, NIB2__, NIB0__, NIB1__ } , 0, 0 }, | |
| 42 | /* 0x026 */ { 0xec, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 43 | /* 0x028 */ { 0x58, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 44 | /* 0x02a */ { 0x80, { NIB3R1, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 45 | /* 0x02c */ { 0x82, { NIB0__, NIB3__, NIB2__, NIB1__ } , 0, 1 }, | |
| 46 | /* 0x02e */ { 0x6a, { NIB3__, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 47 | /* 0x030 */ { 0x00, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 48 | /* 0x032 */ { 0x60, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 49 | /* 0x034 */ { INPUT_PORT_B , { NIB0R3, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 50 | /* 0x036 */ { 0xae, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 51 | /* 0x038 */ { 0x12, { NIB3__, NIB0__, NIB2__, NIB1__ } , 0, 0 }, | |
| 52 | /* 0x03a */ { 0x42, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 53 | /* 0x03c */ { 0x1e, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 54 | /* 0x03e */ { 0xf6, { NIB1__, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 55 | /* 0x040 */ { 0xdc, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 0 }, | |
| 56 | /* 0x042 */ { 0x34, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 57 | /* 0x044 */ { 0x2c, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 58 | /* 0x046 */ { 0x7a, { NIB3R1, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 59 | /* 0x048 */ { 0x10, { NIB1__, NIB2__, BLANK_, NIB3__ } , 0, 0 }, | |
| 60 | /* 0x04a */ { 0x9e, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 61 | /* 0x04c */ { 0x3e, { NIB1__, NIB0__, NIB2__, NIB3__ } , 0, 0 }, | |
| 62 | /* 0x04e */ { 0x0e, { NIB2__, NIB1__, NIB3__, NIB0__ } , 0, 0 }, | |
| 63 | /* 0x050 */ { 0xa4, { BLANK_, NIB3__, BLANK_, NIB2__ } , 0, 1 }, | |
| 64 | /* 0x052 */ { 0x0c, { BLANK_, NIB2__, NIB3__, NIB1__ } , 1, 0 }, | |
| 65 | /* 0x054 */ { 0x40, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 66 | /* 0x056 */ { 0x20, { NIB1__, NIB0__, NIB3__, NIB2__ } , 1, 1 }, | |
| 67 | /* 0x058 */ { 0x46, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 68 | /* 0x05a */ { 0x6c, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 69 | /* 0x05c */ { 0x9a, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 70 | /* 0x05e */ { 0x18, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 71 | /* 0x060 */ { 0xe0, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 0 }, | |
| 72 | /* 0x062 */ { 0x30, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 73 | /* 0x064 */ { 0xca, { NIB2__, NIB1__, NIB0__, NIB3__ } , 0, 1 }, | |
| 74 | /* 0x066 */ { 0xac, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 75 | /* 0x068 */ { 0xe8, { NIB2__, NIB1__, BLANK_, NIB3__ } , 0, 0 }, | |
| 76 | /* 0x06a */ { 0x66, { NIB3__, NIB2__, NIB0__, NIB1__ } , 0, 1 }, | |
| 77 | /* 0x06c */ { 0x14, { NIB2__, NIB1__, NIB0__, NIB3__ } , 0, 0 }, | |
| 78 | /* 0x06e */ { 0x96, { NIB0__, NIB3__, NIB2__, NIB1__ } , 1, 0 }, | |
| 79 | /* 0x070 */ { 0x5c, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 80 | /* 0x072 */ { 0x0a, { NIB0__, NIB2__, NIB3__, NIB1__ } , 0, 1 }, | |
| 81 | /* 0x074 */ { INPUT_PORT_B , { NIB0R1, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 82 | /* 0x076 */ { INPUT_PORT_C , { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 1 }, // dc.w $0076 ; 0x1000 dc.w $0076 ; 0x1000 ; nand | |
| 83 | /* 0x078 */ { 0x5a, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 84 | /* 0x07a */ { 0x74, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 85 | /* 0x07c */ { 0xb4, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 86 | /* 0x07e */ { 0x86, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 87 | /* 0x080 */ { 0x84, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 88 | /* 0x082 */ { 0x28, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 89 | /* 0x084 */ { 0x50, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 90 | /* 0x086 */ { 0x66, { NIB3R1, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 91 | /* 0x088 */ { INPUT_PORT_A , { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, // dc.w $0088 | |
| 92 | /* 0x08a */ { 0x1c, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 93 | /* 0x08c */ { 0x48, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 94 | /* 0x08e */ { 0xc2, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 95 | /* 0x090 */ { 0x44, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 96 | /* 0x092 */ { 0x3c, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 97 | /* 0x094 */ { 0xfa, { NIB1__, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 98 | /* 0x096 */ { 0x22, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 99 | /* 0x098 */ { 0xf0, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 100 | /* 0x09a */ { 0x2e, { BLANK_, NIB3__, BLANK_, NIB2__ } , 1, 0 }, | |
| 101 | /* 0x09c */ { 0x06, { NIB0__, NIB3__, NIB1__, NIB2__ } , 1, 0 }, | |
| 102 | /* 0x09e */ { 0x64, { NIB3__, NIB1__, NIB2__, NIB0__ } , 1, 0 }, | |
| 103 | /* 0x0a0 */ { 0xcc, { NIB2__, NIB1__, NIB3__, NIB0__ } , 1, 0 }, | |
| 104 | /* 0x0a2 */ { 0x7a, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 105 | /* 0x0a4 */ { 0xb2, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 106 | /* 0x0a6 */ { 0xbe, { NIB3__, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 107 | /* 0x0a8 */ { 0xde, { NIB0__, NIB3__, NIB1__, NIB2__ } , 0, 1 }, | |
| 108 | /* 0x0aa */ { 0xf8, { NIB2__, NIB1__, NIB0__, NIB3__ } , 1, 0 }, | |
| 109 | /* 0x0ac */ { 0xca, { NIB2__, NIB3__, NIB1__, NIB0__ } , 1, 0 }, | |
| 110 | /* 0x0ae */ { 0x3e, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 111 | /* 0x0b0 */ { 0xb6, { NIB2__, NIB3__, NIB1__, NIB0__ } , 0, 1 }, | |
| 112 | /* 0x0b2 */ { 0xd8, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 113 | /* 0x0b4 */ { INPUT_PORT_C , { NIB3__, NIB0__, NIB1__, NIB2__ } , 0, 0 }, // dc.w $00B4 ; 0x1000 | |
| 114 | /* 0x0b6 */ { 0xc0, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 115 | /* 0x0b8 */ { 0xa2, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 116 | /* 0x0ba */ { 0xe6, { NIB3__, NIB0__, NIB2__, NIB1__ } , 0, 0 }, | |
| 117 | /* 0x0bc */ { 0x1a, { NIB0__, NIB2__, NIB3__, NIB1__ } , 1, 1 }, | |
| 118 | /* 0x0be */ { 0xb0, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 119 | /* 0x0c0 */ { 0x4c, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 120 | /* 0x0c2 */ { 0x56, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 121 | /* 0x0c4 */ { 0xee, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 0 }, | |
| 122 | /* 0x0c6 */ { 0xd4, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 123 | /* 0x0c8 */ { INPUT_PORT_A , { NIB2__, NIB3__, NIB0__, NIB1__ } , 1, 0 }, // dc.w $00C8 ; xor | |
| 124 | /* 0x0ca */ { 0xda, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 125 | /* 0x0cc */ { 0xce, { NIB1__, NIB3__, NIB0__, NIB2__ } , 1, 0 }, | |
| 126 | /* 0x0ce */ { 0xf2, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 127 | /* 0x0d0 */ { 0x8e, { NIB1__, NIB3__, NIB0__, NIB2__ } , 1, 1 }, | |
| 128 | /* 0x0d2 */ { 0x3a, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 129 | /* 0x0d4 */ { 0x6e, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 0, 0 }, | |
| 130 | /* 0x0d6 */ { 0xa6, { NIB1R1, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 131 | /* 0x0d8 */ { 0x78, { BLANK_, NIB3__, BLANK_, NIB2__ } , 0, 0 }, | |
| 132 | /* 0x0da */ { 0xbc, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 133 | /* 0x0dc */ { 0xba, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 134 | /* 0x0de */ { 0x36, { NIB3R1, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 135 | /* 0x0e0 */ { 0x66, { NIB1__, NIB2__, NIB0__, NIB3__ } , 0, 1 }, | |
| 136 | /* 0x0e2 */ { 0x92, { NIB3__, NIB2__, NIB1__, NIB0__ } , 0, 1 }, | |
| 137 | /* 0x0e4 */ { 0x52, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 138 | /* 0x0e6 */ { 0xf4, { NIB0__, NIB2__, NIB3__, NIB1__ } , 1, 0 }, | |
| 139 | /* 0x0e8 */ { INPUT_PORT_B , { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 140 | /* 0x0ea */ { 0xc6, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 141 | /* 0x0ec */ { 0xea, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 1 }, | |
| 142 | /* 0x0ee */ { 0xfe, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 143 | /* 0x0f0 */ { 0xb2, { BLANK_, BLANK_, BLANK_, NIB3__ } , 0, 1 }, | |
| 144 | /* 0x0f2 */ { 0x32, { NIB0__, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 145 | /* 0x0f4 */ { 0x76, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 146 | /* 0x0f6 */ { 0xe2, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 147 | /* 0x0f8 */ { 0x7c, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 148 | /* 0x0fa */ { 0xa0, { NIB0__, NIB1__, NIB3__, NIB2__ } , 0, 1 }, | |
| 149 | /* 0x0fc */ { 0x4a, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 150 | /* 0x0fe */ { 0x70, { NIB1__, NIB2__, BLANK_, NIB3__ } , 1, 1 }, | |
| 151 | /* 0x100 */ { 0x64, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 152 | /* 0x102 */ { 0x04, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 153 | /* 0x104 */ { 0xe2, { NIB0__, NIB1__, NIB3__, NIB2__ } , 1, 0 }, | |
| 154 | /* 0x106 */ { 0xca, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 155 | /* 0x108 */ { 0xa4, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 156 | /* 0x10a */ { 0x12, { NIB0__, NIB2__, NIB3__, NIB1__ } , 0, 0 }, | |
| 157 | /* 0x10c */ { 0xaa, { BLANK_, BLANK_, BLANK_, NIB3__ } , 0, 0 }, | |
| 158 | /* 0x10e */ { 0x7c, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 159 | /* 0x110 */ { 0xf4, { NIB1__, NIB0__, NIB2__, NIB3__ } , 1, 1 }, | |
| 160 | /* 0x112 */ { 0xda, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 161 | /* 0x114 */ { 0x7a, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 162 | /* 0x116 */ { 0x3a, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 163 | /* 0x118 */ { 0x00, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 164 | /* 0x11a */ { 0x66, { NIB3__, NIB2__, NIB0__, NIB1__ } , 1, 0 }, | |
| 165 | /* 0x11c */ { 0xce, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 166 | /* 0x11e */ { 0xb6, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 167 | /* 0x120 */ { 0x1c, { NIB2__, NIB1__, NIB0__, NIB3__ } , 1, 0 }, | |
| 168 | /* 0x122 */ { 0x82, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 169 | /* 0x124 */ { 0x4a, { NIB3R1, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 170 | /* 0x126 */ { 0x58, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 171 | /* 0x128 */ { 0xbe, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 172 | /* 0x12a */ { 0x36, { NIB1__, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 173 | /* 0x12c */ { 0x9a, { NIB3__, NIB1__, NIB2__, NIB0__ } , 0, 0 }, | |
| 174 | /* 0x12e */ { 0x02, { NIB2__, NIB0__, NIB1__, NIB3__ } , 1, 1 }, | |
| 175 | /* 0x130 */ { 0xea, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 176 | /* 0x132 */ { 0xae, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 177 | /* 0x134 */ { 0x52, { BLANK_, BLANK_, BLANK_, NIB3__ } , 1, 0 }, | |
| 178 | /* 0x136 */ { 0xdc, { NIB3__, NIB2__, NIB1__, NIB0__ } , 0, 0 }, | |
| 179 | /* 0x138 */ { 0x9e, { NIB0__, NIB3__, NIB1__, NIB2__ } , 0, 0 }, | |
| 180 | /* 0x13a */ { 0xfc, { NIB3__, NIB1__, NIB2__, NIB0__ } , 1, 1 }, | |
| 181 | /* 0x13c */ { 0x4c, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 182 | /* 0x13e */ { 0x76, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 183 | /* 0x140 */ { 0x8c, { NIB2__, NIB0__, NIB1__, NIB3__ } , 1, 0 }, | |
| 184 | /* 0x142 */ { 0xd4, { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 1 }, | |
| 185 | /* 0x144 */ { 0x3e, { NIB1__, NIB2__, NIB3__, BLANK_ } , 0, 0 }, | |
| 186 | /* 0x146 */ { 0x16, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 187 | /* 0x148 */ { 0xb8, { NIB3__, NIB2__, NIB1__, NIB0__ } , 1, 0 }, | |
| 188 | /* 0x14a */ { 0x50, { NIB2__, NIB1__, NIB3__, NIB0__ } , 1, 0 }, | |
| 189 | /* 0x14c */ { 0x42, { NIB1R1, NIB2__, NIB3__, BLANK_ } , 1, 0 }, // xor readback address, affected by xor, funky | |
| 190 | /* 0x14e */ { 0xd6, { NIB0__, NIB2__, NIB3__, NIB1__ } , 1, 1 }, | |
| 191 | /* 0x150 */ { 0x7e, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 192 | /* 0x152 */ { 0x92, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 193 | /* 0x154 */ { INPUT_PORT_A , { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 194 | /* 0x156 */ { 0xde, { NIB1__, NIB0__, NIB2__, NIB3__ } , 0, 1 }, | |
| 195 | /* 0x158 */ { 0x1a, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 196 | /* 0x15a */ { 0x9c, { NIB2__, NIB0__, NIB1__, NIB3__ } , 0, 1 }, | |
| 197 | /* 0x15c */ { 0x14, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 198 | /* 0x15e */ { 0x98, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 199 | /* 0x160 */ { 0x40, { BLANK_, NIB2__, NIB3__, NIB1__ } , 0, 0 }, | |
| 200 | /* 0x162 */ { 0x6e, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 201 | /* 0x164 */ { 0xc4, { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 0 }, | |
| 202 | /* 0x166 */ { 0xc6, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 203 | /* 0x168 */ { 0x84, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 204 | /* 0x16a */ { 0x8e, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 205 | /* 0x16c */ { 0x96, { NIB3__, NIB0__, NIB2__, NIB1__ } , 1, 1 }, | |
| 206 | /* 0x16e */ { 0x6a, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 207 | /* 0x170 */ { 0xf0, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 208 | /* 0x172 */ { 0x2a, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 209 | /* 0x174 */ { 0x1e, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 210 | /* 0x176 */ { 0x62, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 211 | /* 0x178 */ { 0x88, { NIB2__, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 212 | /* 0x17a */ { 0xe0, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 213 | /* 0x17c */ { INPUT_PORT_A , { NIB3R1, NIB0__, NIB1__, NIB2__ } , 1, 1 }, // dc.w $017C ; xor,nand | |
| 214 | /* 0x17e */ { 0xcc, { NIB0__, NIB1__, NIB3__, NIB2__ } , 0, 0 }, | |
| 215 | /* 0x180 */ { INPUT_PORT_A , { NIB0R3, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 216 | /* 0x182 */ { 0x46, { NIB2__, NIB1__, NIB0__, NIB3__ } , 0, 0 }, | |
| 217 | /* 0x184 */ { 0x90, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 1 }, | |
| 218 | /* 0x186 */ { 0x72, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 219 | /* 0x188 */ { 0xee, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 220 | /* 0x18a */ { 0x2c, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 221 | /* 0x18c */ { 0x22, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 222 | /* 0x18e */ { 0x38, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 223 | /* 0x190 */ { 0x44, { NIB1__, NIB2__, BLANK_, NIB3__ } , 0, 1 }, | |
| 224 | /* 0x192 */ { 0xc0, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 1 }, | |
| 225 | /* 0x194 */ { 0x54, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 226 | /* 0x196 */ { 0x6c, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 227 | /* 0x198 */ { 0xfa, { NIB2__, NIB1__, BLANK_, NIB3__ } , 0, 1 }, | |
| 228 | /* 0x19a */ { 0x34, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 229 | /* 0x19c */ { 0xa8, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 230 | /* 0x19e */ { 0x3c, { NIB2__, NIB1__, NIB3__, NIB0__ } , 1, 1 }, | |
| 231 | /* 0x1a0 */ { 0x7e, { BLANK_, BLANK_, BLANK_, NIB3__ } , 1, 1 }, | |
| 232 | /* 0x1a2 */ { 0x4e, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 233 | /* 0x1a4 */ { 0x9c, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 234 | /* 0x1a6 */ { 0x16, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 235 | /* 0x1a8 */ { 0x38, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 236 | /* 0x1aa */ { 0xc8, { NIB1__, NIB0__, NIB3__, NIB2__ } , 1, 0 }, | |
| 237 | /* 0x1ac */ { 0x68, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 238 | /* 0x1ae */ { 0x54, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 239 | /* 0x1b0 */ { 0xba, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 240 | /* 0x1b2 */ { 0x78, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 241 | /* 0x1b4 */ { 0xcc, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 0 }, | |
| 242 | /* 0x1b6 */ { 0xfe, { NIB1__, NIB0__, NIB2__, NIB3__ } , 1, 0 }, | |
| 243 | /* 0x1b8 */ { 0x86, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 244 | /* 0x1ba */ { 0x18, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 245 | /* 0x1bc */ { 0x0e, { NIB2__, NIB3__, NIB1__, NIB0__ } , 0, 1 }, | |
| 246 | /* 0x1be */ { 0xc2, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 247 | /* 0x1c0 */ { INPUT_PORT_C , { NIB3__, NIB1__, NIB2__, NIB0__ } , 0, 0 }, // dc.w $01C0 ; 0x1000 | |
| 248 | /* 0x1c2 */ { 0x0c, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 249 | /* 0x1c4 */ { INPUT_PORT_A , { NIB0R1, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 250 | /* 0x1c6 */ { 0x70, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 251 | /* 0x1c8 */ { INPUT_PORT_A , { NIB0R2, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 252 | /* 0x1ca */ { 0x5c, { BLANK_, NIB2__, NIB3__, NIB1__ } , 0, 1 }, | |
| 253 | /* 0x1cc */ { 0xac, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 254 | /* 0x1ce */ { 0x48, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 255 | /* 0x1d0 */ { 0x0a, { BLANK_, NIB3__, BLANK_, NIB2__ } , 1, 1 }, | |
| 256 | /* 0x1d2 */ { 0x94, { NIB2__, NIB3__, NIB1__, NIB0__ } , 1, 0 }, | |
| 257 | /* 0x1d4 */ { 0x66, { BLANK_, NIB2__, NIB3__, NIB1__ } , 1, 1 }, | |
| 258 | /* 0x1d6 */ { 0xf8, { NIB1__, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 259 | /* 0x1d8 */ { 0x68, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 260 | /* 0x1da */ { 0x24, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 261 | /* 0x1dc */ { 0x66, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 262 | /* 0x1de */ { 0xa6, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 263 | /* 0x1e0 */ { 0x74, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 264 | /* 0x1e2 */ { 0xd0, { NIB2__, NIB3__, NIB1__, NIB0__ } , 0, 0 }, | |
| 265 | /* 0x1e4 */ { 0x5e, { NIB3__, NIB0__, NIB2__, NIB1__ } , 0, 1 }, | |
| 266 | /* 0x1e6 */ { 0xe6, { NIB1__, NIB2__, NIB0__, NIB3__ } , 0, 0 }, | |
| 267 | /* 0x1e8 */ { 0x66, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 268 | /* 0x1ea */ { INPUT_PORT_B , { NIB1__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 269 | /* 0x1ec */ { INPUT_PORT_B , { NIB1R2, BLANK_, BLANK_, BLANK_ } , 0, 1 }, // dc.w $01EC ; nand | |
| 270 | /* 0x1ee */ { 0xc8, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 271 | /* 0x1f0 */ { 0xa2, { NIB2__, NIB3__, NIB1__, NIB0__ } , 1, 1 }, | |
| 272 | /* 0x1f2 */ { 0x60, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 273 | /* 0x1f4 */ { 0xbc, { NIB3__, NIB1__, NIB2__, NIB0__ } , 0, 1 }, | |
| 274 | /* 0x1f6 */ { 0x06, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 275 | /* 0x1f8 */ { 0x2e, { NIB1__, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 276 | /* 0x1fa */ { 0x26, { NIB3__, NIB0__, NIB2__, NIB1__ } , 1, 0 }, | |
| 277 | /* 0x1fc */ { 0x56, { NIB1__, NIB2__, BLANK_, NIB3__ } , 1, 0 }, | |
| 278 | /* 0x1fe */ { 0xd2, { NIB1R1, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 279 | /* 0x200 */ { 0xa0, { NIB3R1, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 280 | /* 0x202 */ { 0x34, { NIB2__, NIB1__, BLANK_, NIB3__ } , 1, 0 }, | |
| 281 | /* 0x204 */ { 0xf6, { BLANK_, BLANK_, BLANK_, NIB3__ } , 1, 0 }, | |
| 282 | /* 0x206 */ { INPUT_PORT_A , { NIB2__, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 283 | /* 0x208 */ { 0xae, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 284 | /* 0x20a */ { 0xf4, { BLANK_, NIB2__, NIB3__, NIB1__ } , 1, 0 }, | |
| 285 | /* 0x20c */ { INPUT_PORT_C , { BLANK_, BLANK_, BLANK_, NIB3__ } , 1, 1 }, // dc.w $020C ; Bit not present dc.w $020C ; Bit not present ; xor,nand | |
| 286 | /* 0x20e */ { 0x4e, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 287 | /* 0x210 */ { 0x0e, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 288 | /* 0x212 */ { 0x6e, { NIB0__, NIB3__, NIB1__, NIB2__ } , 1, 0 }, | |
| 289 | /* 0x214 */ { 0x4a, { NIB3__, NIB0__, NIB2__, NIB1__ } , 0, 1 }, | |
| 290 | /* 0x216 */ { 0x0a, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 291 | /* 0x218 */ { 0x82, { NIB1__, NIB2__, NIB0__, NIB3__ } , 1, 1 }, | |
| 292 | /* 0x21a */ { 0x66, { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 0 }, | |
| 293 | /* 0x21c */ { 0x6c, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 294 | /* 0x21e */ { 0xb8, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 295 | /* 0x220 */ { 0x12, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 296 | /* 0x222 */ { 0x06, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 297 | /* 0x224 */ { 0x00, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 298 | /* 0x226 */ { 0x72, { NIB3__, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 299 | /* 0x228 */ { 0xe4, { NIB2__, NIB1__, NIB3__, BLANK_ } , 1, 0 }, | |
| 300 | /* 0x22a */ { 0x90, { NIB3__, NIB2__, NIB1__, NIB0__ } , 1, 1 }, | |
| 301 | /* 0x22c */ { 0xc4, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 302 | /* 0x22e */ { 0x08, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 303 | /* 0x230 */ { 0x98, { NIB1__, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 304 | /* 0x232 */ { 0xda, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 305 | /* 0x234 */ { 0x3a, { NIB1__, NIB3__, NIB0__, NIB2__ } , 1, 0 }, | |
| 306 | /* 0x236 */ { 0xcc, { BLANK_, NIB3__, BLANK_, NIB2__ } , 1, 1 }, | |
| 307 | /* 0x238 */ { 0x7c, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 308 | /* 0x23a */ { 0x86, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 309 | /* 0x23c */ { 0x56, { NIB3__, NIB1__, NIB2__, NIB0__ } , 0, 1 }, | |
| 310 | /* 0x23e */ { 0x8a, { NIB0__, NIB3__, NIB2__, NIB1__ } , 1, 1 }, | |
| 311 | /* 0x240 */ { 0xa0, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 312 | /* 0x242 */ { 0x04, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 313 | /* 0x244 */ { 0x32, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 314 | /* 0x246 */ { 0x48, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 315 | /* 0x248 */ { 0x8c, { NIB3__, NIB2__, NIB0__, NIB1__ } , 1, 1 }, | |
| 316 | /* 0x24a */ { 0xa2, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 317 | /* 0x24c */ { 0xfa, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 318 | /* 0x24e */ { 0x46, { NIB3__, NIB0__, NIB2__, NIB1__ } , 1, 0 }, | |
| 319 | /* 0x250 */ { 0x62, { NIB2__, NIB1__, NIB0__, NIB3__ } , 0, 1 }, | |
| 320 | /* 0x252 */ { 0xe0, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 321 | /* 0x254 */ { 0x7e, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 322 | /* 0x256 */ { 0xce, { NIB1__, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 323 | /* 0x258 */ { 0xf8, { NIB1R1, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 324 | /* 0x25a */ { 0x6a, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 325 | /* 0x25c */ { 0x58, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 326 | /* 0x25e */ { 0xc0, { NIB3__, NIB1__, NIB2__, NIB0__ } , 1, 0 }, | |
| 327 | /* 0x260 */ { 0xe2, { NIB1__, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 328 | /* 0x262 */ { 0x30, { NIB1__, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 329 | /* 0x264 */ { 0x88, { NIB2__, NIB1__, NIB3__, BLANK_ } , 1, 1 }, | |
| 330 | /* 0x266 */ { 0xe8, { NIB0__, NIB2__, NIB3__, NIB1__ } , 1, 0 }, | |
| 331 | /* 0x268 */ { 0xac, { BLANK_, NIB3__, BLANK_, NIB2__ } , 0, 1 }, | |
| 332 | /* 0x26a */ { 0xe6, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 333 | /* 0x26c */ { 0xc2, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 334 | /* 0x26e */ { 0xa8, { NIB3__, NIB2__, NIB1__, NIB0__ } , 0, 0 }, | |
| 335 | /* 0x270 */ { INPUT_PORT_C , { NIB1__, NIB2__, NIB3__, NIB0__ } , 0, 0 }, // dc.w $0270 ; 0x0010 | |
| 336 | /* 0x272 */ { 0x3c, { NIB0__, NIB1__, NIB3__, NIB2__ } , 1, 1 }, | |
| 337 | /* 0x274 */ { 0x68, { NIB1__, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 338 | /* 0x276 */ { 0x2e, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 339 | /* 0x278 */ { 0x18, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 340 | /* 0x27a */ { 0x02, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 341 | /* 0x27c */ { 0x70, { NIB1__, NIB2__, NIB0__, NIB3__ } , 0, 0 }, | |
| 342 | /* 0x27e */ { 0x94, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 343 | /* 0x280 */ { 0x5e, { NIB2__, NIB1__, NIB3__, BLANK_ } , 0, 0 }, | |
| 344 | /* 0x282 */ { 0x26, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 345 | /* 0x284 */ { 0x14, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 346 | /* 0x286 */ { 0x7a, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 0, 0 }, | |
| 347 | /* 0x288 */ { 0xd2, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 348 | /* 0x28a */ { 0xd4, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 349 | /* 0x28c */ { 0xa6, { NIB1__, NIB3__, NIB0__, NIB2__ } , 0, 0 }, | |
| 350 | /* 0x28e */ { 0x36, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 351 | /* 0x290 */ { 0xee, { NIB2__, NIB1__, BLANK_, NIB3__ } , 0, 0 }, | |
| 352 | /* 0x292 */ { INPUT_PORT_C , { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, // dc.w $0292 ; 0x0001 | |
| 353 | /* 0x294 */ { 0x66, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 354 | /* 0x296 */ { 0x5a, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 355 | /* 0x298 */ { 0x64, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 356 | /* 0x29a */ { 0x60, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 357 | /* 0x29c */ { 0xec, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 358 | /* 0x29e */ { 0x80, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 359 | /* 0x2a0 */ { 0xd0, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 360 | /* 0x2a2 */ { 0x44, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 361 | /* 0x2a4 */ { INPUT_PORT_C , { NIB0__, NIB1__, NIB3__, NIB2__ } , 0, 0 }, // dc.w $02A4 ; 0x0001 | |
| 362 | /* 0x2a6 */ { 0xbc, { NIB2__, NIB0__, NIB1__, NIB3__ } , 1, 1 }, | |
| 363 | /* 0x2a8 */ { 0x22, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 364 | /* 0x2aa */ { 0xb2, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 365 | /* 0x2ac */ { 0x1e, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 366 | /* 0x2ae */ { 0x9c, { NIB2__, NIB0__, NIB1__, NIB3__ } , 0, 0 }, | |
| 367 | /* 0x2b0 */ { 0x96, { NIB3__, NIB1__, NIB2__, NIB0__ } , 0, 0 }, | |
| 368 | /* 0x2b2 */ { 0x8e, { NIB2__, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 369 | /* 0x2b4 */ { 0xb6, { NIB0__, NIB3__, NIB1__, NIB2__ } , 1, 1 }, | |
| 370 | /* 0x2b6 */ { 0xfe, { NIB2__, NIB1__, NIB0__, NIB3__ } , 1, 1 }, | |
| 371 | /* 0x2b8 */ { 0x66, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 372 | /* 0x2ba */ { 0xf0, { BLANK_, NIB2__, NIB3__, NIB1__ } , 0, 0 }, | |
| 373 | /* 0x2bc */ { 0x20, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 374 | /* 0x2be */ { 0x40, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 375 | /* 0x2c0 */ { 0x4c, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 376 | /* 0x2c2 */ { 0x76, { BLANK_, NIB3__, BLANK_, NIB2__ } , 1, 1 }, | |
| 377 | /* 0x2c4 */ { 0xca, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 378 | /* 0x2c6 */ { 0x50, { NIB3__, NIB2__, NIB0__, NIB1__ } , 1, 0 }, | |
| 379 | /* 0x2c8 */ { 0x1c, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 380 | /* 0x2ca */ { 0x1a, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 381 | /* 0x2cc */ { INPUT_PORT_B , { NIB0__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 382 | /* 0x2ce */ { 0x92, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 383 | /* 0x2d0 */ { 0x66, { BLANK_, NIB3__, BLANK_, NIB2__ } , 1, 0 }, | |
| 384 | /* 0x2d2 */ { 0x28, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 385 | /* 0x2d4 */ { 0x74, { NIB0__, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 386 | /* 0x2d6 */ { 0x16, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 387 | /* 0x2d8 */ { 0x9e, { NIB1__, NIB0__, NIB2__, NIB3__ } , 0, 0 }, | |
| 388 | /* 0x2da */ { 0xde, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 389 | /* 0x2dc */ { 0xba, { NIB0__, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 390 | /* 0x2de */ { 0x78, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 391 | /* 0x2e0 */ { 0x9a, { NIB1__, NIB2__, BLANK_, NIB3__ } , 0, 0 }, | |
| 392 | /* 0x2e2 */ { 0xc6, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 393 | /* 0x2e4 */ { 0x42, { NIB1__, NIB2__, NIB0__, NIB3__ } , 1, 0 }, | |
| 394 | /* 0x2e6 */ { 0xea, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 395 | /* 0x2e8 */ { 0x0c, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 396 | /* 0x2ea */ { 0xd8, { NIB1__, NIB0__, NIB3__, NIB2__ } , 1, 0 }, | |
| 397 | /* 0x2ec */ { 0x5c, { NIB1__, NIB0__, NIB2__, NIB3__ } , 1, 0 }, | |
| 398 | /* 0x2ee */ { 0xaa, { NIB3R1, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 399 | /* 0x2f0 */ { 0xb4, { NIB0__, NIB3__, NIB2__, NIB1__ } , 1, 0 }, | |
| 400 | /* 0x2f2 */ { 0xf2, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 401 | /* 0x2f4 */ { INPUT_PORT_C , { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 1 }, // dc.w $02F4 ; 0x0001 dc.w $02F4 ; 0x0001 ; nand | |
| 402 | /* 0x2f6 */ { 0x84, { NIB1__, NIB2__, NIB0__, NIB3__ } , 0, 1 }, | |
| 403 | /* 0x2f8 */ { 0xa4, { BLANK_, NIB2__, NIB3__, NIB1__ } , 0, 1 }, | |
| 404 | /* 0x2fa */ { INPUT_PORT_C , { NIB0R3, NIB1__, NIB2__, NIB3__ } , 0, 0 }, // dc.w $02FA ; 0x0008 | |
| 405 | /* 0x2fc */ { 0xfc, { BLANK_, NIB3__, BLANK_, NIB2__ } , 0, 0 }, | |
| 406 | /* 0x2fe */ { 0x10, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 407 | /* 0x300 */ { 0xa4, { BLANK_, BLANK_, BLANK_, NIB3__ } , 0, 0 }, | |
| 408 | /* 0x302 */ { 0x24, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 409 | /* 0x304 */ { 0xe2, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 410 | /* 0x306 */ { 0x32, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 411 | /* 0x308 */ { 0x2a, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 412 | /* 0x30a */ { 0x66, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 413 | /* 0x30c */ { 0x86, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 414 | /* 0x30e */ { 0xaa, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 415 | /* 0x310 */ { 0x66, { NIB2__, NIB1__, NIB3__, NIB0__ } , 0, 0 }, | |
| 416 | /* 0x312 */ { 0x4e, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 417 | /* 0x314 */ { 0x84, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 0, 0 }, | |
| 418 | /* 0x316 */ { 0x96, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 419 | /* 0x318 */ { 0x26, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 420 | /* 0x31a */ { 0x64, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 421 | /* 0x31c */ { 0xac, { NIB2__, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 422 | /* 0x31e */ { 0x78, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 423 | /* 0x320 */ { 0xfe, { NIB0__, NIB3__, NIB2__, NIB1__ } , 0, 0 }, | |
| 424 | /* 0x322 */ { 0x2e, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 425 | /* 0x324 */ { 0x06, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 426 | /* 0x326 */ { 0x92, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 427 | /* 0x328 */ { 0x34, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 428 | /* 0x32a */ { 0xc0, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 429 | /* 0x32c */ { 0x8a, { NIB2__, NIB1__, NIB3__, BLANK_ } , 0, 1 }, | |
| 430 | /* 0x32e */ { 0x46, { NIB1__, NIB2__, BLANK_, NIB3__ } , 0, 1 }, | |
| 431 | /* 0x330 */ { 0xd8, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 432 | /* 0x332 */ { 0xc4, { NIB1__, NIB0__, NIB3__, NIB2__ } , 1, 1 }, | |
| 433 | /* 0x334 */ { 0x30, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 434 | /* 0x336 */ { 0x1a, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 435 | /* 0x338 */ { 0xd0, { BLANK_, BLANK_, BLANK_, NIB3__ } , 1, 1 }, | |
| 436 | /* 0x33a */ { 0x60, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 437 | /* 0x33c */ { 0xf6, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 438 | /* 0x33e */ { 0x00, { NIB3__, NIB2__, NIB1__, NIB0__ } , 0, 1 }, | |
| 439 | /* 0x340 */ { 0x90, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 440 | /* 0x342 */ { 0xfc, { NIB2__, NIB1__, NIB0__, NIB3__ } , 0, 0 }, | |
| 441 | /* 0x344 */ { 0x08, { NIB3__, NIB2__, NIB0__, NIB1__ } , 0, 0 }, | |
| 442 | /* 0x346 */ { 0xa8, { NIB2__, NIB3__, NIB1__, NIB0__ } , 1, 1 }, | |
| 443 | /* 0x348 */ { 0x44, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 444 | /* 0x34a */ { 0x04, { NIB1__, NIB0__, NIB2__, NIB3__ } , 0, 1 }, | |
| 445 | /* 0x34c */ { 0x3c, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 446 | /* 0x34e */ { 0xde, { NIB0__, NIB2__, NIB3__, NIB1__ } , 0, 0 }, | |
| 447 | /* 0x350 */ { 0x72, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 0 }, | |
| 448 | /* 0x352 */ { 0x62, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 449 | /* 0x354 */ { 0x3a, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 450 | /* 0x356 */ { 0xba, { NIB2__, NIB1__, NIB3__, NIB0__ } , 0, 1 }, | |
| 451 | /* 0x358 */ { 0x68, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 1 }, | |
| 452 | /* 0x35a */ { 0x76, { NIB3R1, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 453 | /* 0x35c */ { 0x9e, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 1 }, | |
| 454 | /* 0x35e */ { 0xc6, { NIB2__, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 455 | /* 0x360 */ { 0xe4, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 456 | /* 0x362 */ { 0x02, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 457 | /* 0x364 */ { 0x6c, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 0 }, | |
| 458 | /* 0x366 */ { 0xec, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 459 | /* 0x368 */ { INPUT_PORT_C , { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, // dc.w $0368 ; 0x1000 | |
| 460 | /* 0x36a */ { INPUT_PORT_A , { NIB3__, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 461 | /* 0x36c */ { INPUT_PORT_B , { NIB0__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 462 | /* 0x36e */ { 0x0c, { NIB2__, NIB0__, NIB1__, NIB3__ } , 0, 1 }, | |
| 463 | /* 0x370 */ { 0x80, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 464 | /* 0x372 */ { 0x82, { NIB3__, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 465 | /* 0x374 */ { 0xb8, { NIB3__, NIB2__, NIB0__, NIB1__ } , 0, 1 }, | |
| 466 | /* 0x376 */ { 0x50, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 467 | /* 0x378 */ { 0x20, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 468 | /* 0x37a */ { 0xf4, { NIB0__, NIB2__, NIB3__, NIB1__ } , 0, 1 }, | |
| 469 | /* 0x37c */ { 0x8c, { NIB2__, NIB1__, NIB3__, NIB0__ } , 1, 1 }, | |
| 470 | /* 0x37e */ { 0xe6, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 471 | /* 0x380 */ { 0xda, { NIB2__, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 472 | /* 0x382 */ { 0xf2, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 473 | /* 0x384 */ { 0xdc, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 474 | /* 0x386 */ { 0x9c, { NIB1__, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 475 | /* 0x388 */ { INPUT_PORT_A , { NIB1__, NIB2__, NIB3__, BLANK_ } , 0, 0 }, | |
| 476 | /* 0x38a */ { INPUT_PORT_B , { NIB1__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 477 | /* 0x38c */ { 0x28, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 478 | /* 0x38e */ { 0xb6, { NIB2__, NIB1__, BLANK_, NIB3__ } , 1, 1 }, | |
| 479 | /* 0x390 */ { 0x2c, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 480 | /* 0x392 */ { 0xce, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 481 | /* 0x394 */ { 0x0e, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 482 | /* 0x396 */ { 0x5c, { NIB2__, NIB3__, NIB1__, NIB0__ } , 0, 0 }, | |
| 483 | /* 0x398 */ { 0x52, { BLANK_, NIB3__, BLANK_, NIB2__ } , 1, 1 }, | |
| 484 | /* 0x39a */ { 0x7e, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 485 | /* 0x39c */ { 0x6a, { NIB0__, NIB1__, NIB3__, NIB2__ } , 0, 0 }, | |
| 486 | /* 0x39e */ { 0xa0, { NIB0__, NIB1__, NIB3__, NIB2__ } , 1, 0 }, | |
| 487 | /* 0x3a0 */ { 0x52, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 488 | /* 0x3a2 */ { 0x94, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 489 | /* 0x3a4 */ { 0x2c, { NIB0__, NIB3__, NIB1__, NIB2__ } , 0, 0 }, | |
| 490 | /* 0x3a6 */ { 0xc8, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 491 | /* 0x3a8 */ { 0x18, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 492 | /* 0x3aa */ { 0x56, { NIB3__, NIB2__, NIB1__, NIB0__ } , 1, 0 }, | |
| 493 | /* 0x3ac */ { 0x54, { NIB0__, NIB1__, NIB3__, NIB2__ } , 0, 1 }, | |
| 494 | /* 0x3ae */ { 0x58, { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 1 }, | |
| 495 | /* 0x3b0 */ { INPUT_PORT_B , { NIB1__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 496 | /* 0x3b2 */ { 0x14, { NIB1R1, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 497 | /* 0x3b4 */ { 0x38, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 498 | /* 0x3b6 */ { 0xf8, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 499 | /* 0x3b8 */ { 0xb4, { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 0 }, | |
| 500 | /* 0x3ba */ { 0xd6, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 0 }, | |
| 501 | /* 0x3bc */ { 0x5c, { NIB2__, NIB0__, NIB1__, NIB3__ } , 1, 0 }, | |
| 502 | /* 0x3be */ { 0x1c, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 0 }, | |
| 503 | /* 0x3c0 */ { 0x22, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 504 | /* 0x3c2 */ { 0x66, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 505 | /* 0x3c4 */ { 0x8e, { NIB3__, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 506 | /* 0x3c6 */ { 0xf0, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 507 | /* 0x3c8 */ { 0xae, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 1 }, | |
| 508 | /* 0x3ca */ { 0x1e, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 509 | /* 0x3cc */ { 0xee, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 510 | /* 0x3ce */ { 0xea, { NIB0__, NIB3__, NIB2__, NIB1__ } , 0, 1 }, | |
| 511 | /* 0x3d0 */ { 0xe8, { NIB3__, NIB0__, NIB2__, NIB1__ } , 1, 1 }, | |
| 512 | /* 0x3d2 */ { 0x88, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 513 | /* 0x3d4 */ { INPUT_PORT_C , { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 0 }, // dc.w $03D4 ; 0x0010 | |
| 514 | /* 0x3d6 */ { 0x66, { NIB1__, NIB2__, BLANK_, NIB3__ } , 1, 1 }, | |
| 515 | /* 0x3d8 */ { INPUT_PORT_B , { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 516 | /* 0x3da */ { 0xfa, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 517 | /* 0x3dc */ { 0x4c, { NIB2__, NIB1__, BLANK_, NIB3__ } , 0, 1 }, | |
| 518 | /* 0x3de */ { 0x36, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 519 | /* 0x3e0 */ { 0xe0, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 520 | /* 0x3e2 */ { 0xd4, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 521 | /* 0x3e4 */ { 0xc8, { NIB1__, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 522 | /* 0x3e6 */ { 0xc2, { NIB1__, NIB2__, BLANK_, NIB3__ } , 1, 0 }, | |
| 523 | /* 0x3e8 */ { 0x0a, { BLANK_, NIB2__, NIB3__, NIB1__ } , 1, 1 }, | |
| 524 | /* 0x3ea */ { 0x9a, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 525 | /* 0x3ec */ { 0x7c, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 526 | /* 0x3ee */ { 0x4a, { NIB1R1, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 527 | /* 0x3f0 */ { 0xd2, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 528 | /* 0x3f2 */ { 0x48, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 1 }, | |
| 529 | /* 0x3f4 */ { 0x6e, { NIB1__, NIB2__, NIB3__, BLANK_ } , 0, 0 }, | |
| 530 | /* 0x3f6 */ { 0xa6, { NIB1__, NIB3__, NIB0__, NIB2__ } , 0, 1 }, | |
| 531 | /* 0x3f8 */ { 0x42, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 532 | /* 0x3fa */ { 0x5e, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 533 | /* 0x3fc */ { 0xbc, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 534 | /* 0x3fe */ { 0x10, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 535 | /* 0x400 */ { 0x02, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 536 | /* 0x402 */ { 0x72, { NIB1__, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 537 | /* 0x404 */ { 0x74, { NIB1__, NIB0__, NIB2__, NIB3__ } , 0, 0 }, | |
| 538 | /* 0x406 */ { 0x96, { NIB0__, NIB3__, NIB2__, NIB1__ } , 1, 1 }, | |
| 539 | /* 0x408 */ { 0x54, { BLANK_, NIB2__, NIB3__, NIB1__ } , 1, 0 }, | |
| 540 | /* 0x40a */ { 0xda, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 541 | /* 0x40c */ { 0xd6, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 542 | /* 0x40e */ { 0x8a, { NIB1__, NIB2__, BLANK_, NIB3__ } , 1, 1 }, | |
| 543 | /* 0x410 */ { 0xde, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 544 | /* 0x412 */ { 0xa4, { NIB1__, NIB2__, NIB0__, NIB3__ } , 1, 0 }, | |
| 545 | /* 0x414 */ { 0xa2, { BLANK_, NIB3__, BLANK_, NIB2__ } , 1, 0 }, | |
| 546 | /* 0x416 */ { 0xe4, { BLANK_, BLANK_, BLANK_, NIB3__ } , 0, 1 }, | |
| 547 | /* 0x418 */ { 0x04, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 548 | /* 0x41a */ { 0x84, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 549 | /* 0x41c */ { 0x2a, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 550 | /* 0x41e */ { 0x4c, { NIB0__, NIB2__, NIB3__, NIB1__ } , 0, 1 }, | |
| 551 | /* 0x420 */ { 0x2e, { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 0 }, | |
| 552 | /* 0x422 */ { 0x86, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 553 | /* 0x424 */ { 0x60, { NIB0__, NIB1__, NIB3__, NIB2__ } , 0, 0 }, | |
| 554 | /* 0x426 */ { 0xba, { NIB1__, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 555 | /* 0x428 */ { 0x8c, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 556 | /* 0x42a */ { 0xee, { NIB3__, NIB1__, NIB2__, NIB0__ } , 1, 0 }, | |
| 557 | /* 0x42c */ { 0xac, { BLANK_, NIB2__, NIB3__, NIB1__ } , 0, 0 }, | |
| 558 | /* 0x42e */ { 0x32, { NIB1__, NIB3__, NIB0__, NIB2__ } , 0, 1 }, | |
| 559 | /* 0x430 */ { 0xd2, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 560 | /* 0x432 */ { 0x0e, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 561 | /* 0x434 */ { 0x06, { NIB3__, NIB1__, NIB2__, NIB0__ } , 1, 1 }, | |
| 562 | /* 0x436 */ { 0x66, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 563 | /* 0x438 */ { 0xec, { NIB0__, NIB2__, NIB3__, NIB1__ } , 0, 0 }, | |
| 564 | /* 0x43a */ { 0xfe, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 565 | /* 0x43c */ { INPUT_PORT_B , { BLANK_, BLANK_, BLANK_, BLANK_ } , 0, 0 }, // this address always seems to return 0, is it a port with all bits masked out? I'm going to assume it's a 'B' port (4-bit) with mask applied to those 4 bits so they always return 0 due to a design flaw, that would make 21 of each port type. | |
| 566 | /* 0x43e */ { 0x7a, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 567 | /* 0x440 */ { 0xfc, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 568 | /* 0x442 */ { 0x10, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 569 | /* 0x444 */ { 0x66, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 570 | /* 0x446 */ { 0x16, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 571 | /* 0x448 */ { 0x90, { NIB1__, NIB0__, NIB2__, NIB3__ } , 1, 0 }, | |
| 572 | /* 0x44a */ { 0xb4, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 573 | /* 0x44c */ { INPUT_PORT_B, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 0, 1 }, //dc.w $044C ; nand | |
| 574 | /* 0x44e */ { 0x44, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 0 }, | |
| 575 | /* 0x450 */ { INPUT_PORT_C , { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 0 }, // dc.w $0450 ; 0x0100 dc.w $0450 ; 0x0100 ; xor | |
| 576 | /* 0x452 */ { 0x30, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 577 | /* 0x454 */ { 0x82, { NIB3__, NIB0__, NIB2__, NIB1__ } , 1, 0 }, | |
| 578 | /* 0x456 */ { 0x26, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 579 | /* 0x458 */ { 0x52, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 580 | /* 0x45a */ { 0xc6, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 581 | /* 0x45c */ { 0xd8, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 582 | /* 0x45e */ { 0x18, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 583 | /* 0x460 */ { 0xc8, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 584 | /* 0x462 */ { 0x64, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 585 | /* 0x464 */ { 0xbe, { NIB2__, NIB1__, NIB3__, NIB0__ } , 1, 1 }, | |
| 586 | /* 0x466 */ { 0x42, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 1 }, | |
| 587 | /* 0x468 */ { 0xc0, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 588 | /* 0x46a */ { 0x38, { NIB1R1, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 589 | /* 0x46c */ { 0xd0, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 590 | /* 0x46e */ { 0x9c, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 591 | /* 0x470 */ { 0xa8, { NIB0__, NIB1__, NIB3__, NIB2__ } , 0, 1 }, | |
| 592 | /* 0x472 */ { 0x4a, { NIB1__, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 593 | /* 0x474 */ { 0x1c, { NIB2__, NIB0__, NIB1__, NIB3__ } , 0, 0 }, | |
| 594 | /* 0x476 */ { 0xf0, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 1 }, | |
| 595 | /* 0x478 */ { 0xb6, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 596 | /* 0x47a */ { 0xc2, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 597 | /* 0x47c */ { 0x7e, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 598 | /* 0x47e */ { INPUT_PORT_B , { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 599 | /* 0x480 */ { 0x5a, { NIB2__, NIB1__, NIB3__, NIB0__ } , 0, 1 }, | |
| 600 | /* 0x482 */ { 0x5c, { NIB1__, NIB2__, BLANK_, NIB3__ } , 0, 0 }, | |
| 601 | /* 0x484 */ { 0x5a, { NIB3R1, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 602 | /* 0x486 */ { 0x06, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 603 | /* 0x488 */ { 0x2c, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 604 | /* 0x48a */ { 0x76, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 0 }, | |
| 605 | /* 0x48c */ { 0xbc, { NIB1R1, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 606 | /* 0x48e */ { 0x46, { NIB3__, NIB2__, NIB1__, NIB0__ } , 0, 0 }, | |
| 607 | /* 0x490 */ { 0x66, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 608 | /* 0x492 */ { 0xea, { NIB1__, NIB0__, NIB2__, NIB3__ } , 0, 1 }, | |
| 609 | /* 0x494 */ { 0x9a, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 610 | /* 0x496 */ { 0xb8, { NIB1__, NIB3__, NIB0__, NIB2__ } , 1, 1 }, | |
| 611 | /* 0x498 */ { 0x36, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 612 | /* 0x49a */ { 0x56, { NIB0__, NIB1__, NIB3__, NIB2__ } , 1, 0 }, | |
| 613 | /* 0x49c */ { 0x6c, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 614 | /* 0x49e */ { 0x12, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 615 | /* 0x4a0 */ { 0xa4, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 616 | /* 0x4a2 */ { 0xa8, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 617 | /* 0x4a4 */ { 0xce, { NIB3__, NIB1__, NIB2__, NIB0__ } , 1, 1 }, | |
| 618 | /* 0x4a6 */ { 0x8c, { NIB1__, NIB0__, NIB2__, NIB3__ } , 0, 0 }, | |
| 619 | /* 0x4a8 */ { 0xb0, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 620 | /* 0x4aa */ { 0x48, { NIB1__, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 621 | /* 0x4ac */ { INPUT_PORT_A , { NIB3__, NIB1__, NIB2__, NIB0__ } , 0, 0 }, | |
| 622 | /* 0x4ae */ { 0x92, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 623 | /* 0x4b0 */ { 0x10, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 624 | /* 0x4b2 */ { 0x74, { NIB3__, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 625 | /* 0x4b4 */ { 0x08, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 0, 0 }, | |
| 626 | /* 0x4b6 */ { 0x94, { NIB3__, NIB2__, NIB1__, NIB0__ } , 1, 0 }, | |
| 627 | /* 0x4b8 */ { 0x46, { NIB2__, NIB3__, NIB1__, NIB0__ } , 1, 0 }, | |
| 628 | /* 0x4ba */ { 0x24, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 629 | /* 0x4bc */ { 0x42, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 0, 0 }, | |
| 630 | /* 0x4be */ { 0xa6, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 631 | /* 0x4c0 */ { 0x08, { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 1 }, | |
| 632 | /* 0x4c2 */ { 0x80, { NIB1__, NIB2__, NIB0__, NIB3__ } , 0, 1 }, | |
| 633 | /* 0x4c4 */ { 0x3c, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 634 | /* 0x4c6 */ { 0x94, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 635 | /* 0x4c8 */ { INPUT_PORT_A , { NIB1__, NIB0__, NIB2__, NIB3__ } , 0, 0 }, | |
| 636 | /* 0x4ca */ { 0x20, { NIB2__, NIB1__, NIB3__, BLANK_ } , 1, 1 }, | |
| 637 | /* 0x4cc */ { 0xf6, { NIB2__, NIB1__, NIB3__, NIB0__ } , 0, 0 }, | |
| 638 | /* 0x4ce */ { 0x66, { NIB2__, NIB3__, NIB1__, NIB0__ } , 1, 1 }, | |
| 639 | /* 0x4d0 */ { 0xe2, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 640 | /* 0x4d2 */ { INPUT_PORT_B , { NIB0R2, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 641 | /* 0x4d4 */ { 0xd4, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 642 | /* 0x4d6 */ { 0xa0, { NIB3__, NIB1__, NIB2__, NIB0__ } , 0, 0 }, | |
| 643 | /* 0x4d8 */ { 0x48, { NIB0__, NIB3__, NIB1__, NIB2__ } , 0, 0 }, | |
| 644 | /* 0x4da */ { 0xca, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 645 | /* 0x4dc */ { 0x62, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 646 | /* 0x4de */ { 0x70, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 647 | /* 0x4e0 */ { 0xfa, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 0 }, | |
| 648 | /* 0x4e2 */ { 0x9e, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 649 | /* 0x4e4 */ { 0x40, { NIB1__, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 650 | /* 0x4e6 */ { 0x68, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 651 | /* 0x4e8 */ { 0x88, { NIB1__, NIB2__, BLANK_, NIB3__ } , 0, 1 }, | |
| 652 | /* 0x4ea */ { 0x3e, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 653 | /* 0x4ec */ { 0x7c, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 654 | /* 0x4ee */ { 0xcc, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 655 | /* 0x4f0 */ { 0x34, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 656 | /* 0x4f2 */ { INPUT_PORT_A , { NIB0__, NIB1__, NIB3__, NIB2__ } , 0, 0 }, // dc.w $04F2 | |
| 657 | /* 0x4f4 */ { 0x28, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 658 | /* 0x4f6 */ { 0xe6, { NIB3__, NIB0__, NIB2__, NIB1__ } , 0, 0 }, | |
| 659 | /* 0x4f8 */ { 0x6a, { NIB1__, NIB0__, NIB2__, NIB3__ } , 1, 1 }, | |
| 660 | /* 0x4fa */ { 0xaa, { NIB1__, NIB3__, NIB0__, NIB2__ } , 0, 1 }, | |
| 661 | /* 0x4fc */ { 0x50, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 662 | /* 0x4fe */ { 0xa6, { NIB2__, NIB0__, NIB1__, NIB3__ } , 0, 1 }, | |
| 663 | /* 0x500 */ { 0xf0, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 664 | /* 0x502 */ { 0x88, { NIB3__, NIB0__, NIB2__, NIB1__ } , 1, 1 }, | |
| 665 | /* 0x504 */ { 0x5c, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 1 }, | |
| 666 | /* 0x506 */ { INPUT_PORT_C , { NIB0R2, NIB1__, NIB2__, NIB3__ } , 0, 0 }, // dc.w $0506 ; 0x0004 | |
| 667 | /* 0x508 */ { INPUT_PORT_A , { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 668 | /* 0x50a */ { 0xc0, { BLANK_, NIB3__, BLANK_, NIB2__ } , 0, 1 }, | |
| 669 | /* 0x50c */ { 0x26, { NIB1__, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 670 | /* 0x50e */ { 0x72, { NIB3__, NIB2__, NIB1__, NIB0__ } , 1, 1 }, | |
| 671 | /* 0x510 */ { 0x8a, { NIB2__, NIB0__, NIB1__, NIB3__ } , 1, 1 }, | |
| 672 | /* 0x512 */ { 0x06, { NIB3__, NIB2__, NIB0__, NIB1__ } , 0, 0 }, | |
| 673 | /* 0x514 */ { 0x32, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 674 | /* 0x516 */ { 0xb6, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 675 | /* 0x518 */ { 0x02, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 676 | /* 0x51a */ { 0xb2, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 677 | /* 0x51c */ { 0x0a, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 678 | /* 0x51e */ { 0xd6, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 0, 0 }, | |
| 679 | /* 0x520 */ { 0xaa, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 680 | /* 0x522 */ { 0xca, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 681 | /* 0x524 */ { 0x54, { NIB1__, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 682 | /* 0x526 */ { 0x08, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 683 | /* 0x528 */ { INPUT_PORT_B , { NIB2__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 684 | /* 0x52a */ { 0x8e, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 685 | /* 0x52c */ { 0xe0, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 686 | /* 0x52e */ { 0xba, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 687 | /* 0x530 */ { 0x18, { NIB2__, NIB3__, NIB1__, NIB0__ } , 0, 1 }, | |
| 688 | /* 0x532 */ { 0xb0, { NIB3__, NIB2__, NIB0__, NIB1__ } , 0, 1 }, | |
| 689 | /* 0x534 */ { 0x1a, { NIB1__, NIB0__, NIB2__, NIB3__ } , 1, 1 }, | |
| 690 | /* 0x536 */ { 0x7a, { NIB1__, NIB0__, NIB2__, NIB3__ } , 0, 1 }, | |
| 691 | /* 0x538 */ { 0x3c, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 692 | /* 0x53a */ { 0x0c, { NIB3__, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 693 | /* 0x53c */ { 0xfa, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 694 | /* 0x53e */ { 0x9e, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 695 | /* 0x540 */ { 0x3e, { NIB0__, NIB3__, NIB2__, NIB1__ } , 1, 0 }, | |
| 696 | /* 0x542 */ { 0x9c, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 697 | /* 0x544 */ { 0x5a, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 698 | /* 0x546 */ { 0x62, { NIB2__, NIB1__, BLANK_, NIB3__ } , 0, 1 }, | |
| 699 | /* 0x548 */ { 0xf6, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 700 | /* 0x54a */ { 0xde, { NIB1__, NIB0__, NIB3__, NIB2__ } , 1, 1 }, | |
| 701 | /* 0x54c */ { 0x38, { NIB2__, NIB0__, NIB1__, NIB3__ } , 1, 0 }, | |
| 702 | /* 0x54e */ { 0xe6, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 703 | /* 0x550 */ { 0xa2, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 704 | /* 0x552 */ { 0x4c, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 705 | /* 0x554 */ { 0xae, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 706 | /* 0x556 */ { 0xac, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 707 | /* 0x558 */ { 0x68, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 708 | /* 0x55a */ { 0xf2, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 709 | /* 0x55c */ { 0x66, { NIB1R1, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 710 | /* 0x55e */ { 0xea, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 711 | /* 0x560 */ { 0x82, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 712 | /* 0x562 */ { INPUT_PORT_B , { NIB0__, BLANK_, BLANK_, BLANK_ } , 1, 0 }, // dc.w $0562 ; xor | |
| 713 | /* 0x564 */ { 0x80, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 0, 0 }, | |
| 714 | /* 0x566 */ { 0xf8, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 715 | /* 0x568 */ { 0x6c, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 716 | /* 0x56a */ { 0x7c, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 717 | /* 0x56c */ { INPUT_PORT_A , { NIB1__, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 718 | /* 0x56e */ { 0x98, { NIB3__, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 719 | /* 0x570 */ { 0x24, { NIB2__, NIB1__, BLANK_, NIB3__ } , 1, 0 }, | |
| 720 | /* 0x572 */ { 0xc2, { NIB1__, NIB3__, NIB0__, NIB2__ } , 1, 1 }, | |
| 721 | /* 0x574 */ { 0xdc, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 722 | /* 0x576 */ { 0x52, { NIB2__, NIB1__, BLANK_, NIB3__ } , 0, 0 }, | |
| 723 | /* 0x578 */ { 0x2a, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 724 | /* 0x57a */ { 0xb8, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 0 }, | |
| 725 | /* 0x57c */ { 0x28, { NIB1__, NIB2__, BLANK_, NIB3__ } , 0, 0 }, | |
| 726 | /* 0x57e */ { 0xd8, { NIB1__, NIB2__, NIB0__, NIB3__ } , 0, 0 }, | |
| 727 | /* 0x580 */ { 0x0c, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 728 | /* 0x582 */ { 0x8e, { NIB3__, NIB2__, NIB1__, NIB0__ } , 0, 0 }, | |
| 729 | /* 0x584 */ { 0x22, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 730 | /* 0x586 */ { 0x00, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 731 | /* 0x588 */ { 0x04, { NIB0__, NIB3__, NIB1__, NIB2__ } , 1, 1 }, | |
| 732 | /* 0x58a */ { 0x22, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 0 }, | |
| 733 | /* 0x58c */ { 0xe8, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 734 | /* 0x58e */ { 0x74, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 735 | /* 0x590 */ { 0x0e, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 736 | /* 0x592 */ { 0x66, { BLANK_, NIB2__, NIB3__, NIB1__ } , 1, 1 }, | |
| 737 | /* 0x594 */ { 0x40, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 738 | /* 0x596 */ { 0xc8, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 739 | /* 0x598 */ { 0x70, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 740 | /* 0x59a */ { 0x16, { NIB0__, NIB1__, NIB3__, NIB2__ } , 1, 0 }, | |
| 741 | /* 0x59c */ { 0x12, { NIB0__, NIB3__, NIB2__, NIB1__ } , 0, 0 }, | |
| 742 | /* 0x59e */ { 0x36, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 743 | /* 0x5a0 */ { 0x5e, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 744 | /* 0x5a2 */ { 0x24, { NIB0__, NIB3__, NIB1__, NIB2__ } , 0, 1 }, | |
| 745 | /* 0x5a4 */ { 0xce, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 746 | /* 0x5a6 */ { 0xb0, { NIB3__, NIB2__, NIB0__, NIB1__ } , 1, 0 }, | |
| 747 | /* 0x5a8 */ { 0xf2, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 748 | /* 0x5aa */ { 0x98, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 749 | /* 0x5ac */ { 0x6e, { NIB0__, NIB2__, NIB3__, NIB1__ } , 1, 1 }, | |
| 750 | /* 0x5ae */ { 0xdc, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 751 | /* 0x5b0 */ { 0xc4, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 752 | /* 0x5b2 */ { INPUT_PORT_B , { NIB0__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 753 | /* 0x5b4 */ { 0xe0, { NIB1__, NIB3__, NIB0__, NIB2__ } , 0, 0 }, | |
| 754 | /* 0x5b6 */ { 0x92, { NIB1__, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 755 | /* 0x5b8 */ { 0x4e, { NIB0__, NIB2__, NIB3__, NIB1__ } , 1, 0 }, | |
| 756 | /* 0x5ba */ { 0xf4, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 757 | /* 0x5bc */ { 0x78, { NIB2__, NIB1__, NIB0__, NIB3__ } , 1, 0 }, | |
| 758 | /* 0x5be */ { 0x58, { NIB3__, NIB0__, NIB2__, NIB1__ } , 0, 1 }, | |
| 759 | /* 0x5c0 */ { 0xfe, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 760 | /* 0x5c2 */ { 0x4a, { NIB1__, NIB3__, NIB0__, NIB2__ } , 1, 0 }, | |
| 761 | /* 0x5c4 */ { 0x3a, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 762 | /* 0x5c6 */ { 0x2c, { NIB0__, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 763 | /* 0x5c8 */ { 0x96, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 1 }, | |
| 764 | /* 0x5ca */ { 0x20, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 765 | /* 0x5cc */ { 0xc6, { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 0 }, | |
| 766 | /* 0x5ce */ { 0xa8, { NIB3__, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 767 | /* 0x5d0 */ { 0xe2, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 768 | /* 0x5d2 */ { 0x66, { NIB2__, NIB3__, NIB1__, NIB0__ } , 1, 0 }, | |
| 769 | /* 0x5d4 */ { 0xf4, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 770 | /* 0x5d6 */ { 0xec, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 771 | /* 0x5d8 */ { 0xbe, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 772 | /* 0x5da */ { 0xe8, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 773 | /* 0x5dc */ { 0x6e, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 774 | /* 0x5de */ { 0x1e, { BLANK_, BLANK_, BLANK_, NIB3__ } , 1, 0 }, | |
| 775 | /* 0x5e0 */ { 0x14, { NIB2__, NIB1__, NIB0__, NIB3__ } , 0, 0 }, | |
| 776 | /* 0x5e2 */ { 0x84, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 777 | /* 0x5e4 */ { 0xa0, { NIB0__, NIB3__, NIB1__, NIB2__ } , 1, 0 }, | |
| 778 | /* 0x5e6 */ { 0x34, { NIB3__, NIB2__, NIB0__, NIB1__ } , 1, 1 }, | |
| 779 | /* 0x5e8 */ { 0xe4, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 780 | /* 0x5ea */ { 0x58, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 781 | /* 0x5ec */ { INPUT_PORT_B , { NIB2__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 782 | /* 0x5ee */ { 0x42, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 783 | /* 0x5f0 */ { 0x8c, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 784 | /* 0x5f2 */ { 0x10, { NIB0__, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 785 | /* 0x5f4 */ { INPUT_PORT_C , { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 0 }, // dc.w $05F4 ; 0x0100 | |
| 786 | /* 0x5f6 */ { 0x04, { NIB1__, NIB0__, NIB3__, NIB2__ } , 1, 0 }, | |
| 787 | /* 0x5f8 */ { 0x4e, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 788 | /* 0x5fa */ { 0xd2, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 789 | /* 0x5fc */ { 0x7e, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 790 | /* 0x5fe */ { 0xcc, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 791 | /* 0x600 */ { 0xc6, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 1 }, | |
| 792 | /* 0x602 */ { 0x20, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 793 | /* 0x604 */ { 0x36, { NIB2__, NIB1__, NIB3__, NIB0__ } , 1, 1 }, | |
| 794 | /* 0x606 */ { 0xfc, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 795 | /* 0x608 */ { 0x1c, { NIB0__, NIB3__, NIB2__, NIB1__ } , 1, 0 }, | |
| 796 | /* 0x60a */ { 0xca, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 797 | /* 0x60c */ { INPUT_PORT_A , { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 0 }, | |
| 798 | /* 0x60e */ { 0xa0, { BLANK_, NIB2__, NIB3__, NIB1__ } , 0, 0 }, | |
| 799 | /* 0x610 */ { 0xa4, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 800 | /* 0x612 */ { 0x64, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 801 | /* 0x614 */ { 0x96, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 802 | /* 0x616 */ { 0x7e, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 803 | /* 0x618 */ { 0x0c, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 804 | /* 0x61a */ { 0x38, { NIB3__, NIB0__, NIB2__, NIB1__ } , 1, 1 }, | |
| 805 | /* 0x61c */ { 0x66, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 806 | /* 0x61e */ { 0x22, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 807 | /* 0x620 */ { 0x1a, { NIB1__, NIB0__, NIB2__, NIB3__ } , 1, 0 }, | |
| 808 | /* 0x622 */ { 0xae, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 809 | /* 0x624 */ { 0x9a, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 810 | /* 0x626 */ { 0x4e, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 811 | /* 0x628 */ { 0x5a, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 812 | /* 0x62a */ { 0x8a, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 813 | /* 0x62c */ { INPUT_PORT_A , { NIB1__, NIB2__, BLANK_, NIB3__ } , 0, 1 }, // dc.w $062C ; nand | |
| 814 | /* 0x62e */ { 0x58, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 815 | /* 0x630 */ { INPUT_PORT_B , { NIB0__, BLANK_, BLANK_, BLANK_ } , 0, 1 }, // dc.w $0630 ; nand | |
| 816 | /* 0x632 */ { 0x6a, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 817 | /* 0x634 */ { 0xc2, { NIB2__, NIB0__, NIB1__, NIB3__ } , 1, 0 }, | |
| 818 | /* 0x636 */ { 0xc4, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 819 | /* 0x638 */ { 0x94, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 820 | /* 0x63a */ { 0x3c, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 821 | /* 0x63c */ { 0x74, { NIB0__, NIB3__, NIB1__, NIB2__ } , 1, 1 }, | |
| 822 | /* 0x63e */ { 0x0a, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 823 | /* 0x640 */ { 0x30, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 824 | /* 0x642 */ { 0x68, { NIB1__, NIB0__, NIB2__, NIB3__ } , 1, 0 }, | |
| 825 | /* 0x644 */ { 0x40, { NIB2__, NIB3__, NIB1__, NIB0__ } , 0, 1 }, | |
| 826 | /* 0x646 */ { 0xda, { NIB2__, NIB3__, NIB1__, NIB0__ } , 0, 0 }, | |
| 827 | /* 0x648 */ { 0x60, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 828 | /* 0x64a */ { 0xde, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 829 | /* 0x64c */ { 0x04, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 830 | /* 0x64e */ { 0x86, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 831 | /* 0x650 */ { 0x78, { BLANK_, NIB2__, NIB3__, NIB1__ } , 1, 0 }, | |
| 832 | /* 0x652 */ { 0x4a, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 833 | /* 0x654 */ { 0x4c, { NIB1__, NIB2__, NIB0__, NIB3__ } , 1, 0 }, | |
| 834 | /* 0x656 */ { 0x2e, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 835 | /* 0x658 */ { 0xbc, { NIB2__, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 836 | /* 0x65a */ { 0xc0, { NIB3__, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 837 | /* 0x65c */ { 0x44, { NIB1__, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 838 | /* 0x65e */ { 0x9c, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 839 | /* 0x660 */ { 0x48, { NIB2__, NIB1__, NIB3__, BLANK_ } , 0, 1 }, | |
| 840 | /* 0x662 */ { 0x8c, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 841 | /* 0x664 */ { 0x9e, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 842 | /* 0x666 */ { 0xfe, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 843 | /* 0x668 */ { 0x5e, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 844 | /* 0x66a */ { 0x16, { NIB2__, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 845 | /* 0x66c */ { 0xdc, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 846 | /* 0x66e */ { 0xec, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 847 | /* 0x670 */ { 0xf4, { NIB1R1, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 848 | /* 0x672 */ { 0x6c, { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 1 }, | |
| 849 | /* 0x674 */ { INPUT_PORT_C , { NIB1__, NIB2__, NIB3__, BLANK_ } , 0, 0 }, // dc.w $0674 ; 0x0010 | |
| 850 | /* 0x676 */ { 0xd2, { NIB0__, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 851 | /* 0x678 */ { 0x72, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 852 | /* 0x67a */ { 0x28, { NIB0__, NIB3__, NIB1__, NIB2__ } , 0, 0 }, | |
| 853 | /* 0x67c */ { 0x1e, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 854 | /* 0x67e */ { INPUT_PORT_B , { NIB3R1, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 855 | /* 0x680 */ { 0x7a, { NIB0__, NIB3__, NIB1__, NIB2__ } , 1, 1 }, | |
| 856 | /* 0x682 */ { 0xba, { NIB3__, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 857 | /* 0x684 */ { 0xd8, { NIB0__, NIB3__, NIB2__, NIB1__ } , 0, 0 }, | |
| 858 | /* 0x686 */ { 0x46, { NIB1__, NIB3__, NIB0__, NIB2__ } , 0, 0 }, | |
| 859 | /* 0x688 */ { 0xe4, { NIB1__, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 860 | /* 0x68a */ { 0xd0, { NIB2__, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 861 | /* 0x68c */ { 0x50, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 862 | /* 0x68e */ { 0x92, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 863 | /* 0x690 */ { 0x10, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 864 | /* 0x692 */ { 0x88, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 865 | /* 0x694 */ { 0xf2, { NIB2__, NIB0__, NIB1__, NIB3__ } , 0, 0 }, | |
| 866 | /* 0x696 */ { 0xce, { NIB2__, NIB1__, BLANK_, NIB3__ } , 1, 0 }, | |
| 867 | /* 0x698 */ { 0x12, { NIB2__, NIB1__, BLANK_, NIB3__ } , 1, 1 }, | |
| 868 | /* 0x69a */ { 0x3e, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 869 | /* 0x69c */ { 0x06, { NIB2__, NIB1__, NIB0__, NIB3__ } , 1, 1 }, | |
| 870 | /* 0x69e */ { 0xe8, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 0, 0 }, | |
| 871 | /* 0x6a0 */ { 0xb2, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 872 | /* 0x6a2 */ { 0x28, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 873 | /* 0x6a4 */ { 0xa0, { NIB2__, NIB1__, NIB3__, BLANK_ } , 0, 0 }, | |
| 874 | /* 0x6a6 */ { 0xe4, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 875 | /* 0x6a8 */ { 0x32, { NIB3__, NIB2__, NIB1__, NIB0__ } , 1, 1 }, | |
| 876 | /* 0x6aa */ { 0x20, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 877 | /* 0x6ac */ { 0xf6, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 878 | /* 0x6ae */ { 0xf2, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 879 | /* 0x6b0 */ { 0x10, { NIB2__, NIB1__, NIB3__, BLANK_ } , 1, 1 }, | |
| 880 | /* 0x6b2 */ { 0xb4, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 881 | /* 0x6b4 */ { 0xa0, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 882 | /* 0x6b6 */ { 0x30, { NIB0__, NIB3__, NIB2__, NIB1__ } , 1, 1 }, | |
| 883 | /* 0x6b8 */ { 0xea, { NIB1__, NIB2__, NIB0__, NIB3__ } , 1, 0 }, | |
| 884 | /* 0x6ba */ { 0xf6, { NIB2__, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 885 | /* 0x6bc */ { 0x42, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 886 | /* 0x6be */ { INPUT_PORT_A , { NIB1__, NIB2__, BLANK_, NIB3__ } , 1, 0 }, // dc.w $06BE ; xor | |
| 887 | /* 0x6c0 */ { 0x08, { NIB3__, NIB1__, NIB2__, NIB0__ } , 0, 1 }, | |
| 888 | /* 0x6c2 */ { 0x54, { NIB2__, NIB1__, BLANK_, NIB3__ } , 1, 1 }, | |
| 889 | /* 0x6c4 */ { 0x66, { NIB2__, NIB1__, BLANK_, NIB3__ } , 0, 1 }, | |
| 890 | /* 0x6c6 */ { 0xcc, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 891 | /* 0x6c8 */ { 0x52, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 892 | /* 0x6ca */ { 0xd4, { NIB2__, NIB1__, NIB3__, NIB0__ } , 0, 0 }, | |
| 893 | /* 0x6cc */ { INPUT_PORT_C , { NIB0R1, NIB1__, NIB2__, NIB3__ } , 0, 0 }, // dc.w $06CC ; 0x0002 | |
| 894 | /* 0x6ce */ { 0x0e, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 895 | /* 0x6d0 */ { 0xb2, { BLANK_, BLANK_, BLANK_, NIB3__ } , 0, 0 }, | |
| 896 | /* 0x6d2 */ { 0xa2, { NIB0__, NIB3__, NIB1__, NIB2__ } , 0, 0 }, | |
| 897 | /* 0x6d4 */ { 0xb4, { NIB2__, NIB1__, NIB3__, BLANK_ } , 0, 0 }, | |
| 898 | /* 0x6d6 */ { INPUT_PORT_A , { NIB0__, NIB1__, NIB2__, NIB3__ } , 1, 0 }, // dc.w $06D6 ; xor | |
| 899 | /* 0x6d8 */ { 0xac, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 900 | /* 0x6da */ { 0x24, { BLANK_, NIB2__, NIB3__, NIB1__ } , 0, 1 }, | |
| 901 | /* 0x6dc */ { 0xbe, { NIB1__, NIB0__, NIB3__, NIB2__ } , 1, 0 }, | |
| 902 | /* 0x6de */ { 0xa8, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 903 | /* 0x6e0 */ { 0x2c, { NIB2__, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 904 | /* 0x6e2 */ { 0x90, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 905 | /* 0x6e4 */ { 0x98, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 906 | /* 0x6e6 */ { 0x70, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 907 | /* 0x6e8 */ { 0xb6, { BLANK_, NIB3__, BLANK_, NIB2__ } , 0, 1 }, | |
| 908 | /* 0x6ea */ { 0xb8, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 909 | /* 0x6ec */ { 0x66, { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 0 }, | |
| 910 | /* 0x6ee */ { 0x2a, { NIB0__, NIB2__, NIB3__, NIB1__ } , 1, 0 }, | |
| 911 | /* 0x6f0 */ { 0x62, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 912 | /* 0x6f2 */ { 0xc8, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 913 | /* 0x6f4 */ { 0x14, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 914 | /* 0x6f6 */ { 0xa6, { NIB2__, NIB3__, NIB1__, NIB0__ } , 1, 1 }, | |
| 915 | /* 0x6f8 */ { 0xe6, { NIB2__, NIB1__, BLANK_, NIB3__ } , 0, 0 }, | |
| 916 | /* 0x6fa */ { 0xee, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 917 | /* 0x6fc */ { 0x82, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 918 | /* 0x6fe */ { 0x26, { NIB1__, NIB2__, NIB0__, NIB3__ } , 1, 1 }, | |
| 919 | /* 0x700 */ { 0x66, { BLANK_, NIB3__, BLANK_, NIB2__ } , 1, 0 }, | |
| 920 | /* 0x702 */ { 0x2c, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 921 | /* 0x704 */ { 0x7c, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 922 | /* 0x706 */ { 0x18, { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 0 }, | |
| 923 | /* 0x708 */ { 0xda, { BLANK_, NIB3__, BLANK_, NIB2__ } , 0, 0 }, | |
| 924 | /* 0x70a */ { 0xde, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 925 | /* 0x70c */ { 0x6e, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 926 | /* 0x70e */ { 0x26, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 927 | /* 0x710 */ { 0xca, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 0 }, | |
| 928 | /* 0x712 */ { 0xf0, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 929 | /* 0x714 */ { 0x82, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 1 }, | |
| 930 | /* 0x716 */ { 0xc0, { NIB0__, NIB3__, NIB1__, NIB2__ } , 1, 0 }, | |
| 931 | /* 0x718 */ { 0x8e, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 932 | /* 0x71a */ { 0x20, { NIB3__, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 933 | /* 0x71c */ { 0x4e, { NIB3__, NIB2__, NIB0__, NIB1__ } , 0, 1 }, | |
| 934 | /* 0x71e */ { 0xe0, { BLANK_, BLANK_, BLANK_, NIB3__ } , 1, 1 }, | |
| 935 | /* 0x720 */ { 0x66, { NIB0__, NIB1__, NIB3__, NIB2__ } , 0, 1 }, | |
| 936 | /* 0x722 */ { 0xdc, { NIB1__, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 937 | /* 0x724 */ { 0xb2, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 938 | /* 0x726 */ { INPUT_PORT_C , { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, // dc.w $0726 ; 0x0001 | |
| 939 | /* 0x728 */ { 0xd4, { NIB2__, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 940 | /* 0x72a */ { 0x86, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 941 | /* 0x72c */ { 0x78, { NIB0__, NIB2__, NIB3__, NIB1__ } , 0, 0 }, | |
| 942 | /* 0x72e */ { 0xe4, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 943 | /* 0x730 */ { 0x3e, { NIB3R1, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 944 | /* 0x732 */ { 0x72, { NIB1__, NIB3__, NIB0__, NIB2__ } , 0, 0 }, | |
| 945 | /* 0x734 */ { 0x64, { NIB2__, NIB1__, NIB3__, NIB0__ } , 1, 0 }, | |
| 946 | /* 0x736 */ { 0x68, { BLANK_, BLANK_, BLANK_, NIB3__ } , 0, 1 }, | |
| 947 | /* 0x738 */ { 0x54, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 948 | /* 0x73a */ { 0x00, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 949 | /* 0x73c */ { INPUT_PORT_A , { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, // dc.w $073C | |
| 950 | /* 0x73e */ { 0xae, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 951 | /* 0x740 */ { 0x6a, { NIB1__, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 952 | /* 0x742 */ { 0x2e, { NIB0__, NIB3__, NIB2__, NIB1__ } , 0, 0 }, | |
| 953 | /* 0x744 */ { 0xf6, { NIB2__, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 954 | /* 0x746 */ { INPUT_PORT_C , { NIB0__, NIB1__, NIB2__, NIB3__ } , 1, 0 }, // dc.w $0746 ; 0x0001 dc.w $0746 ; 0x0001 ; xor | |
| 955 | /* 0x748 */ { 0x44, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 956 | /* 0x74a */ { 0x14, { NIB2__, NIB1__, NIB0__, NIB3__ } , 0, 1 }, | |
| 957 | /* 0x74c */ { 0xd2, { BLANK_, BLANK_, BLANK_, NIB3__ } , 1, 0 }, | |
| 958 | /* 0x74e */ { INPUT_PORT_C , { NIB2__, NIB3__, NIB0__, NIB1__ } , 0, 0 }, // dc.w $074E ; 0x0100 | |
| 959 | /* 0x750 */ { 0xaa, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 960 | /* 0x752 */ { 0xbe, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 961 | /* 0x754 */ { 0x76, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 962 | /* 0x756 */ { 0x60, { NIB3R1, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 963 | /* 0x758 */ { 0x70, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 964 | /* 0x75a */ { 0x4c, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 965 | /* 0x75c */ { 0xbc, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 966 | /* 0x75e */ { 0x7e, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 967 | /* 0x760 */ { 0x32, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 968 | /* 0x762 */ { 0x88, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 969 | /* 0x764 */ { 0xe2, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 970 | /* 0x766 */ { 0x66, { NIB2__, NIB1__, NIB0__, NIB3__ } , 0, 0 }, | |
| 971 | /* 0x768 */ { 0x16, { NIB0__, NIB3__, NIB2__, NIB1__ } , 0, 1 }, | |
| 972 | /* 0x76a */ { 0xfa, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 973 | /* 0x76c */ { 0x52, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 974 | /* 0x76e */ { 0xd6, { NIB0__, NIB3__, NIB1__, NIB2__ } , 0, 1 }, | |
| 975 | /* 0x770 */ { INPUT_PORT_B , { NIB1__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 976 | /* 0x772 */ { 0xc4, { NIB1__, NIB3__, NIB0__, NIB2__ } , 1, 0 }, | |
| 977 | /* 0x774 */ { 0x38, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 978 | /* 0x776 */ { 0x6c, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 979 | /* 0x778 */ { 0xfc, { NIB2__, NIB1__, NIB3__, BLANK_ } , 1, 1 }, | |
| 980 | /* 0x77a */ { 0x84, { NIB0__, NIB2__, NIB3__, NIB1__ } , 0, 1 }, | |
| 981 | /* 0x77c */ { 0xb6, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 982 | /* 0x77e */ { 0x62, { NIB3__, NIB1__, NIB2__, NIB0__ } , 0, 0 }, | |
| 983 | /* 0x780 */ { 0xb8, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 984 | /* 0x782 */ { 0xa2, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 985 | /* 0x784 */ { 0x8a, { NIB2__, NIB0__, NIB1__, NIB3__ } , 0, 0 }, | |
| 986 | /* 0x786 */ { 0x3a, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 987 | /* 0x788 */ { 0xf4, { NIB2__, NIB1__, NIB0__, NIB3__ } , 1, 1 }, | |
| 988 | /* 0x78a */ { 0x40, { NIB1__, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 989 | /* 0x78c */ { 0x7a, { NIB1__, NIB2__, NIB3__, BLANK_ } , 0, 0 }, | |
| 990 | /* 0x78e */ { 0x1c, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 991 | /* 0x790 */ { 0x04, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 992 | /* 0x792 */ { 0x1a, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 993 | /* 0x794 */ { 0x0e, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 994 | /* 0x796 */ { 0x30, { NIB3__, NIB0__, NIB2__, NIB1__ } , 1, 0 }, | |
| 995 | /* 0x798 */ { 0x50, { NIB3__, NIB2__, NIB0__, NIB1__ } , 1, 1 }, | |
| 996 | /* 0x79a */ { 0xc8, { NIB3R1, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 997 | /* 0x79c */ { 0xc6, { NIB1__, NIB2__, NIB0__, NIB3__ } , 0, 1 }, | |
| 998 | /* 0x79e */ { 0x12, { NIB1__, NIB0__, NIB3__, NIB2__ } , 1, 1 }, | |
| 999 | /* 0x7a0 */ { 0x6e, { NIB0__, NIB1__, NIB3__, NIB2__ } , 0, 0 }, | |
| 1000 | /* 0x7a2 */ { 0x56, { NIB2__, NIB1__, BLANK_, NIB3__ } , 1, 0 }, | |
| 1001 | /* 0x7a4 */ { 0xe2, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 1002 | /* 0x7a6 */ { 0x00, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 1003 | /* 0x7a8 */ { 0xfa, { NIB3__, NIB1__, NIB2__, NIB0__ } , 1, 0 }, | |
| 1004 | /* 0x7aa */ { 0x76, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 1005 | /* 0x7ac */ { 0x8e, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 1006 | /* 0x7ae */ { 0xaa, { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 0 }, | |
| 1007 | /* 0x7b0 */ { 0x80, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 1008 | /* 0x7b2 */ { 0x3a, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 1009 | /* 0x7b4 */ { 0xf8, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 1010 | /* 0x7b6 */ { 0x02, { NIB0__, NIB2__, NIB3__, NIB1__ } , 1, 1 }, | |
| 1011 | /* 0x7b8 */ { 0x84, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 1012 | /* 0x7ba */ { 0xd0, { NIB0__, NIB1__, NIB3__, NIB2__ } , 1, 1 }, | |
| 1013 | /* 0x7bc */ { 0xd6, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 1 }, | |
| 1014 | /* 0x7be */ { 0x66, { NIB2__, NIB1__, NIB0__, NIB3__ } , 1, 0 }, | |
| 1015 | /* 0x7c0 */ { 0xea, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 1016 | /* 0x7c2 */ { 0xe8, { NIB3__, NIB2__, NIB0__, NIB1__ } , 0, 0 }, | |
| 1017 | /* 0x7c4 */ { 0x9c, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 1018 | /* 0x7c6 */ { 0x02, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 1019 | /* 0x7c8 */ { 0x9a, { BLANK_, NIB2__, NIB3__, NIB1__ } , 1, 1 }, | |
| 1020 | /* 0x7ca */ { 0xa0, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 1021 | /* 0x7cc */ { 0x0c, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 1022 | /* 0x7ce */ { 0x80, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 1023 | /* 0x7d0 */ { 0xec, { NIB1__, NIB2__, NIB0__, NIB3__ } , 0, 0 }, | |
| 1024 | /* 0x7d2 */ { 0x1e, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 1025 | /* 0x7d4 */ { 0xb4, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 1026 | /* 0x7d6 */ { 0x28, { NIB3__, NIB2__, NIB1__, NIB0__ } , 0, 1 }, | |
| 1027 | /* 0x7d8 */ { 0xee, { NIB1__, NIB2__, BLANK_, NIB3__ } , 1, 1 }, | |
| 1028 | /* 0x7da */ { 0x56, { NIB2__, NIB0__, NIB1__, NIB3__ } , 1, 1 }, | |
| 1029 | /* 0x7dc */ { INPUT_PORT_A , { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 1 }, // dc.w $07DC ; nand | |
| 1030 | /* 0x7de */ { 0x2a, { NIB3__, NIB2__, NIB1__, NIB0__ } , 1, 1 }, | |
| 1031 | /* 0x7e0 */ { 0xf8, { NIB3__, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 1032 | /* 0x7e2 */ { 0x96, { NIB1__, NIB2__, BLANK_, NIB3__ } , 1, 0 }, | |
| 1033 | /* 0x7e4 */ { 0x34, { BLANK_, NIB3__, BLANK_, NIB2__ } , 1, 1 }, | |
| 1034 | /* 0x7e6 */ { 0x36, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 1035 | /* 0x7e8 */ { 0x4a, { NIB0__, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 1036 | /* 0x7ea */ { 0x0a, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 1037 | /* 0x7ec */ { 0x66, { NIB3__, NIB2__, NIB0__, NIB1__ } , 1, 0 }, | |
| 1038 | /* 0x7ee */ { 0xc2, { NIB1R1, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 1039 | /* 0x7f0 */ { 0xba, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 1040 | /* 0x7f2 */ { 0x5e, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 1 }, | |
| 1041 | /* 0x7f4 */ { 0x5c, { NIB2__, NIB1__, NIB3__, BLANK_ } , 1, 0 }, | |
| 1042 | /* 0x7f6 */ { 0xac, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 1043 | /* 0x7f8 */ { 0x98, { NIB1__, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 1044 | /* 0x7fa */ { 0x80, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 1045 | /* 0x7fc */ { INPUT_PORT_C , { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 0 }, // dc.w $07FC ; Bit not present | |
| 1046 | /* 0x7fe */ { 0xd8, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 1, 1 } | |
| 23 | 1047 | |
| 24 | /* 0x000 */ { 0x04, { NIB3__, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 25 | /* 0x002 */ { 0x2a, { NIB1__, NIB3__, NIB0__, NIB2__ } , 0, 1 }, | |
| 26 | /* 0x004 */ { 0x5e, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 27 | /* 0x006 */ { 0x98, { NIB0__, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 28 | /* 0x008 */ { 0x94, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 29 | /* 0x00a */ { 0xbe, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 1 }, | |
| 30 | /* 0x00c */ { 0xd6, { NIB1__, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 31 | /* 0x00e */ { 0xe4, { NIB0__, NIB3__, NIB1__, NIB2__ } , 0, 1 }, | |
| 32 | /* 0x010 */ { 0x90, { NIB3__, NIB2__, NIB0__, NIB1__ } , 1, 1 }, | |
| 33 | /* 0x012 */ { 0xa8, { NIB3__, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 34 | /* 0x014 */ { 0x24, { NIB2__, NIB1__, NIB3__, BLANK_ } , 0, 1 }, | |
| 35 | /* 0x016 */ { 0xfc, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 36 | /* 0x018 */ { 0x08, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 37 | /* 0x01a */ { INPUT_PORT_C , { NIB1__, NIB0__, NIB2__, NIB3__ } , 0, 0 }, // dc.w $001A ; 0x0010 | |
| 38 | /* 0x01c */ { 0x72, { NIB2__, NIB1__, NIB3__, BLANK_ } , 1, 0 }, | |
| 39 | /* 0x01e */ { 0xc4, { NIB0__, NIB1__, NIB3__, NIB2__ } , 1, 1 }, | |
| 40 | /* 0x020 */ { 0xd0, { NIB2__, NIB1__, NIB3__, NIB0__ } , 0, 1 }, | |
| 41 | /* 0x022 */ { 0x66, { NIB1__, NIB2__, NIB0__, NIB3__ } , 1, 1 }, | |
| 42 | /* 0x024 */ { 0x8c, { NIB3__, NIB2__, NIB0__, NIB1__ } , 0, 0 }, | |
| 43 | /* 0x026 */ { 0xec, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 44 | /* 0x028 */ { 0x58, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 45 | /* 0x02a */ { 0x80, { NIB3R1, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 46 | /* 0x02c */ { 0x82, { NIB0__, NIB3__, NIB2__, NIB1__ } , 0, 1 }, | |
| 47 | /* 0x02e */ { 0x6a, { NIB3__, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 48 | /* 0x030 */ { 0x00, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 49 | /* 0x032 */ { 0x60, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 50 | /* 0x034 */ { INPUT_PORT_B , { NIB0R3, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 51 | /* 0x036 */ { 0xae, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 52 | /* 0x038 */ { 0x12, { NIB3__, NIB0__, NIB2__, NIB1__ } , 0, 0 }, | |
| 53 | /* 0x03a */ { 0x42, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 54 | /* 0x03c */ { 0x1e, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 55 | /* 0x03e */ { 0xf6, { NIB1__, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 56 | /* 0x040 */ { 0xdc, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 0 }, | |
| 57 | /* 0x042 */ { 0x34, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 58 | /* 0x044 */ { 0x2c, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 59 | /* 0x046 */ { 0x7a, { NIB3R1, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 60 | /* 0x048 */ { 0x10, { NIB1__, NIB2__, BLANK_, NIB3__ } , 0, 0 }, | |
| 61 | /* 0x04a */ { 0x9e, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 62 | /* 0x04c */ { 0x3e, { NIB1__, NIB0__, NIB2__, NIB3__ } , 0, 0 }, | |
| 63 | /* 0x04e */ { 0x0e, { NIB2__, NIB1__, NIB3__, NIB0__ } , 0, 0 }, | |
| 64 | /* 0x050 */ { 0xa4, { BLANK_, NIB3__, BLANK_, NIB2__ } , 0, 1 }, | |
| 65 | /* 0x052 */ { 0x0c, { BLANK_, NIB2__, NIB3__, NIB1__ } , 1, 0 }, | |
| 66 | /* 0x054 */ { 0x40, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 67 | /* 0x056 */ { 0x20, { NIB1__, NIB0__, NIB3__, NIB2__ } , 1, 1 }, | |
| 68 | /* 0x058 */ { 0x46, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 69 | /* 0x05a */ { 0x6c, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 70 | /* 0x05c */ { 0x9a, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 71 | /* 0x05e */ { 0x18, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 72 | /* 0x060 */ { 0xe0, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 0 }, | |
| 73 | /* 0x062 */ { 0x30, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 74 | /* 0x064 */ { 0xca, { NIB2__, NIB1__, NIB0__, NIB3__ } , 0, 1 }, | |
| 75 | /* 0x066 */ { 0xac, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 76 | /* 0x068 */ { 0xe8, { NIB2__, NIB1__, BLANK_, NIB3__ } , 0, 0 }, | |
| 77 | /* 0x06a */ { 0x66, { NIB3__, NIB2__, NIB0__, NIB1__ } , 0, 1 }, | |
| 78 | /* 0x06c */ { 0x14, { NIB2__, NIB1__, NIB0__, NIB3__ } , 0, 0 }, | |
| 79 | /* 0x06e */ { 0x96, { NIB0__, NIB3__, NIB2__, NIB1__ } , 1, 0 }, | |
| 80 | /* 0x070 */ { 0x5c, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 81 | /* 0x072 */ { 0x0a, { NIB0__, NIB2__, NIB3__, NIB1__ } , 0, 1 }, | |
| 82 | /* 0x074 */ { INPUT_PORT_B , { NIB0R1, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 83 | /* 0x076 */ { INPUT_PORT_C , { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 1 }, // dc.w $0076 ; 0x1000 dc.w $0076 ; 0x1000 ; nand | |
| 84 | /* 0x078 */ { 0x5a, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 85 | /* 0x07a */ { 0x74, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 86 | /* 0x07c */ { 0xb4, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 87 | /* 0x07e */ { 0x86, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 88 | /* 0x080 */ { 0x84, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 89 | /* 0x082 */ { 0x28, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 90 | /* 0x084 */ { 0x50, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 91 | /* 0x086 */ { 0x66, { NIB3R1, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 92 | /* 0x088 */ { INPUT_PORT_A , { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, // dc.w $0088 | |
| 93 | /* 0x08a */ { 0x1c, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 94 | /* 0x08c */ { 0x48, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 95 | /* 0x08e */ { 0xc2, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 96 | /* 0x090 */ { 0x44, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 97 | /* 0x092 */ { 0x3c, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 98 | /* 0x094 */ { 0xfa, { NIB1__, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 99 | /* 0x096 */ { 0x22, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 100 | /* 0x098 */ { 0xf0, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 101 | /* 0x09a */ { 0x2e, { BLANK_, NIB3__, BLANK_, NIB2__ } , 1, 0 }, | |
| 102 | /* 0x09c */ { 0x06, { NIB0__, NIB3__, NIB1__, NIB2__ } , 1, 0 }, | |
| 103 | /* 0x09e */ { 0x64, { NIB3__, NIB1__, NIB2__, NIB0__ } , 1, 0 }, | |
| 104 | /* 0x0a0 */ { 0xcc, { NIB2__, NIB1__, NIB3__, NIB0__ } , 1, 0 }, | |
| 105 | /* 0x0a2 */ { 0x7a, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 106 | /* 0x0a4 */ { 0xb2, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 107 | /* 0x0a6 */ { 0xbe, { NIB3__, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 108 | /* 0x0a8 */ { 0xde, { NIB0__, NIB3__, NIB1__, NIB2__ } , 0, 1 }, | |
| 109 | /* 0x0aa */ { 0xf8, { NIB2__, NIB1__, NIB0__, NIB3__ } , 1, 0 }, | |
| 110 | /* 0x0ac */ { 0xca, { NIB2__, NIB3__, NIB1__, NIB0__ } , 1, 0 }, | |
| 111 | /* 0x0ae */ { 0x3e, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 112 | /* 0x0b0 */ { 0xb6, { NIB2__, NIB3__, NIB1__, NIB0__ } , 0, 1 }, | |
| 113 | /* 0x0b2 */ { 0xd8, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 114 | /* 0x0b4 */ { INPUT_PORT_C , { NIB3__, NIB0__, NIB1__, NIB2__ } , 0, 0 }, // dc.w $00B4 ; 0x1000 | |
| 115 | /* 0x0b6 */ { 0xc0, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 116 | /* 0x0b8 */ { 0xa2, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 117 | /* 0x0ba */ { 0xe6, { NIB3__, NIB0__, NIB2__, NIB1__ } , 0, 0 }, | |
| 118 | /* 0x0bc */ { 0x1a, { NIB0__, NIB2__, NIB3__, NIB1__ } , 1, 1 }, | |
| 119 | /* 0x0be */ { 0xb0, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 120 | /* 0x0c0 */ { 0x4c, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 121 | /* 0x0c2 */ { 0x56, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 122 | /* 0x0c4 */ { 0xee, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 0 }, | |
| 123 | /* 0x0c6 */ { 0xd4, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 124 | /* 0x0c8 */ { INPUT_PORT_A , { NIB2__, NIB3__, NIB0__, NIB1__ } , 1, 0 }, // dc.w $00C8 ; xor | |
| 125 | /* 0x0ca */ { 0xda, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 126 | /* 0x0cc */ { 0xce, { NIB1__, NIB3__, NIB0__, NIB2__ } , 1, 0 }, | |
| 127 | /* 0x0ce */ { 0xf2, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 128 | /* 0x0d0 */ { 0x8e, { NIB1__, NIB3__, NIB0__, NIB2__ } , 1, 1 }, | |
| 129 | /* 0x0d2 */ { 0x3a, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 130 | /* 0x0d4 */ { 0x6e, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 0, 0 }, | |
| 131 | /* 0x0d6 */ { 0xa6, { NIB1R1, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 132 | /* 0x0d8 */ { 0x78, { BLANK_, NIB3__, BLANK_, NIB2__ } , 0, 0 }, | |
| 133 | /* 0x0da */ { 0xbc, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 134 | /* 0x0dc */ { 0xba, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 135 | /* 0x0de */ { 0x36, { NIB3R1, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 136 | /* 0x0e0 */ { 0x66, { NIB1__, NIB2__, NIB0__, NIB3__ } , 0, 1 }, | |
| 137 | /* 0x0e2 */ { 0x92, { NIB3__, NIB2__, NIB1__, NIB0__ } , 0, 1 }, | |
| 138 | /* 0x0e4 */ { 0x52, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 139 | /* 0x0e6 */ { 0xf4, { NIB0__, NIB2__, NIB3__, NIB1__ } , 1, 0 }, | |
| 140 | /* 0x0e8 */ { INPUT_PORT_B , { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 141 | /* 0x0ea */ { 0xc6, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 142 | /* 0x0ec */ { 0xea, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 1 }, | |
| 143 | /* 0x0ee */ { 0xfe, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 144 | /* 0x0f0 */ { 0xb2, { BLANK_, BLANK_, BLANK_, NIB3__ } , 0, 1 }, | |
| 145 | /* 0x0f2 */ { 0x32, { NIB0__, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 146 | /* 0x0f4 */ { 0x76, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 147 | /* 0x0f6 */ { 0xe2, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 148 | /* 0x0f8 */ { 0x7c, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 149 | /* 0x0fa */ { 0xa0, { NIB0__, NIB1__, NIB3__, NIB2__ } , 0, 1 }, | |
| 150 | /* 0x0fc */ { 0x4a, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 151 | /* 0x0fe */ { 0x70, { NIB1__, NIB2__, BLANK_, NIB3__ } , 1, 1 }, | |
| 152 | /* 0x100 */ { 0x64, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 153 | /* 0x102 */ { 0x04, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 154 | /* 0x104 */ { 0xe2, { NIB0__, NIB1__, NIB3__, NIB2__ } , 1, 0 }, | |
| 155 | /* 0x106 */ { 0xca, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 156 | /* 0x108 */ { 0xa4, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 157 | /* 0x10a */ { 0x12, { NIB0__, NIB2__, NIB3__, NIB1__ } , 0, 0 }, | |
| 158 | /* 0x10c */ { 0xaa, { BLANK_, BLANK_, BLANK_, NIB3__ } , 0, 0 }, | |
| 159 | /* 0x10e */ { 0x7c, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 160 | /* 0x110 */ { 0xf4, { NIB1__, NIB0__, NIB2__, NIB3__ } , 1, 1 }, | |
| 161 | /* 0x112 */ { 0xda, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 162 | /* 0x114 */ { 0x7a, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 163 | /* 0x116 */ { 0x3a, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 164 | /* 0x118 */ { 0x00, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 165 | /* 0x11a */ { 0x66, { NIB3__, NIB2__, NIB0__, NIB1__ } , 1, 0 }, | |
| 166 | /* 0x11c */ { 0xce, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 167 | /* 0x11e */ { 0xb6, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 168 | /* 0x120 */ { 0x1c, { NIB2__, NIB1__, NIB0__, NIB3__ } , 1, 0 }, | |
| 169 | /* 0x122 */ { 0x82, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 170 | /* 0x124 */ { 0x4a, { NIB3R1, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 171 | /* 0x126 */ { 0x58, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 172 | /* 0x128 */ { 0xbe, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 173 | /* 0x12a */ { 0x36, { NIB1__, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 174 | /* 0x12c */ { 0x9a, { NIB3__, NIB1__, NIB2__, NIB0__ } , 0, 0 }, | |
| 175 | /* 0x12e */ { 0x02, { NIB2__, NIB0__, NIB1__, NIB3__ } , 1, 1 }, | |
| 176 | /* 0x130 */ { 0xea, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 177 | /* 0x132 */ { 0xae, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 178 | /* 0x134 */ { 0x52, { BLANK_, BLANK_, BLANK_, NIB3__ } , 1, 0 }, | |
| 179 | /* 0x136 */ { 0xdc, { NIB3__, NIB2__, NIB1__, NIB0__ } , 0, 0 }, | |
| 180 | /* 0x138 */ { 0x9e, { NIB0__, NIB3__, NIB1__, NIB2__ } , 0, 0 }, | |
| 181 | /* 0x13a */ { 0xfc, { NIB3__, NIB1__, NIB2__, NIB0__ } , 1, 1 }, | |
| 182 | /* 0x13c */ { 0x4c, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 183 | /* 0x13e */ { 0x76, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 184 | /* 0x140 */ { 0x8c, { NIB2__, NIB0__, NIB1__, NIB3__ } , 1, 0 }, | |
| 185 | /* 0x142 */ { 0xd4, { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 1 }, | |
| 186 | /* 0x144 */ { 0x3e, { NIB1__, NIB2__, NIB3__, BLANK_ } , 0, 0 }, | |
| 187 | /* 0x146 */ { 0x16, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 188 | /* 0x148 */ { 0xb8, { NIB3__, NIB2__, NIB1__, NIB0__ } , 1, 0 }, | |
| 189 | /* 0x14a */ { 0x50, { NIB2__, NIB1__, NIB3__, NIB0__ } , 1, 0 }, | |
| 190 | /* 0x14c */ { 0x42, { NIB1R1, NIB2__, NIB3__, BLANK_ } , 1, 0 }, // xor readback address, affected by xor, funky | |
| 191 | /* 0x14e */ { 0xd6, { NIB0__, NIB2__, NIB3__, NIB1__ } , 1, 1 }, | |
| 192 | /* 0x150 */ { 0x7e, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 193 | /* 0x152 */ { 0x92, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 194 | /* 0x154 */ { INPUT_PORT_A , { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 195 | /* 0x156 */ { 0xde, { NIB1__, NIB0__, NIB2__, NIB3__ } , 0, 1 }, | |
| 196 | /* 0x158 */ { 0x1a, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 197 | /* 0x15a */ { 0x9c, { NIB2__, NIB0__, NIB1__, NIB3__ } , 0, 1 }, | |
| 198 | /* 0x15c */ { 0x14, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 199 | /* 0x15e */ { 0x98, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 200 | /* 0x160 */ { 0x40, { BLANK_, NIB2__, NIB3__, NIB1__ } , 0, 0 }, | |
| 201 | /* 0x162 */ { 0x6e, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 202 | /* 0x164 */ { 0xc4, { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 0 }, | |
| 203 | /* 0x166 */ { 0xc6, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 204 | /* 0x168 */ { 0x84, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 205 | /* 0x16a */ { 0x8e, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 206 | /* 0x16c */ { 0x96, { NIB3__, NIB0__, NIB2__, NIB1__ } , 1, 1 }, | |
| 207 | /* 0x16e */ { 0x6a, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 208 | /* 0x170 */ { 0xf0, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 209 | /* 0x172 */ { 0x2a, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 210 | /* 0x174 */ { 0x1e, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 211 | /* 0x176 */ { 0x62, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 212 | /* 0x178 */ { 0x88, { NIB2__, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 213 | /* 0x17a */ { 0xe0, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 214 | /* 0x17c */ { INPUT_PORT_A , { NIB3R1, NIB0__, NIB1__, NIB2__ } , 1, 1 }, // dc.w $017C ; xor,nand | |
| 215 | /* 0x17e */ { 0xcc, { NIB0__, NIB1__, NIB3__, NIB2__ } , 0, 0 }, | |
| 216 | /* 0x180 */ { INPUT_PORT_A , { NIB0R3, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 217 | /* 0x182 */ { 0x46, { NIB2__, NIB1__, NIB0__, NIB3__ } , 0, 0 }, | |
| 218 | /* 0x184 */ { 0x90, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 1 }, | |
| 219 | /* 0x186 */ { 0x72, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 220 | /* 0x188 */ { 0xee, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 221 | /* 0x18a */ { 0x2c, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 222 | /* 0x18c */ { 0x22, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 223 | /* 0x18e */ { 0x38, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 224 | /* 0x190 */ { 0x44, { NIB1__, NIB2__, BLANK_, NIB3__ } , 0, 1 }, | |
| 225 | /* 0x192 */ { 0xc0, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 1 }, | |
| 226 | /* 0x194 */ { 0x54, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 227 | /* 0x196 */ { 0x6c, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 228 | /* 0x198 */ { 0xfa, { NIB2__, NIB1__, BLANK_, NIB3__ } , 0, 1 }, | |
| 229 | /* 0x19a */ { 0x34, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 230 | /* 0x19c */ { 0xa8, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 231 | /* 0x19e */ { 0x3c, { NIB2__, NIB1__, NIB3__, NIB0__ } , 1, 1 }, | |
| 232 | /* 0x1a0 */ { 0x7e, { BLANK_, BLANK_, BLANK_, NIB3__ } , 1, 1 }, | |
| 233 | /* 0x1a2 */ { 0x4e, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 234 | /* 0x1a4 */ { 0x9c, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 235 | /* 0x1a6 */ { 0x16, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 236 | /* 0x1a8 */ { 0x38, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 237 | /* 0x1aa */ { 0xc8, { NIB1__, NIB0__, NIB3__, NIB2__ } , 1, 0 }, | |
| 238 | /* 0x1ac */ { 0x68, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 239 | /* 0x1ae */ { 0x54, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 240 | /* 0x1b0 */ { 0xba, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 241 | /* 0x1b2 */ { 0x78, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 242 | /* 0x1b4 */ { 0xcc, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 0 }, | |
| 243 | /* 0x1b6 */ { 0xfe, { NIB1__, NIB0__, NIB2__, NIB3__ } , 1, 0 }, | |
| 244 | /* 0x1b8 */ { 0x86, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 245 | /* 0x1ba */ { 0x18, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 246 | /* 0x1bc */ { 0x0e, { NIB2__, NIB3__, NIB1__, NIB0__ } , 0, 1 }, | |
| 247 | /* 0x1be */ { 0xc2, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 248 | /* 0x1c0 */ { INPUT_PORT_C , { NIB3__, NIB1__, NIB2__, NIB0__ } , 0, 0 }, // dc.w $01C0 ; 0x1000 | |
| 249 | /* 0x1c2 */ { 0x0c, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 250 | /* 0x1c4 */ { INPUT_PORT_A , { NIB0R1, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 251 | /* 0x1c6 */ { 0x70, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 252 | /* 0x1c8 */ { INPUT_PORT_A , { NIB0R2, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 253 | /* 0x1ca */ { 0x5c, { BLANK_, NIB2__, NIB3__, NIB1__ } , 0, 1 }, | |
| 254 | /* 0x1cc */ { 0xac, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 255 | /* 0x1ce */ { 0x48, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 256 | /* 0x1d0 */ { 0x0a, { BLANK_, NIB3__, BLANK_, NIB2__ } , 1, 1 }, | |
| 257 | /* 0x1d2 */ { 0x94, { NIB2__, NIB3__, NIB1__, NIB0__ } , 1, 0 }, | |
| 258 | /* 0x1d4 */ { 0x66, { BLANK_, NIB2__, NIB3__, NIB1__ } , 1, 1 }, | |
| 259 | /* 0x1d6 */ { 0xf8, { NIB1__, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 260 | /* 0x1d8 */ { 0x68, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 261 | /* 0x1da */ { 0x24, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 262 | /* 0x1dc */ { 0x66, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 263 | /* 0x1de */ { 0xa6, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 264 | /* 0x1e0 */ { 0x74, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 265 | /* 0x1e2 */ { 0xd0, { NIB2__, NIB3__, NIB1__, NIB0__ } , 0, 0 }, | |
| 266 | /* 0x1e4 */ { 0x5e, { NIB3__, NIB0__, NIB2__, NIB1__ } , 0, 1 }, | |
| 267 | /* 0x1e6 */ { 0xe6, { NIB1__, NIB2__, NIB0__, NIB3__ } , 0, 0 }, | |
| 268 | /* 0x1e8 */ { 0x66, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 269 | /* 0x1ea */ { INPUT_PORT_B , { NIB1__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 270 | /* 0x1ec */ { INPUT_PORT_B , { NIB1R2, BLANK_, BLANK_, BLANK_ } , 0, 1 }, // dc.w $01EC ; nand | |
| 271 | /* 0x1ee */ { 0xc8, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 272 | /* 0x1f0 */ { 0xa2, { NIB2__, NIB3__, NIB1__, NIB0__ } , 1, 1 }, | |
| 273 | /* 0x1f2 */ { 0x60, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 274 | /* 0x1f4 */ { 0xbc, { NIB3__, NIB1__, NIB2__, NIB0__ } , 0, 1 }, | |
| 275 | /* 0x1f6 */ { 0x06, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 276 | /* 0x1f8 */ { 0x2e, { NIB1__, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 277 | /* 0x1fa */ { 0x26, { NIB3__, NIB0__, NIB2__, NIB1__ } , 1, 0 }, | |
| 278 | /* 0x1fc */ { 0x56, { NIB1__, NIB2__, BLANK_, NIB3__ } , 1, 0 }, | |
| 279 | /* 0x1fe */ { 0xd2, { NIB1R1, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 280 | /* 0x200 */ { 0xa0, { NIB3R1, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 281 | /* 0x202 */ { 0x34, { NIB2__, NIB1__, BLANK_, NIB3__ } , 1, 0 }, | |
| 282 | /* 0x204 */ { 0xf6, { BLANK_, BLANK_, BLANK_, NIB3__ } , 1, 0 }, | |
| 283 | /* 0x206 */ { INPUT_PORT_A , { NIB2__, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 284 | /* 0x208 */ { 0xae, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 285 | /* 0x20a */ { 0xf4, { BLANK_, NIB2__, NIB3__, NIB1__ } , 1, 0 }, | |
| 286 | /* 0x20c */ { INPUT_PORT_C , { BLANK_, BLANK_, BLANK_, NIB3__ } , 1, 1 }, // dc.w $020C ; Bit not present dc.w $020C ; Bit not present ; xor,nand | |
| 287 | /* 0x20e */ { 0x4e, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 288 | /* 0x210 */ { 0x0e, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 289 | /* 0x212 */ { 0x6e, { NIB0__, NIB3__, NIB1__, NIB2__ } , 1, 0 }, | |
| 290 | /* 0x214 */ { 0x4a, { NIB3__, NIB0__, NIB2__, NIB1__ } , 0, 1 }, | |
| 291 | /* 0x216 */ { 0x0a, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 292 | /* 0x218 */ { 0x82, { NIB1__, NIB2__, NIB0__, NIB3__ } , 1, 1 }, | |
| 293 | /* 0x21a */ { 0x66, { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 0 }, | |
| 294 | /* 0x21c */ { 0x6c, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 295 | /* 0x21e */ { 0xb8, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 296 | /* 0x220 */ { 0x12, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 297 | /* 0x222 */ { 0x06, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 298 | /* 0x224 */ { 0x00, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 299 | /* 0x226 */ { 0x72, { NIB3__, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 300 | /* 0x228 */ { 0xe4, { NIB2__, NIB1__, NIB3__, BLANK_ } , 1, 0 }, | |
| 301 | /* 0x22a */ { 0x90, { NIB3__, NIB2__, NIB1__, NIB0__ } , 1, 1 }, | |
| 302 | /* 0x22c */ { 0xc4, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 303 | /* 0x22e */ { 0x08, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 304 | /* 0x230 */ { 0x98, { NIB1__, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 305 | /* 0x232 */ { 0xda, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 306 | /* 0x234 */ { 0x3a, { NIB1__, NIB3__, NIB0__, NIB2__ } , 1, 0 }, | |
| 307 | /* 0x236 */ { 0xcc, { BLANK_, NIB3__, BLANK_, NIB2__ } , 1, 1 }, | |
| 308 | /* 0x238 */ { 0x7c, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 309 | /* 0x23a */ { 0x86, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 310 | /* 0x23c */ { 0x56, { NIB3__, NIB1__, NIB2__, NIB0__ } , 0, 1 }, | |
| 311 | /* 0x23e */ { 0x8a, { NIB0__, NIB3__, NIB2__, NIB1__ } , 1, 1 }, | |
| 312 | /* 0x240 */ { 0xa0, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 313 | /* 0x242 */ { 0x04, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 314 | /* 0x244 */ { 0x32, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 315 | /* 0x246 */ { 0x48, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 316 | /* 0x248 */ { 0x8c, { NIB3__, NIB2__, NIB0__, NIB1__ } , 1, 1 }, | |
| 317 | /* 0x24a */ { 0xa2, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 318 | /* 0x24c */ { 0xfa, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 319 | /* 0x24e */ { 0x46, { NIB3__, NIB0__, NIB2__, NIB1__ } , 1, 0 }, | |
| 320 | /* 0x250 */ { 0x62, { NIB2__, NIB1__, NIB0__, NIB3__ } , 0, 1 }, | |
| 321 | /* 0x252 */ { 0xe0, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 322 | /* 0x254 */ { 0x7e, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 323 | /* 0x256 */ { 0xce, { NIB1__, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 324 | /* 0x258 */ { 0xf8, { NIB1R1, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 325 | /* 0x25a */ { 0x6a, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 326 | /* 0x25c */ { 0x58, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 327 | /* 0x25e */ { 0xc0, { NIB3__, NIB1__, NIB2__, NIB0__ } , 1, 0 }, | |
| 328 | /* 0x260 */ { 0xe2, { NIB1__, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 329 | /* 0x262 */ { 0x30, { NIB1__, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 330 | /* 0x264 */ { 0x88, { NIB2__, NIB1__, NIB3__, BLANK_ } , 1, 1 }, | |
| 331 | /* 0x266 */ { 0xe8, { NIB0__, NIB2__, NIB3__, NIB1__ } , 1, 0 }, | |
| 332 | /* 0x268 */ { 0xac, { BLANK_, NIB3__, BLANK_, NIB2__ } , 0, 1 }, | |
| 333 | /* 0x26a */ { 0xe6, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 334 | /* 0x26c */ { 0xc2, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 335 | /* 0x26e */ { 0xa8, { NIB3__, NIB2__, NIB1__, NIB0__ } , 0, 0 }, | |
| 336 | /* 0x270 */ { INPUT_PORT_C , { NIB1__, NIB2__, NIB3__, NIB0__ } , 0, 0 }, // dc.w $0270 ; 0x0010 | |
| 337 | /* 0x272 */ { 0x3c, { NIB0__, NIB1__, NIB3__, NIB2__ } , 1, 1 }, | |
| 338 | /* 0x274 */ { 0x68, { NIB1__, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 339 | /* 0x276 */ { 0x2e, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 340 | /* 0x278 */ { 0x18, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 341 | /* 0x27a */ { 0x02, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 342 | /* 0x27c */ { 0x70, { NIB1__, NIB2__, NIB0__, NIB3__ } , 0, 0 }, | |
| 343 | /* 0x27e */ { 0x94, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 344 | /* 0x280 */ { 0x5e, { NIB2__, NIB1__, NIB3__, BLANK_ } , 0, 0 }, | |
| 345 | /* 0x282 */ { 0x26, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 346 | /* 0x284 */ { 0x14, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 347 | /* 0x286 */ { 0x7a, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 0, 0 }, | |
| 348 | /* 0x288 */ { 0xd2, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 349 | /* 0x28a */ { 0xd4, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 350 | /* 0x28c */ { 0xa6, { NIB1__, NIB3__, NIB0__, NIB2__ } , 0, 0 }, | |
| 351 | /* 0x28e */ { 0x36, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 352 | /* 0x290 */ { 0xee, { NIB2__, NIB1__, BLANK_, NIB3__ } , 0, 0 }, | |
| 353 | /* 0x292 */ { INPUT_PORT_C , { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, // dc.w $0292 ; 0x0001 | |
| 354 | /* 0x294 */ { 0x66, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 355 | /* 0x296 */ { 0x5a, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 356 | /* 0x298 */ { 0x64, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 357 | /* 0x29a */ { 0x60, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 358 | /* 0x29c */ { 0xec, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 359 | /* 0x29e */ { 0x80, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 360 | /* 0x2a0 */ { 0xd0, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 361 | /* 0x2a2 */ { 0x44, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 362 | /* 0x2a4 */ { INPUT_PORT_C , { NIB0__, NIB1__, NIB3__, NIB2__ } , 0, 0 }, // dc.w $02A4 ; 0x0001 | |
| 363 | /* 0x2a6 */ { 0xbc, { NIB2__, NIB0__, NIB1__, NIB3__ } , 1, 1 }, | |
| 364 | /* 0x2a8 */ { 0x22, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 365 | /* 0x2aa */ { 0xb2, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 366 | /* 0x2ac */ { 0x1e, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 367 | /* 0x2ae */ { 0x9c, { NIB2__, NIB0__, NIB1__, NIB3__ } , 0, 0 }, | |
| 368 | /* 0x2b0 */ { 0x96, { NIB3__, NIB1__, NIB2__, NIB0__ } , 0, 0 }, | |
| 369 | /* 0x2b2 */ { 0x8e, { NIB2__, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 370 | /* 0x2b4 */ { 0xb6, { NIB0__, NIB3__, NIB1__, NIB2__ } , 1, 1 }, | |
| 371 | /* 0x2b6 */ { 0xfe, { NIB2__, NIB1__, NIB0__, NIB3__ } , 1, 1 }, | |
| 372 | /* 0x2b8 */ { 0x66, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 373 | /* 0x2ba */ { 0xf0, { BLANK_, NIB2__, NIB3__, NIB1__ } , 0, 0 }, | |
| 374 | /* 0x2bc */ { 0x20, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 375 | /* 0x2be */ { 0x40, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 376 | /* 0x2c0 */ { 0x4c, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 377 | /* 0x2c2 */ { 0x76, { BLANK_, NIB3__, BLANK_, NIB2__ } , 1, 1 }, | |
| 378 | /* 0x2c4 */ { 0xca, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 379 | /* 0x2c6 */ { 0x50, { NIB3__, NIB2__, NIB0__, NIB1__ } , 1, 0 }, | |
| 380 | /* 0x2c8 */ { 0x1c, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 381 | /* 0x2ca */ { 0x1a, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 382 | /* 0x2cc */ { INPUT_PORT_B , { NIB0__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 383 | /* 0x2ce */ { 0x92, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 384 | /* 0x2d0 */ { 0x66, { BLANK_, NIB3__, BLANK_, NIB2__ } , 1, 0 }, | |
| 385 | /* 0x2d2 */ { 0x28, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 386 | /* 0x2d4 */ { 0x74, { NIB0__, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 387 | /* 0x2d6 */ { 0x16, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 388 | /* 0x2d8 */ { 0x9e, { NIB1__, NIB0__, NIB2__, NIB3__ } , 0, 0 }, | |
| 389 | /* 0x2da */ { 0xde, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 390 | /* 0x2dc */ { 0xba, { NIB0__, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 391 | /* 0x2de */ { 0x78, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 392 | /* 0x2e0 */ { 0x9a, { NIB1__, NIB2__, BLANK_, NIB3__ } , 0, 0 }, | |
| 393 | /* 0x2e2 */ { 0xc6, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 394 | /* 0x2e4 */ { 0x42, { NIB1__, NIB2__, NIB0__, NIB3__ } , 1, 0 }, | |
| 395 | /* 0x2e6 */ { 0xea, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 396 | /* 0x2e8 */ { 0x0c, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 397 | /* 0x2ea */ { 0xd8, { NIB1__, NIB0__, NIB3__, NIB2__ } , 1, 0 }, | |
| 398 | /* 0x2ec */ { 0x5c, { NIB1__, NIB0__, NIB2__, NIB3__ } , 1, 0 }, | |
| 399 | /* 0x2ee */ { 0xaa, { NIB3R1, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 400 | /* 0x2f0 */ { 0xb4, { NIB0__, NIB3__, NIB2__, NIB1__ } , 1, 0 }, | |
| 401 | /* 0x2f2 */ { 0xf2, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 402 | /* 0x2f4 */ { INPUT_PORT_C , { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 1 }, // dc.w $02F4 ; 0x0001 dc.w $02F4 ; 0x0001 ; nand | |
| 403 | /* 0x2f6 */ { 0x84, { NIB1__, NIB2__, NIB0__, NIB3__ } , 0, 1 }, | |
| 404 | /* 0x2f8 */ { 0xa4, { BLANK_, NIB2__, NIB3__, NIB1__ } , 0, 1 }, | |
| 405 | /* 0x2fa */ { INPUT_PORT_C , { NIB0R3, NIB1__, NIB2__, NIB3__ } , 0, 0 }, // dc.w $02FA ; 0x0008 | |
| 406 | /* 0x2fc */ { 0xfc, { BLANK_, NIB3__, BLANK_, NIB2__ } , 0, 0 }, | |
| 407 | /* 0x2fe */ { 0x10, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 408 | /* 0x300 */ { 0xa4, { BLANK_, BLANK_, BLANK_, NIB3__ } , 0, 0 }, | |
| 409 | /* 0x302 */ { 0x24, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 410 | /* 0x304 */ { 0xe2, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 411 | /* 0x306 */ { 0x32, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 412 | /* 0x308 */ { 0x2a, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 413 | /* 0x30a */ { 0x66, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 414 | /* 0x30c */ { 0x86, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 415 | /* 0x30e */ { 0xaa, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 416 | /* 0x310 */ { 0x66, { NIB2__, NIB1__, NIB3__, NIB0__ } , 0, 0 }, | |
| 417 | /* 0x312 */ { 0x4e, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 418 | /* 0x314 */ { 0x84, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 0, 0 }, | |
| 419 | /* 0x316 */ { 0x96, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 420 | /* 0x318 */ { 0x26, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 421 | /* 0x31a */ { 0x64, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 422 | /* 0x31c */ { 0xac, { NIB2__, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 423 | /* 0x31e */ { 0x78, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 424 | /* 0x320 */ { 0xfe, { NIB0__, NIB3__, NIB2__, NIB1__ } , 0, 0 }, | |
| 425 | /* 0x322 */ { 0x2e, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 426 | /* 0x324 */ { 0x06, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 427 | /* 0x326 */ { 0x92, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 428 | /* 0x328 */ { 0x34, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 429 | /* 0x32a */ { 0xc0, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 430 | /* 0x32c */ { 0x8a, { NIB2__, NIB1__, NIB3__, BLANK_ } , 0, 1 }, | |
| 431 | /* 0x32e */ { 0x46, { NIB1__, NIB2__, BLANK_, NIB3__ } , 0, 1 }, | |
| 432 | /* 0x330 */ { 0xd8, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 433 | /* 0x332 */ { 0xc4, { NIB1__, NIB0__, NIB3__, NIB2__ } , 1, 1 }, | |
| 434 | /* 0x334 */ { 0x30, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 435 | /* 0x336 */ { 0x1a, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 436 | /* 0x338 */ { 0xd0, { BLANK_, BLANK_, BLANK_, NIB3__ } , 1, 1 }, | |
| 437 | /* 0x33a */ { 0x60, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 438 | /* 0x33c */ { 0xf6, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 439 | /* 0x33e */ { 0x00, { NIB3__, NIB2__, NIB1__, NIB0__ } , 0, 1 }, | |
| 440 | /* 0x340 */ { 0x90, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 441 | /* 0x342 */ { 0xfc, { NIB2__, NIB1__, NIB0__, NIB3__ } , 0, 0 }, | |
| 442 | /* 0x344 */ { 0x08, { NIB3__, NIB2__, NIB0__, NIB1__ } , 0, 0 }, | |
| 443 | /* 0x346 */ { 0xa8, { NIB2__, NIB3__, NIB1__, NIB0__ } , 1, 1 }, | |
| 444 | /* 0x348 */ { 0x44, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 445 | /* 0x34a */ { 0x04, { NIB1__, NIB0__, NIB2__, NIB3__ } , 0, 1 }, | |
| 446 | /* 0x34c */ { 0x3c, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 447 | /* 0x34e */ { 0xde, { NIB0__, NIB2__, NIB3__, NIB1__ } , 0, 0 }, | |
| 448 | /* 0x350 */ { 0x72, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 0 }, | |
| 449 | /* 0x352 */ { 0x62, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 450 | /* 0x354 */ { 0x3a, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 451 | /* 0x356 */ { 0xba, { NIB2__, NIB1__, NIB3__, NIB0__ } , 0, 1 }, | |
| 452 | /* 0x358 */ { 0x68, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 1 }, | |
| 453 | /* 0x35a */ { 0x76, { NIB3R1, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 454 | /* 0x35c */ { 0x9e, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 1 }, | |
| 455 | /* 0x35e */ { 0xc6, { NIB2__, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 456 | /* 0x360 */ { 0xe4, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 457 | /* 0x362 */ { 0x02, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 458 | /* 0x364 */ { 0x6c, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 0 }, | |
| 459 | /* 0x366 */ { 0xec, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 460 | /* 0x368 */ { INPUT_PORT_C , { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, // dc.w $0368 ; 0x1000 | |
| 461 | /* 0x36a */ { INPUT_PORT_A , { NIB3__, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 462 | /* 0x36c */ { INPUT_PORT_B , { NIB0__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 463 | /* 0x36e */ { 0x0c, { NIB2__, NIB0__, NIB1__, NIB3__ } , 0, 1 }, | |
| 464 | /* 0x370 */ { 0x80, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 465 | /* 0x372 */ { 0x82, { NIB3__, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 466 | /* 0x374 */ { 0xb8, { NIB3__, NIB2__, NIB0__, NIB1__ } , 0, 1 }, | |
| 467 | /* 0x376 */ { 0x50, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 468 | /* 0x378 */ { 0x20, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 469 | /* 0x37a */ { 0xf4, { NIB0__, NIB2__, NIB3__, NIB1__ } , 0, 1 }, | |
| 470 | /* 0x37c */ { 0x8c, { NIB2__, NIB1__, NIB3__, NIB0__ } , 1, 1 }, | |
| 471 | /* 0x37e */ { 0xe6, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 472 | /* 0x380 */ { 0xda, { NIB2__, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 473 | /* 0x382 */ { 0xf2, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 474 | /* 0x384 */ { 0xdc, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 475 | /* 0x386 */ { 0x9c, { NIB1__, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 476 | /* 0x388 */ { INPUT_PORT_A , { NIB1__, NIB2__, NIB3__, BLANK_ } , 0, 0 }, | |
| 477 | /* 0x38a */ { INPUT_PORT_B , { NIB1__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 478 | /* 0x38c */ { 0x28, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 479 | /* 0x38e */ { 0xb6, { NIB2__, NIB1__, BLANK_, NIB3__ } , 1, 1 }, | |
| 480 | /* 0x390 */ { 0x2c, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 481 | /* 0x392 */ { 0xce, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 482 | /* 0x394 */ { 0x0e, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 483 | /* 0x396 */ { 0x5c, { NIB2__, NIB3__, NIB1__, NIB0__ } , 0, 0 }, | |
| 484 | /* 0x398 */ { 0x52, { BLANK_, NIB3__, BLANK_, NIB2__ } , 1, 1 }, | |
| 485 | /* 0x39a */ { 0x7e, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 486 | /* 0x39c */ { 0x6a, { NIB0__, NIB1__, NIB3__, NIB2__ } , 0, 0 }, | |
| 487 | /* 0x39e */ { 0xa0, { NIB0__, NIB1__, NIB3__, NIB2__ } , 1, 0 }, | |
| 488 | /* 0x3a0 */ { 0x52, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 489 | /* 0x3a2 */ { 0x94, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 490 | /* 0x3a4 */ { 0x2c, { NIB0__, NIB3__, NIB1__, NIB2__ } , 0, 0 }, | |
| 491 | /* 0x3a6 */ { 0xc8, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 492 | /* 0x3a8 */ { 0x18, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 493 | /* 0x3aa */ { 0x56, { NIB3__, NIB2__, NIB1__, NIB0__ } , 1, 0 }, | |
| 494 | /* 0x3ac */ { 0x54, { NIB0__, NIB1__, NIB3__, NIB2__ } , 0, 1 }, | |
| 495 | /* 0x3ae */ { 0x58, { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 1 }, | |
| 496 | /* 0x3b0 */ { INPUT_PORT_B , { NIB1__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 497 | /* 0x3b2 */ { 0x14, { NIB1R1, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 498 | /* 0x3b4 */ { 0x38, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 499 | /* 0x3b6 */ { 0xf8, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 500 | /* 0x3b8 */ { 0xb4, { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 0 }, | |
| 501 | /* 0x3ba */ { 0xd6, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 0 }, | |
| 502 | /* 0x3bc */ { 0x5c, { NIB2__, NIB0__, NIB1__, NIB3__ } , 1, 0 }, | |
| 503 | /* 0x3be */ { 0x1c, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 0 }, | |
| 504 | /* 0x3c0 */ { 0x22, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 505 | /* 0x3c2 */ { 0x66, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 506 | /* 0x3c4 */ { 0x8e, { NIB3__, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 507 | /* 0x3c6 */ { 0xf0, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 508 | /* 0x3c8 */ { 0xae, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 1 }, | |
| 509 | /* 0x3ca */ { 0x1e, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 510 | /* 0x3cc */ { 0xee, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 511 | /* 0x3ce */ { 0xea, { NIB0__, NIB3__, NIB2__, NIB1__ } , 0, 1 }, | |
| 512 | /* 0x3d0 */ { 0xe8, { NIB3__, NIB0__, NIB2__, NIB1__ } , 1, 1 }, | |
| 513 | /* 0x3d2 */ { 0x88, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 514 | /* 0x3d4 */ { INPUT_PORT_C , { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 0 }, // dc.w $03D4 ; 0x0010 | |
| 515 | /* 0x3d6 */ { 0x66, { NIB1__, NIB2__, BLANK_, NIB3__ } , 1, 1 }, | |
| 516 | /* 0x3d8 */ { INPUT_PORT_B , { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 517 | /* 0x3da */ { 0xfa, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 518 | /* 0x3dc */ { 0x4c, { NIB2__, NIB1__, BLANK_, NIB3__ } , 0, 1 }, | |
| 519 | /* 0x3de */ { 0x36, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 520 | /* 0x3e0 */ { 0xe0, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 521 | /* 0x3e2 */ { 0xd4, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 522 | /* 0x3e4 */ { 0xc8, { NIB1__, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 523 | /* 0x3e6 */ { 0xc2, { NIB1__, NIB2__, BLANK_, NIB3__ } , 1, 0 }, | |
| 524 | /* 0x3e8 */ { 0x0a, { BLANK_, NIB2__, NIB3__, NIB1__ } , 1, 1 }, | |
| 525 | /* 0x3ea */ { 0x9a, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 526 | /* 0x3ec */ { 0x7c, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 527 | /* 0x3ee */ { 0x4a, { NIB1R1, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 528 | /* 0x3f0 */ { 0xd2, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 529 | /* 0x3f2 */ { 0x48, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 1 }, | |
| 530 | /* 0x3f4 */ { 0x6e, { NIB1__, NIB2__, NIB3__, BLANK_ } , 0, 0 }, | |
| 531 | /* 0x3f6 */ { 0xa6, { NIB1__, NIB3__, NIB0__, NIB2__ } , 0, 1 }, | |
| 532 | /* 0x3f8 */ { 0x42, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 533 | /* 0x3fa */ { 0x5e, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 534 | /* 0x3fc */ { 0xbc, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 535 | /* 0x3fe */ { 0x10, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 536 | /* 0x400 */ { 0x02, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 537 | /* 0x402 */ { 0x72, { NIB1__, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 538 | /* 0x404 */ { 0x74, { NIB1__, NIB0__, NIB2__, NIB3__ } , 0, 0 }, | |
| 539 | /* 0x406 */ { 0x96, { NIB0__, NIB3__, NIB2__, NIB1__ } , 1, 1 }, | |
| 540 | /* 0x408 */ { 0x54, { BLANK_, NIB2__, NIB3__, NIB1__ } , 1, 0 }, | |
| 541 | /* 0x40a */ { 0xda, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 542 | /* 0x40c */ { 0xd6, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 543 | /* 0x40e */ { 0x8a, { NIB1__, NIB2__, BLANK_, NIB3__ } , 1, 1 }, | |
| 544 | /* 0x410 */ { 0xde, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 545 | /* 0x412 */ { 0xa4, { NIB1__, NIB2__, NIB0__, NIB3__ } , 1, 0 }, | |
| 546 | /* 0x414 */ { 0xa2, { BLANK_, NIB3__, BLANK_, NIB2__ } , 1, 0 }, | |
| 547 | /* 0x416 */ { 0xe4, { BLANK_, BLANK_, BLANK_, NIB3__ } , 0, 1 }, | |
| 548 | /* 0x418 */ { 0x04, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 549 | /* 0x41a */ { 0x84, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 550 | /* 0x41c */ { 0x2a, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 551 | /* 0x41e */ { 0x4c, { NIB0__, NIB2__, NIB3__, NIB1__ } , 0, 1 }, | |
| 552 | /* 0x420 */ { 0x2e, { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 0 }, | |
| 553 | /* 0x422 */ { 0x86, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 554 | /* 0x424 */ { 0x60, { NIB0__, NIB1__, NIB3__, NIB2__ } , 0, 0 }, | |
| 555 | /* 0x426 */ { 0xba, { NIB1__, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 556 | /* 0x428 */ { 0x8c, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 557 | /* 0x42a */ { 0xee, { NIB3__, NIB1__, NIB2__, NIB0__ } , 1, 0 }, | |
| 558 | /* 0x42c */ { 0xac, { BLANK_, NIB2__, NIB3__, NIB1__ } , 0, 0 }, | |
| 559 | /* 0x42e */ { 0x32, { NIB1__, NIB3__, NIB0__, NIB2__ } , 0, 1 }, | |
| 560 | /* 0x430 */ { 0xd2, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 561 | /* 0x432 */ { 0x0e, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 562 | /* 0x434 */ { 0x06, { NIB3__, NIB1__, NIB2__, NIB0__ } , 1, 1 }, | |
| 563 | /* 0x436 */ { 0x66, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 564 | /* 0x438 */ { 0xec, { NIB0__, NIB2__, NIB3__, NIB1__ } , 0, 0 }, | |
| 565 | /* 0x43a */ { 0xfe, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 566 | /* 0x43c */ { INPUT_PORT_B , { BLANK_, BLANK_, BLANK_, BLANK_ } , 0, 0 }, // this address always seems to return 0, is it a port with all bits masked out? I'm going to assume it's a 'B' port (4-bit) with mask applied to those 4 bits so they always return 0 due to a design flaw, that would make 21 of each port type. | |
| 567 | /* 0x43e */ { 0x7a, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 568 | /* 0x440 */ { 0xfc, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 569 | /* 0x442 */ { 0x10, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 570 | /* 0x444 */ { 0x66, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 571 | /* 0x446 */ { 0x16, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 572 | /* 0x448 */ { 0x90, { NIB1__, NIB0__, NIB2__, NIB3__ } , 1, 0 }, | |
| 573 | /* 0x44a */ { 0xb4, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 574 | /* 0x44c */ { INPUT_PORT_B, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 0, 1 }, //dc.w $044C ; nand | |
| 575 | /* 0x44e */ { 0x44, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 0 }, | |
| 576 | /* 0x450 */ { INPUT_PORT_C , { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 0 }, // dc.w $0450 ; 0x0100 dc.w $0450 ; 0x0100 ; xor | |
| 577 | /* 0x452 */ { 0x30, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 578 | /* 0x454 */ { 0x82, { NIB3__, NIB0__, NIB2__, NIB1__ } , 1, 0 }, | |
| 579 | /* 0x456 */ { 0x26, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 580 | /* 0x458 */ { 0x52, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 581 | /* 0x45a */ { 0xc6, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 582 | /* 0x45c */ { 0xd8, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 583 | /* 0x45e */ { 0x18, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 584 | /* 0x460 */ { 0xc8, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 585 | /* 0x462 */ { 0x64, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 586 | /* 0x464 */ { 0xbe, { NIB2__, NIB1__, NIB3__, NIB0__ } , 1, 1 }, | |
| 587 | /* 0x466 */ { 0x42, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 1 }, | |
| 588 | /* 0x468 */ { 0xc0, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 589 | /* 0x46a */ { 0x38, { NIB1R1, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 590 | /* 0x46c */ { 0xd0, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 591 | /* 0x46e */ { 0x9c, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 592 | /* 0x470 */ { 0xa8, { NIB0__, NIB1__, NIB3__, NIB2__ } , 0, 1 }, | |
| 593 | /* 0x472 */ { 0x4a, { NIB1__, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 594 | /* 0x474 */ { 0x1c, { NIB2__, NIB0__, NIB1__, NIB3__ } , 0, 0 }, | |
| 595 | /* 0x476 */ { 0xf0, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 1 }, | |
| 596 | /* 0x478 */ { 0xb6, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 597 | /* 0x47a */ { 0xc2, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 598 | /* 0x47c */ { 0x7e, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 599 | /* 0x47e */ { INPUT_PORT_B , { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 600 | /* 0x480 */ { 0x5a, { NIB2__, NIB1__, NIB3__, NIB0__ } , 0, 1 }, | |
| 601 | /* 0x482 */ { 0x5c, { NIB1__, NIB2__, BLANK_, NIB3__ } , 0, 0 }, | |
| 602 | /* 0x484 */ { 0x5a, { NIB3R1, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 603 | /* 0x486 */ { 0x06, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 604 | /* 0x488 */ { 0x2c, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 605 | /* 0x48a */ { 0x76, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 0 }, | |
| 606 | /* 0x48c */ { 0xbc, { NIB1R1, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 607 | /* 0x48e */ { 0x46, { NIB3__, NIB2__, NIB1__, NIB0__ } , 0, 0 }, | |
| 608 | /* 0x490 */ { 0x66, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 609 | /* 0x492 */ { 0xea, { NIB1__, NIB0__, NIB2__, NIB3__ } , 0, 1 }, | |
| 610 | /* 0x494 */ { 0x9a, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 611 | /* 0x496 */ { 0xb8, { NIB1__, NIB3__, NIB0__, NIB2__ } , 1, 1 }, | |
| 612 | /* 0x498 */ { 0x36, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 613 | /* 0x49a */ { 0x56, { NIB0__, NIB1__, NIB3__, NIB2__ } , 1, 0 }, | |
| 614 | /* 0x49c */ { 0x6c, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 615 | /* 0x49e */ { 0x12, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 616 | /* 0x4a0 */ { 0xa4, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 617 | /* 0x4a2 */ { 0xa8, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 618 | /* 0x4a4 */ { 0xce, { NIB3__, NIB1__, NIB2__, NIB0__ } , 1, 1 }, | |
| 619 | /* 0x4a6 */ { 0x8c, { NIB1__, NIB0__, NIB2__, NIB3__ } , 0, 0 }, | |
| 620 | /* 0x4a8 */ { 0xb0, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 621 | /* 0x4aa */ { 0x48, { NIB1__, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 622 | /* 0x4ac */ { INPUT_PORT_A , { NIB3__, NIB1__, NIB2__, NIB0__ } , 0, 0 }, | |
| 623 | /* 0x4ae */ { 0x92, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 624 | /* 0x4b0 */ { 0x10, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 625 | /* 0x4b2 */ { 0x74, { NIB3__, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 626 | /* 0x4b4 */ { 0x08, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 0, 0 }, | |
| 627 | /* 0x4b6 */ { 0x94, { NIB3__, NIB2__, NIB1__, NIB0__ } , 1, 0 }, | |
| 628 | /* 0x4b8 */ { 0x46, { NIB2__, NIB3__, NIB1__, NIB0__ } , 1, 0 }, | |
| 629 | /* 0x4ba */ { 0x24, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 630 | /* 0x4bc */ { 0x42, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 0, 0 }, | |
| 631 | /* 0x4be */ { 0xa6, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 632 | /* 0x4c0 */ { 0x08, { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 1 }, | |
| 633 | /* 0x4c2 */ { 0x80, { NIB1__, NIB2__, NIB0__, NIB3__ } , 0, 1 }, | |
| 634 | /* 0x4c4 */ { 0x3c, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 635 | /* 0x4c6 */ { 0x94, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 636 | /* 0x4c8 */ { INPUT_PORT_A , { NIB1__, NIB0__, NIB2__, NIB3__ } , 0, 0 }, | |
| 637 | /* 0x4ca */ { 0x20, { NIB2__, NIB1__, NIB3__, BLANK_ } , 1, 1 }, | |
| 638 | /* 0x4cc */ { 0xf6, { NIB2__, NIB1__, NIB3__, NIB0__ } , 0, 0 }, | |
| 639 | /* 0x4ce */ { 0x66, { NIB2__, NIB3__, NIB1__, NIB0__ } , 1, 1 }, | |
| 640 | /* 0x4d0 */ { 0xe2, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 641 | /* 0x4d2 */ { INPUT_PORT_B , { NIB0R2, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 642 | /* 0x4d4 */ { 0xd4, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 643 | /* 0x4d6 */ { 0xa0, { NIB3__, NIB1__, NIB2__, NIB0__ } , 0, 0 }, | |
| 644 | /* 0x4d8 */ { 0x48, { NIB0__, NIB3__, NIB1__, NIB2__ } , 0, 0 }, | |
| 645 | /* 0x4da */ { 0xca, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 646 | /* 0x4dc */ { 0x62, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 647 | /* 0x4de */ { 0x70, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 648 | /* 0x4e0 */ { 0xfa, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 0 }, | |
| 649 | /* 0x4e2 */ { 0x9e, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 650 | /* 0x4e4 */ { 0x40, { NIB1__, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 651 | /* 0x4e6 */ { 0x68, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 652 | /* 0x4e8 */ { 0x88, { NIB1__, NIB2__, BLANK_, NIB3__ } , 0, 1 }, | |
| 653 | /* 0x4ea */ { 0x3e, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 654 | /* 0x4ec */ { 0x7c, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 655 | /* 0x4ee */ { 0xcc, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 656 | /* 0x4f0 */ { 0x34, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 657 | /* 0x4f2 */ { INPUT_PORT_A , { NIB0__, NIB1__, NIB3__, NIB2__ } , 0, 0 }, // dc.w $04F2 | |
| 658 | /* 0x4f4 */ { 0x28, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 659 | /* 0x4f6 */ { 0xe6, { NIB3__, NIB0__, NIB2__, NIB1__ } , 0, 0 }, | |
| 660 | /* 0x4f8 */ { 0x6a, { NIB1__, NIB0__, NIB2__, NIB3__ } , 1, 1 }, | |
| 661 | /* 0x4fa */ { 0xaa, { NIB1__, NIB3__, NIB0__, NIB2__ } , 0, 1 }, | |
| 662 | /* 0x4fc */ { 0x50, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 663 | /* 0x4fe */ { 0xa6, { NIB2__, NIB0__, NIB1__, NIB3__ } , 0, 1 }, | |
| 664 | /* 0x500 */ { 0xf0, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 665 | /* 0x502 */ { 0x88, { NIB3__, NIB0__, NIB2__, NIB1__ } , 1, 1 }, | |
| 666 | /* 0x504 */ { 0x5c, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 1 }, | |
| 667 | /* 0x506 */ { INPUT_PORT_C , { NIB0R2, NIB1__, NIB2__, NIB3__ } , 0, 0 }, // dc.w $0506 ; 0x0004 | |
| 668 | /* 0x508 */ { INPUT_PORT_A , { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 669 | /* 0x50a */ { 0xc0, { BLANK_, NIB3__, BLANK_, NIB2__ } , 0, 1 }, | |
| 670 | /* 0x50c */ { 0x26, { NIB1__, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 671 | /* 0x50e */ { 0x72, { NIB3__, NIB2__, NIB1__, NIB0__ } , 1, 1 }, | |
| 672 | /* 0x510 */ { 0x8a, { NIB2__, NIB0__, NIB1__, NIB3__ } , 1, 1 }, | |
| 673 | /* 0x512 */ { 0x06, { NIB3__, NIB2__, NIB0__, NIB1__ } , 0, 0 }, | |
| 674 | /* 0x514 */ { 0x32, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 675 | /* 0x516 */ { 0xb6, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 676 | /* 0x518 */ { 0x02, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 677 | /* 0x51a */ { 0xb2, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 678 | /* 0x51c */ { 0x0a, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 679 | /* 0x51e */ { 0xd6, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 0, 0 }, | |
| 680 | /* 0x520 */ { 0xaa, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 681 | /* 0x522 */ { 0xca, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 682 | /* 0x524 */ { 0x54, { NIB1__, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 683 | /* 0x526 */ { 0x08, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 684 | /* 0x528 */ { INPUT_PORT_B , { NIB2__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 685 | /* 0x52a */ { 0x8e, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 686 | /* 0x52c */ { 0xe0, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 687 | /* 0x52e */ { 0xba, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 688 | /* 0x530 */ { 0x18, { NIB2__, NIB3__, NIB1__, NIB0__ } , 0, 1 }, | |
| 689 | /* 0x532 */ { 0xb0, { NIB3__, NIB2__, NIB0__, NIB1__ } , 0, 1 }, | |
| 690 | /* 0x534 */ { 0x1a, { NIB1__, NIB0__, NIB2__, NIB3__ } , 1, 1 }, | |
| 691 | /* 0x536 */ { 0x7a, { NIB1__, NIB0__, NIB2__, NIB3__ } , 0, 1 }, | |
| 692 | /* 0x538 */ { 0x3c, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 693 | /* 0x53a */ { 0x0c, { NIB3__, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 694 | /* 0x53c */ { 0xfa, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 695 | /* 0x53e */ { 0x9e, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 696 | /* 0x540 */ { 0x3e, { NIB0__, NIB3__, NIB2__, NIB1__ } , 1, 0 }, | |
| 697 | /* 0x542 */ { 0x9c, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 698 | /* 0x544 */ { 0x5a, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 699 | /* 0x546 */ { 0x62, { NIB2__, NIB1__, BLANK_, NIB3__ } , 0, 1 }, | |
| 700 | /* 0x548 */ { 0xf6, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 701 | /* 0x54a */ { 0xde, { NIB1__, NIB0__, NIB3__, NIB2__ } , 1, 1 }, | |
| 702 | /* 0x54c */ { 0x38, { NIB2__, NIB0__, NIB1__, NIB3__ } , 1, 0 }, | |
| 703 | /* 0x54e */ { 0xe6, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 704 | /* 0x550 */ { 0xa2, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 705 | /* 0x552 */ { 0x4c, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 706 | /* 0x554 */ { 0xae, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 707 | /* 0x556 */ { 0xac, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 708 | /* 0x558 */ { 0x68, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 709 | /* 0x55a */ { 0xf2, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 710 | /* 0x55c */ { 0x66, { NIB1R1, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 711 | /* 0x55e */ { 0xea, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 712 | /* 0x560 */ { 0x82, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 713 | /* 0x562 */ { INPUT_PORT_B , { NIB0__, BLANK_, BLANK_, BLANK_ } , 1, 0 }, // dc.w $0562 ; xor | |
| 714 | /* 0x564 */ { 0x80, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 0, 0 }, | |
| 715 | /* 0x566 */ { 0xf8, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 716 | /* 0x568 */ { 0x6c, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 717 | /* 0x56a */ { 0x7c, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 718 | /* 0x56c */ { INPUT_PORT_A , { NIB1__, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 719 | /* 0x56e */ { 0x98, { NIB3__, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 720 | /* 0x570 */ { 0x24, { NIB2__, NIB1__, BLANK_, NIB3__ } , 1, 0 }, | |
| 721 | /* 0x572 */ { 0xc2, { NIB1__, NIB3__, NIB0__, NIB2__ } , 1, 1 }, | |
| 722 | /* 0x574 */ { 0xdc, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 723 | /* 0x576 */ { 0x52, { NIB2__, NIB1__, BLANK_, NIB3__ } , 0, 0 }, | |
| 724 | /* 0x578 */ { 0x2a, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 725 | /* 0x57a */ { 0xb8, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 0 }, | |
| 726 | /* 0x57c */ { 0x28, { NIB1__, NIB2__, BLANK_, NIB3__ } , 0, 0 }, | |
| 727 | /* 0x57e */ { 0xd8, { NIB1__, NIB2__, NIB0__, NIB3__ } , 0, 0 }, | |
| 728 | /* 0x580 */ { 0x0c, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 729 | /* 0x582 */ { 0x8e, { NIB3__, NIB2__, NIB1__, NIB0__ } , 0, 0 }, | |
| 730 | /* 0x584 */ { 0x22, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 731 | /* 0x586 */ { 0x00, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 732 | /* 0x588 */ { 0x04, { NIB0__, NIB3__, NIB1__, NIB2__ } , 1, 1 }, | |
| 733 | /* 0x58a */ { 0x22, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 0 }, | |
| 734 | /* 0x58c */ { 0xe8, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 735 | /* 0x58e */ { 0x74, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 736 | /* 0x590 */ { 0x0e, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 737 | /* 0x592 */ { 0x66, { BLANK_, NIB2__, NIB3__, NIB1__ } , 1, 1 }, | |
| 738 | /* 0x594 */ { 0x40, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 739 | /* 0x596 */ { 0xc8, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 740 | /* 0x598 */ { 0x70, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 741 | /* 0x59a */ { 0x16, { NIB0__, NIB1__, NIB3__, NIB2__ } , 1, 0 }, | |
| 742 | /* 0x59c */ { 0x12, { NIB0__, NIB3__, NIB2__, NIB1__ } , 0, 0 }, | |
| 743 | /* 0x59e */ { 0x36, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 744 | /* 0x5a0 */ { 0x5e, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 745 | /* 0x5a2 */ { 0x24, { NIB0__, NIB3__, NIB1__, NIB2__ } , 0, 1 }, | |
| 746 | /* 0x5a4 */ { 0xce, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 747 | /* 0x5a6 */ { 0xb0, { NIB3__, NIB2__, NIB0__, NIB1__ } , 1, 0 }, | |
| 748 | /* 0x5a8 */ { 0xf2, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 749 | /* 0x5aa */ { 0x98, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 750 | /* 0x5ac */ { 0x6e, { NIB0__, NIB2__, NIB3__, NIB1__ } , 1, 1 }, | |
| 751 | /* 0x5ae */ { 0xdc, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 752 | /* 0x5b0 */ { 0xc4, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 753 | /* 0x5b2 */ { INPUT_PORT_B , { NIB0__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 754 | /* 0x5b4 */ { 0xe0, { NIB1__, NIB3__, NIB0__, NIB2__ } , 0, 0 }, | |
| 755 | /* 0x5b6 */ { 0x92, { NIB1__, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 756 | /* 0x5b8 */ { 0x4e, { NIB0__, NIB2__, NIB3__, NIB1__ } , 1, 0 }, | |
| 757 | /* 0x5ba */ { 0xf4, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 758 | /* 0x5bc */ { 0x78, { NIB2__, NIB1__, NIB0__, NIB3__ } , 1, 0 }, | |
| 759 | /* 0x5be */ { 0x58, { NIB3__, NIB0__, NIB2__, NIB1__ } , 0, 1 }, | |
| 760 | /* 0x5c0 */ { 0xfe, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 761 | /* 0x5c2 */ { 0x4a, { NIB1__, NIB3__, NIB0__, NIB2__ } , 1, 0 }, | |
| 762 | /* 0x5c4 */ { 0x3a, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 763 | /* 0x5c6 */ { 0x2c, { NIB0__, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 764 | /* 0x5c8 */ { 0x96, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 1 }, | |
| 765 | /* 0x5ca */ { 0x20, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 766 | /* 0x5cc */ { 0xc6, { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 0 }, | |
| 767 | /* 0x5ce */ { 0xa8, { NIB3__, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 768 | /* 0x5d0 */ { 0xe2, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 769 | /* 0x5d2 */ { 0x66, { NIB2__, NIB3__, NIB1__, NIB0__ } , 1, 0 }, | |
| 770 | /* 0x5d4 */ { 0xf4, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 771 | /* 0x5d6 */ { 0xec, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 772 | /* 0x5d8 */ { 0xbe, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 773 | /* 0x5da */ { 0xe8, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 774 | /* 0x5dc */ { 0x6e, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 775 | /* 0x5de */ { 0x1e, { BLANK_, BLANK_, BLANK_, NIB3__ } , 1, 0 }, | |
| 776 | /* 0x5e0 */ { 0x14, { NIB2__, NIB1__, NIB0__, NIB3__ } , 0, 0 }, | |
| 777 | /* 0x5e2 */ { 0x84, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 778 | /* 0x5e4 */ { 0xa0, { NIB0__, NIB3__, NIB1__, NIB2__ } , 1, 0 }, | |
| 779 | /* 0x5e6 */ { 0x34, { NIB3__, NIB2__, NIB0__, NIB1__ } , 1, 1 }, | |
| 780 | /* 0x5e8 */ { 0xe4, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 781 | /* 0x5ea */ { 0x58, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 782 | /* 0x5ec */ { INPUT_PORT_B , { NIB2__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 783 | /* 0x5ee */ { 0x42, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 784 | /* 0x5f0 */ { 0x8c, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 785 | /* 0x5f2 */ { 0x10, { NIB0__, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 786 | /* 0x5f4 */ { INPUT_PORT_C , { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 0 }, // dc.w $05F4 ; 0x0100 | |
| 787 | /* 0x5f6 */ { 0x04, { NIB1__, NIB0__, NIB3__, NIB2__ } , 1, 0 }, | |
| 788 | /* 0x5f8 */ { 0x4e, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 789 | /* 0x5fa */ { 0xd2, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 790 | /* 0x5fc */ { 0x7e, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 791 | /* 0x5fe */ { 0xcc, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 792 | /* 0x600 */ { 0xc6, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 1 }, | |
| 793 | /* 0x602 */ { 0x20, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 794 | /* 0x604 */ { 0x36, { NIB2__, NIB1__, NIB3__, NIB0__ } , 1, 1 }, | |
| 795 | /* 0x606 */ { 0xfc, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 796 | /* 0x608 */ { 0x1c, { NIB0__, NIB3__, NIB2__, NIB1__ } , 1, 0 }, | |
| 797 | /* 0x60a */ { 0xca, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 798 | /* 0x60c */ { INPUT_PORT_A , { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 0 }, | |
| 799 | /* 0x60e */ { 0xa0, { BLANK_, NIB2__, NIB3__, NIB1__ } , 0, 0 }, | |
| 800 | /* 0x610 */ { 0xa4, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 801 | /* 0x612 */ { 0x64, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 802 | /* 0x614 */ { 0x96, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 803 | /* 0x616 */ { 0x7e, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 804 | /* 0x618 */ { 0x0c, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 805 | /* 0x61a */ { 0x38, { NIB3__, NIB0__, NIB2__, NIB1__ } , 1, 1 }, | |
| 806 | /* 0x61c */ { 0x66, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 807 | /* 0x61e */ { 0x22, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 808 | /* 0x620 */ { 0x1a, { NIB1__, NIB0__, NIB2__, NIB3__ } , 1, 0 }, | |
| 809 | /* 0x622 */ { 0xae, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 810 | /* 0x624 */ { 0x9a, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 811 | /* 0x626 */ { 0x4e, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 812 | /* 0x628 */ { 0x5a, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 813 | /* 0x62a */ { 0x8a, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 814 | /* 0x62c */ { INPUT_PORT_A , { NIB1__, NIB2__, BLANK_, NIB3__ } , 0, 1 }, // dc.w $062C ; nand | |
| 815 | /* 0x62e */ { 0x58, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 816 | /* 0x630 */ { INPUT_PORT_B , { NIB0__, BLANK_, BLANK_, BLANK_ } , 0, 1 }, // dc.w $0630 ; nand | |
| 817 | /* 0x632 */ { 0x6a, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 818 | /* 0x634 */ { 0xc2, { NIB2__, NIB0__, NIB1__, NIB3__ } , 1, 0 }, | |
| 819 | /* 0x636 */ { 0xc4, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 820 | /* 0x638 */ { 0x94, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 821 | /* 0x63a */ { 0x3c, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 822 | /* 0x63c */ { 0x74, { NIB0__, NIB3__, NIB1__, NIB2__ } , 1, 1 }, | |
| 823 | /* 0x63e */ { 0x0a, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 824 | /* 0x640 */ { 0x30, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 825 | /* 0x642 */ { 0x68, { NIB1__, NIB0__, NIB2__, NIB3__ } , 1, 0 }, | |
| 826 | /* 0x644 */ { 0x40, { NIB2__, NIB3__, NIB1__, NIB0__ } , 0, 1 }, | |
| 827 | /* 0x646 */ { 0xda, { NIB2__, NIB3__, NIB1__, NIB0__ } , 0, 0 }, | |
| 828 | /* 0x648 */ { 0x60, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 829 | /* 0x64a */ { 0xde, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 830 | /* 0x64c */ { 0x04, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 831 | /* 0x64e */ { 0x86, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 832 | /* 0x650 */ { 0x78, { BLANK_, NIB2__, NIB3__, NIB1__ } , 1, 0 }, | |
| 833 | /* 0x652 */ { 0x4a, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 834 | /* 0x654 */ { 0x4c, { NIB1__, NIB2__, NIB0__, NIB3__ } , 1, 0 }, | |
| 835 | /* 0x656 */ { 0x2e, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 836 | /* 0x658 */ { 0xbc, { NIB2__, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 837 | /* 0x65a */ { 0xc0, { NIB3__, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 838 | /* 0x65c */ { 0x44, { NIB1__, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 839 | /* 0x65e */ { 0x9c, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 840 | /* 0x660 */ { 0x48, { NIB2__, NIB1__, NIB3__, BLANK_ } , 0, 1 }, | |
| 841 | /* 0x662 */ { 0x8c, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 842 | /* 0x664 */ { 0x9e, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 843 | /* 0x666 */ { 0xfe, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 844 | /* 0x668 */ { 0x5e, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 845 | /* 0x66a */ { 0x16, { NIB2__, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 846 | /* 0x66c */ { 0xdc, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 847 | /* 0x66e */ { 0xec, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 848 | /* 0x670 */ { 0xf4, { NIB1R1, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 849 | /* 0x672 */ { 0x6c, { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 1 }, | |
| 850 | /* 0x674 */ { INPUT_PORT_C , { NIB1__, NIB2__, NIB3__, BLANK_ } , 0, 0 }, // dc.w $0674 ; 0x0010 | |
| 851 | /* 0x676 */ { 0xd2, { NIB0__, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 852 | /* 0x678 */ { 0x72, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 853 | /* 0x67a */ { 0x28, { NIB0__, NIB3__, NIB1__, NIB2__ } , 0, 0 }, | |
| 854 | /* 0x67c */ { 0x1e, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 855 | /* 0x67e */ { INPUT_PORT_B , { NIB3R1, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 856 | /* 0x680 */ { 0x7a, { NIB0__, NIB3__, NIB1__, NIB2__ } , 1, 1 }, | |
| 857 | /* 0x682 */ { 0xba, { NIB3__, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 858 | /* 0x684 */ { 0xd8, { NIB0__, NIB3__, NIB2__, NIB1__ } , 0, 0 }, | |
| 859 | /* 0x686 */ { 0x46, { NIB1__, NIB3__, NIB0__, NIB2__ } , 0, 0 }, | |
| 860 | /* 0x688 */ { 0xe4, { NIB1__, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 861 | /* 0x68a */ { 0xd0, { NIB2__, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 862 | /* 0x68c */ { 0x50, { NIB1R2, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 863 | /* 0x68e */ { 0x92, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 864 | /* 0x690 */ { 0x10, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 865 | /* 0x692 */ { 0x88, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 866 | /* 0x694 */ { 0xf2, { NIB2__, NIB0__, NIB1__, NIB3__ } , 0, 0 }, | |
| 867 | /* 0x696 */ { 0xce, { NIB2__, NIB1__, BLANK_, NIB3__ } , 1, 0 }, | |
| 868 | /* 0x698 */ { 0x12, { NIB2__, NIB1__, BLANK_, NIB3__ } , 1, 1 }, | |
| 869 | /* 0x69a */ { 0x3e, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 870 | /* 0x69c */ { 0x06, { NIB2__, NIB1__, NIB0__, NIB3__ } , 1, 1 }, | |
| 871 | /* 0x69e */ { 0xe8, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 0, 0 }, | |
| 872 | /* 0x6a0 */ { 0xb2, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 0, 0 }, | |
| 873 | /* 0x6a2 */ { 0x28, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 874 | /* 0x6a4 */ { 0xa0, { NIB2__, NIB1__, NIB3__, BLANK_ } , 0, 0 }, | |
| 875 | /* 0x6a6 */ { 0xe4, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 876 | /* 0x6a8 */ { 0x32, { NIB3__, NIB2__, NIB1__, NIB0__ } , 1, 1 }, | |
| 877 | /* 0x6aa */ { 0x20, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 878 | /* 0x6ac */ { 0xf6, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 879 | /* 0x6ae */ { 0xf2, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 880 | /* 0x6b0 */ { 0x10, { NIB2__, NIB1__, NIB3__, BLANK_ } , 1, 1 }, | |
| 881 | /* 0x6b2 */ { 0xb4, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 882 | /* 0x6b4 */ { 0xa0, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 883 | /* 0x6b6 */ { 0x30, { NIB0__, NIB3__, NIB2__, NIB1__ } , 1, 1 }, | |
| 884 | /* 0x6b8 */ { 0xea, { NIB1__, NIB2__, NIB0__, NIB3__ } , 1, 0 }, | |
| 885 | /* 0x6ba */ { 0xf6, { NIB2__, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 886 | /* 0x6bc */ { 0x42, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 887 | /* 0x6be */ { INPUT_PORT_A , { NIB1__, NIB2__, BLANK_, NIB3__ } , 1, 0 }, // dc.w $06BE ; xor | |
| 888 | /* 0x6c0 */ { 0x08, { NIB3__, NIB1__, NIB2__, NIB0__ } , 0, 1 }, | |
| 889 | /* 0x6c2 */ { 0x54, { NIB2__, NIB1__, BLANK_, NIB3__ } , 1, 1 }, | |
| 890 | /* 0x6c4 */ { 0x66, { NIB2__, NIB1__, BLANK_, NIB3__ } , 0, 1 }, | |
| 891 | /* 0x6c6 */ { 0xcc, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 892 | /* 0x6c8 */ { 0x52, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 893 | /* 0x6ca */ { 0xd4, { NIB2__, NIB1__, NIB3__, NIB0__ } , 0, 0 }, | |
| 894 | /* 0x6cc */ { INPUT_PORT_C , { NIB0R1, NIB1__, NIB2__, NIB3__ } , 0, 0 }, // dc.w $06CC ; 0x0002 | |
| 895 | /* 0x6ce */ { 0x0e, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 896 | /* 0x6d0 */ { 0xb2, { BLANK_, BLANK_, BLANK_, NIB3__ } , 0, 0 }, | |
| 897 | /* 0x6d2 */ { 0xa2, { NIB0__, NIB3__, NIB1__, NIB2__ } , 0, 0 }, | |
| 898 | /* 0x6d4 */ { 0xb4, { NIB2__, NIB1__, NIB3__, BLANK_ } , 0, 0 }, | |
| 899 | /* 0x6d6 */ { INPUT_PORT_A , { NIB0__, NIB1__, NIB2__, NIB3__ } , 1, 0 }, // dc.w $06D6 ; xor | |
| 900 | /* 0x6d8 */ { 0xac, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 1, 1 }, | |
| 901 | /* 0x6da */ { 0x24, { BLANK_, NIB2__, NIB3__, NIB1__ } , 0, 1 }, | |
| 902 | /* 0x6dc */ { 0xbe, { NIB1__, NIB0__, NIB3__, NIB2__ } , 1, 0 }, | |
| 903 | /* 0x6de */ { 0xa8, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 904 | /* 0x6e0 */ { 0x2c, { NIB2__, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 905 | /* 0x6e2 */ { 0x90, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 906 | /* 0x6e4 */ { 0x98, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 907 | /* 0x6e6 */ { 0x70, { NIB2__, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 908 | /* 0x6e8 */ { 0xb6, { BLANK_, NIB3__, BLANK_, NIB2__ } , 0, 1 }, | |
| 909 | /* 0x6ea */ { 0xb8, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 1, 1 }, | |
| 910 | /* 0x6ec */ { 0x66, { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 0 }, | |
| 911 | /* 0x6ee */ { 0x2a, { NIB0__, NIB2__, NIB3__, NIB1__ } , 1, 0 }, | |
| 912 | /* 0x6f0 */ { 0x62, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 913 | /* 0x6f2 */ { 0xc8, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 0, 1 }, | |
| 914 | /* 0x6f4 */ { 0x14, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 915 | /* 0x6f6 */ { 0xa6, { NIB2__, NIB3__, NIB1__, NIB0__ } , 1, 1 }, | |
| 916 | /* 0x6f8 */ { 0xe6, { NIB2__, NIB1__, BLANK_, NIB3__ } , 0, 0 }, | |
| 917 | /* 0x6fa */ { 0xee, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 918 | /* 0x6fc */ { 0x82, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 919 | /* 0x6fe */ { 0x26, { NIB1__, NIB2__, NIB0__, NIB3__ } , 1, 1 }, | |
| 920 | /* 0x700 */ { 0x66, { BLANK_, NIB3__, BLANK_, NIB2__ } , 1, 0 }, | |
| 921 | /* 0x702 */ { 0x2c, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 922 | /* 0x704 */ { 0x7c, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 923 | /* 0x706 */ { 0x18, { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 0 }, | |
| 924 | /* 0x708 */ { 0xda, { BLANK_, NIB3__, BLANK_, NIB2__ } , 0, 0 }, | |
| 925 | /* 0x70a */ { 0xde, { NIB2R1, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 926 | /* 0x70c */ { 0x6e, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 927 | /* 0x70e */ { 0x26, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 928 | /* 0x710 */ { 0xca, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 0 }, | |
| 929 | /* 0x712 */ { 0xf0, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 930 | /* 0x714 */ { 0x82, { NIB3__, NIB2__, BLANK_, BLANK_ } , 1, 1 }, | |
| 931 | /* 0x716 */ { 0xc0, { NIB0__, NIB3__, NIB1__, NIB2__ } , 1, 0 }, | |
| 932 | /* 0x718 */ { 0x8e, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 933 | /* 0x71a */ { 0x20, { NIB3__, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 934 | /* 0x71c */ { 0x4e, { NIB3__, NIB2__, NIB0__, NIB1__ } , 0, 1 }, | |
| 935 | /* 0x71e */ { 0xe0, { BLANK_, BLANK_, BLANK_, NIB3__ } , 1, 1 }, | |
| 936 | /* 0x720 */ { 0x66, { NIB0__, NIB1__, NIB3__, NIB2__ } , 0, 1 }, | |
| 937 | /* 0x722 */ { 0xdc, { NIB1__, NIB2__, NIB3__, BLANK_ } , 1, 1 }, | |
| 938 | /* 0x724 */ { 0xb2, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 939 | /* 0x726 */ { INPUT_PORT_C , { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, // dc.w $0726 ; 0x0001 | |
| 940 | /* 0x728 */ { 0xd4, { NIB2__, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 941 | /* 0x72a */ { 0x86, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 942 | /* 0x72c */ { 0x78, { NIB0__, NIB2__, NIB3__, NIB1__ } , 0, 0 }, | |
| 943 | /* 0x72e */ { 0xe4, { NIB1R2, NIB2__, NIB3__, BLANK_ } , 0, 1 }, | |
| 944 | /* 0x730 */ { 0x3e, { NIB3R1, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 945 | /* 0x732 */ { 0x72, { NIB1__, NIB3__, NIB0__, NIB2__ } , 0, 0 }, | |
| 946 | /* 0x734 */ { 0x64, { NIB2__, NIB1__, NIB3__, NIB0__ } , 1, 0 }, | |
| 947 | /* 0x736 */ { 0x68, { BLANK_, BLANK_, BLANK_, NIB3__ } , 0, 1 }, | |
| 948 | /* 0x738 */ { 0x54, { NIB3R1, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 949 | /* 0x73a */ { 0x00, { NIB2R3, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 950 | /* 0x73c */ { INPUT_PORT_A , { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, // dc.w $073C | |
| 951 | /* 0x73e */ { 0xae, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 952 | /* 0x740 */ { 0x6a, { NIB1__, NIB2__, NIB3__, NIB0__ } , 0, 0 }, | |
| 953 | /* 0x742 */ { 0x2e, { NIB0__, NIB3__, NIB2__, NIB1__ } , 0, 0 }, | |
| 954 | /* 0x744 */ { 0xf6, { NIB2__, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 955 | /* 0x746 */ { INPUT_PORT_C , { NIB0__, NIB1__, NIB2__, NIB3__ } , 1, 0 }, // dc.w $0746 ; 0x0001 dc.w $0746 ; 0x0001 ; xor | |
| 956 | /* 0x748 */ { 0x44, { NIB0R3, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 957 | /* 0x74a */ { 0x14, { NIB2__, NIB1__, NIB0__, NIB3__ } , 0, 1 }, | |
| 958 | /* 0x74c */ { 0xd2, { BLANK_, BLANK_, BLANK_, NIB3__ } , 1, 0 }, | |
| 959 | /* 0x74e */ { INPUT_PORT_C , { NIB2__, NIB3__, NIB0__, NIB1__ } , 0, 0 }, // dc.w $074E ; 0x0100 | |
| 960 | /* 0x750 */ { 0xaa, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 961 | /* 0x752 */ { 0xbe, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 962 | /* 0x754 */ { 0x76, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 963 | /* 0x756 */ { 0x60, { NIB3R1, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 964 | /* 0x758 */ { 0x70, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 965 | /* 0x75a */ { 0x4c, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 1, 1 }, | |
| 966 | /* 0x75c */ { 0xbc, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 967 | /* 0x75e */ { 0x7e, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 968 | /* 0x760 */ { 0x32, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 0, 1 }, | |
| 969 | /* 0x762 */ { 0x88, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 970 | /* 0x764 */ { 0xe2, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 971 | /* 0x766 */ { 0x66, { NIB2__, NIB1__, NIB0__, NIB3__ } , 0, 0 }, | |
| 972 | /* 0x768 */ { 0x16, { NIB0__, NIB3__, NIB2__, NIB1__ } , 0, 1 }, | |
| 973 | /* 0x76a */ { 0xfa, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 974 | /* 0x76c */ { 0x52, { NIB0R1, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 975 | /* 0x76e */ { 0xd6, { NIB0__, NIB3__, NIB1__, NIB2__ } , 0, 1 }, | |
| 976 | /* 0x770 */ { INPUT_PORT_B , { NIB1__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 977 | /* 0x772 */ { 0xc4, { NIB1__, NIB3__, NIB0__, NIB2__ } , 1, 0 }, | |
| 978 | /* 0x774 */ { 0x38, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 979 | /* 0x776 */ { 0x6c, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 1 }, | |
| 980 | /* 0x778 */ { 0xfc, { NIB2__, NIB1__, NIB3__, BLANK_ } , 1, 1 }, | |
| 981 | /* 0x77a */ { 0x84, { NIB0__, NIB2__, NIB3__, NIB1__ } , 0, 1 }, | |
| 982 | /* 0x77c */ { 0xb6, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 983 | /* 0x77e */ { 0x62, { NIB3__, NIB1__, NIB2__, NIB0__ } , 0, 0 }, | |
| 984 | /* 0x780 */ { 0xb8, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 985 | /* 0x782 */ { 0xa2, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 986 | /* 0x784 */ { 0x8a, { NIB2__, NIB0__, NIB1__, NIB3__ } , 0, 0 }, | |
| 987 | /* 0x786 */ { 0x3a, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 988 | /* 0x788 */ { 0xf4, { NIB2__, NIB1__, NIB0__, NIB3__ } , 1, 1 }, | |
| 989 | /* 0x78a */ { 0x40, { NIB1__, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 990 | /* 0x78c */ { 0x7a, { NIB1__, NIB2__, NIB3__, BLANK_ } , 0, 0 }, | |
| 991 | /* 0x78e */ { 0x1c, { NIB2R3, NIB3__, NIB0__, NIB1__ } , 1, 0 }, | |
| 992 | /* 0x790 */ { 0x04, { NIB0R2, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 993 | /* 0x792 */ { 0x1a, { NIB2R1, NIB3__, NIB0__, NIB1__ } , 1, 1 }, | |
| 994 | /* 0x794 */ { 0x0e, { NIB1R3, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 995 | /* 0x796 */ { 0x30, { NIB3__, NIB0__, NIB2__, NIB1__ } , 1, 0 }, | |
| 996 | /* 0x798 */ { 0x50, { NIB3__, NIB2__, NIB0__, NIB1__ } , 1, 1 }, | |
| 997 | /* 0x79a */ { 0xc8, { NIB3R1, NIB0__, NIB1__, NIB2__ } , 1, 0 }, | |
| 998 | /* 0x79c */ { 0xc6, { NIB1__, NIB2__, NIB0__, NIB3__ } , 0, 1 }, | |
| 999 | /* 0x79e */ { 0x12, { NIB1__, NIB0__, NIB3__, NIB2__ } , 1, 1 }, | |
| 1000 | /* 0x7a0 */ { 0x6e, { NIB0__, NIB1__, NIB3__, NIB2__ } , 0, 0 }, | |
| 1001 | /* 0x7a2 */ { 0x56, { NIB2__, NIB1__, BLANK_, NIB3__ } , 1, 0 }, | |
| 1002 | /* 0x7a4 */ { 0xe2, { NIB2__, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 1003 | /* 0x7a6 */ { 0x00, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 0, 1 }, | |
| 1004 | /* 0x7a8 */ { 0xfa, { NIB3__, NIB1__, NIB2__, NIB0__ } , 1, 0 }, | |
| 1005 | /* 0x7aa */ { 0x76, { NIB1R3, NIB2__, NIB3__, NIB0__ } , 1, 0 }, | |
| 1006 | /* 0x7ac */ { 0x8e, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 1007 | /* 0x7ae */ { 0xaa, { NIB1__, NIB0__, NIB3__, NIB2__ } , 0, 0 }, | |
| 1008 | /* 0x7b0 */ { 0x80, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 1009 | /* 0x7b2 */ { 0x3a, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 1010 | /* 0x7b4 */ { 0xf8, { BLANK_, NIB3__, BLANK_, BLANK_ } , 1, 0 }, | |
| 1011 | /* 0x7b6 */ { 0x02, { NIB0__, NIB2__, NIB3__, NIB1__ } , 1, 1 }, | |
| 1012 | /* 0x7b8 */ { 0x84, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 1013 | /* 0x7ba */ { 0xd0, { NIB0__, NIB1__, NIB3__, NIB2__ } , 1, 1 }, | |
| 1014 | /* 0x7bc */ { 0xd6, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 1 }, | |
| 1015 | /* 0x7be */ { 0x66, { NIB2__, NIB1__, NIB0__, NIB3__ } , 1, 0 }, | |
| 1016 | /* 0x7c0 */ { 0xea, { NIB3R2, NIB0__, NIB1__, NIB2__ } , 0, 0 }, | |
| 1017 | /* 0x7c2 */ { 0xe8, { NIB3__, NIB2__, NIB0__, NIB1__ } , 0, 0 }, | |
| 1018 | /* 0x7c4 */ { 0x9c, { NIB2R2, NIB3__, BLANK_, BLANK_ } , 0, 0 }, | |
| 1019 | /* 0x7c6 */ { 0x02, { NIB3__, BLANK_, BLANK_, BLANK_ } , 1, 0 }, | |
| 1020 | /* 0x7c8 */ { 0x9a, { BLANK_, NIB2__, NIB3__, NIB1__ } , 1, 1 }, | |
| 1021 | /* 0x7ca */ { 0xa0, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 1022 | /* 0x7cc */ { 0x0c, { NIB3R3, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 1023 | /* 0x7ce */ { 0x80, { NIB3R3, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 1024 | /* 0x7d0 */ { 0xec, { NIB1__, NIB2__, NIB0__, NIB3__ } , 0, 0 }, | |
| 1025 | /* 0x7d2 */ { 0x1e, { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 1 }, | |
| 1026 | /* 0x7d4 */ { 0xb4, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 1027 | /* 0x7d6 */ { 0x28, { NIB3__, NIB2__, NIB1__, NIB0__ } , 0, 1 }, | |
| 1028 | /* 0x7d8 */ { 0xee, { NIB1__, NIB2__, BLANK_, NIB3__ } , 1, 1 }, | |
| 1029 | /* 0x7da */ { 0x56, { NIB2__, NIB0__, NIB1__, NIB3__ } , 1, 1 }, | |
| 1030 | /* 0x7dc */ { INPUT_PORT_A , { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 1 }, // dc.w $07DC ; nand | |
| 1031 | /* 0x7de */ { 0x2a, { NIB3__, NIB2__, NIB1__, NIB0__ } , 1, 1 }, | |
| 1032 | /* 0x7e0 */ { 0xf8, { NIB3__, NIB0__, NIB1__, NIB2__ } , 1, 1 }, | |
| 1033 | /* 0x7e2 */ { 0x96, { NIB1__, NIB2__, BLANK_, NIB3__ } , 1, 0 }, | |
| 1034 | /* 0x7e4 */ { 0x34, { BLANK_, NIB3__, BLANK_, NIB2__ } , 1, 1 }, | |
| 1035 | /* 0x7e6 */ { 0x36, { NIB1R1, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 1036 | /* 0x7e8 */ { 0x4a, { NIB0__, NIB1__, NIB2__, NIB3__ } , 1, 0 }, | |
| 1037 | /* 0x7ea */ { 0x0a, { NIB3__, BLANK_, BLANK_, BLANK_ } , 0, 0 }, | |
| 1038 | /* 0x7ec */ { 0x66, { NIB3__, NIB2__, NIB0__, NIB1__ } , 1, 0 }, | |
| 1039 | /* 0x7ee */ { 0xc2, { NIB1R1, NIB2__, NIB3__, BLANK_ } , 1, 0 }, | |
| 1040 | /* 0x7f0 */ { 0xba, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 1041 | /* 0x7f2 */ { 0x5e, { NIB3__, NIB2__, BLANK_, BLANK_ } , 0, 1 }, | |
| 1042 | /* 0x7f4 */ { 0x5c, { NIB2__, NIB1__, NIB3__, BLANK_ } , 1, 0 }, | |
| 1043 | /* 0x7f6 */ { 0xac, { NIB0__, NIB1__, NIB2__, NIB3__ } , 0, 0 }, | |
| 1044 | /* 0x7f8 */ { 0x98, { NIB1__, NIB2__, NIB3__, NIB0__ } , 0, 1 }, | |
| 1045 | /* 0x7fa */ { 0x80, { NIB3R2, BLANK_, BLANK_, BLANK_ } , 1, 1 }, | |
| 1046 | /* 0x7fc */ { INPUT_PORT_C , { BLANK_, NIB3__, BLANK_, BLANK_ } , 0, 0 }, // dc.w $07FC ; Bit not present | |
| 1047 | /* 0x7fe */ { 0xd8, { NIB2R2, NIB3__, NIB0__, NIB1__ } , 1, 1 } | |
| 1048 | }; | |
| 1048 | 1049 | |
| 1049 | }; | |
| 1050 | 1050 | |
| 1051 | 1051 | |
| 1052 | ||
| 1053 | 1052 | const device_type DECO104PROT = &device_creator<deco104_device>; |
| 1054 | 1053 | |
| 1055 | 1054 | |
| r25360 | r25361 | |
| 1083 | 1082 | { |
| 1084 | 1083 | deco_146_base_device::device_reset(); |
| 1085 | 1084 | } |
| 1086 | ||
| 1087 | ||
| 1088 |
| r25360 | r25361 | |
|---|---|---|
| 95 | 95 | |
| 96 | 96 | |
| 97 | 97 | deco146port_xx port_table[] = { |
| 98 | ||
| 99 | ||
| 100 | 98 | /* 0x000 */ { 0x08a, { NIB1__, NIB2__, NIB3__, BLANK_ }, 0, 1 }, |
| 101 | 99 | /* 0x002 */ { 0x0aa, { NIB3__, NIB2__, NIB0__, NIB1__ }, 0, 0 }, |
| 102 | 100 | /* 0x004 */ { 0x018, { NIB2R2, NIB3__, BLANK_, BLANK_ }, 0, 1 }, |
| r25360 | r25361 | |
|---|---|---|
| 61 | 61 | m_c2p_input_buffer[i] = 0; |
| 62 | 62 | m_c2p_output_buffer[i] = 0; |
| 63 | 63 | } |
| 64 | ||
| 64 | ||
| 65 | 65 | for (int i = 0; i < 2; i++) |
| 66 | 66 | { |
| 67 | 67 | m_cdrom_status[i] = 0; |
| r25360 | r25361 | |
|---|---|---|
| 25 | 25 | |
| 26 | 26 | READ64_MEMBER(naomi_state::naomi_biose_idle_skip_r ) |
| 27 | 27 | { |
| 28 | // if (space.device().safe_pc()==0xc04173c) | |
| 29 | // space.device().execute().spin_until_time(attotime::from_usec(500)); | |
| 28 | // if (space.device().safe_pc()==0xc04173c) | |
| 29 | // space.device().execute().spin_until_time(attotime::from_usec(500)); | |
| 30 | 30 | //space.device().execute().spin_until_interrupt(); |
| 31 | 31 | // else |
| 32 | 32 | // printf("%08x\n", space.device().safe_pc()); |
| r25360 | r25361 | |
| 36 | 36 | |
| 37 | 37 | READ64_MEMBER(naomi_state::naomi_biosh_idle_skip_r ) |
| 38 | 38 | { |
| 39 | // if (space.device().safe_pc()==0xc045ffc) | |
| 40 | // space.device().execute().spin_until_time(attotime::from_usec(500)); | |
| 39 | // if (space.device().safe_pc()==0xc045ffc) | |
| 40 | // space.device().execute().spin_until_time(attotime::from_usec(500)); | |
| 41 | 41 | |
| 42 | 42 | // printf("%08x\n", space.device().safe_pc()); |
| 43 | 43 | |
| r25360 | r25361 | |
| 46 | 46 | |
| 47 | 47 | READ64_MEMBER(naomi_state::naomi2_biose_idle_skip_r ) |
| 48 | 48 | { |
| 49 | // if (space.device().safe_pc()==0xc04637c) | |
| 50 | // space.device().execute().spin_until_time(attotime::from_usec(500)); | |
| 49 | // if (space.device().safe_pc()==0xc04637c) | |
| 50 | // space.device().execute().spin_until_time(attotime::from_usec(500)); | |
| 51 | 51 | //space.device().execute().spin_until_interrupt(); |
| 52 | 52 | // else |
| 53 | 53 | // printf("%08x\n", space.device().safe_pc()); |
| r25360 | r25361 | |
| 240 | 240 | |
| 241 | 241 | READ64_MEMBER(naomi_state::naomigd_ggxxsla_idle_skip_r ) |
| 242 | 242 | { |
| 243 | // if (space.device().safe_pc()==0x0c0c9adc) | |
| 244 | // space.device().execute().spin_until_time(attotime::from_usec(500)); | |
| 243 | // if (space.device().safe_pc()==0x0c0c9adc) | |
| 244 | // space.device().execute().spin_until_time(attotime::from_usec(500)); | |
| 245 | 245 | |
| 246 | 246 | return dc_ram[0x1aae18/8]; |
| 247 | 247 | } |
| r25360 | r25361 | |
| 254 | 254 | |
| 255 | 255 | READ64_MEMBER(naomi_state::naomigd_ggxx_idle_skip_r ) |
| 256 | 256 | { |
| 257 | // if (space.device().safe_pc()==0xc0b5c3c) // or 0xc0bab0c | |
| 258 | // space.device().execute().spin_until_time(attotime::from_usec(500)); | |
| 257 | // if (space.device().safe_pc()==0xc0b5c3c) // or 0xc0bab0c | |
| 258 | // space.device().execute().spin_until_time(attotime::from_usec(500)); | |
| 259 | 259 | |
| 260 | 260 | return dc_ram[0x1837b8/8]; |
| 261 | 261 | } |
| r25360 | r25361 | |
| 269 | 269 | |
| 270 | 270 | READ64_MEMBER(naomi_state::naomigd_ggxxrl_idle_skip_r ) |
| 271 | 271 | { |
| 272 | // if (space.device().safe_pc()==0xc0b84bc) // or 0xc0bab0c | |
| 273 | // space.device().execute().spin_until_time(attotime::from_usec(500)); | |
| 272 | // if (space.device().safe_pc()==0xc0b84bc) // or 0xc0bab0c | |
| 273 | // space.device().execute().spin_until_time(attotime::from_usec(500)); | |
| 274 | 274 | |
| 275 | 275 | //printf("%08x\n", space.device().safe_pc()); |
| 276 | 276 | |
| r25360 | r25361 | |
| 286 | 286 | /* at least speeds up the annoying copyright screens ;-) */ |
| 287 | 287 | READ64_MEMBER(naomi_state::naomigd_sfz3ugd_idle_skip_r ) |
| 288 | 288 | { |
| 289 | // if (space.device().safe_pc()==0xc36a2dc) | |
| 290 | // space.device().execute().spin_until_time(attotime::from_usec(500)); | |
| 289 | // if (space.device().safe_pc()==0xc36a2dc) | |
| 290 | // space.device().execute().spin_until_time(attotime::from_usec(500)); | |
| 291 | 291 | |
| 292 | 292 | return dc_ram[0x5dc900/8]; |
| 293 | 293 | } |
| r25360 | r25361 | |
| 331 | 331 | |
| 332 | 332 | READ64_MEMBER(naomi_state::hotd2_idle_skip_r ) |
| 333 | 333 | { |
| 334 | // if (space.device().safe_pc()==0xc0cfcbc) | |
| 335 | // space.device().execute().spin_until_time(attotime::from_usec(500)); | |
| 334 | // if (space.device().safe_pc()==0xc0cfcbc) | |
| 335 | // space.device().execute().spin_until_time(attotime::from_usec(500)); | |
| 336 | 336 | //space.device().execute().spin_until_interrupt(); |
| 337 | 337 | // else |
| 338 | 338 | // printf("%08x\n", space.device().safe_pc()); |
| r25360 | r25361 | |
|---|---|---|
| 871 | 871 | |
| 872 | 872 | //------------------------------------------------- |
| 873 | 873 | // unlock_read/unlock_write - unlock read/write |
| 874 | // | |
| 874 | // handlers | |
| 875 | 875 | //------------------------------------------------- |
| 876 | 876 | |
| 877 | 877 | READ8_MEMBER(atari_eeprom_device::unlock_read) { m_unlocked = true; return space.unmap(); } |
| r25360 | r25361 | |
| 936 | 936 | |
| 937 | 937 | //------------------------------------------------- |
| 938 | 938 | // device_mconfig_additions - return machine |
| 939 | // | |
| 939 | // config fragment | |
| 940 | 940 | //------------------------------------------------- |
| 941 | 941 | |
| 942 | 942 | MACHINE_CONFIG_FRAGMENT(atari_eeprom_2804_config) |
| r25360 | r25361 | |
| 961 | 961 | |
| 962 | 962 | //------------------------------------------------- |
| 963 | 963 | // device_mconfig_additions - return machine |
| 964 | // | |
| 964 | // config fragment | |
| 965 | 965 | //------------------------------------------------- |
| 966 | 966 | |
| 967 | 967 | MACHINE_CONFIG_FRAGMENT(atari_eeprom_2816_config) |
| r25360 | r25361 | |
|---|---|---|
| 102 | 102 | |
| 103 | 103 | #define MCFG_ATARI_VAD_MOB(_config) \ |
| 104 | 104 | { astring fulltag(device->tag(), ":mob"); device_t *device; \ |
| 105 | MCFG_ATARI_MOTION_OBJECTS_ADD(fulltag, "^^screen", _config) } | |
| 105 | MCFG_ATARI_MOTION_OBJECTS_ADD(fulltag, "^^screen", _config) } | |
| 106 | 106 | |
| 107 | 107 | |
| 108 | ||
| 109 | 108 | #define MCFG_ATARI_EEPROM_2804_ADD(_tag) \ |
| 110 | 109 | MCFG_DEVICE_ADD(_tag, ATARI_EEPROM_2804, 0) |
| 111 | 110 | |
| r25360 | r25361 | |
| 202 | 201 | // device type definition |
| 203 | 202 | extern const device_type ATARI_VAD; |
| 204 | 203 | |
| 205 | class atari_vad_device : | |
| 204 | class atari_vad_device : public device_t, | |
| 206 | 205 | public device_video_interface |
| 207 | 206 | { |
| 208 | 207 | public: |
| r25360 | r25361 | |
| 298 | 297 | DECLARE_WRITE16_MEMBER(unlock_write); |
| 299 | 298 | DECLARE_READ32_MEMBER(unlock_read); |
| 300 | 299 | DECLARE_WRITE32_MEMBER(unlock_write); |
| 301 | ||
| 300 | ||
| 302 | 301 | // EEPROM read/write |
| 303 | 302 | DECLARE_READ8_MEMBER(read); |
| 304 | 303 | DECLARE_WRITE8_MEMBER(write); |
| r25360 | r25361 | |
| 310 | 309 | |
| 311 | 310 | // internal state |
| 312 | 311 | required_device<eeprom_parallel_28xx_device> m_eeprom; |
| 313 | ||
| 312 | ||
| 314 | 313 | // live state |
| 315 | bool | |
| 314 | bool m_unlocked; | |
| 316 | 315 | }; |
| 317 | 316 | |
| 318 | 317 | class atari_eeprom_2804_device : public atari_eeprom_device |
| r25360 | r25361 | |
| 337 | 336 | virtual machine_config_constructor device_mconfig_additions() const; |
| 338 | 337 | }; |
| 339 | 338 | |
| 340 | ||
| 341 | 339 | |
| 340 | ||
| 342 | 341 | /*************************************************************************** |
| 343 | 342 | TYPES & STRUCTURES |
| 344 | 343 | ***************************************************************************/ |
| r25360 | r25361 | |
|---|---|---|
| 507 | 507 | UINT16 sr = m_pvc_cartridge_ram[0xff5]; |
| 508 | 508 | |
| 509 | 509 | m_pvc_cartridge_ram[0xff6] = ((gb & 0x001e) >> 1) | |
| 510 | ((gb & 0x1e00) >> 5) | | |
| 511 | ((sr & 0x001e) << 7) | | |
| 512 | ((gb & 0x0001) << 12) | | |
| 513 | ((gb & 0x0100) << 5) | | |
| 514 | ((sr & 0x0001) << 14) | | |
| 515 | ((sr & 0x0100) << 7); | |
| 510 | ((gb & 0x1e00) >> 5) | | |
| 511 | ((sr & 0x001e) << 7) | | |
| 512 | ((gb & 0x0001) << 12) | | |
| 513 | ((gb & 0x0100) << 5) | | |
| 514 | ((sr & 0x0001) << 14) | | |
| 515 | ((sr & 0x0100) << 7); | |
| 516 | 516 | } |
| 517 | 517 | |
| 518 | 518 |
| r25360 | r25361 | |
|---|---|---|
| 312 | 312 | WRITE32_MEMBER(maple_dc_device::sb_mdapro_w) |
| 313 | 313 | { |
| 314 | 314 | } |
| 315 | ||
| 316 | ||
| 317 |
| r25360 | r25361 | |
|---|---|---|
| 571 | 571 | |
| 572 | 572 | // should be correct, note each value only appears once |
| 573 | 573 | UINT8 puzzli2_level_decode[256] = { |
| 574 | ||
| 574 | // 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , a , b , c , d , e , f , | |
| 575 | 575 | 0x32, 0x3e, 0xb2, 0x37, 0x31, 0x22, 0xd6, 0x0d, 0x35, 0x5c, 0x8d, 0x3c, 0x7a, 0x5f, 0xd7, 0xac, // 0x0 |
| 576 | // 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , x , x , | |
| 577 | 0x53, 0xff, 0xeb, 0x44, 0xe8, 0x11, 0x69, 0x77, 0xd9, 0x34, 0x36, 0x45, 0xa6, 0xe9, 0x1c, 0xc6, // 0x1 | |
| 578 | // 0 , 0 , x , x , x , 0 , x , 0 , x , 0 , 0 , 0 , 0 , x , 0 , x , | |
| 576 | // 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , x , x , | |
| 577 | 0x53, 0xff, 0xeb, 0x44, 0xe8, 0x11, 0x69, 0x77, 0xd9, 0x34, 0x36, 0x45, 0xa6, 0xe9, 0x1c, 0xc6, // 0x1 | |
| 578 | // 0 , 0 , x , x , x , 0 , x , 0 , x , 0 , 0 , 0 , 0 , x , 0 , x , | |
| 579 | 579 | 0x3b, 0xbd, 0xad, 0x2e, 0x18, 0xdf, 0xa1, 0xab, 0xdd, 0x52, 0x57, 0xc2, 0xe5, 0x0a, 0x00, 0x6d, // 0x2 |
| 580 | // 0 , 0 , 0 , 1 , 1 , 1 , 1 , x , 1 , 1 , 0 , 0 , 1 , 1 , x , 0 , | |
| 580 | // 0 , 0 , 0 , 1 , 1 , 1 , 1 , x , 1 , 1 , 0 , 0 , 1 , 1 , x , 0 , | |
| 581 | 581 | 0x67, 0x64, 0x15, 0x70, 0xb6, 0x39, 0x27, 0x78, 0x82, 0xd2, 0x71, 0xb9, 0x13, 0xf5, 0x93, 0x92, // 0x3 |
| 582 | // 0 , x , 1 , 1 , x , 1 , 1 , 1 , 1 , 1 , 1 , 1 , x , 0 , x , x , | |
| 582 | // 0 , x , 1 , 1 , x , 1 , 1 , 1 , 1 , 1 , 1 , 1 , x , 0 , x , x , | |
| 583 | 583 | 0xfa, 0xe7, 0x5e, 0xb0, 0xf6, 0xaf, 0x95, 0x8a, 0x7c, 0x73, 0xf9, 0x63, 0x86, 0xcb, 0x1a, 0x56, // 0x4 |
| 584 | // 0 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 0 , | |
| 585 | 0xf1, 0x3a, 0xae, 0x61, 0x01, 0x29, 0x97, 0x23, 0x8e, 0x5d, 0x9a, 0x65, 0x74, 0x21, 0x20, 0x40, // 0x5 | |
| 586 | // 0 , 1 , 1 , 1 , 1 , 0 , x , x , x , 0 , 0 , 1 , 1 , 1 , 1 , 1 , | |
| 587 | 0xd3, 0x05, 0xa2, 0xe1, 0xbc, 0x9e, 0x1e, 0x10, 0x14, 0x0c, 0x88, 0x9c, 0xec, 0x38, 0xb5, 0x9d, // 0x6 | |
| 588 | // 1 , 0 , 0 , x , 1 , 1 , 0 , 0 , x , 0 , x , 0 , 0 , 1 , 1 , 1 , | |
| 589 | 0x2d, 0xf7, 0x17, 0x0e, 0x84, 0xc7, 0x7d, 0xce, 0x94, 0x16, 0x48, 0xa8, 0x81, 0x6e, 0x7b, 0xd8, // 0x7 | |
| 590 | // 1 , 1 , 1 , 1 , x , 0 , x , 0 , 1 , 1 , 1 , x , x , 1 , 1 , 1 , | |
| 591 | 0xa7, 0x7f, 0x42, 0xe6, 0xa0, 0x2a, 0xef, 0xee, 0x24, 0xba, 0xb8, 0x7e, 0xc9, 0x2b, 0x90, 0xcc, // 0x8 | |
| 592 | // 1 , x , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , | |
| 593 | 0x5b, 0xd1, 0xf3, 0xe2, 0x6f, 0xed, 0x9f, 0xf0, 0x4b, 0x54, 0x8c, 0x08, 0xf8, 0x51, 0x68, 0xc8, // 0x9 | |
| 594 | // x , 0 , 0 , 0 , 0 , 0 , 0 , 0 , x , 0 , x , 0 , 0 , 0 , 0 , 1 , | |
| 595 | 0x03, 0x0b, 0xbb, 0xc1, 0xe3, 0x4d, 0x04, 0xc5, 0x8f, 0x09, 0x0f, 0xbf, 0x62, 0x49, 0x76, 0x59, // 0xa | |
| 596 | // 1 , 1 , 1 , 1 , 1 , x , 0 , 1 , 1 , 0 , x , 1 , 1 , 1 , 1 , 0 , | |
| 597 | 0x1d, 0x80, 0xde, 0x60, 0x07, 0xe0, 0x1b, 0x66, 0xa5, 0xbe, 0xcd, 0x87, 0xdc, 0xc3, 0x6b, 0x4e, // 0xb | |
| 598 | // 0 , 1 , 1 , 1 , 1 , x , 0 , x , 0 , x , 0 , 1 , 1 , 0 , 1 , 1 , | |
| 599 | 0xd0, 0xfd, 0xd4, 0x3f, 0x98, 0x96, 0x2f, 0x4c, 0xb3, 0xea, 0x2c, 0x75, 0xe4, 0xc0, 0x6c, 0x6a, // 0xc | |
| 600 | // 0 , x , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , x , 1 , 1 , 1 , | |
| 601 | 0x9b, 0xb7, 0x43, 0x8b, 0x41, 0x47, 0x02, 0xdb, 0x99, 0x3d, 0xa3, 0x79, 0x50, 0x4f, 0xb4, 0x55, // 0xd | |
| 584 | // 0 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 0 , | |
| 585 | 0xf1, 0x3a, 0xae, 0x61, 0x01, 0x29, 0x97, 0x23, 0x8e, 0x5d, 0x9a, 0x65, 0x74, 0x21, 0x20, 0x40, // 0x5 | |
| 586 | // 0 , 1 , 1 , 1 , 1 , 0 , x , x , x , 0 , 0 , 1 , 1 , 1 , 1 , 1 , | |
| 587 | 0xd3, 0x05, 0xa2, 0xe1, 0xbc, 0x9e, 0x1e, 0x10, 0x14, 0x0c, 0x88, 0x9c, 0xec, 0x38, 0xb5, 0x9d, // 0x6 | |
| 588 | // 1 , 0 , 0 , x , 1 , 1 , 0 , 0 , x , 0 , x , 0 , 0 , 1 , 1 , 1 , | |
| 589 | 0x2d, 0xf7, 0x17, 0x0e, 0x84, 0xc7, 0x7d, 0xce, 0x94, 0x16, 0x48, 0xa8, 0x81, 0x6e, 0x7b, 0xd8, // 0x7 | |
| 590 | // 1 , 1 , 1 , 1 , x , 0 , x , 0 , 1 , 1 , 1 , x , x , 1 , 1 , 1 , | |
| 591 | 0xa7, 0x7f, 0x42, 0xe6, 0xa0, 0x2a, 0xef, 0xee, 0x24, 0xba, 0xb8, 0x7e, 0xc9, 0x2b, 0x90, 0xcc, // 0x8 | |
| 592 | // 1 , x , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , | |
| 593 | 0x5b, 0xd1, 0xf3, 0xe2, 0x6f, 0xed, 0x9f, 0xf0, 0x4b, 0x54, 0x8c, 0x08, 0xf8, 0x51, 0x68, 0xc8, // 0x9 | |
| 594 | // x , 0 , 0 , 0 , 0 , 0 , 0 , 0 , x , 0 , x , 0 , 0 , 0 , 0 , 1 , | |
| 595 | 0x03, 0x0b, 0xbb, 0xc1, 0xe3, 0x4d, 0x04, 0xc5, 0x8f, 0x09, 0x0f, 0xbf, 0x62, 0x49, 0x76, 0x59, // 0xa | |
| 596 | // 1 , 1 , 1 , 1 , 1 , x , 0 , 1 , 1 , 0 , x , 1 , 1 , 1 , 1 , 0 , | |
| 597 | 0x1d, 0x80, 0xde, 0x60, 0x07, 0xe0, 0x1b, 0x66, 0xa5, 0xbe, 0xcd, 0x87, 0xdc, 0xc3, 0x6b, 0x4e, // 0xb | |
| 598 | // 0 , 1 , 1 , 1 , 1 , x , 0 , x , 0 , x , 0 , 1 , 1 , 0 , 1 , 1 , | |
| 599 | 0xd0, 0xfd, 0xd4, 0x3f, 0x98, 0x96, 0x2f, 0x4c, 0xb3, 0xea, 0x2c, 0x75, 0xe4, 0xc0, 0x6c, 0x6a, // 0xc | |
| 600 | // 0 , x , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , x , 1 , 1 , 1 , | |
| 601 | 0x9b, 0xb7, 0x43, 0x8b, 0x41, 0x47, 0x02, 0xdb, 0x99, 0x3d, 0xa3, 0x79, 0x50, 0x4f, 0xb4, 0x55, // 0xd | |
| 602 | 602 | // 1 , 0 , 0 , 0 , 1 , 0 , 0 , x , x , 1 , 1 , 1 , 0 , 1 , 1 , 1 , |
| 603 | 0x5a, 0x25, 0xf4, 0xca, 0x58, 0x30, 0xc4, 0x12, 0xa9, 0x46, 0xda, 0x91, 0xa4, 0xaa, 0xfc, 0x85, // 0xe | |
| 604 | // 1 , 1 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , x , | |
| 605 | 0xfb, 0x89, 0x06, 0xcf, 0xfe, 0x33, 0xd5, 0x28, 0x1f, 0x19, 0x4a, 0xb1, 0x83, 0xf2, 0x72, 0x26, // 0xf | |
| 606 | // x , x , 1 , 1 , 1 , 1 , 1 , 1 , x , 0 , 1 , 1 , 1 , 1 , 1 , 1 , | |
| 603 | 0x5a, 0x25, 0xf4, 0xca, 0x58, 0x30, 0xc4, 0x12, 0xa9, 0x46, 0xda, 0x91, 0xa4, 0xaa, 0xfc, 0x85, // 0xe | |
| 604 | // 1 , 1 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , x , | |
| 605 | 0xfb, 0x89, 0x06, 0xcf, 0xfe, 0x33, 0xd5, 0x28, 0x1f, 0x19, 0x4a, 0xb1, 0x83, 0xf2, 0x72, 0x26, // 0xf | |
| 606 | // x , x , 1 , 1 , 1 , 1 , 1 , 1 , x , 0 , 1 , 1 , 1 , 1 , 1 , 1 , | |
| 607 | 607 | }; |
| 608 | 608 | |
| 609 | 609 | |
| r25360 | r25361 | |
| 611 | 611 | |
| 612 | 612 | void pgm_arm_type1_state::command_handler_puzzli2(int pc) |
| 613 | 613 | { |
| 614 | ||
| 615 | 614 | switch (m_ddp3lastcommand) |
| 616 | 615 | { |
| 617 | ||
| 618 | ||
| 619 | ||
| 620 | 616 | case 0x31: |
| 621 | 617 | { |
| 622 | 618 | // how is this selected? command 54? |
| 623 | 619 | |
| 624 | 620 | |
| 625 | /* writes the following sequence before how to play | |
| 621 | /* writes the following sequence before how to play | |
| 626 | 622 | each level has a different sequence written before it, size of sequence doesn't seem directly connected to level size (unlike the reads) |
| 627 | 623 | so it's probably compressed somehow as well as scrambled? 68k doesnt know in advance how big each lot of data is either, it only stops |
| 628 | 624 | writing when it gets a difference response from the MCU. |
| 629 | 625 | |
| 630 | ||
| 626 | ||
| 631 | 627 | 00138278: 31 00fd | (set xor table offset) |
| 632 | 628 | UNKNOWN - related to depth / number of columns? |
| 633 | 629 | 00138278: 31 0087 | value 87, after xor is 75 (table address,value fd,f2) |
| r25360 | r25361 | |
| 639 | 635 | 00138278: 31 003f | value 3f, after xor is 01 (table address,value 01,3e) -> 0x0101 |
| 640 | 636 | 00138278: 31 00b0 | value b0, after xor is 02 (table address,value 02,b2) -> 0x0102 |
| 641 | 637 | 00138278: 31 0035 | value 35, after xor is 02 (table address,value 03,37) -> 0x0102 |
| 642 | ||
| 638 | COLUMN 2 | |
| 643 | 639 | 00138278: 31 0071 | value 71, after xor is 40 (table address,value 04,31) << 4 is the number of entries in this column |
| 644 | 640 | 00138278: 31 002d | value 2d, after xor is 0f (table address,value 05,22) << 0x0f is a mask of 4 bits.. |
| 645 | 641 | |
| r25360 | r25361 | |
| 650 | 646 | COLUMN 3 |
| 651 | 647 | 00138278: 31 00dd | value dd, after xor is 50 (table address,value 0a,8d) << 5 is the number of entries in this column |
| 652 | 648 | 00138278: 31 0023 | value 23, after xor is 1f (table address,value 0b,3c) << 0x1f is a mask of 5 bits.. |
| 653 | ||
| 649 | ||
| 654 | 650 | 00138278: 31 007a | value 7a, after xor is 00 (table address,value 0c,7a) -> 0x0100 |
| 655 | 651 | 00138278: 31 00f3 | value f3, after xor is 01 (table address,value fd,f2) -> 0x0101 |
| 656 | 652 | 00138278: 31 0077 | value 77, after xor is 05 (table address,value fe,72) -> 0x0105 |
| 657 | 653 | 00138278: 31 0022 | value 22, after xor is 04 (table address,value ff,26) -> 0x0104 |
| 658 | 00138278: 31 0036 | value 36, after xor is 04 (table address,value 00,32) -> 0x0104 | |
| 654 | 00138278: 31 0036 | value 36, after xor is 04 (table address,value 00,32) -> 0x0104 | |
| 659 | 655 | COLUMN 4 |
| 660 | 656 | 00138278: 31 002e | value 2e, after xor is 10 (table address,value 01,3e) << 1 is the number of entries in this column |
| 661 | 657 | 00138278: 31 00b3 | value b3, after xor is 01 (table address,value 02,b2) << 0x01 is a mask of 1 bit.. |
| r25360 | r25361 | |
| 664 | 660 | COLUMN 5 |
| 665 | 661 | 00138278: 31 0041 | value 41, after xor is 70 (table address,value 04,31) << 7 is the number of entries in this column |
| 666 | 662 | 00138278: 31 005d | value 5d, after xor is 7f (table address,value 05,22) << 0x7f is a mask of 7 bits.. |
| 667 | ||
| 663 | ||
| 668 | 664 | 00138278: 31 00d6 | value d6, after xor is 00 (table address,value 06,d6) -> 0x0100 |
| 669 | 665 | 00138278: 31 000c | value 0c, after xor is 01 (table address,value 07,0d) -> 0x0101 |
| 670 | 666 | 00138278: 31 0036 | value 36, after xor is 03 (table address,value 08,35) -> 0x0103 |
| r25360 | r25361 | |
| 675 | 671 | COLUMN 6 |
| 676 | 672 | 00138278: 31 00a2 | value a2, after xor is 50 (table address,value fd,f2) << 5 is the number of entries in this column |
| 677 | 673 | 00138278: 31 006d | value 6d, after xor is 1f (table address,value fe,72) << 0x1f is a mask of 5 bits.. |
| 678 | ||
| 674 | ||
| 679 | 675 | 00138278: 31 0023 | value 23, after xor is 05 (table address,value ff,26) -> 0x0105 |
| 680 | 676 | 00138278: 31 0037 | value 37, after xor is 05 (table address,value 00,32) -> 0x0105 |
| 681 | 677 | 00138278: 31 003f | value 3f, after xor is 01 (table address,value 01,3e) -> 0x0101 |
| r25360 | r25361 | |
| 708 | 704 | |
| 709 | 705 | if (!end) |
| 710 | 706 | { |
| 711 | ||
| 712 | 707 | // always d2 0000 when writing doing level data |
| 713 | 708 | // but different for the writes on startup? |
| 714 | 709 | m_valueresponse = 0x00d20000; |
| r25360 | r25361 | |
| 716 | 711 | //UINT8 tableaddr = (hack_31_table_offset + (hack_31_table_offset2&0xf))&0xff; |
| 717 | 712 | //UINT8 xoredval = m_value0 ^ puzzli2_level_decode[tableaddr]; |
| 718 | 713 | //puzzli2_printf("value %02x, after xor is %02x (table address,value %02x,%02x)\n", m_value0, xoredval, tableaddr, puzzli2_level_decode[tableaddr]); |
| 719 | ||
| 714 | ||
| 720 | 715 | hackcount2++; |
| 721 | 716 | hack_31_table_offset2++; |
| 722 | 717 | } |
| 723 | 718 | else |
| 724 | 719 | { |
| 725 | 720 | hackcount2=0; |
| 726 | ||
| 721 | ||
| 727 | 722 | // when the ARM detects the end of the stream has been reached it returns a 0x63 status with the number of columns in the data word |
| 728 | 723 | m_valueresponse = 0x00630000 | numbercolumns; |
| 729 | ||
| 724 | ||
| 730 | 725 | //UINT8 tableaddr = (hack_31_table_offset + (hack_31_table_offset2&0xf))&0xff; |
| 731 | 726 | //UINT8 xoredval = m_value0 ^ puzzli2_level_decode[tableaddr]; |
| 732 | 727 | //puzzli2_printf("value %02x, after xor is %02x (table address,value %02x,%02x) (end, returning %02x as playfield width)\n", m_value0, xoredval, tableaddr, puzzli2_level_decode[tableaddr], m_valueresponse); |
| r25360 | r25361 | |
| 748 | 743 | |
| 749 | 744 | } |
| 750 | 745 | break; |
| 751 | ||
| 752 | 746 | |
| 747 | ||
| 753 | 748 | // after writing the compressed and scrambled data stream for the level (copied from ROM) with command 0x31 |
| 754 | 749 | // the game expects to read back a fully formed level structure from the ARM |
| 755 | 750 | case 0x13: |
| r25360 | r25361 | |
| 758 | 753 | |
| 759 | 754 | // this is the how to play screen, correctly returned with current code |
| 760 | 755 | /* |
| 761 | UINT16 retvals[61] = | |
| 756 | UINT16 retvals[61] = | |
| 762 | 757 | { 0x0008, // depth (-2?) |
| 763 | 758 | 0x0103, 0x0101, 0x0102, 0x0102, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // first column |
| 764 | 759 | 0x0103, 0x0100, 0x0101, 0x0105, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
| r25360 | r25361 | |
| 807 | 802 | m_valueresponse = 0x780000 | m_simregion<<8; // this must also return the cart region or the game will act in odd ways when inserting a coin on continue, or during the game on later levels |
| 808 | 803 | m_valuekey = 0x100; |
| 809 | 804 | m_puzzli_54_trigger = 0; |
| 810 | ||
| 805 | ||
| 811 | 806 | break; |
| 812 | 807 | |
| 813 | 808 | |
| r25360 | r25361 | |
| 846 | 841 | } |
| 847 | 842 | else |
| 848 | 843 | { |
| 849 | ||
| 850 | 844 | int val = ((hack_47_value & 0x0f00)>>8) * 0x19; |
| 851 | 845 | val +=((hack_47_value & 0x000f)>>0) * 0x05; |
| 852 | 846 | val += m_value0 & 0x000f; |
| r25360 | r25361 | |
| 855 | 849 | } |
| 856 | 850 | |
| 857 | 851 | |
| 858 | ||
| 852 | ||
| 859 | 853 | break; |
| 860 | 854 | |
| 861 | 855 | |
| 862 | 856 | |
| 863 | 857 | case 0x61: // ?? |
| 864 | 858 | puzzli2_printf("%08x: %02x %04x\n",pc, m_ddp3lastcommand, m_value0); |
| 865 | ||
| 859 | ||
| 866 | 860 | // this command is written before the values used to decrypt the z80 addresses (assumed) are uploaded with command 31 |
| 867 | 861 | command_31_write_type = 1; |
| 868 | 862 | |
| r25360 | r25361 | |
| 882 | 876 | |
| 883 | 877 | case 0x54: // ?? |
| 884 | 878 | puzzli2_printf("%08x: %02x %04x\n",pc, m_ddp3lastcommand, m_value0); |
| 885 | ||
| 879 | ||
| 886 | 880 | // this command is written before uploading the compressed level data stream with command 31 |
| 887 | 881 | |
| 888 | 882 | command_31_write_type = 2; |
| r25360 | r25361 | |
| 891 | 885 | hackcount2 = 0; |
| 892 | 886 | hackcount = 0; |
| 893 | 887 | m_valueresponse = 0x36<<16; |
| 894 | ||
| 888 | ||
| 895 | 889 | // clear the return structure |
| 896 | 890 | for (int columns=0;columns<8;columns++) |
| 897 | 891 | for (int rows=0;rows<10;rows++) |
| r25360 | r25361 | |
| 899 | 893 | |
| 900 | 894 | break; |
| 901 | 895 | |
| 902 | /* | |
| 896 | /* | |
| 903 | 897 | |
| 904 | puzzli2 on startup (00148a84) puzzli2s on startup (0014cf58) | |
| 905 | ||
| 906 | (001489f6: 61 0202 0014ceca: 61 0202) | |
| 907 | always | |
| 908 | : 31 004e a6f7 | : 31 | 0051 14c9 + 26DD2 | |
| 909 | : 31 279e 534f | : 31 | 27a0 c121 | |
| 910 | : 31 ab5c a7cf | : 31 | ab5f 15a1 | |
| 911 | : 31 145f 7054 | : 31 | 1461 de26 | |
| 912 | : 31 85a0 7b7f | : 31 | 85a2 e951 | |
| 913 | : 31 7003 c5ab | : 31 | 7006 337d | |
| 914 | : 31 456d f3aa | : 31 | 4570 617c | |
| 898 | puzzli2 on startup (00148a84) puzzli2s on startup (0014cf58) | |
| 915 | 899 | |
| 916 | (00148b34: 41 e2bb 0014d008: 41 706d) | |
| 900 | (001489f6: 61 0202 0014ceca: 61 0202) | |
| 901 | always | |
| 902 | : 31 004e a6f7 | : 31 | 0051 14c9 + 26DD2 | |
| 903 | : 31 279e 534f | : 31 | 27a0 c121 | |
| 904 | : 31 ab5c a7cf | : 31 | ab5f 15a1 | |
| 905 | : 31 145f 7054 | : 31 | 1461 de26 | |
| 906 | : 31 85a0 7b7f | : 31 | 85a2 e951 | |
| 907 | : 31 7003 c5ab | : 31 | 7006 337d | |
| 908 | : 31 456d f3aa | : 31 | 4570 617c | |
| 917 | 909 | |
| 918 | actual values needed always | |
| 919 | 0x001694a8 / 0x0019027a + 26DD2 | |
| 920 | 0x0016cfae / 0x00193D80 | |
| 921 | 0x0016ebf2 / 0x001959c4 | |
| 922 | 0x0016faa8 / 0x0019687a | |
| 923 | 0x00174416 / 0x0019b1e8 | |
| 910 | (00148b34: 41 e2bb 0014d008: 41 706d) | |
| 924 | 911 | |
| 925 | 0x00166178 / 0x0018cf4a | |
| 926 | 0x00166e72 / 0x0018dc44 | |
| 912 | actual values needed always | |
| 913 | 0x001694a8 / 0x0019027a + 26DD2 | |
| 914 | 0x0016cfae / 0x00193D80 | |
| 915 | 0x0016ebf2 / 0x001959c4 | |
| 916 | 0x0016faa8 / 0x0019687a | |
| 917 | 0x00174416 / 0x0019b1e8 | |
| 927 | 918 | |
| 928 | as you can see the difference between the values written is always 26dd2, as is the difference between offsets expected | |
| 929 | this makes it impossible to know which value is for which address without further tests! | |
| 930 | ||
| 931 | ||
| 919 | 0x00166178 / 0x0018cf4a | |
| 920 | 0x00166e72 / 0x0018dc44 | |
| 921 | ||
| 922 | as you can see the difference between the values written is always 26dd2, as is the difference between offsets expected | |
| 923 | this makes it impossible to know which value is for which address without further tests! | |
| 924 | ||
| 925 | ||
| 932 | 926 | */ |
| 933 | 927 | |
| 934 | 928 | // I think the values returned here must be connected to the values written to command 31 on startup |
| r25360 | r25361 | |
| 1072 | 1066 | m_simregion = ioport("Region")->read(); |
| 1073 | 1067 | m_valuekey = 0x100; |
| 1074 | 1068 | m_valueresponse = 0x00880000 | m_simregion<<8; |
| 1075 | ||
| 1069 | ||
| 1076 | 1070 | break; |
| 1077 | 1071 | } |
| 1078 | 1072 | } |
| r25360 | r25361 | |
| 1877 | 1871 | } |
| 1878 | 1872 | else |
| 1879 | 1873 | { |
| 1880 | ||
| 1881 | 1874 | UINT8 rawvalue = datvalue; |
| 1882 | 1875 | UINT8 tableloc = (tableoffs+tableoffs2)&0xff; |
| 1883 | 1876 | rawvalue ^= puzzli2_level_decode[tableloc]; |
| r25360 | r25361 | |
| 1916 | 1909 | stage = 2; |
| 1917 | 1910 | entries_left = (rawvalue >> 4); |
| 1918 | 1911 | m_row_bitmask = (rawvalue & 0x0f)<<8; |
| 1919 | ||
| 1912 | ||
| 1920 | 1913 | full_entry = rawvalue; |
| 1921 | 1914 | prev_tablloc = tableloc; |
| 1922 | 1915 | |
| r25360 | r25361 | |
| 1931 | 1924 | |
| 1932 | 1925 | puzzli2_printf("\n"); |
| 1933 | 1926 | |
| 1934 | ||
| 1927 | ||
| 1935 | 1928 | } |
| 1936 | 1929 | else if (stage==2) |
| 1937 | { | |
| 1930 | { | |
| 1938 | 1931 | puzzli2_printf("%02x <- Mask value equal to number of entries (xor table location is %02x)", rawvalue, tableloc); |
| 1939 | 1932 | stage = 3; |
| 1940 | 1933 | |
| r25360 | r25361 | |
| 1945 | 1938 | if (num_mask_bits != num_entries) |
| 1946 | 1939 | puzzli2_printf(" error - number of mask bits != number of entries - "); |
| 1947 | 1940 | |
| 1948 | // | |
| 1941 | // | |
| 1949 | 1942 | if (entries_left == 0) |
| 1950 | 1943 | { |
| 1951 | 1944 | // for 0 entries skip back to state 1 instead of 3, because there is nothing following |
| r25360 | r25361 | |
| 1972 | 1965 | { |
| 1973 | 1966 | return 1; |
| 1974 | 1967 | } |
| 1975 | ||
| 1968 | ||
| 1976 | 1969 | } |
| 1977 | 1970 | else |
| 1978 | 1971 | { |
| r25360 | r25361 | |
| 1982 | 1975 | } |
| 1983 | 1976 | else |
| 1984 | 1977 | { |
| 1985 | ||
| 1986 | 1978 | // this isn't a strict rule |
| 1987 | 1979 | // the mask is used so they can specify spaces between elements too without storing the 00 bytes |
| 1988 | 1980 | coverage[tableloc] = 1; |
| r25360 | r25361 | |
| 2037 | 2029 | { |
| 2038 | 2030 | int fishtype = rawvalue; |
| 2039 | 2031 | puzzli2_printf("%02x <- fish type %d", rawvalue, fishtype); |
| 2040 | object_value = 0x0100 + fishtype; | |
| 2032 | object_value = 0x0100 + fishtype; | |
| 2041 | 2033 | // 0x110 is a flashy fish? might be glitchy and need a special number.. |
| 2042 | 2034 | } |
| 2043 | 2035 | else if (rawvalue<=0x21) // fish in bubbles |
| 2044 | 2036 | { |
| 2045 | 2037 | int fishtype = rawvalue - 0x11; |
| 2046 | 2038 | puzzli2_printf("%02x <- fish in bubble %d", rawvalue, fishtype); |
| 2047 | object_value = 0x0120 + fishtype; | |
| 2039 | object_value = 0x0120 + fishtype; | |
| 2048 | 2040 | // 0x130 is a flashy fish? might be glitchy and need a special number.. |
| 2049 | 2041 | } |
| 2050 | 2042 | else if (rawvalue<=0x32) // fish in eggs |
| 2051 | 2043 | { |
| 2052 | 2044 | int fishtype = rawvalue - 0x22; |
| 2053 | 2045 | puzzli2_printf("%02x <- fish in egg %d", rawvalue, fishtype); |
| 2054 | object_value = 0x0140 + fishtype; | |
| 2046 | object_value = 0x0140 + fishtype; | |
| 2055 | 2047 | // 0x150 is a flashy fish? might be glitchy and need a special number.. |
| 2056 | 2048 | |
| 2057 | 2049 | } |
| r25360 | r25361 | |
| 2059 | 2051 | { |
| 2060 | 2052 | int fishtype = rawvalue - 0x33; |
| 2061 | 2053 | puzzli2_printf("%02x <- fish on hook %d", rawvalue, fishtype); |
| 2062 | object_value = 0x0180 + fishtype; | |
| 2054 | object_value = 0x0180 + fishtype; | |
| 2063 | 2055 | // 0x190 is a flashy fish? might be glitchy and need a special number.. |
| 2064 | 2056 | |
| 2065 | 2057 | } |
| r25360 | r25361 | |
| 2080 | 2072 | if (object_value==0xffff) |
| 2081 | 2073 | { |
| 2082 | 2074 | object_value = 0x110; |
| 2083 | popmessage("unknown object type %02x\n", rawvalue); | |
| 2075 | popmessage("unknown object type %02x\n", rawvalue); | |
| 2084 | 2076 | } |
| 2085 | 2077 | |
| 2086 | 2078 | int realrow = get_position_of_bit(m_row_bitmask, currentrow); |
| r25360 | r25361 | |
| 2105 | 2097 | |
| 2106 | 2098 | } |
| 2107 | 2099 | } |
| 2108 | ||
| 2100 | ||
| 2109 | 2101 | } |
| 2110 | 2102 | |
| 2111 | 2103 | return 0; |
| 2112 | 2104 | } |
| 2113 | ||
| 2114 | 2105 | |
| 2115 | 2106 | |
| 2107 | ||
| 2116 | 2108 | DRIVER_INIT_MEMBER(pgm_arm_type1_state,puzzli2) |
| 2117 | 2109 | { |
| 2118 | 2110 | pgm_basic_init(); |
| r25360 | r25361 | |
| 2142 | 2134 | if (!strcmp(machine().system().name,"puzzli2")) |
| 2143 | 2135 | { |
| 2144 | 2136 | offset = 0x17ab66; |
| 2145 | | |
| 2137 | limit = 476; | |
| 2146 | 2138 | } |
| 2147 | 2139 | else |
| 2148 | 2140 | { |
| 2149 | offset = 0x16c3ca; | |
| 2150 | limit = 500; | |
| 2141 | offset = 0x16c3ca; | |
| 2142 | limit = 500; | |
| 2151 | 2143 | } |
| 2152 | 2144 | |
| 2153 | 2145 | |
| r25360 | r25361 | |
| 2206 | 2198 | fatalerror("mismatch in number of columns vs specified amount\n"); |
| 2207 | 2199 | |
| 2208 | 2200 | printf("\n"); |
| 2209 | ||
| 2210 | 2201 | |
| 2202 | ||
| 2211 | 2203 | } |
| 2212 | 2204 | |
| 2213 | 2205 |
| r25360 | r25361 | |
|---|---|---|
| 24 | 24 | |
| 25 | 25 | sega_genesis_vdp_device::sega_genesis_vdp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 26 | 26 | : sega315_5124_device( mconfig, SEGA315_5246, "Sega Genesis VDP", tag, owner, clock, SEGA315_5124_CRAM_SIZE, 0, true, "sega_genesis_vdp", __FILE__), |
| 27 | m_genesis_vdp_sndirqline_callback(*this), | |
| 28 | m_genesis_vdp_lv6irqline_callback(*this), | |
| 29 | m_genesis_vdp_lv4irqline_callback(*this) | |
| 27 | m_genesis_vdp_sndirqline_callback(*this), | |
| 28 | m_genesis_vdp_lv6irqline_callback(*this), | |
| 29 | m_genesis_vdp_lv4irqline_callback(*this) | |
| 30 | 30 | { |
| 31 | 31 | m_use_alt_timing = 0; |
| 32 | 32 | m_palwrite_base = -1; |
| r25360 | r25361 | |
|---|---|---|
| 165 | 165 | { |
| 166 | 166 | int pc = space.device().safe_pc(); |
| 167 | 167 | int regionhack = ioport("RegionHack")->read(); |
| 168 | // | |
| 168 | // printf("%08x\n", pc); | |
| 169 | 169 | if (pc==0x1b0 && regionhack != 0xff) data = (data & 0xffff0000) | (regionhack << 0); |
| 170 | 170 | COMBINE_DATA(&m_arm7_shareram[0x138/4]); |
| 171 | 171 | } |
| r25360 | r25361 | |
|---|---|---|
| 10 | 10 | UINT8 get_status_bits(); |
| 11 | 11 | UINT8 is_present(); |
| 12 | 12 | void change_speed(INT8 newspeed); |
| 13 | ||
| 13 | ||
| 14 | 14 | protected: |
| 15 | 15 | // device-level overrides |
| 16 | 16 | virtual void device_config_complete(); |
| 17 | 17 | virtual void device_start(); |
| 18 | 18 | virtual void device_reset(); |
| 19 | ||
| 19 | ||
| 20 | 20 | private: |
| 21 | 21 | /* regions within the virtual tape */ |
| 22 | 22 | enum tape_region |
| r25360 | r25361 | |
| 52 | 52 | BYTE_POSTGAP_33 = BYTE_POSTGAP_0 + 33, |
| 53 | 53 | BYTE_BLOCK_TOTAL /* total number of bytes in block */ |
| 54 | 54 | }; |
| 55 | ||
| 55 | ||
| 56 | 56 | // internal state |
| 57 | 57 | emu_timer * m_tape_timer; /* timer for running the tape */ |
| 58 | 58 | INT8 m_speed; /* speed: <-1=fast rewind, -1=reverse, 0=stopped, 1=normal, >1=fast forward */ |
| r25360 | r25361 | |
| 62 | 62 | UINT32 m_clockpos; /* the current clock position of the tape */ |
| 63 | 63 | UINT32 m_numclocks; /* total number of clocks on the entire tape */ |
| 64 | 64 | UINT16 m_crc16[256]; /* CRC16 for each block */ |
| 65 | ||
| 65 | ||
| 66 | 66 | const char *describe_state(); |
| 67 | 67 | TIMER_CALLBACK_MEMBER( tape_clock_callback ); |
| 68 | 68 | }; |
| r25360 | r25361 | |
|---|---|---|
| 987 | 987 | m_rom = machine().root_device().memregion("audiocpu")->base(); |
| 988 | 988 | |
| 989 | 989 | address_space &space = machine().firstcpu->space(AS_PROGRAM); |
| 990 | ||
| 990 | ||
| 991 | 991 | if (m_ymdevice != NULL) |
| 992 | 992 | { |
| 993 | 993 | m_ymdevice->control_port_w(space, 0, 0x2f); |
| r25360 | r25361 | |
| 998 | 998 | m_ymdevice->control_port_w(space, 0, ym2203_init[i++]); |
| 999 | 999 | m_ymdevice->write_port_w(space, 0, ym2203_init[i++]); |
| 1000 | 1000 | } |
| 1001 | } | |
| 1001 | } | |
| 1002 | 1002 | else |
| 1003 | 1003 | return; |
| 1004 | ||
| 1004 | ||
| 1005 | 1005 | m_oki_playing = 0; |
| 1006 | 1006 | |
| 1007 | 1007 | oki_play_sample(0); |
| r25360 | r25361 | |
|---|---|---|
| 68 | 68 | public: |
| 69 | 69 | nmk004_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 70 | 70 | ~nmk004_device() {} |
| 71 | ||
| 71 | ||
| 72 | 72 | void ym2203_irq_handler(int irq); |
| 73 | 73 | DECLARE_READ16_MEMBER( read ); |
| 74 | 74 | DECLARE_WRITE16_MEMBER( write ); |
| r25360 | r25361 | |
| 95 | 95 | /* C020-C19F */ struct fm_control m_fm_control[FM_CHANNELS]; |
| 96 | 96 | /* C220-C2DF */ struct psg_control m_psg_control[PSG_CHANNELS]; |
| 97 | 97 | /* C1A0-C21F */ struct effects_control m_effects_control[EFFECTS_CHANNELS]; |
| 98 | ||
| 98 | ||
| 99 | 99 | TIMER_CALLBACK_MEMBER( real_init ); |
| 100 | 100 | UINT8 read8(int address); |
| 101 | 101 | UINT16 read16(int address); |
| r25360 | r25361 | |
| 112 | 112 | extern const device_type NMK004; |
| 113 | 113 | |
| 114 | 114 | #define MCFG_NMK004_ADD(_tag) \ |
| 115 | MCFG_DEVICE_ADD(_tag, NMK004, 0) | |
| 115 | MCFG_DEVICE_ADD(_tag, NMK004, 0) |
| r25360 | r25361 | |
|---|---|---|
| 22 | 22 | required_shared_ptr<UINT16> m_background2_videoram16; |
| 23 | 23 | required_shared_ptr<UINT16> m_videoram; |
| 24 | 24 | required_shared_ptr<UINT16> m_scrollram16; |
| 25 | ||
| 25 | ||
| 26 | 26 | required_device<cpu_device> m_maincpu; |
| 27 | 27 | required_device<cpu_device> m_audiocpu; |
| 28 | 28 | optional_device<seibu_sound_device> m_seibu_sound; |
| r25360 | r25361 | |
|---|---|---|
| 28 | 28 | required_shared_ptr<UINT8> m_colorram; |
| 29 | 29 | |
| 30 | 30 | /* protection */ |
| 31 | UINT8 | |
| 31 | UINT8 m_prot_value; | |
| 32 | 32 | |
| 33 | 33 | /* video-related */ |
| 34 | tilemap_t *m_bg_tilemap; | |
| 35 | tilemap_t *m_fg_tilemap; | |
| 36 | int m_bg_index[4]; | |
| 34 | tilemap_t *m_bg_tilemap; | |
| 35 | tilemap_t *m_fg_tilemap; | |
| 36 | int m_bg_index[4]; | |
| 37 | 37 | |
| 38 | 38 | virtual void machine_start(); |
| 39 | 39 | virtual void machine_reset(); |
| r25360 | r25361 | |
|---|---|---|
| 185 | 185 | ~micro3d_sound_device() {} |
| 186 | 186 | |
| 187 | 187 | void noise_sh_w(UINT8 data); |
| 188 | ||
| 188 | ||
| 189 | 189 | protected: |
| 190 | 190 | // device-level overrides |
| 191 | 191 | virtual void device_config_complete(); |
| r25360 | r25361 | |
|---|---|---|
| 30 | 30 | required_shared_ptr<UINT16> m_system32_videoram; |
| 31 | 31 | required_shared_ptr<UINT16> m_system32_spriteram; |
| 32 | 32 | optional_shared_ptr_array<UINT16, 2> m_system32_paletteram; |
| 33 | ||
| 33 | ||
| 34 | 34 | required_device<cpu_device> m_maincpu; |
| 35 | 35 | required_device<cpu_device> m_soundcpu; |
| 36 | 36 | optional_device<multipcm_device> m_multipcm; |
| r25360 | r25361 | |
|---|---|---|
| 12 | 12 | |
| 13 | 13 | required_shared_ptr<UINT8> m_videoram; |
| 14 | 14 | required_shared_ptr<UINT8> m_spriteram; |
| 15 | ||
| 15 | ||
| 16 | 16 | required_device<cpu_device> m_maincpu; |
| 17 | 17 | required_device<seibu_sound_device> m_cpu_decrypt; |
| 18 | ||
| 18 | ||
| 19 | 19 | tilemap_t *m_bg_tilemap; |
| 20 | 20 | int m_control_byte; |
| 21 | 21 | DECLARE_WRITE8_MEMBER(mustache_videoram_w); |
| r25360 | r25361 | |
|---|---|---|
| 17 | 17 | m_scrb_videoram(*this, "scrb_videoram"), |
| 18 | 18 | m_scrb_linezoom(*this, "scrb_linezoom"), |
| 19 | 19 | m_scrb_videoregs(*this, "scrb_videoregs"), |
| 20 | ||
| 20 | ||
| 21 | 21 | m_scrc_videoram(*this, "scrc_videoram"), |
| 22 | 22 | m_scrc_linezoom(*this, "scrc_linezoom"), |
| 23 | 23 | m_scrc_videoregs(*this, "scrc_videoregs"), |
| r25360 | r25361 | |
| 30 | 30 | m_mainram(*this, "mainram"), |
| 31 | 31 | m_maincpu(*this, "maincpu"), |
| 32 | 32 | m_audiocpu(*this, "audiocpu") |
| 33 | { | |
| 34 | ||
| 33 | { | |
| 35 | 34 | } |
| 36 | 35 | |
| 37 | 36 | /* memory pointers */ |
| r25360 | r25361 | |
|---|---|---|
| 61 | 61 | |
| 62 | 62 | DECLARE_READ32_MEMBER( read ); |
| 63 | 63 | DECLARE_WRITE32_MEMBER( write ); |
| 64 | ||
| 64 | ||
| 65 | 65 | protected: |
| 66 | 66 | // device-level overrides |
| 67 | 67 | virtual void device_config_complete(); |
| r25360 | r25361 | |
| 108 | 108 | device_t *m_i2cmem; |
| 109 | 109 | |
| 110 | 110 | int m_cdrom_is_device; |
| 111 | ||
| 111 | ||
| 112 | 112 | void nvram_write(UINT32 data); |
| 113 | 113 | UINT32 nvram_read(); |
| 114 | ||
| 114 | ||
| 115 | 115 | void c2p_write(UINT32 data); |
| 116 | 116 | UINT32 c2p_read(); |
| 117 | ||
| 117 | ||
| 118 | 118 | void cdda_stop(); |
| 119 | 119 | void cdda_play(UINT32 lba, UINT32 num_blocks); |
| 120 | 120 | void cdda_pause(int pause); |
| 121 | 121 | UINT8 cdda_getstatus(UINT32 *lba); |
| 122 | 122 | void set_cd_status(UINT32 status); |
| 123 | ||
| 123 | ||
| 124 | 124 | TIMER_CALLBACK_MEMBER(frame_proc); |
| 125 | 125 | TIMER_CALLBACK_MEMBER(dma_proc); |
| 126 | ||
| 126 | ||
| 127 | 127 | void start_dma(); |
| 128 | 128 | void setup_response( int len, UINT8 *r1 ); |
| 129 | ||
| 129 | ||
| 130 | 130 | TIMER_CALLBACK_MEMBER( cd_delayed_cmd ); |
| 131 | 131 | void update_cdrom(); |
| 132 | 132 | }; |
| r25360 | r25361 | |
|---|---|---|
| 38 | 38 | UINT16 m_adpcm_data_offs; |
| 39 | 39 | UINT8 m_adpcm_nibble; |
| 40 | 40 | UINT8 m_adpcm_reset; |
| 41 | ||
| 41 | ||
| 42 | 42 | UINT8 m_coin_state; |
| 43 | 43 | tilemap_t *m_fg_tilemap; |
| 44 | 44 | tilemap_t *m_bg_tilemap; |
| r25360 | r25361 | |
| 62 | 62 | DECLARE_WRITE8_MEMBER(stfight_text_attr_w); |
| 63 | 63 | DECLARE_WRITE8_MEMBER(stfight_sprite_bank_w); |
| 64 | 64 | DECLARE_WRITE8_MEMBER(stfight_vh_latch_w); |
| 65 | DECLARE_WRITE8_MEMBER(cshooter_text_w); | |
| 65 | DECLARE_WRITE8_MEMBER(cshooter_text_w); | |
| 66 | 66 | |
| 67 | 67 | DECLARE_READ8_MEMBER(stfight_fm_r); |
| 68 | 68 |
| r25360 | r25361 | |
|---|---|---|
| 12 | 12 | |
| 13 | 13 | required_shared_ptr<UINT8> m_videoram; |
| 14 | 14 | required_shared_ptr<UINT8> m_s2636_0_ram; |
| 15 | ||
| 15 | ||
| 16 | 16 | required_device<cpu_device> m_maincpu; |
| 17 | 17 | required_device<s2636_device> m_s2636_sound; |
| 18 | ||
| 18 | ||
| 19 | 19 | bitmap_ind16 m_bitmap; |
| 20 | 20 | bitmap_ind16 m_spritebitmap; |
| 21 | 21 | int m_CollisionBackground; |
| r25360 | r25361 | |
|---|---|---|
| 17 | 17 | |
| 18 | 18 | required_device<tilemap_device> m_playfield_tilemap; |
| 19 | 19 | required_device<atari_motion_objects_device> m_mob; |
| 20 | ||
| 20 | ||
| 21 | 21 | virtual void update_interrupts(); |
| 22 | 22 | virtual void scanline_update(screen_device &screen, int scanline); |
| 23 | 23 | DECLARE_WRITE16_MEMBER(interrupt_ack_w); |
| r25360 | r25361 | |
|---|---|---|
| 45 | 45 | m_dac(*this, "dac"), |
| 46 | 46 | m_samples(*this, "samples") { } |
| 47 | 47 | |
| 48 | ||
| 48 | ||
| 49 | 49 | required_shared_ptr<UINT8> m_videoram; |
| 50 | 50 | required_shared_ptr<UINT8> m_sprite1_xpos; |
| 51 | 51 | required_shared_ptr<UINT8> m_sprite1_ypos; |
| r25360 | r25361 | |
| 55 | 55 | required_shared_ptr<UINT8> m_sprite_enable; |
| 56 | 56 | required_shared_ptr<UINT8> m_color_latch; |
| 57 | 57 | required_shared_ptr<UINT8> m_characterram; |
| 58 | ||
| 58 | ||
| 59 | 59 | required_device<cpu_device> m_maincpu; |
| 60 | 60 | optional_device<dac_device> m_dac; |
| 61 | 61 | optional_device<samples_device> m_samples; |
| 62 | ||
| 62 | ||
| 63 | 63 | UINT8 m_last_dial; |
| 64 | 64 | UINT8 m_collision_mask; |
| 65 | 65 | UINT8 m_collision_invert; |
| r25360 | r25361 | |
| 94 | 94 | inline int sprite_1_enabled(); |
| 95 | 95 | void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect); |
| 96 | 96 | void check_collision(); |
| 97 | ||
| 97 | ||
| 98 | 98 | /* Targ and Spectar samples */ |
| 99 | 99 | int m_max_freq; |
| 100 | 100 | UINT8 m_port_1_last; |
| r25360 | r25361 | |
| 107 | 107 | DECLARE_WRITE8_MEMBER(spectar_audio_2_w); |
| 108 | 108 | void adjust_sample(UINT8 freq); |
| 109 | 109 | void common_audio_start(int freq); |
| 110 | ||
| 111 | 110 | |
| 111 | ||
| 112 | 112 | protected: |
| 113 | 113 | virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); |
| 114 | 114 | }; |
| r25360 | r25361 | |
|---|---|---|
| 20 | 20 | required_shared_ptr<UINT16> m_spriteram; |
| 21 | 21 | required_shared_ptr<UINT16> m_colorram; |
| 22 | 22 | required_shared_ptr<UINT16> m_videoram; |
| 23 | ||
| 23 | ||
| 24 | 24 | required_device<cpu_device> m_maincpu; |
| 25 | 25 | required_device<cpu_device> m_audiocpu; |
| 26 | 26 | optional_device<seibu_sound_device> m_seibu_sound; |
| r25360 | r25361 | |
| 28 | 28 | optional_device<seibu_adpcm_device> m_adpcm2; |
| 29 | 29 | optional_device<msm5205_device> m_msm1; |
| 30 | 30 | optional_device<msm5205_device> m_msm2; |
| 31 | ||
| 31 | ||
| 32 | 32 | tilemap_t *m_background_layer; |
| 33 | 33 | tilemap_t *m_text_layer; |
| 34 | 34 | int m_sound_command1; |
| r25360 | r25361 | |
|---|---|---|
| 15 | 15 | m_s14001a(*this, "speech") { } |
| 16 | 16 | |
| 17 | 17 | required_shared_ptr<UINT8> m_alpha_num_ram; |
| 18 | ||
| 18 | ||
| 19 | 19 | required_device<cpu_device> m_maincpu; |
| 20 | 20 | required_device<s14001a_device> m_s14001a; |
| 21 | ||
| 21 | ||
| 22 | 22 | int m_collision; |
| 23 | 23 | unsigned m_current_index; |
| 24 | 24 | UINT8 m_video_invert; |
| r25360 | r25361 | |
|---|---|---|
| 18 | 18 | required_shared_ptr<UINT8> m_videoram; |
| 19 | 19 | required_shared_ptr<UINT8> m_workram; |
| 20 | 20 | required_shared_ptr<UINT8> m_spriteram; |
| 21 | ||
| 21 | ||
| 22 | 22 | required_device<cpu_device> m_maincpu; |
| 23 | 23 | required_device<t5182_device> m_t5182; |
| 24 | ||
| 24 | ||
| 25 | 25 | int m_hw; |
| 26 | 26 | tilemap_t *m_bgtilemap; |
| 27 | 27 | tilemap_t *m_fgtilemap; |
| r25360 | r25361 | |
|---|---|---|
| 19 | 19 | required_shared_ptr<UINT16> m_videoram; |
| 20 | 20 | required_shared_ptr<UINT16> m_back_data; |
| 21 | 21 | required_shared_ptr<UINT16> m_fore_data; |
| 22 | ||
| 22 | ||
| 23 | 23 | required_device<cpu_device> m_maincpu; |
| 24 | 24 | required_device<seibu_sound_device> m_seibu_sound; |
| 25 | 25 |
| r25360 | r25361 | |
|---|---|---|
| 18 | 18 | m_maincpu(*this, "maincpu"), |
| 19 | 19 | m_audiocpu(*this, "audiocpu"), |
| 20 | 20 | m_oki(*this, "oki") |
| 21 | ||
| 21 | ||
| 22 | 22 | { |
| 23 | 23 | vblank_level = 6; |
| 24 | 24 | raster_level = 5; |
| r25360 | r25361 | |
| 27 | 27 | /* memory pointers */ |
| 28 | 28 | required_shared_ptr<UINT16> m_bg_videoram; |
| 29 | 29 | required_shared_ptr<UINT16> m_fg_videoram; |
| 30 | // | |
| 30 | // required_shared_ptr<UINT16> m_spriteram; | |
| 31 | 31 | required_device<buffered_spriteram16_device> m_spriteram; |
| 32 | 32 | // UINT16 * m_paletteram; // currently this uses generic palette handling |
| 33 | 33 |
| r25360 | r25361 | |
|---|---|---|
| 19 | 19 | required_shared_ptr<UINT16> m_videoram; |
| 20 | 20 | required_shared_ptr<UINT16> m_scroll_ram; |
| 21 | 21 | required_shared_ptr<UINT16> m_video_data; |
| 22 | ||
| 22 | ||
| 23 | 23 | required_device<cpu_device> m_maincpu; |
| 24 | 24 | required_device<cpu_device> m_subcpu; |
| 25 | 25 | required_device<seibu_sound_device> m_seibu_sound; |
| 26 | 26 | required_device<seibu_adpcm_device> m_adpcm1; |
| 27 | 27 | required_device<seibu_adpcm_device> m_adpcm2; |
| 28 | ||
| 28 | ||
| 29 | 29 | tilemap_t *m_pf3_layer; |
| 30 | 30 | tilemap_t *m_pf2_layer; |
| 31 | 31 | tilemap_t *m_pf1_layer; |
| r25360 | r25361 | |
|---|---|---|
| 101 | 101 | DECLARE_WRITE_LINE_MEMBER(carpolo_7474_2s_2_q_cb); |
| 102 | 102 | DECLARE_WRITE_LINE_MEMBER(carpolo_7474_2u_1_q_cb); |
| 103 | 103 | DECLARE_WRITE_LINE_MEMBER(carpolo_7474_2u_2_q_cb); |
| 104 | ||
| 104 | ||
| 105 | 105 | void remap_sprite_code(int bank, int code, int *remapped_code, int *flipy); |
| 106 | 106 | void normalize_coordinates(int *x1, int *y1, int *x2, int *y2); |
| 107 | 107 | int check_sprite_left_goal_collision(int x1, int y1, int code1, int flipy1, int goalpost_only); |
| r25360 | r25361 | |
|---|---|---|
| 12 | 12 | public: |
| 13 | 13 | gauntlet_state(const machine_config &mconfig, device_type type, const char *tag) |
| 14 | 14 | : atarigen_state(mconfig, type, tag), |
| 15 | m_playfield_tilemap(*this, "playfield"), | |
| 16 | m_alpha_tilemap(*this, "alpha"), | |
| 17 | m_mob(*this, "mob") { } | |
| 18 | ||
| 15 | m_playfield_tilemap(*this, "playfield"), | |
| 16 | m_alpha_tilemap(*this, "alpha"), | |
| 17 | m_mob(*this, "mob") { } | |
| 18 | ||
| 19 | 19 | required_device<tilemap_device> m_playfield_tilemap; |
| 20 | 20 | required_device<tilemap_device> m_alpha_tilemap; |
| 21 | 21 | required_device<atari_motion_objects_device> m_mob; |
| r25360 | r25361 | |
|---|---|---|
| 564 | 564 | // internal state |
| 565 | 565 | audio_channel m_channel[4]; |
| 566 | 566 | sound_stream * m_stream; |
| 567 | ||
| 567 | ||
| 568 | 568 | TIMER_CALLBACK_MEMBER( signal_irq ); |
| 569 | 569 | }; |
| 570 | 570 |
| r25360 | r25361 | |
|---|---|---|
| 66 | 66 | optional_device<tc0220ioc_device> m_tc0220ioc; |
| 67 | 67 | optional_device<tc0510nio_device> m_tc0510nio; |
| 68 | 68 | optional_device<mb87078_device> m_mb87078; |
| 69 | ||
| 69 | ||
| 70 | 70 | DECLARE_WRITE8_MEMBER(bankswitch_w); |
| 71 | 71 | DECLARE_READ16_MEMBER(tracky1_hi_r); |
| 72 | 72 | DECLARE_READ16_MEMBER(tracky1_lo_r); |
| r25360 | r25361 | |
|---|---|---|
| 17 | 17 | |
| 18 | 18 | optional_device<atari_motion_objects_device> m_mob; |
| 19 | 19 | required_shared_ptr<UINT16> m_bitmap; |
| 20 | ||
| 20 | ||
| 21 | 21 | virtual void update_interrupts(); |
| 22 | 22 | virtual void scanline_update(screen_device &screen, int scanline); |
| 23 | 23 | DECLARE_WRITE16_MEMBER(latch_w); |
| r25360 | r25361 | |
|---|---|---|
| 22 | 22 | m_color_xlat(*this, "color_xlat"){ } |
| 23 | 23 | |
| 24 | 24 | required_device<cpu_device> m_maincpu; // V60 |
| 25 | required_device<segam1audio_device> m_m1audio; | |
| 25 | required_device<segam1audio_device> m_m1audio; // Model 1 standard sound board | |
| 26 | 26 | optional_device<dsbz80_device> m_dsbz80; // Digital Sound Board |
| 27 | 27 | optional_device<mb86233_cpu_device> m_tgp; |
| 28 | 28 |
| r25360 | r25361 | |
|---|---|---|
| 40 | 40 | required_shared_ptr<UINT32> m_lumaram; |
| 41 | 41 | optional_shared_ptr<UINT16> m_soundram; |
| 42 | 42 | optional_shared_ptr<UINT32> m_tgp_program; |
| 43 | ||
| 43 | ||
| 44 | 44 | required_device<i960_cpu_device> m_maincpu; |
| 45 | 45 | optional_device<dsbz80_device> m_dsbz80; // Z80-based MPEG Digital Sound Board |
| 46 | optional_device<segam1audio_device> m_m1audio; | |
| 46 | optional_device<segam1audio_device> m_m1audio; // Model 1 standard sound board | |
| 47 | 47 | optional_device<cpu_device> m_audiocpu; |
| 48 | 48 | optional_device<cpu_device> m_tgp; |
| 49 | 49 | optional_device<cpu_device> m_dsp; |
| r25360 | r25361 | |
|---|---|---|
| 12 | 12 | sprites(*this, "sprites") , |
| 13 | 13 | m_maincpu(*this, "maincpu"), |
| 14 | 14 | m_seibu_sound(*this, "seibu_sound") { } |
| 15 | ||
| 15 | ||
| 16 | 16 | required_shared_ptr<UINT16> back_data,fore_data,mid_data, text_data, sprites; |
| 17 | 17 | required_device<cpu_device> m_maincpu; |
| 18 | 18 | required_device<seibu_sound_device> m_seibu_sound; |
| r25360 | r25361 | |
|---|---|---|
| 20 | 20 | required_shared_ptr<UINT8> m_spriteram2; |
| 21 | 21 | required_shared_ptr<UINT8> m_spriteram3; |
| 22 | 22 | required_shared_ptr<UINT8> m_videoram; |
| 23 | ||
| 23 | ||
| 24 | 24 | required_device<cpu_device> m_maincpu; |
| 25 | 25 | required_device<mjkjidai_adpcm_device> m_mjk_adpcm; |
| 26 | 26 | |
| r25360 | r25361 | |
| 48 | 48 | public: |
| 49 | 49 | mjkjidai_adpcm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 50 | 50 | ~mjkjidai_adpcm_device() {} |
| 51 | ||
| 51 | ||
| 52 | 52 | void mjkjidai_adpcm_play (int offset, int length); |
| 53 | 53 | |
| 54 | 54 | protected: |
| r25360 | r25361 | |
|---|---|---|
| 124 | 124 | { |
| 125 | 125 | public: |
| 126 | 126 | namcos22_renderer(namcos22_state &state); |
| 127 | ||
| 127 | ||
| 128 | 128 | void render_scene(screen_device &screen, bitmap_rgb32 &bitmap); |
| 129 | 129 | struct namcos22_scenenode *new_scenenode(running_machine &machine, UINT32 zsort, namcos22_scenenode_type type); |
| 130 | 130 | |
| r25360 | r25361 | |
| 306 | 306 | float m_camera_lz; // " |
| 307 | 307 | int m_camera_ambient; // 0.0..1.0 |
| 308 | 308 | int m_camera_power; // 0.0..1.0 |
| 309 | ||
| 309 | ||
| 310 | 310 | DECLARE_WRITE32_MEMBER(namcos22s_czram_w); |
| 311 | 311 | DECLARE_READ32_MEMBER(namcos22s_czram_r); |
| 312 | 312 | DECLARE_READ32_MEMBER(namcos22s_vics_control_r); |
| r25360 | r25361 | |
| 396 | 396 | |
| 397 | 397 | inline UINT8 nthbyte(const UINT32 *src, int n) { return (src[n / 4] << ((n & 3) * 8)) >> 24; } |
| 398 | 398 | inline UINT16 nthword(const UINT32 *src, int n) { return (src[n / 2] << ((n & 1) * 16)) >> 16; } |
| 399 | ||
| 399 | ||
| 400 | 400 | inline INT32 signed18(INT32 val) { return (val & 0x00020000) ? (INT32)(val | 0xfffc0000) : val & 0x0001ffff; } |
| 401 | 401 | inline INT32 signed24(INT32 val) { return (val & 0x00800000) ? (INT32)(val | 0xff000000) : val & 0x007fffff; } |
| 402 | ||
| 402 | ||
| 403 | 403 | inline float dspfixed_to_nativefloat(INT16 val) { return val / (float)0x7fff; } |
| 404 | 404 | float dspfloat_to_nativefloat(UINT32 val); |
| 405 | ||
| 405 | ||
| 406 | 406 | void handle_driving_io(); |
| 407 | 407 | void handle_coinage(int slots, int address_is_odd); |
| 408 | 408 | void handle_cybrcomm_io(); |
| r25360 | r25361 | |
| 412 | 412 | void slave_halt(); |
| 413 | 413 | void slave_enable(); |
| 414 | 414 | void enable_slave_simulation(bool enable); |
| 415 | ||
| 415 | ||
| 416 | 416 | void matrix3d_multiply(float a[4][4], float b[4][4]); |
| 417 | 417 | void matrix3d_identity(float m[4][4]); |
| 418 | 418 | void transform_point(float *vx, float *vy, float *vz, float m[4][4]); |
| 419 | 419 | void transform_normal(float *nx, float *ny, float *nz, float m[4][4]); |
| 420 | 420 | void register_normals(INT32 addr, float m[4][4]); |
| 421 | ||
| 421 | ||
| 422 | 422 | void blit_single_quad(bitmap_rgb32 &bitmap, UINT32 color, UINT32 addr, float m[4][4], INT32 polyshift, int flags, int packetformat); |
| 423 | 423 | void blit_quads(bitmap_rgb32 &bitmap, INT32 addr, float m[4][4], INT32 base); |
| 424 | 424 | void blit_polyobject(bitmap_rgb32 &bitmap, int code, float m[4][4]); |
| 425 | ||
| 425 | ||
| 426 | 426 | void slavesim_handle_bb0003(const INT32 *src); |
| 427 | 427 | void slavesim_handle_200002(bitmap_rgb32 &bitmap, const INT32 *src); |
| 428 | 428 | void slavesim_handle_300000(const INT32 *src); |
| 429 | 429 | void slavesim_handle_233002(const INT32 *src); |
| 430 | 430 | void simulate_slavedsp(bitmap_rgb32 &bitmap); |
| 431 | ||
| 431 | ||
| 432 | 432 | INT32 point_read(INT32 addr); |
| 433 | 433 | void init_tables(); |
| 434 | 434 | void update_mixer(); |
| r25360 | r25361 | |
| 441 | 441 | void draw_text_layer(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); |
| 442 | 442 | void namcos22s_mix_text_layer(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, int prival); |
| 443 | 443 | void namcos22_mix_text_layer(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); |
| 444 | ||
| 444 | ||
| 445 | 445 | void install_c74_speedup(); |
| 446 | 446 | void install_130_speedup(); |
| 447 | 447 | void install_141_speedup(); |
| r25360 | r25361 | |
|---|---|---|
| 86 | 86 | DECLARE_WRITE16_MEMBER( atarisy1_xscroll_w ); |
| 87 | 87 | DECLARE_WRITE16_MEMBER( atarisy1_yscroll_w ); |
| 88 | 88 | DECLARE_WRITE16_MEMBER( atarisy1_priority_w ); |
| 89 | ||
| 89 | ||
| 90 | 90 | static const atari_motion_objects_config s_mob_config; |
| 91 | 91 | }; |
| r25360 | r25361 | |
|---|---|---|
| 40 | 40 | UINT8 m_samurai_protection_data; |
| 41 | 41 | int m_nsub_coin_counter; |
| 42 | 42 | int m_nsub_play_counter; |
| 43 | ||
| 43 | ||
| 44 | 44 | int m_port1State; |
| 45 | 45 | int m_port2State; |
| 46 | 46 | int m_psgData; |
| r25360 | r25361 | |
| 79 | 79 | DECLARE_READ8_MEMBER(invinco_io_r); |
| 80 | 80 | DECLARE_WRITE8_MEMBER(invinco_io_w); |
| 81 | 81 | DECLARE_WRITE8_MEMBER(vicdual_palette_bank_w); |
| 82 | ||
| 82 | ||
| 83 | 83 | /*----------- defined in audio/vicdual.c -----------*/ |
| 84 | 84 | DECLARE_WRITE8_MEMBER( frogs_audio_w ); |
| 85 | 85 | DECLARE_WRITE8_MEMBER( headon_audio_w ); |
| 86 | 86 | DECLARE_WRITE8_MEMBER( invho2_audio_w ); |
| 87 | 87 | TIMER_CALLBACK_MEMBER( frogs_croak_callback ); |
| 88 | 88 | |
| 89 | ||
| 89 | ||
| 90 | 90 | /*----------- defined in audio/carnival.c -----------*/ |
| 91 | 91 | DECLARE_WRITE8_MEMBER( carnival_audio_1_w ); |
| 92 | 92 | DECLARE_WRITE8_MEMBER( carnival_audio_2_w ); |
| 93 | 93 | DECLARE_READ8_MEMBER( carnival_music_port_t1_r ); |
| 94 | 94 | DECLARE_WRITE8_MEMBER( carnival_music_port_1_w ); |
| 95 | 95 | DECLARE_WRITE8_MEMBER( carnival_music_port_2_w ); |
| 96 | ||
| 96 | ||
| 97 | 97 | /*----------- defined in audio/depthch.c -----------*/ |
| 98 | 98 | DECLARE_WRITE8_MEMBER( depthch_audio_w ); |
| 99 | ||
| 99 | ||
| 100 | 100 | /*----------- defined in audio/invinco.c -----------*/ |
| 101 | 101 | DECLARE_WRITE8_MEMBER( invinco_audio_w ); |
| 102 | ||
| 102 | ||
| 103 | 103 | /*----------- defined in audio/pulsar.c -----------*/ |
| 104 | 104 | DECLARE_WRITE8_MEMBER( pulsar_audio_1_w ); |
| 105 | 105 | DECLARE_WRITE8_MEMBER( pulsar_audio_2_w ); |
| r25360 | r25361 | |
|---|---|---|
| 19 | 19 | m_mob(*this, "mob") { } |
| 20 | 20 | |
| 21 | 21 | required_device<atari_jsa_i_device> m_jsa; |
| 22 | required_device<tilemap_device> m_playfield_tilemap; | |
| 23 | required_device<tilemap_device> m_alpha_tilemap; | |
| 22 | required_device<tilemap_device> m_playfield_tilemap; | |
| 23 | required_device<tilemap_device> m_alpha_tilemap; | |
| 24 | 24 | required_device<atari_motion_objects_device> m_mob; |
| 25 | ||
| 25 | ||
| 26 | 26 | UINT16 m_h256; |
| 27 | 27 | virtual void update_interrupts(); |
| 28 | 28 | DECLARE_READ16_MEMBER(special_port1_r); |
| r25360 | r25361 | |
|---|---|---|
| 450 | 450 | UINT16 ver_offset; |
| 451 | 451 | UINT8 extbg; |
| 452 | 452 | } m_mode7; |
| 453 | ||
| 453 | ||
| 454 | 454 | screen_device *m_screen; |
| 455 | 455 | |
| 456 | 456 | UINT8 m_mosaic_size; |
| r25360 | r25361 | |
|---|---|---|
| 279 | 279 | UINT8 coverage[256]; // coverage is how much of the table we've managed to verify using known facts about the table structure |
| 280 | 280 | |
| 281 | 281 | int command_31_write_type; |
| 282 | ||
| 283 | 282 | |
| 283 | ||
| 284 | 284 | // the maximum level size returned or read by the device appears to be this size |
| 285 | 285 | UINT16 level_structure[8][10]; |
| 286 | 286 |
| r25360 | r25361 | |
|---|---|---|
| 12 | 12 | galaxia_state(const machine_config &mconfig, device_type type, const char *tag) |
| 13 | 13 | : cvs_state(mconfig, type, tag) { } |
| 14 | 14 | |
| 15 | ||
| 15 | ||
| 16 | 16 | tilemap_t *m_bg_tilemap; |
| 17 | 17 | bitmap_ind16 m_temp_bitmap; |
| 18 | 18 | DECLARE_WRITE8_MEMBER(galaxia_video_w); |
| r25360 | r25361 | |
|---|---|---|
| 17 | 17 | DECLARE_MACHINE_START(superman); |
| 18 | 18 | void reset_sound_region(); |
| 19 | 19 | DECLARE_WRITE_LINE_MEMBER(irqhandler); |
| 20 | ||
| 20 | ||
| 21 | 21 | // superman c-chip |
| 22 | 22 | UINT16 m_current_bank; |
| 23 | 23 | UINT8 m_cc_port; |
| r25360 | r25361 | |
| 26 | 26 | DECLARE_WRITE16_MEMBER( cchip1_ctrl_w ); |
| 27 | 27 | DECLARE_WRITE16_MEMBER( cchip1_bank_w ); |
| 28 | 28 | DECLARE_WRITE16_MEMBER( cchip1_ram_w ); |
| 29 | }; | |
| No newline at end of file | ||
| 29 | }; |
| r25360 | r25361 | |
|---|---|---|
| 76 | 76 | UINT16 * m_dsk_zram; |
| 77 | 77 | UINT16 * m_m68k_slapstic_base; |
| 78 | 78 | UINT16 * m_m68k_sloop_alt_base; |
| 79 | ||
| 79 | ||
| 80 | 80 | required_shared_ptr<UINT16> m_zram; |
| 81 | 81 | |
| 82 | 82 | optional_shared_ptr<UINT16> m_adsp_data_memory; |
| r25360 | r25361 | |
|---|---|---|
| 28 | 28 | required_shared_ptr<UINT8> m_videoram; |
| 29 | 29 | required_shared_ptr<UINT8> m_colorram; |
| 30 | 30 | required_shared_ptr<UINT8> m_charram; |
| 31 | ||
| 31 | ||
| 32 | 32 | required_device<cpu_device> m_maincpu; |
| 33 | 33 | required_device<snk6502_sound_device> m_sound; |
| 34 | 34 | |
| r25360 | r25361 | |
| 102 | 102 | DECLARE_WRITE8_MEMBER( vanguard_speech_w ); |
| 103 | 103 | DECLARE_WRITE8_MEMBER( fantasy_sound_w ); |
| 104 | 104 | DECLARE_WRITE8_MEMBER( fantasy_speech_w ); |
| 105 | ||
| 105 | ||
| 106 | 106 | void set_music_clock(double clock_time); |
| 107 | 107 | void set_music_freq(int freq); |
| 108 | 108 | int music0_playing(); |
| r25360 | r25361 | |
| 131 | 131 | UINT32 m_hd38880_addr; |
| 132 | 132 | int m_hd38880_data_bytes; |
| 133 | 133 | double m_hd38880_speed; |
| 134 | ||
| 134 | ||
| 135 | 135 | inline void validate_tone_channel(int channel); |
| 136 | 136 | void sasuke_build_waveform(int mask); |
| 137 | 137 | void satansat_build_waveform(int mask); |
| r25360 | r25361 | |
|---|---|---|
| 50 | 50 | required_device<filter_volume_device> m_filter3; |
| 51 | 51 | |
| 52 | 52 | // Misc |
| 53 | UINT16 m_cpua_ctrl; | |
| 54 | INT32 m_ioc220_port; | |
| 53 | UINT16 m_cpua_ctrl; | |
| 54 | INT32 m_ioc220_port; | |
| 55 | 55 | |
| 56 | 56 | // ADPCM |
| 57 | UINT8 *m_msm_rom[2]; | |
| 58 | UINT16 m_msm_pos[2]; | |
| 59 | UINT8 m_msm_reset[2]; | |
| 60 | UINT8 m_msm_nibble[2]; | |
| 61 | UINT8 m_msm2_vck; | |
| 62 | UINT8 m_msm2_vck2; | |
| 57 | UINT8 *m_msm_rom[2]; | |
| 58 | UINT16 m_msm_pos[2]; | |
| 59 | UINT8 m_msm_reset[2]; | |
| 60 | UINT8 m_msm_nibble[2]; | |
| 61 | UINT8 m_msm2_vck; | |
| 62 | UINT8 m_msm2_vck2; | |
| 63 | 63 | |
| 64 | 64 | #ifdef MAME_DEBUG |
| 65 | UINT8 | |
| 65 | UINT8 m_dislayer[5]; | |
| 66 | 66 | #endif |
| 67 | 67 | |
| 68 | 68 | // drivers/topspeed.c |
| r25360 | r25361 | |
|---|---|---|
| 288 | 288 | |
| 289 | 289 | DECLARE_WRITE16_MEMBER( write ); |
| 290 | 290 | DECLARE_READ16_MEMBER( read ); |
| 291 | ||
| 292 | 291 | |
| 292 | ||
| 293 | 293 | void set_gfxbank(UINT8 gfxbank); |
| 294 | ||
| 294 | ||
| 295 | 295 | UINT32 update_screen(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); |
| 296 | ||
| 296 | ||
| 297 | 297 | INTERRUPT_GEN_MEMBER( timed_interrupt ); |
| 298 | ||
| 298 | ||
| 299 | 299 | // to be removed |
| 300 | DECLARE_READ16_MEMBER( debug_trigger_r ); | |
| 300 | DECLARE_READ16_MEMBER( debug_trigger_r ); | |
| 301 | 301 | protected: |
| 302 | 302 | // device-level overrides |
| 303 | 303 | virtual void device_start(); |
| r25360 | r25361 | |
| 326 | 326 | void SetPreShortcuts(int reg, int data ); |
| 327 | 327 | void SetPostShortcuts(int reg); |
| 328 | 328 | void ShowYGV608Registers(); |
| 329 | ||
| 329 | ||
| 330 | 330 | union { |
| 331 | 331 | UINT8 b[8]; |
| 332 | 332 | YGV_PORTS s; |
| r25360 | r25361 | |
| 369 | 369 | UINT32 m_base_y_shift; // for extracting pattern y coord 'base' |
| 370 | 370 | |
| 371 | 371 | UINT8 m_screen_resize; // screen requires resize |
| 372 | UINT8 m_tilemap_resize; // tilemap requires resize | |
| 372 | UINT8 m_tilemap_resize; // tilemap requires resize | |
| 373 | 373 | }; |
| 374 | 374 | |
| 375 | 375 | // device type definition |
| r25360 | r25361 | |
|---|---|---|
| 124 | 124 | UINT8 DstAlpha; |
| 125 | 125 | UINT32 DstColor; |
| 126 | 126 | }; |
| 127 | ||
| 127 | ||
| 128 | 128 | /* |
| 129 | 129 | Pick a rare enough color to disable transparency (that way I save a cmp per loop to check |
| 130 | 130 | if I must draw transparent or not. The palette build will take this color in account so |
| r25360 | r25361 | |
|---|---|---|
| 44 | 44 | ~vr0video_device() {} |
| 45 | 45 | |
| 46 | 46 | int vrender0_ProcessPacket(UINT32 PacketPtr, UINT16 *Dest, UINT8 *TEXTURE); |
| 47 | ||
| 47 | ||
| 48 | 48 | protected: |
| 49 | 49 | // device-level overrides |
| 50 | 50 | virtual void device_config_complete(); |
| r25360 | r25361 | |
| 59 | 59 | UINT32 m_LastPalUpdate; |
| 60 | 60 | |
| 61 | 61 | RenderStateInfo m_RenderState; |
| 62 | ||
| 62 | ||
| 63 | 63 | UINT16 Alpha(UINT16 Src, UINT16 Dst); |
| 64 | 64 | }; |
| 65 | 65 |
| r25360 | r25361 | |
|---|---|---|
| 63 | 63 | { |
| 64 | 64 | for (int i = 0; i < 65; i++) |
| 65 | 65 | m_segbuffer[i] = 0; |
| 66 | ||
| 66 | ||
| 67 | 67 | for (int i = 0; i < DM_BYTESPERROW; i++) |
| 68 | 68 | m_scanline[i] = 0; |
| 69 | 69 | } |
| r25360 | r25361 | |
| 98 | 98 | save_item(NAME(m_xcounter)); |
| 99 | 99 | save_item(NAME(m_busy)); |
| 100 | 100 | save_item(NAME(m_comdata)); |
| 101 | ||
| 101 | ||
| 102 | 102 | for (int i = 0; i < 65; i++) |
| 103 | 103 | save_item(NAME(m_segbuffer), i); |
| 104 | ||
| 104 | ||
| 105 | 105 | for (int i = 0; i < DM_BYTESPERROW; i++) |
| 106 | 106 | save_item(NAME(m_scanline), i); |
| 107 | 107 | } |
| r25360 | r25361 | |
|---|---|---|
| 28 | 28 | DECLARE_WRITE8_MEMBER( comm_w ); |
| 29 | 29 | DECLARE_READ8_MEMBER( unknown_r ); |
| 30 | 30 | DECLARE_WRITE8_MEMBER( unknown_w ); |
| 31 | ||
| 31 | ||
| 32 | 32 | void writedata(UINT8 data); |
| 33 | 33 | int busy(void); |
| 34 | 34 | |
| r25360 | r25361 | |
| 38 | 38 | virtual void device_config_complete(); |
| 39 | 39 | virtual void device_start(); |
| 40 | 40 | virtual void device_reset(); |
| 41 | ||
| 41 | ||
| 42 | 42 | private: |
| 43 | 43 | // internal state |
| 44 | 44 | int m_data_avail; |
| r25360 | r25361 | |
| 49 | 49 | |
| 50 | 50 | UINT8 m_scanline[DM_BYTESPERROW]; |
| 51 | 51 | UINT8 m_comdata; |
| 52 | ||
| 52 | ||
| 53 | 53 | int read_data(void); |
| 54 | ||
| 54 | ||
| 55 | 55 | }; |
| 56 | 56 | |
| 57 | 57 | extern const device_type BF_DM01; |
| r25360 | r25361 | |
|---|---|---|
| 164 | 164 | |
| 165 | 165 | tia_video_device::tia_video_device(const machine_config &mconfig, device_type type, const char *name, const char *shortname, const char *tag, device_t *owner, UINT32 clock) |
| 166 | 166 | : device_t(mconfig, type, name, tag, owner, clock, shortname, __FILE__), |
| 167 | | |
| 167 | device_video_interface(mconfig, *this) | |
| 168 | 168 | { |
| 169 | 169 | } |
| 170 | 170 |
| r25360 | r25361 | |
|---|---|---|
| 31 | 31 | #define MCFG_TIA_PAL_VIDEO_ADD(_tag, _config) \ |
| 32 | 32 | MCFG_DEVICE_ADD(_tag, TIA_PAL_VIDEO, 0) \ |
| 33 | 33 | MCFG_DEVICE_CONFIG(_config) |
| 34 | ||
| 34 | ||
| 35 | 35 | #define MCFG_TIA_NTSC_VIDEO_ADD(_tag, _config) \ |
| 36 | 36 | MCFG_DEVICE_ADD(_tag, TIA_NTSC_VIDEO, 0) \ |
| 37 | 37 | MCFG_DEVICE_CONFIG(_config) |
| r25360 | r25361 | |
| 61 | 61 | |
| 62 | 62 | DECLARE_READ8_MEMBER( read ); |
| 63 | 63 | DECLARE_WRITE8_MEMBER( write ); |
| 64 | ||
| 64 | ||
| 65 | 65 | protected: |
| 66 | 66 | // construction/destruction |
| 67 | 67 | tia_video_device(const machine_config &mconfig, device_type type, const char *name, const char *shortname, const char *tag, device_t *owner, UINT32 clock); |
| r25360 | r25361 | |
| 211 | 211 | { |
| 212 | 212 | public: |
| 213 | 213 | tia_pal_video_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 214 | ||
| 214 | ||
| 215 | 215 | DECLARE_PALETTE_INIT(tia_pal); |
| 216 | ||
| 216 | ||
| 217 | 217 | protected: |
| 218 | 218 | virtual machine_config_constructor device_mconfig_additions() const; |
| 219 | 219 | }; |
| r25360 | r25361 | |
| 222 | 222 | { |
| 223 | 223 | public: |
| 224 | 224 | tia_ntsc_video_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 225 | ||
| 225 | ||
| 226 | 226 | DECLARE_PALETTE_INIT(tia_ntsc); |
| 227 | ||
| 227 | ||
| 228 | 228 | protected: |
| 229 | 229 | virtual machine_config_constructor device_mconfig_additions() const; |
| 230 | 230 | }; |
| r25360 | r25361 | |
|---|---|---|
| 113 | 113 | |
| 114 | 114 | static void |
| 115 | 115 | DrawRozHelper( |
| 116 | screen_device &screen, | |
| 116 | screen_device &screen, | |
| 117 | 117 | bitmap_ind16 &bitmap, |
| 118 | 118 | tilemap_t *tmap, |
| 119 | 119 | const rectangle &clip, |
| r25360 | r25361 | |
| 226 | 226 | } |
| 227 | 227 | else |
| 228 | 228 | { |
| 229 | tmap->draw_roz(screen, | |
| 229 | tmap->draw_roz(screen, | |
| 230 | 230 | bitmap, clip, |
| 231 | 231 | rozInfo->startx, rozInfo->starty, |
| 232 | 232 | rozInfo->incxx, rozInfo->incxy, |
| r25360 | r25361 | |
|---|---|---|
| 614 | 614 | t->textured = texture; |
| 615 | 615 | |
| 616 | 616 | // not textured, abort. |
| 617 | // | |
| 617 | // if (!t->textured) return; | |
| 618 | 618 | |
| 619 | 619 | t->address = textureaddress; |
| 620 | 620 | t->pf = pixelformat; |
| r25360 | r25361 | |
| 664 | 664 | t->vqbase = t->address; |
| 665 | 665 | t->blend = use_alpha ? blend_functions[t->blend_mode] : bl10; |
| 666 | 666 | |
| 667 | // | |
| 667 | // fprintf(stderr, "tex %d %d %d %d\n", t->pf, t->mode, pal_ram_ctrl, t->mipmapped); | |
| 668 | 668 | if(!t->textured) |
| 669 | 669 | { |
| 670 | 670 | t->coltype = coltype; |
| r25360 | r25361 | |
| 1002 | 1002 | sanitycount++; |
| 1003 | 1003 | // prevent infinite loop if asked to process invalid data |
| 1004 | 1004 | //if(sanitycount>2000) |
| 1005 | // | |
| 1005 | // break; | |
| 1006 | 1006 | } |
| 1007 | // | |
| 1007 | // printf("ISP START %d %d\n",sanitycount,m_screen->vpos()); | |
| 1008 | 1008 | /* Fire ISP irq after a set amount of time TODO: timing of this */ |
| 1009 | 1009 | endofrender_timer_isp->adjust(state->m_maincpu->cycles_to_attotime(sanitycount*25)); |
| 1010 | 1010 | break; |
| r25360 | r25361 | |
| 1184 | 1184 | COMBINE_DATA(&spg_vblank_int); |
| 1185 | 1185 | |
| 1186 | 1186 | /* clear pending irqs and modify them with the updated ones */ |
| 1187 | // vbin_timer->adjust(attotime::never); | |
| 1188 | // vbout_timer->adjust(attotime::never); | |
| 1187 | // vbin_timer->adjust(attotime::never); | |
| 1188 | // vbout_timer->adjust(attotime::never); | |
| 1189 | 1189 | |
| 1190 | // vbin_timer->adjust(m_screen->time_until_pos(spg_vblank_int & 0x3ff)); | |
| 1191 | // vbout_timer->adjust(m_screen->time_until_pos((spg_vblank_int >> 16) & 0x3ff)); | |
| 1190 | // vbin_timer->adjust(m_screen->time_until_pos(spg_vblank_int & 0x3ff)); | |
| 1191 | // vbout_timer->adjust(m_screen->time_until_pos((spg_vblank_int >> 16) & 0x3ff)); | |
| 1192 | 1192 | } |
| 1193 | 1193 | |
| 1194 | 1194 | READ32_MEMBER( powervr2_device::spg_control_r ) |
| r25360 | r25361 | |
| 1316 | 1316 | UINT32 hsync = ((m_screen->hpos() >= spg_hbstart) || (m_screen->hpos() < spg_hbend)) ? 0 : 1; |
| 1317 | 1317 | /* FIXME: following is just a wild guess */ |
| 1318 | 1318 | UINT32 blank = ((m_screen->vpos() >= spg_vbstart) || (m_screen->vpos() < spg_vbend) | |
| 1319 | ||
| 1319 | (m_screen->hpos() >= spg_hbstart) || (m_screen->hpos() < spg_hbend)) ? 0 : 1; | |
| 1320 | 1320 | if(vo_control & 4) { blank^=1; } |
| 1321 | 1321 | if(vo_control & 2) { vsync^=1; } |
| 1322 | 1322 | if(vo_control & 1) { hsync^=1; } |
| r25360 | r25361 | |
| 1656 | 1656 | |
| 1657 | 1657 | TIMER_CALLBACK_MEMBER(powervr2_device::transfer_opaque_list_irq) |
| 1658 | 1658 | { |
| 1659 | // | |
| 1659 | // printf("OPLST %d\n",m_screen->vpos()); | |
| 1660 | 1660 | |
| 1661 | 1661 | irq_cb(EOXFER_OPLST_IRQ); |
| 1662 | 1662 | } |
| 1663 | 1663 | |
| 1664 | 1664 | TIMER_CALLBACK_MEMBER(powervr2_device::transfer_opaque_modifier_volume_list_irq) |
| 1665 | 1665 | { |
| 1666 | // | |
| 1666 | // printf("OPMV %d\n",m_screen->vpos()); | |
| 1667 | 1667 | |
| 1668 | 1668 | irq_cb(EOXFER_OPMV_IRQ); |
| 1669 | 1669 | } |
| 1670 | 1670 | |
| 1671 | 1671 | TIMER_CALLBACK_MEMBER(powervr2_device::transfer_translucent_list_irq) |
| 1672 | 1672 | { |
| 1673 | // | |
| 1673 | // printf("TRLST %d\n",m_screen->vpos()); | |
| 1674 | 1674 | |
| 1675 | 1675 | irq_cb(EOXFER_TRLST_IRQ); |
| 1676 | 1676 | } |
| 1677 | 1677 | |
| 1678 | 1678 | TIMER_CALLBACK_MEMBER(powervr2_device::transfer_translucent_modifier_volume_list_irq) |
| 1679 | 1679 | { |
| 1680 | // | |
| 1680 | // printf("TRMV %d\n",m_screen->vpos()); | |
| 1681 | 1681 | |
| 1682 | 1682 | irq_cb(EOXFER_TRMV_IRQ); |
| 1683 | 1683 | } |
| 1684 | 1684 | |
| 1685 | 1685 | TIMER_CALLBACK_MEMBER(powervr2_device::transfer_punch_through_list_irq) |
| 1686 | 1686 | { |
| 1687 | // | |
| 1687 | // printf("PTLST %d\n",m_screen->vpos()); | |
| 1688 | 1688 | |
| 1689 | 1689 | irq_cb(EOXFER_PTLST_IRQ); |
| 1690 | 1690 | } |
| r25360 | r25361 | |
| 2164 | 2164 | float *wbufline; |
| 2165 | 2165 | |
| 2166 | 2166 | // untextured cases aren't handled |
| 2167 | // | |
| 2167 | // if (!ti->textured) return; | |
| 2168 | 2168 | |
| 2169 | 2169 | if(xr < 0 || xl >= 640) |
| 2170 | 2170 | return; |
| r25360 | r25361 | |
| 2908 | 2908 | UINT8 packmode = fb_w_ctrl & 0x7; |
| 2909 | 2909 | UINT8 unpackmode = (fb_r_ctrl & 0x0000000c) >>2; // aka fb_depth |
| 2910 | 2910 | |
| 2911 | // | |
| 2911 | // popmessage("%02x %02x",packmode,unpackmode); | |
| 2912 | 2912 | |
| 2913 | 2913 | switch (packmode) |
| 2914 | 2914 | { |
| r25360 | r25361 | |
| 3003 | 3003 | //INT32 ystart_f2 = (vo_starty >> 16) & 0x3ff; |
| 3004 | 3004 | INT32 hstart = (vo_startx & 0x3ff); |
| 3005 | 3005 | int res_x,res_y; |
| 3006 | // | |
| 3006 | // rectangle fbclip; | |
| 3007 | 3007 | |
| 3008 | 3008 | UINT8 unpackmode = (fb_r_ctrl & 0x0000000c) >>2; // aka fb_depth |
| 3009 | 3009 | UINT8 enable = (fb_r_ctrl & 0x00000001); |
| r25360 | r25361 | |
| 3018 | 3018 | dy++; |
| 3019 | 3019 | dy*=2; // probably depends on interlace mode, fields etc... |
| 3020 | 3020 | |
| 3021 | // | |
| 3021 | // popmessage("%d %d %d %d %d",ystart_f1,ystart_f2,interlace_on,spg_vblank & 0x3ff,(spg_vblank >> 16) & 0x3ff); | |
| 3022 | 3022 | |
| 3023 | 3023 | #if 0 |
| 3024 | 3024 | fbclip.min_x = hstart; |
| r25360 | r25361 | |
| 3345 | 3345 | irq_cb(VBL_IN_IRQ); |
| 3346 | 3346 | |
| 3347 | 3347 | //popmessage("VII %d VOI %d VI %d VO %d VS %d",spg_vblank_int & 0x3ff,(spg_vblank_int >> 16) & 0x3ff,spg_vblank & 0x3ff,(spg_vblank >> 16) & 0x3ff,(spg_load >> 16) & 0x3ff); |
| 3348 | // | |
| 3348 | // vbin_timer->adjust(m_screen->time_until_pos(spg_vblank_int & 0x3ff)); | |
| 3349 | 3349 | } |
| 3350 | 3350 | |
| 3351 | 3351 | TIMER_CALLBACK_MEMBER(powervr2_device::vbout) |
| 3352 | 3352 | { |
| 3353 | 3353 | irq_cb(VBL_OUT_IRQ); |
| 3354 | 3354 | |
| 3355 | // | |
| 3355 | // vbout_timer->adjust(m_screen->time_until_pos((spg_vblank_int >> 16) & 0x3ff)); | |
| 3356 | 3356 | } |
| 3357 | 3357 | |
| 3358 | 3358 | TIMER_CALLBACK_MEMBER(powervr2_device::hbin) |
| r25360 | r25361 | |
| 3388 | 3388 | TIMER_CALLBACK_MEMBER(powervr2_device::endofrender_video) |
| 3389 | 3389 | { |
| 3390 | 3390 | printf("VIDEO END %d\n",m_screen->vpos()); |
| 3391 | // | |
| 3391 | // endofrender_timer_video->adjust(attotime::never); | |
| 3392 | 3392 | } |
| 3393 | 3393 | |
| 3394 | 3394 | TIMER_CALLBACK_MEMBER(powervr2_device::endofrender_tsp) |
| 3395 | 3395 | { |
| 3396 | 3396 | printf("TSP END %d\n",m_screen->vpos()); |
| 3397 | 3397 | |
| 3398 | // endofrender_timer_tsp->adjust(attotime::never); | |
| 3399 | // endofrender_timer_video->adjust(attotime::from_usec(500) ); | |
| 3398 | // endofrender_timer_tsp->adjust(attotime::never); | |
| 3399 | // endofrender_timer_video->adjust(attotime::from_usec(500) ); | |
| 3400 | 3400 | } |
| 3401 | 3401 | |
| 3402 | 3402 | TIMER_CALLBACK_MEMBER(powervr2_device::endofrender_isp) |
| r25360 | r25361 | |
| 3405 | 3405 | irq_cb(EOR_TSP_IRQ); // TSP end of render |
| 3406 | 3406 | irq_cb(EOR_VIDEO_IRQ); // VIDEO end of render |
| 3407 | 3407 | |
| 3408 | // | |
| 3408 | // printf("ISP END %d\n",m_screen->vpos()); | |
| 3409 | 3409 | |
| 3410 | 3410 | endofrender_timer_isp->adjust(attotime::never); |
| 3411 | // | |
| 3411 | // endofrender_timer_tsp->adjust(attotime::from_usec(500) ); | |
| 3412 | 3412 | } |
| 3413 | 3413 | |
| 3414 | 3414 | UINT32 powervr2_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) |
| r25360 | r25361 | |
| 3605 | 3605 | |
| 3606 | 3606 | computedilated(); |
| 3607 | 3607 | |
| 3608 | // vbout_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(powervr2_device::vbout),this)); | |
| 3609 | // vbin_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(powervr2_device::vbin),this)); | |
| 3608 | // vbout_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(powervr2_device::vbout),this)); | |
| 3609 | // vbin_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(powervr2_device::vbin),this)); | |
| 3610 | 3610 | hbin_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(powervr2_device::hbin),this)); |
| 3611 | 3611 | yuv_timer_end = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(powervr2_device::yuv_convert_end),this)); |
| 3612 | 3612 | |
| r25360 | r25361 | |
| 3749 | 3749 | renderselect= -1; |
| 3750 | 3750 | grabsel=0; |
| 3751 | 3751 | |
| 3752 | // vbout_timer->adjust(m_screen->time_until_pos((spg_vblank_int >> 16) & 0x3ff)); | |
| 3753 | // vbin_timer->adjust(m_screen->time_until_pos(spg_vblank_int & 0x3ff)); | |
| 3752 | // vbout_timer->adjust(m_screen->time_until_pos((spg_vblank_int >> 16) & 0x3ff)); | |
| 3753 | // vbin_timer->adjust(m_screen->time_until_pos(spg_vblank_int & 0x3ff)); | |
| 3754 | 3754 | hbin_timer->adjust(m_screen->time_until_pos(0, ((spg_hblank_int >> 16) & 0x3ff)-1)); |
| 3755 | 3755 | |
| 3756 | 3756 | scanline = 0; |
| r25360 | r25361 | |
| 3786 | 3786 | if(vbout_line == vpos) |
| 3787 | 3787 | irq_cb(VBL_OUT_IRQ); |
| 3788 | 3788 | } |
| 3789 |
| r25360 | r25361 | |
|---|---|---|
| 394 | 394 | static inline UINT32 cv_yuv(UINT16 c1, UINT16 c2, int x); |
| 395 | 395 | UINT32 tex_r_yuv_n(texinfo *t, float x, float y); |
| 396 | 396 | UINT32 tex_r_yuv_tw(texinfo *t, float x, float y); |
| 397 | // | |
| 397 | // UINT32 tex_r_yuv_vq(texinfo *t, float x, float y); | |
| 398 | 398 | UINT32 tex_r_1555_n(texinfo *t, float x, float y); |
| 399 | 399 | UINT32 tex_r_1555_tw(texinfo *t, float x, float y); |
| 400 | 400 | UINT32 tex_r_1555_vq(texinfo *t, float x, float y); |
| r25360 | r25361 | |
|---|---|---|
| 74 | 74 | const k001005_interface *intf = reinterpret_cast<const k001005_interface *>(static_config()); |
| 75 | 75 | if (intf != NULL) |
| 76 | 76 | *static_cast<k001005_interface *>(this) = *intf; |
| 77 | ||
| 77 | ||
| 78 | 78 | // or initialize to defaults if none provided |
| 79 | 79 | else |
| 80 | 80 | { |
| r25360 | r25361 | |
| 163 | 163 | m_bitmap_page = 0; |
| 164 | 164 | |
| 165 | 165 | memset(m_prev_v, 0, sizeof(m_prev_v)); |
| 166 | m_prev_poly_type = 0; | |
| 166 | m_prev_poly_type = 0; | |
| 167 | 167 | } |
| 168 | 168 | |
| 169 | 169 | //------------------------------------------------- |
| r25360 | r25361 | |
|---|---|---|
| 31 | 31 | void swap_buffers(); |
| 32 | 32 | void preprocess_texture_data(UINT8 *rom, int length, int gticlub); |
| 33 | 33 | void render_polygons(); |
| 34 | ||
| 34 | ||
| 35 | 35 | #if POLY_DEVICE |
| 36 | ||
| 36 | ||
| 37 | 37 | void draw_scanline( void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid ); |
| 38 | 38 | void draw_scanline_tex( void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid ); |
| 39 | ||
| 40 | ||
| 39 | ||
| 40 | ||
| 41 | 41 | #endif |
| 42 | 42 | |
| 43 | 43 | DECLARE_READ32_MEMBER( read ); |
| r25360 | r25361 | |
|---|---|---|
| 68 | 68 | |
| 69 | 69 | TILE_GET_INFO_MEMBER(ddragon3_state::get_fg_tile_info) |
| 70 | 70 | { |
| 71 | ||
| 72 | ||
| 73 | 71 | UINT16 *tilebase; |
| 74 | 72 | int tileno,colbank; |
| 75 | 73 | |
| r25360 | r25361 | |
| 332 | 330 | |
| 333 | 331 | return 0; |
| 334 | 332 | } |
| 335 |
| r25360 | r25361 | |
|---|---|---|
| 425 | 425 | m_row_effect_offs_n = -1; |
| 426 | 426 | m_row_effect_offs_f = 1; |
| 427 | 427 | |
| 428 | m_background_pen | |
| 428 | m_background_pen = machine().config().m_gfxdecodeinfo[0].color_codes_start + | |
| 429 | 429 | (machine().config().m_gfxdecodeinfo[0].total_color_codes - 1) * |
| 430 | 430 | machine().gfx[0]->granularity(); |
| 431 | 431 | |
| r25360 | r25361 | |
| 1666 | 1666 | |
| 1667 | 1667 | for (int chip = 0; chip < 3; chip++) |
| 1668 | 1668 | { |
| 1669 | // | |
| 1669 | // Sprites: 0x987800 - 0x988fff | |
| 1670 | 1670 | for (color = 0; color < 0x40; color++) |
| 1671 | 1671 | for (pen = 0; pen < 0x10; pen++) |
| 1672 | 1672 | m_palette_map[chip][(color << 8) | pen] = 0x7800/2 + ((color << 4) | pen); |
| 1673 | 1673 | |
| 1674 | // | |
| 1674 | // Tiles: 0x980000 - 0x9803ff | |
| 1675 | 1675 | for (color = 0; color < 0x40; color++) |
| 1676 | 1676 | for (pen = 0; pen < 0x10; pen++) |
| 1677 | 1677 | m_palette_map[chip][0x4000 + ((color << 4) | pen)] = ((color << 4) | pen); |
| r25360 | r25361 | |
|---|---|---|
| 34 | 34 | palette_set_color_rgb(machine(), i, pal1bit(i >> 2) >> 1, pal1bit(i >> 1) >> 1, pal1bit(i >> 0) >> 1); |
| 35 | 35 | palette_set_color_rgb(machine(), i | 8, pal1bit(i >> 2), pal1bit(i >> 1), pal1bit(i >> 0)); |
| 36 | 36 | } |
| 37 | ||
| 37 | ||
| 38 | 38 | // but according to photos, pen 6 is clearly orange instead of dark-yellow, and pen 5 is less dark as well |
| 39 | 39 | // pens 1, 2 and 4 are good though. Maybe we're missing a color prom? |
| 40 | 40 | palette_set_color_rgb(machine(), 0x05, 0xff, 0x00, 0x80); // pink |
| r25360 | r25361 | |
|---|---|---|
| 78 | 78 | |
| 79 | 79 | VIDEO_START_MEMBER(toobin_state,toobin) |
| 80 | 80 | { |
| 81 | ||
| 82 | 81 | /* allocate a playfield bitmap for rendering */ |
| 83 | 82 | m_screen->register_screen_bitmap(m_pfbitmap); |
| 84 | 83 |
| r25360 | r25361 | |
|---|---|---|
| 31 | 31 | |
| 32 | 32 | kaneko16_sprite_device::kaneko16_sprite_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock, device_type type) |
| 33 | 33 | : device_t(mconfig, type, "kaneko16_sprite_device", tag, owner, clock, "kaneko16_sprite", __FILE__), |
| 34 | | |
| 34 | device_video_interface(mconfig, *this) | |
| 35 | 35 | { |
| 36 | 36 | m_keep_sprites = 0; // default disabled for games not using it |
| 37 | 37 |
| r25360 | r25361 | |
|---|---|---|
| 373 | 373 | |
| 374 | 374 | segaic16_video_device::segaic16_video_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 375 | 375 | : device_t(mconfig, SEGAIC16VID, "Sega 16-bit Video", tag, owner, clock, "segaic16_video", __FILE__), |
| 376 | | |
| 376 | device_video_interface(mconfig, *this) | |
| 377 | 377 | { |
| 378 | 378 | } |
| 379 | 379 |
| r25360 | r25361 | |
|---|---|---|
| 89 | 89 | |
| 90 | 90 | |
| 91 | 91 | |
| 92 | class segaic16_video_device : | |
| 92 | class segaic16_video_device : public device_t, | |
| 93 | 93 | public device_video_interface |
| 94 | 94 | { |
| 95 | 95 | public: |
| r25360 | r25361 | |
|---|---|---|
| 37 | 37 | //************************************************************************** |
| 38 | 38 | |
| 39 | 39 | //------------------------------------------------- |
| 40 | // round_to_powerof2: Rounds a number up to the | |
| 41 | // nearest power of 2. Even powers of 2 are | |
| 42 | // rounded up to the next greatest power | |
| 40 | // round_to_powerof2: Rounds a number up to the | |
| 41 | // nearest power of 2. Even powers of 2 are | |
| 42 | // rounded up to the next greatest power | |
| 43 | 43 | // (e.g., 4 returns 8). |
| 44 | 44 | //------------------------------------------------- |
| 45 | 45 | |
| r25360 | r25361 | |
| 66 | 66 | |
| 67 | 67 | atari_rle_objects_device::atari_rle_objects_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 68 | 68 | : device_t(mconfig, ATARI_RLE_OBJECTS, "Atari RLE Motion Objects", tag, owner, clock, "atari_rle", __FILE__), |
| 69 | | |
| 69 | device_video_interface(mconfig, *this) | |
| 70 | 70 | { |
| 71 | 71 | } |
| 72 | 72 | |
| 73 | 73 | |
| 74 | 74 | //------------------------------------------------- |
| 75 | 75 | // static_set_config: Set the tag of the |
| 76 | // | |
| 76 | // sound CPU | |
| 77 | 77 | //------------------------------------------------- |
| 78 | 78 | |
| 79 | 79 | void atari_rle_objects_device::static_set_config(device_t &device, const atari_rle_objects_config &config) |
| r25360 | r25361 | |
| 84 | 84 | |
| 85 | 85 | |
| 86 | 86 | //------------------------------------------------- |
| 87 | // control_write: Write handler for MO control | |
| 88 | // bits. | |
| 87 | // control_write: Write handler for MO control | |
| 88 | // bits. | |
| 89 | 89 | //------------------------------------------------- |
| 90 | 90 | |
| 91 | 91 | WRITE8_MEMBER(atari_rle_objects_device::control_write) |
| r25360 | r25361 | |
| 137 | 137 | |
| 138 | 138 | |
| 139 | 139 | //------------------------------------------------- |
| 140 | // command_write: Write handler for MO command | |
| 141 | // bits. | |
| 140 | // command_write: Write handler for MO command | |
| 141 | // bits. | |
| 142 | 142 | //------------------------------------------------- |
| 143 | 143 | |
| 144 | 144 | WRITE8_MEMBER(atari_rle_objects_device::command_write) |
| r25360 | r25361 | |
| 178 | 178 | |
| 179 | 179 | |
| 180 | 180 | //------------------------------------------------- |
| 181 | // device_start: Configures the motion objects | |
| 182 | // using the input description. Allocates all | |
| 183 | // memory necessary and generates the attribute | |
| 181 | // device_start: Configures the motion objects | |
| 182 | // using the input description. Allocates all | |
| 183 | // memory necessary and generates the attribute | |
| 184 | 184 | // lookup table. |
| 185 | 185 | //------------------------------------------------- |
| 186 | 186 | |
| r25360 | r25361 | |
| 284 | 284 | |
| 285 | 285 | |
| 286 | 286 | //------------------------------------------------- |
| 287 | // build_rle_tables: Builds internal table for | |
| 287 | // build_rle_tables: Builds internal table for | |
| 288 | 288 | // RLE mapping. |
| 289 | 289 | //------------------------------------------------- |
| 290 | 290 | |
| r25360 | r25361 | |
| 439 | 439 | |
| 440 | 440 | |
| 441 | 441 | //------------------------------------------------- |
| 442 | // compute_checksum: Compute the checksum values | |
| 443 | // on the ROMs. | |
| 442 | // compute_checksum: Compute the checksum values | |
| 443 | // on the ROMs. | |
| 444 | 444 | //------------------------------------------------- |
| 445 | 445 | |
| 446 | 446 | void atari_rle_objects_device::compute_checksum() |
| r25360 | r25361 | |
| 458 | 458 | |
| 459 | 459 | |
| 460 | 460 | //------------------------------------------------- |
| 461 | // sort_and_render: Render all motion objects in | |
| 462 | // order. | |
| 461 | // sort_and_render: Render all motion objects in | |
| 462 | // order. | |
| 463 | 463 | //------------------------------------------------- |
| 464 | 464 | |
| 465 | 465 | void atari_rle_objects_device::sort_and_render() |
| 466 | { | |
| 466 | { | |
| 467 | 467 | // struct for sorting |
| 468 | 468 | struct sort_entry_t |
| 469 | 469 | { |
| 470 | sort_entry_t * | |
| 470 | sort_entry_t * next; | |
| 471 | 471 | int entry; |
| 472 | 472 | }; |
| 473 | 473 | |
| r25360 | r25361 | |
| 538 | 538 | if (info.data == NULL) |
| 539 | 539 | return; |
| 540 | 540 | |
| 541 | // | |
| 541 | // | |
| 542 | 542 | int scaled_xoffs = (xscale * info.xoffs) >> 12; |
| 543 | 543 | int scaled_yoffs = (yscale * info.yoffs) >> 12; |
| 544 | 544 | |
| r25360 | r25361 | |
| 567 | 567 | |
| 568 | 568 | |
| 569 | 569 | //------------------------------------------------- |
| 570 | // draw_rle_zoom: Draw an RLE-compressed object to | |
| 570 | // draw_rle_zoom: Draw an RLE-compressed object to | |
| 571 | 571 | // a 16-bit bitmap. |
| 572 | 572 | //------------------------------------------------- |
| 573 | 573 | |
| r25360 | r25361 | |
| 745 | 745 | |
| 746 | 746 | |
| 747 | 747 | //------------------------------------------------- |
| 748 | // draw_rle_zoom_hflip: Draw an RLE-compressed | |
| 749 | // object to a 16-bit bitmap with horizontal | |
| 748 | // draw_rle_zoom_hflip: Draw an RLE-compressed | |
| 749 | // object to a 16-bit bitmap with horizontal | |
| 750 | 750 | // flip. |
| 751 | 751 | //------------------------------------------------- |
| 752 | 752 | |
| r25360 | r25361 | |
| 924 | 924 | |
| 925 | 925 | //------------------------------------------------- |
| 926 | 926 | // hilite_object: Hilight an object by drawing a |
| 927 | // | |
| 927 | // flashing box around it | |
| 928 | 928 | //------------------------------------------------- |
| 929 | 929 | |
| 930 | 930 | void atari_rle_objects_device::hilite_object(bitmap_ind16 &bitmap, int hilite) |
| r25360 | r25361 | |
| 1031 | 1031 | //------------------------------------------------- |
| 1032 | 1032 | |
| 1033 | 1033 | atari_rle_objects_device::sprite_parameter::sprite_parameter() |
| 1034 | : m_word(0), | |
| 1035 | m_shift(0), | |
| 1036 | m_mask(0) | |
| 1034 | : m_word(0), | |
| 1035 | m_shift(0), | |
| 1036 | m_mask(0) | |
| 1037 | 1037 | { |
| 1038 | 1038 | } |
| 1039 | 1039 |
| r25360 | r25361 | |
|---|---|---|
| 84 | 84 | UINT16 m_rightclip; // right clip coordinate |
| 85 | 85 | UINT16 m_palettebase; // base palette entry |
| 86 | 86 | |
| 87 | entry m_code_entry; // mask for the code index | |
| 88 | entry m_color_entry; // mask for the color | |
| 89 | entry m_xpos_entry; // mask for the X position | |
| 90 | entry m_ypos_entry; // mask for the Y position | |
| 91 | entry m_scale_entry; // mask for the scale factor | |
| 92 | entry m_hflip_entry; // mask for the horizontal flip | |
| 93 | entry m_order_entry; // mask for the order | |
| 94 | entry m_priority_entry; // mask for the priority | |
| 95 | entry m_vram_entry; // mask for the VRAM target | |
| 87 | entry m_code_entry; // mask for the code index | |
| 88 | entry m_color_entry; // mask for the color | |
| 89 | entry m_xpos_entry; // mask for the X position | |
| 90 | entry m_ypos_entry; // mask for the Y position | |
| 91 | entry m_scale_entry; // mask for the scale factor | |
| 92 | entry m_hflip_entry; // mask for the horizontal flip | |
| 93 | entry m_order_entry; // mask for the order | |
| 94 | entry m_priority_entry; // mask for the priority | |
| 95 | entry m_vram_entry; // mask for the VRAM target | |
| 96 | 96 | }; |
| 97 | 97 | |
| 98 | 98 | |
| r25360 | r25361 | |
| 102 | 102 | extern const device_type ATARI_RLE_OBJECTS; |
| 103 | 103 | |
| 104 | 104 | class atari_rle_objects_device : public device_t, |
| 105 | public device_video_interface, | |
| 106 | public atari_rle_objects_config | |
| 105 | public device_video_interface, | |
| 106 | public atari_rle_objects_config | |
| 107 | 107 | { |
| 108 | 108 | public: |
| 109 | 109 | // construction/destruction |
| r25360 | r25361 | |
| 111 | 111 | |
| 112 | 112 | // static configuration helpers |
| 113 | 113 | static void static_set_config(device_t &device, const atari_rle_objects_config &config); |
| 114 | ||
| 114 | ||
| 115 | 115 | // control handlers |
| 116 | 116 | DECLARE_WRITE8_MEMBER(control_write); |
| 117 | 117 | DECLARE_WRITE8_MEMBER(command_write); |
| 118 | 118 | |
| 119 | 119 | // render helpers |
| 120 | 120 | void vblank_callback(screen_device &screen, bool state); |
| 121 | ||
| 121 | ||
| 122 | 122 | // getters |
| 123 | 123 | bitmap_ind16 &vram(int idx) { return m_vram[idx][(m_control_bits & ATARIRLE_CONTROL_FRAME) >> 2]; } |
| 124 | 124 | |
| r25360 | r25361 | |
| 140 | 140 | UINT16 mask() const { return m_mask; } |
| 141 | 141 | |
| 142 | 142 | private: |
| 143 | UINT16 m_word; // word index | |
| 144 | UINT16 m_shift; // shift amount | |
| 145 | UINT16 m_mask; // final mask | |
| 143 | UINT16 m_word; // word index | |
| 144 | UINT16 m_shift; // shift amount | |
| 145 | UINT16 m_mask; // final mask | |
| 146 | 146 | }; |
| 147 | 147 | |
| 148 | 148 | // internal structure describing each object in the ROMs |
| r25360 | r25361 | |
| 156 | 156 | const UINT16 * table; |
| 157 | 157 | const UINT16 * data; |
| 158 | 158 | }; |
| 159 | ||
| 159 | ||
| 160 | 160 | // internal helpers |
| 161 | 161 | inline int round_to_powerof2(int value); |
| 162 | 162 | void build_rle_tables(); |
| r25360 | r25361 | |
| 177 | 177 | rectangle m_cliprect; // clipping rectangle |
| 178 | 178 | |
| 179 | 179 | // masks |
| 180 | sprite_parameter m_codemask; // mask for the code index | |
| 181 | sprite_parameter m_colormask; // mask for the color | |
| 182 | sprite_parameter m_xposmask; // mask for the X position | |
| 183 | sprite_parameter m_yposmask; // mask for the Y position | |
| 184 | sprite_parameter m_scalemask; // mask for the scale factor | |
| 185 | sprite_parameter m_hflipmask; // mask for the horizontal flip | |
| 186 | sprite_parameter m_ordermask; // mask for the order | |
| 187 | sprite_parameter m_prioritymask; // mask for the priority | |
| 188 | sprite_parameter m_vrammask; // mask for the VRAM target | |
| 180 | sprite_parameter m_codemask; // mask for the code index | |
| 181 | sprite_parameter m_colormask; // mask for the color | |
| 182 | sprite_parameter m_xposmask; // mask for the X position | |
| 183 | sprite_parameter m_yposmask; // mask for the Y position | |
| 184 | sprite_parameter m_scalemask; // mask for the scale factor | |
| 185 | sprite_parameter m_hflipmask; // mask for the horizontal flip | |
| 186 | sprite_parameter m_ordermask; // mask for the order | |
| 187 | sprite_parameter m_prioritymask; // mask for the priority | |
| 188 | sprite_parameter m_vrammask; // mask for the VRAM target | |
| 189 | 189 | |
| 190 | 190 | // ROM information |
| 191 | const UINT16 * m_rombase; // pointer to the base of the GFX ROM | |
| 192 | int m_romlength; // length of the GFX ROM | |
| 193 | int m_objectcount; // number of objects in the ROM | |
| 191 | const UINT16 * m_rombase; // pointer to the base of the GFX ROM | |
| 192 | int m_romlength; // length of the GFX ROM | |
| 193 | int m_objectcount; // number of objects in the ROM | |
| 194 | 194 | dynamic_array<object_info> m_info; // list of info records |
| 195 | 195 | |
| 196 | 196 | // rendering state |
| 197 | bitmap_ind16 m_vram[2][2]; // pointers to VRAM bitmaps and backbuffers | |
| 198 | int m_partial_scanline; // partial update scanline | |
| 197 | bitmap_ind16 m_vram[2][2]; // pointers to VRAM bitmaps and backbuffers | |
| 198 | int m_partial_scanline; // partial update scanline | |
| 199 | 199 | |
| 200 | 200 | // control state |
| 201 | UINT8 m_control_bits; // current control bits | |
| 202 | UINT8 m_command; // current command | |
| 203 | UINT16 m_checksums[256]; // checksums for each 0x40000 bytes | |
| 204 | memory_array m_ram; | |
| 201 | UINT8 m_control_bits; // current control bits | |
| 202 | UINT8 m_command; // current command | |
| 203 | UINT16 m_checksums[256]; // checksums for each 0x40000 bytes | |
| 204 | memory_array m_ram; | |
| 205 | 205 | |
| 206 | 206 | // tables |
| 207 | UINT8 m_rle_bpp[8]; | |
| 208 | UINT16 * m_rle_table[8]; | |
| 209 | UINT16 m_rle_table_data[0x500]; | |
| 207 | UINT8 m_rle_bpp[8]; | |
| 208 | UINT16 * m_rle_table[8]; | |
| 209 | UINT16 m_rle_table_data[0x500]; | |
| 210 | 210 | }; |
| 211 | 211 | |
| 212 | 212 |
| r25360 | r25361 | |
|---|---|---|
| 270 | 270 | vertex_t clipv[6]; |
| 271 | 271 | int clipverts; |
| 272 | 272 | int vertnum; |
| 273 | ||
| 273 | ||
| 274 | 274 | int direct = node->data.quad.direct; |
| 275 | 275 | int flags = node->data.quad.flags; |
| 276 | 276 | int color = node->data.quad.color; |
| 277 | 277 | int cz_adjust = node->data.quad.cz_adjust; |
| 278 | ||
| 278 | ||
| 279 | 279 | extra.destbase = &bitmap; |
| 280 | 280 | extra.pfade_enabled = 0; |
| 281 | 281 | extra.zfog_enabled = 0; |
| r25360 | r25361 | |
| 640 | 640 | struct namcos22_scenenode *node = &m_scenenode_root; |
| 641 | 641 | struct namcos22_scenenode *prev = NULL; |
| 642 | 642 | int hash = 0; |
| 643 | ||
| 643 | ||
| 644 | 644 | for (int i = 0; i < 24; i += NAMCOS22_RADIX_BITS) |
| 645 | 645 | { |
| 646 | 646 | hash = (zsort >> 20) & NAMCOS22_RADIX_MASK; |
| r25360 | r25361 | |
| 751 | 751 | void namcos22_state::matrix3d_multiply(float a[4][4], float b[4][4]) |
| 752 | 752 | { |
| 753 | 753 | float temp[4][4]; |
| 754 | ||
| 754 | ||
| 755 | 755 | for (int row = 0; row < 4; row++) |
| 756 | 756 | { |
| 757 | 757 | for (int col = 0; col < 4; col++) |
| r25360 | r25361 | |
| 764 | 764 | temp[row][col] = sum; |
| 765 | 765 | } |
| 766 | 766 | } |
| 767 | ||
| 767 | ||
| 768 | 768 | memcpy(a, temp, sizeof(temp)); |
| 769 | 769 | } |
| 770 | 770 | |
| r25360 | r25361 | |
| 784 | 784 | float x = *vx; |
| 785 | 785 | float y = *vy; |
| 786 | 786 | float z = *vz; |
| 787 | ||
| 787 | ||
| 788 | 788 | *vx = m[0][0]*x + m[1][0]*y + m[2][0]*z + m[3][0]; |
| 789 | 789 | *vy = m[0][1]*x + m[1][1]*y + m[2][1]*z + m[3][1]; |
| 790 | 790 | *vz = m[0][2]*x + m[1][2]*y + m[2][2]*z + m[3][2]; |
| r25360 | r25361 | |
| 795 | 795 | float x = *nx; |
| 796 | 796 | float y = *ny; |
| 797 | 797 | float z = *nz; |
| 798 | ||
| 798 | ||
| 799 | 799 | *nx = m[0][0]*x + m[1][0]*y + m[2][0]*z; |
| 800 | 800 | *ny = m[0][1]*x + m[1][1]*y + m[2][1]*z; |
| 801 | 801 | *nz = m[0][2]*x + m[1][2]*y + m[2][2]*z; |
| r25360 | r25361 | |
| 2291 | 2291 | if (layer & 1) draw_polygons(bitmap); |
| 2292 | 2292 | m_poly->render_scene(screen, bitmap); |
| 2293 | 2293 | if (layer & 4) namcos22s_mix_text_layer(screen, bitmap, cliprect, 6); |
| 2294 | ||
| 2294 | ||
| 2295 | 2295 | // apply gamma |
| 2296 | 2296 | const UINT8 *rlut = (const UINT8 *)&m_mixer[0x100/4]; |
| 2297 | 2297 | const UINT8 *glut = (const UINT8 *)&m_mixer[0x200/4]; |
| r25360 | r25361 | |
| 2317 | 2317 | update_mixer(); |
| 2318 | 2318 | update_palette(); |
| 2319 | 2319 | screen.priority().fill(0, cliprect); |
| 2320 | ||
| 2320 | ||
| 2321 | 2321 | // background color |
| 2322 | 2322 | bitmap.fill(screen.machine().pens[0x7fff], cliprect); |
| 2323 | ||
| 2323 | ||
| 2324 | 2324 | // layers |
| 2325 | 2325 | draw_polygons(bitmap); |
| 2326 | 2326 | m_poly->render_scene(screen, bitmap); |
| 2327 | 2327 | draw_text_layer(screen, bitmap, cliprect); |
| 2328 | ||
| 2328 | ||
| 2329 | 2329 | // apply gamma |
| 2330 | 2330 | const UINT8 *rlut = (const UINT8 *)m_gamma_proms->base(); |
| 2331 | 2331 | const UINT8 *glut = (const UINT8 *)m_gamma_proms->base() + 0x100; |
| r25360 | r25361 | |
| 2383 | 2383 | { |
| 2384 | 2384 | m_pointrom[i] = signed24(pointrom_high[i] << 16 | pointrom_mid[i] << 8 | pointrom_low[i]); |
| 2385 | 2385 | } |
| 2386 | ||
| 2386 | ||
| 2387 | 2387 | m_pointram = auto_alloc_array_clear(machine(), UINT32, 0x20000); |
| 2388 | 2388 | |
| 2389 | 2389 | // textures |
| r25360 | r25361 | |
| 2393 | 2393 | m_texture_tilemap = (UINT16 *)memregion("textilemap")->base(); |
| 2394 | 2394 | m_texture_tiledata = (UINT8 *)machine().gfx[1]->get_data(0); |
| 2395 | 2395 | m_texture_tileattr = auto_alloc_array(machine(), UINT8, 0x080000*2); |
| 2396 | ||
| 2396 | ||
| 2397 | 2397 | // unpack textures |
| 2398 | 2398 | UINT8 *packed_tileattr = 0x200000 + (UINT8 *)memregion("textilemap")->base(); |
| 2399 | 2399 | UINT8 *unpacked_tileattr = m_texture_tileattr; |
| r25360 | r25361 | |
| 2403 | 2403 | *unpacked_tileattr++ = (*packed_tileattr) & 0xf; |
| 2404 | 2404 | packed_tileattr++; |
| 2405 | 2405 | } |
| 2406 | ||
| 2406 | ||
| 2407 | 2407 | // make attr/y/x lookup table |
| 2408 | 2408 | m_texture_ayx_to_pixel = auto_alloc_array(machine(), UINT8, 16*16*16); |
| 2409 | 2409 | for (int attr = 0; attr < 16; attr++) |
| r25360 | r25361 | |
| 2431 | 2431 | } |
| 2432 | 2432 | } |
| 2433 | 2433 | } |
| 2434 | ||
| 2434 | ||
| 2435 | 2435 | // following setup is Namco System 22 specific |
| 2436 | 2436 | switch (m_gametype) |
| 2437 | 2437 | { |
| r25360 | r25361 | |
| 2475 | 2475 | VIDEO_START_MEMBER(namcos22_state,namcos22) |
| 2476 | 2476 | { |
| 2477 | 2477 | m_is_ss22 = 0; |
| 2478 | ||
| 2478 | ||
| 2479 | 2479 | VIDEO_START_CALL_MEMBER(common); |
| 2480 | 2480 | } |
| 2481 | 2481 |
| r25360 | r25361 | |
|---|---|---|
| 1591 | 1591 | static int debug_tex_page = 0; |
| 1592 | 1592 | static int debug_tex_palette = 0; |
| 1593 | 1593 | */ |
| 1594 | ||
| 1595 |
| r25360 | r25361 | |
|---|---|---|
| 117 | 117 | |
| 118 | 118 | bfm_adder2_device::bfm_adder2_device( const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock ) |
| 119 | 119 | : device_t(mconfig, BFM_ADDER2, "BFM ADDER2", tag, owner, clock, "bfm_adder2", __FILE__), |
| 120 | | |
| 120 | m_cpu(*this, "adder2") | |
| 121 | 121 | { |
| 122 | 122 | } |
| 123 | 123 | |
| r25360 | r25361 | |
| 192 | 192 | void bfm_adder2_device::device_start() |
| 193 | 193 | { |
| 194 | 194 | adder2_decode_char_roms(); |
| 195 | ||
| 195 | ||
| 196 | 196 | save_item(NAME(m_adder2_screen_page_reg)); |
| 197 | 197 | save_item(NAME(m_adder2_c101)); |
| 198 | 198 | save_item(NAME(m_adder2_rx)); |
| r25360 | r25361 | |
| 208 | 208 | m_tilemap0 = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(bfm_adder2_device::get_tile0_info),this), TILEMAP_SCAN_ROWS, 8, 8, 50, 35); |
| 209 | 209 | |
| 210 | 210 | m_tilemap1 = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(bfm_adder2_device::get_tile1_info),this), TILEMAP_SCAN_ROWS, 8, 8, 50, 35); |
| 211 | ||
| 211 | ||
| 212 | 212 | palette_set_color(machine(), 0,MAKE_RGB(0x00,0x00,0x00)); |
| 213 | 213 | palette_set_color(machine(), 1,MAKE_RGB(0x00,0x00,0xFF)); |
| 214 | 214 | palette_set_color(machine(), 2,MAKE_RGB(0x00,0xFF,0x00)); |
| r25360 | r25361 | |
| 224 | 224 | palette_set_color(machine(),12,MAKE_RGB(0x80,0x00,0x00)); |
| 225 | 225 | palette_set_color(machine(),13,MAKE_RGB(0x80,0x00,0x80)); |
| 226 | 226 | palette_set_color(machine(),14,MAKE_RGB(0x80,0x80,0x00)); |
| 227 | palette_set_color(machine(),15,MAKE_RGB(0x80,0x80,0x80)); | |
| 227 | palette_set_color(machine(),15,MAKE_RGB(0x80,0x80,0x80)); | |
| 228 | 228 | } |
| 229 | 229 | |
| 230 | 230 | // video update /////////////////////////////////////////////////////////// |
| 231 | 231 | UINT32 bfm_adder2_device::update_screen(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) |
| 232 | 232 | { |
| 233 | ||
| 234 | 233 | const rectangle visible1(0, 400-1, 0, 280-1); //minx,maxx, miny,maxy |
| 235 | 234 | |
| 236 | 235 | if (m_adder2_screen_page_reg & SL_DISPLAY) m_tilemap1->draw(screen, bitmap, visible1, 0, 0); |
| r25360 | r25361 | |
| 409 | 408 | m_adder2_sc2data = data; // store data |
| 410 | 409 | |
| 411 | 410 | m_adder2_acia_triggered = 1; // set flag, acia IRQ triggered |
| 412 | ||
| 411 | ||
| 413 | 412 | m_cpu->set_input_line(M6809_IRQ_LINE, HOLD_LINE ); |
| 414 | 413 | |
| 415 | 414 | //LOG_SERIAL(("sadder %02X (%c)\n",data, data )); |
| r25360 | r25361 | |
| 564 | 563 | { |
| 565 | 564 | return MACHINE_CONFIG_NAME( adder2 ); |
| 566 | 565 | } |
| 567 |
| r25360 | r25361 | |
|---|---|---|
| 25 | 25 | DECLARE_READ8_MEMBER( adder2_uart_rx_r ); |
| 26 | 26 | DECLARE_WRITE8_MEMBER( adder2_uart_tx_w ); |
| 27 | 27 | DECLARE_READ8_MEMBER( adder2_irq_r ); |
| 28 | ||
| 28 | ||
| 29 | 29 | DECLARE_WRITE8_MEMBER(vid_uart_tx_w); |
| 30 | 30 | DECLARE_WRITE8_MEMBER(vid_uart_ctrl_w); |
| 31 | 31 | DECLARE_READ8_MEMBER(vid_uart_rx_r); |
| 32 | 32 | DECLARE_READ8_MEMBER(vid_uart_ctrl_r); |
| 33 | ||
| 33 | ||
| 34 | 34 | void adder2_decode_char_roms(); |
| 35 | ||
| 35 | ||
| 36 | 36 | protected: |
| 37 | 37 | // device-level overrides |
| 38 | 38 | virtual void device_start(); |
| 39 | 39 | virtual void device_reset(); |
| 40 | 40 | virtual machine_config_constructor device_mconfig_additions() const; |
| 41 | 41 | private: |
| 42 | ||
| 42 | ||
| 43 | 43 | int m_adder2_screen_page_reg; // access/display select |
| 44 | 44 | int m_adder2_c101; |
| 45 | 45 | int m_adder2_rx; |
| 46 | 46 | int m_adder_vbl_triggered; // flag <>0, VBL IRQ triggered |
| 47 | 47 | int m_adder2_acia_triggered; // flag <>0, ACIA receive IRQ |
| 48 | ||
| 48 | ||
| 49 | 49 | UINT8 m_adder_ram[0xE80]; // normal RAM |
| 50 | 50 | UINT8 m_adder_screen_ram[2][0x1180]; // paged display RAM |
| 51 | ||
| 51 | ||
| 52 | 52 | tilemap_t *m_tilemap0; // tilemap screen0 |
| 53 | 53 | tilemap_t *m_tilemap1; // timemap screen1 |
| 54 | ||
| 54 | ||
| 55 | 55 | UINT8 m_adder2_data_from_sc2; |
| 56 | 56 | UINT8 m_adder2_data_to_sc2; |
| 57 | ||
| 57 | ||
| 58 | 58 | UINT8 m_adder2_data; |
| 59 | UINT8 m_adder2_sc2data; | |
| 60 | ||
| 59 | UINT8 m_adder2_sc2data; | |
| 60 | ||
| 61 | 61 | optional_device<cpu_device> m_cpu; |
| 62 | 62 | }; |
| 63 | 63 |
| r25360 | r25361 | |
|---|---|---|
| 48 | 48 | eprom 0 1 1 0 1 0 0 8 0 0 0x100 0x100 0 03ff,0,0,0 0,7fff,0,0 0 0,0,000f,0 0,0,ff80,0 0,0,0,ff80 0,0,0,0070 0,0,0,0007 0,0,0,0008 0 0,0,0070,0 0 0 0 |
| 49 | 49 | guts 0 1 1 0 0 0 0 8 0 0 0x100 0x100 0 03ff,0,0,0 0,7fff,0,0 0 0,0,000f,0 0,0,ff80,0 0,0,0,ff80 0,0,0,0070 0,0,0,000f 0,8000,0,0 0 0,0,0070,0 0 0 0 |
| 50 | 50 | gauntlet 0 1 1 1 0 0 0 8 1 0 0x100 0x100 0 0,0,0,03ff 7fff,0,0,0 0 0,000f,0,0 0,ff80,0,0 0,0,ff80,0 0,0,0038,0 0,0,0007,0 0,0,0040,0 0 0 0 0 0 |
| 51 | klax 1 1 1 0 0 0 0 8 0 0 0x000 0x100 0 00ff,0,0,0 0,0fff,0,0 0 0,0,000f,0 0,0,ff80,0 0,0,0,ff80 0,0,0,0070 0,0,0,0007 0,0,0,0008 0 0 0 0 0 | |
| 52 | offtwall 0 1 1 0 0 0 0 8 0 0 0x100 0x100 0 00ff,0,0,0 0,7fff,0,0 0 0,0,000f,0 0,0,ff80,0 0,0,0,ff80 0,0,0,0070 0,0,0,0007 0,8000,0,0 0 0 0 0 0 | |
| 53 | rampart 0 1 1 0 0 0 0 8 0 0 0x100 0x100 0 00ff,0,0,0 0,7fff,0,0 0 0,0,000f,0 0,0,ff80,0 0,0,0,ff80 0,0,0,0070 0,0,0,0007 0,8000,0,0 0 0 0 0 0 | |
| 51 | klax 1 1 1 0 0 0 0 8 0 0 0x000 0x100 0 00ff,0,0,0 0,0fff,0,0 0 0,0,000f,0 0,0,ff80,0 0,0,0,ff80 0,0,0,0070 0,0,0,0007 0,0,0,0008 0 0 0 0 0 | |
| 52 | offtwall 0 1 1 0 0 0 0 8 0 0 0x100 0x100 0 00ff,0,0,0 0,7fff,0,0 0 0,0,000f,0 0,0,ff80,0 0,0,0,ff80 0,0,0,0070 0,0,0,0007 0,8000,0,0 0 0 0 0 0 | |
| 53 | rampart 0 1 1 0 0 0 0 8 0 0 0x100 0x100 0 00ff,0,0,0 0,7fff,0,0 0 0,0,000f,0 0,0,ff80,0 0,0,0,ff80 0,0,0,0070 0,0,0,0007 0,8000,0,0 0 0 0 0 0 | |
| 54 | 54 | relief 1 1 1 0 0 0 0 8 0 0 0x100 0x100 0 00ff,0,0,0 0,7fff,0,0 0 0,0,000f,0 0,0,ff80,0 0,0,0,ff80 0,0,0,0070 0,0,0,0007 0,8000,0,0 0 0 0 0 0 |
| 55 | 55 | shuuz 1 1 1 0 0 0 0 8 0 0 0x000 0x100 0 00ff,0,0,0 0,7fff,0,0 0 0,0,000f,0 0,0,ff80,0 0,0,0,ff80 0,0,0,0070 0,0,0,0007 0,8000,0,0 0 0 0 0 0 |
| 56 | 56 | skullxbo 0 2 1 0 0 0 0 8 0 0 0x000 0x200 0 00ff,0,0,0 0,7fff,0,0 0 0,0,000f,0 0,0,ffc0,0 0,0,0,ff80 0,0,0,0070 0,0,0,000f 0,8000,0,0 0 0,0,0030,0 0 0 0 |
| 57 | 57 | thunderj 1 1 1 0 1 0 0 8 0 0 0x100 0x100 0 03ff,0,0,0 0,7fff,0,0 0 0,0,000f,0 0,0,ff80,0 0,0,0,ff80 0,0,0,0070 0,0,0,0007 0,8000,0,0 0 0,0,0070,0 0 0 0 |
| 58 | toobin 1 1 1 0 0 1 0 1k 0 0 0x100 0x100 0 0,0,00ff,0 0,3fff,0,0 0 0,0,0,000f 0,0,0,ffc0 7fc0,0,0,0 0007,0,0,0 0038,0,0,0 0,4000,0,0 0,8000,0,0 0 0 8000,0,0,0 0 | |
| 58 | toobin 1 1 1 0 0 1 0 1k 0 0 0x100 0x100 0 0,0,00ff,0 0,3fff,0,0 0 0,0,0,000f 0,0,0,ffc0 7fc0,0,0,0 0007,0,0,0 0038,0,0,0 0,4000,0,0 0,8000,0,0 0 0 8000,0,0,0 0 | |
| 59 | 59 | vindictr 0 1 1 0 0 0 0 8 0 0 0x100 0x100 0 0,0,0,03ff 7fff,0,0,0 0 0,000f,0,0 0,ff80,0,0 0,0,ff80,0 0,0,0038,0 0,0,0007,0 0,0,0040,0 0 0,0070,0,0 0 0 0 |
| 60 | 60 | xybots 1 1 0 0 0 0 0 0 0 0 0x100 0x300 0 003f,0,0,0 3fff,0,0,0 0 0,0,0,000f 0,0,0,ff80 0,0,ff80,0 0 0,0,0007,0 8000,0,0,0 0 0,000f,0,0 0 0 0 |
| 61 | 61 | |
| r25360 | r25361 | |
| 67 | 67 | |
| 68 | 68 | atarisy2 1 1 1 0 0 0 0 0 0 0 0x000 0x040 15 0,0,0,07f8 0,07ff,0,0 0007,0,0,0 0,0,0,3000 0,0,ffc0,0 7fc0,0,0,0 0 0,3800,0,0 0,4000,0,0 0 0,0,0,c000 0,8000,0,0 0 0 |
| 69 | 69 | |
| 70 | toobin 1 1 1 0 0 1 0 1k 0 0 0x100 0x100 0 0,0,00ff,0 0,3fff,0,0 0 0,0,0,000f 0,0,0,ffc0 7fc0,0,0,0 0007,0,0,0 0038,0,0,0 0,4000,0,0 0,8000,0,0 0 0 8000,0,0,0 0 | |
| 70 | toobin 1 1 1 0 0 1 0 1k 0 0 0x100 0x100 0 0,0,00ff,0 0,3fff,0,0 0 0,0,0,000f 0,0,0,ffc0 7fc0,0,0,0 0007,0,0,0 0038,0,0,0 0,4000,0,0 0,8000,0,0 0 0 8000,0,0,0 0 | |
| 71 | 71 | |
| 72 | 72 | gauntlet 0 1 1 1 0 0 0 8 1 0 0x100 0x100 0 0,0,0,03ff 7fff,0,0,0 0 0,000f,0,0 0,ff80,0,0 0,0,ff80,0 0,0,0038,0 0,0,0007,0 0,0,0040,0 0 0 0 0 0 |
| 73 | 73 | vindictr 0 1 1 0 0 0 0 8 0 0 0x100 0x100 0 0,0,0,03ff 7fff,0,0,0 0 0,000f,0,0 0,ff80,0,0 0,0,ff80,0 0,0,0038,0 0,0,0007,0 0,0,0040,0 0 0,0070,0,0 0 0 0 |
| r25360 | r25361 | |
| 85 | 85 | skullxbo 0 2 1 0 0 0 0 8 0 0 0x000 0x200 0 00ff,0,0,0 0,7fff,0,0 0 0,0,000f,0 0,0,ffc0,0 0,0,0,ff80 0,0,0,0070 0,0,0,000f 0,8000,0,0 0 0,0,0030,0 0 0 0 |
| 86 | 86 | thunderj 1 1 1 0 1 0 0 8 0 0 0x100 0x100 0 03ff,0,0,0 0,7fff,0,0 0 0,0,000f,0 0,0,ff80,0 0,0,0,ff80 0,0,0,0070 0,0,0,0007 0,8000,0,0 0 0,0,0070,0 0 0 0 |
| 87 | 87 | arcadecl 0 1 1 0 0 0 0 0 0 0 0x100 0x100 0 00ff,0,0,0 0,7fff,0,0 0 0,0,000f,0 0,0,ff80,0 0,0,0,ff80 0,0,0,0070 0,0,0,0007 0 0 0 0 0 0 |
| 88 | klax 1 1 1 0 0 0 0 8 0 0 0x000 0x100 0 00ff,0,0,0 0,0fff,0,0 0 0,0,000f,0 0,0,ff80,0 0,0,0,ff80 0,0,0,0070 0,0,0,0007 0,0,0,0008 0 0 0 0 0 | |
| 89 | offtwall 0 1 1 0 0 0 0 8 0 0 0x100 0x100 0 00ff,0,0,0 0,7fff,0,0 0 0,0,000f,0 0,0,ff80,0 0,0,0,ff80 0,0,0,0070 0,0,0,0007 0,8000,0,0 0 0 0 0 0 | |
| 90 | rampart 0 1 1 0 0 0 0 8 0 0 0x100 0x100 0 00ff,0,0,0 0,7fff,0,0 0 0,0,000f,0 0,0,ff80,0 0,0,0,ff80 0,0,0,0070 0,0,0,0007 0,8000,0,0 0 0 0 0 0 | |
| 88 | klax 1 1 1 0 0 0 0 8 0 0 0x000 0x100 0 00ff,0,0,0 0,0fff,0,0 0 0,0,000f,0 0,0,ff80,0 0,0,0,ff80 0,0,0,0070 0,0,0,0007 0,0,0,0008 0 0 0 0 0 | |
| 89 | offtwall 0 1 1 0 0 0 0 8 0 0 0x100 0x100 0 00ff,0,0,0 0,7fff,0,0 0 0,0,000f,0 0,0,ff80,0 0,0,0,ff80 0,0,0,0070 0,0,0,0007 0,8000,0,0 0 0 0 0 0 | |
| 90 | rampart 0 1 1 0 0 0 0 8 0 0 0x100 0x100 0 00ff,0,0,0 0,7fff,0,0 0 0,0,000f,0 0,0,ff80,0 0,0,0,ff80 0,0,0,0070 0,0,0,0007 0,8000,0,0 0 0 0 0 0 | |
| 91 | 91 | relief 1 1 1 0 0 0 0 8 0 0 0x100 0x100 0 00ff,0,0,0 0,7fff,0,0 0 0,0,000f,0 0,0,ff80,0 0,0,0,ff80 0,0,0,0070 0,0,0,0007 0,8000,0,0 0 0 0 0 0 |
| 92 | 92 | shuuz 1 1 1 0 0 0 0 8 0 0 0x000 0x100 0 00ff,0,0,0 0,7fff,0,0 0 0,0,000f,0 0,0,ff80,0 0,0,0,ff80 0,0,0,0070 0,0,0,0007 0,8000,0,0 0 0 0 0 0 |
| 93 | 93 | |
| r25360 | r25361 | |
| 102 | 102 | //************************************************************************** |
| 103 | 103 | |
| 104 | 104 | //------------------------------------------------- |
| 105 | // compute_log: Computes the number of bits | |
| 106 | // necessary to hold a given value. The input must | |
| 105 | // compute_log: Computes the number of bits | |
| 106 | // necessary to hold a given value. The input must | |
| 107 | 107 | // be an even power of two. |
| 108 | 108 | //------------------------------------------------- |
| 109 | 109 | |
| r25360 | r25361 | |
| 122 | 122 | |
| 123 | 123 | |
| 124 | 124 | //------------------------------------------------- |
| 125 | // round_to_powerof2: Rounds a number up to the | |
| 126 | // nearest power of 2. Even powers of 2 are | |
| 127 | // rounded up to the next greatest power | |
| 125 | // round_to_powerof2: Rounds a number up to the | |
| 126 | // nearest power of 2. Even powers of 2 are | |
| 127 | // rounded up to the next greatest power | |
| 128 | 128 | // (e.g., 4 returns 8). |
| 129 | 129 | //------------------------------------------------- |
| 130 | 130 | |
| r25360 | r25361 | |
| 183 | 183 | |
| 184 | 184 | //------------------------------------------------- |
| 185 | 185 | // static_set_config: Set the tag of the |
| 186 | // | |
| 186 | // sound CPU | |
| 187 | 187 | //------------------------------------------------- |
| 188 | 188 | |
| 189 | 189 | void atari_motion_objects_device::static_set_config(device_t &device, const atari_motion_objects_config &config) |
| r25360 | r25361 | |
| 261 | 261 | |
| 262 | 262 | |
| 263 | 263 | //------------------------------------------------- |
| 264 | // apply_stain: Mark high palette bits | |
| 265 | // starting at the given X,Y and continuing until | |
| 264 | // apply_stain: Mark high palette bits | |
| 265 | // starting at the given X,Y and continuing until | |
| 266 | 266 | // a stop or the end of line. |
| 267 | 267 | //------------------------------------------------- |
| 268 | 268 | |
| r25360 | r25361 | |
| 315 | 315 | m_tileheight = gfx->height(); |
| 316 | 316 | m_tilexshift = compute_log(m_tilewidth); |
| 317 | 317 | m_tileyshift = compute_log(m_tileheight); |
| 318 | ||
| 318 | ||
| 319 | 319 | // derive bitmap information |
| 320 | 320 | m_bitmapwidth = round_to_powerof2(m_xposmask.mask()); |
| 321 | 321 | m_bitmapheight = round_to_powerof2(m_yposmask.mask()); |
| 322 | 322 | m_bitmapxmask = m_bitmapwidth - 1; |
| 323 | 323 | m_bitmapymask = m_bitmapheight - 1; |
| 324 | ||
| 324 | ||
| 325 | 325 | // derive sprite information |
| 326 | 326 | m_entrycount = round_to_powerof2(m_linkmask.mask()); |
| 327 | 327 | m_entrybits = compute_log(m_entrycount); |
| r25360 | r25361 | |
| 363 | 363 | |
| 364 | 364 | |
| 365 | 365 | //------------------------------------------------- |
| 366 | // device_reset: Handle a device reset by | |
| 367 | // clearing the interrupt lines and states | |
| 366 | // device_reset: Handle a device reset by | |
| 367 | // clearing the interrupt lines and states | |
| 368 | 368 | //------------------------------------------------- |
| 369 | 369 | |
| 370 | 370 | void atari_motion_objects_device::device_reset() |
| r25360 | r25361 | |
| 379 | 379 | |
| 380 | 380 | //------------------------------------------------- |
| 381 | 381 | // device_timer: Handle device-specific timer |
| 382 | // | |
| 382 | // calbacks | |
| 383 | 383 | //------------------------------------------------- |
| 384 | 384 | |
| 385 | 385 | void atari_motion_objects_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) |
| r25360 | r25361 | |
| 399 | 399 | |
| 400 | 400 | |
| 401 | 401 | //------------------------------------------------- |
| 402 | // build_active_list: Build a list of active | |
| 403 | // objects. | |
| 402 | // build_active_list: Build a list of active | |
| 403 | // objects. | |
| 404 | 404 | //------------------------------------------------- |
| 405 | 405 | |
| 406 | 406 | void atari_motion_objects_device::build_active_list(int link) |
| r25360 | r25361 | |
| 445 | 445 | |
| 446 | 446 | |
| 447 | 447 | //------------------------------------------------- |
| 448 | // render_object: Internal processing callback | |
| 449 | // that renders to the backing bitmap and then | |
| 448 | // render_object: Internal processing callback | |
| 449 | // that renders to the backing bitmap and then | |
| 450 | 450 | // copies the result to the destination. |
| 451 | 451 | //------------------------------------------------- |
| 452 | 452 | |
| r25360 | r25361 | |
| 605 | 605 | //------------------------------------------------- |
| 606 | 606 | |
| 607 | 607 | atari_motion_objects_device::sprite_parameter::sprite_parameter() |
| 608 | : m_word(0), | |
| 609 | m_shift(0), | |
| 610 | m_mask(0) | |
| 608 | : m_word(0), | |
| 609 | m_shift(0), | |
| 610 | m_mask(0) | |
| 611 | 611 | { |
| 612 | 612 | } |
| 613 | 613 | |
| r25360 | r25361 | |
| 654 | 654 | //------------------------------------------------- |
| 655 | 655 | |
| 656 | 656 | atari_motion_objects_device::dual_sprite_parameter::dual_sprite_parameter() |
| 657 | : m_uppershift(0) | |
| 657 | : m_uppershift(0) | |
| 658 | 658 | { |
| 659 | 659 | } |
| 660 | 660 | |
| r25360 | r25361 | |
| 670 | 670 | return false; |
| 671 | 671 | if (!m_upper.set(input.data_upper)) |
| 672 | 672 | return false; |
| 673 | ||
| 673 | ||
| 674 | 674 | // determine teh upper shift amount |
| 675 | 675 | UINT16 temp = m_lower.mask(); |
| 676 | 676 | m_uppershift = 0; |
| r25360 | r25361 | |
|---|---|---|
| 50 | 50 | #define MCFG_ATARI_MOTION_OBJECTS_ADD(_tag, _screen, _config) \ |
| 51 | 51 | MCFG_DEVICE_ADD(_tag, ATARI_MOTION_OBJECTS, 0) \ |
| 52 | 52 | MCFG_VIDEO_SET_SCREEN(_screen) \ |
| 53 | atari_motion_objects_device::static_set_config(*device, _config); | |
| 53 | atari_motion_objects_device::static_set_config(*device, _config); | |
| 54 | 54 | |
| 55 | 55 | |
| 56 | ||
| 57 | 56 | //************************************************************************** |
| 58 | 57 | // TYPE DEFINITIONS |
| 59 | 58 | //************************************************************************** |
| r25360 | r25361 | |
| 79 | 78 | UINT16 m_maxcolors; // maximum number of colors (remove me) |
| 80 | 79 | UINT8 m_transpen; // transparent pen index |
| 81 | 80 | |
| 82 | entry m_link_entry; // mask for the link | |
| 83 | dual_entry m_code_entry; // mask for the code index | |
| 84 | dual_entry m_color_entry; // mask for the color/priority | |
| 85 | entry m_xpos_entry; // mask for the X position | |
| 86 | entry m_ypos_entry; // mask for the Y position | |
| 87 | entry m_width_entry; // mask for the width, in tiles*/ | |
| 88 | entry m_height_entry; // mask for the height, in tiles | |
| 89 | entry m_hflip_entry; // mask for the horizontal flip | |
| 90 | entry m_vflip_entry; // mask for the vertical flip | |
| 91 | entry m_priority_entry; // mask for the priority | |
| 92 | entry m_neighbor_entry; // mask for the neighbor | |
| 93 | entry m_absolute_entry; // mask for absolute coordinates | |
| 94 | entry m_special_entry; // mask for the special value | |
| 95 | UINT16 m_specialvalue; // resulting value to indicate "special" | |
| 81 | entry m_link_entry; // mask for the link | |
| 82 | dual_entry m_code_entry; // mask for the code index | |
| 83 | dual_entry m_color_entry; // mask for the color/priority | |
| 84 | entry m_xpos_entry; // mask for the X position | |
| 85 | entry m_ypos_entry; // mask for the Y position | |
| 86 | entry m_width_entry; // mask for the width, in tiles*/ | |
| 87 | entry m_height_entry; // mask for the height, in tiles | |
| 88 | entry m_hflip_entry; // mask for the horizontal flip | |
| 89 | entry m_vflip_entry; // mask for the vertical flip | |
| 90 | entry m_priority_entry; // mask for the priority | |
| 91 | entry m_neighbor_entry; // mask for the neighbor | |
| 92 | entry m_absolute_entry; // mask for absolute coordinates | |
| 93 | entry m_special_entry; // mask for the special value | |
| 94 | UINT16 m_specialvalue; // resulting value to indicate "special" | |
| 96 | 95 | }; |
| 97 | 96 | |
| 98 | 97 | |
| r25360 | r25361 | |
| 114 | 113 | |
| 115 | 114 | // static configuration helpers |
| 116 | 115 | static void static_set_config(device_t &device, const atari_motion_objects_config &config); |
| 117 | ||
| 116 | ||
| 118 | 117 | // getters |
| 119 | 118 | int bank() const { return m_bank; } |
| 120 | 119 | int xscroll() const { return m_xscroll; } |
| r25360 | r25361 | |
| 133 | 132 | // rendering |
| 134 | 133 | virtual void draw(bitmap_ind16 &bitmap, const rectangle &cliprect); |
| 135 | 134 | void apply_stain(bitmap_ind16 &bitmap, UINT16 *pf, UINT16 *mo, int x, int y); |
| 136 | ||
| 135 | ||
| 137 | 136 | // memory access |
| 138 | 137 | UINT16 &slipram(int offset) { return m_slipram[offset]; } |
| 139 | 138 | |
| r25360 | r25361 | |
| 173 | 172 | UINT16 mask() const { return m_mask; } |
| 174 | 173 | |
| 175 | 174 | private: |
| 176 | UINT16 m_word; // word index | |
| 177 | UINT16 m_shift; // shift amount | |
| 178 | UINT16 m_mask; // final mask | |
| 175 | UINT16 m_word; // word index | |
| 176 | UINT16 m_shift; // shift amount | |
| 177 | UINT16 m_mask; // final mask | |
| 179 | 178 | }; |
| 180 | ||
| 179 | ||
| 181 | 180 | // a sprite parameter, which is a word index + shift + mask |
| 182 | 181 | class dual_sprite_parameter |
| 183 | 182 | { |
| r25360 | r25361 | |
| 188 | 187 | UINT16 mask() const { return m_lower.mask() | (m_upper.mask() << m_uppershift); } |
| 189 | 188 | |
| 190 | 189 | private: |
| 191 | sprite_parameter m_lower; // lower parameter | |
| 192 | sprite_parameter m_upper; // upper parameter | |
| 193 | UINT16 m_uppershift; // upper shift | |
| 190 | sprite_parameter m_lower; // lower parameter | |
| 191 | sprite_parameter m_upper; // upper parameter | |
| 192 | UINT16 m_uppershift; // upper shift | |
| 194 | 193 | }; |
| 195 | ||
| 194 | ||
| 196 | 195 | // parameter masks |
| 197 | sprite_parameter m_linkmask; // mask for the link | |
| 198 | sprite_parameter m_gfxmask; // mask for the graphics bank | |
| 199 | dual_sprite_parameter m_codemask; // mask for the code index | |
| 200 | dual_sprite_parameter m_colormask; // mask for the color | |
| 201 | sprite_parameter m_xposmask; // mask for the X position | |
| 202 | sprite_parameter m_yposmask; // mask for the Y position | |
| 203 | sprite_parameter m_widthmask; // mask for the width, in tiles*/ | |
| 204 | sprite_parameter m_heightmask; // mask for the height, in tiles | |
| 205 | sprite_parameter m_hflipmask; // mask for the horizontal flip | |
| 206 | sprite_parameter m_vflipmask; // mask for the vertical flip | |
| 207 | sprite_parameter m_prioritymask; // mask for the priority | |
| 208 | sprite_parameter m_neighbormask; // mask for the neighbor | |
| 209 | sprite_parameter m_absolutemask; // mask for absolute coordinates | |
| 210 | sprite_parameter m_specialmask; // mask for the special value | |
| 196 | sprite_parameter m_linkmask; // mask for the link | |
| 197 | sprite_parameter m_gfxmask; // mask for the graphics bank | |
| 198 | dual_sprite_parameter m_codemask; // mask for the code index | |
| 199 | dual_sprite_parameter m_colormask; // mask for the color | |
| 200 | sprite_parameter m_xposmask; // mask for the X position | |
| 201 | sprite_parameter m_yposmask; // mask for the Y position | |
| 202 | sprite_parameter m_widthmask; // mask for the width, in tiles*/ | |
| 203 | sprite_parameter m_heightmask; // mask for the height, in tiles | |
| 204 | sprite_parameter m_hflipmask; // mask for the horizontal flip | |
| 205 | sprite_parameter m_vflipmask; // mask for the vertical flip | |
| 206 | sprite_parameter m_prioritymask; // mask for the priority | |
| 207 | sprite_parameter m_neighbormask; // mask for the neighbor | |
| 208 | sprite_parameter m_absolutemask; // mask for absolute coordinates | |
| 209 | sprite_parameter m_specialmask; // mask for the special value | |
| 211 | 210 | |
| 212 | 211 | // derived tile information |
| 213 | int m_tilewidth; // width of non-rotated tile | |
| 214 | int m_tileheight; // height of non-rotated tile | |
| 215 | int m_tilexshift; // bits to shift X coordinate when drawing | |
| 216 | int m_tileyshift; // bits to shift Y coordinate when drawing | |
| 212 | int m_tilewidth; // width of non-rotated tile | |
| 213 | int m_tileheight; // height of non-rotated tile | |
| 214 | int m_tilexshift; // bits to shift X coordinate when drawing | |
| 215 | int m_tileyshift; // bits to shift Y coordinate when drawing | |
| 217 | 216 | |
| 218 | 217 | // derived bitmap information |
| 219 | int m_bitmapwidth; // width of the full playfield bitmap | |
| 220 | int m_bitmapheight; // height of the full playfield bitmap | |
| 221 | int m_bitmapxmask; // x coordinate mask for the playfield bitmap | |
| 222 | int m_bitmapymask; // y coordinate mask for the playfield bitmap | |
| 223 | ||
| 218 | int m_bitmapwidth; // width of the full playfield bitmap | |
| 219 | int m_bitmapheight; // height of the full playfield bitmap | |
| 220 | int m_bitmapxmask; // x coordinate mask for the playfield bitmap | |
| 221 | int m_bitmapymask; // y coordinate mask for the playfield bitmap | |
| 222 | ||
| 224 | 223 | // derived sprite information |
| 225 | int m_entrycount; // number of entries per bank | |
| 226 | int m_entrybits; // number of bits needed to represent entrycount | |
| 227 | int m_spriterammask; // combined mask when accessing sprite RAM with raw addresses | |
| 228 | int m_spriteramsize; // total size of sprite RAM, in entries | |
| 229 | int m_slipshift; // log2(pixels_per_SLIP) | |
| 230 | int m_sliprammask; // combined mask when accessing SLIP RAM with raw addresses | |
| 231 | int m_slipramsize; // total size of SLIP RAM, in entries | |
| 224 | int m_entrycount; // number of entries per bank | |
| 225 | int m_entrybits; // number of bits needed to represent entrycount | |
| 226 | int m_spriterammask; // combined mask when accessing sprite RAM with raw addresses | |
| 227 | int m_spriteramsize; // total size of sprite RAM, in entries | |
| 228 | int m_slipshift; // log2(pixels_per_SLIP) | |
| 229 | int m_sliprammask; // combined mask when accessing SLIP RAM with raw addresses | |
| 230 | int m_slipramsize; // total size of SLIP RAM, in entries | |
| 232 | 231 | |
| 233 | 232 | // live state |
| 234 | emu_timer * m_force_update_timer; // timer for forced updating | |
| 235 | UINT32 m_bank; // current bank number | |
| 236 | UINT32 m_xscroll; // xscroll offset | |
| 237 | UINT32 m_yscroll; // yscroll offset | |
| 233 | emu_timer * m_force_update_timer; // timer for forced updating | |
| 234 | UINT32 m_bank; // current bank number | |
| 235 | UINT32 m_xscroll; // xscroll offset | |
| 236 | UINT32 m_yscroll; // yscroll offset | |
| 238 | 237 | |
| 239 | 238 | // arrays |
| 240 | 239 | optional_shared_ptr<UINT16> m_slipram; // pointer to the SLIP RAM |
| 241 | dynamic_array<UINT16> m_codelookup; // lookup table for codes | |
| 242 | dynamic_array<UINT8> m_colorlookup; // lookup table for colors | |
| 243 | dynamic_array<UINT8> m_gfxlookup; // lookup table for graphics | |
| 244 | ||
| 245 | UINT16 m_activelist[MAX_PER_BANK*4]; // active list | |
| 246 | UINT16 * m_activelast; // last entry in the active list | |
| 240 | dynamic_array<UINT16> m_codelookup; // lookup table for codes | |
| 241 | dynamic_array<UINT8> m_colorlookup; // lookup table for colors | |
| 242 | dynamic_array<UINT8> m_gfxlookup; // lookup table for graphics | |
| 247 | 243 | |
| 248 | UINT32 m_last_xpos; // (during processing) the previous X position | |
| 249 | UINT32 m_next_xpos; // (during processing) the next X position | |
| 244 | UINT16 m_activelist[MAX_PER_BANK*4]; // active list | |
| 245 | UINT16 * m_activelast; // last entry in the active list | |
| 246 | ||
| 247 | UINT32 m_last_xpos; // (during processing) the previous X position | |
| 248 | UINT32 m_next_xpos; // (during processing) the next X position | |
| 250 | 249 | }; |
| 251 | 250 | |
| 252 | 251 |
| r25360 | r25361 | |
|---|---|---|
| 421 | 421 | |
| 422 | 422 | template<class _BitmapClass> |
| 423 | 423 | void deco16ic_device::custom_tilemap_draw( |
| 424 | screen_device &screen, | |
| 424 | screen_device &screen, | |
| 425 | 425 | _BitmapClass &bitmap, |
| 426 | 426 | const rectangle &cliprect, |
| 427 | 427 | tilemap_t *tilemap0_8x8, |
| r25360 | r25361 | |
|---|---|---|
| 92 | 92 | |
| 93 | 93 | template<class _BitmapClass> |
| 94 | 94 | void custom_tilemap_draw( |
| 95 | screen_device &screen, | |
| 95 | screen_device &screen, | |
| 96 | 96 | _BitmapClass &bitmap, |
| 97 | 97 | const rectangle &cliprect, |
| 98 | 98 | tilemap_t *tilemap0_8x8, |
| r25360 | r25361 | |
|---|---|---|
| 1647 | 1647 | { |
| 1648 | 1648 | m_screen = &screen; |
| 1649 | 1649 | running_machine &machine = screen.machine(); |
| 1650 | ||
| 1650 | ||
| 1651 | 1651 | #if SNES_LAYER_DEBUG |
| 1652 | 1652 | memset(&debug_options, 0, sizeof(debug_options)); |
| 1653 | 1653 | #endif |
| r25360 | r25361 | |
|---|---|---|
| 8 | 8 | public: |
| 9 | 9 | k037122_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 10 | 10 | ~k037122_device() {} |
| 11 | ||
| 11 | ||
| 12 | 12 | static void static_set_gfx_index(device_t &device, int index) { downcast<k037122_device &>(device).m_gfx_index = index; } |
| 13 | 13 | |
| 14 | 14 | void tile_draw( screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect ); |
| r25360 | r25361 | |
|---|---|---|
| 1510 | 1510 | |
| 1511 | 1511 | mcd212_device::mcd212_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 1512 | 1512 | : device_t(mconfig, MACHINE_MCD212, "MCD212", tag, owner, clock, "mcd212", __FILE__), |
| 1513 | | |
| 1513 | device_video_interface(mconfig, *this) | |
| 1514 | 1514 | { |
| 1515 | 1515 | } |
| 1516 | 1516 |
| r25360 | r25361 | |
|---|---|---|
| 105 | 105 | (machine().config().m_gfxdecodeinfo[x].gfxlayout->total) |
| 106 | 106 | |
| 107 | 107 | TILE_GET_INFO_MEMBER( ygv608_device::get_tile_info_A_8 ) |
| 108 | { | |
| 108 | { | |
| 109 | 109 | // extract row,col packed into tile_index |
| 110 | 110 | int col = tile_index >> 6; |
| 111 | 111 | int row = tile_index & 0x3f; |
| r25360 | r25361 | |
| 502 | 502 | memset(&m_regs, 0, sizeof(m_regs)); |
| 503 | 503 | memset(&m_pattern_name_table, 0, sizeof(m_pattern_name_table)); |
| 504 | 504 | memset(&m_sprite_attribute_table, 0, sizeof(m_sprite_attribute_table)); |
| 505 | ||
| 505 | ||
| 506 | 506 | memset(&m_scroll_data_table, 0, sizeof(m_scroll_data_table)); |
| 507 | 507 | memset(&m_colour_palette, 0, sizeof(m_colour_palette)); |
| 508 | 508 | |
| r25360 | r25361 | |
| 512 | 512 | m_pny_shift = 0; |
| 513 | 513 | m_na8_mask = 0; |
| 514 | 514 | m_col_shift = 0; |
| 515 | ||
| 515 | ||
| 516 | 516 | m_ax = 0; m_dx = 0; m_dxy = 0; m_ay = 0; m_dy = 0; m_dyx = 0; |
| 517 | 517 | |
| 518 | 518 | memset(&m_base_addr, 0, sizeof(m_base_addr)); |
| r25360 | r25361 | |
| 526 | 526 | m_namcond1_gfxbank = 0; |
| 527 | 527 | save_item(NAME(m_namcond1_gfxbank)); |
| 528 | 528 | |
| 529 | /* create tilemaps of all sizes and combinations */ | |
| 529 | /* create tilemaps of all sizes and combinations */ | |
| 530 | 530 | m_tilemap_A_cache_8[0] = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(ygv608_device::get_tile_info_A_8),this), tilemap_mapper_delegate(FUNC(ygv608_device::get_tile_offset),this), 8,8, 32,32); |
| 531 | 531 | m_tilemap_A_cache_8[1] = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(ygv608_device::get_tile_info_A_8),this), tilemap_mapper_delegate(FUNC(ygv608_device::get_tile_offset),this), 8,8, 64,32); |
| 532 | 532 | m_tilemap_A_cache_8[2] = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(ygv608_device::get_tile_info_A_8),this), tilemap_mapper_delegate(FUNC(ygv608_device::get_tile_offset),this), 8,8, 32,64); |
| r25360 | r25361 | |
|---|---|---|
| 228 | 228 | |
| 229 | 229 | MCFG_TIMER_DRIVER_ADD("scan_timer", skullxbo_state, scanline_timer) |
| 230 | 230 | MCFG_MACHINE_RESET_OVERRIDE(skullxbo_state,skullxbo) |
| 231 | ||
| 231 | ||
| 232 | 232 | MCFG_ATARI_EEPROM_2816_ADD("eeprom") |
| 233 | 233 | |
| 234 | 234 | /* video hardware */ |
| r25360 | r25361 | |
|---|---|---|
| 1175 | 1175 | { |
| 1176 | 1176 | common_reset(); |
| 1177 | 1177 | sprcpt_init(); |
| 1178 | ||
| 1178 | ||
| 1179 | 1179 | membank("mainbank")->set_entry(1); |
| 1180 | 1180 | |
| 1181 | 1181 | prg_bank = 0; |
| r25360 | r25361 | |
| 1186 | 1186 | { |
| 1187 | 1187 | common_reset(); |
| 1188 | 1188 | sprcpt_init(); |
| 1189 | ||
| 1189 | ||
| 1190 | 1190 | membank("mainbank")->set_entry(8); |
| 1191 | 1191 | |
| 1192 | 1192 | prg_bank = 0x08; |
| r25360 | r25361 | |
| 1200 | 1200 | fg_bank = 2; |
| 1201 | 1201 | mid_bank = 1; |
| 1202 | 1202 | sprcpt_init(); |
| 1203 | ||
| 1203 | ||
| 1204 | 1204 | membank("mainbank")->set_entry(1); |
| 1205 | 1205 | |
| 1206 | 1206 | prg_bank = 0; |
| r25360 | r25361 | |
| 1213 | 1213 | fg_bank = 2; |
| 1214 | 1214 | mid_bank = 1; |
| 1215 | 1215 | sprcpt_init(); |
| 1216 | ||
| 1216 | ||
| 1217 | 1217 | //membank("mainbank")->set_entry(1); |
| 1218 | 1218 | |
| 1219 | 1219 | //cop_init(); |
| r25360 | r25361 | |
|---|---|---|
| 97 | 97 | required_device<msm5205_device> m_msm2; |
| 98 | 98 | required_device<z80ctc_device> m_ctc; |
| 99 | 99 | |
| 100 | required_memory_bank m_dma_bank; | |
| 101 | required_memory_region m_msm1_rom; | |
| 102 | required_memory_region m_msm2_rom; | |
| 100 | required_memory_bank m_dma_bank; | |
| 101 | required_memory_region m_msm1_rom; | |
| 102 | required_memory_region m_msm2_rom; | |
| 103 | 103 | |
| 104 | required_shared_ptr<UINT16> m_g_ram; | |
| 105 | required_shared_ptr<UINT16> m_cha_ram; | |
| 106 | required_shared_ptr<UINT16> m_dot_ram; | |
| 107 | required_shared_ptr<UINT8> m_power_ram; | |
| 104 | required_shared_ptr<UINT16> m_g_ram; | |
| 105 | required_shared_ptr<UINT16> m_cha_ram; | |
| 106 | required_shared_ptr<UINT16> m_dot_ram; | |
| 107 | required_shared_ptr<UINT8> m_power_ram; | |
| 108 | 108 | |
| 109 | UINT16 *m_dma_ram; | |
| 110 | UINT8 m_dma_cpu_bank; | |
| 111 | UINT8 m_dma_busy; | |
| 112 | UINT16 m_dsp_hold_signal; | |
| 109 | UINT16 *m_dma_ram; | |
| 110 | UINT8 m_dma_cpu_bank; | |
| 111 | UINT8 m_dma_busy; | |
| 112 | UINT16 m_dsp_hold_signal; | |
| 113 | 113 | |
| 114 | UINT32 m_msm_pos[2]; | |
| 115 | UINT8 m_msm_reset[2]; | |
| 116 | UINT8 m_msm_nibble[2]; | |
| 117 | UINT8 m_msm2_vck; | |
| 118 | UINT8 m_msm2_vck2; | |
| 114 | UINT32 m_msm_pos[2]; | |
| 115 | UINT8 m_msm_reset[2]; | |
| 116 | UINT8 m_msm_nibble[2]; | |
| 117 | UINT8 m_msm2_vck; | |
| 118 | UINT8 m_msm2_vck2; | |
| 119 | 119 | |
| 120 | 120 | virtual void machine_start(); |
| 121 | 121 | virtual void machine_reset(); |
| r25360 | r25361 | |
| 261 | 261 | |
| 262 | 262 | |
| 263 | 263 | /* |
| 264 | ||
| 264 | FEDCBA9876543210 | |
| 265 | 265 | |
| 266 | 0 ...xxxxx xxxxxxxx Tile index | |
| 267 | ..x..... ........ Clear mode | |
| 268 | .x...... ........ Clear pixel/palette data | |
| 269 | x....... ........ Transparent/opaque mode | |
| 266 | 0 ...xxxxx xxxxxxxx Tile index | |
| 267 | ..x..... ........ Clear mode | |
| 268 | .x...... ........ Clear pixel/palette data | |
| 269 | x....... ........ Transparent/opaque mode | |
| 270 | 270 | |
| 271 | 1 .......x xxxxxxxx X Coordinate | |
| 272 | xxxxx... ........ Width in 8x8 tiles | |
| 271 | 1 .......x xxxxxxxx X Coordinate | |
| 272 | xxxxx... ........ Width in 8x8 tiles | |
| 273 | 273 | |
| 274 | 2 .......x xxxxxxxx Y Coordinate | |
| 275 | .....xx. ........ Unused | |
| 276 | xxxxx... ........ Height in 8x8 tiles | |
| 274 | 2 .......x xxxxxxxx Y Coordinate | |
| 275 | .....xx. ........ Unused | |
| 276 | xxxxx... ........ Height in 8x8 tiles | |
| 277 | 277 | |
| 278 | ||
| 278 | 3 ........ ....xxxx Colour | |
| 279 | 279 | */ |
| 280 | 280 | UINT32 mlanding_state::exec_dma() |
| 281 | 281 | { |
| r25360 | r25361 | |
| 414 | 414 | READ16_MEMBER(mlanding_state::input_r) |
| 415 | 415 | { |
| 416 | 416 | /* |
| 417 | FEDCBA98 76543210 | |
| 418 | ........ xxxxxxxx DSWA | |
| 419 | .xxxxxxx ........ DSWB | |
| 420 | x....... ........ DMA busy | |
| 417 | FEDCBA98 76543210 | |
| 418 | ........ xxxxxxxx DSWA | |
| 419 | .xxxxxxx ........ DSWB | |
| 420 | x....... ........ DMA busy | |
| 421 | 421 | */ |
| 422 | 422 | |
| 423 | 423 | UINT8 dswa = ioport("DSWA")->read(); |
| r25360 | r25361 | |
| 429 | 429 | WRITE16_MEMBER(mlanding_state::output_w) |
| 430 | 430 | { |
| 431 | 431 | /* |
| 432 | 76543210 | |
| 433 | x....... Start lamp? | |
| 434 | .x...... /Mecha CPU reset | |
| 435 | ..x..... ? (Briefly transitions from 1 to 0 at $5040, after pressing start) | |
| 436 | ...x.... /Sub CPU reset | |
| 437 | ....x... Coin counter B | |
| 438 | .....x.. Coin counter A | |
| 439 | ......x. /Coin lockout B | |
| 440 | .......x /Coin lockout A | |
| 432 | 76543210 | |
| 433 | x....... Start lamp? | |
| 434 | .x...... /Mecha CPU reset | |
| 435 | ..x..... ? (Briefly transitions from 1 to 0 at $5040, after pressing start) | |
| 436 | ...x.... /Sub CPU reset | |
| 437 | ....x... Coin counter B | |
| 438 | .....x.. Coin counter A | |
| 439 | ......x. /Coin lockout B | |
| 440 | .......x /Coin lockout A | |
| 441 | 441 | */ |
| 442 | 442 | m_subcpu->set_input_line(INPUT_LINE_RESET, data & 0x10 ? CLEAR_LINE : ASSERT_LINE); |
| 443 | 443 | m_mechacpu->set_input_line(INPUT_LINE_RESET, data & 0x40 ? CLEAR_LINE : ASSERT_LINE); |
| r25360 | r25361 | |
| 472 | 472 | READ16_MEMBER(mlanding_state::analog1_lsb_r) |
| 473 | 473 | { |
| 474 | 474 | /* |
| 475 | 76543210 | |
| 476 | ....xxxx Counter 1 bits 3-0 | |
| 477 | ...x.... Handle left | |
| 478 | ..x..... Slot down | |
| 479 | .x...... Slot up | |
| 475 | 76543210 | |
| 476 | ....xxxx Counter 1 bits 3-0 | |
| 477 | ...x.... Handle left | |
| 478 | ..x..... Slot down | |
| 479 | .x...... Slot up | |
| 480 | 480 | */ |
| 481 | 481 | UINT16 throttle = ioport("THROTTLE")->read(); |
| 482 | 482 | UINT16 x = ioport("STICK_X")->read(); |
| r25360 | r25361 | |
| 498 | 498 | READ16_MEMBER(mlanding_state::analog2_lsb_r) |
| 499 | 499 | { |
| 500 | 500 | /* |
| 501 | 76543210 | |
| 502 | ....xxxx Counter 2 bits 3-0 | |
| 501 | 76543210 | |
| 502 | ....xxxx Counter 2 bits 3-0 | |
| 503 | 503 | */ |
| 504 | 504 | return ioport("STICK_X")->read() & 0x0f; |
| 505 | 505 | } |
| r25360 | r25361 | |
| 508 | 508 | READ16_MEMBER(mlanding_state::analog3_lsb_r) |
| 509 | 509 | { |
| 510 | 510 | /* |
| 511 | 76543210 | |
| 512 | ....xxxx Counter 3 bits 3-0 | |
| 513 | ...x.... Handle up | |
| 514 | ..x..... Handle right | |
| 515 | .x...... Handle down | |
| 511 | 76543210 | |
| 512 | ....xxxx Counter 3 bits 3-0 | |
| 513 | ...x.... Handle up | |
| 514 | ..x..... Handle right | |
| 515 | .x...... Handle down | |
| 516 | 516 | */ |
| 517 | 517 | UINT16 x = ioport("STICK_X")->read(); |
| 518 | 518 | UINT16 y = ioport("STICK_Y")->read(); |
| r25360 | r25361 | |
| 546 | 546 | WRITE16_MEMBER(mlanding_state::dsp_control_w) |
| 547 | 547 | { |
| 548 | 548 | /* |
| 549 | 1 after zeroing 'dot' RAM | |
| 550 | 3 after uploading DSP program | |
| 549 | 1 after zeroing 'dot' RAM | |
| 550 | 3 after uploading DSP program | |
| 551 | 551 | */ |
| 552 | 552 | m_dsp->set_input_line(INPUT_LINE_RESET, data & 0x2 ? CLEAR_LINE : ASSERT_LINE); |
| 553 | 553 | } |
| r25360 | r25361 | |
| 692 | 692 | READ8_MEMBER(mlanding_state::motor_r) |
| 693 | 693 | { |
| 694 | 694 | /* |
| 695 | 9001: RIGHT MOTOR: 1F=UP, 00=STOP, 2F=DOWN | |
| 696 | 9003: LEFT MOTOR: 1F=UP, 00=STOP, 2F=DOWN | |
| 695 | 9001: RIGHT MOTOR: 1F=UP, 00=STOP, 2F=DOWN | |
| 696 | 9003: LEFT MOTOR: 1F=UP, 00=STOP, 2F=DOWN | |
| 697 | 697 | |
| 698 | 9800: xxxx .... - Counter R 3-0 | |
| 699 | 9801: .... xxxx - Counter R 7-4 | |
| 700 | ...x .... - SW R | |
| 701 | 9802: xxxx .... - Counter L 3-0 | |
| 702 | 9803: .... xxxx - Counter L 7-4 | |
| 703 | 9804: .... .... - | |
| 704 | 9805: ...x .... - SW L | |
| 698 | 9800: xxxx .... - Counter R 3-0 | |
| 699 | 9801: .... xxxx - Counter R 7-4 | |
| 700 | ...x .... - SW R | |
| 701 | 9802: xxxx .... - Counter L 3-0 | |
| 702 | 9803: .... xxxx - Counter L 7-4 | |
| 703 | 9804: .... .... - | |
| 704 | 9805: ...x .... - SW L | |
| 705 | 705 | */ |
| 706 | 706 | |
| 707 | 707 | return 0x10; |
| r25360 | r25361 | |
| 928 | 928 | |
| 929 | 929 | static Z80CTC_INTERFACE( ctc_intf ) |
| 930 | 930 | { |
| 931 | DEVCB_NULL, | |
| 931 | DEVCB_NULL, // Interrupt handler | |
| 932 | 932 | DEVCB_DRIVER_LINE_MEMBER(mlanding_state, z80ctc_to0), // ZC/TO0 callback |
| 933 | 933 | DEVCB_NULL, // ZC/TO1 callback |
| 934 | DEVCB_NULL | |
| 934 | DEVCB_NULL // ZC/TO2 callback | |
| 935 | 935 | }; |
| 936 | 936 | |
| 937 | 937 | |
| 938 | 938 | static const msm5205_interface msm5205_1_config = |
| 939 | 939 | { |
| 940 | 940 | DEVCB_DRIVER_LINE_MEMBER(mlanding_state, msm5205_1_vck), // VCK function |
| 941 | MSM5205_S48_4B | |
| 941 | MSM5205_S48_4B // 8 kHz, 4-bit | |
| 942 | 942 | }; |
| 943 | 943 | |
| 944 | 944 | |
| 945 | 945 | static const msm5205_interface msm5205_2_config = |
| 946 | 946 | { |
| 947 | DEVCB_NULL, // VCK function | |
| 948 | MSM5205_SEX_4B // Slave mode, 4-bit | |
| 947 | DEVCB_NULL, // VCK function | |
| 948 | MSM5205_SEX_4B // Slave mode, 4-bit | |
| 949 | 949 | }; |
| 950 | 950 | |
| 951 | 951 |
| r25360 | r25361 | |
|---|---|---|
| 521 | 521 | |
| 522 | 522 | /*bits 0-7 are almost surely to be coinage.*/ |
| 523 | 523 | PORT_START("DSW1") |
| 524 | PORT_DIPUNUSED_DIPLOC( 0x0001, IP_ACTIVE_LOW, "SW1:8" ) /* Listed as "Always Off" */ | |
| 525 | PORT_DIPUNUSED_DIPLOC( 0x0002, IP_ACTIVE_LOW, "SW1:7" ) /* Listed as "Always Off" */ | |
| 526 | PORT_DIPNAME( 0x001c, 0x001c, DEF_STR( Coin_B ) ) PORT_DIPLOCATION("SW1:6,5,4") | |
| 524 | PORT_DIPUNUSED_DIPLOC( 0x0001, IP_ACTIVE_LOW, "SW1:8" ) /* Listed as "Always Off" */ | |
| 525 | PORT_DIPUNUSED_DIPLOC( 0x0002, IP_ACTIVE_LOW, "SW1:7" ) /* Listed as "Always Off" */ | |
| 526 | PORT_DIPNAME( 0x001c, 0x001c, DEF_STR( Coin_B ) ) PORT_DIPLOCATION("SW1:6,5,4") | |
| 527 | 527 | PORT_DIPSETTING( 0x0010, DEF_STR( 4C_1C ) ) |
| 528 | 528 | PORT_DIPSETTING( 0x0008, DEF_STR( 3C_1C ) ) |
| 529 | 529 | PORT_DIPSETTING( 0x0018, DEF_STR( 2C_1C ) ) |
| r25360 | r25361 | |
| 532 | 532 | PORT_DIPSETTING( 0x0014, DEF_STR( 1C_3C ) ) |
| 533 | 533 | PORT_DIPSETTING( 0x0004, DEF_STR( 1C_4C ) ) |
| 534 | 534 | PORT_DIPSETTING( 0x0000, DEF_STR( Free_Play ) ) |
| 535 | PORT_DIPNAME( 0x00e0, 0x00e0, DEF_STR( Coin_A ) ) | |
| 535 | PORT_DIPNAME( 0x00e0, 0x00e0, DEF_STR( Coin_A ) ) PORT_DIPLOCATION("SW1:3,2,1") | |
| 536 | 536 | PORT_DIPSETTING( 0x0080, DEF_STR( 4C_1C ) ) |
| 537 | 537 | PORT_DIPSETTING( 0x0040, DEF_STR( 3C_1C ) ) |
| 538 | 538 | PORT_DIPSETTING( 0x00c0, DEF_STR( 2C_1C ) ) |
| r25360 | r25361 | |
| 541 | 541 | PORT_DIPSETTING( 0x00a0, DEF_STR( 1C_3C ) ) |
| 542 | 542 | PORT_DIPSETTING( 0x0020, DEF_STR( 1C_4C ) ) |
| 543 | 543 | PORT_DIPSETTING( 0x0000, DEF_STR( Free_Play ) ) /* Not listed in "dips" text, but current effect is FREE PLAY. Is this correct? */ |
| 544 | PORT_DIPNAME( 0x0100, 0x0100, DEF_STR( Flip_Screen ) ) | |
| 544 | PORT_DIPNAME( 0x0100, 0x0100, DEF_STR( Flip_Screen ) ) PORT_DIPLOCATION("SW2:8") | |
| 545 | 545 | PORT_DIPSETTING( 0x0100, DEF_STR( Off ) ) |
| 546 | 546 | PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) |
| 547 | PORT_DIPNAME( 0x0200, 0x0000, DEF_STR( Demo_Sounds ) ) | |
| 547 | PORT_DIPNAME( 0x0200, 0x0000, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW2:7") | |
| 548 | 548 | PORT_DIPSETTING( 0x0200, DEF_STR( Off ) ) |
| 549 | 549 | PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) |
| 550 | PORT_DIPNAME( 0x0400, 0x0000, DEF_STR( Language ) ) | |
| 550 | PORT_DIPNAME( 0x0400, 0x0000, DEF_STR( Language ) ) PORT_DIPLOCATION("SW2:6") | |
| 551 | 551 | PORT_DIPSETTING( 0x0400, DEF_STR( Japanese ) ) |
| 552 | 552 | PORT_DIPSETTING( 0x0000, DEF_STR( English ) ) |
| 553 | PORT_DIPNAME( 0x1800, 0x1800, DEF_STR( Difficulty ) ) | |
| 553 | PORT_DIPNAME( 0x1800, 0x1800, DEF_STR( Difficulty ) ) PORT_DIPLOCATION("SW2:5,4") | |
| 554 | 554 | PORT_DIPSETTING( 0x0800, DEF_STR( Easy ) ) |
| 555 | 555 | PORT_DIPSETTING( 0x1800, DEF_STR( Normal ) ) |
| 556 | 556 | PORT_DIPSETTING( 0x1000, DEF_STR( Hard ) ) |
| 557 | 557 | PORT_DIPSETTING( 0x0000, DEF_STR( Hardest ) ) |
| 558 | PORT_DIPNAME( 0x2000, 0x2000, "Lady Stripping" ) | |
| 558 | PORT_DIPNAME( 0x2000, 0x2000, "Lady Stripping" ) PORT_DIPLOCATION("SW2:3") | |
| 559 | 559 | PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) |
| 560 | 560 | PORT_DIPSETTING( 0x2000, DEF_STR( On ) ) |
| 561 | PORT_DIPUNUSED_DIPLOC( 0x4000, IP_ACTIVE_LOW, "SW2:2" ) /* Listed as "Always Off" */ | |
| 562 | PORT_DIPUNUSED_DIPLOC( 0x8000, IP_ACTIVE_LOW, "SW2:1" ) /* Listed as "Always Off" */ | |
| 561 | PORT_DIPUNUSED_DIPLOC( 0x4000, IP_ACTIVE_LOW, "SW2:2" ) /* Listed as "Always Off" */ | |
| 562 | PORT_DIPUNUSED_DIPLOC( 0x8000, IP_ACTIVE_LOW, "SW2:1" ) /* Listed as "Always Off" */ | |
| 563 | 563 | |
| 564 | 564 | PORT_START("UNK") |
| 565 | 565 | INPUT_PORTS_END |
| r25360 | r25361 | |
|---|---|---|
| 33 | 33 | |
| 34 | 34 | required_shared_ptr<UINT8> m_videoram; |
| 35 | 35 | required_shared_ptr<UINT8> m_colorram; |
| 36 | ||
| 36 | ||
| 37 | 37 | required_device<cpu_device> m_maincpu; |
| 38 | 38 | required_device<s14001a_device> m_s14001a; |
| 39 | 39 | required_device<ttl74181_device> m_ls181_10c; |
| 40 | 40 | required_device<ttl74181_device> m_ls181_12c; |
| 41 | 41 | required_device<exidy_sound_device> m_custom; |
| 42 | ||
| 42 | ||
| 43 | 43 | UINT8 m_magicram_control; |
| 44 | 44 | UINT8 m_last_shift_data; |
| 45 | 45 | UINT8 m_intercept; |
| r25360 | r25361 | |
|---|---|---|
| 138 | 138 | * RR1.GAM (for Ridge Racer 1/2, Rave Racer) |
| 139 | 139 | ********************************************************************************************************** |
| 140 | 140 | * |
| 141 | *Namco Super System 22 Hardware Overview (last updated 21st | |
| 142 | *December 2012 at 7:15pm) | |
| 141 | *Namco Super System 22 Hardware Overview (last updated 21st | |
| 142 | *December 2012 at 7:15pm) | |
| 143 | 143 | *--------------------------------------- |
| 144 | 144 | * |
| 145 | 145 | *This document covers all the known Namco Super System 22 games, including.... |
| r25360 | r25361 | |
| 883 | 883 | * |
| 884 | 884 | *Game ROMs populated (All Intel E28F016SA TSOP56 16M FlashROMs) |
| 885 | 885 | *----------------------------------------------------------------- |
| 886 | *Armadillo Racing F1E, F1J, F2E, F2J - CCRL/CCRH | |
| 887 | *ROMs (prototype or | |
| 886 | *Armadillo Racing F1E, F1J, F2E, F2J - CCRL/CCRH | |
| 887 | *ROMs (prototype or | |
| 888 | 888 | *early test version)F4E, F4J, F5E, F5J, F6E, F6J, \ |
| 889 | 889 | * F7E, F7J, F8E, F8J, F9E, F9J, \ CGx ROMs |
| 890 | 890 | * F11E, F11J, F12E, F12J / |
| r25360 | r25361 | |
| 1292 | 1292 | } |
| 1293 | 1293 | break; |
| 1294 | 1294 | } |
| 1295 | ||
| 1295 | ||
| 1296 | 1296 | // acknowledge irqs |
| 1297 | 1297 | case 0x04: // vblank |
| 1298 | 1298 | case 0x05: // hblank |
| r25360 | r25361 | |
| 1304 | 1304 | m_maincpu->set_input_line(m_syscontrol[offset-4] & 7, CLEAR_LINE); |
| 1305 | 1305 | break; |
| 1306 | 1306 | } |
| 1307 | ||
| 1307 | ||
| 1308 | 1308 | // watchdog |
| 1309 | 1309 | case 0x14: |
| 1310 | 1310 | break; |
| 1311 | ||
| 1311 | ||
| 1312 | 1312 | // reset mcu |
| 1313 | 1313 | case 0x16: |
| 1314 | 1314 | m_mcu->set_input_line(INPUT_LINE_RESET, data ? CLEAR_LINE : ASSERT_LINE); |
| 1315 | 1315 | break; |
| 1316 | ||
| 1316 | ||
| 1317 | 1317 | // dsp control |
| 1318 | 1318 | case 0x1c: |
| 1319 | 1319 | if (data != m_syscontrol[0x1c]) |
| r25360 | r25361 | |
| 1341 | 1341 | } |
| 1342 | 1342 | } |
| 1343 | 1343 | break; |
| 1344 | ||
| 1344 | ||
| 1345 | 1345 | // other regs: unknown |
| 1346 | 1346 | default: |
| 1347 | 1347 | break; |
| 1348 | 1348 | } |
| 1349 | ||
| 1349 | ||
| 1350 | 1350 | m_syscontrol[offset] = data; |
| 1351 | 1351 | } |
| 1352 | 1352 | |
| r25360 | r25361 | |
| 1436 | 1436 | } |
| 1437 | 1437 | break; |
| 1438 | 1438 | } |
| 1439 | ||
| 1439 | ||
| 1440 | 1440 | // acknowledge irqs |
| 1441 | 1441 | case 0x05: // unknown |
| 1442 | 1442 | case 0x06: // ? |
| r25360 | r25361 | |
| 1449 | 1449 | m_maincpu->set_input_line(m_syscontrol[offset-5] & 7, CLEAR_LINE); |
| 1450 | 1450 | break; |
| 1451 | 1451 | } |
| 1452 | ||
| 1452 | ||
| 1453 | 1453 | // watchdog |
| 1454 | 1454 | case 0x16: |
| 1455 | 1455 | break; |
| 1456 | ||
| 1456 | ||
| 1457 | 1457 | // reset mcu |
| 1458 | 1458 | case 0x18: |
| 1459 | 1459 | m_mcu->set_input_line(INPUT_LINE_RESET, data ? CLEAR_LINE : ASSERT_LINE); |
| r25360 | r25361 | |
| 1661 | 1661 | // other bits: no clue |
| 1662 | 1662 | if (ACCESSING_BITS_16_23) |
| 1663 | 1663 | m_chipselect = data >> 16; |
| 1664 | ||
| 1664 | ||
| 1665 | 1665 | // 8-bit access? (see alpinerd) |
| 1666 | 1666 | else if (ACCESSING_BITS_24_31) |
| 1667 | 1667 | m_chipselect = data >> 24; |
| r25360 | r25361 | |
| 1987 | 1987 | READ16_MEMBER(namcos22_state::namcos22_dspram16_r) |
| 1988 | 1988 | { |
| 1989 | 1989 | UINT32 value = m_polygonram[offset]; |
| 1990 | ||
| 1990 | ||
| 1991 | 1991 | switch (m_dspram_bank) |
| 1992 | 1992 | { |
| 1993 | 1993 | case 0: |
| r25360 | r25361 | |
| 2006 | 2006 | default: |
| 2007 | 2007 | break; |
| 2008 | 2008 | } |
| 2009 | ||
| 2009 | ||
| 2010 | 2010 | return (UINT16)value; |
| 2011 | 2011 | } |
| 2012 | 2012 | |
| r25360 | r25361 | |
| 2034 | 2034 | default: |
| 2035 | 2035 | break; |
| 2036 | 2036 | } |
| 2037 | ||
| 2037 | ||
| 2038 | 2038 | m_polygonram[offset] = (hi << 16) | lo; |
| 2039 | 2039 | } |
| 2040 | 2040 | |
| r25360 | r25361 | |
| 2246 | 2246 | } |
| 2247 | 2247 | } |
| 2248 | 2248 | } |
| 2249 | ||
| 2249 | ||
| 2250 | 2250 | return 0; |
| 2251 | 2251 | } |
| 2252 | 2252 | |
| r25360 | r25361 | |
| 3681 | 3681 | m_master->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); |
| 3682 | 3682 | m_slave->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); |
| 3683 | 3683 | m_mcu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); |
| 3684 | ||
| 3684 | ||
| 3685 | 3685 | m_poly->reset(); |
| 3686 | 3686 | } |
| 3687 | 3687 | |
| r25360 | r25361 | |
| 3799 | 3799 | /* basic machine hardware */ |
| 3800 | 3800 | MCFG_CPU_MODIFY("mcu") |
| 3801 | 3801 | MCFG_CPU_IO_MAP(alpine_io_map) |
| 3802 | ||
| 3802 | ||
| 3803 | 3803 | MCFG_TIMER_DRIVER_ADD("motor_timer", namcos22_state, alpine_steplock_callback) |
| 3804 | 3804 | MACHINE_CONFIG_END |
| 3805 | 3805 | |
| r25360 | r25361 | |
| 3822 | 3822 | /* basic machine hardware */ |
| 3823 | 3823 | MCFG_CPU_MODIFY("mcu") |
| 3824 | 3824 | MCFG_CPU_IO_MAP(propcycl_io_map) |
| 3825 | ||
| 3825 | ||
| 3826 | 3826 | MCFG_TIMER_DRIVER_ADD_PERIODIC("pc_p_upd", namcos22_state, propcycl_pedal_update, attotime::from_msec(20)) |
| 3827 | 3827 | MCFG_TIMER_DRIVER_ADD("pc_p_int", namcos22_state, propcycl_pedal_interrupt) |
| 3828 | 3828 | MACHINE_CONFIG_END |
| r25360 | r25361 | |
|---|---|---|
| 2853 | 2853 | memcpy(buffer+i*0x100, rom+ckonggx_remap[i], 0x100); |
| 2854 | 2854 | |
| 2855 | 2855 | } |
| 2856 | ||
| 2856 | ||
| 2857 | 2857 | memcpy(rom, buffer, 0x5800); |
| 2858 | 2858 | auto_free(machine(), buffer); |
| 2859 | 2859 | } |
| r25360 | r25361 | |
| 2864 | 2864 | |
| 2865 | 2865 | ROM_START( ckonggx ) |
| 2866 | 2866 | ROM_REGION( 0x10000, "maincpu", 0 ) |
| 2867 | ROM_LOAD( "kk1.bin", 0x0000, 0x0800, CRC(615c1ddb) SHA1(68e8393da9041cf94692fc4b53b58c17086e4ebc) ) | |
| 2867 | ROM_LOAD( "kk1.bin", 0x0000, 0x0800, CRC(615c1ddb) SHA1(68e8393da9041cf94692fc4b53b58c17086e4ebc) ) | |
| 2868 | 2868 | ROM_LOAD( "kk2.bin", 0x0800, 0x0800, CRC(72f259bc) SHA1(0afa349926f70b6c35da1dbb380ad2018f003d56) ) |
| 2869 | 2869 | ROM_LOAD( "kk3.bin", 0x1000, 0x0800, CRC(17f5e9ac) SHA1(17218ca3582ff4498e0b2684781db24d528bff71) ) |
| 2870 | 2870 | ROM_LOAD( "kk4.bin", 0x1800, 0x0800, CRC(7aeafd74) SHA1(b9382322367b3953498e8fbbe81b26b18cd7a745) ) |
| r25360 | r25361 | |
| 2958 | 2958 | ROM_LOAD( "dk5.bin", 0x3000, 0x1000, CRC(d8df2ec4) SHA1(bef1d4b404cddb8a5f9d4e3f30ee09915c602f56) ) |
| 2959 | 2959 | ROM_LOAD( "dk6.bin", 0x4000, 0x1000, CRC(9ddcc06f) SHA1(63bc77d8b3273681ca4e681105a117d19a0f23a5) ) |
| 2960 | 2960 | |
| 2961 | // | |
| 2961 | // ROM_LOAD( "kk8.bin", 0x5000, 0x0800, CRC(8cd4bc17) SHA1(43c3f2575182c8f5233b9c6160aa9f41d772bb9d) ) // works if you use this rom from ckonggx but it's definitely not on the PCB | |
| 2962 | 2962 | |
| 2963 | 2963 | ROM_REGION( 0x2000, "gfx1", 0 ) |
| 2964 | 2964 | ROM_LOAD( "1h.bin", 0x0000, 0x1000, CRC(7866d2cb) SHA1(62dd8b80bc0459c7337d8a8cb83e53b999e7f4a9) ) |
| r25360 | r25361 | |
|---|---|---|
| 731 | 731 | |
| 732 | 732 | MCFG_MACHINE_START_OVERRIDE(atarisy1_state,atarisy1) |
| 733 | 733 | MCFG_MACHINE_RESET_OVERRIDE(atarisy1_state,atarisy1) |
| 734 | ||
| 734 | ||
| 735 | 735 | MCFG_ATARI_EEPROM_2804_ADD("eeprom") |
| 736 | 736 | |
| 737 | 737 | MCFG_TIMER_DRIVER_ADD("joystick_timer", atarisy1_state, delayed_joystick_int) |
| r25360 | r25361 | |
| 746 | 746 | |
| 747 | 747 | MCFG_TILEMAP_ADD_STANDARD("playfield", 2, atarisy1_state, get_playfield_tile_info, 8,8, SCAN_ROWS, 64,64) |
| 748 | 748 | MCFG_TILEMAP_ADD_STANDARD_TRANSPEN("alpha", 2, atarisy1_state, get_alpha_tile_info, 8,8, SCAN_ROWS, 64,32, 0) |
| 749 | ||
| 749 | ||
| 750 | 750 | MCFG_ATARI_MOTION_OBJECTS_ADD("mob", "screen", atarisy1_state::s_mob_config) |
| 751 | 751 | |
| 752 | 752 | MCFG_SCREEN_ADD("screen", RASTER) |
| r25360 | r25361 | |
|---|---|---|
| 542 | 542 | |
| 543 | 543 | MCFG_MACHINE_START_OVERRIDE(atarig42_state,atarig42) |
| 544 | 544 | MCFG_MACHINE_RESET_OVERRIDE(atarig42_state,atarig42) |
| 545 | ||
| 545 | ||
| 546 | 546 | MCFG_ATARI_EEPROM_2816_ADD("eeprom") |
| 547 | 547 | |
| 548 | 548 | /* video hardware */ |
| r25360 | r25361 | |
|---|---|---|
| 183 | 183 | MCFG_CPU_PROGRAM_MAP(main_map) |
| 184 | 184 | |
| 185 | 185 | MCFG_MACHINE_RESET_OVERRIDE(vindictr_state,vindictr) |
| 186 | ||
| 186 | ||
| 187 | 187 | MCFG_ATARI_EEPROM_2804_ADD("eeprom") |
| 188 | 188 | |
| 189 | 189 | /* video hardware */ |
| r25360 | r25361 | |
| 194 | 194 | MCFG_TILEMAP_ADD_STANDARD("playfield", 2, vindictr_state, get_playfield_tile_info, 8,8, SCAN_COLS, 64,64) |
| 195 | 195 | MCFG_TILEMAP_ADD_STANDARD_TRANSPEN("alpha", 2, vindictr_state, get_alpha_tile_info, 8,8, SCAN_ROWS, 64,32, 0) |
| 196 | 196 | MCFG_ATARI_MOTION_OBJECTS_ADD("mob", "screen", vindictr_state::s_mob_config) |
| 197 | ||
| 197 | ||
| 198 | 198 | MCFG_SCREEN_ADD("screen", RASTER) |
| 199 | 199 | /* note: these parameters are from published specs, not derived */ |
| 200 | 200 | /* the board uses a SYNGEN chip to generate video signals */ |
| r25360 | r25361 | |
|---|---|---|
| 99 | 99 | if (m_flipscreen) |
| 100 | 100 | { |
| 101 | 101 | delta = -1; |
| 102 | x0 = 256-1; x1 = -1; | |
| 103 | y0 = 256-1; y1 = -1; | |
| 102 | x0 = 256-1; x1 = -1; | |
| 103 | y0 = 256-1; y1 = -1; | |
| 104 | 104 | } |
| 105 | 105 | else |
| 106 | 106 | { |
| 107 | 107 | delta = 1; |
| 108 | x0 = 0; x1 = 256; | |
| 109 | y0 = 0; y1 = 256; | |
| 108 | x0 = 0; x1 = 256; | |
| 109 | y0 = 0; y1 = 256; | |
| 110 | 110 | } |
| 111 | 111 | |
| 112 | 112 | int pixaddr = 0; |
| r25360 | r25361 | |
| 114 | 114 | { |
| 115 | 115 | for (x = x0; x != x1; x += delta) |
| 116 | 116 | { |
| 117 | UINT8 p1 = m_vram1[pixaddr/2]; | |
| 118 | UINT8 p2 = m_vram2[pixaddr/2]; | |
| 119 | UINT8 mask = (pixaddr & 1) ? 0xf0 : 0x0f; | |
| 120 | UINT8 shift = (pixaddr & 1) ? 4 : 0; | |
| 117 | UINT8 p1 = m_vram1[pixaddr/2]; | |
| 118 | UINT8 p2 = m_vram2[pixaddr/2]; | |
| 119 | UINT8 mask = (pixaddr & 1) ? 0xf0 : 0x0f; | |
| 120 | UINT8 shift = (pixaddr & 1) ? 4 : 0; | |
| 121 | 121 | |
| 122 | 122 | if (p2 & mask) |
| 123 | 123 | bitmap.pix16(y, x) = (p2 & mask) >> shift; |
| r25360 | r25361 | |
| 164 | 164 | READ8_MEMBER(laserbas_state::protram_r) |
| 165 | 165 | { |
| 166 | 166 | UINT8 prot = m_protram[offset]; |
| 167 | // prot = machine().rand(); | |
| 168 | // logerror("%s: Z1 read %03x = %02x\n", machine().describe_context(), offset, prot); | |
| 167 | // prot = machine().rand(); | |
| 168 | // logerror("%s: Z1 read %03x = %02x\n", machine().describe_context(), offset, prot); | |
| 169 | 169 | return prot; |
| 170 | 170 | } |
| 171 | 171 | |
| 172 | 172 | WRITE8_MEMBER(laserbas_state::protram_w) |
| 173 | 173 | { |
| 174 | // | |
| 174 | // logerror("%s: Z1 write %03x = %02x\n", machine().describe_context(), offset, data); | |
| 175 | 175 | m_protram[offset] = data; |
| 176 | 176 | } |
| 177 | 177 | |
| r25360 | r25361 | |
| 222 | 222 | ADDRESS_MAP_END |
| 223 | 223 | |
| 224 | 224 | static INPUT_PORTS_START( laserbas ) |
| 225 | PORT_START("DSW") // $20 | |
| 226 | PORT_DIPNAME( 0x01, 0x01, DEF_STR( Cabinet ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 227 | PORT_DIPSETTING( 0x00, DEF_STR( Upright ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 228 | PORT_DIPSETTING( 0x01, DEF_STR( Cocktail ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 229 | PORT_DIPNAME( 0x02, 0x02, DEF_STR( Difficulty ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 230 | PORT_DIPSETTING( 0x00, DEF_STR( Easy ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 231 | PORT_DIPSETTING( 0x02, DEF_STR( Normal ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 232 | PORT_DIPNAME( 0x04, 0x04, DEF_STR( Bonus_Life ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 233 | PORT_DIPSETTING( 0x04, "10k" ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 234 | PORT_DIPSETTING( 0x00, "30k" ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 235 | PORT_DIPNAME( 0x08, 0x08, DEF_STR( Demo_Sounds ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 236 | PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 237 | PORT_DIPSETTING( 0x08, DEF_STR( On ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 238 | PORT_DIPNAME( 0x30, 0x30, DEF_STR( Coin_B ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 239 | PORT_DIPSETTING( 0x10, DEF_STR( 3C_1C ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 240 | PORT_DIPSETTING( 0x20, DEF_STR( 2C_1C ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 241 | PORT_DIPSETTING( 0x30, DEF_STR( 1C_1C ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 242 | PORT_DIPSETTING( 0x00, DEF_STR( Free_Play ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 243 | PORT_DIPNAME( 0xc0, 0xc0, DEF_STR( Coin_A ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 244 | PORT_DIPSETTING( 0xc0, DEF_STR( 1C_1C ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 245 | PORT_DIPSETTING( 0x80, DEF_STR( 1C_2C ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 246 | PORT_DIPSETTING( 0x40, DEF_STR( 1C_3C ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 247 | PORT_DIPSETTING( 0x00, DEF_STR( 1C_6C ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 225 | PORT_START("DSW") // $20 | |
| 226 | PORT_DIPNAME( 0x01, 0x01, DEF_STR( Cabinet ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 227 | PORT_DIPSETTING( 0x00, DEF_STR( Upright ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 228 | PORT_DIPSETTING( 0x01, DEF_STR( Cocktail ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 229 | PORT_DIPNAME( 0x02, 0x02, DEF_STR( Difficulty ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 230 | PORT_DIPSETTING( 0x00, DEF_STR( Easy ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 231 | PORT_DIPSETTING( 0x02, DEF_STR( Normal ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 232 | PORT_DIPNAME( 0x04, 0x04, DEF_STR( Bonus_Life ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 233 | PORT_DIPSETTING( 0x04, "10k" ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 234 | PORT_DIPSETTING( 0x00, "30k" ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 235 | PORT_DIPNAME( 0x08, 0x08, DEF_STR( Demo_Sounds ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 236 | PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 237 | PORT_DIPSETTING( 0x08, DEF_STR( On ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 238 | PORT_DIPNAME( 0x30, 0x30, DEF_STR( Coin_B ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 239 | PORT_DIPSETTING( 0x10, DEF_STR( 3C_1C ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 240 | PORT_DIPSETTING( 0x20, DEF_STR( 2C_1C ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 241 | PORT_DIPSETTING( 0x30, DEF_STR( 1C_1C ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 242 | PORT_DIPSETTING( 0x00, DEF_STR( Free_Play ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 243 | PORT_DIPNAME( 0xc0, 0xc0, DEF_STR( Coin_A ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 244 | PORT_DIPSETTING( 0xc0, DEF_STR( 1C_1C ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 245 | PORT_DIPSETTING( 0x80, DEF_STR( 1C_2C ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 246 | PORT_DIPSETTING( 0x40, DEF_STR( 1C_3C ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 247 | PORT_DIPSETTING( 0x00, DEF_STR( 1C_6C ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20) | |
| 248 | 248 | // To do: split into separate switches (easier to debug as it is now though) |
| 249 | PORT_DIPNAME( 0xff, 0xfe, "Service Mode Test" ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x00) | |
| 250 | PORT_DIPSETTING( 0xfe, "S RAM CHECK" ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x00) | |
| 251 | PORT_DIPSETTING( 0xfd, "D RAM CHECK F" ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x00) | |
| 252 | PORT_DIPSETTING( 0xfb, "D RAM CHECK B" ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x00) | |
| 253 | PORT_DIPSETTING( 0xf7, "ROM CHECK" ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x00) | |
| 254 | PORT_DIPSETTING( 0xef, "CRT INVERT CHECK" ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x00) // press start 2 | |
| 255 | PORT_DIPSETTING( 0xdf, "SWITCH CHECK" ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x00) | |
| 256 | PORT_DIPSETTING( 0xbf, "COLOR CHECK" ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x00) | |
| 257 | PORT_DIPSETTING( 0x7f, "SOUND CHECK" ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x00) | |
| 249 | PORT_DIPNAME( 0xff, 0xfe, "Service Mode Test" ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x00) | |
| 250 | PORT_DIPSETTING( 0xfe, "S RAM CHECK" ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x00) | |
| 251 | PORT_DIPSETTING( 0xfd, "D RAM CHECK F" ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x00) | |
| 252 | PORT_DIPSETTING( 0xfb, "D RAM CHECK B" ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x00) | |
| 253 | PORT_DIPSETTING( 0xf7, "ROM CHECK" ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x00) | |
| 254 | PORT_DIPSETTING( 0xef, "CRT INVERT CHECK" ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x00) // press start 2 | |
| 255 | PORT_DIPSETTING( 0xdf, "SWITCH CHECK" ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x00) | |
| 256 | PORT_DIPSETTING( 0xbf, "COLOR CHECK" ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x00) | |
| 257 | PORT_DIPSETTING( 0x7f, "SOUND CHECK" ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x00) | |
| 258 | 258 | |
| 259 | PORT_START("INPUTS") | |
| 259 | PORT_START("INPUTS") // $21 | |
| 260 | 260 | PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) |
| 261 | 261 | PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) |
| 262 | 262 | PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START1 ) |
| r25360 | r25361 | |
| 264 | 264 | PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_COIN2 ) |
| 265 | 265 | PORT_SERVICE( 0x20, IP_ACTIVE_LOW ) |
| 266 | 266 | PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 ) |
| 267 | PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SERVICE1 ) | |
| 267 | PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SERVICE1 ) // service coin | |
| 268 | 268 | |
| 269 | 269 | PORT_START("TRACK_X") |
| 270 | 270 | PORT_BIT( 0x1f, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(10) PORT_KEYDELTA(1) PORT_RESET |
| r25360 | r25361 | |
| 350 | 350 | MCFG_CPU_PROGRAM_MAP(laserbas_memory) |
| 351 | 351 | MCFG_CPU_IO_MAP(laserbas_io) |
| 352 | 352 | MCFG_CPU_VBLANK_INT_DRIVER("screen", laserbas_state, irq0_line_hold) |
| 353 | // | |
| 353 | // MCFG_TIMER_DRIVER_ADD_PERIODIC("nmi", laserbas_state, nmi_line_pulse, attotime::from_hz(60)) | |
| 354 | 354 | |
| 355 | 355 | MCFG_PIT8253_ADD("pit0", laserbas_pit8253_intf_0) |
| 356 | 356 | MCFG_PIT8253_ADD("pit1", laserbas_pit8253_intf_1) |
| r25360 | r25361 | |
|---|---|---|
| 1783 | 1783 | MCFG_SOUND_ROUTE(0, "lspeaker", 1.0) |
| 1784 | 1784 | MCFG_SOUND_ROUTE(1, "rspeaker", 1.0) |
| 1785 | 1785 | |
| 1786 | // TODO: Hookup cdrom audio | |
| 1787 | // MCFG_SOUND_MODIFY("scsi1:cdda") | |
| 1788 | // MCFG_SOUND_ROUTE(0, "^^lspeaker", 1.0) | |
| 1789 | // MCFG_SOUND_ROUTE(1, "^^rspeaker", 1.0) | |
| 1786 | // TODO: Hookup cdrom audio | |
| 1787 | // MCFG_SOUND_MODIFY("scsi1:cdda") | |
| 1788 | // MCFG_SOUND_ROUTE(0, "^^lspeaker", 1.0) | |
| 1789 | // MCFG_SOUND_ROUTE(1, "^^rspeaker", 1.0) | |
| 1790 | 1790 | |
| 1791 | 1791 | MCFG_PC16552D_ADD("duart_com", firebeat_com0_interface, firebeat_com1_interface, XTAL_19_6608MHz) // pgmd to 9600baud |
| 1792 | 1792 | MCFG_PC16552D_ADD("duart_midi", firebeat_midi0_interface, firebeat_midi1_interface, XTAL_24MHz) // in all memory maps, pgmd to 31250baud |
| r25360 | r25361 | |
|---|---|---|
| 327 | 327 | |
| 328 | 328 | MCFG_MCD212_ADD("mcd212") |
| 329 | 329 | MCFG_MCD212_SET_SCREEN("screen") |
| 330 | ||
| 330 | ||
| 331 | 331 | MCFG_SCREEN_ADD("screen", RASTER) |
| 332 | 332 | MCFG_SCREEN_REFRESH_RATE(60) |
| 333 | 333 | MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0)) |
| r25360 | r25361 | |
|---|---|---|
| 82 | 82 | TILE_GET_INFO_MEMBER(get_tile3_info); |
| 83 | 83 | |
| 84 | 84 | int m_oki_bank; |
| 85 | UINT16 | |
| 85 | UINT16 m_gfx_control; | |
| 86 | 86 | |
| 87 | 87 | DECLARE_WRITE16_HANDLER(gfx_ctrl_w); |
| 88 | 88 | DECLARE_WRITE16_HANDLER(tilemap1_scrollx_w); |
| r25360 | r25361 | |
| 177 | 177 | |
| 178 | 178 | UINT32 _3x3puzzle_state::screen_update( screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect ) |
| 179 | 179 | { |
| 180 | ||
| 181 | ||
| 182 | 180 | m_tilemap1->draw(screen, bitmap, cliprect, 0, 1); |
| 183 | 181 | m_tilemap2->draw(screen, bitmap, cliprect, 0, 2); |
| 184 | 182 | m_tilemap3->draw(screen, bitmap, cliprect, 0, 3); |
| r25360 | r25361 | |
| 241 | 239 | PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) |
| 242 | 240 | PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_UNUSED ) |
| 243 | 241 | PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNUSED ) |
| 244 | ||
| 242 | ||
| 245 | 243 | PORT_START("SYS") |
| 246 | 244 | PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_COIN1 ) |
| 247 | 245 | PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_COIN2 ) |
| r25360 | r25361 | |
| 308 | 306 | PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_START1 ) |
| 309 | 307 | |
| 310 | 308 | PORT_MODIFY("DSW01") /* Do NOT trust "DIP INFO" for correct settings! At least Coinage is WRONG! */ |
| 311 | PORT_DIPNAME( 0x0003, 0x0003, DEF_STR( Coinage ) ) | |
| 309 | PORT_DIPNAME( 0x0003, 0x0003, DEF_STR( Coinage ) ) PORT_DIPLOCATION("SW1:1,2") | |
| 312 | 310 | PORT_DIPSETTING( 0x0002, DEF_STR( 1C_2C ) ) /* Dip info shows 2 Coins / Credit */ |
| 313 | 311 | PORT_DIPSETTING( 0x0003, DEF_STR( 1C_1C ) ) |
| 314 | 312 | PORT_DIPSETTING( 0x0001, DEF_STR( 2C_1C ) ) /* Dip info shows 3 Coins / Credit */ |
| 315 | 313 | PORT_DIPSETTING( 0x0000, DEF_STR( 3C_1C ) ) /* Dip info shows 5 Coins / Credit */ |
| 316 | PORT_DIPNAME( 0x000c, 0x000c, DEF_STR( Difficulty ) ) | |
| 314 | PORT_DIPNAME( 0x000c, 0x000c, DEF_STR( Difficulty ) ) PORT_DIPLOCATION("SW1:3,4") | |
| 317 | 315 | PORT_DIPSETTING( 0x0008, DEF_STR( Easy ) ) |
| 318 | 316 | PORT_DIPSETTING( 0x000c, DEF_STR( Normal ) ) |
| 319 | 317 | PORT_DIPSETTING( 0x0004, DEF_STR( Hard ) ) |
| 320 | 318 | PORT_DIPSETTING( 0x0000, DEF_STR( Very_Hard ) ) |
| 321 | PORT_DIPNAME( 0x0010, 0x0000, DEF_STR( Demo_Sounds ) ) | |
| 319 | PORT_DIPNAME( 0x0010, 0x0000, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW1:5") | |
| 322 | 320 | PORT_DIPSETTING( 0x0010, DEF_STR( Off ) ) |
| 323 | 321 | PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) |
| 324 | 322 | PORT_DIPUNUSED_DIPLOC( 0x0020, 0x0020, "SW1:6" ) |
| 325 | 323 | PORT_DIPUNUSED_DIPLOC( 0x0040, 0x0040, "SW1:7" ) |
| 326 | PORT_DIPNAME( 0x0080, 0x0080, "Dip Info" ) | |
| 324 | PORT_DIPNAME( 0x0080, 0x0080, "Dip Info" ) PORT_DIPLOCATION("SW1:8") | |
| 327 | 325 | PORT_DIPSETTING( 0x0080, DEF_STR( Off ) ) |
| 328 | 326 | PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) |
| 329 | 327 | PORT_DIPUNUSED_DIPLOC( 0x0100, 0x0100, "SW2:1" ) /* DSW2 bank, not used? */ |
| r25360 | r25361 | |
| 480 | 478 | ROM_LOAD32_BYTE( "casanova.u81", 0x200000, 0x80000, CRC(9eafd37d) SHA1(bc9e7a035849f23da48c9d923188c61188d93c43) ) |
| 481 | 479 | ROM_LOAD32_BYTE( "casanova.u83", 0x200001, 0x80000, CRC(9d4ce407) SHA1(949c7f329bd348beff4f14ac7b506c8aef212ad8) ) |
| 482 | 480 | ROM_LOAD32_BYTE( "casanova.u85", 0x200002, 0x80000, CRC(113c6e3a) SHA1(e90d78c4415d244004734a481501f8040f8aa468) ) |
| 483 | ROM_LOAD32_BYTE( "casanova.u87", 0x200003, 0x80000, CRC(61bd80f8) SHA1(13b93f2638c37a5dec5b4016c058f486f9cbadae) ) | |
| 481 | ROM_LOAD32_BYTE( "casanova.u87", 0x200003, 0x80000, CRC(61bd80f8) SHA1(13b93f2638c37a5dec5b4016c058f486f9cbadae) ) | |
| 484 | 482 | |
| 485 | 483 | ROM_REGION( 0x200000, "gfx2", 0 ) |
| 486 | 484 | ROM_LOAD32_BYTE( "casanova.u39", 0x000003, 0x80000, CRC(97d4095a) SHA1(4b1fde984025fae240bf64f812d67bc9cbf3a60c) ) |
| r25360 | r25361 | |
|---|---|---|
| 200 | 200 | |
| 201 | 201 | MCFG_MACHINE_START_OVERRIDE(batman_state,batman) |
| 202 | 202 | MCFG_MACHINE_RESET_OVERRIDE(batman_state,batman) |
| 203 | ||
| 203 | ||
| 204 | 204 | MCFG_ATARI_EEPROM_2816_ADD("eeprom") |
| 205 | 205 | |
| 206 | 206 | /* video hardware */ |
| r25360 | r25361 | |
|---|---|---|
| 176 | 176 | MCFG_DEVICE_VBLANK_INT_DRIVER("screen", atarigen_state, video_int_gen) |
| 177 | 177 | |
| 178 | 178 | MCFG_MACHINE_RESET_OVERRIDE(blstroid_state,blstroid) |
| 179 | ||
| 179 | ||
| 180 | 180 | MCFG_ATARI_EEPROM_2804_ADD("eeprom") |
| 181 | 181 | |
| 182 | 182 | /* video hardware */ |
| r25360 | r25361 | |
|---|---|---|
| 1350 | 1350 | MCFG_MACHINE_START_OVERRIDE(harddriv_state,harddriv) |
| 1351 | 1351 | MCFG_MACHINE_RESET_OVERRIDE(harddriv_state,harddriv) |
| 1352 | 1352 | |
| 1353 | // TODO: ZRAM is really an MK48T02 | |
| 1353 | // TODO: ZRAM is really an MK48T02 MCFG_MK48T02_ADD("zram") | |
| 1354 | 1354 | MCFG_NVRAM_ADD_1FILL("zram") |
| 1355 | 1355 | |
| 1356 | 1356 | MCFG_DUARTN68681_ADD("duartn68681", XTAL_3_6864MHz, duart_config) |
| r25360 | r25361 | |
|---|---|---|
| 789 | 789 | m_banknum = -1; |
| 790 | 790 | save_item(NAME(m_banknum)); |
| 791 | 791 | machine().save().register_postload(save_prepost_delegate(FUNC(taitox_state::reset_sound_region), this)); |
| 792 | ||
| 792 | ||
| 793 | 793 | m_current_bank = 0; |
| 794 | 794 | m_cc_port = 0; |
| 795 | 795 | save_item(NAME(m_current_bank)); |
| r25360 | r25361 | |
| 817 | 817 | MCFG_QUANTUM_TIME(attotime::from_hz(600)) /* 10 CPU slices per frame - enough for the sound CPU to read all commands */ |
| 818 | 818 | |
| 819 | 819 | MCFG_MACHINE_START_OVERRIDE(taitox_state,superman) |
| 820 | ||
| 820 | ||
| 821 | 821 | MCFG_DEVICE_ADD("spritegen", SETA001_SPRITE, 0) |
| 822 | 822 | |
| 823 | 823 | /* video hardware */ |
| r25360 | r25361 | |
|---|---|---|
| 74 | 74 | m_textram(*this, "textram"), |
| 75 | 75 | m_spritebank(*this, "spritebank"), |
| 76 | 76 | m_maincpu(*this, "maincpu"), |
| 77 | m_t5182(*this, "t5182") | |
| 77 | m_t5182(*this, "t5182") { } | |
| 78 | 78 | |
| 79 | 79 | required_shared_ptr<UINT8> m_mainram; |
| 80 | 80 | required_shared_ptr<UINT8> m_spriteram; |
| r25360 | r25361 | |
| 289 | 289 | m_bgtilemap->set_scrollx(0, m_scrollx); |
| 290 | 290 | m_bgtilemap->draw(screen, *m_temprender, m_tempbitmap_clip, 0,0); |
| 291 | 291 | |
| 292 | // m_infotilemap_2->set_scrollx(0, m_scrollx); | |
| 293 | // m_infotilemap_2->draw(screen, *m_temprender, m_tempbitmap_clip, 0,0); | |
| 292 | // m_infotilemap_2->set_scrollx(0, m_scrollx); | |
| 293 | // m_infotilemap_2->draw(screen, *m_temprender, m_tempbitmap_clip, 0,0); | |
| 294 | 294 | |
| 295 | 295 | |
| 296 | 296 | bitmap.fill(get_black_pen(machine()), cliprect); |
| r25360 | r25361 | |
| 619 | 619 | MCFG_SCREEN_REFRESH_RATE(60) |
| 620 | 620 | MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500) /* not accurate */) |
| 621 | 621 | MCFG_SCREEN_SIZE(32*8, 32*8) |
| 622 | // | |
| 622 | // MCFG_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 0*8, 32*8-1) | |
| 623 | 623 | MCFG_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 2*8, 30*8-1) |
| 624 | 624 | |
| 625 | 625 | MCFG_SCREEN_UPDATE_DRIVER(panicr_state, screen_update_panicr) |
| r25360 | r25361 | |
|---|---|---|
| 224 | 224 | READ8_MEMBER(exprraid_state::exprraid_prot_status_r) |
| 225 | 225 | { |
| 226 | 226 | /* |
| 227 | 76543210 | |
| 228 | .......x ? | |
| 229 | ......x. Device data available | |
| 230 | .....x.. CPU data available (cleared by device) | |
| 227 | 76543210 | |
| 228 | .......x ? | |
| 229 | ......x. Device data available | |
| 230 | .....x.. CPU data available (cleared by device) | |
| 231 | 231 | */ |
| 232 | 232 | |
| 233 | 233 | return 0x02; |
| r25360 | r25361 | |
|---|---|---|
| 760 | 760 | { |
| 761 | 761 | UINT32 d = m_ata->read_cs0(space, (UINT32) 0, (UINT32) 0xffff) << 0; |
| 762 | 762 | d |= m_ata->read_cs0(space, (UINT32) 0, (UINT32) 0xffff) << 16; |
| 763 | ||
| 763 | ||
| 764 | 764 | m_p_n_psxram[ m_atapi_xferbase / 4 ] = d; |
| 765 | 765 | m_atapi_xferbase += 4; |
| 766 | 766 | m_atapi_xfersize--; |
| r25360 | r25361 | |
|---|---|---|
| 254 | 254 | |
| 255 | 255 | MCFG_MACHINE_START_OVERRIDE(thunderj_state,thunderj) |
| 256 | 256 | MCFG_MACHINE_RESET_OVERRIDE(thunderj_state,thunderj) |
| 257 | ||
| 257 | ||
| 258 | 258 | MCFG_ATARI_EEPROM_2816_ADD("eeprom") |
| 259 | 259 | |
| 260 | 260 | /* perfect synchronization due to shared RAM */ |
| r25360 | r25361 | |
|---|---|---|
| 374 | 374 | PORT_BIT( 0xffff, IP_ACTIVE_LOW, IPT_UNKNOWN ) |
| 375 | 375 | |
| 376 | 376 | PORT_START("DSW1") /* read by the Z80 through the sound chip */ |
| 377 | PORT_DIPNAME( 0x03, 0x03, DEF_STR( Lives ) ) | |
| 377 | PORT_DIPNAME( 0x03, 0x03, DEF_STR( Lives ) ) PORT_DIPLOCATION("SW1:1,2") | |
| 378 | 378 | PORT_DIPSETTING( 0x02, "1" ) |
| 379 | 379 | PORT_DIPSETTING( 0x01, "2" ) |
| 380 | 380 | PORT_DIPSETTING( 0x03, "3" ) |
| 381 | 381 | PORT_DIPSETTING( 0x00, "5" ) |
| 382 | PORT_DIPNAME( 0x0c, 0x0c, "Bombs" ) | |
| 382 | PORT_DIPNAME( 0x0c, 0x0c, "Bombs" ) PORT_DIPLOCATION("SW1:3,4") | |
| 383 | 383 | PORT_DIPSETTING( 0x08, "1" ) |
| 384 | 384 | PORT_DIPSETTING( 0x04, "2" ) |
| 385 | 385 | PORT_DIPSETTING( 0x0c, "3" ) |
| 386 | 386 | PORT_DIPSETTING( 0x00, "5" ) |
| 387 | PORT_DIPNAME( 0x30, 0x20, DEF_STR( Difficulty ) ) | |
| 387 | PORT_DIPNAME( 0x30, 0x20, DEF_STR( Difficulty ) ) PORT_DIPLOCATION("SW1:5,6") | |
| 388 | 388 | PORT_DIPSETTING( 0x30, DEF_STR( Easy ) ) |
| 389 | 389 | PORT_DIPSETTING( 0x20, DEF_STR( Normal ) ) |
| 390 | 390 | PORT_DIPSETTING( 0x10, DEF_STR( Hard ) ) |
| 391 | 391 | PORT_DIPSETTING( 0x00, DEF_STR( Hardest ) ) |
| 392 | PORT_DIPNAME( 0xc0, 0xc0, DEF_STR( Bonus_Life ) ) | |
| 392 | PORT_DIPNAME( 0xc0, 0xc0, DEF_STR( Bonus_Life ) ) PORT_DIPLOCATION("SW1:7,8") | |
| 393 | 393 | PORT_DIPSETTING( 0x80, "100K, 300K" ) |
| 394 | 394 | PORT_DIPSETTING( 0xc0, "200K, 500K" ) |
| 395 | 395 | PORT_DIPSETTING( 0x40, "500K, 1000K" ) |
| 396 | 396 | PORT_DIPSETTING( 0x00, "1000K, 3000K" ) |
| 397 | 397 | |
| 398 | 398 | PORT_START("DSW2") /* read by the Z80 through the sound chip */ |
| 399 | PORT_DIPNAME( 0x0f, 0x0f, DEF_STR( Coinage ) ) | |
| 399 | PORT_DIPNAME( 0x0f, 0x0f, DEF_STR( Coinage ) ) PORT_DIPLOCATION("SW2:1,2,3,4") | |
| 400 | 400 | PORT_DIPSETTING( 0x0a, DEF_STR( 6C_1C ) ) |
| 401 | 401 | PORT_DIPSETTING( 0x0b, DEF_STR( 5C_1C ) ) |
| 402 | 402 | PORT_DIPSETTING( 0x0c, DEF_STR( 4C_1C ) ) |
| r25360 | r25361 | |
| 413 | 413 | PORT_DIPSETTING( 0x06, DEF_STR( 1C_5C ) ) |
| 414 | 414 | PORT_DIPSETTING( 0x05, DEF_STR( 1C_6C ) ) |
| 415 | 415 | PORT_DIPSETTING( 0x00, DEF_STR( Free_Play ) ) |
| 416 | PORT_DIPNAME( 0x10, 0x10, DEF_STR( Flip_Screen ) ) | |
| 416 | PORT_DIPNAME( 0x10, 0x10, DEF_STR( Flip_Screen ) ) PORT_DIPLOCATION("SW2:5") | |
| 417 | 417 | PORT_DIPSETTING( 0x10, DEF_STR( Off ) ) |
| 418 | 418 | PORT_DIPSETTING( 0x00, DEF_STR( On ) ) |
| 419 | PORT_DIPNAME( 0x20, 0x20, DEF_STR( Allow_Continue ) ) | |
| 419 | PORT_DIPNAME( 0x20, 0x20, DEF_STR( Allow_Continue ) ) PORT_DIPLOCATION("SW2:6") | |
| 420 | 420 | PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) |
| 421 | 421 | PORT_DIPSETTING( 0x20, DEF_STR( On ) ) |
| 422 | PORT_DIPNAME( 0x40, 0x40, DEF_STR( Demo_Sounds ) ) | |
| 422 | PORT_DIPNAME( 0x40, 0x40, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW2:7") | |
| 423 | 423 | PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) |
| 424 | 424 | PORT_DIPSETTING( 0x40, DEF_STR( On ) ) |
| 425 | 425 | PORT_SERVICE_DIPLOC( 0x80, IP_ACTIVE_LOW, "SW2:8" ) |
| r25360 | r25361 | |
|---|---|---|
| 525 | 525 | |
| 526 | 526 | MCFG_S2636_ADD("s2636", s2636_config) |
| 527 | 527 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.10) |
| 528 | ||
| 528 | ||
| 529 | 529 | MCFG_DM9368_ADD("sc_thousand", digit_score_thousand_intf) |
| 530 | 530 | MCFG_DM9368_ADD("sc_hundred", digit_score_hundred_intf) |
| 531 | 531 | MCFG_DM9368_ADD("sc_half", digit_score_half_a_score_intf) |
| r25360 | r25361 | |
|---|---|---|
| 214 | 214 | |
| 215 | 215 | PORT_START("DSW1") |
| 216 | 216 | PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED ) |
| 217 | PORT_DIPNAME( 0x0300, 0x0000, DEF_STR( Coin_B ) ) | |
| 217 | PORT_DIPNAME( 0x0300, 0x0000, DEF_STR( Coin_B ) ) PORT_DIPLOCATION("SW1:!8,!7") | |
| 218 | 218 | PORT_DIPSETTING( 0x0000, DEF_STR( 1C_1C ) ) |
| 219 | 219 | PORT_DIPSETTING( 0x0200, DEF_STR( 1C_2C ) ) |
| 220 | 220 | PORT_DIPSETTING( 0x0100, DEF_STR( 1C_3C ) ) |
| 221 | 221 | PORT_DIPSETTING( 0x0300, DEF_STR( 1C_4C ) ) |
| 222 | PORT_DIPNAME( 0x0c00, 0x0000, DEF_STR( Coin_A ) ) | |
| 222 | PORT_DIPNAME( 0x0c00, 0x0000, DEF_STR( Coin_A ) ) PORT_DIPLOCATION("SW1:!6,!5") | |
| 223 | 223 | PORT_DIPSETTING( 0x0c00, DEF_STR( 4C_1C ) ) |
| 224 | 224 | PORT_DIPSETTING( 0x0400, DEF_STR( 3C_1C ) ) |
| 225 | 225 | PORT_DIPSETTING( 0x0800, DEF_STR( 2C_1C ) ) |
| 226 | 226 | PORT_DIPSETTING( 0x0000, DEF_STR( 1C_1C ) ) |
| 227 | PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Lives ) ) | |
| 227 | PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Lives ) ) PORT_DIPLOCATION("SW1:!4") | |
| 228 | 228 | PORT_DIPSETTING( 0x0000, "2" ) |
| 229 | 229 | PORT_DIPSETTING( 0x1000, "3" ) |
| 230 | PORT_DIPNAME( 0x2000, 0x0000, "Bonus Occurrence" ) | |
| 230 | PORT_DIPNAME( 0x2000, 0x0000, "Bonus Occurrence" ) PORT_DIPLOCATION("SW1:!3") | |
| 231 | 231 | PORT_DIPSETTING( 0x0000, "1st & 2nd only" ) |
| 232 | 232 | PORT_DIPSETTING( 0x2000, "1st & every 2nd" ) |
| 233 | PORT_DIPNAME( 0x4000, 0x0000, DEF_STR( Language ) ) | |
| 233 | PORT_DIPNAME( 0x4000, 0x0000, DEF_STR( Language ) ) PORT_DIPLOCATION("SW1:!2") | |
| 234 | 234 | PORT_DIPSETTING( 0x0000, DEF_STR( English ) ) |
| 235 | 235 | PORT_DIPSETTING( 0x4000, DEF_STR( Japanese ) ) |
| 236 | PORT_DIPNAME( 0x8000, 0x0000, DEF_STR( Flip_Screen ) ) | |
| 236 | PORT_DIPNAME( 0x8000, 0x0000, DEF_STR( Flip_Screen ) ) PORT_DIPLOCATION("SW1:!1") | |
| 237 | 237 | PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) |
| 238 | 238 | PORT_DIPSETTING( 0x8000, DEF_STR( On ) ) |
| 239 | 239 | |
| 240 | 240 | PORT_START("DSW2") |
| 241 | 241 | PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED ) |
| 242 | 242 | PORT_SERVICE_DIPLOC( 0x0100, IP_ACTIVE_HIGH, "SW2:!8" ) |
| 243 | PORT_DIPNAME( 0x0200, 0x0000, DEF_STR( Allow_Continue ) ) | |
| 243 | PORT_DIPNAME( 0x0200, 0x0000, DEF_STR( Allow_Continue ) ) PORT_DIPLOCATION("SW2:!7") | |
| 244 | 244 | PORT_DIPSETTING( 0x0200, DEF_STR( No ) ) |
| 245 | 245 | PORT_DIPSETTING( 0x0000, DEF_STR( Yes ) ) |
| 246 | PORT_DIPNAME( 0x0c00, 0x0000, DEF_STR( Bonus_Life ) ) | |
| 246 | PORT_DIPNAME( 0x0c00, 0x0000, DEF_STR( Bonus_Life ) ) PORT_DIPLOCATION("SW2:!6,!5") | |
| 247 | 247 | PORT_DIPSETTING( 0x0000, "20k 50k" ) |
| 248 | 248 | PORT_DIPSETTING( 0x0800, "40k 100k" ) |
| 249 | 249 | PORT_DIPSETTING( 0x0400, "60k 150k" ) |
| 250 | 250 | PORT_DIPSETTING( 0x0c00, DEF_STR( None ) ) |
| 251 | PORT_DIPNAME( 0x3000, 0x0000, "Game Mode" ) | |
| 251 | PORT_DIPNAME( 0x3000, 0x0000, "Game Mode" ) PORT_DIPLOCATION("SW2:!4,!3") | |
| 252 | 252 | PORT_DIPSETTING( 0x2000, "Demo Sounds Off" ) |
| 253 | 253 | PORT_DIPSETTING( 0x0000, "Demo Sounds On" ) |
| 254 | 254 | PORT_DIPSETTING( 0x3000, "Freeze" ) |
| 255 | 255 | PORT_DIPSETTING( 0x1000, "Infinite Lives (Cheat)") |
| 256 | PORT_DIPNAME( 0xc000, 0x0000, DEF_STR( Difficulty ) ) | |
| 256 | PORT_DIPNAME( 0xc000, 0x0000, DEF_STR( Difficulty ) ) PORT_DIPLOCATION("SW2:!2,!1") | |
| 257 | 257 | PORT_DIPSETTING( 0x8000, DEF_STR( Easy ) ) |
| 258 | 258 | PORT_DIPSETTING( 0x0000, DEF_STR( Normal ) ) |
| 259 | 259 | PORT_DIPSETTING( 0x4000, DEF_STR( Hard ) ) |
| r25360 | r25361 | |
| 302 | 302 | |
| 303 | 303 | PORT_START("DSW1") |
| 304 | 304 | PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED ) |
| 305 | PORT_DIPNAME( 0x0100, 0x0000, DEF_STR( Joystick ) ) | |
| 305 | PORT_DIPNAME( 0x0100, 0x0000, DEF_STR( Joystick ) ) PORT_DIPLOCATION("SW1:!8") | |
| 306 | 306 | PORT_DIPSETTING( 0x0000, "Rotary Joystick" ) |
| 307 | 307 | PORT_DIPSETTING( 0x0100, "Standard Joystick" ) |
| 308 | PORT_DIPNAME( 0x0200, 0x0000, DEF_STR( Unknown ) ) | |
| 308 | PORT_DIPNAME( 0x0200, 0x0000, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SW1:!7") | |
| 309 | 309 | PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) |
| 310 | 310 | PORT_DIPSETTING( 0x0200, DEF_STR( On ) ) |
| 311 | PORT_DIPNAME( 0x0c00, 0x0000, DEF_STR( Lives ) ) | |
| 311 | PORT_DIPNAME( 0x0c00, 0x0000, DEF_STR( Lives ) ) PORT_DIPLOCATION("SW1:!6,!5") | |
| 312 | 312 | PORT_DIPSETTING( 0x0800, "2" ) |
| 313 | 313 | PORT_DIPSETTING( 0x0000, "3" ) |
| 314 | 314 | PORT_DIPSETTING( 0x0400, "4" ) |
| 315 | 315 | PORT_DIPSETTING( 0x0c00, "5" ) |
| 316 | PORT_DIPNAME( 0x3000, 0x0000, "Coin A & B" ) | |
| 316 | PORT_DIPNAME( 0x3000, 0x0000, "Coin A & B" ) PORT_DIPLOCATION("SW1:!4,!3") | |
| 317 | 317 | PORT_DIPSETTING( 0x2000, DEF_STR( 2C_1C ) ) |
| 318 | 318 | PORT_DIPSETTING( 0x0000, DEF_STR( 1C_1C ) ) |
| 319 | 319 | PORT_DIPSETTING( 0x1000, DEF_STR( 1C_2C ) ) |
| 320 | 320 | PORT_DIPSETTING( 0x3000, DEF_STR( Free_Play ) ) |
| 321 | PORT_DIPNAME( 0x4000, 0x0000, "Bonus Occurrence" ) | |
| 321 | PORT_DIPNAME( 0x4000, 0x0000, "Bonus Occurrence" ) PORT_DIPLOCATION("SW1:!2") | |
| 322 | 322 | PORT_DIPSETTING( 0x0000, "1st & 2nd only" ) |
| 323 | 323 | PORT_DIPSETTING( 0x4000, "1st & every 2nd" ) |
| 324 | PORT_DIPNAME( 0x8000, 0x0000, DEF_STR( Flip_Screen ) ) | |
| 324 | PORT_DIPNAME( 0x8000, 0x0000, DEF_STR( Flip_Screen ) ) PORT_DIPLOCATION("SW1:!1") | |
| 325 | 325 | PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) |
| 326 | 326 | PORT_DIPSETTING( 0x8000, DEF_STR( On ) ) |
| 327 | 327 | |
| 328 | 328 | PORT_START("DSW2") |
| 329 | 329 | PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED ) |
| 330 | 330 | PORT_SERVICE_DIPLOC( 0x0100, IP_ACTIVE_HIGH, "SW2:!8" ) |
| 331 | PORT_DIPNAME( 0x0200, 0x0000, DEF_STR( Allow_Continue ) ) | |
| 331 | PORT_DIPNAME( 0x0200, 0x0000, DEF_STR( Allow_Continue ) ) PORT_DIPLOCATION("SW2:!7") | |
| 332 | 332 | PORT_DIPSETTING( 0x0200, DEF_STR( No ) ) |
| 333 | 333 | PORT_DIPSETTING( 0x0000, DEF_STR( Yes ) ) |
| 334 | PORT_DIPNAME( 0x0c00, 0x0000, DEF_STR( Bonus_Life ) ) | |
| 334 | PORT_DIPNAME( 0x0c00, 0x0000, DEF_STR( Bonus_Life ) ) PORT_DIPLOCATION("SW2:!6,!5") | |
| 335 | 335 | PORT_DIPSETTING( 0x0000, "50k 200k" ) |
| 336 | 336 | PORT_DIPSETTING( 0x0800, "70k 270k" ) |
| 337 | 337 | PORT_DIPSETTING( 0x0400, "90k 350k" ) |
| 338 | 338 | PORT_DIPSETTING( 0x0c00, DEF_STR( None ) ) |
| 339 | PORT_DIPNAME( 0x3000, 0x0000, "Game Mode" ) | |
| 339 | PORT_DIPNAME( 0x3000, 0x0000, "Game Mode" ) PORT_DIPLOCATION("SW2:!4,!3") | |
| 340 | 340 | PORT_DIPSETTING( 0x2000, "Demo Sounds Off" ) |
| 341 | 341 | PORT_DIPSETTING( 0x0000, "Demo Sounds On" ) |
| 342 | 342 | PORT_DIPSETTING( 0x3000, "Freeze" ) |
| 343 | 343 | PORT_DIPSETTING( 0x1000, "Infinite Lives (Cheat)") |
| 344 | PORT_DIPNAME( 0xc000, 0x0000, DEF_STR( Difficulty ) ) | |
| 344 | PORT_DIPNAME( 0xc000, 0x0000, DEF_STR( Difficulty ) ) PORT_DIPLOCATION("SW2:!2,!1") | |
| 345 | 345 | PORT_DIPSETTING( 0x8000, DEF_STR( Easy ) ) |
| 346 | 346 | PORT_DIPSETTING( 0x0000, DEF_STR( Normal ) ) |
| 347 | 347 | PORT_DIPSETTING( 0x4000, DEF_STR( Hard ) ) |
| r25360 | r25361 | |
| 388 | 388 | |
| 389 | 389 | PORT_START("DSW1") /* Dip switches (Active high) */ |
| 390 | 390 | PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED ) |
| 391 | PORT_DIPNAME( 0x0300, 0x0000, DEF_STR( Lives ) ) | |
| 391 | PORT_DIPNAME( 0x0300, 0x0000, DEF_STR( Lives ) ) PORT_DIPLOCATION("SW1:!8,7") | |
| 392 | 392 | PORT_DIPSETTING( 0x0200, "1" ) |
| 393 | 393 | PORT_DIPSETTING( 0x0000, "2" ) |
| 394 | 394 | PORT_DIPSETTING( 0x0100, "3" ) |
| 395 | 395 | PORT_DIPSETTING( 0x0300, "4" ) |
| 396 | PORT_DIPNAME( 0x0c00, 0x0000, "Coin A & B" ) | |
| 396 | PORT_DIPNAME( 0x0c00, 0x0000, "Coin A & B" ) PORT_DIPLOCATION("SW1:!6,5") | |
| 397 | 397 | PORT_DIPSETTING( 0x0800, DEF_STR( 2C_1C ) ) |
| 398 | 398 | PORT_DIPSETTING( 0x0000, DEF_STR( 1C_1C ) ) |
| 399 | 399 | PORT_DIPSETTING( 0x0400, DEF_STR( 1C_2C ) ) |
| 400 | 400 | PORT_DIPSETTING( 0x0c00, DEF_STR( Free_Play ) ) |
| 401 | PORT_DIPNAME( 0x1000, 0x0000, DEF_STR( Unknown ) ) | |
| 401 | PORT_DIPNAME( 0x1000, 0x0000, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SW1:!4") | |
| 402 | 402 | PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) |
| 403 | 403 | PORT_DIPSETTING( 0x1000, DEF_STR( On ) ) |
| 404 | PORT_DIPNAME( 0x2000, 0x0000, "Bonus Occurrence" ) | |
| 404 | PORT_DIPNAME( 0x2000, 0x0000, "Bonus Occurrence" ) PORT_DIPLOCATION("SW1:!3") | |
| 405 | 405 | PORT_DIPSETTING( 0x0000, "1st & 2nd only" ) |
| 406 | 406 | PORT_DIPSETTING( 0x2000, "1st & every 2nd" ) |
| 407 | PORT_DIPNAME( 0x4000, 0x0000, DEF_STR( Unknown ) ) | |
| 407 | PORT_DIPNAME( 0x4000, 0x0000, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SW1:!2") | |
| 408 | 408 | PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) |
| 409 | 409 | PORT_DIPSETTING( 0x4000, DEF_STR( On ) ) |
| 410 | PORT_DIPNAME( 0x8000, 0x0000, DEF_STR( Flip_Screen ) ) | |
| 410 | PORT_DIPNAME( 0x8000, 0x0000, DEF_STR( Flip_Screen ) ) PORT_DIPLOCATION("SW1:!1") | |
| 411 | 411 | PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) |
| 412 | 412 | PORT_DIPSETTING( 0x8000, DEF_STR( On ) ) |
| 413 | 413 | |
| 414 | 414 | PORT_START("DSW2") /* Dip switches (Active high) */ |
| 415 | 415 | PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED ) |
| 416 | 416 | PORT_SERVICE_DIPLOC( 0x0100, IP_ACTIVE_HIGH, "SW2:!8" ) |
| 417 | PORT_DIPNAME( 0x0200, 0x0000, DEF_STR( Allow_Continue ) ) | |
| 417 | PORT_DIPNAME( 0x0200, 0x0000, DEF_STR( Allow_Continue ) ) PORT_DIPLOCATION("SW2:!7") | |
| 418 | 418 | PORT_DIPSETTING( 0x0200, DEF_STR( No ) ) |
| 419 | 419 | PORT_DIPSETTING( 0x0000, DEF_STR( Yes ) ) |
| 420 | PORT_DIPNAME( 0x0c00, 0x0000, DEF_STR( Bonus_Life ) ) | |
| 420 | PORT_DIPNAME( 0x0c00, 0x0000, DEF_STR( Bonus_Life ) ) PORT_DIPLOCATION("SW2:!6,!5") | |
| 421 | 421 | PORT_DIPSETTING( 0x0000, "200k 400k" ) |
| 422 | 422 | PORT_DIPSETTING( 0x0800, "400k 600k" ) |
| 423 | 423 | PORT_DIPSETTING( 0x0400, "600k 800k" ) |
| 424 | 424 | PORT_DIPSETTING( 0x0c00, DEF_STR( None ) ) |
| 425 | PORT_DIPNAME( 0x3000, 0x0000, "Game Mode" ) | |
| 425 | PORT_DIPNAME( 0x3000, 0x0000, "Game Mode" ) PORT_DIPLOCATION("SW2:!4,!3") | |
| 426 | 426 | PORT_DIPSETTING( 0x2000, "Demo Sounds Off" ) |
| 427 | 427 | PORT_DIPSETTING( 0x0000, "Demo Sounds On" ) |
| 428 | 428 | PORT_DIPSETTING( 0x3000, "Freeze" ) |
| 429 | 429 | PORT_DIPSETTING( 0x1000, "Infinite Lives (Cheat)") |
| 430 | PORT_DIPNAME( 0xc000, 0x0000, DEF_STR( Difficulty ) ) | |
| 430 | PORT_DIPNAME( 0xc000, 0x0000, DEF_STR( Difficulty ) ) PORT_DIPLOCATION("SW2:!2,!1") | |
| 431 | 431 | PORT_DIPSETTING( 0x8000, DEF_STR( Easy ) ) |
| 432 | 432 | PORT_DIPSETTING( 0x0000, DEF_STR( Normal ) ) |
| 433 | 433 | PORT_DIPSETTING( 0x4000, DEF_STR( Hard ) ) |
| r25360 | r25361 | |
| 445 | 445 | PORT_INCLUDE( streetsm ) |
| 446 | 446 | |
| 447 | 447 | PORT_MODIFY("DSW1") |
| 448 | PORT_DIPNAME( 0x0c00, 0x0000, DEF_STR( Coinage ) ) | |
| 448 | PORT_DIPNAME( 0x0c00, 0x0000, DEF_STR( Coinage ) ) PORT_DIPLOCATION("SW1:!6,5") | |
| 449 | 449 | PORT_DIPSETTING( 0x0c00, "A 4/1 B 1/4" ) |
| 450 | 450 | PORT_DIPSETTING( 0x0400, "A 3/1 B 1/3" ) |
| 451 | 451 | PORT_DIPSETTING( 0x0800, "A 2/1 B 1/2" ) |
| r25360 | r25361 | |
| 486 | 486 | |
| 487 | 487 | PORT_START("DSW1") /* Dip switches (Active high) */ |
| 488 | 488 | PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED ) |
| 489 | PORT_DIPNAME( 0x0300, 0x0000, DEF_STR( Lives ) ) | |
| 489 | PORT_DIPNAME( 0x0300, 0x0000, DEF_STR( Lives ) ) PORT_DIPLOCATION("SW1:!8,!7") | |
| 490 | 490 | PORT_DIPSETTING( 0x0200, "2" ) |
| 491 | 491 | PORT_DIPSETTING( 0x0000, "3" ) |
| 492 | 492 | PORT_DIPSETTING( 0x0100, "4" ) |
| 493 | 493 | PORT_DIPSETTING( 0x0300, "5" ) |
| 494 | PORT_DIPNAME( 0x0c00, 0x0000, "Coin A & B" ) | |
| 494 | PORT_DIPNAME( 0x0c00, 0x0000, "Coin A & B" ) PORT_DIPLOCATION("SW1:!6,!5") | |
| 495 | 495 | PORT_DIPSETTING( 0x0800, "First 2 Coins/1 Credit then 1/1" ) |
| 496 | 496 | PORT_DIPSETTING( 0x0000, DEF_STR( 1C_1C ) ) |
| 497 | 497 | PORT_DIPSETTING( 0x0400, "First 1 Coin/2 Credits then 1/1" ) |
| 498 | 498 | PORT_DIPSETTING( 0x0c00, DEF_STR( Free_Play ) ) |
| 499 | PORT_DIPNAME( 0x1000, 0x0000, DEF_STR( Unknown ) ) | |
| 499 | PORT_DIPNAME( 0x1000, 0x0000, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SW1:!4") | |
| 500 | 500 | PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) |
| 501 | 501 | PORT_DIPSETTING( 0x1000, DEF_STR( On ) ) |
| 502 | PORT_DIPNAME( 0x2000, 0x0000, "Bonus Occurrence" ) | |
| 502 | PORT_DIPNAME( 0x2000, 0x0000, "Bonus Occurrence" ) PORT_DIPLOCATION("SW1:!3") | |
| 503 | 503 | PORT_DIPSETTING( 0x0000, "1st & 2nd only" ) |
| 504 | 504 | PORT_DIPSETTING( 0x2000, "1st & every 2nd" ) |
| 505 | PORT_DIPNAME( 0x4000, 0x0000, "Blood" ) | |
| 505 | PORT_DIPNAME( 0x4000, 0x0000, "Blood" ) PORT_DIPLOCATION("SW1:!2") | |
| 506 | 506 | PORT_DIPSETTING( 0x4000, DEF_STR( Off ) ) |
| 507 | 507 | PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) |
| 508 | PORT_DIPNAME( 0x8000, 0x0000, DEF_STR( Flip_Screen ) ) | |
| 508 | PORT_DIPNAME( 0x8000, 0x0000, DEF_STR( Flip_Screen ) ) PORT_DIPLOCATION("SW1:!1") | |
| 509 | 509 | PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) |
| 510 | 510 | PORT_DIPSETTING( 0x8000, DEF_STR( On ) ) |
| 511 | 511 | |
| 512 | 512 | PORT_START("DSW2") /* Dip switches (Active high) */ |
| 513 | 513 | PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED ) |
| 514 | 514 | PORT_SERVICE_DIPLOC( 0x0100, IP_ACTIVE_HIGH, "SW2:!8" ) |
| 515 | PORT_DIPNAME( 0x0200, 0x0000, DEF_STR( Allow_Continue ) ) | |
| 515 | PORT_DIPNAME( 0x0200, 0x0000, DEF_STR( Allow_Continue ) ) PORT_DIPLOCATION("SW2:!7") | |
| 516 | 516 | PORT_DIPSETTING( 0x0200, DEF_STR( No ) ) |
| 517 | 517 | PORT_DIPSETTING( 0x0000, DEF_STR( Yes ) ) |
| 518 | PORT_DIPNAME( 0x0c00, 0x0000, DEF_STR( Bonus_Life ) ) | |
| 518 | PORT_DIPNAME( 0x0c00, 0x0000, DEF_STR( Bonus_Life ) ) PORT_DIPLOCATION("SW2:!6,!5") | |
| 519 | 519 | PORT_DIPSETTING( 0x0000, "20k 50k" ) |
| 520 | 520 | PORT_DIPSETTING( 0x0800, "40k 100k" ) |
| 521 | 521 | PORT_DIPSETTING( 0x0400, "60k 150k" ) |
| 522 | 522 | PORT_DIPSETTING( 0x0c00, DEF_STR( None ) ) |
| 523 | PORT_DIPNAME( 0x3000, 0x0000, "Game Mode" ) | |
| 523 | PORT_DIPNAME( 0x3000, 0x0000, "Game Mode" ) PORT_DIPLOCATION("SW2:!4,!3") | |
| 524 | 524 | PORT_DIPSETTING( 0x2000, "Demo Sounds Off" ) |
| 525 | 525 | PORT_DIPSETTING( 0x0000, "Demo Sounds On" ) |
| 526 | 526 | PORT_DIPSETTING( 0x3000, "Freeze" ) |
| 527 | 527 | PORT_DIPSETTING( 0x1000, "Infinite Lives (Cheat)") |
| 528 | PORT_DIPNAME( 0xc000, 0x8000, DEF_STR( Difficulty ) ) | |
| 528 | PORT_DIPNAME( 0xc000, 0x8000, DEF_STR( Difficulty ) ) PORT_DIPLOCATION("SW2:!2,!1") | |
| 529 | 529 | PORT_DIPSETTING( 0x0000, DEF_STR( Easy ) ) |
| 530 | 530 | PORT_DIPSETTING( 0x8000, DEF_STR( Normal ) ) |
| 531 | 531 | PORT_DIPSETTING( 0x4000, DEF_STR( Hard ) ) |
| r25360 | r25361 | |
|---|---|---|
| 1406 | 1406 | MCFG_DEVICE_VBLANK_INT_DRIVER("screen", atarigen_state, video_int_gen) |
| 1407 | 1407 | |
| 1408 | 1408 | MCFG_MACHINE_RESET_OVERRIDE(atarigx2_state,atarigx2) |
| 1409 | ||
| 1409 | ||
| 1410 | 1410 | MCFG_ATARI_EEPROM_2816_ADD("eeprom") |
| 1411 | 1411 | |
| 1412 | 1412 | /* video hardware */ |
| r25360 | r25361 | |
|---|---|---|
| 4 | 4 | seems to be Kupidon in the ROMs? |
| 5 | 5 | |
| 6 | 6 | these act a bit like the pluto5 ones but with a video system, possibly a variant on that? |
| 7 | ||
| 7 | ||
| 8 | 8 | needs 68340 peripherals (irq controller + timer at least) to be fleshed out. |
| 9 | 9 | |
| 10 | 10 | video might be vga-like? |
| r25360 | r25361 | |
| 46 | 46 | |
| 47 | 47 | UINT32 cupidon_state::screen_update_cupidon(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) |
| 48 | 48 | { |
| 49 | ||
| 50 | 49 | int count = 0; |
| 51 | 50 | |
| 52 | 51 | for (int ytile=0;ytile<16;ytile++) |
| 53 | 52 | { |
| 54 | ||
| 55 | ||
| 56 | 53 | for (int xtile=0;xtile<32;xtile++) |
| 57 | 54 | { |
| 58 | ||
| 59 | 55 | for (int y=0;y<16;y++) |
| 60 | 56 | { |
| 61 | 57 | UINT16* destline = &bitmap.pix16(ytile*16 + y); |
| r25360 | r25361 | |
| 79 | 75 | |
| 80 | 76 | // could be pumped through the get_cs function (if they use the memory protection features we might have to) but that's slow... |
| 81 | 77 | static ADDRESS_MAP_START( cupidon_map, AS_PROGRAM, 32, cupidon_state ) |
| 82 | AM_RANGE(0x0000000, 0x07fffff) AM_ROM AM_MIRROR(0x1000000) | |
| 78 | AM_RANGE(0x0000000, 0x07fffff) AM_ROM AM_MIRROR(0x1000000) | |
| 83 | 79 | |
| 84 | 80 | AM_RANGE(0x1000000, 0x100ffff) AM_RAM |
| 85 | 81 | AM_RANGE(0x1800000, 0x1800003) AM_READ(cupidon_return_ffffffff) |
| 86 | 82 | AM_RANGE(0x2000074, 0x2000077) AM_RAM // port |
| 87 | 83 | |
| 88 | // | |
| 84 | // AM_RANGE(0x2000040, 0x200004f) AM_RAM | |
| 89 | 85 | |
| 90 | 86 | |
| 91 | 87 | // might just be 4mb of VRAM |
| 92 | 88 | AM_RANGE(0x3000000, 0x33bffff) AM_RAM |
| 93 | 89 | AM_RANGE(0x33c0000, 0x33fffff) AM_RAM AM_SHARE("gfxram") // seems to upload graphics to here, tiles etc. if you skip the loop after the romtest in funnyfm |
| 94 | // AM_RANGE(0x3400000, 0x3400fff) AM_RAM | |
| 95 | // AM_RANGE(0x3F80000, 0x3F80003) AM_RAM | |
| 90 | // AM_RANGE(0x3400000, 0x3400fff) AM_RAM | |
| 91 | // AM_RANGE(0x3F80000, 0x3F80003) AM_RAM | |
| 96 | 92 | AM_RANGE(0x3FF0400, 0x3FF0403) AM_RAM // register? gangrose likes to read this? |
| 97 | 93 | ADDRESS_MAP_END |
| 98 | 94 |
| r25360 | r25361 | |
|---|---|---|
| 532 | 532 | |
| 533 | 533 | static const msm5205_interface msm5205_config = |
| 534 | 534 | { |
| 535 | DEVCB_DRIVER_LINE_MEMBER(stfight_state, stfight_adpcm_int), // Interrupt function | |
| 536 | MSM5205_S48_4B // 8KHz, 4-bit | |
| 535 | DEVCB_DRIVER_LINE_MEMBER(stfight_state, stfight_adpcm_int), // Interrupt function | |
| 536 | MSM5205_S48_4B // 8KHz, 4-bit | |
| 537 | 537 | }; |
| 538 | 538 | |
| 539 | 539 | static MACHINE_CONFIG_START( stfight, stfight_state ) |
| r25360 | r25361 | |
|---|---|---|
| 1960 | 1960 | ROM_REGION(0x200000, "gfx1" , ROMREGION_ERASE00 ) /* Sprites */ |
| 1961 | 1961 | ROM_LOAD16_BYTE ("cq80-obj-0l-c166.ic8", 0x000000, 0x80000, CRC(9bff223b) SHA1(acf22731d91d61aefc3373f78006fd310bb89edf) ) |
| 1962 | 1962 | ROM_LOAD16_BYTE ("cq80-obj-0m-24f4.ic30", 0x000001, 0x80000, CRC(ee71f643) SHA1(7a2042c6fad8f1b7e0a3ad077d054dc163a22230) ) |
| 1963 | ROM_LOAD | |
| 1963 | ROM_LOAD ("cq80-obj-0h-990d.ic32", 0x180000, 0x80000, CRC(4d3a78e0) SHA1(b19fb66e6082a68dc8600b8882ba50a3afce27c3) ) | |
| 1964 | 1964 | |
| 1965 | 1965 | ROM_REGION(0x400000, "gfx2" , ROMREGION_ERASE00 ) /* Tiles */ |
| 1966 | 1966 | ROM_LOAD32_BYTE("cq80-scr0-5ba4.ic7", 0x000000, 0x080000, CRC(044dc38b) SHA1(0bb715c9ae8298c6852c6309d69f769e87ab2fdc) ) |
| r25360 | r25361 | |
|---|---|---|
| 824 | 824 | MCFG_CPU_PERIODIC_INT_DRIVER(atarigen_state, scanline_int_gen, 250) |
| 825 | 825 | |
| 826 | 826 | MCFG_MACHINE_RESET_OVERRIDE(atarigt_state,atarigt) |
| 827 | ||
| 827 | ||
| 828 | 828 | MCFG_ATARI_EEPROM_2816_ADD("eeprom") |
| 829 | 829 | |
| 830 | 830 | /* video hardware */ |
| r25360 | r25361 | |
|---|---|---|
| 265 | 265 | MCFG_CPU_PROGRAM_MAP(main_map) |
| 266 | 266 | |
| 267 | 267 | MCFG_MACHINE_RESET_OVERRIDE(relief_state,relief) |
| 268 | ||
| 268 | ||
| 269 | 269 | MCFG_ATARI_EEPROM_2816_ADD("eeprom") |
| 270 | 270 | |
| 271 | 271 | /* video hardware */ |
| r25360 | r25361 | |
|---|---|---|
| 1 | 1 | /* |
| 2 | 2 | |
| 3 | 3 | Double Wings |
| 4 | Mitchell 1993 | |
| 4 | Mitchell 1993 | |
| 5 | 5 | |
| 6 | 6 | This game runs on Data East hardware. |
| 7 | 7 | |
| r25360 | r25361 | |
| 302 | 302 | PORT_DIPSETTING( 0x0200, "1" ) |
| 303 | 303 | PORT_DIPSETTING( 0x0100, "2" ) |
| 304 | 304 | PORT_DIPSETTING( 0x0300, "3" ) |
| 305 | PORT_DIPSETTING( 0x0000, "5" ) | |
| 305 | PORT_DIPSETTING( 0x0000, "5" ) | |
| 306 | 306 | PORT_DIPNAME( 0x0c00, 0x0c00, DEF_STR( Difficulty ) ) PORT_DIPLOCATION("SW2:3,4") |
| 307 | 307 | PORT_DIPSETTING( 0x0800, DEF_STR( Easy ) ) |
| 308 | 308 | PORT_DIPSETTING( 0x0c00, DEF_STR( Normal ) ) |
| r25360 | r25361 | |
|---|---|---|
| 162 | 162 | MCFG_DEVICE_VBLANK_INT_DRIVER("screen", atarigen_state, video_int_gen) |
| 163 | 163 | |
| 164 | 164 | MCFG_MACHINE_RESET_OVERRIDE(klax_state,klax) |
| 165 | ||
| 165 | ||
| 166 | 166 | MCFG_ATARI_EEPROM_2816_ADD("eeprom") |
| 167 | 167 | |
| 168 | 168 | /* video hardware */ |
| r25360 | r25361 | |
|---|---|---|
| 494 | 494 | |
| 495 | 495 | /* sound hardware */ |
| 496 | 496 | MCFG_SEIBU_SOUND_ADD("seibu_sound") |
| 497 | ||
| 497 | ||
| 498 | 498 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 499 | 499 | |
| 500 | 500 | MCFG_YM2151_ADD("ymsnd", XTAL_3_579545MHz) /* verified on pcb */ |
| r25360 | r25361 | |
|---|---|---|
| 338 | 338 | MCFG_DEVICE_VBLANK_INT_DRIVER("screen", atarigen_state, video_int_gen) |
| 339 | 339 | |
| 340 | 340 | MCFG_MACHINE_RESET_OVERRIDE(rampart_state,rampart) |
| 341 | ||
| 341 | ||
| 342 | 342 | MCFG_ATARI_EEPROM_2816_ADD("eeprom") |
| 343 | 343 | |
| 344 | 344 | MCFG_WATCHDOG_VBLANK_INIT(8) |
| r25360 | r25361 | |
|---|---|---|
| 182 | 182 | int Scorpion1_GetSwitchState(int strobe, int data); |
| 183 | 183 | int sc1_find_project_string( ); |
| 184 | 184 | required_device<cpu_device> m_maincpu; |
| 185 | optional_device<upd7759_device> m_upd7759; | |
| 185 | optional_device<upd7759_device> m_upd7759; | |
| 186 | 186 | }; |
| 187 | 187 | |
| 188 | 188 | #define VFD_RESET 0x20 |
| r25360 | r25361 | |
| 1092 | 1092 | MCFG_CPU_PROGRAM_MAP(sc1_adder2) // setup read and write memorymap |
| 1093 | 1093 | |
| 1094 | 1094 | MCFG_DEFAULT_LAYOUT(layout_sc1_vid) |
| 1095 | ||
| 1095 | ||
| 1096 | 1096 | MCFG_BFM_ADDER2_ADD("adder2") |
| 1097 | 1097 | MACHINE_CONFIG_END |
| 1098 | 1098 |
| r25360 | r25361 | |
|---|---|---|
| 404 | 404 | PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNUSED ) |
| 405 | 405 | |
| 406 | 406 | PORT_START("DSW1") /* provided by the MCU - $200386.b <- $400200 */ |
| 407 | PORT_DIPNAME( 0x0100, 0x0100, "Test Mode" ) | |
| 407 | PORT_DIPNAME( 0x0100, 0x0100, "Test Mode" ) PORT_DIPLOCATION("DSW:1") | |
| 408 | 408 | PORT_DIPSETTING( 0x0100, DEF_STR( Off ) ) |
| 409 | 409 | PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) |
| 410 | PORT_DIPNAME( 0x0200, 0x0200, DEF_STR( Flip_Screen ) ) | |
| 410 | PORT_DIPNAME( 0x0200, 0x0200, DEF_STR( Flip_Screen ) ) PORT_DIPLOCATION("DSW:2") | |
| 411 | 411 | PORT_DIPSETTING( 0x0200, DEF_STR( Off ) ) |
| 412 | 412 | PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) |
| 413 | PORT_DIPNAME( 0x0400, 0x0400, DEF_STR( Demo_Sounds ) ) | |
| 413 | PORT_DIPNAME( 0x0400, 0x0400, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("DSW:3") | |
| 414 | 414 | PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) |
| 415 | 415 | PORT_DIPSETTING( 0x0400, DEF_STR( On ) ) |
| 416 | 416 | PORT_DIPUNUSED_DIPLOC( 0x0800, IP_ACTIVE_LOW, "DSW:4" ) /* Listed as "Unused" */ |
| 417 | 417 | PORT_DIPUNUSED_DIPLOC( 0x1000, IP_ACTIVE_LOW, "DSW:5" ) /* Listed as "Unused" */ |
| 418 | 418 | PORT_DIPUNUSED_DIPLOC( 0x2000, IP_ACTIVE_LOW, "DSW:6" ) /* Listed as "Unused" */ |
| 419 | 419 | PORT_DIPUNUSED_DIPLOC( 0x4000, IP_ACTIVE_LOW, "DSW:7" ) /* Listed as "Unused" */ |
| 420 | PORT_DIPNAME( 0x8000, 0x8000, DEF_STR( Unknown ) ) | |
| 420 | PORT_DIPNAME( 0x8000, 0x8000, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DSW:8") // unused ? | |
| 421 | 421 | PORT_DIPSETTING( 0x8000, DEF_STR( Off ) ) |
| 422 | 422 | PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) |
| 423 | 423 | INPUT_PORTS_END |
| r25360 | r25361 | |
|---|---|---|
| 533 | 533 | MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) |
| 534 | 534 | MCFG_SCREEN_SIZE(0x400, 0x100) |
| 535 | 535 | MCFG_SCREEN_VISIBLE_AREA(0, 0x280-1, 0, 0xf0-1) |
| 536 | ||
| 536 | MCFG_SCREEN_UPDATE_DEVICE("tms", tms34010_device, tms340x0_ind16) | |
| 537 | 537 | |
| 538 | 538 | |
| 539 | 539 | // MCFG_GFXDECODE( skimaxx ) |
| r25360 | r25361 | |
|---|---|---|
| 3683 | 3683 | |
| 3684 | 3684 | /* sound hardware */ |
| 3685 | 3685 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 3686 | ||
| 3686 | ||
| 3687 | 3687 | MCFG_NMK004_ADD("nmk004") |
| 3688 | 3688 | |
| 3689 | 3689 | MCFG_SOUND_ADD("ymsnd", YM2203, 1500000) |
| r25360 | r25361 | |
| 3757 | 3757 | |
| 3758 | 3758 | /* sound hardware */ |
| 3759 | 3759 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 3760 | ||
| 3760 | ||
| 3761 | 3761 | MCFG_NMK004_ADD("nmk004") |
| 3762 | 3762 | |
| 3763 | 3763 | MCFG_SOUND_ADD("ymsnd", YM2203, BIOSHIP_CRYSTAL2 / 8) /* 1.5 Mhz (verified) */ |
| r25360 | r25361 | |
| 3799 | 3799 | |
| 3800 | 3800 | /* sound hardware */ |
| 3801 | 3801 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 3802 | ||
| 3802 | ||
| 3803 | 3803 | MCFG_NMK004_ADD("nmk004") |
| 3804 | 3804 | |
| 3805 | 3805 | MCFG_SOUND_ADD("ymsnd", YM2203, XTAL_12MHz/8) /* verified on pcb */ |
| r25360 | r25361 | |
| 3844 | 3844 | |
| 3845 | 3845 | /* sound hardware */ |
| 3846 | 3846 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 3847 | ||
| 3847 | ||
| 3848 | 3848 | MCFG_NMK004_ADD("nmk004") |
| 3849 | 3849 | |
| 3850 | 3850 | MCFG_OKIM6295_ADD("oki1", 16000000/4, OKIM6295_PIN7_LOW) |
| r25360 | r25361 | |
| 3875 | 3875 | |
| 3876 | 3876 | /* sound hardware */ |
| 3877 | 3877 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 3878 | ||
| 3878 | ||
| 3879 | 3879 | MCFG_NMK004_ADD("nmk004") |
| 3880 | 3880 | |
| 3881 | 3881 | MCFG_SOUND_ADD("ymsnd", YM2203, 1500000) /* (verified on pcb) */ |
| r25360 | r25361 | |
| 3949 | 3949 | |
| 3950 | 3950 | /* sound hardware */ |
| 3951 | 3951 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 3952 | ||
| 3952 | ||
| 3953 | 3953 | MCFG_NMK004_ADD("nmk004") |
| 3954 | 3954 | |
| 3955 | 3955 | MCFG_SOUND_ADD("ymsnd", YM2203, XTAL_12MHz/8) /* verified on pcb */ |
| r25360 | r25361 | |
| 4024 | 4024 | |
| 4025 | 4025 | /* sound hardware */ |
| 4026 | 4026 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 4027 | ||
| 4027 | ||
| 4028 | 4028 | MCFG_NMK004_ADD("nmk004") |
| 4029 | 4029 | |
| 4030 | 4030 | MCFG_SOUND_ADD("ymsnd", YM2203, 1500000) |
| r25360 | r25361 | |
| 4067 | 4067 | |
| 4068 | 4068 | /* sound hardware */ |
| 4069 | 4069 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 4070 | ||
| 4070 | ||
| 4071 | 4071 | MCFG_NMK004_ADD("nmk004") |
| 4072 | 4072 | |
| 4073 | 4073 | MCFG_SOUND_ADD("ymsnd", YM2203, 1500000) |
| r25360 | r25361 | |
| 4109 | 4109 | |
| 4110 | 4110 | /* sound hardware */ |
| 4111 | 4111 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 4112 | ||
| 4112 | ||
| 4113 | 4113 | MCFG_NMK004_ADD("nmk004") |
| 4114 | 4114 | |
| 4115 | 4115 | MCFG_SOUND_ADD("ymsnd", YM2203, 1500000) |
| r25360 | r25361 | |
| 4151 | 4151 | |
| 4152 | 4152 | /* sound hardware */ |
| 4153 | 4153 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 4154 | ||
| 4154 | ||
| 4155 | 4155 | MCFG_NMK004_ADD("nmk004") |
| 4156 | 4156 | |
| 4157 | 4157 | MCFG_SOUND_ADD("ymsnd", YM2203, XTAL_12MHz/8 ) /* verified on pcb */ |
| r25360 | r25361 | |
| 4193 | 4193 | |
| 4194 | 4194 | /* sound hardware */ |
| 4195 | 4195 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 4196 | ||
| 4196 | ||
| 4197 | 4197 | MCFG_NMK004_ADD("nmk004") |
| 4198 | 4198 | |
| 4199 | 4199 | MCFG_SOUND_ADD("ymsnd", YM2203, 1500000) |
| r25360 | r25361 | |
|---|---|---|
| 808 | 808 | UINT16 x = ioport(player ? "TOUCH2_X" : "TOUCH1_X")->read(); |
| 809 | 809 | UINT16 y = ioport(player ? "TOUCH2_Y" : "TOUCH1_Y")->read(); |
| 810 | 810 | |
| 811 | if (x & 0x8000) | |
| 811 | if (x & 0x8000) // touching | |
| 812 | 812 | { |
| 813 | 813 | x &= 0x7fff; |
| 814 | 814 | |
| 815 | 815 | // x |
| 816 | 816 | int slot_x = floor( ((320.0f - 1 - x) - 12) / 20 ); |
| 817 | ||
| 817 | ||
| 818 | 818 | if (slot_x < 0) |
| 819 | 819 | slot_x = 0; |
| 820 | 820 | else if (slot_x > 14) |
| r25360 | r25361 | |
| 834 | 834 | if ( ((m_ppsatan_io_mux >> 2) & (1 << slot_y)) || ((m_ppsatan_io_mux << 6) & (1 << slot_y)) ) |
| 835 | 835 | ret_y |= 1 << (slot_y % 6); |
| 836 | 836 | |
| 837 | // | |
| 837 | // if (!player) popmessage("TOUCH %03x %03x -> %f -> %d", x, y, ((320.0f - 1 - x) - 12) / 20, slot_x); | |
| 838 | 838 | } |
| 839 | 839 | |
| 840 | 840 | return ret_x | (ret_y << 8); |
| r25360 | r25361 | |
| 864 | 864 | { |
| 865 | 865 | set_led_status(machine(), 4, data & 0x0100); |
| 866 | 866 | set_led_status(machine(), 5, data & 0x0200); |
| 867 | set_led_status(machine(), 6, data & 0x0400); // not tested in service mode | |
| 868 | set_led_status(machine(), 7, data & 0x0800); // not tested in service mode | |
| 867 | set_led_status(machine(), 6, data & 0x0400); // not tested in service mode | |
| 868 | set_led_status(machine(), 7, data & 0x0800); // not tested in service mode | |
| 869 | 869 | |
| 870 | 870 | m_oki->set_bank_base((data & 0x8000) ? 0x40000 : 0); |
| 871 | 871 | } |
| 872 | 872 | |
| 873 | // | |
| 873 | // popmessage("OUT %04x", data); | |
| 874 | 874 | } |
| 875 | 875 | |
| 876 | 876 | static ADDRESS_MAP_START( ppsatan_map, AS_PROGRAM, 16, cave_state ) |
| r25360 | r25361 | |
| 880 | 880 | // Left Screen (Player 2) |
| 881 | 881 | AM_RANGE(0x080000, 0x080005) AM_RAM AM_SHARE("vctrl.1") // Layer Control |
| 882 | 882 | AM_RANGE(0x100000, 0x107fff) AM_RAM_WRITE(cave_vram_1_w) AM_SHARE("vram.1") // Layer |
| 883 | // AM_RANGE(0x180000, 0x1803ff) AM_RAM // Palette (Tilemaps) | |
| 884 | // AM_RANGE(0x187800, 0x188fff) AM_RAM AM_SHARE("paletteram.1") // Palette (Sprites) | |
| 883 | // AM_RANGE(0x180000, 0x1803ff) AM_RAM // Palette (Tilemaps) | |
| 884 | // AM_RANGE(0x187800, 0x188fff) AM_RAM AM_SHARE("paletteram.1") // Palette (Sprites) | |
| 885 | 885 | AM_RANGE(0x180000, 0x188fff) AM_RAM AM_SHARE("paletteram.1") // Palette |
| 886 | 886 | AM_RANGE(0x1c0000, 0x1c7fff) AM_RAM AM_SHARE("spriteram.1") // Sprites |
| 887 | 887 | AM_RANGE(0x200000, 0x200001) AM_READ_PORT("SYSTEM" ) // DSW + (unused) EEPROM |
| r25360 | r25361 | |
| 898 | 898 | // Right Screen (Player 1) |
| 899 | 899 | AM_RANGE(0x480000, 0x480005) AM_RAM AM_SHARE("vctrl.2") // Layer Control |
| 900 | 900 | AM_RANGE(0x500000, 0x507fff) AM_RAM_WRITE(cave_vram_2_w) AM_SHARE("vram.2") // Layer |
| 901 | // AM_RANGE(0x580000, 0x5803ff) AM_RAM // Palette (Tilemaps) | |
| 902 | // AM_RANGE(0x587800, 0x588fff) AM_RAM //AM_SHARE("paletteram.2") // Palette (Sprites) | |
| 901 | // AM_RANGE(0x580000, 0x5803ff) AM_RAM // Palette (Tilemaps) | |
| 902 | // AM_RANGE(0x587800, 0x588fff) AM_RAM //AM_SHARE("paletteram.2") // Palette (Sprites) | |
| 903 | 903 | AM_RANGE(0x580000, 0x588fff) AM_RAM AM_SHARE("paletteram.2") // Palette |
| 904 | 904 | AM_RANGE(0x5c0000, 0x5c7fff) AM_RAM AM_SHARE("spriteram.2") // Sprites |
| 905 | 905 | AM_RANGE(0x6c0000, 0x6c007f) AM_WRITEONLY AM_SHARE("videoregs.2") // Video Regs |
| r25360 | r25361 | |
| 907 | 907 | // Top Screen |
| 908 | 908 | AM_RANGE(0x880000, 0x880005) AM_RAM AM_SHARE("vctrl.0") // Layer Control |
| 909 | 909 | AM_RANGE(0x900000, 0x907fff) AM_RAM_WRITE(cave_vram_0_w) AM_SHARE("vram.0") // Layer |
| 910 | // AM_RANGE(0x980000, 0x9803ff) AM_RAM // Palette (Tilemaps) | |
| 911 | // AM_RANGE(0x987800, 0x988fff) AM_RAM AM_SHARE("paletteram.0") // Palette (Sprites) | |
| 910 | // AM_RANGE(0x980000, 0x9803ff) AM_RAM // Palette (Tilemaps) | |
| 911 | // AM_RANGE(0x987800, 0x988fff) AM_RAM AM_SHARE("paletteram.0") // Palette (Sprites) | |
| 912 | 912 | AM_RANGE(0x980000, 0x988fff) AM_RAM AM_SHARE("paletteram.0") // Palette |
| 913 | 913 | AM_RANGE(0x9c0000, 0x9c7fff) AM_RAM AM_SHARE("spriteram.0") // Sprites |
| 914 | 914 | AM_RANGE(0xac0000, 0xac007f) AM_WRITEONLY AM_SHARE("videoregs.0") // Video Regs |
| r25360 | r25361 | |
| 1660 | 1660 | PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_COIN1 ) |
| 1661 | 1661 | PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_UNKNOWN ) |
| 1662 | 1662 | PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_SERVICE1 ) // service coin |
| 1663 | PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_SERVICE2 ) | |
| 1663 | PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_SERVICE2 ) // advance in service mode | |
| 1664 | 1664 | PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_UNKNOWN ) |
| 1665 | 1665 | PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_UNKNOWN ) |
| 1666 | 1666 | PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_UNKNOWN ) |
| r25360 | r25361 | |
| 1678 | 1678 | PORT_DIPSETTING( 0x3000, DEF_STR( Normal ) ) // 20 hits |
| 1679 | 1679 | PORT_DIPSETTING( 0x0000, DEF_STR( Hard ) ) // 25 hits |
| 1680 | 1680 | PORT_DIPSETTING( 0x2000, "Hard (duplicate)" ) |
| 1681 | PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW1:7") | |
| 1681 | PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW1:7") // Jingle after "warning" screen (every 3 demo loops) | |
| 1682 | 1682 | PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) |
| 1683 | 1683 | PORT_DIPSETTING( 0x4000, DEF_STR( On ) ) |
| 1684 | 1684 | PORT_SERVICE(0x8000, IP_ACTIVE_LOW) PORT_DIPLOCATION("SW1:8") |
| r25360 | r25361 | |
| 2473 | 2473 | |
| 2474 | 2474 | MCFG_MACHINE_START_OVERRIDE(cave_state,cave) |
| 2475 | 2475 | MCFG_MACHINE_RESET_OVERRIDE(cave_state,cave) |
| 2476 | ||
| 2476 | ||
| 2477 | 2477 | MCFG_EEPROM_SERIAL_93C46_ADD("eeprom") |
| 2478 | 2478 | MCFG_EEPROM_SERIAL_ENABLE_STREAMING() |
| 2479 | 2479 | |
| r25360 | r25361 | |
| 2513 | 2513 | |
| 2514 | 2514 | TIMER_DEVICE_CALLBACK_MEMBER( cave_state::timer_lev2_cb ) |
| 2515 | 2515 | { |
| 2516 | m_maincpu->set_input_line(M68K_IRQ_2, HOLD_LINE); | |
| 2516 | m_maincpu->set_input_line(M68K_IRQ_2, HOLD_LINE); // ppsatan: read touch screens | |
| 2517 | 2517 | } |
| 2518 | 2518 | |
| 2519 | 2519 | static MACHINE_CONFIG_START( ppsatan, cave_state ) |
| r25360 | r25361 | |
| 2532 | 2532 | MCFG_TIMER_DRIVER_ADD_PERIODIC("timer_lev2", cave_state, timer_lev2_cb, attotime::from_hz(60)) |
| 2533 | 2533 | |
| 2534 | 2534 | /* video hardware */ |
| 2535 | MCFG_SCREEN_ADD("screen", RASTER) | |
| 2535 | MCFG_SCREEN_ADD("screen", RASTER) // Top | |
| 2536 | 2536 | MCFG_SCREEN_REFRESH_RATE(15625/271.5) |
| 2537 | 2537 | MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0)) |
| 2538 | 2538 | MCFG_SCREEN_SIZE(320, 240) |
| r25360 | r25361 | |
|---|---|---|
| 364 | 364 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) |
| 365 | 365 | MCFG_S2636_ADD("s2636_1", malzac_s2636_1_config) |
| 366 | 366 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) |
| 367 | ||
| 367 | ||
| 368 | 368 | MCFG_SAA5050_ADD("saa5050", 6000000, malzac_saa5050_intf) |
| 369 | 369 | |
| 370 | 370 | /* sound hardware */ |
| r25360 | r25361 | |
|---|---|---|
| 2994 | 2994 | the game doesn't use any tiles from here but the roms must be present on the board to avoid |
| 2995 | 2995 | tile 0 being solid and obscuring the bitmap (however if we load them in the correct region |
| 2996 | 2996 | unwanted tiles from here are shown after gameover which is wrong) - There is an undumped PAL |
| 2997 | ||
| 2997 | C12-01 that controls this effect. | |
| 2998 | 2998 | */ |
| 2999 | 2999 | ROM_LOAD( "b81-03.14", 0x000000, 0x080000, CRC(551b75e6) SHA1(5b8388ee2c6262f359c9e6d04c951ea8dc3901c9) ) |
| 3000 | 3000 | ROM_LOAD( "b81-04.15", 0x080000, 0x080000, CRC(cf734e12) SHA1(4201a74468058761454515738fbf3a7b22a66e00) ) |
| r25360 | r25361 | |
| 3024 | 3024 | the game doesn't use any tiles from here but the roms must be present on the board to avoid |
| 3025 | 3025 | tile 0 being solid and obscuring the bitmap (however if we load them in the correct region |
| 3026 | 3026 | unwanted tiles from here are shown after gameover which is wrong) - There is an undumped PAL |
| 3027 | ||
| 3027 | C35-06 that controls this effect. | |
| 3028 | 3028 | */ |
| 3029 | 3029 | ROM_LOAD( "b72-02.6", 0x000000, 0x080000, CRC(843444eb) SHA1(2b466045f882996c80e0090009ee957e11d32825) ) |
| 3030 | 3030 | ROM_LOAD( "b72-01.5", 0x080000, 0x080000, CRC(a24ac26e) SHA1(895715a2bb0cb15334cba2283bd228b4fc08cd0c) ) |
| r25360 | r25361 | |
|---|---|---|
| 34 | 34 | shanghai_state(const machine_config &mconfig, device_type type, const char *tag) |
| 35 | 35 | : driver_device(mconfig, type, tag), |
| 36 | 36 | m_maincpu(*this, "maincpu"), |
| 37 | m_hd63484(*this, "hd63484") | |
| 37 | m_hd63484(*this, "hd63484") { } | |
| 38 | 38 | |
| 39 | 39 | DECLARE_WRITE16_MEMBER(shanghai_coin_w); |
| 40 | 40 | DECLARE_READ16_MEMBER(kothello_hd63484_status_r); |
| r25360 | r25361 | |
|---|---|---|
| 4029 | 4029 | ROM_LOAD( "tp-026-3", 0x000000, 0x200000, CRC(e5578d98) SHA1(280d2b716d955e767d311fc9596823852435b6d7) ) \ |
| 4030 | 4030 | ROM_LOAD( "tp-026-4", 0x200000, 0x200000, CRC(b760cb53) SHA1(bc9c5e49e45cdda0f774be0038aa4deb21d4d285) ) \ |
| 4031 | 4031 | ROM_REGION( 0x40000, "oki", 0 ) \ |
| 4032 | ROM_LOAD( "tp-026-2", 0x00000, 0x40000, CRC(85063f1f) SHA1(1bf4d77494de421c98f6273b9876e60d827a6826) ) | |
| 4032 | ROM_LOAD( "tp-026-2", 0x00000, 0x40000, CRC(85063f1f) SHA1(1bf4d77494de421c98f6273b9876e60d827a6826) ) | |
| 4033 | 4033 | |
| 4034 | ||
| 4035 | 4034 | ROM_START( fixeightkt ) |
| 4036 | 4035 | ROMS_FIXEIGHT |
| 4037 | 4036 | ROM_REGION( 0x80, "eeprom", 0 ) |
| r25360 | r25361 | |
|---|---|---|
| 63 | 63 | m_stream = machine().sound().stream_alloc(*this, 0, 1, clock(), this); |
| 64 | 64 | m_base = machine().root_device().memregion("adpcm")->base(); |
| 65 | 65 | m_adpcm.reset(); |
| 66 | ||
| 66 | ||
| 67 | 67 | save_item(NAME(m_current)); |
| 68 | 68 | save_item(NAME(m_end)); |
| 69 | 69 | save_item(NAME(m_nibble)); |
| r25360 | r25361 | |
|---|---|---|
| 290 | 290 | return; |
| 291 | 291 | } |
| 292 | 292 | |
| 293 | // | |
| 293 | // logerror("COPRO FIFOOUT PUSH %08X, %f, %d\n", data, *(float*)&data,m_copro_fifoout_num); | |
| 294 | 294 | |
| 295 | 295 | m_copro_fifoout_data[m_copro_fifoout_wpos++] = data; |
| 296 | 296 | if (m_copro_fifoout_wpos == COPRO_FIFOOUT_SIZE) |
| r25360 | r25361 | |
|---|---|---|
| 439 | 439 | PORT_DIPSETTING( 0x80, "1 Coin/50 Credits" ) |
| 440 | 440 | |
| 441 | 441 | PORT_START("DSW3") |
| 442 | PORT_DIPNAME( 0x01, 0x00, "Manufacturer" ) PORT_DIPLOCATION("SW3:1") | |
| 442 | PORT_DIPNAME( 0x01, 0x00, "Manufacturer" ) PORT_DIPLOCATION("SW3:1") /* Set to "Sega" to show Japanese text on the "Continue" screen */ | |
| 443 | 443 | PORT_DIPSETTING( 0x00, "Nihon System" ) |
| 444 | 444 | PORT_DIPSETTING( 0x01, "Sega/Nihon System" ) |
| 445 | 445 | PORT_DIPUNUSED_DIPLOC( 0x02, 0x02, "SW3:2" ) |
| r25360 | r25361 | |
|---|---|---|
| 133 | 133 | hardware which creates the 3d background scenes? It seems |
| 134 | 134 | the TMS320C25 is being used as a co-processor to relieve the |
| 135 | 135 | 68000 of 3d calculations... it has direct access to line ram |
| 136 | along with the 68000. | |
| 136 | along with the 68000. | |
| 137 | 137 | |
| 138 | 138 | Gradiation RAM is used to display a rotatable gradient background. |
| 139 | 139 | The rotation is most likely handled by the TC0430GRW ROZ chip. |
| r25360 | r25361 | |
| 691 | 691 | static MACHINE_CONFIG_START( airsys, taitoair_state ) |
| 692 | 692 | |
| 693 | 693 | /* basic machine hardware */ |
| 694 | MCFG_CPU_ADD("maincpu", M68000, XTAL_12MHz) | |
| 694 | MCFG_CPU_ADD("maincpu", M68000, XTAL_12MHz) // MC68000P12 | |
| 695 | 695 | MCFG_CPU_PROGRAM_MAP(airsys_map) |
| 696 | 696 | MCFG_CPU_VBLANK_INT_DRIVER("screen", taitoair_state, irq5_line_hold) |
| 697 | 697 | |
| 698 | MCFG_CPU_ADD("audiocpu", Z80, XTAL_16MHz / 4) | |
| 698 | MCFG_CPU_ADD("audiocpu", Z80, XTAL_16MHz / 4) // Z8400AB1 | |
| 699 | 699 | MCFG_CPU_PROGRAM_MAP(sound_map) |
| 700 | 700 | |
| 701 | 701 | MCFG_CPU_ADD("dsp", TMS32025, XTAL_36MHz) // Unverified |
| r25360 | r25361 | |
|---|---|---|
| 323 | 323 | MCFG_SOUND_ROUTE(3, "lspeaker", 1.00) |
| 324 | 324 | |
| 325 | 325 | MCFG_AT28C16_ADD( "at28c16", NULL ) |
| 326 | ||
| 326 | ||
| 327 | 327 | MCFG_YGV608_ADD("ygv608") |
| 328 | 328 | MACHINE_CONFIG_END |
| 329 | 329 |
| r25360 | r25361 | |
|---|---|---|
| 227 | 227 | { |
| 228 | 228 | m_coin_status = 0; |
| 229 | 229 | m_palette_bank = 0; |
| 230 | ||
| 230 | ||
| 231 | 231 | m_port1State = 0; |
| 232 | 232 | m_port2State = 0; |
| 233 | 233 | m_psgData = 0; |
| r25360 | r25361 | |
|---|---|---|
| 1235 | 1235 | |
| 1236 | 1236 | MCFG_MACHINE_START_OVERRIDE(atarisy2_state,atarisy2) |
| 1237 | 1237 | MCFG_MACHINE_RESET_OVERRIDE(atarisy2_state,atarisy2) |
| 1238 | ||
| 1238 | ||
| 1239 | 1239 | MCFG_EEPROM_2804_ADD("eeprom") |
| 1240 | 1240 | |
| 1241 | 1241 | /* video hardware */ |
| r25360 | r25361 | |
| 1245 | 1245 | |
| 1246 | 1246 | MCFG_TILEMAP_ADD_STANDARD("playfield", 2, atarisy2_state, get_playfield_tile_info, 8,8, SCAN_ROWS, 128,64) |
| 1247 | 1247 | MCFG_TILEMAP_ADD_STANDARD_TRANSPEN("alpha", 2, atarisy2_state, get_alpha_tile_info, 8,8, SCAN_ROWS, 64,48, 0) |
| 1248 | ||
| 1248 | ||
| 1249 | 1249 | MCFG_ATARI_MOTION_OBJECTS_ADD("mob", "screen", atarisy2_state::s_mob_config) |
| 1250 | 1250 | |
| 1251 | 1251 | MCFG_SCREEN_ADD("screen", RASTER) |
| r25360 | r25361 | |
|---|---|---|
| 67 | 67 | DECLARE_INPUT_CHANGED_MEMBER(audio_nmi); |
| 68 | 68 | DECLARE_READ8_MEMBER(dmd_status_r); |
| 69 | 69 | |
| 70 | // DECLARE_READ8_MEMBER(sound_latch_r); | |
| 71 | // DECLARE_WRITE8_MEMBER(sample_bank_w); | |
| 70 | // DECLARE_READ8_MEMBER(sound_latch_r); | |
| 71 | // DECLARE_WRITE8_MEMBER(sample_bank_w); | |
| 72 | 72 | |
| 73 | 73 | required_device<decobsmt_device> m_decobsmt; |
| 74 | 74 | bool m_nmi_enable; |
| r25360 | r25361 | |
| 83 | 83 | // driver_device overrides |
| 84 | 84 | virtual void machine_reset(); |
| 85 | 85 | private: |
| 86 | // UINT32 m_segment1; | |
| 87 | // UINT32 m_segment2; | |
| 86 | // UINT32 m_segment1; | |
| 87 | // UINT32 m_segment2; | |
| 88 | 88 | UINT8 m_strobe; |
| 89 | 89 | UINT8 m_kbdrow; |
| 90 | 90 | UINT8 m_diag; |
| r25360 | r25361 | |
| 197 | 197 | // 6821 PIA at 0x2800 |
| 198 | 198 | WRITE8_MEMBER( de_3_state::dig0_w ) |
| 199 | 199 | { |
| 200 | // static const UINT8 patterns[16] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7c, 0x07, 0x7f, 0x67, 0x58, 0x4c, 0x62, 0x69, 0x78, 0 }; // 7447 | |
| 201 | // data &= 0x7f; | |
| 202 | // m_strobe = data & 15; | |
| 203 | // m_diag = (data & 0x70) >> 4; | |
| 204 | // output_set_digit_value(60, patterns[data>>4]); // diag digit | |
| 205 | // m_segment1 = 0; | |
| 206 | // m_segment2 = 0; | |
| 200 | // static const UINT8 patterns[16] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7c, 0x07, 0x7f, 0x67, 0x58, 0x4c, 0x62, 0x69, 0x78, 0 }; // 7447 | |
| 201 | // data &= 0x7f; | |
| 202 | // m_strobe = data & 15; | |
| 203 | // m_diag = (data & 0x70) >> 4; | |
| 204 | // output_set_digit_value(60, patterns[data>>4]); // diag digit | |
| 205 | // m_segment1 = 0; | |
| 206 | // m_segment2 = 0; | |
| 207 | 207 | } |
| 208 | 208 | |
| 209 | 209 | WRITE8_MEMBER( de_3_state::dig1_w ) |
| 210 | 210 | { |
| 211 | // m_segment2 |= data; | |
| 212 | // m_segment2 |= 0x30000; | |
| 213 | // if ((m_segment2 & 0x70000) == 0x30000) | |
| 214 | // { | |
| 215 | // if(m_is_alpha3) // Alphanumeric type 2 uses 7 segment LEDs on the bottom row, type 3 uses 14 segment LEDs | |
| 216 | // output_set_digit_value(m_strobe+16, BITSWAP16(m_segment2, 7, 15, 12, 10, 8, 14, 13, 9, 11, 6, 5, 4, 3, 2, 1, 0)); | |
| 217 | // else | |
| 218 | // output_set_digit_value(m_strobe+16, BITSWAP16(m_segment2, 11, 15, 12, 10, 8, 14, 13, 9, 7, 6, 5, 4, 3, 2, 1, 0)); | |
| 219 | // m_segment2 |= 0x40000; | |
| 220 | // } | |
| 211 | // m_segment2 |= data; | |
| 212 | // m_segment2 |= 0x30000; | |
| 213 | // if ((m_segment2 & 0x70000) == 0x30000) | |
| 214 | // { | |
| 215 | // if(m_is_alpha3) // Alphanumeric type 2 uses 7 segment LEDs on the bottom row, type 3 uses 14 segment LEDs | |
| 216 | // output_set_digit_value(m_strobe+16, BITSWAP16(m_segment2, 7, 15, 12, 10, 8, 14, 13, 9, 11, 6, 5, 4, 3, 2, 1, 0)); | |
| 217 | // else | |
| 218 | // output_set_digit_value(m_strobe+16, BITSWAP16(m_segment2, 11, 15, 12, 10, 8, 14, 13, 9, 7, 6, 5, 4, 3, 2, 1, 0)); | |
| 219 | // m_segment2 |= 0x40000; | |
| 220 | // } | |
| 221 | 221 | } |
| 222 | 222 | |
| 223 | 223 | READ8_MEMBER( de_3_state::pia28_w7_r ) |
| r25360 | r25361 | |
| 244 | 244 | m_dmdtype1->data_w(space,offset,data); |
| 245 | 245 | logerror("DMD: Data write %02x\n", data); |
| 246 | 246 | } |
| 247 | // m_segment1 |= (data<<8); | |
| 248 | // m_segment1 |= 0x10000; | |
| 249 | // if ((m_segment1 & 0x70000) == 0x30000) | |
| 250 | // { | |
| 251 | // output_set_digit_value(m_strobe, BITSWAP16(m_segment1, 7, 15, 12, 10, 8, 14, 13, 9, 11, 6, 5, 4, 3, 2, 1, 0)); | |
| 252 | // m_segment1 |= 0x40000; | |
| 253 | // } | |
| 247 | // m_segment1 |= (data<<8); | |
| 248 | // m_segment1 |= 0x10000; | |
| 249 | // if ((m_segment1 & 0x70000) == 0x30000) | |
| 250 | // { | |
| 251 | // output_set_digit_value(m_strobe, BITSWAP16(m_segment1, 7, 15, 12, 10, 8, 14, 13, 9, 11, 6, 5, 4, 3, 2, 1, 0)); | |
| 252 | // m_segment1 |= 0x40000; | |
| 253 | // } | |
| 254 | 254 | } |
| 255 | 255 | |
| 256 | 256 | READ8_MEMBER( de_3_state::pia2c_pb_r ) |
| r25360 | r25361 | |
| 276 | 276 | logerror("DMD: Control write %02x\n", data); |
| 277 | 277 | } |
| 278 | 278 | |
| 279 | // m_segment1 |= data; | |
| 280 | // m_segment1 |= 0x20000; | |
| 281 | // if ((m_segment1 & 0x70000) == 0x30000) | |
| 282 | // { | |
| 283 | // output_set_digit_value(m_strobe, BITSWAP16(m_segment1, 7, 15, 12, 10, 8, 14, 13, 9, 11, 6, 5, 4, 3, 2, 1, 0)); | |
| 284 | // m_segment1 |= 0x40000; | |
| 285 | // } | |
| 279 | // m_segment1 |= data; | |
| 280 | // m_segment1 |= 0x20000; | |
| 281 | // if ((m_segment1 & 0x70000) == 0x30000) | |
| 282 | // { | |
| 283 | // output_set_digit_value(m_strobe, BITSWAP16(m_segment1, 7, 15, 12, 10, 8, 14, 13, 9, 11, 6, 5, 4, 3, 2, 1, 0)); | |
| 284 | // m_segment1 |= 0x40000; | |
| 285 | // } | |
| 286 | 286 | } |
| 287 | 287 | |
| 288 | 288 | |
| r25360 | r25361 | |
| 310 | 310 | WRITE8_MEMBER( de_3_state::pia34_pa_w ) |
| 311 | 311 | { |
| 312 | 312 | // Not connected? |
| 313 | // m_segment2 |= (data<<8); | |
| 314 | // m_segment2 |= 0x10000; | |
| 315 | // if ((m_segment2 & 0x70000) == 0x30000) | |
| 316 | // { | |
| 317 | // output_set_digit_value(m_strobe+16, BITSWAP16(m_segment2, 7, 15, 12, 10, 8, 14, 13, 9, 11, 6, 5, 4, 3, 2, 1, 0)); | |
| 318 | // m_segment2 |= 0x40000; | |
| 319 | // } | |
| 313 | // m_segment2 |= (data<<8); | |
| 314 | // m_segment2 |= 0x10000; | |
| 315 | // if ((m_segment2 & 0x70000) == 0x30000) | |
| 316 | // { | |
| 317 | // output_set_digit_value(m_strobe+16, BITSWAP16(m_segment2, 7, 15, 12, 10, 8, 14, 13, 9, 11, 6, 5, 4, 3, 2, 1, 0)); | |
| 318 | // m_segment2 |= 0x40000; | |
| 319 | // } | |
| 320 | 320 | } |
| 321 | 321 | |
| 322 | 322 | READ8_MEMBER( de_3_state::dmd_status_r ) |
| r25360 | r25361 | |
|---|---|---|
| 184 | 184 | switch(offset) |
| 185 | 185 | { |
| 186 | 186 | case 0: |
| 187 | // | |
| 187 | // ret = pia28_w7_r(space,0); | |
| 188 | 188 | break; |
| 189 | 189 | case 3: |
| 190 | 190 | ret = pia2c_pb_r(space,0); |
| r25360 | r25361 | |
| 199 | 199 | switch(offset) |
| 200 | 200 | { |
| 201 | 201 | case 0: |
| 202 | // | |
| 202 | // dig0_w(space,0,data); | |
| 203 | 203 | break; |
| 204 | 204 | case 1: |
| 205 | // | |
| 205 | // dig1_w(space,0,data); | |
| 206 | 206 | break; |
| 207 | 207 | case 2: |
| 208 | 208 | pia2c_pa_w(space,0,data); |
| r25360 | r25361 | |
| 211 | 211 | pia2c_pb_w(space,0,data); |
| 212 | 212 | break; |
| 213 | 213 | case 4: |
| 214 | // | |
| 214 | // pia34_pa_w(space,0,data); | |
| 215 | 215 | break; |
| 216 | 216 | } |
| 217 | 217 | } |
| r25360 | r25361 | |
|---|---|---|
| 183 | 183 | MCFG_DEVICE_VBLANK_INT_DRIVER("screen", atarigen_state, video_int_gen) |
| 184 | 184 | |
| 185 | 185 | MCFG_MACHINE_RESET_OVERRIDE(xybots_state,xybots) |
| 186 | ||
| 186 | ||
| 187 | 187 | MCFG_ATARI_EEPROM_2804_ADD("eeprom") |
| 188 | 188 | |
| 189 | 189 | /* video hardware */ |
| r25360 | r25361 | |
|---|---|---|
| 984 | 984 | MCFG_CPU_VBLANK_INT_DRIVER("screen", vamphalf_state, irq1_line_hold) |
| 985 | 985 | |
| 986 | 986 | MCFG_EEPROM_SERIAL_93C46_ADD("eeprom") |
| 987 | MCFG_EEPROM_ERASE_TIME(attotime::from_usec(250)) // coolmini requires fast erase | |
| 988 | MCFG_EEPROM_WRITE_TIME(attotime::from_usec(250)) // dtfamily requires fast write | |
| 987 | MCFG_EEPROM_ERASE_TIME(attotime::from_usec(250)) // coolmini requires fast erase | |
| 988 | MCFG_EEPROM_WRITE_TIME(attotime::from_usec(250)) // dtfamily requires fast write | |
| 989 | 989 | |
| 990 | 990 | /* video hardware */ |
| 991 | 991 | MCFG_SCREEN_ADD("screen", RASTER) |
| r25360 | r25361 | |
|---|---|---|
| 144 | 144 | m_stream = machine().sound().stream_alloc(*this, 0, 1, clock(), this); |
| 145 | 145 | m_base = machine().root_device().memregion("adpcm")->base(); |
| 146 | 146 | m_adpcm.reset(); |
| 147 | ||
| 147 | ||
| 148 | 148 | save_item(NAME(m_current)); |
| 149 | 149 | save_item(NAME(m_end)); |
| 150 | 150 | save_item(NAME(m_nibble)); |
| r25360 | r25361 | |
|---|---|---|
| 316 | 316 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) |
| 317 | 317 | MCFG_S2636_ADD("s2636_2", galaxia_s2636_config[2]) |
| 318 | 318 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) |
| 319 | ||
| 319 | ||
| 320 | 320 | /* sound hardware */ |
| 321 | 321 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 322 | 322 |
| r25360 | r25361 | |
|---|---|---|
| 62 | 62 | m_custom(*this, "cust") { } |
| 63 | 63 | |
| 64 | 64 | required_device<galaxian_sound_device> m_custom; |
| 65 | ||
| 65 | ||
| 66 | 66 | int m_noise_data; |
| 67 | 67 | DECLARE_WRITE8_MEMBER(dambustr_noise_enable_w); |
| 68 | 68 | DECLARE_DRIVER_INIT(dambustr); |
| r25360 | r25361 | |
|---|---|---|
| 262 | 262 | // TAITO Type X Model 006B No 150FG0217 AC100V 50/60Hz 2.5A |
| 263 | 263 | // Windows(R) XP Embedded 00039-111-243-487 X11-15305 |
| 264 | 264 | // |
| 265 | // | |
| 265 | // USAGI M9006613A VER.2.04JPN 40.0GB WD WD400BB-22JHCO | |
| 266 | 266 | ROM_START( usagiol ) |
| 267 | 267 | ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF ) |
| 268 | 268 | ROM_LOAD("taito_type_x_bios.bin", 0x00, 0x10000, NO_DUMP ) // size unknown. |
| r25360 | r25361 | |
|---|---|---|
| 212 | 212 | { |
| 213 | 213 | switch (offset) |
| 214 | 214 | { |
| 215 | case 0x0: | |
| 215 | case 0x0: // Motor status? | |
| 216 | 216 | return (machine().rand() & 0xff); |
| 217 | 217 | |
| 218 | case 0x101: | |
| 218 | case 0x101: // Motor CPU status? | |
| 219 | 219 | return 0x55; |
| 220 | 220 | |
| 221 | 221 | case 0x141: // Left limit data |
| r25360 | r25361 | |
| 315 | 315 | |
| 316 | 316 | switch (offset) |
| 317 | 317 | { |
| 318 | case 0x000: filter = m_filter2; break; // MSM5205 1 | |
| 319 | case 0x200: filter = m_filter3; break; // MSM5205 2 | |
| 320 | case 0x400: filter = m_filter1l; break; // YM-2151 L | |
| 321 | case 0x600: filter = m_filter1r; break; // YM-2151 R | |
| 318 | case 0x000: filter = m_filter2; break; // MSM5205 1 | |
| 319 | case 0x200: filter = m_filter3; break; // MSM5205 2 | |
| 320 | case 0x400: filter = m_filter1l; break; // YM-2151 L | |
| 321 | case 0x600: filter = m_filter1r; break; // YM-2151 R | |
| 322 | 322 | } |
| 323 | 323 | |
| 324 | 324 | filter->flt_volume_set_volume(data / 255.0f); |
| r25360 | r25361 | |
| 494 | 494 | |
| 495 | 495 | static const gfx_layout tile16x8_layout = |
| 496 | 496 | { |
| 497 | 16,8, | |
| 497 | 16,8, // 16*8 sprites | |
| 498 | 498 | RGN_FRAC(1,1), |
| 499 | 4, | |
| 499 | 4, // 4 bits per pixel | |
| 500 | 500 | { 0, 8, 16, 24 }, |
| 501 | 501 | { 32, 33, 34, 35, 36, 37, 38, 39, 0, 1, 2, 3, 4, 5, 6, 7 }, |
| 502 | 502 | { 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64 }, |
| 503 | 64*8 | |
| 503 | 64*8 // every sprite takes 64 consecutive bytes | |
| 504 | 504 | }; |
| 505 | 505 | |
| 506 | 506 | static const gfx_layout charlayout = |
| 507 | 507 | { |
| 508 | 508 | 8,8, // 8*8 characters |
| 509 | 509 | RGN_FRAC(1,1), |
| 510 | 4, | |
| 510 | 4, // 4 bits per pixel | |
| 511 | 511 | { 0, 1, 2, 3 }, |
| 512 | 512 | { 2*4, 3*4, 0*4, 1*4, 6*4, 7*4, 4*4, 5*4 }, |
| 513 | 513 | { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32 }, |
| 514 | 32*8 | |
| 514 | 32*8 // every sprite takes 32 consecutive bytes | |
| 515 | 515 | }; |
| 516 | 516 | |
| 517 | 517 | static GFXDECODE_START( topspeed ) |
| 518 | GFXDECODE_ENTRY( "gfx2", 0x0, tile16x8_layout, 0, 256 ) // Sprite parts | |
| 519 | GFXDECODE_ENTRY( "gfx1", 0x0, charlayout, 0, 256 ) // Sprites & playfield | |
| 518 | GFXDECODE_ENTRY( "gfx2", 0x0, tile16x8_layout, 0, 256 ) // Sprite parts | |
| 519 | GFXDECODE_ENTRY( "gfx1", 0x0, charlayout, 0, 256 ) // Sprites & playfield | |
| 520 | 520 | // Road Lines gfxdecodable ? |
| 521 | 521 | GFXDECODE_END |
| 522 | 522 | |
| r25360 | r25361 | |
| 528 | 528 | static const msm5205_interface msm5205_config_1 = |
| 529 | 529 | { |
| 530 | 530 | DEVCB_DRIVER_LINE_MEMBER(topspeed_state, msm5205_1_vck), // VCK function |
| 531 | MSM5205_S48_4B | |
| 531 | MSM5205_S48_4B // 8 kHz, 4-bit | |
| 532 | 532 | }; |
| 533 | 533 | |
| 534 | 534 | static const msm5205_interface msm5205_config_2 = |
| 535 | 535 | { |
| 536 | DEVCB_NULL, // VCK function | |
| 537 | MSM5205_SEX_4B // Slave mode, 4-bit | |
| 536 | DEVCB_NULL, // VCK function | |
| 537 | MSM5205_SEX_4B // Slave mode, 4-bit | |
| 538 | 538 | }; |
| 539 | 539 | |
| 540 | 540 | |
| r25360 | r25361 | |
| 544 | 544 | |
| 545 | 545 | static const pc080sn_interface pc080sn_intf = |
| 546 | 546 | { |
| 547 | 1, | |
| 547 | 1, // gfxnum | |
| 548 | 548 | 0, 8, 0, 0 // x_offset, y_offset, y_invert, dblwidth |
| 549 | 549 | }; |
| 550 | 550 | |
| r25360 | r25361 | |
| 564 | 564 | |
| 565 | 565 | static Z80CTC_INTERFACE( ctc_intf ) |
| 566 | 566 | { |
| 567 | DEVCB_NULL, | |
| 567 | DEVCB_NULL, // Interrupt handler | |
| 568 | 568 | DEVCB_DRIVER_LINE_MEMBER(topspeed_state, z80ctc_to0), // ZC/TO0 callback |
| 569 | 569 | DEVCB_NULL, // ZC/TO1 callback |
| 570 | DEVCB_NULL | |
| 570 | DEVCB_NULL // ZC/TO2 callback | |
| 571 | 571 | }; |
| 572 | 572 | |
| 573 | 573 |
| r25360 | r25361 | |
|---|---|---|
| 67 | 67 | TODO (game-specific): |
| 68 | 68 | - 18 Wheeler Deluxe: "MOTOR NETWORK ERR IN 01 OUT FF" msg pops up during gameplay; |
| 69 | 69 | - Airline Pilots Deluxe: returns error 03 |
| 70 | - Capcom vs. SNK Pro: doesn't accept start input (REGRESSION) | |
| 71 | - Derby Owner Club: if you try to start a game, it moans about something and enters into some kind of JP test mode, pretty bogus behaviour; | |
| 70 | - Capcom vs. SNK Pro: doesn't accept start input (REGRESSION) | |
| 71 | - Derby Owner Club: if you try to start a game, it moans about something and enters into some kind of JP test mode, pretty bogus behaviour; | |
| 72 | 72 | - Ferrari 355 Challenge: dies at the network check; |
| 73 | 73 | - Giant Gram 2: no VMU emulation; |
| 74 | 74 | - Gun Survivor 2: crashes during game loading; |
| r25360 | r25361 | |
|---|---|---|
| 40 | 40 | required_shared_ptr<UINT16> m_md_vram; |
| 41 | 41 | required_shared_ptr<UINT16> m_fg_vram; |
| 42 | 42 | required_shared_ptr<UINT16> m_tx_vram; |
| 43 | ||
| 43 | ||
| 44 | 44 | required_device<cpu_device> m_maincpu; |
| 45 | 45 | optional_device<seibu_sound_device> m_seibu_sound; |
| 46 | 46 | optional_device<eeprom_serial_93cxx_device> m_eeprom; |
| 47 | ||
| 47 | ||
| 48 | 48 | DECLARE_WRITE16_MEMBER(rdx_bg_vram_w); |
| 49 | 49 | DECLARE_WRITE16_MEMBER(rdx_md_vram_w); |
| 50 | 50 | DECLARE_WRITE16_MEMBER(rdx_fg_vram_w); |
| r25360 | r25361 | |
|---|---|---|
| 403 | 403 | |
| 404 | 404 | MCFG_MACHINE_START_OVERRIDE(cyberbal_state,cyberbal) |
| 405 | 405 | MCFG_MACHINE_RESET_OVERRIDE(cyberbal_state,cyberbal) |
| 406 | ||
| 406 | ||
| 407 | 407 | MCFG_ATARI_EEPROM_2804_ADD("eeprom") |
| 408 | 408 | |
| 409 | 409 | /* video hardware */ |
| r25360 | r25361 | |
| 465 | 465 | |
| 466 | 466 | MCFG_MACHINE_START_OVERRIDE(cyberbal_state,cyberbal) |
| 467 | 467 | MCFG_MACHINE_RESET_OVERRIDE(cyberbal_state,cyberbal2p) |
| 468 | ||
| 468 | ||
| 469 | 469 | MCFG_ATARI_EEPROM_2816_ADD("eeprom") |
| 470 | 470 | |
| 471 | 471 | /* video hardware */ |
| r25360 | r25361 | |
|---|---|---|
| 503 | 503 | |
| 504 | 504 | MCFG_MACHINE_START_OVERRIDE(badlands_state,badlands) |
| 505 | 505 | MCFG_MACHINE_RESET_OVERRIDE(badlands_state,badlands) |
| 506 | ||
| 506 | ||
| 507 | 507 | MCFG_ATARI_EEPROM_2816_ADD("eeprom") |
| 508 | 508 | |
| 509 | 509 | /* video hardware */ |
| r25360 | r25361 | |
| 656 | 656 | ADDRESS_MAP_END |
| 657 | 657 | |
| 658 | 658 | static INPUT_PORTS_START( badlandsb ) |
| 659 | ||
| 659 | ||
| 660 | 660 | PORT_INCLUDE( badlands ) |
| 661 | 661 | |
| 662 | 662 | PORT_MODIFY("AUDIO") /* audio port */ |
| r25360 | r25361 | |
| 705 | 705 | |
| 706 | 706 | MCFG_MACHINE_START_OVERRIDE(badlands_state,badlands) |
| 707 | 707 | MCFG_MACHINE_RESET_OVERRIDE(badlands_state,badlandsb) |
| 708 | ||
| 708 | ||
| 709 | 709 | MCFG_ATARI_EEPROM_2816_ADD("eeprom") |
| 710 | 710 | |
| 711 | 711 | /* video hardware */ |
| r25360 | r25361 | |
|---|---|---|
| 362 | 362 | MCFG_CPU_PROGRAM_MAP(main_map) |
| 363 | 363 | |
| 364 | 364 | MCFG_MACHINE_RESET_OVERRIDE(offtwall_state,offtwall) |
| 365 | ||
| 365 | ||
| 366 | 366 | MCFG_ATARI_EEPROM_2816_ADD("eeprom") |
| 367 | 367 | |
| 368 | 368 | /* video hardware */ |
| r25360 | r25361 | |
|---|---|---|
| 2155 | 2155 | MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
| 2156 | 2156 | |
| 2157 | 2157 | /* on at least hatch catch, cookie & bibi and choky choky the YM2151 clock is connected |
| 2158 | directly to the Z80 clock so the speed should match */ | |
| 2159 | MCFG_YM2151_ADD("ymsnd", 15000000/4) | |
| 2158 | directly to the Z80 clock so the speed should match */ | |
| 2159 | MCFG_YM2151_ADD("ymsnd", 15000000/4) | |
| 2160 | 2160 | MCFG_YM2151_IRQ_HANDLER(INPUTLINE("audiocpu", 0)) |
| 2161 | 2161 | MCFG_SOUND_ROUTE(0, "lspeaker", 0.10) |
| 2162 | 2162 | MCFG_SOUND_ROUTE(1, "rspeaker", 0.10) |
| r25360 | r25361 | |
| 2173 | 2173 | MACHINE_CONFIG_END |
| 2174 | 2174 | |
| 2175 | 2175 | static MACHINE_CONFIG_DERIVED( chokchok, htchctch ) |
| 2176 | MCFG_OKIM6295_REPLACE("oki", 3579545/4, OKIM6295_PIN7_HIGH) | |
| 2177 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 1.0) | |
| 2178 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.0) | |
| 2176 | MCFG_OKIM6295_REPLACE("oki", 3579545/4, OKIM6295_PIN7_HIGH) | |
| 2177 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 1.0) | |
| 2178 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.0) | |
| 2179 | 2179 | MACHINE_CONFIG_END |
| 2180 | 2180 | |
| 2181 | 2181 | static MACHINE_CONFIG_DERIVED( cookbib_mcu, htchctch ) |
| r25360 | r25361 | |
|---|---|---|
| 626 | 626 | public: |
| 627 | 627 | taitotz_renderer(taitotz_state &state, int width, int height, UINT32 *texram) |
| 628 | 628 | : poly_manager<float, taitotz_polydata, 6, 50000>(state.machine()), |
| 629 | | |
| 629 | m_state(state) | |
| 630 | 630 | { |
| 631 | 631 | m_zbuffer = auto_bitmap_ind32_alloc(state.machine(), width, height); |
| 632 | 632 | m_texture = texram; |
| r25360 | r25361 | |
|---|---|---|
| 174 | 174 | MCFG_CPU_ADD("maincpu", Z80, CPU_CLOCK) |
| 175 | 175 | MCFG_CPU_PROGRAM_MAP(memmap) |
| 176 | 176 | MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", mustache_state, mustache_scanline, "screen", 0, 1) |
| 177 | ||
| 177 | ||
| 178 | 178 | MCFG_T5182_ADD("t5182") |
| 179 | 179 | MCFG_FRAGMENT_ADD(t5182) |
| 180 | 180 | |
| r25360 | r25361 | |
| 192 | 192 | |
| 193 | 193 | /* sound hardware */ |
| 194 | 194 | MCFG_SEIBU_SOUND_ADD("seibu_sound") // for seibu_sound_decrypt on the MAIN cpu (not sound) |
| 195 | ||
| 195 | ||
| 196 | 196 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 197 | ||
| 197 | ||
| 198 | 198 | MCFG_YM2151_ADD("ymsnd", YM_CLOCK) |
| 199 | 199 | MCFG_YM2151_IRQ_HANDLER(DEVWRITELINE("t5182", t5182_device, ym2151_irq_handler)) |
| 200 | 200 | MCFG_SOUND_ROUTE(0, "mono", 1.0) |
| r25360 | r25361 | |
|---|---|---|
| 198 | 198 | MCFG_CPU_PROGRAM_MAP(main_map) |
| 199 | 199 | |
| 200 | 200 | MCFG_MACHINE_RESET_OVERRIDE(toobin_state,toobin) |
| 201 | ||
| 201 | ||
| 202 | 202 | MCFG_ATARI_EEPROM_2804_ADD("eeprom") |
| 203 | ||
| 203 | ||
| 204 | 204 | MCFG_WATCHDOG_VBLANK_INIT(8) |
| 205 | 205 | |
| 206 | 206 | /* video hardware */ |
| r25360 | r25361 | |
|---|---|---|
| 62 | 62 | #include "includes/ddragon.h" |
| 63 | 63 | |
| 64 | 64 | |
| 65 | #define MAIN_CLOCK XTAL_12MHz | |
| 66 | #define SOUND_CLOCK XTAL_3_579545MHz | |
| 67 | #define MCU_CLOCK MAIN_CLOCK / 3 | |
| 68 | #define PIXEL_CLOCK MAIN_CLOCK / 2 | |
| 65 | #define MAIN_CLOCK XTAL_12MHz | |
| 66 | #define SOUND_CLOCK XTAL_3_579545MHz | |
| 67 | #define MCU_CLOCK MAIN_CLOCK / 3 | |
| 68 | #define PIXEL_CLOCK MAIN_CLOCK / 2 | |
| 69 | 69 | |
| 70 | 70 | |
| 71 | 71 | /************************************* |
| r25360 | r25361 | |
| 164 | 164 | WRITE8_MEMBER(ddragon_state::ddragon_bankswitch_w) |
| 165 | 165 | { |
| 166 | 166 | /* |
| 167 | 76543210 | |
| 168 | .......x X-scroll D9 (H9BT) | |
| 169 | ......x. Y-scroll D9 (V9BT) | |
| 170 | .....x.. /Screen flip (*1P/2P) | |
| 171 | ....x... /Sub CPU reset (*RESET) | |
| 172 | ...x.... /Sub CPU halt (*HALT) | |
| 173 | xxx..... ROM bank (*BANK) | |
| 167 | 76543210 | |
| 168 | .......x X-scroll D9 (H9BT) | |
| 169 | ......x. Y-scroll D9 (V9BT) | |
| 170 | .....x.. /Screen flip (*1P/2P) | |
| 171 | ....x... /Sub CPU reset (*RESET) | |
| 172 | ...x.... /Sub CPU halt (*HALT) | |
| 173 | xxx..... ROM bank (*BANK) | |
| 174 | 174 | */ |
| 175 | 175 | m_scrollx_hi = data & 0x01; |
| 176 | 176 | m_scrolly_hi = (data & 0x02) >> 1; |
| r25360 | r25361 | |
| 1682 | 1682 | ROM_LOAD( "26j7-0.bin", 0x20000, 0x20000, CRC(bc6a48d5) SHA1(04c434f8cd42a8f82a263548183569396f9b684d) ) |
| 1683 | 1683 | |
| 1684 | 1684 | ROM_REGION( 0x0200, "proms", 0 ) |
| 1685 | ROM_LOAD( "prom.16", 0x0000, 0x0200, CRC(46339529) SHA1(64f4c42a826d67b7cbaa8a23a45ebc4eb6248891) ) /* sprite timing (same as ddragon) */ | |
| 1685 | ROM_LOAD( "prom.16", 0x0000, 0x0200, CRC(46339529) SHA1(64f4c42a826d67b7cbaa8a23a45ebc4eb6248891) ) /* sprite timing (same as ddragon) */ | |
| 1686 | 1686 | ROM_END |
| 1687 | 1687 | |
| 1688 | 1688 | ROM_START( ddragon2u ) |
| r25360 | r25361 | |
|---|---|---|
| 32 | 32 | Sound: AY-3-8910 |
| 33 | 33 | RAM: AMD AM9128-15PC (2048x8 Static RAM) |
| 34 | 34 | OSC: 10.000MHz |
| 35 | Video: F6845P (or H6845P also labeled as HD46505RP) 40 pin dil (8 bit CRT Controller) | |
| 35 | Video: F6845P (or H6845P also labeled as HD46505RP) 40 pin dil (8 bit CRT Controller) | |
| 36 | 36 | Misc: RCA X (CDM6116E2) 24 pin dil (General-Purpose Static RAM - Multiplexed I/O) |
| 37 | 37 | Roms: u7f lat green - type 2764 |
| 38 | 38 | u6f lat green - type 2764 |
| r25360 | r25361 | |
|---|---|---|
| 68 | 68 | 3x trimmer |
| 69 | 69 | |
| 70 | 70 | |
| 71 | TODO: Convert to stock i8279 implementation, as currently inputs aren't read. | |
| 72 | Fix meter reading (possibly related to above) | |
| 71 | TODO: Convert to stock i8279 implementation, as currently inputs aren't read. | |
| 72 | Fix meter reading (possibly related to above) | |
| 73 | 73 | ******************************************************************************************/ |
| 74 | 74 | #include "emu.h" |
| 75 | 75 | #include "includes/maygay1b.h" |
| r25360 | r25361 | |
| 741 | 741 | int i; |
| 742 | 742 | for (i=0; i<8; i++) |
| 743 | 743 | { |
| 744 | if ( data & (1 << i) ) | |
| 744 | if ( data & (1 << i) ) | |
| 745 | 745 | { |
| 746 | 746 | MechMtr_update(i, data & (1 << i) ); |
| 747 | 747 | m_meter = data; |
| r25360 | r25361 | |
| 804 | 804 | { |
| 805 | 805 | //ay8910_device *ay8910 = machine().device<ay8910_device>("aysnd"); |
| 806 | 806 | //return ay8910->data_r(space, offset); |
| 807 | ||
| 807 | ||
| 808 | 808 | //TODO: Game should read the meter state through Port A of the AY chip, but our timings aren't good enough (?) |
| 809 | 809 | return m_meter; |
| 810 | 810 | } |
| r25360 | r25361 | |
|---|---|---|
| 61 | 61 | | 6116 6116 G003K5.U63 |------| | |
| 62 | 62 | |--------------------------------------------------------------------| |
| 63 | 63 | Notes: |
| 64 | * - These ROMs not populated. Korean-specific ROMs have a K as part of the label text | |
| 65 | 68000 - Clock 13.500MHz [27/2] | |
| 66 | M6295 - Clock 2.000MHz [16/8]. Pin 7 HIGH | |
| 67 | V-080D - Custom Kaneko RGB DAC | |
| 68 | MC-1091 - Custom Kaneko I/O module | |
| 69 | LFP-6K - Custom Kaneko sound filter/DAC | |
| 70 | PX4460 - Custom Kaneko sound filter/DAC | |
| 71 | PISCES - NEC uPD78324 series MCU with 32k internal rom. Clock 13.500MHz [27/2] on pins 51 & 52 | |
| 72 | VSync - 59.1856Hz | |
| 73 | HSync - 15.625kHz | |
| 64 | * - These ROMs not populated. Korean-specific ROMs have a K as part of the label text | |
| 65 | 68000 - Clock 13.500MHz [27/2] | |
| 66 | M6295 - Clock 2.000MHz [16/8]. Pin 7 HIGH | |
| 67 | V-080D - Custom Kaneko RGB DAC | |
| 68 | MC-1091 - Custom Kaneko I/O module | |
| 69 | LFP-6K - Custom Kaneko sound filter/DAC | |
| 70 | PX4460 - Custom Kaneko sound filter/DAC | |
| 71 | PISCES - NEC uPD78324 series MCU with 32k internal rom. Clock 13.500MHz [27/2] on pins 51 & 52 | |
| 72 | VSync - 59.1856Hz | |
| 73 | HSync - 15.625kHz | |
| 74 | 74 | |
| 75 | 75 | ***************************************************************************/ |
| 76 | 76 | |
| r25360 | r25361 | |
| 426 | 426 | |
| 427 | 427 | static INPUT_PORTS_START( galpani2 ) |
| 428 | 428 | PORT_START("DSW1_P1") /* 780000.w */ |
| 429 | PORT_DIPNAME( 0x0007, 0x0007, DEF_STR( Difficulty ) ) | |
| 429 | PORT_DIPNAME( 0x0007, 0x0007, DEF_STR( Difficulty ) ) PORT_DIPLOCATION("SW B:8,7,6") | |
| 430 | 430 | PORT_DIPSETTING( 0x0007, DEF_STR( Normal ) ) |
| 431 | 431 | PORT_DIPSETTING( 0x0006, DEF_STR( Very_Easy ) ) |
| 432 | 432 | PORT_DIPSETTING( 0x0005, DEF_STR( Easy ) ) |
| r25360 | r25361 | |
| 435 | 435 | PORT_DIPSETTING( 0x0002, DEF_STR( Very_Hard ) ) |
| 436 | 436 | PORT_DIPSETTING( 0x0001, "Ultra Hard" ) |
| 437 | 437 | PORT_DIPSETTING( 0x0000, "God Hands" ) |
| 438 | PORT_DIPNAME( 0x0008, 0x0008, "Picture Mode" ) | |
| 438 | PORT_DIPNAME( 0x0008, 0x0008, "Picture Mode" ) PORT_DIPLOCATION("SW B:5") | |
| 439 | 439 | PORT_DIPSETTING( 0x0008, DEF_STR( Normal ) ) |
| 440 | 440 | PORT_DIPSETTING( 0x0000, "Adult" ) |
| 441 | PORT_DIPNAME( 0x0030, 0x0030, DEF_STR( Lives ) ) | |
| 441 | PORT_DIPNAME( 0x0030, 0x0030, DEF_STR( Lives ) ) PORT_DIPLOCATION("SW B:4,3") | |
| 442 | 442 | PORT_DIPSETTING( 0x0030, "3" ) |
| 443 | 443 | PORT_DIPSETTING( 0x0020, "1" ) |
| 444 | 444 | PORT_DIPSETTING( 0x0010, "4" ) |
| 445 | 445 | PORT_DIPSETTING( 0x0000, "5" ) |
| 446 | PORT_DIPNAME( 0x00c0, 0x00c0, "Max Unit of Players" ) | |
| 446 | PORT_DIPNAME( 0x00c0, 0x00c0, "Max Unit of Players" ) PORT_DIPLOCATION("SW B:2,1") | |
| 447 | 447 | PORT_DIPSETTING( 0x00c0, "9" ) |
| 448 | 448 | PORT_DIPSETTING( 0x0080, "1" ) |
| 449 | 449 | PORT_DIPSETTING( 0x0040, "4" ) |
| r25360 | r25361 | |
| 459 | 459 | PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(1) |
| 460 | 460 | |
| 461 | 461 | PORT_START("DSW2_P2") /* 780002.w */ |
| 462 | PORT_DIPNAME( 0x000f, 0x000f, DEF_STR( Coinage ) ) | |
| 462 | PORT_DIPNAME( 0x000f, 0x000f, DEF_STR( Coinage ) ) PORT_DIPLOCATION("SW A:8,7,6,5") | |
| 463 | 463 | PORT_DIPSETTING( 0x000f, "1 Coin/1 Credit 1/1" ) |
| 464 | 464 | PORT_DIPSETTING( 0x000e, "2 Coin/1 Credit 2/1" ) |
| 465 | 465 | PORT_DIPSETTING( 0x000d, "3 Coin/1 Credit 3/1" ) |
| r25360 | r25361 | |
| 476 | 476 | PORT_DIPSETTING( 0x0002, "1 Coin/2 Credit 1/2" ) |
| 477 | 477 | PORT_DIPSETTING( 0x0001, "1 Coin/3 Credit 1/3" ) |
| 478 | 478 | PORT_DIPSETTING( 0x0000, DEF_STR( Free_Play ) ) |
| 479 | PORT_DIPNAME( 0x0010, 0x0010, "Card Dispenser" ) | |
| 479 | PORT_DIPNAME( 0x0010, 0x0010, "Card Dispenser" ) PORT_DIPLOCATION("SW A:4") | |
| 480 | 480 | PORT_DIPSETTING( 0x0010, "Used" ) |
| 481 | 481 | PORT_DIPSETTING( 0x0000, DEF_STR( Unused ) ) |
| 482 | PORT_DIPNAME( 0x0020, 0x0020, DEF_STR( Flip_Screen ) ) | |
| 482 | PORT_DIPNAME( 0x0020, 0x0020, DEF_STR( Flip_Screen ) ) PORT_DIPLOCATION("SW A:3") | |
| 483 | 483 | PORT_DIPSETTING( 0x0020, DEF_STR( Off ) ) |
| 484 | 484 | PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) |
| 485 | PORT_DIPNAME( 0x0040, 0x0040, DEF_STR( Demo_Sounds ) ) | |
| 485 | PORT_DIPNAME( 0x0040, 0x0040, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW A:2") | |
| 486 | 486 | PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) |
| 487 | 487 | PORT_DIPSETTING( 0x0040, DEF_STR( On ) ) |
| 488 | 488 | PORT_SERVICE_DIPLOC( 0x0080, IP_ACTIVE_LOW, "SW A:1" ) |
| r25360 | r25361 | |
| 528 | 528 | PORT_DIPUNUSED_DIPLOC( 0x0008, IP_ACTIVE_LOW, "SW B:5" ) // picture mode is "normal fix" and cannot be changed |
| 529 | 529 | |
| 530 | 530 | PORT_MODIFY("DSW2_P2") /* 780002.w */ |
| 531 | PORT_DIPNAME( 0x0010, 0x0010, "Card Dispenser" ) | |
| 531 | PORT_DIPNAME( 0x0010, 0x0010, "Card Dispenser" ) PORT_DIPLOCATION("SW A:4") // Reversed compared to other sets. | |
| 532 | 532 | PORT_DIPSETTING( 0x0000, "Used" ) |
| 533 | 533 | PORT_DIPSETTING( 0x0010, DEF_STR( Unused ) ) |
| 534 | 534 |
| r25360 | r25361 | |
|---|---|---|
| 5538 | 5538 | ROM3 429D |
| 5539 | 5539 | ROM4 AA27 |
| 5540 | 5540 | ROM5 C409 |
| 5541 | ROM6 59B6 | |
| 5541 | ROM6 59B6 | |
| 5542 | 5542 | |
| 5543 | 5543 | Note: ROM5 & ROM6 graphics roms were updated at some point to correct the misspelling of |
| 5544 | 5544 | POINT on the play field, currently it's "PONIT". Theses are currently undumped. |
| r25360 | r25361 | |
|---|---|---|
| 583 | 583 | int i; |
| 584 | 584 | |
| 585 | 585 | m_maincpu->set_irq_acknowledge_callback(device_irq_acknowledge_delegate(FUNC(crystal_state::icallback),this)); |
| 586 | ||
| 586 | ||
| 587 | 587 | for (i = 0; i < 4; i++) |
| 588 | 588 | m_Timer[i] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(crystal_state::Timercb),this), (void*)(FPTR)i); |
| 589 | 589 |
| r25360 | r25361 | |
|---|---|---|
| 796 | 796 | ROM_LOAD16_BYTE( "iscr7.06", 0x400001, 0x80000, CRC(2dee0c31) SHA1(1097006e6e5d16b24fb71615b6c0754fe0ecbe33) ) |
| 797 | 797 | |
| 798 | 798 | ROM_REGION( 0x80000, "gfx1", 0 ) /* sprites */ |
| 799 | ||
| 799 | ROM_LOAD( "nf95obj1.13", 0x00000, 0x80000, CRC(e6d1bc71) SHA1(df0b6c1742c01991196659bab2691230323e7b8d) ) | |
| 800 | 800 | |
| 801 | 801 | ROM_REGION( 0x140000, "oki", 0 ) /* OKIM6295 samples */ |
| 802 | 802 | /* 00000-2ffff is fixed, 30000-3ffff is bank switched from all the ROMs */ |
| r25360 | r25361 | |
| 806 | 806 | ROM_END |
| 807 | 807 | |
| 808 | 808 | ROM_START( newfanta ) |
| 809 | ROM_REGION( 0x500000, "maincpu", 0 ) /* 68000 code */ | |
| 810 | ROM_LOAD16_BYTE( "prog2.12", 0x000000, 0x80000, CRC(de43a457) SHA1(91db13f63b46146131c58e775119ea3b073ca409) ) | |
| 811 | ROM_LOAD16_BYTE( "prog1.07", 0x000001, 0x80000, CRC(370b45be) SHA1(775873df9d3af803dbd1a392a45cad5f37b1b1c7) ) | |
| 812 | ROM_LOAD16_BYTE( "iscr2.10", 0x100000, 0x80000, CRC(4f2da2eb) SHA1(4f0b72327d1bdfad24d822953f45218bfae29cff) ) | |
| 813 | ROM_LOAD16_BYTE( "iscr1.05", 0x100001, 0x80000, CRC(63c6894f) SHA1(213544da570a167f3411357308c576805f6882f3) ) | |
| 814 | ROM_LOAD16_BYTE( "iscr4.09", 0x200000, 0x80000, CRC(725741ec) SHA1(3455cf0aed9653c66b8b2f905ad683687d517419) ) | |
| 815 | ROM_LOAD16_BYTE( "iscr3.04", 0x200001, 0x80000, CRC(51d6b362) SHA1(bcd57643ac9d79c150714ec6b6a2bb8a24acf7a5) ) | |
| 816 | ROM_LOAD16_BYTE( "iscr6.08", 0x300000, 0x80000, CRC(178b2ef3) SHA1(d3c092a282278968a319e06731481570f217d404) ) | |
| 817 | ROM_LOAD16_BYTE( "iscr5.03", 0x300001, 0x80000, CRC(d2b5c5fa) SHA1(80fde69bc5f4e958b5d57a5179b6e601192780f4) ) | |
| 818 | ROM_LOAD16_BYTE( "iscr8.11", 0x400000, 0x80000, CRC(f4148528) SHA1(4e27fff0b7ead068a159b3ed80c5793a6166fc4e) ) | |
| 819 | ROM_LOAD16_BYTE( "iscr7.06", 0x400001, 0x80000, CRC(2dee0c31) SHA1(1097006e6e5d16b24fb71615b6c0754fe0ecbe33) ) | |
| 809 | ROM_REGION( 0x500000, "maincpu", 0 ) /* 68000 code */ | |
| 810 | ROM_LOAD16_BYTE( "prog2.12", 0x000000, 0x80000, CRC(de43a457) SHA1(91db13f63b46146131c58e775119ea3b073ca409) ) | |
| 811 | ROM_LOAD16_BYTE( "prog1.07", 0x000001, 0x80000, CRC(370b45be) SHA1(775873df9d3af803dbd1a392a45cad5f37b1b1c7) ) | |
| 812 | ROM_LOAD16_BYTE( "iscr2.10", 0x100000, 0x80000, CRC(4f2da2eb) SHA1(4f0b72327d1bdfad24d822953f45218bfae29cff) ) | |
| 813 | ROM_LOAD16_BYTE( "iscr1.05", 0x100001, 0x80000, CRC(63c6894f) SHA1(213544da570a167f3411357308c576805f6882f3) ) | |
| 814 | ROM_LOAD16_BYTE( "iscr4.09", 0x200000, 0x80000, CRC(725741ec) SHA1(3455cf0aed9653c66b8b2f905ad683687d517419) ) | |
| 815 | ROM_LOAD16_BYTE( "iscr3.04", 0x200001, 0x80000, CRC(51d6b362) SHA1(bcd57643ac9d79c150714ec6b6a2bb8a24acf7a5) ) | |
| 816 | ROM_LOAD16_BYTE( "iscr6.08", 0x300000, 0x80000, CRC(178b2ef3) SHA1(d3c092a282278968a319e06731481570f217d404) ) | |
| 817 | ROM_LOAD16_BYTE( "iscr5.03", 0x300001, 0x80000, CRC(d2b5c5fa) SHA1(80fde69bc5f4e958b5d57a5179b6e601192780f4) ) | |
| 818 | ROM_LOAD16_BYTE( "iscr8.11", 0x400000, 0x80000, CRC(f4148528) SHA1(4e27fff0b7ead068a159b3ed80c5793a6166fc4e) ) | |
| 819 | ROM_LOAD16_BYTE( "iscr7.06", 0x400001, 0x80000, CRC(2dee0c31) SHA1(1097006e6e5d16b24fb71615b6c0754fe0ecbe33) ) | |
| 820 | 820 | |
| 821 | ||
| 821 | ROM_REGION( 0x80000, "gfx1", 0 ) /* sprites */ | |
| 822 | 822 | ROM_LOAD( "obj1.13", 0x00000, 0x80000, CRC(832cd451) SHA1(29dfab1d4b7a15f3fe9fbedef41d405a40235a77) ) |
| 823 | 823 | |
| 824 | ROM_REGION( 0x140000, "oki", 0 ) /* OKIM6295 samples */ | |
| 825 | /* 00000-2ffff is fixed, 30000-3ffff is bank switched from all the ROMs */ | |
| 826 | ROM_LOAD( "musc1.01", 0x00000, 0x80000, CRC(10347fce) SHA1(f5fbe8ef363fe18b7104be5d2fa92943d1a5d7a2) ) | |
| 827 | ROM_RELOAD( 0x40000, 0x80000 ) | |
| 828 | ROM_LOAD( "musc2.02", 0xc0000, 0x80000, CRC(b9646a8c) SHA1(e9432261ac86e4251a2c97301c6d014c05110a9c) ) | |
| 824 | ROM_REGION( 0x140000, "oki", 0 ) /* OKIM6295 samples */ | |
| 825 | /* 00000-2ffff is fixed, 30000-3ffff is bank switched from all the ROMs */ | |
| 826 | ROM_LOAD( "musc1.01", 0x00000, 0x80000, CRC(10347fce) SHA1(f5fbe8ef363fe18b7104be5d2fa92943d1a5d7a2) ) | |
| 827 | ROM_RELOAD( 0x40000, 0x80000 ) | |
| 828 | ROM_LOAD( "musc2.02", 0xc0000, 0x80000, CRC(b9646a8c) SHA1(e9432261ac86e4251a2c97301c6d014c05110a9c) ) | |
| 829 | 829 | ROM_END |
| 830 | 830 | |
| 831 | 831 | ROM_START( missw96 ) |
| r25360 | r25361 | |
|---|---|---|
| 390 | 390 | MCFG_QUANTUM_TIME(attotime::from_hz(6000)) |
| 391 | 391 | |
| 392 | 392 | MCFG_MACHINE_RESET_OVERRIDE(eprom_state,eprom) |
| 393 | ||
| 393 | ||
| 394 | 394 | MCFG_ATARI_EEPROM_2804_ADD("eeprom") |
| 395 | 395 | |
| 396 | 396 | /* video hardware */ |
| r25360 | r25361 | |
| 430 | 430 | MCFG_QUANTUM_TIME(attotime::from_hz(600)) |
| 431 | 431 | |
| 432 | 432 | MCFG_MACHINE_RESET_OVERRIDE(eprom_state,eprom) |
| 433 | ||
| 433 | ||
| 434 | 434 | MCFG_ATARI_EEPROM_2804_ADD("eeprom") |
| 435 | 435 | |
| 436 | 436 | /* video hardware */ |
| r25360 | r25361 | |
| 469 | 469 | MCFG_QUANTUM_TIME(attotime::from_hz(600)) |
| 470 | 470 | |
| 471 | 471 | MCFG_MACHINE_RESET_OVERRIDE(eprom_state,eprom) |
| 472 | ||
| 472 | ||
| 473 | 473 | MCFG_ATARI_EEPROM_2804_ADD("eeprom") |
| 474 | 474 | |
| 475 | 475 | /* video hardware */ |
| r25360 | r25361 | |
|---|---|---|
| 215 | 215 | AM_RANGE(0x04800, 0x05fff) AM_RAM |
| 216 | 216 | AM_RANGE(0x06000, 0x06fff) AM_WRITEONLY AM_SHARE("char_gfx_ram") |
| 217 | 217 | AM_RANGE(0x0a000, 0x0bfff) AM_WRITE(sprite_gfx_w) |
| 218 | // | |
| 218 | // AM_RANGE(0x0fffe, 0x0ffff) AM_WRITENOP | |
| 219 | 219 | |
| 220 | // | |
| 220 | // AM_RANGE(0x0c000, 0x0dfff) // is this the sound waveforms in a different format? | |
| 221 | 221 | AM_RANGE(0x07000, 0x0717f) AM_WRITE(sprite_ram_w) |
| 222 | 222 | |
| 223 | // | |
| 223 | // AM_RANGE(0x00000, 0x3ffff) AM_DEVREADWRITE("flash", sst_39vf020_device, read, write ) // (always fall through if nothing else is mapped?) | |
| 224 | 224 | |
| 225 | 225 | ADDRESS_MAP_END |
| 226 | 226 | |
| r25360 | r25361 | |
| 255 | 255 | return 0xff; |
| 256 | 256 | } |
| 257 | 257 | |
| 258 | ||
| 258 | static ADDRESS_MAP_START( 25pacman_io_map, AS_IO, 8, _25pacman_state ) | |
| 259 | 259 | ADDRESS_MAP_GLOBAL_MASK(0xff) |
| 260 | 260 | AM_RANGE(0x00, 0x3f) AM_NOP /* Z180 internal registers */ |
| 261 | 261 | AM_RANGE(0x40, 0x7f) AM_NOP /* Z180 internal registers */ |
| r25360 | r25361 | |
| 265 | 265 | AM_RANGE(0x80, 0x80) AM_WRITE(watchdog_reset_w) |
| 266 | 266 | AM_RANGE(0x81, 0x81) AM_WRITE(timer_pulse_w) /* ??? pulsed by the timer irq */ |
| 267 | 267 | AM_RANGE(0x82, 0x82) AM_WRITE(irqack_w) |
| 268 | // | |
| 268 | // AM_RANGE(0x84, 0x84) AM_NOP /* ?? */ | |
| 269 | 269 | AM_RANGE(0x85, 0x86) AM_WRITEONLY AM_SHARE("stars_seed") /* stars: rng seed (lo/hi) */ |
| 270 | 270 | AM_RANGE(0x87, 0x87) AM_READ( _25pacman_io_87_r ) // not eeprom on this |
| 271 | 271 | AM_RANGE(0x88, 0x88) AM_WRITE(ram_bank_select_w) |
| r25360 | r25361 | |
| 339 | 339 | |
| 340 | 340 | PORT_START( "EEPROMOUT" ) |
| 341 | 341 | PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_93cxx_device, cs_write) /* bit 5 is cs (active high) */ |
| 342 | PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_93cxx_device, clk_write) | |
| 342 | PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_93cxx_device, clk_write) /* bit 6 is clock (active high) */ | |
| 343 | 343 | PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_93cxx_device, di_write) /* bit 7 is data */ |
| 344 | 344 | INPUT_PORTS_END |
| 345 | 345 | |
| r25360 | r25361 | |
| 449 | 449 | // guzuta v2.2 PCB |
| 450 | 450 | // this uses the main FLASH rom to save things instead of eeprom (type is AM29LV20) |
| 451 | 451 | // different memory map.. no palette rom |
| 452 | ROM_START( 25pacman ) /* Revision 3.00 */ | |
| 452 | ROM_START( 25pacman ) /* Revision 3.00 */ | |
| 453 | 453 | ROM_REGION( 0x40000, "flash", 0 ) |
| 454 | 454 | ROM_LOAD( "pacman25ver3.u1", 0x00000, 0x40000, CRC(55b0076e) SHA1(4544cc193bdd22bfc88d096083ccc4069cac4607) ) /* program says Rev 3.00 */ |
| 455 | 455 | ROM_REGION( 0x100000, "maincpu", ROMREGION_ERASE00 ) |
| r25360 | r25361 | |
|---|---|---|
| 92 | 92 | |
| 93 | 93 | switch ( cs ) |
| 94 | 94 | { |
| 95 | ||
| 96 | 95 | case 2: |
| 97 | 96 | if ((addr & 0xf0) == 0xf0) |
| 98 | 97 | { |
| r25360 | r25361 | |
| 144 | 143 | |
| 145 | 144 | switch ( cs ) |
| 146 | 145 | { |
| 147 | ||
| 148 | 146 | case 2: |
| 149 | 147 | if ((addr & 0xf0) == 0xf0) |
| 150 | 148 | { |
| r25360 | r25361 | |
|---|---|---|
| 289 | 289 | DECLARE_MACHINE_RESET(hangplt); |
| 290 | 290 | DECLARE_VIDEO_START(gticlub); |
| 291 | 291 | INTERRUPT_GEN_MEMBER(gticlub_vblank); |
| 292 | ||
| 292 | ||
| 293 | 293 | UINT32 screen_update_gticlub(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); |
| 294 | 294 | UINT32 screen_update_hangplt(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); |
| 295 | 295 | |
| r25360 | r25361 | |
| 297 | 297 | virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); |
| 298 | 298 | private: |
| 299 | 299 | void gticlub_led_setreg(int offset, UINT8 data); |
| 300 | ||
| 301 | UINT8 gticlub_led_reg[2]; | |
| 300 | ||
| 301 | UINT8 gticlub_led_reg[2]; | |
| 302 | 302 | }; |
| 303 | 303 | |
| 304 | 304 |
| r25360 | r25361 | |
|---|---|---|
| 327 | 327 | MCFG_VIDEO_ATTRIBUTES(VIDEO_UPDATE_BEFORE_VBLANK) |
| 328 | 328 | MCFG_GFXDECODE(arcadecl) |
| 329 | 329 | MCFG_PALETTE_LENGTH(512) |
| 330 | ||
| 330 | ||
| 331 | 331 | MCFG_ATARI_MOTION_OBJECTS_ADD("mob", "screen", arcadecl_state::s_mob_config) |
| 332 | 332 | |
| 333 | 333 | MCFG_SCREEN_ADD("screen", RASTER) |
| r25360 | r25361 | |
| 348 | 348 | static MACHINE_CONFIG_DERIVED( sparkz, arcadecl ) |
| 349 | 349 | MCFG_DEVICE_REMOVE("mob") |
| 350 | 350 | MACHINE_CONFIG_END |
| 351 | ||
| 352 | 351 | |
| 353 | 352 | |
| 353 | ||
| 354 | 354 | /************************************* |
| 355 | 355 | * |
| 356 | 356 | * ROM definition(s) |
| r25360 | r25361 | |
|---|---|---|
| 537 | 537 | PORT_SERVICE( 0x08, IP_ACTIVE_LOW ) |
| 538 | 538 | |
| 539 | 539 | PORT_START("DSWA") |
| 540 | PORT_DIPNAME( 0x07, 0x07, DEF_STR( Coin_A ) ) | |
| 540 | PORT_DIPNAME( 0x07, 0x07, DEF_STR( Coin_A ) ) PORT_DIPLOCATION("SW1:1,2,3") | |
| 541 | 541 | PORT_DIPSETTING( 0x05, DEF_STR( 3C_1C ) ) |
| 542 | 542 | PORT_DIPSETTING( 0x03, DEF_STR( 2C_1C ) ) |
| 543 | 543 | PORT_DIPSETTING( 0x07, DEF_STR( 1C_1C ) ) |
| r25360 | r25361 | |
| 546 | 546 | PORT_DIPSETTING( 0x02, DEF_STR( 1C_3C ) ) |
| 547 | 547 | PORT_DIPSETTING( 0x00, DEF_STR( 1C_5C ) ) |
| 548 | 548 | PORT_DIPSETTING( 0x01, DEF_STR( 1C_6C ) ) |
| 549 | PORT_DIPNAME( 0x18, 0x18, DEF_STR( Coin_B ) ) | |
| 549 | PORT_DIPNAME( 0x18, 0x18, DEF_STR( Coin_B ) ) PORT_DIPLOCATION("SW1:4,5") | |
| 550 | 550 | PORT_DIPSETTING( 0x10, DEF_STR( 2C_1C ) ) |
| 551 | 551 | PORT_DIPSETTING( 0x18, DEF_STR( 1C_1C ) ) |
| 552 | 552 | PORT_DIPSETTING( 0x00, DEF_STR( 2C_3C ) ) |
| 553 | 553 | PORT_DIPSETTING( 0x08, DEF_STR( 1C_2C ) ) |
| 554 | PORT_DIPNAME( 0x60, 0x60, DEF_STR( Game_Time ) ) | |
| 554 | PORT_DIPNAME( 0x60, 0x60, DEF_STR( Game_Time ) ) PORT_DIPLOCATION("SW1:6,7") | |
| 555 | 555 | PORT_DIPSETTING( 0x60, "90 secs." ) |
| 556 | 556 | PORT_DIPSETTING( 0x20, "100 secs." ) |
| 557 | 557 | PORT_DIPSETTING( 0x40, "110 secs." ) |
| 558 | 558 | PORT_DIPSETTING( 0x00, "120 secs." ) |
| 559 | PORT_DIPNAME( 0x80, 0x80, "Racing Laps" ) | |
| 559 | PORT_DIPNAME( 0x80, 0x80, "Racing Laps" ) PORT_DIPLOCATION("SW1:8") | |
| 560 | 560 | PORT_DIPSETTING( 0x80, "3" ) /* Manufacturer's recommended settings for Upright cabinet */ |
| 561 | 561 | PORT_DIPSETTING( 0x00, "4" ) /* Manufacturer's recommended settings for Sit-Down cabinet */ |
| 562 | 562 | |
| r25360 | r25361 | |
| 564 | 564 | PORT_BIT( 0x0f, 0x00, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, polepos_state,high_port_r, "DSWA") |
| 565 | 565 | |
| 566 | 566 | PORT_START("DSWB") |
| 567 | PORT_DIPNAME( 0x07, 0x03, "Extended Rank" ) | |
| 567 | PORT_DIPNAME( 0x07, 0x03, "Extended Rank" ) PORT_DIPLOCATION("SW2:1,2,3") | |
| 568 | 568 | PORT_DIPSETTING( 0x07, "A" ) |
| 569 | 569 | PORT_DIPSETTING( 0x03, "B" ) |
| 570 | 570 | PORT_DIPSETTING( 0x05, "C" ) |
| r25360 | r25361 | |
| 573 | 573 | PORT_DIPSETTING( 0x02, "F" ) |
| 574 | 574 | PORT_DIPSETTING( 0x04, "G" ) |
| 575 | 575 | PORT_DIPSETTING( 0x00, "H" ) |
| 576 | PORT_DIPNAME( 0x38, 0x28, "Practice Rank" ) | |
| 576 | PORT_DIPNAME( 0x38, 0x28, "Practice Rank" ) PORT_DIPLOCATION("SW2:4,5,6") | |
| 577 | 577 | PORT_DIPSETTING( 0x38, "A" ) |
| 578 | 578 | PORT_DIPSETTING( 0x18, "B" ) |
| 579 | 579 | PORT_DIPSETTING( 0x28, "C" ) |
| r25360 | r25361 | |
| 582 | 582 | PORT_DIPSETTING( 0x10, "F" ) |
| 583 | 583 | PORT_DIPSETTING( 0x20, "G" ) |
| 584 | 584 | PORT_DIPSETTING( 0x00, "H" ) |
| 585 | PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) | |
| 585 | PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SW2:7") /* Is MPH or Km/H for "English" regions, but only Km/H for Japan ;-) */ | |
| 586 | 586 | PORT_DIPSETTING( 0x40, DEF_STR( Off) ) |
| 587 | 587 | PORT_DIPSETTING( 0x00, DEF_STR( On ) ) |
| 588 | PORT_DIPNAME( 0x80, 0x00, DEF_STR( Demo_Sounds ) ) | |
| 588 | PORT_DIPNAME( 0x80, 0x00, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW2:8") | |
| 589 | 589 | PORT_DIPSETTING( 0x80, DEF_STR( Off )) |
| 590 | 590 | PORT_DIPSETTING( 0x00, DEF_STR( On ) ) |
| 591 | 591 | |
| r25360 | r25361 | |
| 607 | 607 | PORT_INCLUDE( polepos ) |
| 608 | 608 | |
| 609 | 609 | PORT_MODIFY("DSWA") |
| 610 | PORT_DIPNAME( 0xe0, 0xe0, DEF_STR( Coin_A ) ) | |
| 610 | PORT_DIPNAME( 0xe0, 0xe0, DEF_STR( Coin_A ) ) PORT_DIPLOCATION("SW1:1,2,3") | |
| 611 | 611 | PORT_DIPSETTING( 0xc0, DEF_STR( 3C_1C ) ) |
| 612 | 612 | PORT_DIPSETTING( 0x20, DEF_STR( 2C_1C ) ) |
| 613 | 613 | PORT_DIPSETTING( 0x40, DEF_STR( 3C_2C ) ) |
| r25360 | r25361 | |
| 616 | 616 | PORT_DIPSETTING( 0x60, DEF_STR( 1C_2C ) ) |
| 617 | 617 | PORT_DIPSETTING( 0xa0, DEF_STR( 1C_3C ) ) |
| 618 | 618 | PORT_DIPSETTING( 0x00, DEF_STR( Free_Play ) ) |
| 619 | PORT_DIPNAME( 0x18, 0x18, DEF_STR( Coin_B ) ) | |
| 619 | PORT_DIPNAME( 0x18, 0x18, DEF_STR( Coin_B ) ) PORT_DIPLOCATION("SW1:4,5") | |
| 620 | 620 | PORT_DIPSETTING( 0x08, DEF_STR( 2C_1C ) ) |
| 621 | 621 | PORT_DIPSETTING( 0x10, DEF_STR( 3C_2C ) ) |
| 622 | 622 | PORT_DIPSETTING( 0x00, DEF_STR( 4C_3C ) ) |
| 623 | 623 | PORT_DIPSETTING( 0x18, DEF_STR( 1C_1C ) ) |
| 624 | PORT_DIPNAME( 0x06, 0x06, DEF_STR( Game_Time ) ) | |
| 624 | PORT_DIPNAME( 0x06, 0x06, DEF_STR( Game_Time ) ) PORT_DIPLOCATION("SW1:6,7") | |
| 625 | 625 | PORT_DIPSETTING( 0x06, "90 secs." ) |
| 626 | 626 | PORT_DIPSETTING( 0x02, "100 secs." ) |
| 627 | 627 | PORT_DIPSETTING( 0x04, "110 secs." ) |
| 628 | 628 | PORT_DIPSETTING( 0x00, "120 secs." ) |
| 629 | PORT_DIPNAME( 0x01, 0x01, "Racing Laps" ) | |
| 629 | PORT_DIPNAME( 0x01, 0x01, "Racing Laps" ) PORT_DIPLOCATION("SW1:8") | |
| 630 | 630 | PORT_DIPSETTING( 0x01, "3" ) /* Manufacturer's recommended settings for Upright cabinet */ |
| 631 | 631 | PORT_DIPSETTING( 0x00, "4" ) /* Manufacturer's recommended settings for Sit-Down cabinet */ |
| 632 | 632 | |
| 633 | 633 | PORT_MODIFY("DSWB") |
| 634 | PORT_DIPNAME( 0xe0, 0x60, "Practice Rank" ) | |
| 634 | PORT_DIPNAME( 0xe0, 0x60, "Practice Rank" ) PORT_DIPLOCATION("SW2:1,2,3") | |
| 635 | 635 | PORT_DIPSETTING( 0xe0, "A" ) |
| 636 | 636 | PORT_DIPSETTING( 0x60, "B" ) |
| 637 | 637 | PORT_DIPSETTING( 0xa0, "C" ) |
| r25360 | r25361 | |
| 640 | 640 | PORT_DIPSETTING( 0x40, "F" ) |
| 641 | 641 | PORT_DIPSETTING( 0x80, "G" ) |
| 642 | 642 | PORT_DIPSETTING( 0x00, "H" ) |
| 643 | PORT_DIPNAME( 0x1c, 0x14, "Extended Rank" ) | |
| 643 | PORT_DIPNAME( 0x1c, 0x14, "Extended Rank" ) PORT_DIPLOCATION("SW2:4,5,6") | |
| 644 | 644 | PORT_DIPSETTING( 0x1c, "A" ) |
| 645 | 645 | PORT_DIPSETTING( 0x0c, "B" ) |
| 646 | 646 | PORT_DIPSETTING( 0x14, "C" ) |
| r25360 | r25361 | |
| 649 | 649 | PORT_DIPSETTING( 0x08, "F" ) |
| 650 | 650 | PORT_DIPSETTING( 0x10, "G" ) |
| 651 | 651 | PORT_DIPSETTING( 0x00, "H" ) |
| 652 | PORT_DIPNAME( 0x02, 0x00, "Speed Unit" ) | |
| 652 | PORT_DIPNAME( 0x02, 0x00, "Speed Unit" ) PORT_DIPLOCATION("SW2:7") /* MPH as per Atari manuals for the US regions */ | |
| 653 | 653 | PORT_DIPSETTING( 0x00, "mph" ) |
| 654 | 654 | PORT_DIPSETTING( 0x02, "km/h" ) |
| 655 | PORT_DIPNAME( 0x01, 0x00, DEF_STR( Demo_Sounds ) ) | |
| 655 | PORT_DIPNAME( 0x01, 0x00, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW2:8") | |
| 656 | 656 | PORT_DIPSETTING( 0x01, DEF_STR( Off )) |
| 657 | 657 | PORT_DIPSETTING( 0x00, DEF_STR( On ) ) |
| 658 | 658 | INPUT_PORTS_END |
| r25360 | r25361 | |
| 746 | 746 | PORT_INCLUDE( polepos ) |
| 747 | 747 | |
| 748 | 748 | PORT_MODIFY("DSWA") |
| 749 | PORT_DIPNAME( 0xe0, 0xe0, DEF_STR( Coin_A ) ) | |
| 749 | PORT_DIPNAME( 0xe0, 0xe0, DEF_STR( Coin_A ) ) PORT_DIPLOCATION("SW1:1,2,3") | |
| 750 | 750 | PORT_DIPSETTING( 0xc0, DEF_STR( 3C_1C ) ) |
| 751 | 751 | PORT_DIPSETTING( 0x20, DEF_STR( 2C_1C ) ) |
| 752 | 752 | PORT_DIPSETTING( 0x40, DEF_STR( 3C_2C ) ) |
| r25360 | r25361 | |
| 755 | 755 | PORT_DIPSETTING( 0x60, DEF_STR( 1C_2C ) ) |
| 756 | 756 | PORT_DIPSETTING( 0xa0, DEF_STR( 1C_3C ) ) |
| 757 | 757 | PORT_DIPSETTING( 0x00, DEF_STR( Free_Play ) ) |
| 758 | PORT_DIPNAME( 0x18, 0x18, DEF_STR( Coin_B ) ) | |
| 758 | PORT_DIPNAME( 0x18, 0x18, DEF_STR( Coin_B ) ) PORT_DIPLOCATION("SW1:4,5") | |
| 759 | 759 | PORT_DIPSETTING( 0x08, DEF_STR( 2C_1C ) ) |
| 760 | 760 | PORT_DIPSETTING( 0x10, DEF_STR( 3C_2C ) ) |
| 761 | 761 | PORT_DIPSETTING( 0x00, DEF_STR( 4C_3C ) ) |
| 762 | 762 | PORT_DIPSETTING( 0x18, DEF_STR( 1C_1C ) ) |
| 763 | PORT_DIPNAME( 0x04, 0x00, "Speed Unit" ) | |
| 763 | PORT_DIPNAME( 0x04, 0x00, "Speed Unit" ) PORT_DIPLOCATION("SW1:6") /* Set defualt to MPH for "English" regions */ | |
| 764 | 764 | PORT_DIPSETTING( 0x00, "mph" ) |
| 765 | 765 | PORT_DIPSETTING( 0x04, "km/h" ) |
| 766 | PORT_DIPNAME( 0x02, 0x02, DEF_STR( Demo_Sounds ) ) | |
| 766 | PORT_DIPNAME( 0x02, 0x02, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW1:7") | |
| 767 | 767 | PORT_DIPSETTING( 0x00, DEF_STR( Off )) |
| 768 | 768 | PORT_DIPSETTING( 0x02, DEF_STR( On ) ) |
| 769 | PORT_DIPNAME( 0x01, 0x01, DEF_STR( Unknown ) ) | |
| 769 | PORT_DIPNAME( 0x01, 0x01, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SW1:8") /* docs say "freeze", but it doesn't seem to work */ | |
| 770 | 770 | PORT_DIPSETTING( 0x01, DEF_STR( Off )) |
| 771 | 771 | PORT_DIPSETTING( 0x00, DEF_STR( On ) ) |
| 772 | 772 | |
| 773 | 773 | PORT_MODIFY("DSWB") |
| 774 | PORT_DIPNAME( 0x80, 0x80, DEF_STR( Game_Time ) ) | |
| 774 | PORT_DIPNAME( 0x80, 0x80, DEF_STR( Game_Time ) ) PORT_DIPLOCATION("SW2:1") | |
| 775 | 775 | PORT_DIPSETTING( 0x80, "90 secs." ) |
| 776 | 776 | PORT_DIPSETTING( 0x00, "120 secs." ) |
| 777 | PORT_DIPNAME( 0x60, 0x60, "Practice Rank" ) | |
| 777 | PORT_DIPNAME( 0x60, 0x60, "Practice Rank" ) PORT_DIPLOCATION("SW2:2,3") | |
| 778 | 778 | PORT_DIPSETTING( 0x20, "A" ) |
| 779 | 779 | PORT_DIPSETTING( 0x60, "B" ) |
| 780 | 780 | PORT_DIPSETTING( 0x40, "C" ) |
| 781 | 781 | PORT_DIPSETTING( 0x00, "D" ) |
| 782 | PORT_DIPNAME( 0x18, 0x18, "Extended Rank" ) | |
| 782 | PORT_DIPNAME( 0x18, 0x18, "Extended Rank" ) PORT_DIPLOCATION("SW2:4,5") | |
| 783 | 783 | PORT_DIPSETTING( 0x08, "A" ) |
| 784 | 784 | PORT_DIPSETTING( 0x18, "B" ) |
| 785 | 785 | PORT_DIPSETTING( 0x10, "C" ) |
| 786 | 786 | PORT_DIPSETTING( 0x00, "D" ) |
| 787 | PORT_DIPNAME( 0x06, 0x06, "Goal" ) | |
| 787 | PORT_DIPNAME( 0x06, 0x06, "Goal" ) PORT_DIPLOCATION("SW2:6,7") | |
| 788 | 788 | PORT_DIPSETTING( 0x02, "3" ) |
| 789 | 789 | PORT_DIPSETTING( 0x06, "4" ) |
| 790 | 790 | PORT_DIPSETTING( 0x04, "5" ) |
| 791 | 791 | PORT_DIPSETTING( 0x00, "6" ) |
| 792 | PORT_DIPNAME( 0x01, 0x01, "Speed" ) | |
| 792 | PORT_DIPNAME( 0x01, 0x01, "Speed" ) PORT_DIPLOCATION("SW2:8") | |
| 793 | 793 | PORT_DIPSETTING( 0x01, "Average" ) |
| 794 | 794 | PORT_DIPSETTING( 0x00, DEF_STR( High ) ) |
| 795 | 795 | INPUT_PORTS_END |
| r25360 | r25361 | |
| 799 | 799 | PORT_INCLUDE( polepos2 ) |
| 800 | 800 | |
| 801 | 801 | PORT_MODIFY("DSWA") |
| 802 | PORT_DIPNAME( 0x04, 0x04, "Speed Unit" ) | |
| 802 | PORT_DIPNAME( 0x04, 0x04, "Speed Unit" ) PORT_DIPLOCATION("SW1:6") /* Set defualt to km/h for Japan */ | |
| 803 | 803 | PORT_DIPSETTING( 0x00, "mph" ) |
| 804 | 804 | PORT_DIPSETTING( 0x04, "km/h" ) |
| 805 | 805 | INPUT_PORTS_END |
| r25360 | r25361 | |
|---|---|---|
| 1501 | 1501 | static READ32_DEVICE_HANDLER( ethernet_r ) |
| 1502 | 1502 | { |
| 1503 | 1503 | smc91c94_device *ethernet = space.machine().device<smc91c94_device>("ethernet"); |
| 1504 | ||
| 1504 | ||
| 1505 | 1505 | UINT32 result = 0; |
| 1506 | 1506 | if (ACCESSING_BITS_0_15) |
| 1507 | 1507 | result |= ethernet->read(space, offset * 2 + 0, mem_mask); |
| r25360 | r25361 | |
| 1514 | 1514 | static WRITE32_DEVICE_HANDLER( ethernet_w ) |
| 1515 | 1515 | { |
| 1516 | 1516 | smc91c94_device *ethernet = space.machine().device<smc91c94_device>("ethernet"); |
| 1517 | ||
| 1517 | ||
| 1518 | 1518 | if (ACCESSING_BITS_0_15) |
| 1519 | 1519 | ethernet->write(space, offset * 2 + 0, data, mem_mask); |
| 1520 | 1520 | if (ACCESSING_BITS_16_31) |
| r25360 | r25361 | |
|---|---|---|
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | |
| 3 | ||
| 3 | Tap a Tune | |
| 4 | 4 | |
| 5 | 5 | driver by Mariusz Wojcieszek and Phil Bennett |
| 6 | 6 | |
| 7 | 7 | |
| 8 | ||
| 8 | PCB Notes: | |
| 9 | 9 | |
| 10 | ||
| 10 | Top board notable: | |
| 11 | 11 | |
| 12 | - Hitachi HD68HC000-12 68000 CPU (24 MHz crystal) | |
| 13 | - Hitachi HD46505SP-2 CRTC | |
| 14 | - 2x Sony CXK581000P-10L RAM | |
| 15 | - 2x Mosel MS6264L-10PC RAM | |
| 16 | - 2x Mosel MS62256L-10PC RAM | |
| 17 | - rom0.u3 / rom1.u12 - 68000 program | |
| 18 | - rom2.u4 / rom3.u13 / rom4.u5 / rom5.u14 - graphics | |
| 12 | - Hitachi HD68HC000-12 68000 CPU (24 MHz crystal) | |
| 13 | - Hitachi HD46505SP-2 CRTC | |
| 14 | - 2x Sony CXK581000P-10L RAM | |
| 15 | - 2x Mosel MS6264L-10PC RAM | |
| 16 | - 2x Mosel MS62256L-10PC RAM | |
| 17 | - rom0.u3 / rom1.u12 - 68000 program | |
| 18 | - rom2.u4 / rom3.u13 / rom4.u5 / rom5.u14 - graphics | |
| 19 | 19 | |
| 20 | ||
| 20 | Bottom board notable: | |
| 21 | 21 | |
| 22 | - Zilog Z0840006PSC Z80 CPU (24 MHz crystal) | |
| 23 | - BSMT2000 custom audio IC | |
| 24 | - rom.u8 Z80 program | |
| 25 | - arom1.u16 BSMT2000 samples | |
| 26 | - 2 banks of 8-position DIP switches | |
| 27 | - red/green/yellow LEDs | |
| 28 | - many connectors for I/O | |
| 22 | - Zilog Z0840006PSC Z80 CPU (24 MHz crystal) | |
| 23 | - BSMT2000 custom audio IC | |
| 24 | - rom.u8 Z80 program | |
| 25 | - arom1.u16 BSMT2000 samples | |
| 26 | - 2 banks of 8-position DIP switches | |
| 27 | - red/green/yellow LEDs | |
| 28 | - many connectors for I/O | |
| 29 | 29 | |
| 30 | The sound and I/O board is used by other redemption games such as | |
| 31 | Colorama and Wheel 'Em In | |
| 30 | The sound and I/O board is used by other redemption games such as | |
| 31 | Colorama and Wheel 'Em In | |
| 32 | 32 | |
| 33 | 33 | ****************************************************************************/ |
| 34 | 34 | |
| r25360 | r25361 | |
| 70 | 70 | UINT8 m_z80_to_68k_data; |
| 71 | 71 | UINT8 m_68k_to_z80_index; |
| 72 | 72 | UINT8 m_68k_to_z80_data; |
| 73 | UINT8 m_z80_data_available; | |
| 74 | UINT8 m_68k_data_available; | |
| 75 | UINT8 m_bsmt_data_l; | |
| 76 | UINT8 m_bsmt_data_h; | |
| 77 | bool m_bsmt_reset; | |
| 73 | UINT8 m_z80_data_available; | |
| 74 | UINT8 m_68k_data_available; | |
| 75 | UINT8 m_bsmt_data_l; | |
| 76 | UINT8 m_bsmt_data_h; | |
| 77 | bool m_bsmt_reset; | |
| 78 | 78 | |
| 79 | 79 | virtual void machine_start(); |
| 80 | 80 | virtual void machine_reset(); |
| r25360 | r25361 | |
| 330 | 330 | WRITE8_MEMBER(tapatune_state::controls_mux) |
| 331 | 331 | { |
| 332 | 332 | /* |
| 333 | | |
| 333 | Input multiplexer select and outputs: | |
| 334 | 334 | |
| 335 | 76543210 | |
| 336 | .......x Mux A | |
| 337 | ......x. Mux B (/Red LED) | |
| 338 | .....x.. Mux C (/Yellow LED) | |
| 339 | ....x... Mux D (/Green LED) | |
| 340 | ...x.... DOUT1 - High current driver 0 | |
| 341 | ..x..... DOUT2 - High current driver 1 | |
| 342 | .x...... DOUT3 - High current driver 2 | |
| 343 | x....... DOUT4 - Ticket dispenser | |
| 335 | 76543210 | |
| 336 | .......x Mux A | |
| 337 | ......x. Mux B (/Red LED) | |
| 338 | .....x.. Mux C (/Yellow LED) | |
| 339 | ....x... Mux D (/Green LED) | |
| 340 | ...x.... DOUT1 - High current driver 0 | |
| 341 | ..x..... DOUT2 - High current driver 1 | |
| 342 | .x...... DOUT3 - High current driver 2 | |
| 343 | x....... DOUT4 - Ticket dispenser | |
| 344 | 344 | */ |
| 345 | 345 | |
| 346 | 346 | m_controls_mux = data; |
| r25360 | r25361 | |
| 373 | 373 | WRITE8_MEMBER(tapatune_state::lamps_w) |
| 374 | 374 | { |
| 375 | 375 | /* |
| 376 | | |
| 376 | Button Lamps: | |
| 377 | 377 | |
| 378 | 7654 3210 | |
| 379 | .... ...x Pink | |
| 380 | .... ..x. Purple | |
| 381 | .... .x.. Blue | |
| 382 | .... x... Dark Green | |
| 383 | ...x .... Light Green | |
| 384 | ..x. .... Yellow | |
| 385 | .x.. .... Orange | |
| 386 | x... .... Red | |
| 378 | 7654 3210 | |
| 379 | .... ...x Pink | |
| 380 | .... ..x. Purple | |
| 381 | .... .x.. Blue | |
| 382 | .... x... Dark Green | |
| 383 | ...x .... Light Green | |
| 384 | ..x. .... Yellow | |
| 385 | .x.. .... Orange | |
| 386 | x... .... Red | |
| 387 | 387 | */ |
| 388 | 388 | } |
| 389 | 389 | |
| r25360 | r25361 | |
| 468 | 468 | PORT_DIPSETTING( 0x01, "35 secs" ) |
| 469 | 469 | PORT_DIPSETTING( 0x00, "40 secs" ) |
| 470 | 470 | PORT_DIPNAME( 0x18, 0x10, "Bad note penalty" ) PORT_DIPLOCATION("SW5:4,5") |
| 471 | PORT_DIPSETTING( 0x18, "0 secs" ) | |
| 472 | PORT_DIPSETTING( 0x10, "1 secs" ) | |
| 473 | PORT_DIPSETTING( 0x08, "5 secs" ) | |
| 474 | PORT_DIPSETTING( 0x00, "10 secs" ) | |
| 471 | PORT_DIPSETTING( 0x18, "0 secs" ) | |
| 472 | PORT_DIPSETTING( 0x10, "1 secs" ) | |
| 473 | PORT_DIPSETTING( 0x08, "5 secs" ) | |
| 474 | PORT_DIPSETTING( 0x00, "10 secs" ) | |
| 475 | 475 | PORT_DIPNAME( 0x20, 0x20, "Coins per game" ) PORT_DIPLOCATION("SW5:6") |
| 476 | 476 | PORT_DIPSETTING( 0x20, "1" ) |
| 477 | 477 | PORT_DIPSETTING( 0x00, "2" ) |
| r25360 | r25361 | |
|---|---|---|
| 284 | 284 | catacomb // 1982 MTM Games |
| 285 | 285 | ckongg // 1981 bootleg |
| 286 | 286 | ckongmc // 1981 bootleg |
| 287 | ckonggx | |
| 287 | ckonggx // | |
| 288 | 288 | ckongcv // 19?? Competitive Video? |
| 289 | ckongis | |
| 289 | ckongis // | |
| 290 | 290 | porter // 1982 bootleg (Arcade TV Game List - P.98, Left, 15 from bottom) |
| 291 | 291 | tdpgal // 1983 Design Labs / Thomas Automatics |
| 292 | 292 | guttangt |
| r25360 | r25361 | |
| 1095 | 1095 | |
| 1096 | 1096 | // Misc Namco games |
| 1097 | 1097 | 30test // (c) 1997 |
| 1098 | 25pacman | |
| 1098 | 25pacman // (c) 2006 Ver 3.0 | |
| 1099 | 1099 | 25pacmano // (c) 2005 Ver 2.0 - Same hardware as 20pacgal |
| 1100 | 1100 | 20pacgal // (c) 2000 Ver 1.08 |
| 1101 | 1101 | 20pacgalr4 // (c) 2000 Ver 1.04 |
| r25360 | r25361 | |
| 1107 | 1107 | |
| 1108 | 1108 | // Universal games |
| 1109 | 1109 | cosmicg // 7907 (c) 1979 |
| 1110 | cosmicgi | |
| 1110 | cosmicgi // bootleg (Inder) | |
| 1111 | 1111 | cosmica // 7910-AII (c) [1979] |
| 1112 | 1112 | cosmica1 // 7910-A (c) [1979] |
| 1113 | 1113 | cosmica2 // 7910 (c) 1979 |
| r25360 | r25361 | |
| 1345 | 1345 | multigm2 // 1992 |
| 1346 | 1346 | multigm3 // 19?? |
| 1347 | 1347 | multigmt |
| 1348 | sgmt1 | |
| 1348 | sgmt1 // 1994 | |
| 1349 | 1349 | supergm3 // 1996 |
| 1350 | 1350 | cham24 // 2002 |
| 1351 | 1351 | |
| r25360 | r25361 | |
| 2405 | 2405 | dariusgu // 1994.11 D87 (c) 1994 Taito America Corporation (US) |
| 2406 | 2406 | dariusgx // 1994.?? D87 (c) 1994 Taito Corporation |
| 2407 | 2407 | bublbob2 // 1994.?? D90 (c) 1994 Taito Corporation Japan (World) |
| 2408 | bublbob2p | |
| 2408 | bublbob2p // prototype | |
| 2409 | 2409 | bubsymphe // 1994.?? D90 (c) 1994 Taito Corporation Japan (Europe) |
| 2410 | 2410 | bubsymphu // 1994.10 D90 (c) 1994 Taito America Corporation (US) |
| 2411 | 2411 | bubsymphj // 1994.10 D90 (c) 1994 Taito Corporation (Japan) |
| r25360 | r25361 | |
| 2498 | 2498 | hotgmkmp // (c) 2005 XNauts |
| 2499 | 2499 | raiden3 // (c) 2005 Seibu Kaihatsu/Moss Ltd |
| 2500 | 2500 | spicaadv // (c) 2005 Taito Corporation |
| 2501 | usagiol | |
| 2501 | usagiol // (c) 2005 Taito Corporation/Warashi | |
| 2502 | 2502 | shikiga3 // (c) 2006 Alfa System/SKonec Entertainment |
| 2503 | 2503 | raiden4 // (c) 2007 Seibu Kaihatsu/Moss Ltd |
| 2504 | 2504 | kof98um // (c) 2008 SNK |
| r25360 | r25361 | |
| 5825 | 5825 | hvysmshj // MBG (c) 1993 Data East Corporation (Japan) |
| 5826 | 5826 | nslasher // MBH (c) 1993 Data East Corporation |
| 5827 | 5827 | nslasherj // MBH (c) 1993 Data East Corporation (Japan) |
| 5828 | nslashers // MBH (c) 1993 Data East Corporation | |
| 5829 | nslasheru // MBH (c) 1993 Data EAst Corporation (US) | |
| 5828 | nslashers // MBH (c) 1993 Data East Corporation | |
| 5829 | nslasheru // MBH (c) 1993 Data EAst Corporation (US) | |
| 5830 | 5830 | // MBI ?? |
| 5831 | 5831 | // MBJ ?? |
| 5832 | 5832 | // MBK ?? |
| r25360 | r25361 | |
| 9476 | 9476 | dmnfrntb // |
| 9477 | 9477 | dmnfrntpcb // |
| 9478 | 9478 | kovshp // (c) 2004 Knights of Valor Superheroes PLUS |
| 9479 | kovshpa // | |
| 9480 | kovytzy // (c) 1999 Knights of Valour: Yi Tong Zhong Yuan | |
| 9479 | kovshpa // | |
| 9480 | kovytzy // (c) 1999 Knights of Valour: Yi Tong Zhong Yuan | |
| 9481 | 9481 | kovshxas // bootleg |
| 9482 | 9482 | kovlsqh // bootleg |
| 9483 | 9483 | kovlsqh2 // bootleg |
| r25360 | r25361 | |
| 9495 | 9495 | ddpdoja // |
| 9496 | 9496 | ddpdojb // |
| 9497 | 9497 | ddpdojblk // |
| 9498 | ddpdojblka | |
| 9498 | ddpdojblka // | |
| 9499 | 9499 | espgal // (c) 2003 Espgaluda |
| 9500 | 9500 | |
| 9501 | 9501 | // IGS PGM2 Platform |
| r25360 | r25361 | |
| 11886 | 11886 | |
| 11887 | 11887 | // unknown |
| 11888 | 11888 | fruitpc // ??? |
| 11889 | casanova | |
| 11889 | casanova // | |
| 11890 | 11890 | |
| 11891 | 11891 | // Leisure Ent. |
| 11892 | 11892 | roul // (c) 1990 |
| r25360 | r25361 | |
|---|---|---|
| 177 | 177 | void t5182_device::device_start() |
| 178 | 178 | { |
| 179 | 179 | m_t5182_sharedram = reinterpret_cast<UINT8 *>(machine().root_device().memshare("t5182_sharedram")->ptr()); |
| 180 | ||
| 180 | ||
| 181 | 181 | save_pointer(NAME(m_t5182_sharedram), sizeof(UINT8)); |
| 182 | 182 | save_item(NAME(m_irqstate)); |
| 183 | 183 | save_item(NAME(m_semaphore_main)); |
| 184 | 184 | save_item(NAME(m_semaphore_snd)); |
| 185 | ||
| 185 | ||
| 186 | 186 | m_ourcpu = machine().device<cpu_device>("t5182_z80"); |
| 187 | 187 | } |
| 188 | 188 | |
| r25360 | r25361 | |
| 220 | 220 | m_irqstate &= ~2; |
| 221 | 221 | break; |
| 222 | 222 | } |
| 223 | ||
| 223 | ||
| 224 | 224 | if (m_ourcpu == NULL) |
| 225 | 225 | return; |
| 226 | 226 |
| r25360 | r25361 | |
|---|---|---|
| 32 | 32 | DECLARE_WRITE_LINE_MEMBER(ym2151_irq_handler); |
| 33 | 33 | DECLARE_WRITE8_MEMBER(ym2151_irq_ack_w); |
| 34 | 34 | DECLARE_WRITE8_MEMBER(cpu_irq_ack_w); |
| 35 | ||
| 35 | ||
| 36 | 36 | protected: |
| 37 | 37 | // device-level overrides |
| 38 | 38 | virtual void device_config_complete(); |
| r25360 | r25361 | |
| 45 | 45 | int m_irqstate; |
| 46 | 46 | int m_semaphore_main; |
| 47 | 47 | int m_semaphore_snd; |
| 48 | ||
| 48 | ||
| 49 | 49 | TIMER_CALLBACK_MEMBER( setirq_callback ); |
| 50 | 50 | }; |
| 51 | 51 |
| r25360 | r25361 | |
|---|---|---|
| 148 | 148 | { |
| 149 | 149 | running_machine &machine = device.machine(); |
| 150 | 150 | exidy_state *state = machine.driver_data<exidy_state>(); |
| 151 | ||
| 151 | ||
| 152 | 152 | state->common_audio_start(SPECTAR_MAXFREQ); |
| 153 | 153 | } |
| 154 | 154 | |
| r25360 | r25361 | |
| 157 | 157 | { |
| 158 | 158 | running_machine &machine = device.machine(); |
| 159 | 159 | exidy_state *state = machine.driver_data<exidy_state>(); |
| 160 | ||
| 160 | ||
| 161 | 161 | state->common_audio_start(TARG_MAXFREQ); |
| 162 | 162 | |
| 163 | 163 | state->m_tone_pointer = 0; |
| r25360 | r25361 | |
|---|---|---|
| 632 | 632 | case 0: |
| 633 | 633 | /* we have to return 0 periodically so that they handle interrupts */ |
| 634 | 634 | //if ((++m_clock_tick & 7) == 0) |
| 635 | // | |
| 635 | // return 0; | |
| 636 | 636 | |
| 637 | 637 | /* if we've filled up all the active channels, we can give this CPU a reset */ |
| 638 | 638 | /* until the next interrupt */ |
| r25360 | r25361 | |
|---|---|---|
| 411 | 411 | void galaxian_sound_device::device_start() |
| 412 | 412 | { |
| 413 | 413 | m_lfo_val = 0; |
| 414 | ||
| 414 | ||
| 415 | 415 | m_discrete = machine().device<discrete_device>(GAL_AUDIO); |
| 416 | ||
| 416 | ||
| 417 | 417 | save_item(NAME(m_lfo_val)); |
| 418 | 418 | } |
| 419 | 419 | |
| r25360 | r25361 | |
| 508 | 508 | |
| 509 | 509 | MCFG_SOUND_ADD("cust", GALAXIAN, 0) |
| 510 | 510 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.4) |
| 511 | ||
| 511 | ||
| 512 | 512 | MCFG_SOUND_ADD(GAL_AUDIO, DISCRETE, 0) |
| 513 | 513 | MCFG_SOUND_CONFIG_DISCRETE(galaxian) |
| 514 | 514 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0) |
| r25360 | r25361 | |
| 518 | 518 | |
| 519 | 519 | MCFG_SOUND_ADD("cust", GALAXIAN, 0) |
| 520 | 520 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.4) |
| 521 | ||
| 521 | ||
| 522 | 522 | MCFG_SOUND_ADD(GAL_AUDIO, DISCRETE, 0) |
| 523 | 523 | MCFG_SOUND_CONFIG_DISCRETE(mooncrst) |
| 524 | 524 |
| r25360 | r25361 | |
|---|---|---|
| 1 | 1 | /********************************************************************************************** |
| 2 | 2 | |
| 3 | Taito TC0140SYT | |
| 4 | ||
| 5 | TODO: | |
| 6 | - Add pinout and description | |
| 7 | - Create a separate implementation for the PC060HA | |
| 3 | Taito TC0140SYT | |
| 8 | 4 | |
| 5 | TODO: | |
| 6 | - Add pinout and description | |
| 7 | - Create a separate implementation for the PC060HA | |
| 8 | ||
| 9 | 9 | **********************************************************************************************/ |
| 10 | 10 | |
| 11 | 11 | #include "emu.h" |
| r25360 | r25361 | |
|---|---|---|
| 141 | 141 | *************************************/ |
| 142 | 142 | |
| 143 | 143 | //todo: hook up cpu/es5510 |
| 144 | ||
| 144 | ||
| 145 | 145 | READ16_MEMBER( taito_en_device::es5510_dsp_r ) |
| 146 | 146 | { |
| 147 | 147 | // logerror("%06x: DSP read offset %04x (data is %04x)\n",space.device().safe_pc(),offset,m_es5510_dsp_ram[offset]); |
| r25360 | r25361 | |
|---|---|---|
| 7 | 7 | public: |
| 8 | 8 | taito_en_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 9 | 9 | ~taito_en_device() {} |
| 10 | ||
| 10 | ||
| 11 | 11 | DECLARE_READ16_MEMBER( en_68000_share_r ); |
| 12 | 12 | DECLARE_WRITE16_MEMBER( en_68000_share_w ); |
| 13 | 13 | DECLARE_WRITE16_MEMBER( en_es5505_bank_w ); |
| 14 | 14 | DECLARE_WRITE16_MEMBER( en_volume_w ); |
| 15 | ||
| 15 | ||
| 16 | 16 | //todo: hook up cpu/es5510 |
| 17 | 17 | DECLARE_READ16_MEMBER( es5510_dsp_r ); |
| 18 | 18 | DECLARE_WRITE16_MEMBER( es5510_dsp_w ); |
| 19 | ||
| 19 | ||
| 20 | 20 | protected: |
| 21 | 21 | // device-level overrides |
| 22 | 22 | virtual void device_config_complete(); |
| r25360 | r25361 | |
| 35 | 35 | UINT32 m_es5510_dadr_latch; |
| 36 | 36 | UINT32 m_es5510_gpr_latch; |
| 37 | 37 | UINT8 m_es5510_ram_sel; |
| 38 | ||
| 38 | ||
| 39 | 39 | UINT32 *m_snd_shared_ram; |
| 40 | ||
| 40 | ||
| 41 | 41 | }; |
| 42 | 42 | |
| 43 | 43 | extern const device_type TAITO_EN; |
| r25360 | r25361 | |
|---|---|---|
| 43 | 43 | |
| 44 | 44 | |
| 45 | 45 | /*************************************************************************** |
| 46 | ||
| 46 | Seibu Sound System | |
| 47 | 47 | ***************************************************************************/ |
| 48 | 48 | |
| 49 | 49 | /* |
| r25360 | r25361 | |
| 100 | 100 | { |
| 101 | 101 | m_main2sub[0] = m_main2sub[1] = 0; |
| 102 | 102 | m_sub2main[0] = m_sub2main[1] = 0; |
| 103 | ||
| 103 | ||
| 104 | 104 | save_item(NAME(m_main2sub_pending)); |
| 105 | 105 | save_item(NAME(m_sub2main_pending)); |
| 106 | ||
| 106 | ||
| 107 | 107 | save_item(NAME(m_main2sub)); |
| 108 | 108 | save_item(NAME(m_sub2main)); |
| 109 | ||
| 109 | ||
| 110 | 110 | for (int i = 0; i < 2; i++) |
| 111 | 111 | { |
| 112 | 112 | save_item(NAME(m_main2sub[i]), i); |
| r25360 | r25361 | |
| 222 | 222 | m_sound_cpu->execute().set_input_line_and_vector(0,ASSERT_LINE,irq1 & irq2); |
| 223 | 223 | else |
| 224 | 224 | return; |
| 225 | } | |
| 226 | ||
| 225 | } | |
| 227 | 226 | |
| 227 | ||
| 228 | 228 | WRITE8_MEMBER( seibu_sound_device::irq_clear_w ) |
| 229 | 229 | { |
| 230 | 230 | /* Denjin Makai and SD Gundam doesn't like this, it's tied to the rst18 ack ONLY so it could be related to it. */ |
| r25360 | r25361 | |
| 497 | 497 | ADDRESS_MAP_END |
| 498 | 498 | |
| 499 | 499 | /*************************************************************************** |
| 500 | ||
| 500 | Seibu ADPCM device | |
| 501 | 501 | ***************************************************************************/ |
| 502 | 502 | |
| 503 | 503 | const device_type SEIBU_ADPCM = &device_creator<seibu_adpcm_device>; |
| r25360 | r25361 | |
|---|---|---|
| 64 | 64 | DECLARE_WRITE8_MEMBER( pending_w ); |
| 65 | 65 | void decrypt(const char *cpu,int length); |
| 66 | 66 | void update_irq_lines(int param); |
| 67 | ||
| 67 | ||
| 68 | 68 | protected: |
| 69 | 69 | // device-level overrides |
| 70 | 70 | virtual void device_config_complete(); |
| r25360 | r25361 | |
| 77 | 77 | UINT8 m_main2sub[2]; |
| 78 | 78 | UINT8 m_sub2main[2]; |
| 79 | 79 | int m_main2sub_pending; |
| 80 | int m_sub2main_pending; | |
| 81 | ||
| 80 | int m_sub2main_pending; | |
| 81 | ||
| 82 | 82 | enum |
| 83 | 83 | { |
| 84 | 84 | VECTOR_INIT, |
| r25360 | r25361 | |
| 112 | 112 | void decrypt(const char *region); |
| 113 | 113 | DECLARE_WRITE8_MEMBER( adr_w ); |
| 114 | 114 | DECLARE_WRITE8_MEMBER( ctl_w ); |
| 115 | ||
| 115 | ||
| 116 | 116 | protected: |
| 117 | 117 | // device-level overrides |
| 118 | 118 | virtual void device_config_complete(); |
| r25360 | r25361 | |
| 142 | 142 | /**************************************************************************/ |
| 143 | 143 | |
| 144 | 144 | #define MCFG_SEIBU_SOUND_ADD(_tag) \ |
| 145 | MCFG_DEVICE_ADD(_tag, SEIBU_SOUND, 0) | |
| 145 | MCFG_DEVICE_ADD(_tag, SEIBU_SOUND, 0) | |
| 146 | 146 | |
| 147 | 147 | #define SEIBU_COIN_INPUTS \ |
| 148 | 148 | PORT_START("COIN") \ |
| r25360 | r25361 | |
| 159 | 159 | |
| 160 | 160 | #define SEIBU_SOUND_SYSTEM_CPU(freq) \ |
| 161 | 161 | MCFG_CPU_ADD("audiocpu", Z80, freq) \ |
| 162 | MCFG_CPU_PROGRAM_MAP(seibu_sound_map) \ | |
| 163 | MCFG_SEIBU_SOUND_ADD("seibu_sound") | |
| 164 | ||
| 162 | MCFG_CPU_PROGRAM_MAP(seibu_sound_map) \ | |
| 163 | MCFG_SEIBU_SOUND_ADD("seibu_sound") | |
| 164 | ||
| 165 | 165 | #define SEIBU2_SOUND_SYSTEM_CPU(freq) \ |
| 166 | 166 | MCFG_CPU_ADD("audiocpu", Z80, freq) \ |
| 167 | MCFG_CPU_PROGRAM_MAP(seibu2_sound_map) \ | |
| 168 | MCFG_SEIBU_SOUND_ADD("seibu_sound") | |
| 169 | ||
| 167 | MCFG_CPU_PROGRAM_MAP(seibu2_sound_map) \ | |
| 168 | MCFG_SEIBU_SOUND_ADD("seibu_sound") | |
| 169 | ||
| 170 | 170 | #define SEIBU2_AIRRAID_SOUND_SYSTEM_CPU(freq) \ |
| 171 | 171 | MCFG_CPU_ADD("audiocpu", Z80, freq) \ |
| 172 | MCFG_CPU_PROGRAM_MAP(seibu2_airraid_sound_map) \ | |
| 173 | MCFG_SEIBU_SOUND_ADD("seibu_sound") | |
| 172 | MCFG_CPU_PROGRAM_MAP(seibu2_airraid_sound_map) \ | |
| 173 | MCFG_SEIBU_SOUND_ADD("seibu_sound") | |
| 174 | 174 | |
| 175 | 175 | #define SEIBU2_RAIDEN2_SOUND_SYSTEM_CPU(freq) \ |
| 176 | 176 | MCFG_CPU_ADD("audiocpu", Z80, freq) \ |
| 177 | MCFG_CPU_PROGRAM_MAP(seibu2_raiden2_sound_map) \ | |
| 178 | MCFG_SEIBU_SOUND_ADD("seibu_sound") | |
| 179 | ||
| 177 | MCFG_CPU_PROGRAM_MAP(seibu2_raiden2_sound_map) \ | |
| 178 | MCFG_SEIBU_SOUND_ADD("seibu_sound") | |
| 179 | ||
| 180 | 180 | #define SEIBU_NEWZEROTEAM_SOUND_SYSTEM_CPU(freq) \ |
| 181 | 181 | MCFG_CPU_ADD("audiocpu", Z80, freq) \ |
| 182 | MCFG_CPU_PROGRAM_MAP(seibu_newzeroteam_sound_map) \ | |
| 183 | MCFG_SEIBU_SOUND_ADD("seibu_sound") | |
| 184 | ||
| 182 | MCFG_CPU_PROGRAM_MAP(seibu_newzeroteam_sound_map) \ | |
| 183 | MCFG_SEIBU_SOUND_ADD("seibu_sound") | |
| 184 | ||
| 185 | 185 | #define SEIBU3_SOUND_SYSTEM_CPU(freq) \ |
| 186 | 186 | MCFG_CPU_ADD("audiocpu", Z80, freq) \ |
| 187 | MCFG_CPU_PROGRAM_MAP(seibu3_sound_map) \ | |
| 188 | MCFG_SEIBU_SOUND_ADD("seibu_sound") | |
| 189 | ||
| 187 | MCFG_CPU_PROGRAM_MAP(seibu3_sound_map) \ | |
| 188 | MCFG_SEIBU_SOUND_ADD("seibu_sound") | |
| 189 | ||
| 190 | 190 | #define SEIBU3A_SOUND_SYSTEM_CPU(freq) \ |
| 191 | 191 | MCFG_CPU_ADD("audiocpu", Z80, freq) \ |
| 192 | MCFG_CPU_PROGRAM_MAP(seibu3_adpcm_sound_map) \ | |
| 193 | MCFG_SEIBU_SOUND_ADD("seibu_sound") | |
| 194 | ||
| 192 | MCFG_CPU_PROGRAM_MAP(seibu3_adpcm_sound_map) \ | |
| 193 | MCFG_SEIBU_SOUND_ADD("seibu_sound") | |
| 194 | ||
| 195 | 195 | #define SEIBU_SOUND_SYSTEM_YM3812_INTERFACE(freq1,freq2) \ |
| 196 | 196 | MCFG_SPEAKER_STANDARD_MONO("mono") \ |
| 197 | 197 | \ |
| r25360 | r25361 | |
|---|---|---|
| 764 | 764 | m_pia0->reset(); |
| 765 | 765 | //machine().device("pia1")->reset(); |
| 766 | 766 | m_pia1->reset(); |
| 767 | ||
| 767 | ||
| 768 | 768 | /* 6532 */ |
| 769 | 769 | m_riot->reset(); |
| 770 | 770 | |
| r25360 | r25361 | |
| 999 | 999 | |
| 1000 | 1000 | save_item(NAME(m_riot_irq_state)); |
| 1001 | 1001 | sh8253_register_state_globals(); |
| 1002 | ||
| 1002 | ||
| 1003 | 1003 | m_tms = machine().device<tms5220_device>("tms"); |
| 1004 | 1004 | } |
| 1005 | 1005 |
| r25360 | r25361 | |
|---|---|---|
| 42 | 42 | DECLARE_READ8_MEMBER( sh6840_r ); |
| 43 | 43 | DECLARE_WRITE8_MEMBER( sh6840_w ); |
| 44 | 44 | DECLARE_WRITE8_MEMBER( sfxctrl_w ); |
| 45 | ||
| 45 | ||
| 46 | 46 | DECLARE_WRITE_LINE_MEMBER( update_irq_state ); |
| 47 | ||
| 47 | ||
| 48 | 48 | DECLARE_WRITE8_MEMBER( r6532_porta_w ); |
| 49 | 49 | DECLARE_READ8_MEMBER( r6532_porta_r ); |
| 50 | 50 | DECLARE_WRITE8_MEMBER( r6532_portb_w ); |
| 51 | 51 | DECLARE_READ8_MEMBER( r6532_portb_r ); |
| 52 | 52 | void r6532_irq(int state); |
| 53 | ||
| 53 | ||
| 54 | 54 | DECLARE_WRITE8_MEMBER( sh8253_w ); |
| 55 | 55 | DECLARE_READ8_MEMBER( sh8253_r ); |
| 56 | ||
| 56 | ||
| 57 | 57 | protected: |
| 58 | 58 | // device-level overrides |
| 59 | 59 | virtual void device_config_complete(); |
| 60 | 60 | virtual void device_start(); |
| 61 | 61 | virtual void device_reset(); |
| 62 | ||
| 62 | ||
| 63 | 63 | void common_sh_start(); |
| 64 | 64 | void common_sh_reset(); |
| 65 | ||
| 65 | ||
| 66 | 66 | void sh6840_register_state_globals(); |
| 67 | 67 | void sh8253_register_state_globals(); |
| 68 | 68 | |
| 69 | 69 | // sound stream update overrides |
| 70 | 70 | virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); |
| 71 | ||
| 71 | ||
| 72 | 72 | cpu_device *m_maincpu; |
| 73 | ||
| 73 | ||
| 74 | 74 | /* 6532 variables */ |
| 75 | 75 | riot6532_device *m_riot; |
| 76 | ||
| 76 | ||
| 77 | 77 | /* IRQ variable */ |
| 78 | 78 | UINT8 m_riot_irq_state; |
| 79 | ||
| 79 | ||
| 80 | 80 | /* 8253 variables */ |
| 81 | 81 | int m_has_sh8253; |
| 82 | 82 | struct sh8253_timer_channel m_sh8253_timer[3]; |
| 83 | ||
| 83 | ||
| 84 | 84 | /* 5220/CVSD variables */ |
| 85 | 85 | hc55516_device *m_cvsd; |
| 86 | 86 | tms5220_device *m_tms; |
| 87 | 87 | pia6821_device *m_pia0; |
| 88 | 88 | pia6821_device *m_pia1; |
| 89 | ||
| 89 | ||
| 90 | 90 | /* sound streaming variables */ |
| 91 | 91 | sound_stream *m_stream; |
| 92 | 92 | double m_freq_to_step; |
| 93 | ||
| 93 | ||
| 94 | 94 | private: |
| 95 | 95 | // internal state |
| 96 | 96 | struct sh6840_timer_channel m_sh6840_timer[3]; |
| r25360 | r25361 | |
| 116 | 116 | { |
| 117 | 117 | public: |
| 118 | 118 | venture_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 119 | ||
| 119 | ||
| 120 | 120 | DECLARE_WRITE8_MEMBER( mtrap_voiceio_w ); |
| 121 | 121 | DECLARE_READ8_MEMBER( mtrap_voiceio_r ); |
| 122 | ||
| 122 | ||
| 123 | 123 | DECLARE_WRITE8_MEMBER( filter_w ); |
| 124 | ||
| 124 | ||
| 125 | 125 | protected: |
| 126 | 126 | // device-level overrides |
| 127 | 127 | virtual void device_config_complete(); |
| r25360 | r25361 | |
| 130 | 130 | |
| 131 | 131 | // sound stream update overrides |
| 132 | 132 | virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); |
| 133 | ||
| 133 | ||
| 134 | 134 | private: |
| 135 | 135 | // internal state |
| 136 | 136 | }; |
| r25360 | r25361 | |
| 141 | 141 | { |
| 142 | 142 | public: |
| 143 | 143 | victory_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 144 | ||
| 144 | ||
| 145 | 145 | DECLARE_READ8_MEMBER( response_r ); |
| 146 | 146 | DECLARE_READ8_MEMBER( status_r ); |
| 147 | 147 | DECLARE_WRITE8_MEMBER( command_w ); |
| 148 | 148 | DECLARE_WRITE8_MEMBER( irq_clear_w ); |
| 149 | 149 | DECLARE_WRITE8_MEMBER( main_ack_w ); |
| 150 | ||
| 150 | ||
| 151 | 151 | protected: |
| 152 | 152 | // device-level overrides |
| 153 | 153 | virtual void device_config_complete(); |
| r25360 | r25361 | |
| 156 | 156 | |
| 157 | 157 | // sound stream update overrides |
| 158 | 158 | virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); |
| 159 | ||
| 159 | ||
| 160 | 160 | private: |
| 161 | 161 | // internal state |
| 162 | 162 | UINT8 m_victory_sound_response_ack_clk; /* 7474 @ F4 */ |
| 163 | ||
| 164 | TIMER_CALLBACK_MEMBER( delayed_command_w ); | |
| 163 | ||
| 164 | TIMER_CALLBACK_MEMBER( delayed_command_w ); | |
| 165 | 165 | }; |
| 166 | 166 | |
| 167 | 167 | extern const device_type EXIDY_VICTORY; |
| r25360 | r25361 | |
|---|---|---|
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | |
| 3 | Sega Model 1 sound board (68000 + 2x 315-5560 "MultiPCM") | |
| 3 | Sega Model 1 sound board (68000 + 2x 315-5560 "MultiPCM") | |
| 4 | 4 | |
| 5 | 5 | used for Model 1 and early Model 2 games |
| 6 | 6 | |
| r25360 | r25361 | |
| 8 | 8 | |
| 9 | 9 | #include "audio/segam1audio.h" |
| 10 | 10 | |
| 11 | #define M68000_TAG | |
| 11 | #define M68000_TAG "m1sndcpu" | |
| 12 | 12 | #define MULTIPCM_1_TAG "m1pcm1" |
| 13 | 13 | #define MULTIPCM_2_TAG "m1pcm2" |
| 14 | #define YM3438_TAG | |
| 14 | #define YM3438_TAG "m1ym" | |
| 15 | 15 | |
| 16 | 16 | static ADDRESS_MAP_START( segam1audio_map, AS_PROGRAM, 16, segam1audio_device ) |
| 17 | 17 | AM_RANGE(0x000000, 0x0bffff) AM_ROM AM_REGION(":m1sndcpu", 0) |
| r25360 | r25361 | |
| 172 | 172 | // signal the 68000 that there's data waiting |
| 173 | 173 | m_audiocpu->set_input_line(2, HOLD_LINE); |
| 174 | 174 | } |
| 175 |
| r25360 | r25361 | |
|---|---|---|
| 30 | 30 | DECLARE_WRITE8_MEMBER(bsmt_comms_w); |
| 31 | 31 | |
| 32 | 32 | DECLARE_WRITE_LINE_MEMBER(bsmt_reset_line); |
| 33 | ||
| 33 | ||
| 34 | 34 | INTERRUPT_GEN_MEMBER(decobsmt_firq_interrupt); |
| 35 | 35 | |
| 36 | 36 | required_device<cpu_device> m_ourcpu; |
| r25360 | r25361 | |
|---|---|---|
| 62 | 62 | m_stream(NULL) |
| 63 | 63 | { |
| 64 | 64 | m_sound_banks[0] = m_sound_banks[1] = m_sound_banks[2] = m_sound_banks[3] = 0; |
| 65 | ||
| 65 | ||
| 66 | 66 | for (int i = 0; i < 4; i++) |
| 67 | 67 | { |
| 68 | 68 | m_sound_channel[i].base = NULL; |
| r25360 | r25361 | |
| 108 | 108 | save_item(NAME(m_m6844_priority)); |
| 109 | 109 | save_item(NAME(m_m6844_interrupt)); |
| 110 | 110 | save_item(NAME(m_m6844_chain)); |
| 111 | ||
| 111 | ||
| 112 | 112 | m_channel_frequency[0] = clock(); /* channels 0 and 1 are run by FCLK */ |
| 113 | 113 | m_channel_frequency[1] = clock(); |
| 114 | 114 | m_channel_frequency[2] = clock()/2; /* channels 2 and 3 are run by SCLK */ |
| r25360 | r25361 | |
|---|---|---|
| 514 | 514 | {22, NO_OUTPUT_ENABLE_FUSE_ROW, 0, 280}}; /* Registered Output */ |
| 515 | 515 | |
| 516 | 516 | static pin_fuse_rows pal20x4pinfuserows[] = { |
| 517 | {14, 1440, 1480, 1560}, | |
| 518 | {15, 1280, 1320, 1400}, | |
| 519 | {16, 1120, 1160, 1240}, | |
| 520 | {17, NO_OUTPUT_ENABLE_FUSE_ROW, 960, 1080}, /* Registered Output */ | |
| 521 | {18, NO_OUTPUT_ENABLE_FUSE_ROW, 800, 920}, /* Registered Output */ | |
| 522 | {19, NO_OUTPUT_ENABLE_FUSE_ROW, 640, 760}, /* Registered Output */ | |
| 523 | {20, NO_OUTPUT_ENABLE_FUSE_ROW, 480, 600}, /* Registered Output */ | |
| 524 | {21, 320, 360, 440}, | |
| 525 | {22, 160, 200, 280}, | |
| 526 | {23, 0, 40, 120}}; | |
| 517 | {14, 1440, 1480, 1560}, | |
| 518 | {15, 1280, 1320, 1400}, | |
| 519 | {16, 1120, 1160, 1240}, | |
| 520 | {17, NO_OUTPUT_ENABLE_FUSE_ROW, 960, 1080}, /* Registered Output */ | |
| 521 | {18, NO_OUTPUT_ENABLE_FUSE_ROW, 800, 920}, /* Registered Output */ | |
| 522 | {19, NO_OUTPUT_ENABLE_FUSE_ROW, 640, 760}, /* Registered Output */ | |
| 523 | {20, NO_OUTPUT_ENABLE_FUSE_ROW, 480, 600}, /* Registered Output */ | |
| 524 | {21, 320, 360, 440}, | |
| 525 | {22, 160, 200, 280}, | |
| 526 | {23, 0, 40, 120}}; | |
| 527 | 527 | |
| 528 | 528 | static pin_fuse_rows pal20x8pinfuserows[] = { |
| 529 | {14, 1440, 1480, 1560}, | |
| 530 | {15, NO_OUTPUT_ENABLE_FUSE_ROW, 1280, 1400}, /* Registered Output */ | |
| 531 | {16, NO_OUTPUT_ENABLE_FUSE_ROW, 1120, 1240}, /* Registered Output */ | |
| 532 | {17, NO_OUTPUT_ENABLE_FUSE_ROW, 960, 1080}, /* Registered Output */ | |
| 533 | {18, NO_OUTPUT_ENABLE_FUSE_ROW, 800, 920}, /* Registered Output */ | |
| 534 | {19, NO_OUTPUT_ENABLE_FUSE_ROW, 640, 760}, /* Registered Output */ | |
| 535 | {20, NO_OUTPUT_ENABLE_FUSE_ROW, 480, 600}, /* Registered Output */ | |
| 536 | {21, NO_OUTPUT_ENABLE_FUSE_ROW, 320, 440}, /* Registered Output */ | |
| 537 | {22, NO_OUTPUT_ENABLE_FUSE_ROW, 160, 280}, /* Registered Output */ | |
| 538 | {23, 0, 40, 120}}; | |
| 529 | {14, 1440, 1480, 1560}, | |
| 530 | {15, NO_OUTPUT_ENABLE_FUSE_ROW, 1280, 1400}, /* Registered Output */ | |
| 531 | {16, NO_OUTPUT_ENABLE_FUSE_ROW, 1120, 1240}, /* Registered Output */ | |
| 532 | {17, NO_OUTPUT_ENABLE_FUSE_ROW, 960, 1080}, /* Registered Output */ | |
| 533 | {18, NO_OUTPUT_ENABLE_FUSE_ROW, 800, 920}, /* Registered Output */ | |
| 534 | {19, NO_OUTPUT_ENABLE_FUSE_ROW, 640, 760}, /* Registered Output */ | |
| 535 | {20, NO_OUTPUT_ENABLE_FUSE_ROW, 480, 600}, /* Registered Output */ | |
| 536 | {21, NO_OUTPUT_ENABLE_FUSE_ROW, 320, 440}, /* Registered Output */ | |
| 537 | {22, NO_OUTPUT_ENABLE_FUSE_ROW, 160, 280}, /* Registered Output */ | |
| 538 | {23, 0, 40, 120}}; | |
| 539 | 539 | |
| 540 | 540 | static pin_fuse_rows pal20x10pinfuserows[] = { |
| 541 | {14, NO_OUTPUT_ENABLE_FUSE_ROW, 1440, 1560}, /* Registered Output */ | |
| 542 | {15, NO_OUTPUT_ENABLE_FUSE_ROW, 1280, 1400}, /* Registered Output */ | |
| 543 | {16, NO_OUTPUT_ENABLE_FUSE_ROW, 1120, 1240}, /* Registered Output */ | |
| 544 | {17, NO_OUTPUT_ENABLE_FUSE_ROW, 960, 1080}, /* Registered Output */ | |
| 545 | {18, NO_OUTPUT_ENABLE_FUSE_ROW, 800, 920}, /* Registered Output */ | |
| 546 | {19, NO_OUTPUT_ENABLE_FUSE_ROW, 640, 760}, /* Registered Output */ | |
| 547 | {20, NO_OUTPUT_ENABLE_FUSE_ROW, 480, 600}, /* Registered Output */ | |
| 548 | {21, NO_OUTPUT_ENABLE_FUSE_ROW, 320, 440}, /* Registered Output */ | |
| 549 | {22, NO_OUTPUT_ENABLE_FUSE_ROW, 160, 280}, /* Registered Output */ | |
| 550 | {23, NO_OUTPUT_ENABLE_FUSE_ROW, 0, 120}}; /* Registered Output */ | |
| 541 | {14, NO_OUTPUT_ENABLE_FUSE_ROW, 1440, 1560}, /* Registered Output */ | |
| 542 | {15, NO_OUTPUT_ENABLE_FUSE_ROW, 1280, 1400}, /* Registered Output */ | |
| 543 | {16, NO_OUTPUT_ENABLE_FUSE_ROW, 1120, 1240}, /* Registered Output */ | |
| 544 | {17, NO_OUTPUT_ENABLE_FUSE_ROW, 960, 1080}, /* Registered Output */ | |
| 545 | {18, NO_OUTPUT_ENABLE_FUSE_ROW, 800, 920}, /* Registered Output */ | |
| 546 | {19, NO_OUTPUT_ENABLE_FUSE_ROW, 640, 760}, /* Registered Output */ | |
| 547 | {20, NO_OUTPUT_ENABLE_FUSE_ROW, 480, 600}, /* Registered Output */ | |
| 548 | {21, NO_OUTPUT_ENABLE_FUSE_ROW, 320, 440}, /* Registered Output */ | |
| 549 | {22, NO_OUTPUT_ENABLE_FUSE_ROW, 160, 280}, /* Registered Output */ | |
| 550 | {23, NO_OUTPUT_ENABLE_FUSE_ROW, 0, 120}}; /* Registered Output */ | |
| 551 | 551 | |
| 552 | 552 | static pin_fuse_rows _82s153_pls153pinfuserows[] = { |
| 553 | {9, 1472, 0, 0}, | |
| 554 | {11, 1508, 0, 0}, | |
| 555 | {12, 1544, 0, 0}, | |
| 556 | {13, 1580, 0, 0}, | |
| 557 | {14, 1616, 0, 0}, | |
| 558 | {15, 1652, 0, 0}, | |
| 559 | {16, 1688, 0, 0}, | |
| 560 | {17, 1724, 0, 0}, | |
| 561 | {18, 1760, 0, 0}, | |
| 562 | {19, 1796, 0, 0}}; | |
| 553 | {9, 1472, 0, 0}, | |
| 554 | {11, 1508, 0, 0}, | |
| 555 | {12, 1544, 0, 0}, | |
| 556 | {13, 1580, 0, 0}, | |
| 557 | {14, 1616, 0, 0}, | |
| 558 | {15, 1652, 0, 0}, | |
| 559 | {16, 1688, 0, 0}, | |
| 560 | {17, 1724, 0, 0}, | |
| 561 | {18, 1760, 0, 0}, | |
| 562 | {19, 1796, 0, 0}}; | |
| 563 | 563 | |
| 564 | 564 | static pin_fuse_rows ck2605pinfuserows[] = { |
| 565 | {9, 736, 0, 0}, | |
| 566 | {11, 772, 0, 0}, | |
| 567 | {12, 808, 0, 0}, | |
| 568 | {13, 844, 0, 0}, | |
| 569 | {14, 880, 0, 0}, | |
| 570 | {15, 916, 0, 0}, | |
| 571 | {16, 952, 0, 0}, | |
| 572 | {17, 988, 0, 0}, | |
| 573 | {18, 1024, 0, 0}, | |
| 574 | {19, 1060, 0, 0}}; | |
| 565 | {9, 736, 0, 0}, | |
| 566 | {11, 772, 0, 0}, | |
| 567 | {12, 808, 0, 0}, | |
| 568 | {13, 844, 0, 0}, | |
| 569 | {14, 880, 0, 0}, | |
| 570 | {15, 916, 0, 0}, | |
| 571 | {16, 952, 0, 0}, | |
| 572 | {17, 988, 0, 0}, | |
| 573 | {18, 1024, 0, 0}, | |
| 574 | {19, 1060, 0, 0}}; | |
| 575 | 575 | |
| 576 | 576 | static pin_fuse_columns pal10l8pinfusecolumns[] = { |
| 577 | 577 | {1, 3, 2}, |
| r25360 | r25361 | |
| 970 | 970 | {23, 3, 2}}; |
| 971 | 971 | |
| 972 | 972 | static pin_fuse_columns pal20x4pinfusecolumns[] = { |
| 973 | {2, 1, 0}, | |
| 974 | {3, 5, 4}, | |
| 975 | {4, 9, 8}, | |
| 976 | {5, 13, 12}, | |
| 977 | {6, 17, 16}, | |
| 978 | {7, 21, 20}, | |
| 979 | {8, 25, 24}, | |
| 980 | {9, 29, 28}, | |
| 981 | {10, 33, 32}, | |
| 982 | {11, 37, 36}, | |
| 983 | {14, 39, 38}, | |
| 984 | {15, 35, 34}, | |
| 985 | {16, 31, 30}, | |
| 986 | {17, 27, 26}, | |
| 987 | {18, 23, 22}, | |
| 988 | {19, 19, 18}, | |
| 989 | {20, 15, 14}, | |
| 990 | {21, 11, 10}, | |
| 991 | {22, 7, 6}, | |
| 992 | {23, 3, 2}}; | |
| 973 | {2, 1, 0}, | |
| 974 | {3, 5, 4}, | |
| 975 | {4, 9, 8}, | |
| 976 | {5, 13, 12}, | |
| 977 | {6, 17, 16}, | |
| 978 | {7, 21, 20}, | |
| 979 | {8, 25, 24}, | |
| 980 | {9, 29, 28}, | |
| 981 | {10, 33, 32}, | |
| 982 | {11, 37, 36}, | |
| 983 | {14, 39, 38}, | |
| 984 | {15, 35, 34}, | |
| 985 | {16, 31, 30}, | |
| 986 | {17, 27, 26}, | |
| 987 | {18, 23, 22}, | |
| 988 | {19, 19, 18}, | |
| 989 | {20, 15, 14}, | |
| 990 | {21, 11, 10}, | |
| 991 | {22, 7, 6}, | |
| 992 | {23, 3, 2}}; | |
| 993 | 993 | |
| 994 | 994 | static pin_fuse_columns pal20x8pinfusecolumns[] = { |
| 995 | {2, 1, 0}, | |
| 996 | {3, 5, 4}, | |
| 997 | {4, 9, 8}, | |
| 998 | {5, 13, 12}, | |
| 999 | {6, 17, 16}, | |
| 1000 | {7, 21, 20}, | |
| 1001 | {8, 25, 24}, | |
| 1002 | {9, 29, 28}, | |
| 1003 | {10, 33, 32}, | |
| 1004 | {11, 37, 36}, | |
| 1005 | {14, 39, 38}, | |
| 1006 | {15, 35, 34}, | |
| 1007 | {16, 31, 30}, | |
| 1008 | {17, 27, 26}, | |
| 1009 | {18, 23, 22}, | |
| 1010 | {19, 19, 18}, | |
| 1011 | {20, 15, 14}, | |
| 1012 | {21, 11, 10}, | |
| 1013 | {22, 7, 6}, | |
| 1014 | {23, 3, 2}}; | |
| 995 | {2, 1, 0}, | |
| 996 | {3, 5, 4}, | |
| 997 | {4, 9, 8}, | |
| 998 | {5, 13, 12}, | |
| 999 | {6, 17, 16}, | |
| 1000 | {7, 21, 20}, | |
| 1001 | {8, 25, 24}, | |
| 1002 | {9, 29, 28}, | |
| 1003 | {10, 33, 32}, | |
| 1004 | {11, 37, 36}, | |
| 1005 | {14, 39, 38}, | |
| 1006 | {15, 35, 34}, | |
| 1007 | {16, 31, 30}, | |
| 1008 | {17, 27, 26}, | |
| 1009 | {18, 23, 22}, | |
| 1010 | {19, 19, 18}, | |
| 1011 | {20, 15, 14}, | |
| 1012 | {21, 11, 10}, | |
| 1013 | {22, 7, 6}, | |
| 1014 | {23, 3, 2}}; | |
| 1015 | 1015 | |
| 1016 | 1016 | static pin_fuse_columns pal20x10pinfusecolumns[] = { |
| 1017 | {2, 1, 0}, | |
| 1018 | {3, 5, 4}, | |
| 1019 | {4, 9, 8}, | |
| 1020 | {5, 13, 12}, | |
| 1021 | {6, 17, 16}, | |
| 1022 | {7, 21, 20}, | |
| 1023 | {8, 25, 24}, | |
| 1024 | {9, 29, 28}, | |
| 1025 | {10, 33, 32}, | |
| 1026 | {11, 37, 36}, | |
| 1027 | {14, 39, 38}, | |
| 1028 | {15, 35, 34}, | |
| 1029 | {16, 31, 30}, | |
| 1030 | {17, 27, 26}, | |
| 1031 | {18, 23, 22}, | |
| 1032 | {19, 19, 18}, | |
| 1033 | {20, 15, 14}, | |
| 1034 | {21, 11, 10}, | |
| 1035 | {22, 7, 6}, | |
| 1036 | {23, 3, 2} | |
| 1017 | {2, 1, 0}, | |
| 1018 | {3, 5, 4}, | |
| 1019 | {4, 9, 8}, | |
| 1020 | {5, 13, 12}, | |
| 1021 | {6, 17, 16}, | |
| 1022 | {7, 21, 20}, | |
| 1023 | {8, 25, 24}, | |
| 1024 | {9, 29, 28}, | |
| 1025 | {10, 33, 32}, | |
| 1026 | {11, 37, 36}, | |
| 1027 | {14, 39, 38}, | |
| 1028 | {15, 35, 34}, | |
| 1029 | {16, 31, 30}, | |
| 1030 | {17, 27, 26}, | |
| 1031 | {18, 23, 22}, | |
| 1032 | {19, 19, 18}, | |
| 1033 | {20, 15, 14}, | |
| 1034 | {21, 11, 10}, | |
| 1035 | {22, 7, 6}, | |
| 1036 | {23, 3, 2} | |
| 1037 | 1037 | }; |
| 1038 | 1038 | |
| 1039 | 1039 | static pin_fuse_columns _82s153_pls153pinfusecolumns[] = { |
| 1040 | {1, 1, 0}, | |
| 1041 | {2, 3, 2}, | |
| 1042 | {3, 5, 4}, | |
| 1043 | {4, 7, 6}, | |
| 1044 | {5, 9, 8}, | |
| 1045 | {6, 11, 10}, | |
| 1046 | {7, 13, 12}, | |
| 1047 | {8, 15, 14}, | |
| 1048 | {9, 17, 16}, | |
| 1049 | {11, 19, 18}, | |
| 1050 | {12, 21, 20}, | |
| 1051 | {13, 23, 22}, | |
| 1052 | {14, 25, 24}, | |
| 1053 | {15, 27, 26}, | |
| 1054 | {16, 29, 28}, | |
| 1055 | {17, 31, 30}, | |
| 1056 | {18, 33, 32}, | |
| 1057 | {19, 35, 34}}; | |
| 1040 | {1, 1, 0}, | |
| 1041 | {2, 3, 2}, | |
| 1042 | {3, 5, 4}, | |
| 1043 | {4, 7, 6}, | |
| 1044 | {5, 9, 8}, | |
| 1045 | {6, 11, 10}, | |
| 1046 | {7, 13, 12}, | |
| 1047 | {8, 15, 14}, | |
| 1048 | {9, 17, 16}, | |
| 1049 | {11, 19, 18}, | |
| 1050 | {12, 21, 20}, | |
| 1051 | {13, 23, 22}, | |
| 1052 | {14, 25, 24}, | |
| 1053 | {15, 27, 26}, | |
| 1054 | {16, 29, 28}, | |
| 1055 | {17, 31, 30}, | |
| 1056 | {18, 33, 32}, | |
| 1057 | {19, 35, 34}}; | |
| 1058 | 1058 | |
| 1059 | 1059 | static pin_fuse_columns ck2605pinfusecolumns[] = { |
| 1060 | {1, 1, 0}, | |
| 1061 | {2, 3, 2}, | |
| 1062 | {3, 5, 4}, | |
| 1063 | {4, 7, 6}, | |
| 1064 | {5, 9, 8}, | |
| 1065 | {6, 11, 10}, | |
| 1066 | {7, 13, 12}, | |
| 1067 | {8, 15, 14}, | |
| 1068 | {9, 17, 16}, | |
| 1069 | {11, 19, 18}, | |
| 1070 | {12, 21, 20}, | |
| 1071 | {13, 23, 22}, | |
| 1072 | {14, 25, 24}, | |
| 1073 | {15, 27, 26}, | |
| 1074 | {16, 29, 28}, | |
| 1075 | {17, 31, 30}, | |
| 1076 | {18, 33, 32}, | |
| 1077 | {19, 35, 34}}; | |
| 1060 | {1, 1, 0}, | |
| 1061 | {2, 3, 2}, | |
| 1062 | {3, 5, 4}, | |
| 1063 | {4, 7, 6}, | |
| 1064 | {5, 9, 8}, | |
| 1065 | {6, 11, 10}, | |
| 1066 | {7, 13, 12}, | |
| 1067 | {8, 15, 14}, | |
| 1068 | {9, 17, 16}, | |
| 1069 | {11, 19, 18}, | |
| 1070 | {12, 21, 20}, | |
| 1071 | {13, 23, 22}, | |
| 1072 | {14, 25, 24}, | |
| 1073 | {15, 27, 26}, | |
| 1074 | {16, 29, 28}, | |
| 1075 | {17, 31, 30}, | |
| 1076 | {18, 33, 32}, | |
| 1077 | {19, 35, 34}}; | |
| 1078 | 1078 | |
| 1079 | 1079 | static pal_data paldata[] = { |
| 1080 | 1080 | {"PAL10L8", |
| r25360 | r25361 | |
| 1172 | 1172 | /*{"PAL16RA8", NULL, 0, NULL, 0, NULL, NULL, NULL, NULL}, |
| 1173 | 1173 | {"PAL16V8R", NULL, 0, NULL, 0, NULL, NULL, NULL, NULL},*/ |
| 1174 | 1174 | {"PALCE16V8", |
| 1175 | palce16v8pinfuserows, ARRAY_LEN(palce16v8pinfuserows), | |
| 1176 | palce16v8pinfusecolumns, ARRAY_LEN(palce16v8pinfusecolumns), | |
| 1175 | palce16v8pinfuserows, ARRAY_LEN(palce16v8pinfuserows), | |
| 1176 | palce16v8pinfusecolumns, ARRAY_LEN(palce16v8pinfusecolumns), | |
| 1177 | 1177 | print_palce16v8_product_terms, |
| 1178 | 1178 | config_palce16v8_pins, |
| 1179 | NULL, | |
| 1180 | NULL}, | |
| 1179 | NULL, | |
| 1180 | NULL}, | |
| 1181 | 1181 | {"GAL16V8", |
| 1182 | 1182 | gal16v8pinfuserows, ARRAY_LEN(gal16v8pinfuserows), |
| 1183 | 1183 | gal16v8pinfusecolumns, ARRAY_LEN(gal16v8pinfusecolumns), |
| r25360 | r25361 | |
| 1192 | 1192 | config_peel18cv8_pins, |
| 1193 | 1193 | NULL, |
| 1194 | 1194 | get_peel18cv8_pin_fuse_state}, |
| 1195 | ||
| 1195 | {"GAL18V10", | |
| 1196 | 1196 | gal18v10pinfuserows, ARRAY_LEN(gal18v10pinfuserows), |
| 1197 | 1197 | gal18v10pinfusecolumns, ARRAY_LEN(gal18v10pinfusecolumns), |
| 1198 | 1198 | print_gal18v10_product_terms, |
| r25360 | r25361 | |
| 1273 | 1273 | config_82s153_pls153_pins, |
| 1274 | 1274 | NULL, |
| 1275 | 1275 | NULL}, |
| 1276 | ||
| 1276 | {"CK2605", | |
| 1277 | 1277 | ck2605pinfuserows, ARRAY_LEN(ck2605pinfuserows), |
| 1278 | 1278 | ck2605pinfusecolumns, ARRAY_LEN(ck2605pinfusecolumns), |
| 1279 | 1279 | print_ck2605_product_terms, |
| r25360 | r25361 | |
| 2140 | 2140 | |
| 2141 | 2141 | static void print_palce16v8_product_terms(const pal_data* pal, const jed_data* jed) |
| 2142 | 2142 | { |
| 2143 | ||
| 2143 | fprintf(stderr, "Printing product terms for PALCE16V8 not supported!\n"); | |
| 2144 | 2144 | |
| 2145 | 2145 | /*print_product_terms(pal, jed);*/ |
| 2146 | 2146 | } |
| r25360 | r25361 | |
| 2347 | 2347 | printf("Equations:\n\n"); |
| 2348 | 2348 | |
| 2349 | 2349 | for (index = 0; index < outputpinscount; ++index) |
| 2350 | ||
| 2350 | { | |
| 2351 | 2351 | flags = outputpins[index].flags; |
| 2352 | 2352 | |
| 2353 | 2353 | indent = 0; |
| r25360 | r25361 | |
| 2363 | 2363 | |
| 2364 | 2364 | printf("%s", buffer); |
| 2365 | 2365 | |
| 2366 | ||
| 2366 | haveterms = 0; | |
| 2367 | 2367 | indent += strlen(buffer); |
| 2368 | 2368 | |
| 2369 | 2369 | fuse_rows = find_fuse_rows(pal, outputpins[index].pin); |
| 2370 | ||
| 2370 | fuserow = 0; | |
| 2371 | 2371 | |
| 2372 | if (outputpins[index].pin != 9) | |
| 2373 | { | |
| 2374 | or_column = 19 - outputpins[index].pin; | |
| 2375 | } | |
| 2376 | else | |
| 2377 | { | |
| 2378 | or_column = 9; | |
| 2379 | } | |
| 2372 | if (outputpins[index].pin != 9) | |
| 2373 | { | |
| 2374 | or_column = 19 - outputpins[index].pin; | |
| 2375 | } | |
| 2376 | else | |
| 2377 | { | |
| 2378 | or_column = 9; | |
| 2379 | } | |
| 2380 | 2380 | |
| 2381 | for (row = 0; row < 32; ++row) | |
| 2382 | { | |
| 2383 | if (!jed_get_fuse(jed, fuserow + columncount + or_column)) | |
| 2384 | { | |
| 2385 | generate_product_terms(pal, jed, fuserow, buffer); | |
| 2381 | for (row = 0; row < 32; ++row) | |
| 2382 | { | |
| 2383 | if (!jed_get_fuse(jed, fuserow + columncount + or_column)) | |
| 2384 | { | |
| 2385 | generate_product_terms(pal, jed, fuserow, buffer); | |
| 2386 | 2386 | |
| 2387 | if (strlen(buffer) > 0) | |
| 2388 | { | |
| 2389 | if (haveterms) | |
| 2390 | { | |
| 2391 | printf(" +\n"); | |
| 2387 | if (strlen(buffer) > 0) | |
| 2388 | { | |
| 2389 | if (haveterms) | |
| 2390 | { | |
| 2391 | printf(" +\n"); | |
| 2392 | 2392 | |
| 2393 | for (indentindex = 0; indentindex < indent; ++indentindex) | |
| 2394 | { | |
| 2395 | printf(" "); | |
| 2396 | } | |
| 2397 | } | |
| 2398 | else | |
| 2399 | { | |
| 2400 | haveterms = 1; | |
| 2401 | } | |
| 2393 | for (indentindex = 0; indentindex < indent; ++indentindex) | |
| 2394 | { | |
| 2395 | printf(" "); | |
| 2396 | } | |
| 2397 | } | |
| 2398 | else | |
| 2399 | { | |
| 2400 | haveterms = 1; | |
| 2401 | } | |
| 2402 | 2402 | |
| 2403 | printf("%s", buffer); | |
| 2404 | } | |
| 2405 | } | |
| 2403 | printf("%s", buffer); | |
| 2404 | } | |
| 2405 | } | |
| 2406 | 2406 | |
| 2407 | fuserow += (columncount + 10); | |
| 2408 | } | |
| 2409 | ||
| 2410 | printf("\n"); | |
| 2407 | fuserow += (columncount + 10); | |
| 2408 | } | |
| 2411 | 2409 | |
| 2410 | printf("\n"); | |
| 2411 | ||
| 2412 | 2412 | /* output enable equations */ |
| 2413 | 2413 | |
| 2414 | 2414 | printf("o%d.oe = ", outputpins[index].pin); |
| r25360 | r25361 | |
| 2425 | 2425 | } |
| 2426 | 2426 | |
| 2427 | 2427 | printf("\n"); |
| 2428 | ||
| 2428 | } | |
| 2429 | 2429 | } |
| 2430 | 2430 | |
| 2431 | 2431 | |
| r25360 | r25361 | |
| 2450 | 2450 | printf("Equations:\n\n"); |
| 2451 | 2451 | |
| 2452 | 2452 | for (index = 0; index < outputpinscount; ++index) |
| 2453 | ||
| 2453 | { | |
| 2454 | 2454 | flags = outputpins[index].flags; |
| 2455 | 2455 | |
| 2456 | 2456 | indent = 0; |
| r25360 | r25361 | |
| 2466 | 2466 | |
| 2467 | 2467 | printf("%s", buffer); |
| 2468 | 2468 | |
| 2469 | ||
| 2469 | haveterms = 0; | |
| 2470 | 2470 | indent += strlen(buffer); |
| 2471 | 2471 | |
| 2472 | 2472 | fuse_rows = find_fuse_rows(pal, outputpins[index].pin); |
| 2473 | ||
| 2473 | fuserow = 0; | |
| 2474 | 2474 | |
| 2475 | if (outputpins[index].pin != 9) | |
| 2476 | { | |
| 2477 | or_column = 19 - outputpins[index].pin; | |
| 2478 | } | |
| 2479 | else | |
| 2480 | { | |
| 2481 | or_column = 9; | |
| 2482 | } | |
| 2475 | if (outputpins[index].pin != 9) | |
| 2476 | { | |
| 2477 | or_column = 19 - outputpins[index].pin; | |
| 2478 | } | |
| 2479 | else | |
| 2480 | { | |
| 2481 | or_column = 9; | |
| 2482 | } | |
| 2483 | 2483 | |
| 2484 | for (row = 0; row < 16; ++row) | |
| 2485 | { | |
| 2486 | if (!jed_get_fuse(jed, fuserow + columncount + or_column)) | |
| 2487 | { | |
| 2488 | generate_product_terms(pal, jed, fuserow, buffer); | |
| 2484 | for (row = 0; row < 16; ++row) | |
| 2485 | { | |
| 2486 | if (!jed_get_fuse(jed, fuserow + columncount + or_column)) | |
| 2487 | { | |
| 2488 | generate_product_terms(pal, jed, fuserow, buffer); | |
| 2489 | 2489 | |
| 2490 | if (strlen(buffer) > 0) | |
| 2491 | { | |
| 2492 | if (haveterms) | |
| 2493 | { | |
| 2494 | printf(" +\n"); | |
| 2490 | if (strlen(buffer) > 0) | |
| 2491 | { | |
| 2492 | if (haveterms) | |
| 2493 | { | |
| 2494 | printf(" +\n"); | |
| 2495 | 2495 | |
| 2496 | for (indentindex = 0; indentindex < indent; ++indentindex) | |
| 2497 | { | |
| 2498 | printf(" "); | |
| 2499 | } | |
| 2500 | } | |
| 2501 | else | |
| 2502 | { | |
| 2503 | haveterms = 1; | |
| 2504 | } | |
| 2496 | for (indentindex = 0; indentindex < indent; ++indentindex) | |
| 2497 | { | |
| 2498 | printf(" "); | |
| 2499 | } | |
| 2500 | } | |
| 2501 | else | |
| 2502 | { | |
| 2503 | haveterms = 1; | |
| 2504 | } | |
| 2505 | 2505 | |
| 2506 | printf("%s", buffer); | |
| 2507 | } | |
| 2508 | } | |
| 2506 | printf("%s", buffer); | |
| 2507 | } | |
| 2508 | } | |
| 2509 | 2509 | |
| 2510 | fuserow += (columncount + 10); | |
| 2511 | } | |
| 2512 | ||
| 2513 | printf("\n"); | |
| 2510 | fuserow += (columncount + 10); | |
| 2511 | } | |
| 2514 | 2512 | |
| 2513 | printf("\n"); | |
| 2514 | ||
| 2515 | 2515 | /* output enable equations */ |
| 2516 | 2516 | |
| 2517 | 2517 | printf("o%d.oe = ", outputpins[index].pin); |
| r25360 | r25361 | |
| 2528 | 2528 | } |
| 2529 | 2529 | |
| 2530 | 2530 | printf("\n"); |
| 2531 | ||
| 2531 | } | |
| 2532 | 2532 | } |
| 2533 | 2533 | |
| 2534 | 2534 | |
| r25360 | r25361 | |
| 2888 | 2888 | struct _output_logic_macrocell |
| 2889 | 2889 | { |
| 2890 | 2890 | UINT16 pin; |
| 2891 | ||
| 2891 | UINT16 sl0_fuse; /* registers allowed */ | |
| 2892 | 2892 | UINT16 sl1_fuse; /* output polarity 0 - low, 1 - high */ |
| 2893 | 2893 | }; |
| 2894 | 2894 | |
| r25360 | r25361 | |
| 2901 | 2901 | {17, 2122, 2050}, |
| 2902 | 2902 | {18, 2121, 2049}, |
| 2903 | 2903 | {19, 2120, 2048}}; |
| 2904 | UINT16 sg0 = 2192; /* guessing on fuse here */ | |
| 2905 | UINT16 sg1 = 2193; /* guessing on fuse here */ | |
| 2906 | UINT16 index; | |
| 2904 | UINT16 sg0 = 2192; /* guessing on fuse here */ | |
| 2905 | UINT16 sg1 = 2193; /* guessing on fuse here */ | |
| 2906 | UINT16 index; | |
| 2907 | 2907 | |
| 2908 | for (index = 0; index < ARRAY_LEN(macrocells); ++index) | |
| 2909 | { | |
| 2910 | if (jed_get_fuse(jed, sg0)) | |
| 2911 | { | |
| 2912 | /* Device uses no registers */ | |
| 2908 | for (index = 0; index < ARRAY_LEN(macrocells); ++index) | |
| 2909 | { | |
| 2910 | if (jed_get_fuse(jed, sg0)) | |
| 2911 | { | |
| 2912 | /* Device uses no registers */ | |
| 2913 | 2913 | |
| 2914 | if (jed_get_fuse(jed, sg1)) | |
| 2915 | { | |
| 2916 | /* Combinatorial I/O */ | |
| 2917 | } | |
| 2918 | else | |
| 2919 | { | |
| 2920 | /* Combinatorial Output or Input */ | |
| 2921 | } | |
| 2922 | } | |
| 2923 | else | |
| 2924 | { | |
| 2925 | /* Device uses registers */ | |
| 2914 | if (jed_get_fuse(jed, sg1)) | |
| 2915 | { | |
| 2916 | /* Combinatorial I/O */ | |
| 2917 | } | |
| 2918 | else | |
| 2919 | { | |
| 2920 | /* Combinatorial Output or Input */ | |
| 2921 | } | |
| 2922 | } | |
| 2923 | else | |
| 2924 | { | |
| 2925 | /* Device uses registers */ | |
| 2926 | 2926 | |
| 2927 | if (jed_get_fuse(jed, sg1)) | |
| 2928 | { | |
| 2929 | } | |
| 2930 | else | |
| 2931 | { | |
| 2932 | fprintf(stderr, "Unknown configuration type!\n"); | |
| 2933 | } | |
| 2934 | } | |
| 2935 | } | |
| 2927 | if (jed_get_fuse(jed, sg1)) | |
| 2928 | { | |
| 2929 | } | |
| 2930 | else | |
| 2931 | { | |
| 2932 | fprintf(stderr, "Unknown configuration type!\n"); | |
| 2933 | } | |
| 2934 | } | |
| 2935 | } | |
| 2936 | 2936 | |
| 2937 | ||
| 2937 | /* 2056 - 2119 are the 64 bit signature fuses */ | |
| 2938 | 2938 | |
| 2939 | 2939 | fprintf(stderr, "Configuring product terms for PALCE16V8 not supported!\n"); |
| 2940 | 2940 | } |
| r25360 | r25361 | |
| 3641 | 3641 | { |
| 3642 | 3642 | static UINT16 input_pins[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}; |
| 3643 | 3643 | static pin_output_config output_pins[] = { |
| 3644 | ||
| 3644 | {14, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_OUTPUT}, | |
| 3645 | 3645 | {15, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_OUTPUT}, |
| 3646 | 3646 | {16, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_OUTPUT}, |
| 3647 | 3647 | {17, OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED}, |
| r25360 | r25361 | |
| 3650 | 3650 | {20, OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED}, |
| 3651 | 3651 | {21, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_OUTPUT}, |
| 3652 | 3652 | {22, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_OUTPUT}, |
| 3653 | ||
| 3653 | {23, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_OUTPUT}}; | |
| 3654 | 3654 | |
| 3655 | 3655 | set_input_pins(input_pins, ARRAY_LEN(input_pins)); |
| 3656 | 3656 | set_output_pins(output_pins, ARRAY_LEN(output_pins)); |
| r25360 | r25361 | |
| 3665 | 3665 | { |
| 3666 | 3666 | static UINT16 input_pins[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}; |
| 3667 | 3667 | static pin_output_config output_pins[] = { |
| 3668 | ||
| 3668 | {14, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_OUTPUT}, | |
| 3669 | 3669 | {15, OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED}, |
| 3670 | 3670 | {16, OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED}, |
| 3671 | 3671 | {17, OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED}, |
| r25360 | r25361 | |
| 3674 | 3674 | {20, OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED}, |
| 3675 | 3675 | {21, OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED}, |
| 3676 | 3676 | {22, OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED}, |
| 3677 | ||
| 3677 | {23, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_OUTPUT}}; | |
| 3678 | 3678 | |
| 3679 | 3679 | set_input_pins(input_pins, ARRAY_LEN(input_pins)); |
| 3680 | 3680 | set_output_pins(output_pins, ARRAY_LEN(output_pins)); |
| r25360 | r25361 | |
| 3691 | 3691 | { |
| 3692 | 3692 | static UINT16 input_pins[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}; |
| 3693 | 3693 | static pin_output_config output_pins[] = { |
| 3694 | ||
| 3694 | {14, OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED}, | |
| 3695 | 3695 | {15, OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED}, |
| 3696 | 3696 | {16, OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED}, |
| 3697 | 3697 | {17, OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED}, |
| r25360 | r25361 | |
| 3700 | 3700 | {20, OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED}, |
| 3701 | 3701 | {21, OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED}, |
| 3702 | 3702 | {22, OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED}, |
| 3703 | ||
| 3703 | {23, OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED}}; | |
| 3704 | 3704 | |
| 3705 | 3705 | set_input_pins(input_pins, ARRAY_LEN(input_pins)); |
| 3706 | 3706 | set_output_pins(output_pins, ARRAY_LEN(output_pins)); |
| r25360 | r25361 | |
| 3721 | 3721 | |
| 3722 | 3722 | output_pin_count = 0; |
| 3723 | 3723 | |
| 3724 | for (index = 0; index < pal->pinfuserowscount; ++index) | |
| 3725 | { | |
| 3726 | if (does_output_enable_fuse_row_allow_output(pal, jed, pal->pinfuserows[index].fuserowoutputenable)) | |
| 3727 | { | |
| 3728 | output_pins[output_pin_count].pin = pal->pinfuserows[index].pin; | |
| 3729 | output_pins[output_pin_count].flags = OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_OUTPUT; | |
| 3724 | for (index = 0; index < pal->pinfuserowscount; ++index) | |
| 3725 | { | |
| 3726 | if (does_output_enable_fuse_row_allow_output(pal, jed, pal->pinfuserows[index].fuserowoutputenable)) | |
| 3727 | { | |
| 3728 | output_pins[output_pin_count].pin = pal->pinfuserows[index].pin; | |
| 3729 | output_pins[output_pin_count].flags = OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_OUTPUT; | |
| 3730 | 3730 | |
| 3731 | 3731 | if (jed_get_fuse(jed, 1832 + (9 - index))) |
| 3732 | 3732 | { |
| r25360 | r25361 | |
| 3737 | 3737 | output_pins[output_pin_count].flags |= OUTPUT_ACTIVEHIGH; |
| 3738 | 3738 | } |
| 3739 | 3739 | |
| 3740 | ++output_pin_count; | |
| 3741 | } | |
| 3742 | } | |
| 3740 | ++output_pin_count; | |
| 3741 | } | |
| 3742 | } | |
| 3743 | 3743 | |
| 3744 | 3744 | set_input_pins(input_pins, ARRAY_LEN(input_pins)); |
| 3745 | 3745 | set_output_pins(output_pins, output_pin_count); |
| r25360 | r25361 | |
| 3760 | 3760 | |
| 3761 | 3761 | output_pin_count = 0; |
| 3762 | 3762 | |
| 3763 | for (index = 0; index < pal->pinfuserowscount; ++index) | |
| 3764 | { | |
| 3765 | if (does_output_enable_fuse_row_allow_output(pal, jed, pal->pinfuserows[index].fuserowoutputenable)) | |
| 3766 | { | |
| 3767 | output_pins[output_pin_count].pin = pal->pinfuserows[index].pin; | |
| 3768 | output_pins[output_pin_count].flags = OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_OUTPUT; | |
| 3763 | for (index = 0; index < pal->pinfuserowscount; ++index) | |
| 3764 | { | |
| 3765 | if (does_output_enable_fuse_row_allow_output(pal, jed, pal->pinfuserows[index].fuserowoutputenable)) | |
| 3766 | { | |
| 3767 | output_pins[output_pin_count].pin = pal->pinfuserows[index].pin; | |
| 3768 | output_pins[output_pin_count].flags = OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_OUTPUT; | |
| 3769 | 3769 | |
| 3770 | 3770 | if (jed_get_fuse(jed, 1096 + (9 - index))) |
| 3771 | 3771 | { |
| r25360 | r25361 | |
| 3776 | 3776 | output_pins[output_pin_count].flags |= OUTPUT_ACTIVEHIGH; |
| 3777 | 3777 | } |
| 3778 | 3778 | |
| 3779 | ++output_pin_count; | |
| 3780 | } | |
| 3781 | } | |
| 3779 | ++output_pin_count; | |
| 3780 | } | |
| 3781 | } | |
| 3782 | 3782 | |
| 3783 | 3783 | set_input_pins(input_pins, ARRAY_LEN(input_pins)); |
| 3784 | 3784 | set_output_pins(output_pins, output_pin_count); |
| Previous | 199869 Revisions | Next |