commit c2b07b8

0uppy  ·  2026-07-20 20:10:02 +0000 UTC
parent c2b07b8
cotton v0.1 - it lives :D
14 files changed,  +872, -0
+6, -0
1@@ -0,0 +1,6 @@
2+build/
3+.cache/
4+cotton
5+*.o
6+*.a
7+tools/eikimaker
+59, -0
 1@@ -0,0 +1,59 @@
 2+# cotton
 3+
 4+![cotton](cotton.png)
 5+
 6+cotton is a tiny virtual computer that lives in a window. it originally had a chip-8 emulator as a base but i ended up rewriting the vast, VAST majority of it to my liking. cotton is heavily inspired by [uxn](https://100r.co/site/uxn.html) and a little bit by [pico-8](https://www.lexaloffle.com/pico-8.php) (go check both projects out, they're awesome!!).
 7+
 8+on cotton you write programs in `.cot` files using the cot programming language — a simple, straightforward, lua-esque language (that is being made alongside cotton's development) made FOR cotton.
 9+
10+## building cotton,
11+
12+```
13+meson setup build
14+ninja -C build
15+```
16+
17+(make sure you also have sdl installed or else windows wont open wawawaw!!)
18+
19+## running cotton,
20+
21+```
22+cotton <file.cot>
23+```
24+
25+## the cot language
26+
27+as i said on at the top of this file, cot is being developed alongside cotton and is meant to be small and straightforward, as of writting this (v0.1's release) these are the current features it has:
28+
29+```
30+print "blah blah blah"   # prints text to the screen
31+wait 2                   # waits 2 seconds
32+kill                     # exits cotton
33+
34+comments written as ' # '
35+```
36+
37+i plan to focus more on cot itself for the next update so expect this list to grow some more by then :P
38+
39+## tools
40+
41+this is more so a thing for me, but, i figured i'd explain it:
42+
43+you may notice there is a tools/ folder, in there you will find "eikimaker", a small program i made to help design the eiki font, i might expand on it at some point but for now it works just fine ^^
44+
45+## to-do
46+
47+this list may and will be updated over time, but, as of now this is what i have in mind for cotton/cot
48+
49+- [] `clear`, `color`, `input` fully implemented (for v0.2)
50+- [] variables (`set` / `get`) (perhaps for v0.2..?)
51+- [] `if` / `loop` (same as above)
52+- [] sound
53+- [] images (im not sure yet, i want to think of a unique way to implement it.. or not..)
54+- [] more eiki font characters (i.e. lowercase, punctuation) & potential remake of the font overall
55+- [] making a mascot (i already have one but im thinking of how to implement it as a feature or so x3)
56+- [] a "main" .cot program actually worth showing off
57+
58+## credits
59+
60+i'd like to thank [this guide](https://austinmorlan.com/posts/chip8_emulator/) for helping me figure out the initial base for cotton, even if 90% of it is gone by now, it helped me learn alot of stuff that i am now applying for cotton, awesome stuff ^^
+0, -0
+5, -0
1@@ -0,0 +1,5 @@
2+print "HELLO FROM COT :D"
3+wait 1
4+print "THIS IS A SHOWCASE COT FILE"
5+wait 1
6+print "WORDS WORDS WORDS"
+14, -0
 1@@ -0,0 +1,14 @@
 2+project('cotton', 'c',
 3+  version : '0.1',
 4+  default_options : ['c_std=c99', 'warning_level=2'])
 5+
 6+sdl2 = dependency('sdl2')
 7+
 8+src_files = [
 9+  'src/main.c',
10+  'src/cotton.c',
11+  'src/cottonwindow.c',
12+  'src/interpreter.c',
13+]
14+
15+executable('cotton', src_files, dependencies : sdl2)
+12, -0
 1@@ -0,0 +1,12 @@
 2+#include "cotton.h"
 3+#include <string.h>
 4+#include <time.h>
 5+#include <stdlib.h>
 6+
 7+void cotton_init(Cotton *c) 
 8+{
 9+    memset(c, 0, sizeof(Cotton));
10+
11+    srand((unsigned int)time(NULL));
12+        
13+}
+25, -0
 1@@ -0,0 +1,25 @@
 2+#ifndef COTTON_H
 3+#define COTTON_H
 4+
 5+#include <stdint.h>
 6+
 7+#define MEMORY_SIZE  (1024 * 1024)
 8+#define VIDEO_WIDTH  200
 9+#define VIDEO_HEIGHT 125
10+
11+typedef struct
12+{
13+    uint8_t  memory[MEMORY_SIZE];
14+    uint32_t video[VIDEO_WIDTH * VIDEO_HEIGHT];
15+
16+    // i cant come up with a better name that gets straight to the point than "cursor" so ig it will stay this way for now,,      
17+    int cursor_x;
18+    int cursor_y;
19+
20+    uint32_t ticktock;
21+
22+} Cotton;
23+
24+void cotton_init(Cotton *c);
25+
26+#endif
+81, -0
 1@@ -0,0 +1,81 @@
 2+#include "cottonwindow.h"
 3+#include <stdio.h>
 4+
 5+int cottonwindow_init(CottonWindow *cw, const char *title, int window_w, int window_h, int texture_w, int texture_h)
 6+{
 7+    SDL_Init(SDL_INIT_VIDEO);
 8+
 9+    if (SDL_Init(SDL_INIT_VIDEO) != 0)
10+    {
11+        fprintf(stderr, "cotton couldn't start SDL :( : %s\n", SDL_GetError());
12+        return 0;
13+    }
14+
15+    cw->window = SDL_CreateWindow(title, 0, 0, window_w, window_h, SDL_WINDOW_SHOWN);
16+    if (!cw->window)
17+    {
18+        fprintf(stderr, "cotton couldn't create a window :( : %s\n", SDL_GetError());
19+        return 0;
20+    }
21+
22+    cw->renderer = SDL_CreateRenderer(cw->window, -1, 0);
23+    if (!cw->renderer)
24+    {
25+        fprintf(stderr, "cotton couldn't render this :( : %s\n", SDL_GetError());
26+        return 0;
27+    }
28+
29+    cw->texture = SDL_CreateTexture(cw->renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, texture_w, texture_h);
30+    if (!cw->texture)
31+    {
32+        fprintf(stderr, "cotton couldn't apply textures :( : %s\n", SDL_GetError());
33+        return 0;
34+    }
35+
36+    return 1;
37+}
38+
39+void cottonwindow_update(CottonWindow *cw, const void *buffer, int pitch)
40+{
41+    SDL_UpdateTexture(cw->texture, NULL, buffer, pitch);
42+    SDL_RenderClear(cw->renderer);
43+    SDL_RenderCopy(cw->renderer, cw->texture, NULL, NULL);
44+    SDL_RenderPresent(cw->renderer);
45+}
46+
47+int cottonwindow_process_input(CottonWindow *cw, uint8_t *keys)
48+{
49+    (void)cw;
50+    (void)keys;
51+    int quit = 0;
52+    SDL_Event event;
53+
54+    while (SDL_PollEvent(&event))
55+    {
56+        switch (event.type)
57+        {
58+            case SDL_QUIT:
59+            {
60+                quit = 1;
61+                break;
62+            }
63+
64+            case SDL_KEYDOWN:
65+            {
66+                if (event.key.keysym.sym == SDLK_ESCAPE)
67+                    quit = 1;
68+                break;
69+            }
70+        }
71+    }
72+
73+    return quit;
74+}
75+
76+void cottonwindow_destroy(CottonWindow *cw)
77+{
78+    SDL_DestroyTexture(cw->texture);
79+    SDL_DestroyRenderer(cw->renderer);
80+    SDL_DestroyWindow(cw->window);
81+    SDL_Quit();
82+}
+20, -0
 1@@ -0,0 +1,20 @@
 2+#ifndef COTTONWINDOW_H
 3+#define COTTONWINDOW_H
 4+
 5+#include <SDL2/SDL.h>
 6+#include <stdint.h>
 7+
 8+typedef struct
 9+{
10+    SDL_Window   *window;
11+    SDL_Renderer *renderer;
12+    SDL_Texture  *texture;
13+
14+} CottonWindow;
15+
16+int  cottonwindow_init(CottonWindow *cw, const char *title, int window_w, int window_h, int texture_w, int texture_h);
17+void cottonwindow_update(CottonWindow *cw, const void *buffer, int pitch);
18+int  cottonwindow_process_input(CottonWindow *cw, uint8_t *keys);
19+void cottonwindow_destroy(CottonWindow *cw);
20+
21+#endif
+317, -0
  1@@ -0,0 +1,317 @@
  2+// I might refactor some of these letters and characters at some point but but for now this should be a-okay :D
  3+// Atleast i think these are readable for now so that's good enough x3
  4+
  5+#ifndef EIKI_H
  6+#define EIKI_H
  7+
  8+#include <stdint.h>
  9+
 10+static const uint8_t EIKI_FONT[256][5] = {
 11+
 12+    [' '] = {
 13+        0b00000000,
 14+        0b00000000,
 15+        0b00000000,
 16+        0b00000000,
 17+        0b00000000,
 18+    },
 19+
 20+    ['A'] = {
 21+        0b00001110,
 22+        0b00010001,
 23+        0b00011111,
 24+        0b00010001,
 25+        0b00010001,
 26+    },
 27+
 28+    ['B'] = {
 29+        0b00001111,
 30+        0b00010001,
 31+        0b00001111,
 32+        0b00010001,
 33+        0b00001111,
 34+    },
 35+
 36+    ['C'] = {
 37+        0b00011111,
 38+        0b00000001,
 39+        0b00000001,
 40+        0b00000001,
 41+        0b00011111,
 42+    },
 43+
 44+    ['D'] = {
 45+        0b00001111,
 46+        0b00010001,
 47+        0b00010001,
 48+        0b00010001,
 49+        0b00001111,
 50+    },
 51+
 52+    ['E'] = {
 53+        0b00011111,
 54+        0b00000001,
 55+        0b00011111,
 56+        0b00000001,
 57+        0b00011111,
 58+    },
 59+
 60+    ['F'] = {
 61+        0b00011111,
 62+        0b00000001,
 63+        0b00011111,
 64+        0b00000001,
 65+        0b00000001,
 66+    },
 67+
 68+    ['G'] = {
 69+        0b00011111,
 70+        0b00000001,
 71+        0b00011001,
 72+        0b00010001,
 73+        0b00011111,
 74+    },
 75+
 76+    ['H'] = {
 77+        0b00010001,
 78+        0b00010001,
 79+        0b00011111,
 80+        0b00010001,
 81+        0b00010001,
 82+    },
 83+
 84+    ['I'] = {
 85+        0b00011111,
 86+        0b00000100,
 87+        0b00000100,
 88+        0b00000100,
 89+        0b00011111,
 90+    },
 91+
 92+    ['J'] = {
 93+        0b00011100,
 94+        0b00010000,
 95+        0b00010000,
 96+        0b00010011,
 97+        0b00011110,
 98+    },
 99+
100+    ['K'] = {
101+        0b00010001,
102+        0b00011001,
103+        0b00000111,
104+        0b00010001,
105+        0b00010001,
106+    },
107+
108+    ['L'] = {
109+        0b00000001,
110+        0b00000001,
111+        0b00000001,
112+        0b00010001,
113+        0b00011111,
114+    },
115+
116+    ['M'] = {
117+        0b00011011,
118+        0b00011111,
119+        0b00010101,
120+        0b00010001,
121+        0b00010001,
122+    },
123+
124+    ['N'] = {
125+        0b00010001,
126+        0b00010011,
127+        0b00010101,
128+        0b00011001,
129+        0b00010001,
130+    },
131+
132+    ['O'] = {
133+        0b00011111,
134+        0b00010001,
135+        0b00010001,
136+        0b00010001,
137+        0b00011111,
138+    },
139+
140+    ['P'] = {
141+        0b00011111,
142+        0b00010001,
143+        0b00011111,
144+        0b00000001,
145+        0b00000001,
146+    },
147+
148+    ['Q'] = {
149+        0b00011111,
150+        0b00010001,
151+        0b00010001,
152+        0b00011001,
153+        0b00011111,
154+    },
155+
156+    ['R'] = {
157+        0b00011111,
158+        0b00010001,
159+        0b00011111,
160+        0b00001001,
161+        0b00010001,
162+    },
163+
164+    ['S'] = {
165+        0b00011111,
166+        0b00000001,
167+        0b00011111,
168+        0b00010000,
169+        0b00011111,
170+    },
171+
172+    ['T'] = {
173+        0b00011111,
174+        0b00000100,
175+        0b00000100,
176+        0b00000100,
177+        0b00000100,
178+    },
179+
180+    ['U'] = {
181+        0b00010001,
182+        0b00010001,
183+        0b00010001,
184+        0b00010001,
185+        0b00011111,
186+    },
187+
188+    ['V'] = {
189+        0b00010001,
190+        0b00010001,
191+        0b00011011,
192+        0b00001010,
193+        0b00000100,
194+    },
195+
196+    ['W'] = {
197+        0b00010001,
198+        0b00010001,
199+        0b00010101,
200+        0b00011011,
201+        0b00010001,
202+    },
203+
204+    ['X'] = {
205+        0b00010001,
206+        0b00001010,
207+        0b00000100,
208+        0b00001010,
209+        0b00010001,
210+    },
211+
212+    ['Y'] = {
213+        0b00010001,
214+        0b00010001,
215+        0b00001010,
216+        0b00000100,
217+        0b00000100,
218+    },
219+
220+    ['Z'] = {
221+        0b00011111,
222+        0b00010001,
223+        0b00000100,
224+        0b00010010,
225+        0b00011111,
226+    },
227+
228+    ['0'] = {
229+        0b00001110,
230+        0b00010001,
231+        0b00010001,
232+        0b00010001,
233+        0b00001110,
234+    },
235+
236+    ['1'] = {
237+        0b00000100,
238+        0b00001100,
239+        0b00000100,
240+        0b00000100,
241+        0b00001110,
242+    },
243+
244+    ['2'] = {
245+        0b00001110,
246+        0b00010001,
247+        0b00000010,
248+        0b00000100,
249+        0b00011111,
250+    },
251+
252+    ['3'] = {
253+        0b00011111,
254+        0b00010001,
255+        0b00011100,
256+        0b00010001,
257+        0b00011111,
258+    },
259+
260+    ['4'] = {
261+        0b00010010,
262+        0b00010010,
263+        0b00011111,
264+        0b00000010,
265+        0b00000010,
266+    },
267+
268+    ['5'] = {
269+        0b00011111,
270+        0b00010000,
271+        0b00011110,
272+        0b00000001,
273+        0b00011110,
274+    },
275+
276+    ['6'] = {
277+        0b00001110,
278+        0b00010000,
279+        0b00011110,
280+        0b00010001,
281+        0b00001110,
282+    },
283+
284+    ['7'] = {
285+        0b00011111,
286+        0b00000001,
287+        0b00000010,
288+        0b00000100,
289+        0b00000100,
290+    },
291+
292+    ['8'] = {
293+        0b00001110,
294+        0b00010001,
295+        0b00001110,
296+        0b00010001,
297+        0b00001110,
298+    },
299+
300+    ['9'] = {
301+        0b00001110,
302+        0b00010001,
303+        0b00001111,
304+        0b00000001,
305+        0b00001110,
306+    },
307+
308+    [':'] = {
309+        0b00000000,
310+        0b00000100,
311+        0b00000000,
312+        0b00000100,
313+        0b00000000,
314+    },
315+
316+};
317+
318+#endif
+236, -0
  1@@ -0,0 +1,236 @@
  2+// i got to eventually clean up this file a bit i feel like its very janky but i suppose i can worry about that later
  3+
  4+#include <stdio.h>
  5+#include <string.h>
  6+#include <stdlib.h>
  7+#include <unistd.h>
  8+#include <SDL2/SDL.h>
  9+#include "interpreter.h"
 10+#include "cottonwindow.h"
 11+#include "eiki.h"
 12+
 13+// maximum length of a .cot file line
 14+#define MAX_LINE 256
 15+
 16+
 17+// da string stuff
 18+
 19+static void strip_newline(char *s)
 20+{
 21+    s[strcspn(s, "\r\n")] = 0;
 22+}
 23+
 24+static char *get_arg(char *line)
 25+{
 26+    char *space = strchr(line, ' ');
 27+
 28+    if (space != NULL)
 29+    {
 30+        return space + 1;
 31+    }
 32+
 33+    else
 34+    {
 35+        return NULL;
 36+    }
 37+}
 38+
 39+static char *strip_quotes(char *s)
 40+{
 41+    if (s[0] == '"')
 42+    {
 43+        char *end = strrchr(s, '"');
 44+
 45+        if (end == NULL)
 46+        {
 47+            fprintf(stderr, "looks like you forgot a quote at the end xP\n");
 48+            return s;
 49+        }
 50+
 51+        *end = '\0';
 52+        return s + 1;
 53+    }
 54+
 55+    return s;
 56+}
 57+
 58+
 59+// da graphics stuff
 60+
 61+static void draw_pixel(Cotton *cotton, int x, int y, uint32_t color)
 62+{
 63+    cotton->video[y * VIDEO_WIDTH + x] = color;
 64+}
 65+
 66+static void draw_char(Cotton *cotton, char c, int x, int y)
 67+{
 68+    for (int row = 0; row < 5; row++)
 69+    {
 70+        uint8_t bits = EIKI_FONT[(uint8_t)c][row];
 71+
 72+    for (int col = 0; col < 5; col++)
 73+    {
 74+
 75+        if (bits & (1 << col)) 
 76+        {
 77+            draw_pixel(cotton, x + col, y + row, 0xffffffff);
 78+        }
 79+    }
 80+
 81+    }
 82+}
 83+
 84+
 85+// da commands
 86+
 87+static void cmd_print(Cotton *cotton, CottonWindow *cw, char *arg)
 88+{
 89+    (void)cw;
 90+    
 91+    if (!arg) 
 92+        return;
 93+
 94+    char *text = strip_quotes(arg);
 95+
 96+    printf("%s\n", text);
 97+
 98+    for (int i = 0; text[i] != '\0'; i++)
 99+    {
100+        // when the limit of a line is reached we go down one line,, pmo when it just gluedtogehterlikethisacrosslinesaaaaaa
101+        if (text[i] == '\n')
102+        {
103+            cotton->cursor_x = 0;
104+            cotton->cursor_y += 6; 
105+            continue;
106+        }
107+
108+        draw_char(cotton, text[i], cotton->cursor_x, cotton->cursor_y);
109+        cotton->cursor_x += 6;
110+        
111+        // those who wrap
112+        if (cotton->cursor_x + 6 >= VIDEO_WIDTH)
113+        {
114+            cotton->cursor_x = 0;
115+            cotton->cursor_y += 6;
116+        }
117+    }
118+
119+    cotton->cursor_x = 0;
120+    cotton->cursor_y += 6;
121+
122+}
123+
124+static void cmd_wait(Cotton *cotton, char *arg)
125+{
126+    if (!arg)
127+        return;
128+
129+    int seconds = atoi(arg);
130+
131+    cotton->ticktock = SDL_GetTicks() + (seconds * 1000);
132+}
133+
134+static void cmd_kill(void)
135+{
136+    printf("[cotton stopped]\n");
137+    exit(0);
138+}
139+
140+static void cmd_clear(CottonWindow *cw)
141+{
142+    (void)cw;
143+
144+    // will work on this for v0.2
145+}
146+
147+static void cmd_color(CottonWindow *cw, char *arg)
148+{
149+    (void)cw;
150+    (void)arg;
151+
152+    // will work on this for v0.2
153+}
154+
155+static void cmd_input(CottonWindow *cw, char *arg)
156+{
157+    (void)cw;
158+    (void)arg;
159+
160+    // will work on this for v0.2 or whenever it is that i add variables
161+}
162+
163+static void cmd_unknown(const char *cmd)
164+{
165+    fprintf(stderr, "cotton doesn't know what \"%s\" means, care to type that out again? :<\n", cmd);
166+}
167+
168+
169+// da interpreter loop
170+
171+void cotton_interpret(Cotton *cotton, CottonWindow *cw, FILE *file)
172+{
173+    char line[MAX_LINE];
174+
175+    // this reads the file one line at a time until we get to da end of da file
176+    if (!fgets(line, sizeof(line), file))
177+        return;
178+
179+    strip_newline(line);
180+
181+    // cot shall use # comments like C because C is cool and i love C so bwaaa
182+    if (line[0] == '\0' || line[0] == '#')
183+        return;
184+
185+
186+    char line_copy[MAX_LINE];
187+
188+    strncpy(line_copy, line, MAX_LINE - 1);
189+    line_copy[MAX_LINE - 1] = '\0';
190+
191+
192+    char *cmd = strtok(line_copy, " ");
193+
194+    if (!cmd)
195+        return;
196+
197+
198+    // RELEASE THE KRAKE- I MEAN, RELEASE THE GREAT WALL OF COMMANDS !!! 
199+    // could i format this better? maybe,, but but i'd say this is readable and i think readability is gud so i will keep it nice and green,,, green!! :D
200+    char *arg = get_arg(line);
201+
202+
203+    if (strcmp(cmd, "print") == 0)
204+    {
205+        cmd_print(cotton, cw, arg);
206+    }
207+
208+    else if (strcmp(cmd, "clear") == 0)
209+    {
210+        cmd_clear(cw);
211+    }
212+
213+    else if (strcmp(cmd, "color") == 0)
214+    {
215+        cmd_color(cw, arg);
216+    }
217+
218+    else if (strcmp(cmd, "wait") == 0)
219+    {
220+        cmd_wait(cotton, arg);
221+    }
222+
223+    else if (strcmp(cmd, "input") == 0)
224+    {
225+        cmd_input(cw, arg);
226+    }
227+
228+    else if (strcmp(cmd, "kill") == 0)
229+    {
230+        cmd_kill();
231+    }
232+
233+    else
234+    {
235+        cmd_unknown(cmd);
236+    }
237+}
+10, -0
 1@@ -0,0 +1,10 @@
 2+#ifndef INTERPRETER_H
 3+#define INTERPRETER_H
 4+
 5+#include "cotton.h"
 6+#include "cottonwindow.h"
 7+#include <stdio.h>
 8+
 9+void cotton_interpret(Cotton *cotton, CottonWindow *cw, FILE *file);
10+
11+#endif
+47, -0
 1@@ -0,0 +1,47 @@
 2+#include <stdio.h>
 3+#include "cotton.h"
 4+#include "cottonwindow.h"
 5+#include "interpreter.h"
 6+
 7+int main(int argc, char **argv)
 8+{
 9+    if (argc != 2)
10+    {
11+        fprintf(stderr, "usage: cotton <file.cot>\n");
12+        return 1;
13+    }
14+
15+    CottonWindow cw;
16+
17+    if (!cottonwindow_init(&cw, "cotton", VIDEO_WIDTH * 4, VIDEO_HEIGHT * 4, VIDEO_WIDTH, VIDEO_HEIGHT))
18+        return 1;
19+
20+    Cotton cotton;
21+    cotton_init(&cotton);
22+
23+    FILE *file = fopen(argv[1], "r");
24+    if (!file)
25+    {
26+        fprintf(stderr, "cotton couldn't open \"%s\" :(\n", argv[1]);
27+        return 1;
28+    }
29+
30+    int pitch = sizeof(cotton.video[0]) * VIDEO_WIDTH;
31+    int quit = 0;
32+
33+    while (!quit)
34+    {
35+        quit = cottonwindow_process_input(&cw, NULL);
36+
37+        if (SDL_GetTicks() >= cotton.ticktock)
38+        {
39+            cotton_interpret(&cotton, &cw, file);
40+        }
41+
42+        cottonwindow_update(&cw, cotton.video, pitch);
43+    }
44+
45+    fclose(file);
46+    cottonwindow_destroy(&cw);
47+    return 0;
48+}
+40, -0
 1@@ -0,0 +1,40 @@
 2+// i would have made this as a shell script but im more familiar with Go anyway so blehh
 3+package main
 4+
 5+import (
 6+	"fmt"
 7+)
 8+
 9+func main() {
10+
11+	fmt.Print("da character / letter : ")
12+
13+	var ch string
14+	fmt.Scanln(&ch)
15+
16+	fmt.Println("type a # for a pixel and a . for an empty spot")
17+
18+	rows := make([]string, 5)
19+
20+	for i := 0; i < 5; i++ {
21+		fmt.Printf("%d: ", i)
22+		fmt.Scanln(&rows[i])
23+	}
24+
25+	fmt.Println()
26+	fmt.Printf("['%s'] = {\n", ch)
27+
28+	for _, row := range rows {
29+		var value uint8
30+
31+		for i, pixel := range row {
32+			if pixel == '#' {
33+				value |= 1 << i
34+			}
35+		}
36+
37+		fmt.Printf("    0b%08b,\n", value)
38+	}
39+
40+	fmt.Println("},")
41+}