ref: 01aa306241cded28cf14e20744138a7551a9ff4d
parent: 287fcaf8a0877fb0c2abaadc0ceeda6fe482cc3b
author: Jacob Moody <moody@posixcafe.org>
date: Mon May 15 16:41:42 EDT 2023
initial view implementation
--- /dev/null
+++ b/dex.c
@@ -1,0 +1,895 @@
+#include <u.h>
+#include <libc.h>
+
+char *dexfiletab[] = {
+ [0] "bulbasaur",
+ [1] "ivysaur",
+ [2] "venusaur",
+ [3] "charmander",
+ [4] "charmeleon",
+ [5] "charizard",
+ [6] "squirtle",
+ [7] "wartortle",
+ [8] "blastoise",
+ [9] "caterpie",
+ [10] "metapod",
+ [11] "butterfree",
+ [12] "weedle",
+ [13] "kakuna",
+ [14] "beedrill",
+ [15] "pidgey",
+ [16] "pidgeotto",
+ [17] "pidgeot",
+ [18] "rattata",
+ [19] "raticate",
+ [20] "spearow",
+ [21] "fearow",
+ [22] "ekans",
+ [23] "arbok",
+ [24] "pikachu",
+ [25] "raichu",
+ [26] "sandshrew",
+ [27] "sandslash",
+ [28] "nidoran-f",
+ [29] "nidorina",
+ [30] "nidoqueen",
+ [31] "nidoran-m",
+ [32] "nidorino",
+ [33] "nidoking",
+ [34] "clefairy",
+ [35] "clefable",
+ [36] "vulpix",
+ [37] "ninetales",
+ [38] "jigglypuff",
+ [39] "wigglytuff",
+ [40] "zubat",
+ [41] "golbat",
+ [42] "oddish",
+ [43] "gloom",
+ [44] "vileplume",
+ [45] "paras",
+ [46] "parasect",
+ [47] "venonat",
+ [48] "venomoth",
+ [49] "diglett",
+ [50] "dugtrio",
+ [51] "meowth",
+ [52] "persian",
+ [53] "psyduck",
+ [54] "golduck",
+ [55] "mankey",
+ [56] "primeape",
+ [57] "growlithe",
+ [58] "arcanine",
+ [59] "poliwag",
+ [60] "poliwhirl",
+ [61] "poliwrath",
+ [62] "abra",
+ [63] "kadabra",
+ [64] "alakazam",
+ [65] "machop",
+ [66] "machoke",
+ [67] "machamp",
+ [68] "bellsprout",
+ [69] "weepinbell",
+ [70] "victreebel",
+ [71] "tentacool",
+ [72] "tentacruel",
+ [73] "geodude",
+ [74] "graveler",
+ [75] "golem",
+ [76] "ponyta",
+ [77] "rapidash",
+ [78] "slowpoke",
+ [79] "slowbro",
+ [80] "magnemite",
+ [81] "magneton",
+ [82] "farfetchd",
+ [83] "doduo",
+ [84] "dodrio",
+ [85] "seel",
+ [86] "dewgong",
+ [87] "grimer",
+ [88] "muk",
+ [89] "shellder",
+ [90] "cloyster",
+ [91] "gastly",
+ [92] "haunter",
+ [93] "gengar",
+ [94] "onix",
+ [95] "drowzee",
+ [96] "hypno",
+ [97] "krabby",
+ [98] "kingler",
+ [99] "voltorb",
+ [100] "electrode",
+ [101] "exeggcute",
+ [102] "exeggutor",
+ [103] "cubone",
+ [104] "marowak",
+ [105] "hitmonlee",
+ [106] "hitmonchan",
+ [107] "lickitung",
+ [108] "koffing",
+ [109] "weezing",
+ [110] "rhyhorn",
+ [111] "rhydon",
+ [112] "chansey",
+ [113] "tangela",
+ [114] "kangaskhan",
+ [115] "horsea",
+ [116] "seadra",
+ [117] "goldeen",
+ [118] "seaking",
+ [119] "staryu",
+ [120] "starmie",
+ [121] "mr-mime",
+ [122] "scyther",
+ [123] "jynx",
+ [124] "electabuzz",
+ [125] "magmar",
+ [126] "pinsir",
+ [127] "tauros",
+ [128] "magikarp",
+ [129] "gyarados",
+ [130] "lapras",
+ [131] "ditto",
+ [132] "eevee",
+ [133] "vaporeon",
+ [134] "jolteon",
+ [135] "flareon",
+ [136] "porygon",
+ [137] "omanyte",
+ [138] "omastar",
+ [139] "kabuto",
+ [140] "kabutops",
+ [141] "aerodactyl",
+ [142] "snorlax",
+ [143] "articuno",
+ [144] "zapdos",
+ [145] "moltres",
+ [146] "dratini",
+ [147] "dragonair",
+ [148] "dragonite",
+ [149] "mewtwo",
+ [150] "mew",
+ [151] "chikorita",
+ [152] "bayleef",
+ [153] "meganium",
+ [154] "cyndaquil",
+ [155] "quilava",
+ [156] "typhlosion",
+ [157] "totodile",
+ [158] "croconaw",
+ [159] "feraligatr",
+ [160] "sentret",
+ [161] "furret",
+ [162] "hoothoot",
+ [163] "noctowl",
+ [164] "ledyba",
+ [165] "ledian",
+ [166] "spinarak",
+ [167] "ariados",
+ [168] "crobat",
+ [169] "chinchou",
+ [170] "lanturn",
+ [171] "pichu",
+ [172] "cleffa",
+ [173] "igglybuff",
+ [174] "togepi",
+ [175] "togetic",
+ [176] "natu",
+ [177] "xatu",
+ [178] "mareep",
+ [179] "flaaffy",
+ [180] "ampharos",
+ [181] "bellossom",
+ [182] "marill",
+ [183] "azumarill",
+ [184] "sudowoodo",
+ [185] "politoed",
+ [186] "hoppip",
+ [187] "skiploom",
+ [188] "jumpluff",
+ [189] "aipom",
+ [190] "sunkern",
+ [191] "sunflora",
+ [192] "yanma",
+ [193] "wooper",
+ [194] "quagsire",
+ [195] "espeon",
+ [196] "umbreon",
+ [197] "murkrow",
+ [198] "slowking",
+ [199] "misdreavus",
+ [200] "unown",
+ [201] "wobbuffet",
+ [202] "girafarig",
+ [203] "pineco",
+ [204] "forretress",
+ [205] "dunsparce",
+ [206] "gligar",
+ [207] "steelix",
+ [208] "snubbull",
+ [209] "granbull",
+ [210] "qwilfish",
+ [211] "scizor",
+ [212] "shuckle",
+ [213] "heracross",
+ [214] "sneasel",
+ [215] "teddiursa",
+ [216] "ursaring",
+ [217] "slugma",
+ [218] "magcargo",
+ [219] "swinub",
+ [220] "piloswine",
+ [221] "corsola",
+ [222] "remoraid",
+ [223] "octillery",
+ [224] "delibird",
+ [225] "mantine",
+ [226] "skarmory",
+ [227] "houndour",
+ [228] "houndoom",
+ [229] "kingdra",
+ [230] "phanpy",
+ [231] "donphan",
+ [232] "porygon2",
+ [233] "stantler",
+ [234] "smeargle",
+ [235] "tyrogue",
+ [236] "hitmontop",
+ [237] "smoochum",
+ [238] "elekid",
+ [239] "magby",
+ [240] "miltank",
+ [241] "blissey",
+ [242] "raikou",
+ [243] "entei",
+ [244] "suicune",
+ [245] "larvitar",
+ [246] "pupitar",
+ [247] "tyranitar",
+ [248] "lugia",
+ [249] "ho-oh",
+ [250] "celebi",
+ [251] "treecko",
+ [252] "grovyle",
+ [253] "sceptile",
+ [254] "torchic",
+ [255] "combusken",
+ [256] "blaziken",
+ [257] "mudkip",
+ [258] "marshtomp",
+ [259] "swampert",
+ [260] "poochyena",
+ [261] "mightyena",
+ [262] "zigzagoon",
+ [263] "linoone",
+ [264] "wurmple",
+ [265] "silcoon",
+ [266] "beautifly",
+ [267] "cascoon",
+ [268] "dustox",
+ [269] "lotad",
+ [270] "lombre",
+ [271] "ludicolo",
+ [272] "seedot",
+ [273] "nuzleaf",
+ [274] "shiftry",
+ [275] "taillow",
+ [276] "swellow",
+ [277] "wingull",
+ [278] "pelipper",
+ [279] "ralts",
+ [280] "kirlia",
+ [281] "gardevoir",
+ [282] "surskit",
+ [283] "masquerain",
+ [284] "shroomish",
+ [285] "breloom",
+ [286] "slakoth",
+ [287] "vigoroth",
+ [288] "slaking",
+ [289] "nincada",
+ [290] "ninjask",
+ [291] "shedinja",
+ [292] "whismur",
+ [293] "loudred",
+ [294] "exploud",
+ [295] "makuhita",
+ [296] "hariyama",
+ [297] "azurill",
+ [298] "nosepass",
+ [299] "skitty",
+ [300] "delcatty",
+ [301] "sableye",
+ [302] "mawile",
+ [303] "aron",
+ [304] "lairon",
+ [305] "aggron",
+ [306] "meditite",
+ [307] "medicham",
+ [308] "electrike",
+ [309] "manectric",
+ [310] "plusle",
+ [311] "minun",
+ [312] "volbeat",
+ [313] "illumise",
+ [314] "roselia",
+ [315] "gulpin",
+ [316] "swalot",
+ [317] "carvanha",
+ [318] "sharpedo",
+ [319] "wailmer",
+ [320] "wailord",
+ [321] "numel",
+ [322] "camerupt",
+ [323] "torkoal",
+ [324] "spoink",
+ [325] "grumpig",
+ [326] "spinda",
+ [327] "trapinch",
+ [328] "vibrava",
+ [329] "flygon",
+ [330] "cacnea",
+ [331] "cacturne",
+ [332] "swablu",
+ [333] "altaria",
+ [334] "zangoose",
+ [335] "seviper",
+ [336] "lunatone",
+ [337] "solrock",
+ [338] "barboach",
+ [339] "whiscash",
+ [340] "corphish",
+ [341] "crawdaunt",
+ [342] "baltoy",
+ [343] "claydol",
+ [344] "lileep",
+ [345] "cradily",
+ [346] "anorith",
+ [347] "armaldo",
+ [348] "feebas",
+ [349] "milotic",
+ [350] "castform",
+ [351] "kecleon",
+ [352] "shuppet",
+ [353] "banette",
+ [354] "duskull",
+ [355] "dusclops",
+ [356] "tropius",
+ [357] "chimecho",
+ [358] "absol",
+ [359] "wynaut",
+ [360] "snorunt",
+ [361] "glalie",
+ [362] "spheal",
+ [363] "sealeo",
+ [364] "walrein",
+ [365] "clamperl",
+ [366] "huntail",
+ [367] "gorebyss",
+ [368] "relicanth",
+ [369] "luvdisc",
+ [370] "bagon",
+ [371] "shelgon",
+ [372] "salamence",
+ [373] "beldum",
+ [374] "metang",
+ [375] "metagross",
+ [376] "regirock",
+ [377] "regice",
+ [378] "registeel",
+ [379] "latias",
+ [380] "latios",
+ [381] "kyogre",
+ [382] "groudon",
+ [383] "rayquaza",
+ [384] "jirachi",
+ [385] "deoxys",
+ [386] "turtwig",
+ [387] "grotle",
+ [388] "torterra",
+ [389] "chimchar",
+ [390] "monferno",
+ [391] "infernape",
+ [392] "piplup",
+ [393] "prinplup",
+ [394] "empoleon",
+ [395] "starly",
+ [396] "staravia",
+ [397] "staraptor",
+ [398] "bidoof",
+ [399] "bibarel",
+ [400] "kricketot",
+ [401] "kricketune",
+ [402] "shinx",
+ [403] "luxio",
+ [404] "luxray",
+ [405] "budew",
+ [406] "roserade",
+ [407] "cranidos",
+ [408] "rampardos",
+ [409] "shieldon",
+ [410] "bastiodon",
+ [411] "burmy",
+ [412] "wormadam",
+ [413] "mothim",
+ [414] "combee",
+ [415] "vespiquen",
+ [416] "pachirisu",
+ [417] "buizel",
+ [418] "floatzel",
+ [419] "cherubi",
+ [420] "cherrim",
+ [421] "shellos",
+ [422] "gastrodon",
+ [423] "ambipom",
+ [424] "drifloon",
+ [425] "drifblim",
+ [426] "buneary",
+ [427] "lopunny",
+ [428] "mismagius",
+ [429] "honchkrow",
+ [430] "glameow",
+ [431] "purugly",
+ [432] "chingling",
+ [433] "stunky",
+ [434] "skuntank",
+ [435] "bronzor",
+ [436] "bronzong",
+ [437] "bonsly",
+ [438] "mime-jr",
+ [439] "happiny",
+ [440] "chatot",
+ [441] "spiritomb",
+ [442] "gible",
+ [443] "gabite",
+ [444] "garchomp",
+ [445] "munchlax",
+ [446] "riolu",
+ [447] "lucario",
+ [448] "hippopotas",
+ [449] "hippowdon",
+ [450] "skorupi",
+ [451] "drapion",
+ [452] "croagunk",
+ [453] "toxicroak",
+ [454] "carnivine",
+ [455] "finneon",
+ [456] "lumineon",
+ [457] "mantyke",
+ [458] "snover",
+ [459] "abomasnow",
+ [460] "weavile",
+ [461] "magnezone",
+ [462] "lickilicky",
+ [463] "rhyperior",
+ [464] "tangrowth",
+ [465] "electivire",
+ [466] "magmortar",
+ [467] "togekiss",
+ [468] "yanmega",
+ [469] "leafeon",
+ [470] "glaceon",
+ [471] "gliscor",
+ [472] "mamoswine",
+ [473] "porygon-z",
+ [474] "gallade",
+ [475] "probopass",
+ [476] "dusknoir",
+ [477] "froslass",
+ [478] "rotom",
+ [479] "uxie",
+ [480] "mesprit",
+ [481] "azelf",
+ [482] "dialga",
+ [483] "palkia",
+ [484] "heatran",
+ [485] "regigigas",
+ [486] "giratina",
+ [487] "cresselia",
+ [488] "phione",
+ [489] "manaphy",
+ [490] "darkrai",
+ [491] "shaymin",
+ [492] "arceus",
+ [493] "victini",
+ [494] "snivy",
+ [495] "servine",
+ [496] "serperior",
+ [497] "tepig",
+ [498] "pignite",
+ [499] "emboar",
+ [500] "oshawott",
+ [501] "dewott",
+ [502] "samurott",
+ [503] "patrat",
+ [504] "watchog",
+ [505] "lillipup",
+ [506] "herdier",
+ [507] "stoutland",
+ [508] "purrloin",
+ [509] "liepard",
+ [510] "pansage",
+ [511] "simisage",
+ [512] "pansear",
+ [513] "simisear",
+ [514] "panpour",
+ [515] "simipour",
+ [516] "munna",
+ [517] "musharna",
+ [518] "pidove",
+ [519] "tranquill",
+ [520] "unfezant",
+ [521] "blitzle",
+ [522] "zebstrika",
+ [523] "roggenrola",
+ [524] "boldore",
+ [525] "gigalith",
+ [526] "woobat",
+ [527] "swoobat",
+ [528] "drilbur",
+ [529] "excadrill",
+ [530] "audino",
+ [531] "timburr",
+ [532] "gurdurr",
+ [533] "conkeldurr",
+ [534] "tympole",
+ [535] "palpitoad",
+ [536] "seismitoad",
+ [537] "throh",
+ [538] "sawk",
+ [539] "sewaddle",
+ [540] "swadloon",
+ [541] "leavanny",
+ [542] "venipede",
+ [543] "whirlipede",
+ [544] "scolipede",
+ [545] "cottonee",
+ [546] "whimsicott",
+ [547] "petilil",
+ [548] "lilligant",
+ [549] "basculin",
+ [550] "sandile",
+ [551] "krokorok",
+ [552] "krookodile",
+ [553] "darumaka",
+ [554] "darmanitan",
+ [555] "maractus",
+ [556] "dwebble",
+ [557] "crustle",
+ [558] "scraggy",
+ [559] "scrafty",
+ [560] "sigilyph",
+ [561] "yamask",
+ [562] "cofagrigus",
+ [563] "tirtouga",
+ [564] "carracosta",
+ [565] "archen",
+ [566] "archeops",
+ [567] "trubbish",
+ [568] "garbodor",
+ [569] "zorua",
+ [570] "zoroark",
+ [571] "minccino",
+ [572] "cinccino",
+ [573] "gothita",
+ [574] "gothorita",
+ [575] "gothitelle",
+ [576] "solosis",
+ [577] "duosion",
+ [578] "reuniclus",
+ [579] "ducklett",
+ [580] "swanna",
+ [581] "vanillite",
+ [582] "vanillish",
+ [583] "vanilluxe",
+ [584] "deerling",
+ [585] "sawsbuck",
+ [586] "emolga",
+ [587] "karrablast",
+ [588] "escavalier",
+ [589] "foongus",
+ [590] "amoonguss",
+ [591] "frillish",
+ [592] "jellicent",
+ [593] "alomomola",
+ [594] "joltik",
+ [595] "galvantula",
+ [596] "ferroseed",
+ [597] "ferrothorn",
+ [598] "klink",
+ [599] "klang",
+ [600] "klinklang",
+ [601] "tynamo",
+ [602] "eelektrik",
+ [603] "eelektross",
+ [604] "elgyem",
+ [605] "beheeyem",
+ [606] "litwick",
+ [607] "lampent",
+ [608] "chandelure",
+ [609] "axew",
+ [610] "fraxure",
+ [611] "haxorus",
+ [612] "cubchoo",
+ [613] "beartic",
+ [614] "cryogonal",
+ [615] "shelmet",
+ [616] "accelgor",
+ [617] "stunfisk",
+ [618] "mienfoo",
+ [619] "mienshao",
+ [620] "druddigon",
+ [621] "golett",
+ [622] "golurk",
+ [623] "pawniard",
+ [624] "bisharp",
+ [625] "bouffalant",
+ [626] "rufflet",
+ [627] "braviary",
+ [628] "vullaby",
+ [629] "mandibuzz",
+ [630] "heatmor",
+ [631] "durant",
+ [632] "deino",
+ [633] "zweilous",
+ [634] "hydreigon",
+ [635] "larvesta",
+ [636] "volcarona",
+ [637] "cobalion",
+ [638] "terrakion",
+ [639] "virizion",
+ [640] "tornadus",
+ [641] "thundurus",
+ [642] "reshiram",
+ [643] "zekrom",
+ [644] "landorus",
+ [645] "kyurem",
+ [646] "keldeo",
+ [647] "meloetta",
+ [648] "genesect",
+ [649] "chespin",
+ [650] "quilladin",
+ [651] "chesnaught",
+ [652] "fennekin",
+ [653] "braixen",
+ [654] "delphox",
+ [655] "froakie",
+ [656] "frogadier",
+ [657] "greninja",
+ [658] "bunnelby",
+ [659] "diggersby",
+ [660] "fletchling",
+ [661] "fletchinder",
+ [662] "talonflame",
+ [663] "scatterbug",
+ [664] "spewpa",
+ [665] "vivillon",
+ [666] "litleo",
+ [667] "pyroar",
+ [668] "flabebe",
+ [669] "floette",
+ [670] "florges",
+ [671] "skiddo",
+ [672] "gogoat",
+ [673] "pancham",
+ [674] "pangoro",
+ [675] "furfrou",
+ [676] "espurr",
+ [677] "meowstic",
+ [678] "honedge",
+ [679] "doublade",
+ [680] "aegislash",
+ [681] "spritzee",
+ [682] "aromatisse",
+ [683] "swirlix",
+ [684] "slurpuff",
+ [685] "inkay",
+ [686] "malamar",
+ [687] "binacle",
+ [688] "barbaracle",
+ [689] "skrelp",
+ [690] "dragalge",
+ [691] "clauncher",
+ [692] "clawitzer",
+ [693] "helioptile",
+ [694] "heliolisk",
+ [695] "tyrunt",
+ [696] "tyrantrum",
+ [697] "amaura",
+ [698] "aurorus",
+ [699] "sylveon",
+ [700] "hawlucha",
+ [701] "dedenne",
+ [702] "carbink",
+ [703] "goomy",
+ [704] "sliggoo",
+ [705] "goodra",
+ [706] "klefki",
+ [707] "phantump",
+ [708] "trevenant",
+ [709] "pumpkaboo",
+ [710] "gourgeist",
+ [711] "bergmite",
+ [712] "avalugg",
+ [713] "noibat",
+ [714] "noivern",
+ [715] "xerneas",
+ [716] "yveltal",
+ [717] "zygarde",
+ [718] "diancie",
+ [719] "hoopa",
+ [720] "volcanion",
+ [721] "rowlet",
+ [722] "dartrix",
+ [723] "decidueye",
+ [724] "litten",
+ [725] "torracat",
+ [726] "incineroar",
+ [727] "popplio",
+ [728] "brionne",
+ [729] "primarina",
+ [730] "pikipek",
+ [731] "trumbeak",
+ [732] "toucannon",
+ [733] "yungoos",
+ [734] "gumshoos",
+ [735] "grubbin",
+ [736] "charjabug",
+ [737] "vikavolt",
+ [738] "crabrawler",
+ [739] "crabominable",
+ [740] "oricorio",
+ [741] "cutiefly",
+ [742] "ribombee",
+ [743] "rockruff",
+ [744] "lycanroc",
+ [745] "wishiwashi",
+ [746] "mareanie",
+ [747] "toxapex",
+ [748] "mudbray",
+ [749] "mudsdale",
+ [750] "dewpider",
+ [751] "araquanid",
+ [752] "fomantis",
+ [753] "lurantis",
+ [754] "morelull",
+ [755] "shiinotic",
+ [756] "salandit",
+ [757] "salazzle",
+ [758] "stufful",
+ [759] "bewear",
+ [760] "bounsweet",
+ [761] "steenee",
+ [762] "tsareena",
+ [763] "comfey",
+ [764] "oranguru",
+ [765] "passimian",
+ [766] "wimpod",
+ [767] "golisopod",
+ [768] "sandygast",
+ [769] "palossand",
+ [770] "pyukumuku",
+ [771] "type-null",
+ [772] "silvally",
+ [773] "minior",
+ [774] "komala",
+ [775] "turtonator",
+ [776] "togedemaru",
+ [777] "mimikyu",
+ [778] "bruxish",
+ [779] "drampa",
+ [780] "dhelmise",
+ [781] "jangmo-o",
+ [782] "hakamo-o",
+ [783] "kommo-o",
+ [784] "tapu-koko",
+ [785] "tapu-lele",
+ [786] "tapu-bulu",
+ [787] "tapu-fini",
+ [788] "cosmog",
+ [789] "cosmoem",
+ [790] "solgaleo",
+ [791] "lunala",
+ [792] "nihilego",
+ [793] "buzzwole",
+ [794] "pheromosa",
+ [795] "xurkitree",
+ [796] "celesteela",
+ [797] "kartana",
+ [798] "guzzlord",
+ [799] "necrozma",
+ [800] "magearna",
+ [801] "marshadow",
+ [802] "poipole",
+ [803] "naganadel",
+ [804] "stakataka",
+ [805] "blacephalon",
+ [806] "zeraora",
+ [807] "meltan",
+ [808] "melmetal",
+ [809] "grookey",
+ [810] "thwackey",
+ [811] "rillaboom",
+ [812] "scorbunny",
+ [813] "raboot",
+ [814] "cinderace",
+ [815] "sobble",
+ [816] "drizzile",
+ [817] "inteleon",
+ [818] "skwovet",
+ [819] "greedent",
+ [820] "rookidee",
+ [821] "corvisquire",
+ [822] "corviknight",
+ [823] "blipbug",
+ [824] "dottler",
+ [825] "orbeetle",
+ [826] "nickit",
+ [827] "thievul",
+ [828] "gossifleur",
+ [829] "eldegoss",
+ [830] "wooloo",
+ [831] "dubwool",
+ [832] "chewtle",
+ [833] "drednaw",
+ [834] "yamper",
+ [835] "boltund",
+ [836] "rolycoly",
+ [837] "carkol",
+ [838] "coalossal",
+ [839] "applin",
+ [840] "flapple",
+ [841] "appletun",
+ [842] "silicobra",
+ [843] "sandaconda",
+ [844] "cramorant",
+ [845] "arrokuda",
+ [846] "barraskewda",
+ [847] "toxel",
+ [848] "toxtricity",
+ [849] "sizzlipede",
+ [850] "centiskorch",
+ [851] "clobbopus",
+ [852] "grapploct",
+ [853] "sinistea",
+ [854] "polteageist",
+ [855] "hatenna",
+ [856] "hattrem",
+ [857] "hatterene",
+ [858] "impidimp",
+ [859] "morgrem",
+ [860] "grimmsnarl",
+ [861] "obstagoon",
+ [862] "perrserker",
+ [863] "cursola",
+ [864] "sirfetch'd",
+ [865] "mr.-rime",
+ [866] "runerigus",
+ [867] "milcery",
+ [868] "alcremie",
+ [869] "falinks",
+ [870] "pincurchin",
+ [871] "snom",
+ [872] "frosmoth",
+ [873] "stonjourner",
+ [874] "eiscue",
+ [875] "indeedee",
+ [876] "morpeko",
+ [877] "cufant",
+ [878] "copperajah",
+ [879] "dracozolt",
+ [880] "arctozolt",
+ [881] "dracovish",
+ [882] "arctovish",
+ [883] "duraludon",
+ [884] "dreepy",
+ [885] "drakloak",
+ [886] "dragapult",
+ [887] "zacian",
+ [888] "zamazenta",
+ [889] "eternatus",
+};
--- /dev/null
+++ b/fs.c
@@ -1,0 +1,111 @@
+#include <u.h>
+#include <libc.h>
+#include <fcall.h>
+#include <thread.h>
+#include <9p.h>
+#include "gen3dat.h"
+#include "gen3.h"
+
+Gen3 gen3;
+
+enum { Qtrainer, Qpokemon };
+typedef struct Xfile Xfile;
+struct Xfile {
+ int type;
+ union {
+ Pokemon *p;
+ Invent *i;
+ Trainer *tr;
+ };
+};
+
+static void
+fsread(Req *r)
+{
+ Xfile *f;
+ char buf[8192];
+ uchar str[64];
+ Pokedat pd;
+ char *p, *e;
+
+ f = r->fid->file->aux;
+ p = buf;
+ e = buf + sizeof buf;
+
+ switch(f->type){
+ case Qtrainer:
+ gen3pkstr(str, f->tr->name, sizeof f->tr->name);
+ seprint(p, e, "%s\t%d\t%d\n", (char*)str, f->tr->id, f->tr->secretid);
+ break;
+ case Qpokemon:
+ decryptpokemon(&pd, f->p);
+ gen3pkstr(str, f->p->name, sizeof f->p->name);
+ seprint(p, e, "%s\t%d\n", (char*)str, pd.g.species);
+ break;
+ }
+ readstr(r, buf);
+ respond(r, nil);
+}
+
+Srv fs = {
+.read = fsread,
+};
+
+static void
+usage(void)
+{
+ fprint(2, "usage: %s [-s srv] [-m mtpt] file.sav\n", argv0);
+ exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+ int fd;
+ int j;
+ Xfile *xf;
+ File *box;
+ char *user;
+ char *mtpt, *srvname;
+
+ srvname = nil;
+ mtpt = "/mnt/pse";
+ ARGBEGIN{
+ case 's':
+ srvname = EARGF(usage());
+ break;
+ case 'm':
+ mtpt = EARGF(usage());
+ break;
+ default:
+ usage();
+ }ARGEND;
+ if(argc < 1)
+ usage();
+
+ fd = open(argv[0], OREAD);
+ if(fd < 0)
+ sysfatal("open: %r");
+
+ getgen3(fd, &gen3);
+
+ user = getenv("user");
+ fs.tree = alloctree(user, "sys", DMDIR|0555, nil);
+ box = createfile(fs.tree->root, "box", user, DMDIR|0555, nil);
+
+ xf = mallocz(sizeof *xf, 1);
+ xf->type = Qtrainer;
+ xf->tr = &gen3.tr;
+ createfile(fs.tree->root, "trainer", user, 0444, xf);
+
+ for(j = 0; j < 420; j++){
+ if(gen3.pc.box[j].personality == 0 && gen3.pc.box[j].otid == 0)
+ continue;
+ xf = mallocz(sizeof *xf, 1);
+ xf->type = Qpokemon;
+ xf->p = &gen3.pc.box[j];
+ createfile(box, smprint("%d", j), user, 0444, xf);
+ }
+ postmountsrv(&fs, srvname, mtpt, MREPL);
+ exits(nil);
+}
--- a/gen3.c
+++ b/gen3.c
@@ -1,8 +1,6 @@
#include <u.h>
#include <libc.h>
-#include <fcall.h>
-#include <thread.h>
-#include <9p.h>
+#include "gen3dat.h"
#include "gen3.h"
int poketab[24][4] = {
@@ -32,43 +30,6 @@
{24, 36, 12, 0},
};
-enum{
- STrainer,
- SInvent,
- SState,
- SMisc,
- SRiv,
- SPCA,
- SPCB,
- SPCC,
- SPCD,
- SPCE,
- SPCF,
- SPCG,
- SPCH,
- SPCI,
-};
-
-typedef struct Save Save;
-struct Save{
- Section bank1[14];
- Section bank2[14];
- Section *active;
- Trainer tr;
- Invent inv;
- PC pc;
-};
-
-Save save;
-
-uchar pcbuf[3968*8 + 2000];
-
-long getsection(Section*,uchar*);
-long gettrainer(Trainer*,uchar*);
-long getinvent(Invent*,uchar*);
-long getpokedat(Pokedat*,uchar*);
-long getpc(PC*,uchar*);
-
#define PUT4(p, u) (p)[3] = (u)>>24, (p)[2] = (u)>>16, (p)[1] = (u)>>8, (p)[0] = (u)
static void
@@ -82,11 +43,10 @@
b[i] = b[i] ^ key[i%4];
}
-static Pokedat
-decryptpokemon(Pokemon *src)
+void
+decryptpokemon(Pokedat *dst, Pokemon *src)
{
uchar buf[12*4];
- Pokedat ret;
int *t;
t = poketab[src->personality % nelem(poketab)];
@@ -95,17 +55,15 @@
memcpy(buf + t[2], src->data + 24, 12);
memcpy(buf + t[3], src->data + 36, 12);
cryptpokedat(buf, src->otid, src->personality);
- assert(getpokedat(&ret, buf) == sizeof buf);
- return ret;
+ assert(getpokedat(dst, buf) == sizeof buf);
}
-static char*
-pkstr(uchar *p, uchar *e)
+void
+gen3pkstr(uchar *d, uchar *p, int n)
{
- char out[16];
- char *d;
+ uchar *e;
- for(d = out; p < e && *p != 0xFF; p++){
+ for(e = p+n; p<e && *p != 0xFF; p++){
if(*p >= 0xA1 && *p <= 0xAA)
*d++ = '0' + (*p - 0xA1);
else if(*p >= 0xBB && *p <= 0xD4)
@@ -114,138 +72,47 @@
*d++ = 'a' + (*p - 0xD5);
}
*d = 0;
- return strdup(out);
}
-enum { Qtrainer, Qpokemon };
-typedef struct Xfile Xfile;
-struct Xfile {
- int type;
- union {
- Pokemon *p;
- Invent *i;
- Trainer *tr;
- };
-};
-
-static void
-fsread(Req *r)
-{
- Xfile *f;
- char buf[8192];
- Pokedat pd;
- char *p, *e;
-
- f = r->fid->file->aux;
- p = buf;
- e = buf + sizeof buf;
-
- switch(f->type){
- case Qtrainer:
- seprint(p, e, "%s\t%d\t%d\n", pkstr(f->tr->name, f->tr->name + 7), f->tr->id, f->tr->secretid);
- break;
- case Qpokemon:
- pd = decryptpokemon(f->p);
- seprint(p, e, "%s\t%d\n", pkstr(f->p->name, f->p->name + 10), pd.g.species);
- break;
- }
- readstr(r, buf);
- respond(r, nil);
-}
-
-Srv fs = {
-.read = fsread,
-};
-
-static void
-usage(void)
-{
- fprint(2, "usage: %s [-s srv] [-m mtpt] file.sav\n", argv0);
- exits("usage");
-}
-
void
-main(int argc, char **argv)
+getgen3(int fd, Gen3 *save)
{
- int fd;
int i, j;
uchar buf[8192];
- Xfile *xf;
- File *box;
- char *user;
- char *mtpt, *srvname;
- srvname = nil;
- mtpt = "/mnt/gen3";
- ARGBEGIN{
- case 's':
- srvname = EARGF(usage());
- break;
- case 'm':
- mtpt = EARGF(usage());
- break;
- default:
- usage();
- }ARGEND;
- if(argc < 1)
- usage();
-
- fd = open(argv[0], OREAD);
- if(fd < 0)
- sysfatal("open: %r");
-
for(i = 0; i < 14; i++){
if(readn(fd, buf, 4096) != 4096)
sysfatal("unexpected eof");
- getsection(save.bank1 + i, buf);
+ getsection(save->bank1 + i, buf);
}
-
seek(fd, 0xE000, 0);
for(i = 0; i < 14; i++){
if(readn(fd, buf, 4096) != 4096)
sysfatal("unexpected eof");
- getsection(save.bank2 + i, buf);
+ getsection(save->bank2 + i, buf);
}
- save.active = save.bank1[0].index > save.bank2[0].index ? save.bank1 : save.bank2;
+ save->active = save->bank1[0].index > save->bank2[0].index ? save->bank1 : save->bank2;
- user = getenv("user");
- fs.tree = alloctree(user, "sys", DMDIR|0555, nil);
- box = createfile(fs.tree->root, "box", user, DMDIR|0555, nil);
-
for(i = 0; i < 14; i++){
- switch(save.active[i].id){
+ switch(save->active[i].id){
case STrainer:
- gettrainer(&save.tr, save.active[i].data);
- xf = mallocz(sizeof *xf, 1);
- xf->type = Qtrainer;
- xf->tr = &save.tr;
- createfile(fs.tree->root, "trainer", user, 0444, xf);
+ gettrainer(&save->tr, save->active[i].data);
break;
case SInvent:
- getinvent(&save.inv, save.active[i].data + 0x34);
+ getinvent(&save->inv, save->active[i].data + 0x34);
break;
case SState: case SMisc: case SRiv:
break;
default:
- j = save.active[i].id - SPCA;
+ j = save->active[i].id - SPCA;
if(j >= 0 && j < 8)
- memcpy(pcbuf + j * 3968, save.active[i].data, 3968);
+ memcpy(save->pcbuf + j * 3968, save->active[i].data, 3968);
else if(j == 8)
- memcpy(pcbuf + 8 * 3968, save.active[i].data, 2000);
+ memcpy(save->pcbuf + 8 * 3968, save->active[i].data, 2000);
else
sysfatal("invalid section");
}
}
- getpc(&save.pc, pcbuf);
- for(j = 0; j < 420; j++){
- if(save.pc.box[j].personality == 0 && save.pc.box[j].otid == 0)
- continue;
- xf = mallocz(sizeof *xf, 1);
- xf->type = Qpokemon;
- xf->p = &save.pc.box[j];
- createfile(box, smprint("%d", j), user, 0444, xf);
- }
- postmountsrv(&fs, srvname, mtpt, MREPL);
- exits(nil);
+ getpc(&save->pc, save->pcbuf);
}
--- a/gen3.h
+++ b/gen3.h
@@ -1,121 +1,45 @@
-typedef struct Section Section;
-typedef struct Trainer Trainer;
-typedef struct Pokemon Pokemon;
-typedef struct Invent Invent;
-typedef struct InventPokemon InventPokemon;
+enum{
+ /* Sections */
+ STrainer,
+ SInvent,
+ SState,
+ SMisc,
+ SRiv,
+ SPCA,
+ SPCB,
+ SPCC,
+ SPCD,
+ SPCE,
+ SPCF,
+ SPCG,
+ SPCH,
+ SPCI,
-typedef struct Blocka Blocka;
-typedef struct Blockg Blockg;
-typedef struct Blockm Blockm;
-typedef struct Blocke Blocke;
-typedef struct Pokedat Pokedat;
-
-typedef struct Boxname Boxname;
-typedef struct PC PC;
-
-struct Section {
- uchar data[4084];
- u16int id;
- u16int chk;
- u32int pad;
- u32int index;
+ /* Game Type */
+ GRS,
+ GFRLG,
+ GEM,
};
-struct Trainer {
- uchar name[7];
- uchar gender;
- u16int pad0;
- u16int id;
- u16int secretid;
- u16int hours;
- uchar min;
- uchar sec;
- uchar frame;
- uchar button;
- uchar text;
- uchar misc;
- uchar pad1[150];
- u32int gamecode;
-};
+long getsection(Section*,uchar*);
+long gettrainer(Trainer*,uchar*);
+long getinvent(Invent*,uchar*);
+long getpokedat(Pokedat*,uchar*);
+long getpc(PC*,uchar*);
-struct Blockg {
- u16int species;
- u16int item;
- u32int exp;
- uchar ppbonus;
- uchar friendship;
- u16int magic;
-};
+typedef struct Gen3 Gen3;
+struct Gen3{
+ int type;
+ Section bank1[14];
+ Section bank2[14];
+ Section *active;
+ Trainer tr;
+ Invent inv;
+ PC pc;
-struct Blocka {
- u16int move1;
- u16int move2;
- u16int move3;
- u16int move4;
- uchar pp[4];
+ uchar pcbuf[3968*8 + 2000];
};
-struct Blockm {
- uchar pokerus;
- uchar met;
- u16int origins;
- u32int iv;
- u32int ribbions;
-};
-
-struct Blocke {
- uchar hp;
- uchar atk;
- uchar def;
- uchar spd;
- uchar spatk;
- uchar spdef;
- uchar cool;
- uchar beauty;
- uchar cute;
- uchar smart;
- uchar tough;
- uchar feel;
-};
-
-struct Pokedat {
- Blockg g;
- Blocka a;
- Blockm m;
- Blocke e;
-};
-
-struct Pokemon {
- u32int personality;
- u32int otid;
- uchar name[10];
- u16int lang;
- uchar otname[7];
- uchar marks;
- u16int chk;
- u16int magic;
- uchar data[48];
-};
-
-struct InventPokemon {
- Pokemon p;
- uchar derived[20];
-};
-
-struct Invent {
- u32int teamsz;
- InventPokemon team[6];
- u32int money;
- u16int coins;
-};
-
-struct Boxname {
- uchar n[9];
-};
-
-struct PC {
- u32int current;
- Pokemon box[420];
- Boxname name[14];
- uchar wallpaper[14];
-};
+void gen3pkstr(uchar *d, uchar *s, int n);
+void getgen3(int fd, Gen3 *save);
+void decryptpokemon(Pokedat *dst, Pokemon *src);
--- a/gen3dat.c
+++ b/gen3dat.c
@@ -1,6 +1,6 @@
#include <u.h>
#include <libc.h>
-#include "gen3.h"
+#include "gen3dat.h"
#define GET2(p) (u16int)(p)[0] | (u16int)(p)[1]<<8
#define PUT2(p, u) (p)[1] = (u)>>8, (p)[0] = (u)
--- /dev/null
+++ b/gen3dat.h
@@ -1,0 +1,121 @@
+typedef struct Section Section;
+typedef struct Trainer Trainer;
+typedef struct Pokemon Pokemon;
+typedef struct Invent Invent;
+typedef struct InventPokemon InventPokemon;
+
+typedef struct Blocka Blocka;
+typedef struct Blockg Blockg;
+typedef struct Blockm Blockm;
+typedef struct Blocke Blocke;
+typedef struct Pokedat Pokedat;
+
+typedef struct Boxname Boxname;
+typedef struct PC PC;
+
+struct Section {
+ uchar data[4084];
+ u16int id;
+ u16int chk;
+ u32int pad;
+ u32int index;
+};
+
+struct Trainer {
+ uchar name[7];
+ uchar gender;
+ u16int pad0;
+ u16int id;
+ u16int secretid;
+ u16int hours;
+ uchar min;
+ uchar sec;
+ uchar frame;
+ uchar button;
+ uchar text;
+ uchar misc;
+ uchar pad1[150];
+ u32int gamecode;
+};
+
+struct Blockg {
+ u16int species;
+ u16int item;
+ u32int exp;
+ uchar ppbonus;
+ uchar friendship;
+ u16int magic;
+};
+
+struct Blocka {
+ u16int move1;
+ u16int move2;
+ u16int move3;
+ u16int move4;
+ uchar pp[4];
+};
+
+struct Blockm {
+ uchar pokerus;
+ uchar met;
+ u16int origins;
+ u32int iv;
+ u32int ribbions;
+};
+
+struct Blocke {
+ uchar hp;
+ uchar atk;
+ uchar def;
+ uchar spd;
+ uchar spatk;
+ uchar spdef;
+ uchar cool;
+ uchar beauty;
+ uchar cute;
+ uchar smart;
+ uchar tough;
+ uchar feel;
+};
+
+struct Pokedat {
+ Blockg g;
+ Blocka a;
+ Blockm m;
+ Blocke e;
+};
+
+struct Pokemon {
+ u32int personality;
+ u32int otid;
+ uchar name[10];
+ u16int lang;
+ uchar otname[7];
+ uchar marks;
+ u16int chk;
+ u16int magic;
+ uchar data[48];
+};
+
+struct InventPokemon {
+ Pokemon p;
+ uchar derived[20];
+};
+
+struct Invent {
+ u32int teamsz;
+ InventPokemon team[6];
+ u32int money;
+ u16int coins;
+};
+
+struct Boxname {
+ uchar n[9];
+};
+
+struct PC {
+ u32int current;
+ Pokemon box[420];
+ Boxname name[14];
+ uchar wallpaper[14];
+};
--- a/mkfile
+++ b/mkfile
@@ -1,15 +1,35 @@
</$objtype/mkfile
-BIN=$home/bin/$objtype
-TARG=pse
+BIN=$home/bin/$objtype/pse
+TARG=\
+ fs\
+ view\
+
HFILES=\
gen3.h\
+ gen3dat.h\
OFILES=\
gen3.$O\
gen3dat.$O\
+ dex.$O\
-</sys/src/cmd/mkone
+</sys/src/cmd/mkmany
-gen3dat.c: gen3.h
+gen3dat.c: gen3dat.h
dfc -l $prereq > $target
+
+pokesprite:
+ git/clone https://github.com/msikma/pokesprite.git
+
+installsprite: pokesprite
+ mkdir -p sprite/regular
+ for(i in pokesprite/pokemon-gen7x/regular/*.png)
+ png -tc $i | resize -n '-x200%' '-y200%' > sprite/regular/^`{basename $i}
+ mkdir -p /sys/games/lib/pokesprite
+ clone sprite/* /sys/games/lib/pokesprite
+
+install:V:
+ mkdir -p $BIN
+ for(i in $TARG)
+ mk $MKFLAGS $i.install
--- /dev/null
+++ b/view.c
@@ -1,0 +1,245 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <thread.h>
+#include <mouse.h>
+#include <cursor.h>
+#include <keyboard.h>
+#include <ctype.h>
+#include "gen3dat.h"
+#include "gen3.h"
+
+Gen3 gen3;
+
+static void
+mklower(char *d, char *e, char *s)
+{
+ assert(d <= e-1);
+ for(; *s != 0 && d < e-1; s++){
+ if(!isascii(*s))
+ continue;
+ *d++ = tolower(*s);
+ }
+ *d = 0;
+}
+
+int currentbox = 0;
+Pokemon *currentpk = nil;
+Point spwd;
+Image *background, *light;
+
+extern char *dexfiletab[];
+
+static void
+chbox(int x)
+{
+ currentbox += x;
+ if(currentbox < 0)
+ currentbox = 0;
+ else if(currentbox > 13)
+ currentbox = 13;
+}
+
+static void
+redraw(void)
+{
+ char buf[32];
+ char path[128];
+ Image *image;
+ Rectangle r, r2;
+ Pokedat pd;
+ int i;
+ int fd;
+
+ draw(screen, screen->r, background, nil, ZP);
+ r = screen->r;
+ r2 = r;
+ spwd = Pt(68*2, 56*2);
+
+ gen3pkstr((uchar*)buf, gen3.tr.name, sizeof gen3.tr.name);
+ snprint(path, sizeof path, "Name: %s ID: %d Secret ID: %d", buf, gen3.tr.id, gen3.tr.secretid);
+ string(screen, r.min, display->black, ZP, display->defaultfont, path);
+ r.min.y += display->defaultfont->height;
+ snprint(path, sizeof path, "Time Played: %dhr %dmin", gen3.tr.hours, gen3.tr.min);
+ string(screen, r.min, display->black, ZP, display->defaultfont, path);
+ r.min.y += display->defaultfont->height;
+ gen3pkstr((uchar*)buf, gen3.pc.name[currentbox].n, sizeof gen3.pc.name[currentbox].n);
+ snprint(path, sizeof path, "Box %d: %s", currentbox+1, buf);
+ string(screen, r.min, display->black, ZP, display->defaultfont, path);
+ r.min.y += display->defaultfont->height;
+
+ if(currentpk == nil)
+ currentpk = gen3.pc.box;
+ for(i = 0; i < 30; i++){
+ if(gen3.pc.box[currentbox*30 + i].otid == 0)
+ continue;
+ decryptpokemon(&pd, gen3.pc.box + currentbox*30 + i);
+ if(pd.g.species > 251)
+ pd.g.species -= 0x19;
+ //fprint(2, "%d %s\n", pd.g.species, dexfiletab[pd.g.species]);
+ snprint(path, sizeof path, "/sys/games/lib/pokesprite/regular/%s.png", dexfiletab[pd.g.species-1]);
+ r2.min.x = r.min.x + (i%6) * spwd.x;
+ r2.min.y = r.min.y + (i/6) * spwd.y;
+ r2.max.x = r2.min.x + spwd.x;
+ r2.max.y = r2.min.y + spwd.y;
+
+ if(gen3.pc.box + currentbox*30 + i == currentpk)
+ draw(screen, r2, light, nil, ZP);
+
+ //fprint(2, "opening %s\n", path);
+ fd = open(path, OREAD);
+ if(fd < 0){
+ fprint(2, "could not open %s\n", path);
+ continue;
+ }
+ image = readimage(display, fd, 0);
+ close(fd);
+ if(image == nil)
+ continue;
+ draw(screen, r2, image, nil, ZP);
+ freeimage(image);
+ }
+
+ decryptpokemon(&pd, currentpk);
+ r = screen->r;
+ r.min.x += 6*spwd.x;
+
+ snprint(path, sizeof path, "Species: %d", pd.g.species);
+ string(screen, r.min, display->black, ZP, display->defaultfont, path);
+ r.min.y += display->defaultfont->height;
+ snprint(path, sizeof path, "Exp: %d", pd.g.exp);
+ string(screen, r.min, display->black, ZP, display->defaultfont, path);
+ r.min.y += display->defaultfont->height;
+ snprint(path, sizeof path, "Move 1: %d Move 2: %d Move 3: %d Move 4: %d", pd.a.move1, pd.a.move2, pd.a.move3, pd.a.move4);
+ string(screen, r.min, display->black, ZP, display->defaultfont, path);
+ r.min.y += display->defaultfont->height;
+
+ snprint(path, sizeof path, "HP: %d Atk: %d Def: %d SpA: %d SpD: %d Spe: %d", pd.e.hp, pd.e.atk, pd.e.def, pd.e.spatk, pd.e.spdef, pd.e.spd);
+ string(screen, r.min, display->black, ZP, display->defaultfont, path);
+ r.min.y += display->defaultfont->height;
+
+ flushimage(display, 1);
+}
+
+static int
+click(Mouse *m)
+{
+ Point p;
+
+ if((m->buttons&(1<<3)) != 0){
+ chbox(-1);
+ return 1;
+ } else if((m->buttons&(1<<4)) != 0){
+ chbox(1);
+ return 1;
+ }
+ if((m->buttons&1) == 0)
+ return 0;
+ p = m->xy;
+
+ p.y -= screen->r.min.y;
+ p.x -= screen->r.min.x;
+
+ p.y -= display->defaultfont->height*3;
+
+ p.x /= spwd.x;
+ p.y /= spwd.y;
+ if(p.x + (p.y*6) > 30)
+ return 0;
+ currentpk = gen3.pc.box +currentbox*30 + (p.x + (p.y*6));
+ return 1;
+}
+
+enum{
+ Ckey,
+ Cmouse,
+ Cresize,
+ Numchan,
+};
+
+void
+usage(void)
+{
+ fprint(2, "usage: %s game.sav\n", argv0);
+ threadexitsall("usage");
+}
+
+mainstacksize = 8192*16;
+
+void
+threadmain(int argc, char **argv)
+{
+ Mousectl *mctl;
+ Keyboardctl *kctl;
+ Rune r;
+ Mouse m;
+ int fd;
+ Alt a[Numchan+1] = {
+ [Ckey] = {nil, &r, CHANRCV},
+ [Cmouse] = {nil, &m, CHANRCV },
+ [Cresize] = {nil, nil, CHANRCV},
+ {nil, nil, CHANEND},
+ };
+
+ ARGBEGIN{
+ default:
+ usage();
+ }ARGEND;
+ if(argc < 1)
+ usage();
+
+ fd = open(argv[0], OREAD);
+ if(fd < 0)
+ sysfatal("open: %r");
+
+ getgen3(fd, &gen3);
+
+ if(initdraw(nil, nil, "pse") < 0)
+ sysfatal("initdraw: %r");
+ if((kctl = initkeyboard(nil)) == nil)
+ sysfatal("initkeyboard: %r");
+ a[Ckey].c = kctl->c;
+ if((mctl = initmouse(nil, screen)) == nil)
+ sysfatal("initmouse: %r");
+ a[Cmouse].c = mctl->c;
+ a[Cresize].c = mctl->resizec;
+
+ light = allocimagemix(display, DMedblue, DWhite);
+ background = allocimagemix(display, DPaleyellow, DWhite);
+
+ redraw();
+ for(;;){
+ switch(alt(a)){
+ case -1:
+ goto end;
+ case Ckey:
+ switch (r) {
+ case 'w':
+ chbox(-1);
+ redraw();
+ break;
+ case 'e':
+ chbox(1);
+ redraw();
+ break;
+ case Kdel:
+ case 'q':
+ goto end;
+ break;
+ }
+ break;
+
+ case Cmouse:
+ if(click(&m))
+ redraw();
+ break;
+
+ case Cresize:
+ getwindow(display, Refnone);
+ redraw();
+ break;
+ }
+ }
+end:
+ threadexitsall(nil);
+}