commit 6944182c93a0e28bb46e8b855b2ad83961abab4f Author: shoofle Date: Fri Apr 12 10:44:45 2024 -0400 initial update diff --git a/.info.pod b/.info.pod new file mode 100644 index 0000000..496ee17 Binary files /dev/null and b/.info.pod differ diff --git a/appdata/system/settings.pod b/appdata/system/settings.pod new file mode 100644 index 0000000..be15931 Binary files /dev/null and b/appdata/system/settings.pod differ diff --git a/atelier2.p64 b/atelier2.p64 new file mode 100644 index 0000000..2a9d0ae --- /dev/null +++ b/atelier2.p64 @@ -0,0 +1,1119 @@ +picotron cartridge // www.picotron.net +version 2 + +:: gfx/ +:: map/ +:: sfx/ +:: story.txt +--[[pod_format="raw",created="2024-03-30 15:58:22",modified="2024-04-11 01:41:32",revision=208]] +ATELIER HESTER + +welcome to atelier phoebe 2! this is my document for +recording story ideas! please don't read this; it is +all the spoilers! if you want to know what happens +i recommend playing the game, that is the proper +way to experience this :) + +-------------- + +main gameplay interface, you're shown a gridd of +cubbiess which contain various ingredients + +you look at the things in the cubbies and label them? +labeling could be hard with just o/x +you have twwo books, one of recipes and one of +ingredients? +drag a label from the book to the drawer/plant? + +-------------- +plot ddetails follow!!! + +main character amnesia from alchemy gone wrong. +main character badly in debt to loan shark +everyone in town has some debt and don't talk about it +most people don't like main character +mc has to mend relationships with everyone in order +to gather everyone together to defeat loan shark +player controls a fairy assistant for alchemy +possibly fairy is new to the atelier? +early dialog esstablishes it's common knowledge that +fairies can blink white (o) to confirm things or +red (x) to be uncertain / ask a question + +maybe other colors at other timess but you get it, +those are our two verbs - ask about something and +suggest something + +interface is an apothecary cabinet you can open +the drawerss of and ask about. you have to suggest +ingredients to mix together for the cauldron + +at the beginning MC is unsure and doesn't know about +your suggestions - "i guess i can look that up?", +"maybe i'll try this?" because the player is guiding +them. towards the end MC responds as though teaching +the player fairy, like "that's right, that'll work!" +and "good job, yeah!" to communicate that the MC +is more confident and getting their mlemory of +alchemy back + +the town generally ddoesn't like the alchemisst just +because she's been kindda nasty and rude at times, +just petty disagreements that have boiled over. +she's known to be a decent alchemist though i guesss + +endgame is that you rally the town together to break +free of the loan shark; it's hard too convince +townsfolk both because they don't like you at first +and also because the loans ARE legitimate. but it +turnss out that the rest of the town also has debt +to the shark and if you convince everyone you can both +1. achieve independence from the supplies he sells +(maybe he's the intermediary with the trader? or buys +and ressells everything at a markup?) +2. convince people to just reject the loanss/debt; +quesstion here of whether they do this by force, +whether cops exist, idk, this is explicitly passtoral +fantasy. maybe at the end the player will muse about +whether it's good to have mob rule, "no one in toown +liked me, what if they threatened to burn down my +shop?" "yeah, that would suck. maybe we could build +something. but right now rule by mob is better than +rule by loan shark!" idk this feels overly didactic +but you get the idea + +this is really getting into the weeds of how we view +the justice system but maybe he threatens to say +"i'll send for the king's knights!" and the crowd is +like "you can do that if you want, but by the time +they get here your house will be burned down. +alternately, you can keep your house and try to +be friendly. maybe even contribute to the town. it's +up to you. burn down your storehouse or genuinely +connect with people?" + +definitely overly preachy but i like that + +------------------ +script!!!!!!!!!!!! +------------------ + +title screen +new game or load? +new game -> +hester with her back to cauldrron holding a little fairy doll in pieces +fairy shakes and then comes to life +hester: "ahhh, the synthesis wworked! ... i think" +hester: "a fairy like you should be a good help around the shop." +hester: "you might noot be able to speak but you can flash white for yes and red for not sure" +the whole time there's more and more bubbling in the cauldron +hester: "you can be my hands across the atelier!" +explosion! +soot-covered hester stands up +"what just happened." +"wait a second. who am i." +"alchemy books? a cauldron?" +outside view of shop, Atelier Hester on the sign +"Hester..." +back inside +"i must be an alchemist..." +loan shark arrives +"hester! you got the latest payment for me, girlie?" +"i'm afraid i don't knwo who i am - can you help me?" +"nice try. remember you owe me 4000Z by the end of the month. have a nice day!!!" +loan shark leaves +(SAVE POINT) +"am i... in debt?" +"i don't know hwo to do alchemy... but maybe these books..." +(player opens books) +"it looks like this one has recipes... this one has infoormation about ingredients... my head..." +(when quit uot of both books, old man comes in) +"hey, hester. can i get that purified water?" +"i don't knwo who i am" +"sorry, i can't hear so good these days - purified water? my usual order?" +(moves on when you've crafted purified water) +"thank you, hester. this will help me out. here's your payment." +(old man leaves) +"i guess i'll just try to... be an alchemist and pay off my debts..." +(SAVE POINT) + +at the beginning MC is unsure and doesn't know about +your suggestions - "i guess i can look that up?", +"maybe i'll try this?" because the player is guiding +them. towards the end MC responds as though teaching +the player fairy, like "that's right, that'll work!" +and "good job, yeah!" to communicate that the MC +is more confident and getting their mlemory of +alchemy back + +the town generally ddoesn't like the alchemisst just +because she's been kindda nasty and rude at times, +just petty disagreements that have boiled over. +she's known to be a decent alchemist though i guesss + +endgame is that you rally the town together to break +free of the loan shark; it's hard too convince +townsfolk both because they don't like you at first +and also because the loans ARE legitimate. but it +turnss out that the rest of the town also has debt +to the shark and if you convince everyone you can both +1. achieve independence from the supplies he sells +(maybe he's the intermediary with the trader? or buys +and ressells everything at a markup?) +2. convince people to just reject the loanss/debt; +quesstion here of whether they do this by force, +whether cops exist, idk, this is explicitly passtoral +fantasy. maybe at the end the player will muse about +whether it's good to have mob rule, "no one in toown +liked me, what if they threatened to burn down my +shop?" "yeah, that would suck. maybe we could build +something. but right now rule by mob is better than +rule by loan shark!" idk this feels overly didactic +but you get the idea + +this is really getting into the weeds of how we view +the justice system but maybe he threatens to say +"i'll send for the king's knights!" and the crowd is +like "you can do that if you want, but by the time +they get here your house will be burned down. +alternately, you can keep your house and try to +be friendly. maybe even contribute to the town. it's +up to you. burn down your storehouse or genuinely +connect with people?" + +definitely overly preachy but i like that +:: art.lua +--[[pod_format="raw",created="2024-03-31 01:52:08",modified="2024-04-12 14:41:51",revision=629]] +function bob(s, x, y, w, h, t) + sspr(s, 0, 0, w, h, x+t/2, y-t/2, w-t, h+t) +end + +function ragged_box(x1, y1, x2, y2) + ragged_box_color(x1, y1, x2, y2, 15) +end + +function ragged_box_color(x1, y1, x2, y2, bgcolor) + rectfill(x1+1, y1+1, x2, y2, bgcolor) + sspr(004, 0,0, 8,2, x1+1, y1, x2-x1, 2) + sspr(004, 0,0, 8,2, x1+1, y2, x2-x1, 2) + sspr(004, 0,0, 2,4, x1, y1, 2, y2-y1) + sspr(004, 0,0, 2,4, x2, y1+2, 2, y2-y1) +end + +function easeTrig(t) + if t<0 then return 0 end + if t>1 then return 1 end + return 0.5-0.5*cos(t/2) +end +function easeAccelerate(t) + if t<0 then return 0 end + if t>1 then return 1 end + return t*t +end +function easeDecelerate(t) + if t<0 then return 0 end + if t>1 then return 1 end + return 1-(1-t)*(1-t) +end +function easeSine(t) + if t<0 then return 0 end + if t>1 then return 1 end + return sin(t/4) +end + +-- add newlines to a string to fit it into lines. +function wrap(str, line_length) + -- thanks to https://stackoverflow.com/questions/17586/best-word-wrap-algorithm, i did not feel like thinking this out myself + local words = split(str, " ", false) + local output = "" + + local c = 0 + for w in all(words) do + while sub(w, 1, 1) == "\n" do + output = output .. "\n" + c = 0 + w = sub(w, 2) + end + if c + print(w,0,-10) > line_length then + if c > 0 then + output = output .. "\n" + c = 0 + end + end + + output = output .. w .. " " + c += print(w,0,-10) + print(" ", 0, -10) + end + return output +end + +function collides(position, object) + return position.x < object.right and position.x > object.left and position.y > object.top and position.y < object.bottom +end +:: cabinet.lua +--[[pod_format="raw",created="2024-04-03 19:46:51",modified="2024-04-10 01:58:59",revision=627]] +Cabinet = {} +function Cabinet:new(x, y, gaps) + local c = { + x=40, + y=10, + drawers = {}, + shelves = {}, + hover_plant = nil, + height = 4*(gaps+16) + } + -- populate the big drawers + local xoff = x + for i=0,0 do + for j=0,1 do + add(c.drawers, + Drawer:new(xoff + gaps + i*(gaps+32), y + gaps + j*(gaps+32), 009, 32)) + end + end + xoff += gaps + (gaps + 32) + + -- populate ssmall drawers + for i=0,3 do + for j=0,3 do + add(c.drawers, + Drawer:new(xoff + gaps + i*(gaps+16), y + gaps + j*(gaps+16), 008, 16)) + end + end + xoff += gaps + 4*(gaps+16) + + local s = Shelf:new(xoff+gaps, y + gaps, 76, 32) + add(s.plants, {13, 4}) + add(s.plants, {14, 14}) + add(c.shelves, s) + + local s = Shelf:new(xoff+gaps, y + 3*gaps + 32, 76, 32) + add(s.plants, {15, 10}) + add(c.shelves, s) + + setmetatable(c, self) + self.__index = self + return c +end + +function Cabinet:draw() + -- cabinet! + rectfill(self.x, self.y, 230, self.y + self.height, 2) + + -- drawers + for a in all(self.drawers) do + a:draw() + end + + -- plant shelves + for s in all(self.shelves) do s:draw(self.hover_plant) end +end + +function Cabinet:update(x,y) + for d in all(self.drawers) do + if d:contains(x,y) then + d.offset = 4 + else + d.offset = 0 + end + end + local closest_distance = 1000 + local closest_plant = nil + for s in all(self.shelves) do + for p in all(s.plants) do + local dist = abs(p[2] + s.x - x+16) + abs(s.y + 24 - y) + if dist < closest_distance then + closest_distance = dist + closest_plant = p + end + end + end + + if closest_distance < 32 then self.hover_plant = closest_plant + else self.hover_plant = nil end +end +function Cabinet:drawer_at(x, y) + for d in all(self.drawers) do + if d:contains(x,y) then + return d + end + end + return nil +end + +Drawer = {} +function Drawer:new(x, y, sprite, size) + local c = {x=x, y=y, sprite=sprite, size=size, offset=0} + setmetatable(c, self) + self.__index = self + return c +end +function Drawer:draw() + rectfill(self.x+2, self.y+2, self.x+self.size-3, self.y+self.size-3, 0) + spr(self.sprite, self.x, self.y+self.offset) +end +function Drawer:contains(x, y) + return x >= self.x and + x <= self.x + self.size and + y >= self.y and + y <= self.y + self.size +end + + +Shelf = {} +function Shelf:new(x, y, width, height) + local c = {x=x, y=y, width=width, height=height, plants={}} + setmetatable(c, self) + self.__index = self + return c +end +function Shelf:draw(highlighted) + rectfill(self.x, self.y, self.x + self.width, self.y + self.height, 0) + for p in all(self.plants) do + if highlighted ~= p then + palt(0, true) + palt(10, true) + end + spr(p[1], self.x+p[2], self.y + self.height - 32+2) + palt(10, false) + palt(0, true) + end +end +:: conversation.lua +--[[pod_format="raw",created="2024-04-03 02:38:22",modified="2024-04-10 14:42:28",revision=642]] +default_script = { + {"welcome to Atelier Hester!", talk_sprite} +} + +Conversation = {} + +function Conversation:new(script, final) + local c = {script=script or default_script, final=final or function() end, index=1} + + setmetatable(c, self) + self.__index = self + + return c +end + +function Conversation:before() + self.behind = scene + self.before = function() end -- only ddo othis the firstt time this scene is played +end + +function Conversation:update() + local now = self.script[self.index] + if now.during ~= nil then now.during() end + if btnp(4) or btnp(5) then + if now.after ~= nil then now.after() end + if self.index < #self.script then + self.index += 1 + else + --self:after() + end + end +end + +function Conversation:draw() + self.behind:draw() + + ragged_box(30, 100, 240-30, 130) + color(0) + print(self.script[self.index][1], 34, 104) +end + +function Conversation:after() + self.final() + --change_scene(self.behind) +end +:: fairy.lua +--[[pod_format="raw",created="2024-04-03 17:32:32",modified="2024-04-10 01:58:59",revision=384]] +Fairy = { + velocity = 1, + accel_frames = 20, + min_velocity = 0, + max_velocity = 3, + f = false +} + +function Fairy:new(ff) + local f = ff or {x=120, y=68} + setmetatable(f, self) + self.__index = self + + return f +end + +function Fairy:draw() + if flr(30*t()) % 2 == 0 then + spr(5, self.x-8, self.y-8, self.f) + else + spr(6, self.x-8, self.y-8, self.f) + end +end + +function Fairy:move() + if self.velocity < self.max_velocity then + self.velocity += (self.max_velocity - self.min_velocity) / self.accel_frames + end + + if btn(0) and self.x > 0 then self.x -= self.velocity end + if btn(1) and self.x < 240 then self.x += self.velocity end + if btn(2) and self.y > 0 then self.y -= self.velocity end + if btn(3) and self.y < 135 then self.y += self.velocity end + + if not (btn(0) or btn(1) or btn(2) or btn(3)) then + self.velocity = self.min_velocity + end + + if btn(1) then self.f = false end + if btn(0) then self.f = true end +end + +Glow = {} + +function Glow:new(x,y) + local g = {x=x, y=y, t=0, length=0.7, radius=10, start_color=8, end_color=9} + + setmetatable(g, self) + self.__index = self + + return g +end + +function Glow:draw() + for i=0,4 do + local eff_radius = self.t*self.radius / self.length + if eff_radius - i >= 0 then + local c = self.start_color + if i < (self.t/self.length)*4 then + c = self.end_color + end + circ(self.x, self.y, eff_radius-i, c) + end + end +end + +function Glow:update() + self.t += 1/30.0 + return self.t < self.length +end +:: gfx/0.gfx +b64$LS1bW3BvZCxjcmVhdGVkPSIyMDI0LTAzLTI5IDAxOjE0OjUxIixtb2RpZmllZD0iMjAyNC0w +NC0xMiAxNDo0MTo1MSIscmV2aXNpb249MTA1MF1dbHo0AJQUAADWVQAA8Rp7WzBdPXtibXA9cHh1 +AEMgEBAE8PAsZmxhZ3M9MCxwYW5feD0wLjM3NQwA_wJ5PS0wLjEyNSx6b29tPTV9LDoAkCR6cAoP +HU8eCgcAcD8ODx4KYBoJAP8CDRpQCh8dPw4dClAKDx1fDg0IAAT-Aw8eClAKDl8ODgpQCn4KUJrw +A4sAJqUGOrAKHxMKsAoeBADwAKAaHhqQCgMOEQqQCgMPEgcAPQ4dAQYArw4KkAo_CpBa8AV9ACYQ +Jn0AER1xAP8GYDoPFy46MAo9HxweHxIKMAodbxwPCAACIF8cIAD-ARodPxwODxIaQBpeGmB68ASE +ACJRCAgECQACABIQCAAfGQ4AFh8J9QAm-yAQLxyQPgAuUC4AHiAuEC4gLjAOEA4wHgBeEF5ALBos +YDwaPFAcEAogHIAa0ArwOWgAJccgLDAsUAwADDAMAAwIADAcEBwIABEQAgD-EVAcAAwQDAAcYCwQ +LIAcGhyQHxwaHpAeCgAegB4aEB6QfwAaDx4DNVD-FAHUHgIAsAS5BB4ECT8PGT0JCQAanQYAMQ8V +DggAhwwOBLkEDA7UAwAf7HsAIp8gIAT-FBH0Dh4DAALANPkGNB40CX8POX0JCQAxjRmNCAAv-QQH +AAsyDxUOCQAeDAgAf-kGNAwO9A4EABI-HvwO1gAlctQPFPAB1A4EAP8SxB7wAcQO8AK0HvACpB7w +A5Qe8AR0LvAFVC7wB27w--_rZgAl-wn5MCD6CoD5BND6APAB2fAC2fADufD---xQACVf8P----M9 +ACfwCKIq8A0KAwrwDBoDCvAISgMACvAICgMgCAAjBToIAFAKAxADAAIAZBrwBAoAAwIAHwoOAApE +AToAAwIA8A5KwAr-EgEKwCrOKuAKzgrwARquGvACCq4K8AMajlUAb44K8AWqoMYAJ8AAOvAMCh8T +GvAIOi7BAPAiHgAuOvAFCi4AThrwAiouJD4K8AIKFA4ADgQQHgAa4DoALgAEDxQzCvAACi4AHiQN +PgoAUQAuEAMkCgDgICQQFBAq8AAKHhQANCOwAKBeJBAa8AEKfhQeSgAhLkAIANIaYBQQSuAK7xgK +4ArsBAChGswa8AAKzArwAQUAfxqsGvACypDZACfwDl1K8AZaLxMK8AYKTgQeCvAGGh4TBBMq8AUK +IA5DOgHwByAeBD4a8AMKLhAELgAOCvADCkMkEwCdABAwugBAAgoOQ7sAsAIKDgMODxQuFA4AdQEw +EB0QwgDTBAogDRAUEDrwAQrGCgUAIBqmLgAQpiYAEIZhABCGAQIfhqABJ-1iYGAE-x4P-xUS-x4j +-xUo-x4R-xU2-x4G-xU_3x7-FUZ-Hv8VSj8e-xUM8Bj_Cg8e-gHwMP4FBT7wPD4FnhUO8EAOFZ51 +8DZ1rvUE8Bz1BM71Qv4A9T7_BPU6-gv1MP4c9Rj_Ch3_Th3_Ti3_TE3_Sl0DAE9N-kw9AwAEES05 +AAUDADAN-v8BACQ1DREABVkABTIAAmIAQW3_SH0DAPtYjf5Gnf5Grf5Ezf5C3f5C7f5A-QH_Pv0C +-j79A-48-QX_Ov0H-jj9Cf42-Qv_NP0N-jL9D-4w-RH_Lv0T-iz9Ff4q-Rj_Jv0b-iT9Hv4g-SH_ +Hv0k-hr9Kf4U-S7_EP00-gj9Pd79GXoBdC01LjE1ODMBAASEAVcxNC44MBcAAY4BGTOOAfMgQEAE +8P8HjxjwJt7wIf4D8B3_CPAY-gvwFP4Q8A-_FfAL-hnwBf4b8AT_HPAE-hsMACIbBwUAwAP_Gxfw +Av4cBwbwAQYAMBcO4AcA8QIHLsD_HQYHBi7A-hwGBwY_sBUADw8ACKAGBwYHPqBOV-4SCgByLqBO +Fnf_DhUA8wU_JzZH-gwGFwYHLrAuFxY3Nhf_CxoA8AE3Njc2-ggGBwYXLrA_Jkc2HAAQASoAID6w +NgBBNjc27ioAQcAuJkcPADFXBi4uAELQPhc2EgAAiAARFyUAdNBORzZHRjcUAFA_0H5XRiIAEhci +AEE_8AG_MwARFhEAQD7wAu4uAPAIJwYHBic_8AbuVzY3JhcGJy7wDO5HNjcUAEEQzmcmKgDwABW_ +AFcGFwA_8BquADdO8NECUCLO8CdeqQUbhskBNjIuOEMDETkNAAFDAx00tQHRYl8Y8B-_APAV-gvw +D60BURHwDv4RCAACEAAABAAQEhQAtBfwC-4TZ-AF-hN3BQBjEofwBP4TBQCQA-4Uh-AC-hSHxgEh +FXfGASEUh8YBIhSHqQEiFHeqAQQQACIThxAAIhOXEAAhDtcQAFB_d473BZwBNE73GMoBI-cYxwEl +9xTEASb3DcMBNhb3DMEBJvcGvgE4FvcBvwEp9wK8ARrXtgECxgEPuAGQ9Cz-Fl8b8CXO8CD_AfAb +-gbwFv4L8BD_EfAN-hTwBP4e8AH_IOD_IsD_JaD_JpD_J3D_KWD_KlAOCv4pQAUAsiowDgoOCv4j +Hw8uCgDwKB99QC4K-hwtJx0nUB4K-hktJy03HUAeCv4VPSctNz1QPgr_EC03LTdNJ1AuCv4MPTct +J10nHQ4NADAJLUcNADAtBy5DAEAFPTc9DgD0AF5gHgr_Ai1HLTddFz1_cAsAci2ukE4Kbj0MAHCe +4D4KTh1XVgByLW7wBT4KTkoAc37wCC4KThcMAFAMHgpOHQsA8QaO8A5_F10XPY7wEm5NFy0HjvAW +Xh0IAPAEGl4HHRd_8B3_AfAgzvAknvAoLmMBL-_hZAEmshQfG-ArXvAnnvAkaQG1HP4F8Bj_CfAU +-g1tAdIJ-hfwB-4a8AX_HPADeQHwA-AA-iHg-iOw-iQPD6D_JAcdgF0BgVcNcA4K-h1XDgBhGlct +Fx1gdgFSFkctVw0LAFAURx1HbUEBUxI3LTcdhwF0ECctJw0HDYwBRQ8XHRePAUYKFy0HkgFHCS0X +HZQBWAcdFy0nlgFHHQctF5gBRQ0nHReaASANJz0ABJwBVi0XLScNngE1Jx13ngE1Fy1XngEfTZ0B +ZA-gDBoPOgD--------------------------------------------------6TwI2CABPD-JL8U +8ED_AvA8-gbwOT8V-gTwNz3_BfA1Tf4H8DNN-gjwMk3_CvAwTf4L8C9dBQD4AE3_DPAuXf4N8C1N +-g3wLgUAMwzwLwUAMQsPDwcAEDwmAPAMCTzwLBxN-gg88C4cPf4HLA8X8DFN-gULHAsMCQDwrAQM +CwwLDPAzTb4tLg8ZHAsc8DNdjj0uGjzwNV1ObR4qPPA2-QFKPPA3zXos8DkKTdoc8Dv6AwzwO5oM +ivA7amx68DpafHrwOVofHAxpavA4WqlaOfA0WslKOfA0SgDpKknwMyogmS8MKQpZ8DQKSEn4BPAw +_BHwLmgPCvgM8CtoFygn_AfwKfgDNzgXqPAoJ-gMB7jwIgf4EieI8CH4FgeI8CD4GAd48CD4GSc4 +8B-4IfAf_CLwHfggBxgGAPEHFxjwHPghByjwG-gl8Bv4JvAaKAn4IgYA8CMOCfgE8BoYCfgOGSgJ +_ADwGRgJ_A8ZGAmYB1jwGAgZ_BAJKAmIB1jwGQn4ERkoCRgJWBkAVAn4Eik4CwDxAhQZGBlYF1jw +Fwn4FRkIGWgHCwCBGBno8BYJ_Bk_AGQUGfgVGRgLAFAUCTgZ6AkAEBpyAIITGfgaGYgXOAkARvgA +8BIIABEbiACBEQn4HAmoB0gJACQZmAkAsPgB8BAZ_BspqAc4CQCmHBm4BzjwDwn4HQkAocgHGPAQ +CfgcKdhOACApyGUAMBOpuH0A8AEPSXgZqPAVGfgOGbgZiPAXQgDyAQggGPAaKfgbGQjwHyn4HAkH +ABAZBgDwIxo5CPAeKfgYWQjwHxn4F2kt8B0Z_BRpCAlN8BwZ_BF5CG3wHgn4DpltFfAeGfgKmY0l +CABQBqkYbVUJAPJCArkYfYXwHhnIyQiNxfAeCZi5zdXwHwlYqd31AvAfyQjN9QUABfAemRWN9Q3w +Hmmt9Q8ABfAdDRm99RXwG931GPAZjQUN9RzwGS31JPAZPQUNAgCi9RzwGC31JvAXLRAAQwUN9R0S +AAYkAKQe8BU99SjwFC0VEgCGIPAULfUq8BIkAIUi8BIt9SzwEBIAARQAhRAt9SwABfAPXgAAFgCJ +BvAPPfUqABUXAANXAIsPLfUtAAXwDO0Dbi0yOS4xMC4xXDM4Ljc1LjEeMQIE8S3--8NvFPBF7vA8 +PxV_KV7wOF2OKV7wNz0OSW4JbvA2PQ5Z7vA1PQ5pbgpu8DQdPmnu8DQNTln_APA0bkkGAPCEKW6v +GfA03tzwNBmO-AHwNBlu-AMQHw-wMBle-AMQG-AxGV78AgsAK-Axbpzb8DFujNvwMl6Mmx8fK-Ay +XnyLKDvwMl5sSwgbKCcb8DNeXCs4Sx8OBwvwNF4sHxcbKEsIGx8OK-AzHnsfFxgLFw8OKxhb8DMO +mw8XCycfDjsYS-AzHksfF0sXHw5LCEvwMz4rLxe7FgDwJw1ODAsWuwhb8DM9HizrGCvwMz0OHAAs +qyg78DMtDmyLKEsfHPA1jGsYWwYPDB8c8DSMAMsGLwoA8kkyrKsWBT8MFfAxDAB8qwYbRCXwMJzb +RBUU8C_sy0QllPAnjEWLFSRFpPAkjAU0FXslBAX0AfAifBVEJXsl9AEV8CB8BYQFayX0AwXwIGwF +lAVrGvQF8CBcCgDxQAbwH1wFlBVrCgX0BvAeTAAFlBVbBAoF9AfwHiwAJXQFBBU7FBr0B-AhFQQV +ZAUUBUoFGqQFtPAfFQoUJUQFFBpUCqQFxPAcFQQKRCUkBaQOAPAGGhUECnQlBAW0CpQF1PAYFcQl +xAqECgBQBQQKxBUMAPAK5PAWBQQK9BcF9ADwFQUK9BgV9ADwExX0GggAYBIF9BIKhAoA8wARBfQT +CnQABfQC8A8F9BQLAHAOBfQVCmQQCwAQDQsAEXQLAEEMBfQWIQA0A-ALCwChBPAKBfQfABX0AwkA +EBAdADIK9CAIAFDUFfQQEBsA8gEIBeQF9AgKZCAV9ALwCPQADQAyJfQBDQCFCQpEEBUUJeQOAEEA +FUQFDgBgFfQICkQAOQEwCPQBGwAfNA0AAsEV9A0ABfQF8Aj0AwULADME8AkLAFAEKtTwCwwAgAwg +GgQatPAMDADACAokEAo0GpTwDfQCYwCgJAAKVAqE8A70AlcAAA4AQBpk8A8OAJIKCiQVVApU8BAN +AGE0BVQaNAUOAPEEBHX0AQo0BWQKJAXwEeRVZAX0AA8AgRQF8BL0DQXkDQBwBAXwEwX0DBwAsyQF +ZAoF8BQF9AsVDgDB8BUF9Awa5AokBQpUDQBwCzr0AnrwF2kAYBRaROvwGAoAUmQaFOsWCwCAdAoE +2wYr8BmlAFSECusWGxcAQcsGKwYNAFEJCnQK2w0AEhclAAANADEL8BgMAIRrPwU7BhsGCykAMUtj +Kw8AAVAARFQaK4MPAFHUtVrjGwwAYhoFZHXzDhgA8hIbZW3zDjsGCwMb8BqNAw3zEisGC0PwGS3z +HAtj8Bk9Aw0CABDzRgVS8yXwGC0QAIADDfMe8Bct80YFAhAAARIAMBU980YFFBMSAABGBRDzRgUC +EAAwAw3zRgUQ80YFJwMNFABlEC3zLvAPXACfAw3zJPAOPfMuJwUsD50JJw_FCv8gIP8UgjHxAXz0 +P-4BBP8VPQT_AQT9PA4HACA7HgcAQS30Ny4IAE8E-jUECgD-NARSASH0OGIBMR30OnEBcg30Pf4B +9D8nOjH--_iUAR-9kwH-dh9cYgMUHzLlCQHyKxjfFvBALr8PHvA9Lu0e8Dse-QIO8Doe-QMe8DkO +-QMfEQ4N8DUcHs18DhzwMRwAHA7dDA0cDVzwMUwKAPYGHA0MDgzwMQwgHv0BDD0MDvA2Dv0IBgBg +LU4dTm0uDwCwBR4NDvA3Dl0O-QAIAEBNHv0BIQBRPR49Ds0qAFAeTQ69HgkAUA5dDp0KLQDwDR4d +Pi0OjQou8DgOTU6dCg7wOR79BA7wOg5NPq0HAPGALQ5tDm0e8DsOHR5NHl0_8DoeHX5NHh0u8Dk_ +QH5NHvBBHs0ODQLwPx7NDxhi8DourQtyG-A5Dp0bYjvwNAs_nQtiGw0r8DICCw0enRtSGz0CC-Aw +Egu9G1IbXQIL8CwNCyIbrQtSG30CC-AqHQsyG30rQhudAgsC8CgdC1IrPRtiC70bAvAnHQtyW2Ib +zQsLAPIA8gQb3RvwJi0L8gMb7QILCgCwC-0AG-AlPQvyAhsKAPAEAggX8BA9C-IBG-0CC-ACCDfw +Dg4A8QAL-QML8AMIN-ANPQvyABsOAEAYR-ALDgBQC-0CDg0eAGAHGDfwCU0SADFNDr0TAEwYBxgn +EwBIAFfwCBIAYQQIEFfwBxIAIz0eEgByIEcALxXwAxUAIg7NFQA5MEcpEwCwAvADCDA3KQ3wAl2U +ABUtFQBwQAdJHfABXbcAUB0ezQ4bPABBWa0gvREAIQ7dEQBJIEn9DBAAMCn9DhAA0hIO3Q4CC-AK +-Q8L8gQMADoL-Q4MABEFCwBUDI0g-QENAPQKDW3wBBvyBc0eAgvwDk3wBQvyBs0OEgvwKAkAcB0O +vfIFvR4KAPACXhBObcLNDiIL8CANAG69ct0LAPEMGmVuC-0RHiIL8BYVDkVOEC4L-REOMgvwFYWe +CgDwTfAWhU4AHhAL-RAeIvAXhW4tC-0PHjIAC-AV1R0Q-REOQivwFLVgC-0NLjJL8BNlECVgCxL9 +CS6SK-AShYALMv0EPtIb8BFVsAti3T7yAhvwEFWwC-ICPvIGK-AOCwAiHRsIAEAeG-ANCAAgHwsI +AKbyIBvwDFWg8iILBwBgsPIhG-ALJABnIBvwC2WgCAA-C-AMCAABAEwAAAgAYR4L8A9VoGwAAQgA +EByHAPAAoAvyGxvwEUXAC-IZG-ASCABAGBvwEwgAQBcb8BQIAEEVK-AVCAA-C-AXCAANITXQCABv +FkXgC-IUCAAUIxMbCABPCxLwFQkADR8bRAAAYvAA8hTwFwcAHwPyBBUPyAgnDzoA------------ +---3UG09NX19 +:: gfx/.info.pod +b64$LS1bW3BvZCxjcmVhdGVkPSIyMDI0LTAzLTI5IDAxOjE0OjUxIixzdG9yZWQ9IjIwMjQtMDMt +MjkgMDE6MTQ6NTEiXV1sejQABAAAAAMAAAAwbmls +:: library.lua +--[[pod_format="raw",created="2024-04-10 00:24:20",modified="2024-04-10 01:58:59",revision=35]] +plant_descriptions = { +[-1]={{"i don't know what that is. where did you find this?"}}, +[14]={{"this is foxglove"}}, +} +function get_conversation(plant) + local id = plant[1] + return plant_descriptions[id] or plant_descriptions[-1] +end + +:: main.lua +--[[pod_format="raw",created="2024-04-02 02:59:37",modified="2024-04-12 14:41:51",revision=951]] +-- this is atelier hester! + +-- except for the one line in _init that does change_screen(shop_screen) +-- this is just a file that sets up the framework we're using: +-- change_scene to change the displayed sscene +-- _update and _draw to run the current scene +-- and some stuff for setting animations. +include("art.lua") +include("script.lua") + +include("s_title.lua") +include("s_shop.lua") +include("s_conversation.lua") +include("s_drawer.lua") + +DEBUG = true + +scene = { + before=function() end, + draw=function() end, + update=function() end +} +previous_scene = scene + +animations = {} + +script = {} + +function _init() + vid(3) + change_scene(title_screen) +end + +function _draw() + scene:draw() + + for anim in all(animations) do + if anim.draw ~= nil then anim:draw() end + end + + if DEBUG then + rectfill(0,0,90,10, 7) + print("animations: "..#animations, 0,0,0) + rectfill(0,10,90,20,7) + print("script nodes: "..#script, 0,10, 0) + end +end + +function _update() + if #script == 0 or not script[1].blocking then + scene:update() + end + + local new_animations = {} + for anim in all(animations) do + local result = anim:update() + if result then + add(new_animations, anim) + end + end + animations = new_animations + + if #script > 0 then + local result = script[1]:update() + if not result then + deli(script, 1) + end + end +end + +function change_scene(new_scene) + if new_scene.before ~= nil then + new_scene:before() + end + + scene = new_scene +end + +function play_script(s) + for action in all(s) do + add(script, action) + end +end +:: map/0.map +b64$LS1bW3BvZCxjcmVhdGVkPSIyMDI0LTAzLTI5IDAxOjE0OjUxIixtb2RpZmllZD0iMjAyNC0w +NC0wNSAxMzo1NDowNiIscmV2aXNpb249NjgzXV1sejQAaAAAAFgQAADwCHt7Ym1wPXVzZXJkYXRh +KCJpMTYiLDMyAwAvIjABAP--------------------vxCCIpLGhpZGRlbj1mYWxzZSxwYW5feD0w +CADSeT0wLHRpbGVfaD0xNgoAEHcKAIB6b29tPTF9fQ== +:: map/.info.pod +b64$LS1bW3BvZCxjcmVhdGVkPSIyMDI0LTAzLTI5IDAxOjE0OjUxIixzdG9yZWQ9IjIwMjQtMDMt +MjkgMDE6MTQ6NTEiXV1sejQABAAAAAMAAAAwbmls +:: s_conversation.lua +--[[pod_format="raw",created="2024-04-05 14:55:45",modified="2024-04-12 14:41:51",revision=118]] +default_script = { + {"welcome to Atelier Hester!", talk_sprite} +} + +Conversation = {} + +function Conversation:new(script, final) + local c = {script=script or default_script, final=final or function() end, index=1} + setmetatable(c, self) + self.__index = self + + return c +end + +function Conversation:before() + self.behind = scene + self.before = function() end -- only ddo othis the firstt time this scene is played +end + +function Conversation:update() + local now = self.script[self.index] + if now.during ~= nil then now.during() end + if btnp(4) or btnp(5) then + if now.after ~= nil then now.after() end + if self.index < #self.script then + self.index += 1 + else + self:after() + end + end +end + +function Conversation:draw() + self.behind:draw() + + ragged_box(30, 100, 240-30, 130) + color(0) + print(wrap(self.script[self.index][1], 240-68), 34, 104) +end + +function Conversation:after() + self:final() + change_scene(self.behind) +end +:: s_drawer.lua +--[[pod_format="raw",created="2024-04-05 00:59:36",modified="2024-04-12 14:41:51",revision=273]] +DrawerScene = { + extension = 0, + behind = nil, + inset = 60, +} + +function DrawerScene:new(drawer) + c = {extension=0, behind=nil, inset=60} + if drawer.size > 16 then c.inset=30 end + setmetatable(c, self) + self.__index = self + + return c +end + +function DrawerScene:before() + self.behind = scene + play_script({ + Script.len(function(s) + self.extension = 115*easeDecelerate(s.timer/s.length) + end, 0.5) + }) + self.before = function() end +end + +function DrawerScene:update() + if btnp(5) then play_script({ + Script.len(function(s) + self.extension = 115*(1-easeAccelerate(s.timer/s.length)) + end, 0.5), + Script.once(function(s) change_scene(self.behind) end) + }) end +end + +function DrawerScene:draw() + self.behind:draw() + draw_drawer(self.extension, self.inset) +end + +function draw_drawer(distance, inset) + rectfill(inset, -1, 240-inset, distance, 20) + fillp(0b1010110110110101) + rectfill(inset, -1, inset+40, distance, 20 | 21<<8) + fillp() + + for i=1,4 do + rect(inset-i, -i, 240-inset+i, distance+i, 4) + end + + rectfill(inset-10, distance, 240-inset+10, distance+10, 4) + rect(inset-10, distance+10, 240-inset+10, distance+10, 20) + spr(10, inset-10-32, distance, true) + spr(10, 240-inset+10, distance) + + rectfill(inset+10, distance+10+1, 240-inset-10, distance+10+2, 9) + spr(11, 120-16, distance+10+1) +end +:: s_shop.lua +--[[pod_format="raw",created="2024-04-05 14:55:27",modified="2024-04-12 14:41:51",revision=158]] +-- this manages the main shop interface, where you look at the cupboard and plantss +-- and sstuff. +include("art.lua") +include("fairy.lua") +include("cabinet.lua") +include("library.lua") + +cabinet = Cabinet:new(40, 10, 2) +fairy = Fairy:new() +alchemist_sprite = 192 +alchemist_bob = 0 +customer_sprite = 0 +customer_bob = 0 +customer_visible = false +door_open = 0 + +shop_screen = {} +function shop_screen.draw() + cls() + + cabinet:draw() + + -- alchemist! + bob(alchemist_sprite, 0, 7, 96, 128, alchemist_bob) + + palt(30, true) + palt(0, false) + spr(16, 240-110, 135-36) + palt(30, false) + palt(0, true) + + -- countertop! + draw_counter(14) + + local book1 = {left=10, right=74, top=100, bottom=164} + if collides(fairy, book1) then spr(18, book1.left, book1.top) + else spr(17, book1.left, book1.top) end + + local book2 = {left=80, right=144, top=100, bottom=164} + if collides(fairy, book2) then spr(20, book2.left, book2.top) + else spr(19, book2.left, book2.top) end + + if customer_visible then + bob(customer_sprite, 240-96, 7, 96, 128, customer_bob) + end + + fairy:draw() + + draw_door(door_open) +end + +function draw_counter(height) + rectfill(0, 135-height, 240, 135, 4) + for i=1,height do + rectfill(0,135-height, 0.5*i*i, 135-i, 4+16) + rectfill(240,135-height, 240-0.5*i*i, 135-i, 4+16) + end + line(0,135-height, 240, 135-height, 4+16) +end + +function shop_screen.update() + fairy:move() + cabinet:update(fairy.x, fairy.y) + if btnp(4) then + local glow = Glow:new(fairy.x, fairy.y) + glow.start_color = 7 + glow.end_color = 12 + add(animations, glow) + + local drawer = cabinet:drawer_at(fairy.x, fairy.y) + if drawer then change_scene(DrawerScene:new(drawer)) end + end + + if btnp(5) then + add(animations, Glow:new(fairy.x, fairy.y)) + if cabinet.hover_plant ~= nil then + change_scene(Conversation:new(get_conversation(cabinet.hover_plant))) + end + end +end + +function draw_door(open) + palt(0x00, true) + if open >=0.0 then fillp(0b1111111111111111) end + if open > 0.1 then fillp(0b1011010111100101) end + if open > 0.2 then fillp(0b1010010110100101) end + if open > 0.4 then fillp(0b1010000110100100) end + if open > 0.7 then fillp(0x0000) end + rectfill(240-(96*open), 135-128, 240, 135, 0x00) + sspr(200, 0,0,96,128, 240-(96*open), 135-128, 96*open, 128) + palt() + fillp() +end +:: s_title.lua +--[[pod_format="raw",created="2024-04-10 01:43:09",modified="2024-04-10 15:04:40",revision=101]] +title_screen = { + continue=false +} + +function title_screen:update() + if btnp(2) or btnp(3) then self.continue = not self.continue end + + if btnp(4) and not self.continue then + change_scene(shop_screen) + play_script(the_script) + end +end + +function title_screen:draw() + cls() + print("Atelier Hester ", 120-(68/2), 50, 7) + print("Start", 120-25/2, 70, 7) + print("Continue", 120-39/2, 90, 7) + local y = 70 + if self.continue then y=90 end + rect(120-50/2, y-5, 120+50/2-1, y+7+5, 7) +end +:: screen_drawer.lua +--[[pod_format="raw",created="2024-04-05 00:59:25",modified="2024-04-05 00:59:26",revision=1]] + +:: script.lua +--[[pod_format="raw",created="2024-04-04 01:01:55",modified="2024-04-12 14:41:51",revision=538]] +Script = {} +-- sscriptanim generates animation functions and adds the boilerplate we want +-- can track time, but generally the ssystem we're working with is that +-- animations are objects which repeatedly get :update() called on them +-- they run at least once, every frame, *until they return false*. +-- so keep returning true to keep playing, rerturn false to end +-- the blocking argument determines whether update() is called on the underlying +-- scene, i think. + +-- the ScriptAnim.len variant will take nil returnss as carte blanche to keep +-- running, checking for exactly the value false to cancel out. +function Script.len(func, len, blocking) + local b = blocking + if b == nil then b = true end + return { + timer = 0, + length=len, + blocking=b, + update=function(self) + -- we wrap the function we got passsed so that it'll update the timer + -- and end appropriately + self.timer += 1/60.0 + if func(self) == false then return false end + return self.timer < self.length + end + } +end +-- ScriptAnim.once is cnofusingly named, and will call func(self) every frame +-- until it returns false. +function Script.once(func, blocking) + local b = blocking + if b == nil then b = true end + return { + timer=0, + blocking=b, + update=function(self) + self.timer += 1/60.0 + return func(self) + end + } +end +-- stay in this script node until func(self) sets self.done to true +function Script.waitTilAfter(func, blocking) + local b = blocking + if b == nil then b = true end + return { + first=true, + done=false, + timer=0, + blocking=b, + update=function(self) + if self.first then + func(self) + self.first = not self.first + end + return not self.done + end + } +end + + +-- functions for making a cnoversation script line that bobs the alchemist or the +-- custmoer respectively +function A(arg) + arg.during=function() alchemist_bob=abs(5*sin(3*t())) end + arg.after=function() alchemist_bob=0 end + return arg +end +function B(arg) + arg.during=function() customer_bob=abs(5*sin(3*t())) end + arg.after=function() customer_bob=0 end + return arg +end + + +-- here's a sample script for a guy walking in and asking for flibbertygibbets +the_script = { +Script.len(function(s) -- open door + door_open = easeTrig(s.timer/s.length) +end, 0.5, false), +Script.once(function() -- person appearss + alchemist_sprite = 193 + customer_visible = true + customer_sprite = 201 + return false +end, false), +Script.len(function(s) -- door closes + door_open = easeTrig(1-(s.timer/s.length)) +end, 0.5, false), +Script.waitTilAfter(function(s) -- cnoversation starts + change_scene(Conversation:new({ + A{"Welcome to Atelier Hester!"}, + B{"hey do yuo have flibbertygibbetss"}, + A{"Fresh out, sorry."} + }, function() s.done = true end)) +end, false), +Script.len(function(s) -- open door + door_open = easeTrig(s.timer/s.length) +end, 0.5), +Script.once(function() -- person appearss + alchemist_sprite = 192 + customer_visible = false + return false +end), +Script.len(function(s) -- door closes + door_open = easeTrig(1-(s.timer/s.length)) +end, 0.5), +} +:: sfx/0.sfx +b64$LS1bW3BvZCxjcmVhdGVkPSIyMDI0LTAzLTI5IDAxOjE0OjUxIixtb2RpZmllZD0iMjAyNC0w +NC0wNSAxMzo1NDowNiIscmV2aXNpb249NjY4XV1sejQAEAEAAFEHAADwJ3B4dQADKAAAAwAED0AQ +Ag4AAaABIAKgDgAPEAAN8MoBAgMEBQYHAA--kAgJCgsPDA8NDw4PDxAA8AANDxEPEg8TDxQPFQ8W +DxcTAPEBDxgPGQ8aDxsPHA8dDx4PHxQA8QAgDyEPIg8jDyQPJQ8mDycUAPEAKA8pDyoPKw8sDy0P +Lg8vFADxADAPMQ8yDzMPNA81DzYPNxQA-wU4DzkPOg87DzwPPQ8_Dz8AD--w-wEA6-8nWgEQBg8g +EAEgASAB8AACEAIMEAEgDyEgATAPQPDDDygP--DGD-gKD-8PgA-3Dw0B8AkBEAYMMAD-OR--AQDc +v-gPQAANQP--sPBwCgD--2Qf-wEAl1D-----Hw== +:: sfx/.info.pod +b64$LS1bW3BvZCxjcmVhdGVkPSIyMDI0LTAzLTI5IDAxOjE0OjUxIixzdG9yZWQ9IjIwMjQtMDMt +MjkgMDE6MTQ6NTEiXV1sejQABAAAAAMAAAAwbmls +:: shop.lua +--[[pod_format="raw",created="2024-03-29 01:14:51",modified="2024-04-05 14:54:05",revision=1117]] +-- this manages the main shop interface, where you look at the cupboard and plantss +-- and sstuff. +include("art.lua") +include("fairy.lua") +include("cabinet.lua") + +cabinet = Cabinet:new(40, 10, 2) +fairy = Fairy:new() +alchemist_sprite = 192 +alchemist_bob = 0 +customer_sprite = 0 +customer_bob = 0 +customer_visible = false +door_open = 0 + +shop_screen = {} +function shop_screen.draw() + cls() + + cabinet:draw() + + -- alchemist! + bob(alchemist_sprite, 0, 7, 96, 128, alchemist_bob) + + fairy:draw() + + -- countertop! + draw_counter(14) + + if customer_visible then + bob(customer_sprite, 240-96, 7, 96, 128, customer_bob) + end + + draw_door(door_open) +end + +function draw_counter(height) + rectfill(0, 135-height, 240, 135, 4) + for i=1,height do + rectfill(0,135-height, 0.5*i*i, 135-i, 4+16) + rectfill(240,135-height, 240-0.5*i*i, 135-i, 4+16) + end + line(0,135-height, 240, 135-height, 4+16) +end + +function shop_screen.update() + fairy:move() + cabinet:update(fairy.x, fairy.y) + if btnp(4) then + local drawer = cabinet:drawer_at(fairy.x, fairy.y) + if drawer then change_scene(DrawerScene:new(drawer)) end + end +end + +function draw_door(open) + palt(0x00, true) + if open >=0.0 then fillp(0b1111111111111111) end + if open > 0.1 then fillp(0b1011010111100101) end + if open > 0.2 then fillp(0b1010010110100101) end + if open > 0.4 then fillp(0b1010000110100100) end + if open > 0.7 then fillp(0x0000) end + rectfill(240-(96*open), 135-128, 240, 135, 0x00) + sspr(200, 0,0,96,128, 240-(96*open), 135-128, 96*open, 128) + palt() + fillp() +end +:: [eoc] diff --git a/desktop/drive.loc b/desktop/drive.loc new file mode 100644 index 0000000..37d5ed1 Binary files /dev/null and b/desktop/drive.loc differ diff --git a/desktop/readme.txt b/desktop/readme.txt new file mode 100644 index 0000000..9968bc8 --- /dev/null +++ b/desktop/readme.txt @@ -0,0 +1,234 @@ +--[[pod_format="raw",created="2024-03-10 12:02:52",icon=userdata("u8",16,16,"00000101010101010101010101000000000106060606060606060606060100000107010606060606060606060606010000010106060707070707070606060100000106060607070707070707060601000107010606060606060706070606010000010106060707070607070706060100000106060607060706060606060601000107010606070707070707070606010000010106060607070707070706060100000106060606060606060606060601000107010606060606060606060601010000010101010101010101010101070100000101070707070707070707070601000000010606060606060606060601000000000001010101010101010101000000"),modified="2024-03-25 20:51:12",revision=64,stored="2024-03-10 12:03:12"]] +-==================================================- + Getting Started with Picotron +-==================================================- + + +--[[pod_type="image"]]unpod("b64:bHo0AF4HAACACwAA8RlweHUAQyDwZATw-----9Zd8FaN8A2N8DyNUI3wTQ0QDRANAA3wDQ0ACwAh8DwHABKQDQADHwAj-Q8dAII6-QzwNC3wBC0AI-0PPQA3Og0ANgCTAA3wMh0gHfACFgBF0B3ADSkAwfAKDfAwHWAd8AANYBoAEWAWAKgEHTAN8C8NoA3gFwBRQA0QDTAGAJ4gDfAXLdD9C3AfADBQDQAfAJ4WDSANwB3wBx0jABIdfgBgIA3wD-0DLwBf8AUNAA1LAABTAB0ADQAqAJ8d4B1QDRD9BRApAAEiMC0lAIANAA3ADQANUBwBIAMNKwBxUA3gHdANUCsAEp1MAAEpADEQzRAnAD3AHTAoAABTAEFNIA0wKABSDTAtMA0sADFgDTD7AAwwACSNYCwAMyBNICwANRANgCwAYEAN8AAd4AcAETrVAEAQPQAdAQFwMA2wHQAd0CgANB0AHToAXkANYB0wOACBrRAdAA1ADaBcABnAbAAt8AMvAKnwCg2QHQAtAB2wwgAAOwEREAgAYDAN8AAt8IQAAi4AImAtrgARoLYAJCANXAAAagAvAB0yAAEAHgABoQFBHQAtgFYAADkBAjYAQTAdQA0aAAA6ABFdOAASXTYAEUAUABMghgAEhgFtID0wDQBtZgAAFwEGAgAxIA1AUwAA1wARAI8BBe4BARcCSF3wAR1oABQ9ZwIYYDwCITANJwACYQAAGAEGAgATIBAAMABNIJACCZwCC10BEiCGAFJNAC3wEuUCCyEAAlAAERCEAErwEv0LIQAM2QAFSgEQPVcAL-A0TgAEAzoBL-AzTQAKAZwAEz1RAAAtAKBQDbBdwA1QLfA4TAAB5AAVPUoA8gNQDcANME1wDSAtID3wNP0MQB3YAAGHAGBQDdAdYC13AWOQHfBUDRBVASHwNQADgIANMB3QHfBSzQLwJy0ATfAKrfARDVD9BHA98AIN8FKdAA3wCw2gDfAQDVD9BmANEB0wPYAN8EgdcA0ADUAt8AoNwDYDALMA8ALwBT0gDQBtMD1QHfBGHXAtQDoAkOAN8A4dED3wAR0CsA0APTA9MF3wSB2gwQP4AQsN8AEN8CQdgC0AHYAd8FAWAOAjDcA9oA3wPK1gLQAdYCQBEAkjA9jwIB2QnZAd8DjtQB0QGACwHw1ALRAdMB0wHRB5AGA3PRAtED0kABBQYwSACA1AjUAN8B4hASAdQIQDwB0gLSAN8DYtIC0gLS4BEmAnADAwDYBVAlEdTTAdQCsAaDBN8DQ9gCMAESCLA3AgDfAlDTBNTQHVMA3wOw0AHTAtMB0wXSUAANoD8QIgDfAkDSCNIF0gDfA5LUBNQJ4CBWsAIBBN9wRA8CNNEKwCUT0QTfA4aQAHJwCQBU0wjTBN8CZd9gRKAF3wPUYAsgI9EC3gLRA98CJNFwVAAF3wO98ARC1ADTAlAABtA1AgLcAtIA8CAPcAACkAUCBd8DFtigQTQCcA4dAdMC0gLaAtIC0wHfAePgDyAwAN8Db9LWAdYC0g7SAtYB3wIRUA8wQ1DfAtDUANkC0wrTAtkA3wIQ0gLACRQA2wPeA9sA3wZQAxLfA03gMCAgAArgOB0E2gTdAN8BzPAEkQHfAyIABgIA3wAf0B-gETGQQBMvAxDc0ACAQAADcEgPAEzfAEDfAXfwRZDUAd8C9JAO8ADfAnDfAUHZBNQA3wLhsAAHATDUAtMA0AmAHwAS0NAP0pAB3wKQ3wEQ0gnRCHARIsJwACFgBAEE0gPZwAQQAd8DMsAGEN8CsN8BatBhIAfwMCnQEyIB0ACgARPRcAIgkNKgAxFR0gpwMWACoAAtUDAeEDoj2grSAd8C0N8BnMAx41IwAABAhBHXANMCcAEBi8AQYnABUgJQAyAB2Q4gQQL7cHAGYGL-A2TAACNYC9MCUAAMQALvA2TABijSANkA0gJwAB5gYfAE4ABCM9MKIIIPAxUgAB0AINnACAHQANID0QvSAUAQOPA0-wFg0w7wAGQD0QzVAsAD5gDVAsAAlYAPABjRA9ID0gDcANsA1ADVANoI0EWhH9A-AwVwABCgCAEA1gHSBNIE0IAgD1AhGwLQABbQQeMIYAQe0gXTAzAgArCQArAEmQHfAFLQCwIB0A-QwgjbBNoA0PBIKQTbANgD3wBH4A0v0C8AnN8AE98Agt8AEMCFEd8AD9AdECIPAA3gDAoA3wBR0Q-QAQHfAEcAlxXQAd8AEN4PQCIP0DfQCMMN3wB-0E8AYeAACHAAB8AhGgwAGAwA3wCP0A8AdLB2KN8ALt8DIiAAFCAAkeADN98AMeABACEgdy0A3wCG0AfRwAMG3wBCwABB4AYAPdMA3wBxEBuW3wBg1wDQBtII1wIQABXgAg8AZBAEEFDYCN2AcRDSMA8BEx-TDwBP0A8AP9CUANAP0R8FHtcB1wTUD9APABHcB9ILAD0YtdAB0gHTD9AKBd4H1OBfAGk-0X8AV9QC3wlW0g-QLwxw2QDfDUBQAS0woA8ABATfDWDSAN8Nwt8P---0c=") + +Congratulations on being the new owner of your very +own Picotron Fantasy Workstation! + +This is a quick guide to get you started using +Picotron and creating your own cartridges. + +** Workspaces ** + +Press ALT+LEFT or ALT+RIGHT to cycle through desktop +workspaces. Click and drag the toolbar to reveal a +tooltray. + +On boot, /appdata/system/startup.lua is run if it +exists, and you can use that to install widgets in +the tooltray. See /system/startup.lua for an example. + + +** Customizing your Desktop ** + +You can open the system settings via the Picotron +menu (top left) or by typing settings at the prompt. +To create your own lists of themes, wallpapers and +screensavers, create the following folders: + +/appdata/system/themes +/appdata/system/wallpapers +/appdata/system/screensavers + +** Creating a Program ** + +Picotron always has a global cartridge sitting in RAM +at /ram/cart ready to be edited. Click on the code +workspace (it looks like "()" at the top right) and +type in a program: + +function _draw() + cls(1) + for i=1,24 do + circ(240,135, i*t(), i) + end +end + +Now hit CTRL-R to run it. You can do this from +anywhere -- CTRL-R means: "run whatever is in +/ram/cart", and the entry point for any cart is +always main.lua. + +To stop a running program, press ESC and then ESC +once more to return to the last desktop workspace. + +To create a windowed program, the window size can +be set with: window(width, height), or to run at +different resolution use the vid() function: + + vid(0) 480x270 + vid(3) 240x135 + vid(4) 160x90 + +Some handy functions to get started: + + cls(col) -- clear the screen to a colour (0..63) + circfill(x,y,radius,col) -- filled circle + line(x0,y0,x1,y1,col) -- draw a line + spr(index,x,y) -- draw a sprite + map() -- draw the default map + sfx(index) -- play a sfx + music(index) -- play a pattern + +Picotron programs can define a function called _draw +that is called each frame, _update that is always +called at 60fps, and _init that is called once when +the program is run. + +** Saving a Cartridge ** + +From terminal, use the save command: + +/>save mycart + +An extension will automatically be added (.p64) and +the contents of /ram/cart will be stored in that +cartridge. Inside Picotron, cartridges are folders, so +you can open them up and look inside! But in the real +world they are stored as single .p64 or p64.png files. + +** Commands ** + +Some handy commands: + +ls list the current directory (folder) +cd change directory (e.g. cd /desktop) +mkdir create a folder +folder open the current folder in your Host OS +open open a file with an associated editor + +To create your own commands, put .p64 or .lua files +in /appdata/system/util. + + +** Running a Cartridge ** + +There are some demos in /system/demos: + +> cd /system/demos +/system/demos> load carpet.p64 + +Cartridges are also like regular applications that can +be opened by double clicking on them, or typing their +name from the command prompt. If the cartridge +creates a new fullscreen workspace, you can close it +by pressing ESC and then right-clicking on the +workspace icon. + + +** GFX Editor ** + +The second workspace is a sprite editor. Each .gfx +file contains up to 256 sprites, and if the filename +starts with a number, it can be indexed by the map +editor. + +Don't forget to save your cartridge after drawing +something -- the default filenames all point to +/ram/cart and isn't actually stored to disk until +you use the save command (or CTRL-S to save the +current cartridge) + +s select +space pan +f/v flip selection horizontall or vertically +cursors move selection +ctrl-c copy selection +ctrl-v paste to current sprite +ctrl-b paste big (2x2) +tab toggle RH pane +-,+ navigate sprites +ctrl modify some draw tools (fill) +rmb pick up colour + +Draw sprites from your program with spr(index, x, y). +0.gfx is loaded automatically. + + +** MAP Editor ** + +Changes made to /ram/cart/gfx/0.gfx automatically +show up in the map editor. + +The map editor uses similar shortcuts, with a few +changes in meaning. For example, f and v also flip +selected tiles, but also set special bits on those +tiles to indicate that the tile itself should also +be drawn flipped. The map() command also observes +those bits. + + +** SFX Editor ** + +There are 3 modes to the SFX editor: an instrument +(synth patch) designer, SFX editor (for playing +sequences of notes) and a pattern editor, for +arranging SFXs into groups to play music. + +Each instrument is a tree of nodes that can either +create or modify an audio signal. Please refer to the +PFX6416 design document for details: + +https://www.lexaloffle.com/dl/docs/picotron_synth.html + +Basic node instrument editing: + +Click and drag a knob to turn it +Right mouse draw to adjust the range of a knob +Click and drag an envelope to a knob field +-> The envelope now applies to that range + +Press SPACE while in the instrument editor to +kill all sound. + +** Saving a PNG Cartridge ** + +To create a .p64.png ready to be uploaded to the +BBS, first capture a label while running it (ctrl-7) +and then save it with a .p64.png filename extension. +To print a title and author/version on the label, +type: about mycart.p64.png + +** Loading a BBS Cartridge ** + +> load #cart_id + +This loads the cart with a temporary filename in +/ram. Don't forget to save somewhere to disk if +you want to keep any changes. + + + +** Reading Games Controllers ** + +Use btn(index) to read the state of game controllers: + + 0,1,2,3 Stick L,R,U,D + 4,5 Buttons: O, X + 6,7 (reserved) + 8,9,10,11 Secondary Stick + 12,13,14,15 Buttons, SL, SR + +A secondary stick is not guaranteed on all platforms! +It is preferable to offer an alternative control +scheme that does not require it, if possible. + +Keyboard controls are currently hard-coded: + + 0~5 Cursors, Z/X + 8~11 ADWS + 12,13 F,G + 14,15 Q,E + + +-------------- + +There are still many unfinished and rough corners +but I hope you enjoy messing around with this first +version. See you on the BBS! + +-- zep diff --git a/listcolors.p64 b/listcolors.p64 new file mode 100644 index 0000000..aa5776e --- /dev/null +++ b/listcolors.p64 @@ -0,0 +1,257 @@ +picotron cartridge // www.picotron.net +version 2 + +:: gfx/ +:: gfx/0.gfx +b64$LS1bW3BvZCxjcmVhdGVkPSIyMDI0LTAzLTMxIDAyOjE2OjI4Iixtb2RpZmllZD0iMjAyNC0w +My0zMSAxNDo0NjowNyIscmV2aXNpb249MTldXWx6NABtAAAABTEAAPMUe1swXT17Ym1wPXB4dQBD +IBAQBPDwLGZsYWdzPTAscGFuX3gIAM95PTAsem9vbT04fSwxAP-------------------------- +-------------------------------------_dQbT04fX0= +:: gfx/.info.pod +b64$LS1bW3BvZCxjcmVhdGVkPSIyMDI0LTAzLTMxIDAyOjE2OjI3IixzdG9yZWQ9IjIwMjQtMDMt +MzEgMDI6MTY6MjciXV1sejQABAAAAAMAAAAwbmls +:: label.png +b64$iVBORw0KGgoAAAANSUhEUgAAAeAAAAEOCAIAAADe_FMwAAApKUlEQVR4Ae2dX4gVx7b-qzc_ +pQmBg4FwT3nBhxAkzAnhBNHrHw7moXGYmOho-rDJ3lyQgATBB416TPKQxGjMPAgShCBcekKjxj1J +NMNIPyQENccgCZIrBwl5EE76XoRIQELndf9_lzVTU-b_17u7VnVV9fqyWPvbvfeuWl1d9VmvXvf_ +XUYikUgk89SgJSCRSCQztSJz-d7R_cydN49M0TKRSCQkAXOAM7If8uPM7-NjKufvx8Dg_9-0v--3 +v42s5M0jU5DHAPSggWgbkUgkVDqDee-ovELmyKgda0z5x728Lq88dO4D6ExZMAptIxKJRFLbMPL0 +jyygxR-g10RnEolkPulyqi8E9StTxpBnyQIa-gx-MORhSCQSqRdQfS-zMD0-2UaP-Pe-oT5sH0BD +TZkloG1BIpGcV07WL_v9b1DBnQV0-nZEIpFIJQXAee-o-JtHpgQfwedkKCqvhlfSH8eDkF2oZq97 +-y7tEhKJRDJQDVoCEolEMlMeb3UYY0mQ8tiHW1V5t5UEKe22kqrJViGRpE3f6rAo5K0OROWeRSGE +k148KeUymcK0MIohLvlFQJvGMocXXTwpRcmgXmVmNg0mdntaCP2_Pv1fg6cVMNAbewatyx5vdRhj +SZDy2GeMGeidVBKkDj_dfrm9W0g13tnUmavz9jZ2MzOFaWERW8z0i4C2iGuuvQAJ1hRKgnqVmdki +yBjkaSEq9w73-wo9rYBR3sxzZ372eKvDGEuClMc_Y8xSb7uSIHXjQUyTMzuEVNcd7ESXNqozF-YW +NXa7MoVp4QBz9PhFQDvDODeaDQVGUK8yJ7sEHFxPC2Gad6n-G_hpBYzyhpw7Y7PHWx3GWBKkPPYZ +Y455S5UEqdX1my-bdwipNjuVurTB3vD2bnumMC2cZ9HY7LKaX2N5G18ShYagXmVOrgOIxvO0EIZ7 +q-u-RZ5WwBBf_bkzKnu81WGMJUHKY58xpsFP3JwBM0SXD_1BrcEuJUFqY9k2ytIdQnJ3R_rtkFsn +1nXv3x0ZWyfWaainwi5dwBvY3t3OFNWGTi4Z6xcBrYc1OeksM1pDbRa9MFE5hbagXmVC1gMoE73O +ycYFdK1fzABvV-93xtMKVO4rOXeVZ4_3OuxBJUHKYx-DT9ycWbj2RWa6QZrc_MKtp-ej1jPcG6sk +SA2v0EmZvzFILmoAuTE64daJdd37d3PG1ol1NezY_b05Tb5umaLaqJAJ_j3LD4LyvhigK_Sg6S9P +ekcUmoN6lQm5Qjho8jonGxfQtXgB5bzhLcR5TytQodd-1vRnj7c6LJ_SIOWxX8ZP3JxZuPZFzukm +N75w6_n9SuZV601TEqRmFlYTGbsxSE5oTKKX6XhbJ9Z1D57r3r87Og6e2zqxzszura1jj_UrbPKU +5R1CUVUYyIrynhWGQoG-LAI6XwhAG8tEM5sHRbVBvaqqbDIoinudkwlAH9h2_sC20yMB7eyio3kz +20YNPa1AhV7DWdOWPd7qMHVKgpTH-hA-cXNmYXLfyHEmF07eenp-zjEN8YYoCVKj6qmtTNsYJDul +lPd5utzWiXUjg7p3ea_51VMeeSgoKgnrGPIATzAAYRSnKvEmvGAKo4J6VVXZbpjUnKRue0NaBfkM +NWg1NHvUs4aaPd7qMHwlQcpjv56_WiVBakIZJFmG7A2SDdLSB0RDq20nR_reOb22V0x5rONAoTns +40Yl4KiKU5X7Cl_2vPgU5gT1qqqyFdDwWBQyxhhjPPaTIM3pu1MB3DFN3nw87rPY7ZttM18EiYQq +3uowxpIg5bEPdwp45edRefbgOcfSL6c2mvzmvPm4zDurxBdTMruz2-mWziqphvJ2bijALvsek0Xh +uFzvTgUmP9KqvdfsonOxTs6abaIziRitZChj_eCxKMwPBSsA7c3HBXhXuYf3kf-lJbM7CdA59T-- +_b_MsT--17_JS_F7fznoq_FjIpU6Vkn1BPTicVCXjYJDQ_2SvXd0fqz7w4cq8C_LiJzxQN6xcq-e +mP3v3qCTnAGcEt5hQBNYnKEzvT55Y2fuA1XFUSrvFUoesLBfUeSfU2PX_uaRsf-z5pGpwoAWNQPI +7PVD3kXS76lPtP5Ch3kkBGW8CgL__b-_Dbz8A-nb3v8OGhY4O2ScXv4OGlOMU3M6i40te1UQlL3a +AcvnFdA6xsp9F1GG6XtH5wVeZSO_ypg8BM-8TEzX_8dlhEld0VIv2rt4tOX1n_2-lYnawyUjDwiY +_Upmt-ytuMzc7-vVkHF668n8cRCvSfpVOQdWCBDIUBju_9JTpq18R2b08D8OYXTmZ8N-LLjmgBev +Sryw5U7Z79mJxcVgrRyIvdzPOUtfXg9HPDF0_VCozvL4lfgG0qoNAWgvfAfhu7DEQ7rke3Ov3pj9 +796gMzwciAKglczyP--5v4P4C--C6B926UTrL2Izn2j9pZfO4pgo9yKXJ1Ixv6LIP-OydxiUBcHz +o7zAigDI3POMsWTAVibmDhJwECgpe5mA4mYGqfKljEsYp_9X8m8ys8hElv8yfJyaM1ot_Mb15Qcp +lldAuxgr9y7Tm0em3js6PwTHMpQzdBZ-7P1WXIqfwVe9-_r7zkQndNiTcmoQEIf8svcHQy7z-2s4 +f8f6MakqaTvjHotCwTUB3_G_OxWYvHbefDzW49jqm_1u51s6KqTaytu5gbc6wDLNWdthbzj55tyn +89IGpaCobTDGgJjiaGjzJemU33u81Rl3gl9ObTSZzqv2XhNerKl7njXbtvfRLnsOewqPfSkmAq9Q +Bc7OuEpmd4q5ZC9-VVhX2RR2-ZvYvJgIvJhavjT5FVSrRhKkiwc_d5YJaCCdRZ0O07lkD6_Vuuw5 +j33psS819AMkyRgCUpenszYBizexedEPNDQGnQLgoPkohOCtjqvezUdzAp3YAbOI6ZRzEzt6GS3f +LI9O7MhMl8lqWtfSoTAhKz-sDZda2cgWx2PfGU-KKY99CbD22JduPFGG3VboKpvaxOYxjjaPfXE0 +Kvdjv0rpL319g8c_BNytiRerYLUn5RGgGTDtxhMlszuT2Z0WMTpD56tsSuSyvWoU4PT7sVg0MjeS +IIVGVKvc24Et9SSSXXTexObhUr7ppGTUlPBRCMFbndp6K8u2X132HHbIEymvn7c62JGZSL5Ugk7s +yMwiT63qFYhDYXIufNhXUIdnjPHYFy3LFk-KL499aXX9yezOIZeGaxObz3mzyMoEKY99cTTM9GUo +1OCxDwF3a_7F6ljhSaSaSz4Lxvqc-OmbG8BpyqJ3ZTqz4Z5EItklGTU5fBRC8FaHfMYbXZ796rLn +sAO1ft7qYAdq-VfZFHZgbyE4DnblsQ57gxrasNcf_6KVmeZJJFISpDz2xdGwwos8nDxgGjz2IeAu +_ZFerGDlnkSqueSzYJ0fwhmRG0mQQiOinDOL9RVdsUJPIpHcEOClx0chBG91yOf31Zdhv7rsOexA +rR_2AWqg1n_VTWEH9haC4_BG7nvYG9S4SrY7HvuVeBKJlAQpj31xNKz2fR-Qw_7SNdwrejxrtlc9 +OY39UL-8cw7MqienhVel7ifoL8V7dXki8CoVhegP0GwvzwVenlR8W0i-vo5e-qMfLU8ke-nbMnIe +X40kSBcPvK48cXNmeGiuR1WuhNR6pKET4Kn7CfNeZd6rOvoBljJQhrBEv77OHv2IPfrRMprhsjyd +HZZAyooMX7D9xM2Zhcl9w4ubXJhJgj166lHuZWQDRrH8rL7t8ss-56xmtPVqth9gtFXCBnESpDz2 +Xc0rdL6qrcdPL1z7YnLjC8MZvTC5b-L4yVtP77f6TMES43lSTnmvsu4nzj1VFLJm26J6f319mdS- +vq4M3EAxcTTc8w0e_xDwBaq-9fT_yY0vLK-u3-_WjR7GaatNj5efq7wn5We09yrR2Qg6P-rRYgCm +S0o_C076RhKk0Ii05YXJfQPX_0FG668NNYuuKHf_kp5EsojOpHG1QhBEZiKS33r89MK1LyY3vrDI +6Pe-eQDN73_TAbTO2jR4cQl4Letn9e2SVU9OQ-7ln3M27vLuJ4wx5r1q7TGNwsXcbFvKaNCjHz3g +lSgJUh77ruYVwml4T5cP7Znc_MIDUAYBqXvo7KRgwcv4RUZrrNlSLgtZjGZQhstWYToDYlVclumc +ORoueY_3Ojrf1sTNmYXJfcuAfv_bxfygJhdO3np6fx14ndlnI72ANWu2Vz05bTWau59YjuYo1I1m +pfr1dd10Vi7N_NKvBhx4PXni5szCtS8mF04uz--3vy1mEQ9iqyY5J6nlHluf7kUi1VaNDCNQ-eVD +eyY3vrA8_fvfjKxPW20meIFs_U7vt71YJ5Fqq95z4VJu8NhnjA3KGFqY3PcAozNBYozHvkAweB77 +4r0ITyIRncW5cNJ7vNXRtpoTN2cWrn0xufGFBxjdo8mFk4yxW0-vp-0H70nA_gE126uenMYu4Jd- +zuEN3v0EfQG9VzFHj0L0B2i28cb_9XX08h-9CHd8nfiqRI3M4ZcvMx4uy_TLh-ZMbnwBEDwkFq59 +IRdQ5ywYDX01k0kkkttaIVjAY1_goa-PA-GRHiQQ3F-vf6NkLmd8f3zP0u4lkZYZ5WRu8NgHOo_V +C_vyoT2LCB4ckwsnF39Wb-HYF2ve15NIRGdxLpz0Hm919C-rxM2ZId-eeno-7bwkSEf8otl__-Fp +7DLe_XmOMQYTgVeo7r0nsOv3Vv4k5pK9-FVhHdh2Grv_Dy-tEXPJXv6qsE7e24Jd-76VX4uJwPde +llEl_NKpRoYFY3kwBfKtp-dfPrRnUC4zshtZ7qVDsh69-fj0Oz-PvfPznIZ_gCS5EwCpvZU-aWgP +qiR3AiD1h5f2aGgPSnTy3pZ9K7-et-Jr4LK4dBusygBdBiVl4E6_fPPTo3d_nrN9l3srfxqCbPP1 +4aU99i4_NovLEMz83OCx--9BXT6TlIjHvljVkV6n3n582gFSCzr3ItsiWB-YdvrAttN2UfvkvS2C +1CfvbTl5b4sqOotz4aRfkSFsYa9kkJp70TZlM9DPEp0Lyl46M8YEmi1itExnxhj4zM1ich4L-wdo +QevhvjsV2LWVV_29Bo9gRZY7Z65MdCZZSGfSWPJYFApmAyb6euvovPh48-Hw5zLHj61m__3Hp7EX +8J2f5_RZ1JK6e_8J9A2w8id5IvkSfBkd2HYau-4PL_2RJ5IvwZdEJ3b9_1Z_Lc8CpIY7aqgdheIc +OZkbPPbhCUdmEpJ47It1Hsvr0Ts-z4mwdIW9lT9ByJcW1f-hpT0Q8qUtxe9b_bUI_Y7CsyMTTea1 +A97jrU6ehfjl1EYbT_aqvdcMrzAJ0oL-bLbffnxaA53xBu-ee0IDmvEGP7DttAY04w1_8t4WDXTG +nSAKM7y2EVND1MgwYpBXpfeOziv-15Bv4RGMzXLPLJBJJFLmRGBQq0J5ogXx2BfP1uu7U4EqQL95 +ZErtv4Z8683Hw5_rWl9Kzfbbj09j7493fp7DG7x77wn0-b3yJ7zBD2w7jV3-h5f24A1_8t4W7Pr3 +rfwad4IlfA1idxKkVueG3H_G514sQgaT8cMvhR-y_0ETyYP0LcOKng9R0pNINdfwMyKTTua1Rd7j +rU6ehfjl1Ma_3HzzyJS4BC_MfD-z7aDc_-fM4H0n6vsX0Kq910zbUkmQqhmo2X778Wnsat-5eQ5v +8O69J7Dr91b_hDf4gW2nsev-8NIevMFP3tuCXf__lV-jThCF_VFuYwdqZJAxyPdVBovvHZ0Have9 +HKmcvweaD4FyLw3NyfJeKZ9JJFLO8zKSZmbKEy1IfoZe350KenkqI3LQJZhBl33v9GV35vd9TZ-H +m4_HP5d_r0zN9tuPT2Pvj3d_nsMbvHvvCfT9vfInvMEPbDuNXf_Hl-bgDX7y3hbs_vet-Bp3giV8 +jcv0JEityI2c-WfkMwNkIeTLzLc5-w7Y7f12_H8N7-MQCj2JVHMVOzsyAWVeG_g93urkWYhfTm20 +8f2t2nvNhDKSIFU-aLPNjm1HL-3w54yxxYnAq1yXtfgn_MbyXML3XhbSn6ZfwS7-t7mzYi7Zy18V +1yX8-bPt8_WJZC9-W0ZRWB7xJhOskcHHIG_p4BGqzfI_UJs16dh2dvhzdvhzHf0Aax882Ak0NAal +kjsBkPq3ubMa2oMaXdrOtn3Otn2_jGkIVS243DkynHKeaEFyrb2_OxXYeDC9_Xj4c_nxKGq2dRDz +sHSQgNR43MQQv7E8l-C9l6W5iaTf5s7KXO5rSqETWzKIgdSDLotpCV_qWJ8EqVG5kbPPePOxjXSu +tgAe_xBIXp_ObVdPZ1JRZP9p_hUNvUGxMOi8dBxUnSmZjDKvK-Qeb3Vo02MoCVLcCZptdmw7_mPI +UFbO6GQtfpO8sTyX8L2XhaSBkr-NnRVzCT-oThFoYgsojENnxhiLQsX7JfbN4ghvdVgU8lYHwigP +xsasYyIgJnbALALQipvYWvQY1AxU9IY-Tb_CHUOagYL2cGk7evRtAwobg_pjm-GVB2NRCAGVkVfl +0UMboMVEyqUN0MMvjQd030sF668N0PKlakArjOHnupo8pHsY5c2Hcrb1Ya_MTkAjSRugcaQN0FjS +A2hMladKsTOuzXuLR52kBDhBqm_yZhsdoIyxw5-jAhr9BN9ABTR2_b-NncUFNLa2Ye4fxlgUFtwX +sW8HU3R2g-JedDMDs_5JGWPHtqMHbkNbix6Y_tP0K9iBu-6XtqMHtooe1ZJeWzCgnqiefBmvNQjQ +BGgCdKGzo-bs42aFXUWzrxbKfTuq1hUgQBOgaw-onOcFmwl4J91bPOqkwpAJ0mombrbRAcoYO-w5 +LqDRT-ANVEBjl--b3FlcQGNrG_b_YYxF4bCXH-vW8wWD_pq93CE15wqnZoyxY9vRA7e5rUUPTP1p +_hXswF3-S9vRA1ujjme1XCofjEUhBIxOflxfWRCgCdAE6J5zYQ4flOQGj33GmBsZT31nhKjQk0g1 +l3wuTKstCVJRW2Hv8VaHXnOBpa__iGb7wo612JPs_uwGmAs71gqvSmvmutj13572xFyyl78qrP1P +rcGuf_bH22Ii8L2XhbX7zh-Y9Z9Z-ZCYCHzvZSlFoZl0VqVGBjfOeDAYWbTuyrM2aegEqJI7AZD6 +9rSnoT0o0f6n1sz8eHvmx9vA5cyl_dp9548zqx86s-oh4HLmsrzEWbCFUWPJgxYEzylGIT-cG6Fm +WwM3d31248KOtSLjcRNJt6c9mcuZ2TN3CqATu-6ZH29nSC1y5tti6MSu-8zqhzKkhiwuy04QhdYx +ZKzcgP7jai7Tk-tmCEM8qUxvKElnzQIu93pbJHAMjFZDZzsF5JV5PcgnQerxVoeOa85lNaugZvvC +jrXYk_z67IY8y67PbqilJHb9gsIykVXRef9Ta7DrBxD3pXN5TO__8wd2-UBhGcfCK2G0q-gC2vDY +b2TQ47CHy2J5cTcs9TdDsh7t_uwGcFktnauSKjprU3kQVyslIB4OMjd8hlTgPRaFgj7iC-K93jg1 +2xd2rNVAZzAXdqxVDug1c13s_oHFYqLb0548aUlS739qDXb9Mz-elmcBUsOd8tTefecP7PrPrH5I +ngVIDXfUUDsKXeIMGDk3eOzDF7XKskb_HsJAr1PK6axTt6c9CNmXpLM2zfx4W4R8x5bFP7P6IRHy +HXu3k3IJUoORs8dbHVqgkQtnoprtCzvWWs3lNXNdDWjGG3z-U2s00Blv8N13-tBAZ9TxbccXEIbH +vkBNxjcyGKqJ7_1UvVmskbGZRKq57GWRoNDwX3osCvuSm7zparYv7FiLPcmuz27gDb5mrotd-_1p +D2-w-U_twa5-5sfbeIPvvvMHdv1nVj_EO0EU2sgWMHlyg8c_-IGynCEM9yQSyUYBpvNkj7c6tF6Z +hbNDzfaFHWuxJ9n12Q28wdfMdbHrvz3t4Q2_-6k12PXP-Hgbb-Ddd-7Arv-M6odQx7cIX0mQ8tgX +hMnpGxkqOelz9itYQVgXKzKJVHPZwh8ZNWON4LEoHIvozntr1Gxf2LEWe5Jdn93AG3zNXBe7-tvT +Ht7g_59ag13-zI_38QbffecP7PrPrH4Id4IoNJknYMrkBo99GKjOGZYDAu5Y4UkkkskCTJfJHm91 +aBGtrLvZbr-0PPYk4fmL8izh_YsKB3-3jTPY9b91YreYS-byV4W1dWIddv2Xb30nJgIvppYvi_mr +j_9g1--sa6vFROB7L8vIQHwlQcpjX1ClpG9kCOWAH6tHwWrCWliXtSk8fxHC0h4sdwIg9Vsndmto +D0oELL586zvRDzQ0BoX66uM7z762_tnXVgOXM5flaWiOz8BHycgei0IlpLfaW6lmu-3S8xrQ3H7p +eSQ0a0DkWyd2y1zOzJ65UwCd2PVfvvVdhtS9vgw6set-9rXVGVJDFpdlJ4hCExgCBiM3eOzDBHXL +sAQQcMc6r03tl57X0Ay06d03zpSns2YpIXKFEjgGRmvoDToFmMbIHm91XFqpsRbUbjXbGqAZnr8o +Y1q_VAJK7PoFhXuJXJ7RWyfWYdcPUO6lsxJea6AkQFnQuS_yy6hyfAmS8NjH8I0MrazzBfpSEqQ8 +9uH5rc4kM7uCWilhcYVSAuKRfNTvIVBnYYx5LApRO4Cx3no12_2XnseeJDx-UcwSnr9oHSvfOrFb +nki_BF8Sndj1X771nTwLkFrcKQnurz6_g13-s6_tlmcBUsMdNdSOQv3cgEsNmTHWgI_aZHhsCLhj +tdej8PxFCHt72VsndkPIl7YUf-nWdyIyd6yo-9nXVouQ79i7nQDWerLHWx17V6rAsrqjZrv90vMa +6Iw3_LtvnNGAZrzBt06s00BnvMG-_viOBjqjjq8NX4IePPbxPI-9zLyNDLkM94V7URKk8PAuZRKp +5tLDHG2Uk3kF3mNRqKEzGOKdUrPdful57EnC8xfxBn-3jTPY9b91Yjfe4Fsn1mHXf-nWd3iDf-Xx +Hez6n31tNe4EUYjHCrjUkAWde30DPhzO8KgQcMcZTyKR8ASwrjZ7vNVxfondVLPdful57EnC8xfx +Bn-3jTPY9b91Yjfe4Fsn1mHXf-nWd3iDf-XxHez6n31tNer4yvEliMFjH9vnqaeRoZhRvmT-SYIU +VsHVTCLVXAqZA6GNcplJB3mPRaG2jlGJd1bNdvul57EnCc9fxBv83TfOYNf-1ondeINvnViHXf-l +W9-hDf7Vx3ew63-2tdW4E0RheVYAE_GmtiwYPdw34MOxDI8HAXec9CQSqaSSIAVYa8iiMeTPHm91 +3FvxWuysZvvK1evYk2zetJ4xBhOBV6juwXPY9XsfvCzmEr73sphmjx-Grr916JiYCHzvZfGT8vAF +7Pr577vEROB7L0uNXxRfghICmtiex36BOhsZolXolfQoaFNiOdzOenTl6vXNm9Yrp7NOZTqBhsag +ULPHD7cOHWsdOgZczlyar_ThC-z3Xfz3XcDlzGXZwQtxphLKyYzK7z0WhZo7iQZfCzXbV65ex55k +86b1AGgN3MSQ98HLYi7wYMRlSXRi1986dCxD6kGXxdCJXT--fVeG1CJnvi2oKMzPB2Af3NSWBZ2L +_QZ8OJDhkSDgjvNem65cva6hGZCGNwO1dNap5OELwGWZ1LprCFKAtV3Z462OA9tX9MkaqdnWAM3N +m9ZfuXp986b1gGkwqtQ9eA67fu_Dl8Vc4OVJxbeFoYldP1AYic7Jwxew65dBDFwWdFaC6ZH4EmTg +sa-Tq1rARoZu2rzCPpMEKaxI3TKpGLKByyXprE1IdNYm1DYwhDMQ_snWW0AZ77EorKTDKPe1U7N9 +5ep17Ek2b1rPGIOJwCtU9_A5DTiWJxJQ7h48Vx7Qs8cPY9ffOnRMnqX30lh0Lp7Q33eJicD3XpZS +FA5iAphKsmB0ed_AD0szPAYE3KmV16bNm9Yrp7NOeR_8DJEBtxVqHTomovfSCvHfd8k4zlyqlSA1 +GG1ZNAa12eOtjqWnTryJmqrZvnL1ugY04w3ePXhOA5rxBp89flgDnRFP0MMXNKAZd3wJXwAEAUpt +nsc_3gM2MqRD8sp7i1iXOmcSqeaSgYBKsL6_l2-KvceiUGe3UetrrWb7ytXr2JNs3rQeb-DuwXPY +9XsfvIw3_Ozxw9j1tw4dQ6Tbwxew6_e-78KdIAoBCJVkAWg834APizKUDgF3autJJFISpA5nj7c6 +1r0MEmOMNdtXrl7HnmTzpvV4g3cPnsOu3-vgZbzBZ48fxq6-degY4ml6_AJ2-fz3XbgTRCFjjMe_ +IIMGr-OUNzLUU_KR_kkSpLA6lDXvEhLJZCkn2BAvWCRzCc970IL0d6GxPKmPmu0rV69jT7J503q8 +wbsHz2HX733wMt7gs8cPY9ffOnQMkWsPX8Cun-__C3eCKARQoGbBZf2_AR9WZAjywpNIpCRIHc4e +b3XMX31SHzXb3ft3sSfxHnlMnsV75DGFg3e--xS9-mdeFHOBlycV3xasv-Mtev07N4iJwPdeFq-- +6F70_o_cEhOBF1PLl8UVhYwxHvsCFAq9Cae8kYHguB61e8grRbk365H3yGMQ9vayTCfwnnkRwo7i +O996Ozd4OzcAlzOXFtR-dK935JR35JToB8obQxmCDScbRIXegxaE14UKe9IINdvd_3c10Hn5pN2- +qxbTGW6i1L9E4e73n4IXRgk60evfuSFD6kGXxdCJXv_RUxlS9-pSikKAhvIsGF2tb8CHsRmCfF_v +U8rpXKG633_qoTcorlnCcbfzbXk6ay3_6F5lRO5REqQOZ4_3Oqa9TqiMNELNdvf_XexJAMpIdNZA +Se_ZF8Vcwg_6UwCa6PXv3JChc19kF_Ymev0SlGVGK_N1FDLGeOwLaBT2PPYNPOWNDBBHeuyOIVaN +8shMqoMyINbQFRTXj98GxiLYSLJBGOI9aEGqulBJTxpDzXb3-l3sSbxHHmOMde-fBaP46H7-KXr9 +z7woT_Q986Lsy6MTvf6dG_RZgNRwR6a2sej0jpwSE4GX5xV3iisKASCFs6Czmb4BH0ZlCPIjvTZh +0Flr-c_8CJHxdhS-c4MI_Y5N63-klMxiuFRA5yWWOZw93uqY8AqhGtIYara79_9ajebu959qQDNi +-Z1vNdAZsf6jezWgGXeCKGSM8dgXAMnpbTnljQwcM6DU0yXkVaOcP5NIpCEEG042CMO9By2oWBdS +4kkF1Wx379-FnsR75DG8wbvff4pe-zMvItbf_Ra9-p0bEOs-uhe9-iOncCeIQoDJWFkw2nzfgI-K +MwT5sTyJREqCNE8GOuf-vSHZ461OtStLKqhmu3v-LvYk3iOP4Q3e-f5T9PqfeRGx-s636PXv3IBY +-9G96PUfOYU7QRQyxgR8_3oe_6Pr-OFs96_vGHjKGzIodXYGsYKUC2cSiZRBSq9PglQ2vd774ey- +-vGR98PZIb_pynvQgkZ2IbWepEDNdvf_XexJvEcewxu8_-2n6PU-8yJi-Z1v0evfuQGx-qN70es- +cgp3gigEsPTNAtPDPQCaMfbv--F696_vjPVfbN_Aj0oyBPmCPgpR6Ukima4oBJaVzEL-_sdH3g9n +lYypKnu81dG5pJkVIZVVs01rQKqheKsjYMJjX-bjDuX9cPZf--hIXP77f7ze-esrBnUh3uroydom +oqw-y__XfE28gSEXltOvenK6e-9u9-7dVU9Or3pyuvA4KF7bZBRuhykbmrwWr7n958-Fmg2gGRht +VCNk2iYzsP_TL7V1jDyfGjIB2rRweM093uowZCVBij0FSad47NMi1FDiIPPYN8TXYCsuMRspow5O +WX_W3yn5mngDQy7MZY86AYUbUZfDQL7Ha27-_XNNGiRDnaBWS_nsFjHyfGrIBGiToybvwuOtDkNQ +EqQYw5L0iMc_LUJtJQ4vj31zfF335BKzFWblA1LWn_X3SL4m3vCQi6yLVz4ohb1RxwNAfonROtt- +-lzzxsmUD0rLapc39mRqywRok6Pm78jjrQ5TpCRIVQ1F0iAe_7QINRecWR774vAa4unVLGmJ2SWz +kkEo68ny_yJfT8_i0NiQy6u7VzIQhV1BB6DmHrX9l8-URIVnqroxLaXRr9n4M6khE6BNDnpHfb3H +Wx1WVEmQFv4vSY947NMikOCo8tgXZ9YoT7t0sJaYPW4u-EfK2jIE_Tp7OKrmh1wq_WVf_M8UtNHJ +G_5R23-5TE10pGcF-kzLZ_7rNP5MasgEaFuC3tdI7-FWh42jJEjH_j0JWzz2aRFI8gnlsS-OqYGe +3tE4WmJ2njzWjylryxDka_7hhBoecp3kR-ux-kBBG528gR61-avN1FDHa7o5-0BLZoK36BxqyARo +2Zsc9I4Ke4_3OmyUkiAd_RsSqnjs0yKQMqeSx744m2Z62reltcTsQXnkDyijZgjy5IWHU2l4yHWS +L_5H-oiCNjp5Q7zy9o_XqaGqacZDfkTLVM0rseocasgEaNnbEvS_lHiPtzqsn5Ig7XufhCce_7QI +pN6TyGNfnEfDPb0v1Vpitpz73qSMmiHIkxceTqJFIddMvoxfzn1-REEbmny1Xm37x8vUUBX6Pvsh +8yNaJm3elhOoLROUM4C2Iuh9KfGDKOHxVoctKQlS4UkY4rFPi0AaInEGeeyb7OlN6ZLEckFuynh5 +SLckX2dvUcgFky-jR2e7doalQRuR-CCvtv3rydRQC-ux9wktGZK37tRpywTlDKCtC3p3BXwxkngs +ChlJqXjs0yKQhisJUrFbzPe0paujyRKtKZfPBTok_bp5S0Munvy4vni2d8fQJiZvkVdwVrVnaqiF +vbL9Q0tZ8jVQHpQJyhlAWxf07gp4tYTxWBQy0vjisU_LQBqpJEjFhrHF01szCTRLtKacPyvskORd +9ZaGXDz5PB4327uTaOOSN9PrOLdomZrrWB59X9ES53wNlAdlgrLsbQx6dwW8HvJ4LAoZqZ947NMi +kHIqCVKxbSzytMmNx9ASrSn3Zg0dkrzt3oGQH4T8IK8ziz3G3NhhtFnJ6-f6z63CTM11LK9tX2Uv +aeltP2k6uzr5ku3fnKD3mNPrJFJvDR6LQlZj8div8_OTCigJUtg5YOzy9PoM31riHS16QfG6ZW1d +kbwznkWh1SE-AvlBXmceufeY7XuONit5PV7-6VWeqdEO8Zr3Vd6f1ec1uHHG9HR18iXbvzlB73Gk +N7kZeCwKmevise-8M5KUKwlS2DxgrPO07U3eWuLtjPCC7q7mSjokeas9i0KrQ34E8oO8zlx4TzLb +9yJtUPJqvf7TqzxTox3iNe_rsn937zW4ccb0dHXyBdq-_UHvtK_3sRl4LAqZ-eKx78BTkCpREqSw +hcDY6Gn-G7u1xKsp6AX1bc_VdEjytnsWhW6E-CzkZa8zq9_ftCnJ19PrP73KMzXaIV7zvsIa1rql +d_Bc6e-q5AcdKquD3mNf71Iz8FgUMkvEY9_WUklmKglSHvtJkIodZaOn92jmvkLxohuYnCvpiuRd +8iwK3Qj5WcjLXmfWt29pU5J32_s-vaiZmm7Ga95Xuqczc_ndO1d6ujr5QYfK6qD32Nc73wx4q_Ox +KGQmice_UfWQbFQSpDz2kyAVm8peTyfCtH2l1YsuYUKupCuSd8mzKHQv5OcirzNXv59p85F3xldy +hpEyNd3eplvJXqp4S1e_9JQLdHXygw6VM0HvtMLGYM46eCwKmV7x2Nc8I8ltJUEqtpbtnt6mITtK +vIuKvegeOnMlXZG8e96xkB_KvM5s7D5ntPnIW_crOcMacs2bbrV7ydCtjrr0Tp4inV2d-KBD5UzQ +O62wMZi-Ph6LQoYgHvsYw5LqrCRIxe5ywNMZMWFHibdgqBddRVWupBOSd9s7FvJDkdeZrdv-jDYf +eWN9JWdYQ6550612L1l2BJQsN_WSXZ38oEPlZNT2nVbVGOxdN49FISsqHvuF-0siDVISpGKDueTp +zVa4o8T6W_ZFtxk3V9IJybvtHQ75Aevjq8rOnAtGm4y8Cb7a84yUa950K9lLjh0NNtZyUy7Z1ckP +OlRORm3faVWNwb31bCRBCsEY6-WMMR77jDFhKBfOEOSFF5IvHfD0fqt9C3INtnsmutCgXEknJO_2 +dzjkB6yPryo7f14YbTLyOn2151lDrmHTrWQv1eTI-D_o_YTEtLDizgAAABB0RVh0TG9kZVBORwAy +MDExMDIyMeNZtsEAAAAASUVORK5CYII= +:: main.lua +--[[pod_format="raw",created="2024-03-31 02:16:28",modified="2024-03-31 14:46:07",revision=34]] + +function _init() + window(64*4,16*8) +end + +function _draw() + for j=0,4 do + for i=0,8 do + rectfill( + j*64, i*16, + j*64+32,(i+1)*16, + i+8*j) + print(i+8*j, j*64+34, i*16) + end + end +end +:: map/ +:: map/0.map +b64$LS1bW3BvZCxjcmVhdGVkPSIyMDI0LTAzLTMxIDAyOjE2OjI4Iixtb2RpZmllZD0iMjAyNC0w +My0zMSAxNDo0NjowNyIscmV2aXNpb249MThdXWx6NABoAAAAWBAAAPAIe3tibXA9dXNlcmRhdGEo +ImkxNiIsMzIDAC8iMAEA--------------------_-EIIiksaGlkZGVuPWZhbHNlLHBhbl94PTAI +ANJ5PTAsdGlsZV9oPTE2CgAQdwoAgHpvb209MX19 +:: map/.info.pod +b64$LS1bW3BvZCxjcmVhdGVkPSIyMDI0LTAzLTMxIDAyOjE2OjI3IixzdG9yZWQ9IjIwMjQtMDMt +MzEgMDI6MTY6MjciXV1sejQABAAAAAMAAAAwbmls +:: sfx/ +:: sfx/0.sfx +b64$LS1bW3BvZCxjcmVhdGVkPSIyMDI0LTAzLTMxIDAyOjE2OjI4Iixtb2RpZmllZD0iMjAyNC0w +My0zMSAxNDo0NjowNyIscmV2aXNpb249MTddXWx6NAAQAQAAUQcAAPAncHh1AAMoAAADAAQPQBAC +DgABoAEgAqAOAA8QAA3wygECAwQFBgcAD-_QCAkKCw8MDw0PDg8PEADwAA0PEQ8SDxMPFA8VDxYP +FxMA8QEPGA8ZDxoPGw8cDx0PHg8fFADxACAPIQ8iDyMPJA8lDyYPJxQA8QAoDykPKg8rDywPLQ8u +Dy8UAPEAMA8xDzIPMw80DzUPNg83FAD-BTgPOQ86DzsPPA89Dz4PPwAP--D-AQDr-ydaARAGDyAQ +ASABIAHwAAIQAgwQASAPISABMA9A8MMPKA--8MYP_AoP-w_AD-cPDQHwCQEQBgwwAP85H-8BANy- +_A9AAA1A--_w8HAKAP--ZB--AQCXUP----8f +:: sfx/.info.pod +b64$LS1bW3BvZCxjcmVhdGVkPSIyMDI0LTAzLTMxIDAyOjE2OjI3IixzdG9yZWQ9IjIwMjQtMDMt +MzEgMDI6MTY6MjciXV1sejQABAAAAAMAAAAwbmls +:: .info.pod +b64$LS1bW3BvZCxub3Rlcz0ianVzdCBsaXN0cyBvdXQgdGhlIGNvbG9ycyBcbndpdGggdGhlaXIg +bnVtYmVycyEiLGF1dGhvcj0ic2hvb2ZsZSIsaWNvbj11c2VyZGF0YSgidTgiLDE2LDE2LCIwMDAw +MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw +MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxMDEwMTAxMDAwMTAwMDAwMDAw +MDAwMDAwMDAwMDAwMDEwMTAxMDEwMDAxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw +MDAwMDAwMDAwMDAwMDAwMDAwMDBkMGQwZDBkMDAwZDBkMDAwMDAwMDAwMDAwMDAwMDAwMGQwZDBk +MGQwMDAwMGQwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw +MDA2MDYwNjA2MDAwNjAwMDAwMDAwMDAwMDAwMDAwMDAwMDYwNjA2MDYwMDA2MDAwMDAwMDAwMDAw +MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA3MDcwNzA3MDAwNzAwMDcw +MDAwMDAwMDAwMDAwMDAwMDcwNzA3MDcwMDA3MDAwNzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw +MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCIpLHJ1 +bnRpbWU9NCxzdG9yZWQ9IjIwMjQtMDMtMzEgMTQ6NDY6MDciLHRpdGxlPSJMaXN0IENvbG9ycyIs +dmVyc2lvbj0iMSIsd29ya3NwYWNlcz17e2xvY2F0aW9uPSJtYWluLmx1YSMzIix3b3Jrc3BhY2Vf +aW5kZXg9MX0se2xvY2F0aW9uPSJnZngvMC5nZngiLHdvcmtzcGFjZV9pbmRleD0yfSx7bG9jYXRp +b249Im1hcC8wLm1hcCIsd29ya3NwYWNlX2luZGV4PTN9LHtsb2NhdGlvbj0ic2Z4LzAuc2Z4Iix3 +b3Jrc3BhY2VfaW5kZXg9NH19XV1sejQABAAAAAMAAAAwbmls +:: [eoc] diff --git a/listcolors.p64.png b/listcolors.p64.png new file mode 100644 index 0000000..f677b4a Binary files /dev/null and b/listcolors.p64.png differ