From 32aee75462ebe1b03daa00873198b41f1b1a6282 Mon Sep 17 00:00:00 2001 From: Jeremy Rand Date: Fri, 18 Dec 2020 00:50:01 -0500 Subject: [PATCH] Add the segment, spider and extra life sounds. Add some more information about the mysterious crash. --- BUGS.md | 3 + BuGS.xcodeproj/project.pbxproj | 2 + BuGS/gamePlayer.s | 2 +- BuGS/gameSound.s | 212 +++++++++++++++++++++++++++++++-- BuGS/gameSpider.s | 3 + BuGS/level.s | 2 + BuGS/main.c | 9 ++ BuGS/main.h | 1 + BuGS/main.rez | 1 + BuGS/sound/extralife.raw | 6 + 10 files changed, 227 insertions(+), 14 deletions(-) create mode 100644 BuGS/sound/extralife.raw diff --git a/BUGS.md b/BUGS.md index 173e98b..692d2af 100644 --- a/BUGS.md +++ b/BUGS.md @@ -7,6 +7,9 @@ This is a list of the software bugs (as opposed to the bugs in the game that you * I am thinking this is the same crash as the one which follows. I tried to reproduce this on real HW again with that debug in place but could not. * I reproduced a crash on GSPlus after dying and starting a new game. From the stack, it was clear it was trying to draw a body segment but the jump instruction was set to garbage. I am hoping this is the same crash as the one saw on real HW. * I have added some debug code to detect this. I am validating that the offset into the draw table for head and body segments is "sane" and if not brk. + * I reproduced it and ended up at brk $4 with y set to $2270 which is much larger than the max of 156. Also odd is that X is 1 but I think it needs to be an even number. + * In order to get the wrong value in Y, I noticed that the segmentSpriteOffset was overwritten with the pattern 70 02 70 02, etc. + * Something is trashing memory. * A spider moving left to right went off screen and left garbage on the RHS as it exited. I have only seen this once. I think it coincided with the player dying. * Sometimes when the player dies, the "you can shoot" indicator is left behind as garbage on-screen. diff --git a/BuGS.xcodeproj/project.pbxproj b/BuGS.xcodeproj/project.pbxproj index 2f403fe..5126615 100644 --- a/BuGS.xcodeproj/project.pbxproj +++ b/BuGS.xcodeproj/project.pbxproj @@ -46,6 +46,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 9D0DC8EF258C715E00DE9E87 /* extralife.raw */ = {isa = PBXFileReference; lastKnownFileType = text; path = extralife.raw; sourceTree = ""; }; 9D1553DE257ACA1800657188 /* ACKNOWLEDGEMENTS.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = ACKNOWLEDGEMENTS.md; sourceTree = ""; }; 9D1553E9257F3E5200657188 /* fire.raw */ = {isa = PBXFileReference; lastKnownFileType = file; path = fire.raw; sourceTree = ""; }; 9D1553EA257F3E5200657188 /* bonus.raw */ = {isa = PBXFileReference; lastKnownFileType = file; path = bonus.raw; sourceTree = ""; }; @@ -123,6 +124,7 @@ isa = PBXGroup; children = ( 9D1553EA257F3E5200657188 /* bonus.raw */, + 9D0DC8EF258C715E00DE9E87 /* extralife.raw */, 9D1553EB257F3E5200657188 /* death.raw */, 9D1553E9257F3E5200657188 /* fire.raw */, 9D1553EC257F3E5200657188 /* kill.raw */, diff --git a/BuGS/gamePlayer.s b/BuGS/gamePlayer.s index 100e40a..54bf859 100644 --- a/BuGS/gamePlayer.s +++ b/BuGS/gamePlayer.s @@ -71,7 +71,7 @@ playerAddLife entry lda #TILE_PLAYER sta tileType,x _dirtyNonGameTile - rtl + jmp playExtraLifeSound updatePlayer entry diff --git a/BuGS/gameSound.s b/BuGS/gameSound.s index d438574..cd9043f 100644 --- a/BuGS/gameSound.s +++ b/BuGS/gameSound.s @@ -27,7 +27,12 @@ SOUND_HALTED equ 1 SOUND_STARTED equ 0 SPIDER_SOUND_ADDR equ $0000 -SPIDER_SOUND_SIZE equ 6 +SPIDER_OSC_NUM equ 8 +SPIDER_FREQ_HIGH equ 0 +SPIDER_FREQ_LOW equ 214 +SPIDER_VOLUME equ 255 +SPIDER_CONTROL equ 6 +SPIDER_SIZE equ $36 DEATH_SOUND_ADDR equ $4000 DEATH_OSC_NUM equ 5 @@ -38,9 +43,22 @@ DEATH_CONTROL equ 2 DEATH_SIZE equ $36 SEGMENTS_SOUND_ADDR equ $7000 -SEGMENTS_SOUND_SIZE equ 4 +SEGMENTS_OSC_NUM equ 6 +SEGMENTS_FREQ_HIGH equ 0 +SEGMENTS_FREQ_LOW equ 214 +SEGMENTS_VOLUME equ 255 +SEGMENTS_CONTROL equ 6 +SEGMENTS_SIZE equ $24 -BONUS_SOUND_ADDR equ $8000 +EXTRA_LIFE_SOUND_ADDR equ $8000 +EXTRA_LIFE_OSC_NUM equ 10 +EXTRA_LIFE_FREQ_HIGH equ 0 +EXTRA_LIFE_FREQ_LOW equ 107 +EXTRA_LIFE_VOLUME equ 255 +EXTRA_LIFE_CONTROL equ 2 +EXTRA_LIFE_SIZE equ $36 + +BONUS_SOUND_ADDR equ $b000 BONUS_OSC_NUM equ 0 BONUS_FREQ_HIGH equ 0 BONUS_FREQ_LOW equ 214 @@ -48,7 +66,7 @@ BONUS_VOLUME equ 255 BONUS_CONTROL equ 2 BONUS_SIZE equ $24 -KILL_SOUND_ADDR equ $9000 +KILL_SOUND_ADDR equ $c000 KILL_OSC_NUM equ 4 KILL_FREQ_HIGH equ 0 KILL_FREQ_LOW equ 214 @@ -56,7 +74,7 @@ KILL_VOLUME equ 255 KILL_CONTROL equ 2 KILL_SIZE equ $24 -FIRE_SOUND_ADDR equ $a000 +FIRE_SOUND_ADDR equ $d000 FIRE_OSC_NUM equ 3 FIRE_FREQ_HIGH equ 0 FIRE_FREQ_LOW equ 214 @@ -135,6 +153,54 @@ soundInit_writeRegLow anop ; Spider sound pea SPIDER_SOUND_ADDR jsl loadSpiderSound + + lda #SPIDER_FREQ_LOW + ldx #SOUND_REG_FREQ_LOW+SPIDER_OSC_NUM + jsl writeSoundReg + + lda #SPIDER_FREQ_HIGH + ldx #SOUND_REG_FREQ_HIGH+SPIDER_OSC_NUM + jsl writeSoundReg + + lda #SPIDER_VOLUME + ldx #SOUND_REG_VOLUME+SPIDER_OSC_NUM + jsl writeSoundReg + + lda #SPIDER_SIZE + ldx #SOUND_REG_SIZE+SPIDER_OSC_NUM + jsl writeSoundReg + + lda #SPIDER_SOUND_ADDR/256 + ldx #SOUND_REG_POINTER+SPIDER_OSC_NUM + jsl writeSoundReg + + lda #SPIDER_CONTROL+SOUND_HALTED + ldx #SOUND_REG_CONTROL+SPIDER_OSC_NUM + jsl writeSoundReg + + lda #SPIDER_FREQ_LOW + ldx #SOUND_REG_FREQ_LOW+SPIDER_OSC_NUM+1 + jsl writeSoundReg + + lda #SPIDER_FREQ_HIGH + ldx #SOUND_REG_FREQ_HIGH+SPIDER_OSC_NUM+1 + jsl writeSoundReg + + lda #SPIDER_VOLUME + ldx #SOUND_REG_VOLUME+SPIDER_OSC_NUM+1 + jsl writeSoundReg + + lda #SPIDER_SIZE + ldx #SOUND_REG_SIZE+SPIDER_OSC_NUM+1 + jsl writeSoundReg + + lda #SPIDER_SOUND_ADDR/256 + ldx #SOUND_REG_POINTER+SPIDER_OSC_NUM+1 + jsl writeSoundReg + + lda #SPIDER_CONTROL+SOUND_HALTED + ldx #SOUND_REG_CONTROL+SPIDER_OSC_NUM+1 + jsl writeSoundReg ; Death sound @@ -169,6 +235,54 @@ soundInit_writeRegLow anop ; Segments sound pea SEGMENTS_SOUND_ADDR jsl loadSegmentsSound + + lda #SEGMENTS_FREQ_LOW + ldx #SOUND_REG_FREQ_LOW+SEGMENTS_OSC_NUM + jsl writeSoundReg + + lda #SEGMENTS_FREQ_HIGH + ldx #SOUND_REG_FREQ_HIGH+SEGMENTS_OSC_NUM + jsl writeSoundReg + + lda #SEGMENTS_VOLUME + ldx #SOUND_REG_VOLUME+SEGMENTS_OSC_NUM + jsl writeSoundReg + + lda #SEGMENTS_SIZE + ldx #SOUND_REG_SIZE+SEGMENTS_OSC_NUM + jsl writeSoundReg + + lda #SEGMENTS_SOUND_ADDR/256 + ldx #SOUND_REG_POINTER+SEGMENTS_OSC_NUM + jsl writeSoundReg + + lda #SEGMENTS_CONTROL+SOUND_HALTED + ldx #SOUND_REG_CONTROL+SEGMENTS_OSC_NUM + jsl writeSoundReg + + lda #SEGMENTS_FREQ_LOW + ldx #SOUND_REG_FREQ_LOW+SEGMENTS_OSC_NUM+1 + jsl writeSoundReg + + lda #SEGMENTS_FREQ_HIGH + ldx #SOUND_REG_FREQ_HIGH+SEGMENTS_OSC_NUM+1 + jsl writeSoundReg + + lda #SEGMENTS_VOLUME + ldx #SOUND_REG_VOLUME+SEGMENTS_OSC_NUM+1 + jsl writeSoundReg + + lda #SEGMENTS_SIZE + ldx #SOUND_REG_SIZE+SEGMENTS_OSC_NUM+1 + jsl writeSoundReg + + lda #SEGMENTS_SOUND_ADDR/256 + ldx #SOUND_REG_POINTER+SEGMENTS_OSC_NUM+1 + jsl writeSoundReg + + lda #SEGMENTS_CONTROL+SOUND_HALTED + ldx #SOUND_REG_CONTROL+SEGMENTS_OSC_NUM+1 + jsl writeSoundReg ; Bonus sound @@ -303,7 +417,35 @@ soundInit_writeRegLow anop lda #FIRE_CONTROL+SOUND_HALTED ldx #SOUND_REG_CONTROL+FIRE_OSC_NUM jsl writeSoundReg - + +; Extra life sound + pea EXTRA_LIFE_SOUND_ADDR + jsl loadExtraLifeSound + + lda #EXTRA_LIFE_FREQ_LOW + ldx #SOUND_REG_FREQ_LOW+EXTRA_LIFE_OSC_NUM + jsl writeSoundReg + + lda #EXTRA_LIFE_FREQ_HIGH + ldx #SOUND_REG_FREQ_HIGH+EXTRA_LIFE_OSC_NUM + jsl writeSoundReg + + lda #EXTRA_LIFE_VOLUME + ldx #SOUND_REG_VOLUME+EXTRA_LIFE_OSC_NUM + jsl writeSoundReg + + lda #EXTRA_LIFE_SIZE + ldx #SOUND_REG_SIZE+EXTRA_LIFE_OSC_NUM + jsl writeSoundReg + + lda #EXTRA_LIFE_SOUND_ADDR/256 + ldx #SOUND_REG_POINTER+EXTRA_LIFE_OSC_NUM + jsl writeSoundReg + + lda #EXTRA_LIFE_CONTROL+SOUND_HALTED + ldx #SOUND_REG_CONTROL+EXTRA_LIFE_OSC_NUM + jsl writeSoundReg + rtl @@ -332,6 +474,11 @@ playBonusSound_noWrap anop playDeathSound entry + jsl stopSpiderSound + jsl stopFleaSound + jsl stopScorpionSound + jsl stopSegmentSound + lda #DEATH_CONTROL+SOUND_HALTED ldx #SOUND_REG_CONTROL+DEATH_OSC_NUM jsl writeSoundReg @@ -353,11 +500,6 @@ playKillSound entry rtl -playExtraLifeSound entry -; Write this code... - rtl - - playFireSound entry lda #FIRE_CONTROL+SOUND_HALTED ldx #SOUND_REG_CONTROL+FIRE_OSC_NUM @@ -367,15 +509,59 @@ playFireSound entry ldx #SOUND_REG_CONTROL+FIRE_OSC_NUM jsl writeSoundReg rtl + +playExtraLifeSound entry + lda #EXTRA_LIFE_CONTROL+SOUND_HALTED + ldx #SOUND_REG_CONTROL+EXTRA_LIFE_OSC_NUM + jsl writeSoundReg + lda #EXTRA_LIFE_CONTROL + ldx #SOUND_REG_CONTROL+EXTRA_LIFE_OSC_NUM + jsl writeSoundReg + rtl + + + +startSegmentSound entry + jsl stopSegmentSound + + lda #SEGMENTS_CONTROL + ldx #SOUND_REG_CONTROL+SEGMENTS_OSC_NUM + jsl writeSoundReg + rtl + + +stopSegmentSound entry + lda #SEGMENTS_CONTROL+SOUND_HALTED + ldx #SOUND_REG_CONTROL+SEGMENTS_OSC_NUM + jsl writeSoundReg + + lda #SEGMENTS_CONTROL+SOUND_HALTED + ldx #SOUND_REG_CONTROL+SEGMENTS_OSC_NUM+1 + jsl writeSoundReg + + rtl + + startSpiderSound entry -; Write this code... + jsl stopSpiderSound + + lda #SPIDER_CONTROL + ldx #SOUND_REG_CONTROL+SPIDER_OSC_NUM + jsl writeSoundReg rtl stopSpiderSound entry -; Write this code... + lda #SPIDER_CONTROL+SOUND_HALTED + ldx #SOUND_REG_CONTROL+SPIDER_OSC_NUM + jsl writeSoundReg + + lda #SPIDER_CONTROL+SOUND_HALTED + ldx #SOUND_REG_CONTROL+SPIDER_OSC_NUM+1 + jsl writeSoundReg + rtl diff --git a/BuGS/gameSpider.s b/BuGS/gameSpider.s index 67e9d50..957a02f 100644 --- a/BuGS/gameSpider.s +++ b/BuGS/gameSpider.s @@ -559,6 +559,7 @@ updateSpider_downChangeDirDiagRight anop rtl updateSpider_offScreen anop + jsl stopSpiderSound stz spiderState rtl @@ -569,6 +570,7 @@ addSpider entry rtl addSpider_checkSpeed anop + jsl startSpiderSound lda gameScore+2 bne addSpider_fast lda gameScore @@ -862,6 +864,7 @@ explodeSpider entry lda spiderScreenOffset inc a sta spiderScreenOffset + jsl stopSpiderSound explodeSpider_done anop rtl diff --git a/BuGS/level.s b/BuGS/level.s index e2359ec..e1dfd78 100644 --- a/BuGS/level.s +++ b/BuGS/level.s @@ -29,6 +29,7 @@ levelInit entry levelStart entry lda colourLevelNum jsl setColour + jsl startSegmentSound ldx centipedeLevelNum lda levelTable,x @@ -89,6 +90,7 @@ updateLevel_checkSegments anop bne updateLevel_done lda #NEXT_LEVEL_FRAME_COUNT sta nextLevelFrameCount + jsl stopSegmentSound updateLevel_done anop rtl diff --git a/BuGS/main.c b/BuGS/main.c index a383df0..b7415cf 100644 --- a/BuGS/main.c +++ b/BuGS/main.c @@ -100,6 +100,15 @@ void loadFireSound(word addr) } +void loadExtraLifeSound(word addr) +{ + Handle handle = LoadResource(rRawSound, EXTRA_LIFE_SOUND); + HLock(handle); + WriteRamBlock(*handle, addr, GetHandleSize(handle)); + HUnlock(handle); +} + + int main(void) { int event; diff --git a/BuGS/main.h b/BuGS/main.h index 80d0c4e..2855d21 100644 --- a/BuGS/main.h +++ b/BuGS/main.h @@ -23,6 +23,7 @@ #define KILL_SOUND 6 #define SEGMENTS_SOUND 7 #define SPIDER_SOUND 8 +#define EXTRA_LIFE_SOUND 9 #endif /* defined(_GUARD_PROJECTBuGS_FILEmain_) */ diff --git a/BuGS/main.rez b/BuGS/main.rez index 7982854..05c693b 100644 --- a/BuGS/main.rez +++ b/BuGS/main.rez @@ -54,3 +54,4 @@ read rRawSound (FIRE_SOUND) "sound/fire.raw"; read rRawSound (KILL_SOUND) "sound/kill.raw"; read rRawSound (SEGMENTS_SOUND) "sound/segments.raw"; read rRawSound (SPIDER_SOUND) "sound/spider.raw"; +read rRawSound (EXTRA_LIFE_SOUND) "sound/extralife.raw"; diff --git a/BuGS/sound/extralife.raw b/BuGS/sound/extralife.raw new file mode 100644 index 0000000..5bc3b99 --- /dev/null +++ b/BuGS/sound/extralife.raw @@ -0,0 +1,6 @@ +RouxuxjfZ?FSk|p|dv}yvy|[S[\j}abn±wkOXsvf^jmqzy|whuo{~_tpgc`oitmhLtzy{yht|{zkq|}{dpw{{osqxrzmpu}qc{rvyorkszquz~{z}a_trmkvbdri|ql{}zVstrbUnkqotv}~fZ|w\aqk~sopzyYsywlXgowvqvx|gZ~}vvYVnkyxst|Zl|xtgPclo{nqtwr[~|vrZTigxwolu}|do{zwnUbop~tqq||zpY|wxaSmnyx{rry~~|ah|vmS`st~sqq}xwYx{taSgo}rop|~|cbrlW\no|tps~w|XsyueRfmyyqqz~g^yt\\on~uxoo|\syrkRamwkvyd}dXk[^wklnsgrlvsxzqU]pltlmt~]dtpp\gxtqlr[Y{ur`i~usifz{^Wyvxch{qzqflQ}qufdjnnh~nMt{g`|`mpdypFvzl^dqwog=ulq`UgvziwtCrloaZhrthtxEohmeZjnoajDbptm]~fiohnG`tsn[whmsiiHYrljZrmmsljP]vojSknovifUTymlYiqlsmfYRyor[guiqmg[L|pr\euhqmdbInp]`}hrpcziHno]\kpneynGyno^ZkqpdwxFumpaYiqpfs}JtorbXjsqdqLpotgY{hlqhnJershUvkqshlLcoplYuimsjiS]tomZmolrlfUWxrpYillsmgYVvmnZhsfopi^^tjuuky|zskmltfyfrz|]vuxxVjl}yqkmh]e|fnxygrc@7Zsc]}˶ec];4XbI@h˳ĩ}qqP7PbF8`ͰtwWAVfI.N{ɨ_J]nS=Y~Ÿ{{xUJdoS=\â~|rNCXaI?_¡{vqPC]dG<_Ȥ}ZKbfD8\}z~ȣ^MhlH:ax}[SmsRHku{YSquUQvr}sONlkMPxqyqNGegIMvv~sQMijKJsw~qPLfeIKss}pNOjjORynzkJNokLSrzjHKicGP|w|fGOjcFS}zfGRk^DSy~|jJUm`ET{u~iIUpdH[vhHSpcES}xdFVqcEX~u|bDUq`AU{hK\vbF[{vcFXu`C[yw{^FZq]E`vw{]G]r\GavswZBWo\Eazwz]G]qYDbwx{\G_rT=c͹xlXd`4:O_}زrSbR/ShxxnWPuU@gȏk\G)?h=Lӳ^7$!JR&[ҮпU3+,L7'kغٱyR=:Pp=:~͐uV@Ggf-X¾z]=9HlN0vȢ֦lS73Ie2Bˠ؊\@+(NV$WƤy\A.+YA"mҳkQ8/Ai44ǚՐjO75[e,WϽyY7,7`F'oخ۬oS0(@b3>Σ؍cG//RZ(Wӻz_?.7gN.w˩֤lW8.Gk1:ǘҎkM41Zc+\v]:,5bH)s֭ڧkT3(>g9AРڌcH1,O]%Uϻx]>08hQ.tЮѥiN2.Bk;?˜όeF12Sd/XϾ{_=6:aN*nʬڰtX97Ef57ǢܔnL41JV!Nģc=.1YL)qҶ֨lQ2/4өؗdJ3-Gb,Iǜ~\A52ZZ-iθзrV819bA3}ΩӘhJ4/Ca2L͢Έc?0.ST(`ҼзtT5/6aA2|խ֛eD/-Fg3Kś˂_>02XX,eизuX93;cA2{֛ͩgI0-Db1Iˠυa@0/UU'cԼзpT8/4cB3ԪٟjM3,Fe,E˚΀]?/+VY(gپӹoW8-7eD0~Σ؝iP81Kj2HǗӊeG51XW%\ѽӾvW9-0]A.yױܣiH1,Cb.Fʜσ_>./TV'dӼѻuY8/7aA/zЫ۝jN40Db.FɞӆgF4/U\'`μͺs[:26aB.zԲݧlL2/?^/@ͤч_9*0QV+bӽʻtZ=08dJ1zάСgJ4-Cd5D̟ЋgG31V[*`ͺ̺w^<3:cD,t˫٧pO61Fe4BƝҋcE6-PX'Záx\910YG.t۹̤gI:4"Nnq}ǷZYvicdh^gt|rgzhflVbz|o|hQMijgTavyrSSe{oYhppoYMgyfPesw`TizeM_x}hTgx\G[wţgN_hQ8Tvxzʹ^HYeF7YĵßwutO8UfPd\-fдx`GAOvF2x͗pXJKdv:QāeHGSo]0l¥Ͱs[=7Dh?:˥٘bE62H]*LƠЃaE5.UM"e̶׷qT>7>hB3{ȟіlL75Sm2QȾ~_A9;bV*iӳҳqW4+a,@Фшa=/-RT%_м̹uY72;dH3z˨՛kN78Kg5LǾ̃eD8;]\+cdzιyc@8@eD3{ɧٞmS41Hd.FƝτfG48\[,dʹɴqZ:/;fH3}Ω՟jS62Ih5FƚυbB00U],aнɺw\=48cK3xͫҞiM52Eg8DȠЎkH84SZ+]˺ͽ{\907]C1uѯҞkL11Df;Lŝʇa>14U^/_̺ǻ{]:4:dN6xɧТlN55Ih9BĝύhF67Xa.^˸ȼwX719bL2x˪ӢmP76Ij9DƛόeD45U_+Z˹z_@69eO2u˫ҥmR96Eh9?ǝЎgG76Vf.[˽z^>67`L,qͭԩoQ86Ei<@ɡюdC43Qa.Y˻¾z[;7;aS6wɯˡhL79Fg?FˎfG;9Ud2Y˽}^>47aM,nͯԫsW:2@e:?̡ϋbD10O^.]ξĿw\:18aP1vͰФkS63Bg>Bŝ̋fI::Wf3[Ⱥ|^=59_P.pʭϩnT;8Dg==ʤՓhH62M^+SĀbA67]Q.nγӫpU72?d::ɡՒiI41Na-Vƛ{]:-/\P,qѲѪmR50>iA?̣ӑeJ71M_+SyZ;37bV3t̮ͧnU75Dh>>ÞҒlL85Qb,U~c@57aV)j̴ӱs\<79kF8̦ԗkP;8Ao8GΚЇkH@5Lp1Y͒ƃjDH2Ti/cōbBL1`b5mŽ|VDL5k[:mǴé{RHG5oYDxȬ¢qLNHcy\X]?iq;lt\[\Csj7ps`^X?s\8{ȧo`_R>vP<¡̝kZ_LDyHDțϕgS_EHw_u=d|]T`?fo=ly]Y_@md=px]ZYFwZ:wǨtZ]TCzSle9ss]\V@w^9tũw\[Q=pP?}âkV[MJzLGŗ˖iYbEHu@JǚȋcTV@QoA]cVaHZt?^ò~l"%LJٌ88%1yJ>1sHJ1, OT0# .%@Y! y0%(6`%' u>$!&,o'4r+,{ XL "%$((6PC%*+")JQ #&)6f"&.q3#/%1t%0!*8#1G*/9mdU9ҾmWG"H`Ob@@VJVChܯ8/:OP ${&,E?uнʼn3BTG׷g2^P廱l46֎#6*fӞ8&D4\ӷǝ?0MAfի0 QOl긷( @Dbǭ9*,EV546i$BC<ݼn#CUJ߿l7WPѱr(H?ݾʒ+'E3aзʤD:S:[G>dN`ƛC8eWeҡB)WSaۮK$LKVܷX'KJLٷc)INL׹c%DQOòh 8JG̹v$4F=κƅ,3E7tͷʑ35K8i˲ę<6Q?gͭ<.QDcֱ?'LBX۴K'LERڳS#KIL޶\!GKGέcAPIïi#HHc޹CFG[㾺LAFPV?GK`?JJ´e ;MKɵj4JEδw 0L@ϲ".Q@vկ)*R@jح/#RFhݲ2$GEzͪi/4~^,pr5]ϭu2+KMTY^pMavfEawijn=?cͧN%Kgʨz74KjͲg5OTz[WXeo]u]}ahuz]c}qtScz|Q[ksqQ^k[cnoq]nzrUly}]LkdI\lWJcvkL]h[Vhqs\jlaizxnez}oUmtURnmK\of\ilfvsxpv{yphzware`~v_p~hd}x{cx|hn{~rd~~`n~oazxbr|zmh|wax}cfo[v~`g}}q`zzbp~me|z_rie|y{at{jk}wxcz{dn}m`z||^n{kbzw}`py|kg{vzbwzfi|xtawybm{xpbxubpxymf{u{_rw~fgyvv_tuciyvqaxwao||lc|y{^s|gf}xv_uzdh|xr_wzbm{znbyx|_oz}lf|xzarzgi{yvbvyek{zscxydmzzncxx|`q~jf}|x`t|eg}|uawzdk|{qbzz~ap~}kd|zz_r|fd{yx_txdhzxtaxxal{{k`z{{^o{~hczxy^szfg{ytawzcl}{obyz~an|}ldzy}bqz~igzyv`tzfk{ztbxycm{zobyxblz|jayxz`qz~ge{zu^uzci|zp^vx~`m{|lb{x{^p{~gczyw^u{eh~{s_x{bl}|oazy}`o{}hczxy_szfh|wu^wzbj}yr_vx_kzzmazy{`p{if}{vavzfk}ytaxzclzymazx~al|~kby{z`rz~fc|vy_tzgj}{raxybl}zma}y~_rie}yx_u~fh}ytcvycg|}o|M7sV +dE. +c +3C)5TĵX(KVO˰Å9HD k6* a !|w + +-:x IB۷$"JFqĘ1"A8^ȧ:?6\ǡ98@[»;EFV꼷QCIC翾`5<=a '6=Ǻb DJڲn2ZQɠ{$6]I{̬‘45Q@jЭ5)QGk۳9%MLe٭D,UP]ҩS.\ZYթX*PTQүg-QZPնo-FNAϻ}/BM?ȷ'0D8{Ҿʉ*.E:vҷË,,L=pӴÕ5,L=bշť?&H;W޼ǬBB:SðE@@P缹KELT潴UENM߻c!ANGn!:JAȸt 5J?δw1MAб#.PAyү+/R@nհ1(M>e۵ß5"K>_޴:!KE`ᵺAJGVⷺM GDK޹Y!CEGûd=JDók:OEȰv!6OB˲%3M@}Ҵ(+J@wص*'NDrر0&NDjڵ?%KDZܵI#HCRἺOBFLºV͹{$-H?}ն‹)+L?oٲ-%NBhݵ3H?]:HAY滾<@>eϼ~;'gk>]ي(#D޹D)EoYH\UOUwuIQm}O;[wӱj$6^سM-CZ̹;JTekJ^fYpgjr`suqa}uW[x`SikSWn}c^ph`i|{Z`y}jLc~tMNe{gC[p{SQavmMcoz^fm{k_{vtbq}~]ayfTg{}SSkuv]fi|mouo}qzg{z|kis\wdc|}r^y{dk}pe{zct|hb~y_q}if}w{cw|fm{saz~~`k|o_{zbq}zne}yz`x~gg|u`x{dk~ytc{ycs|me|y]tec|{v\szfgyvu`xxfn|ypc|zcq}~mg|x~bt{|kj~x{dy{fl}xtaxxcn|zrcyvcpy{kf|y{bv|gh}yt`wycl|xscywcp|{mf|x|`t{}jh}w{bvygj|wt`yxcn|zobzw~apz{id{vz_ryfg|xu_v{cj}{o`yyap}|nd{y{ar|~if~{waw~ei~ztaz{cl~zrc{ycp}{md}z|au~hf{x_v|cjzsaz{co{ob|y}`s~~jd~yz`v|ei~yvay{enzqb{xan{|jb{x{^r{ge{xu^tzch|zq`vyam||mc{z{`q~jf~{xav}gh}zuawzek|{sdzzbp}{nd}z|`t|~hf|xx_uydh|xtayzdlzzoaxx}`p{}je|xz^u}fg}xt]vzbi~{q^|z_p~zob{y|cq|jh|x{`w{gj}zs`yybn}{pbzx`r|zldx|`u{hg{yv`tzfh}zs_zydo}rk \ No newline at end of file