diff --git a/Makefile b/Makefile index a9671f3..7f238b7 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # Makefile for the nibbles lab. # ---> Compile with gamke on BSD systems! <--- -all: nibbles_asm nibbles_asm_start +all: nibbles_c nibbles_asm nibbles_asm_start # Rule for compiling C source .c.o: @@ -25,7 +25,10 @@ nibbles_asm: main.o nibbles.o helpers.o nibbles_asm_start: start.o nibbles.o helpers.o gcc -m32 -lcurses -lc -nostdlib $^ -o $@ +# Documentation +docs: cnibbles.c nibbles.S start.S + docco --languages=docco-languages.json $^ + clean: - rm -f *~ rm -f *.o rm -f nibbles_c nibbles_asm nibbles_asm_start diff --git a/cnibbles.c b/cnibbles.c index d336e46..ae0b5ff 100644 --- a/cnibbles.c +++ b/cnibbles.c @@ -22,6 +22,8 @@ void spawnApple(); void tick(); void draw(); +// start_game +// ========== void start_game(int len, int n_apples) { if (startLength == 0) @@ -36,8 +38,6 @@ void start_game(int len, int n_apples) nib_init(); - //printf("Started with worm length %i and %i apples!\n", snakeLength, numApples); - // Initialize the snake array // Set every cell to a time value greater than the snake length for (unsigned int i = 0; i < WIDTH*HEIGHT; ++i) { @@ -69,6 +69,8 @@ void start_game(int len, int n_apples) } } +// spawnApple +// ========== void spawnApple() { unsigned int x = rand() % WIDTH; @@ -77,26 +79,30 @@ void spawnApple() x = rand() % WIDTH; y = rand() % HEIGHT; } - //printf("Placing apple at (%i,%i)\n", x, y); snake[x + y*WIDTH] = -1; } +// tick +// ==== void tick() { currentTick++; // Increment cell times + // -------------------- for (unsigned int i = 0; i < WIDTH*HEIGHT; ++i) { int val = snake[i]; if (val < 0) { // Apple lifetime - //snake[i]--; + /* snake[i]--; */ } else if (val >= 0 && val <= snakeLength) { // Other cells snake[i]++; } } + // Input + // ----- int key = nib_poll_kbd(); if (key == 'w' && snakeDirY != 1) { snakeDirX = 0; @@ -116,8 +122,12 @@ void tick() } // Move snake + // ---------- snakeX = (snakeX + snakeDirX + WIDTH) % WIDTH; snakeY = (snakeY + snakeDirY + HEIGHT) % HEIGHT; + + // Collision + // --------- // On collision with self int val = snake[snakeX + snakeY*WIDTH]; if (val < snakeLength && val >= 0) { @@ -131,45 +141,50 @@ void tick() // Increase our length! snakeLength++; } + + // Update world + // ------------ snake[snakeX + snakeY*WIDTH] = 0; } +// draw +// ==== void draw() { char body[] = "NIBBLES"; for (int y = -1; y <= HEIGHT; ++y) { for (int x = -1; x <= WIDTH; ++x) { - + // Draw a border outside the playing field if (x == -1 || y == -1 || x == WIDTH || y == HEIGHT) { - if (x == -1 || y == -1) { - unsigned int screenX = x + 1; - unsigned int screenY = y + 1; - nib_put_scr(screenX, screenY, '#'); - } else { - unsigned int screenX = x + 1; - unsigned int screenY = y + 1; - nib_put_scr(screenX, screenY, '#'); - } + unsigned int screenX = x + 1; + unsigned int screenY = y + 1; + nib_put_scr(screenX, screenY, '#'); } else { int snakeVal = snake[x + y*WIDTH]; unsigned int screenX = x + 1; unsigned int screenY = y + 1; - + + // If the `DEBUG` flag is set, draw the raw ASCII-value for debugging purposes if (DEBUG) { nib_put_scr(screenX, screenY, '0' + snakeVal); continue; } + // If the value is greater than `0` and less than `snakeLength`, it's part of the snake if (snakeVal >= 0 && snakeVal < snakeLength) { if (x == snakeX && y == snakeY) { + // Draw the head nib_put_scr(screenX, screenY, '@'); } else { + // Draw the body nib_put_scr(screenX, screenY, body[(snakeVal - 1) % 7]); } } else if (snakeVal < 0) { + // If the value is less than `0`, it's an apple nib_put_scr(screenX, screenY, 'o'); } else { + // Otherwise it's empty. nib_put_scr(screenX, screenY, ' '); } } diff --git a/docco-languages.json b/docco-languages.json new file mode 100644 index 0000000..324a2d9 --- /dev/null +++ b/docco-languages.json @@ -0,0 +1,4 @@ +{ + ".S": {"name": "x86asm", "symbol": "//"}, + ".c": {"name": "c", "symbol": "//"} +} diff --git a/docs/cnibbles.html b/docs/cnibbles.html new file mode 100644 index 0000000..1411deb --- /dev/null +++ b/docs/cnibbles.html @@ -0,0 +1,693 @@ + + + + + cnibbles.c + + + + + +
+
+ + + + +
+ + diff --git a/docs/docco.css b/docs/docco.css new file mode 100644 index 0000000..a2899ac --- /dev/null +++ b/docs/docco.css @@ -0,0 +1,506 @@ +/*--------------------- Typography ----------------------------*/ + +@font-face { + font-family: 'aller-light'; + src: url('public/fonts/aller-light.eot'); + src: url('public/fonts/aller-light.eot?#iefix') format('embedded-opentype'), + url('public/fonts/aller-light.woff') format('woff'), + url('public/fonts/aller-light.ttf') format('truetype'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'aller-bold'; + src: url('public/fonts/aller-bold.eot'); + src: url('public/fonts/aller-bold.eot?#iefix') format('embedded-opentype'), + url('public/fonts/aller-bold.woff') format('woff'), + url('public/fonts/aller-bold.ttf') format('truetype'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'novecento-bold'; + src: url('public/fonts/novecento-bold.eot'); + src: url('public/fonts/novecento-bold.eot?#iefix') format('embedded-opentype'), + url('public/fonts/novecento-bold.woff') format('woff'), + url('public/fonts/novecento-bold.ttf') format('truetype'); + font-weight: normal; + font-style: normal; +} + +/*--------------------- Layout ----------------------------*/ +html { height: 100%; } +body { + font-family: "aller-light"; + font-size: 14px; + line-height: 18px; + color: #30404f; + margin: 0; padding: 0; + height:100%; +} +#container { min-height: 100%; } + +a { + color: #000; +} + +b, strong { + font-weight: normal; + font-family: "aller-bold"; +} + +p { + margin: 15px 0 0px; +} + .annotation ul, .annotation ol { + margin: 25px 0; + } + .annotation ul li, .annotation ol li { + font-size: 14px; + line-height: 18px; + margin: 10px 0; + } + +h1, h2, h3, h4, h5, h6 { + color: #112233; + line-height: 1em; + font-weight: normal; + font-family: "novecento-bold"; + text-transform: uppercase; + margin: 30px 0 15px 0; +} + +h1 { + margin-top: 40px; +} + +hr { + border: 0; + background: 1px #ddd; + height: 1px; + margin: 20px 0; +} + +pre, tt, code { + font-size: 12px; line-height: 16px; + font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace; + margin: 0; padding: 0; +} + .annotation pre { + display: block; + margin: 0; + padding: 7px 10px; + background: #fcfcfc; + -moz-box-shadow: inset 0 0 10px rgba(0,0,0,0.1); + -webkit-box-shadow: inset 0 0 10px rgba(0,0,0,0.1); + box-shadow: inset 0 0 10px rgba(0,0,0,0.1); + overflow-x: auto; + } + .annotation pre code { + border: 0; + padding: 0; + background: transparent; + } + + +blockquote { + border-left: 5px solid #ccc; + margin: 0; + padding: 1px 0 1px 1em; +} + .sections blockquote p { + font-family: Menlo, Consolas, Monaco, monospace; + font-size: 12px; line-height: 16px; + color: #999; + margin: 10px 0 0; + white-space: pre-wrap; + } + +ul.sections { + list-style: none; + padding:0 0 5px 0;; + margin:0; +} + +/* + Force border-box so that % widths fit the parent + container without overlap because of margin/padding. + + More Info : http://www.quirksmode.org/css/box.html +*/ +ul.sections > li > div { + -moz-box-sizing: border-box; /* firefox */ + -ms-box-sizing: border-box; /* ie */ + -webkit-box-sizing: border-box; /* webkit */ + -khtml-box-sizing: border-box; /* konqueror */ + box-sizing: border-box; /* css3 */ +} + + +/*---------------------- Jump Page -----------------------------*/ +#jump_to, #jump_page { + margin: 0; + background: white; + -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; + -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; + font: 16px Arial; + cursor: pointer; + text-align: right; + list-style: none; +} + +#jump_to a { + text-decoration: none; +} + +#jump_to a.large { + display: none; +} +#jump_to a.small { + font-size: 22px; + font-weight: bold; + color: #676767; +} + +#jump_to, #jump_wrapper { + position: fixed; + right: 0; top: 0; + padding: 10px 15px; + margin:0; +} + +#jump_wrapper { + display: none; + padding:0; +} + +#jump_to:hover #jump_wrapper { + display: block; +} + +#jump_page { + padding: 5px 0 3px; + margin: 0 0 25px 25px; +} + +#jump_page .source { + display: block; + padding: 15px; + text-decoration: none; + border-top: 1px solid #eee; +} + +#jump_page .source:hover { + background: #f5f5ff; +} + +#jump_page .source:first-child { +} + +/*---------------------- Low resolutions (> 320px) ---------------------*/ +@media only screen and (min-width: 320px) { + .pilwrap { display: none; } + + ul.sections > li > div { + display: block; + padding:5px 10px 0 10px; + } + + ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol { + padding-left: 30px; + } + + ul.sections > li > div.content { + overflow-x:auto; + -webkit-box-shadow: inset 0 0 5px #e5e5ee; + box-shadow: inset 0 0 5px #e5e5ee; + border: 1px solid #dedede; + margin:5px 10px 5px 10px; + padding-bottom: 5px; + } + + ul.sections > li > div.annotation pre { + margin: 7px 0 7px; + padding-left: 15px; + } + + ul.sections > li > div.annotation p tt, .annotation code { + background: #f8f8ff; + border: 1px solid #dedede; + font-size: 12px; + padding: 0 0.2em; + } +} + +/*---------------------- (> 481px) ---------------------*/ +@media only screen and (min-width: 481px) { + #container { + position: relative; + } + body { + background-color: #F5F5FF; + font-size: 15px; + line-height: 21px; + } + pre, tt, code { + line-height: 18px; + } + p, ul, ol { + margin: 0 0 15px; + } + + + #jump_to { + padding: 5px 10px; + } + #jump_wrapper { + padding: 0; + } + #jump_to, #jump_page { + font: 10px Arial; + text-transform: uppercase; + } + #jump_page .source { + padding: 5px 10px; + } + #jump_to a.large { + display: inline-block; + } + #jump_to a.small { + display: none; + } + + + + #background { + position: absolute; + top: 0; bottom: 0; + width: 350px; + background: #fff; + border-right: 1px solid #e5e5ee; + z-index: -1; + } + + ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol { + padding-left: 40px; + } + + ul.sections > li { + white-space: nowrap; + } + + ul.sections > li > div { + display: inline-block; + } + + ul.sections > li > div.annotation { + max-width: 350px; + min-width: 350px; + min-height: 5px; + padding: 13px; + overflow-x: hidden; + white-space: normal; + vertical-align: top; + text-align: left; + } + ul.sections > li > div.annotation pre { + margin: 15px 0 15px; + padding-left: 15px; + } + + ul.sections > li > div.content { + padding: 13px; + vertical-align: top; + border: none; + -webkit-box-shadow: none; + box-shadow: none; + } + + .pilwrap { + position: relative; + display: inline; + } + + .pilcrow { + font: 12px Arial; + text-decoration: none; + color: #454545; + position: absolute; + top: 3px; left: -20px; + padding: 1px 2px; + opacity: 0; + -webkit-transition: opacity 0.2s linear; + } + .for-h1 .pilcrow { + top: 47px; + } + .for-h2 .pilcrow, .for-h3 .pilcrow, .for-h4 .pilcrow { + top: 35px; + } + + ul.sections > li > div.annotation:hover .pilcrow { + opacity: 1; + } +} + +/*---------------------- (> 1025px) ---------------------*/ +@media only screen and (min-width: 1025px) { + + body { + font-size: 16px; + line-height: 24px; + } + + #background { + width: 525px; + } + ul.sections > li > div.annotation { + max-width: 525px; + min-width: 525px; + padding: 10px 25px 1px 50px; + } + ul.sections > li > div.content { + padding: 9px 15px 16px 25px; + } +} + +/*---------------------- Syntax Highlighting -----------------------------*/ + +td.linenos { background-color: #f0f0f0; padding-right: 10px; } +span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } +/* + +github.com style (c) Vasily Polovnyov + +*/ + +pre code { + display: block; padding: 0.5em; + color: #000; + background: #f8f8ff +} + +pre .hljs-comment, +pre .hljs-template_comment, +pre .hljs-diff .hljs-header, +pre .hljs-javadoc { + color: #408080; + font-style: italic +} + +pre .hljs-keyword, +pre .hljs-assignment, +pre .hljs-literal, +pre .hljs-css .hljs-rule .hljs-keyword, +pre .hljs-winutils, +pre .hljs-javascript .hljs-title, +pre .hljs-lisp .hljs-title, +pre .hljs-subst { + color: #954121; + /*font-weight: bold*/ +} + +pre .hljs-number, +pre .hljs-hexcolor { + color: #40a070 +} + +pre .hljs-string, +pre .hljs-tag .hljs-value, +pre .hljs-phpdoc, +pre .hljs-tex .hljs-formula { + color: #219161; +} + +pre .hljs-title, +pre .hljs-id { + color: #19469D; +} +pre .hljs-params { + color: #00F; +} + +pre .hljs-javascript .hljs-title, +pre .hljs-lisp .hljs-title, +pre .hljs-subst { + font-weight: normal +} + +pre .hljs-class .hljs-title, +pre .hljs-haskell .hljs-label, +pre .hljs-tex .hljs-command { + color: #458; + font-weight: bold +} + +pre .hljs-tag, +pre .hljs-tag .hljs-title, +pre .hljs-rules .hljs-property, +pre .hljs-django .hljs-tag .hljs-keyword { + color: #000080; + font-weight: normal +} + +pre .hljs-attribute, +pre .hljs-variable, +pre .hljs-instancevar, +pre .hljs-lisp .hljs-body { + color: #008080 +} + +pre .hljs-regexp { + color: #B68 +} + +pre .hljs-class { + color: #458; + font-weight: bold +} + +pre .hljs-symbol, +pre .hljs-ruby .hljs-symbol .hljs-string, +pre .hljs-ruby .hljs-symbol .hljs-keyword, +pre .hljs-ruby .hljs-symbol .hljs-keymethods, +pre .hljs-lisp .hljs-keyword, +pre .hljs-tex .hljs-special, +pre .hljs-input_number { + color: #990073 +} + +pre .hljs-builtin, +pre .hljs-constructor, +pre .hljs-built_in, +pre .hljs-lisp .hljs-title { + color: #0086b3 +} + +pre .hljs-preprocessor, +pre .hljs-pi, +pre .hljs-doctype, +pre .hljs-shebang, +pre .hljs-cdata { + color: #999; + font-weight: bold +} + +pre .hljs-deletion { + background: #fdd +} + +pre .hljs-addition { + background: #dfd +} + +pre .hljs-diff .hljs-change { + background: #0086b3 +} + +pre .hljs-chunk { + color: #aaa +} + +pre .hljs-tex .hljs-formula { + opacity: 0.5; +} diff --git a/docs/nibbles.html b/docs/nibbles.html new file mode 100644 index 0000000..9e01661 --- /dev/null +++ b/docs/nibbles.html @@ -0,0 +1,1966 @@ + + + + + nibbles.S + + + + + +
+
+ + + + +
+ + diff --git a/docs/public/fonts/aller-bold.eot b/docs/public/fonts/aller-bold.eot new file mode 100644 index 0000000..1b32532 Binary files /dev/null and b/docs/public/fonts/aller-bold.eot differ diff --git a/docs/public/fonts/aller-bold.ttf b/docs/public/fonts/aller-bold.ttf new file mode 100644 index 0000000..dc4cc9c Binary files /dev/null and b/docs/public/fonts/aller-bold.ttf differ diff --git a/docs/public/fonts/aller-bold.woff b/docs/public/fonts/aller-bold.woff new file mode 100644 index 0000000..fa16fd0 Binary files /dev/null and b/docs/public/fonts/aller-bold.woff differ diff --git a/docs/public/fonts/aller-light.eot b/docs/public/fonts/aller-light.eot new file mode 100644 index 0000000..40bd654 Binary files /dev/null and b/docs/public/fonts/aller-light.eot differ diff --git a/docs/public/fonts/aller-light.ttf b/docs/public/fonts/aller-light.ttf new file mode 100644 index 0000000..c2c7290 Binary files /dev/null and b/docs/public/fonts/aller-light.ttf differ diff --git a/docs/public/fonts/aller-light.woff b/docs/public/fonts/aller-light.woff new file mode 100644 index 0000000..81a09d1 Binary files /dev/null and b/docs/public/fonts/aller-light.woff differ diff --git a/docs/public/fonts/novecento-bold.eot b/docs/public/fonts/novecento-bold.eot new file mode 100644 index 0000000..98a9a7f Binary files /dev/null and b/docs/public/fonts/novecento-bold.eot differ diff --git a/docs/public/fonts/novecento-bold.ttf b/docs/public/fonts/novecento-bold.ttf new file mode 100644 index 0000000..2af39b0 Binary files /dev/null and b/docs/public/fonts/novecento-bold.ttf differ diff --git a/docs/public/fonts/novecento-bold.woff b/docs/public/fonts/novecento-bold.woff new file mode 100644 index 0000000..de558b5 Binary files /dev/null and b/docs/public/fonts/novecento-bold.woff differ diff --git a/docs/public/stylesheets/normalize.css b/docs/public/stylesheets/normalize.css new file mode 100644 index 0000000..73abb76 --- /dev/null +++ b/docs/public/stylesheets/normalize.css @@ -0,0 +1,375 @@ +/*! normalize.css v2.0.1 | MIT License | git.io/normalize */ + +/* ========================================================================== + HTML5 display definitions + ========================================================================== */ + +/* + * Corrects `block` display not defined in IE 8/9. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section, +summary { + display: block; +} + +/* + * Corrects `inline-block` display not defined in IE 8/9. + */ + +audio, +canvas, +video { + display: inline-block; +} + +/* + * Prevents modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/* + * Addresses styling for `hidden` attribute not present in IE 8/9. + */ + +[hidden] { + display: none; +} + +/* ========================================================================== + Base + ========================================================================== */ + +/* + * 1. Sets default font family to sans-serif. + * 2. Prevents iOS text size adjust after orientation change, without disabling + * user zoom. + */ + +html { + font-family: sans-serif; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ + -ms-text-size-adjust: 100%; /* 2 */ +} + +/* + * Removes default margin. + */ + +body { + margin: 0; +} + +/* ========================================================================== + Links + ========================================================================== */ + +/* + * Addresses `outline` inconsistency between Chrome and other browsers. + */ + +a:focus { + outline: thin dotted; +} + +/* + * Improves readability when focused and also mouse hovered in all browsers. + */ + +a:active, +a:hover { + outline: 0; +} + +/* ========================================================================== + Typography + ========================================================================== */ + +/* + * Addresses `h1` font sizes within `section` and `article` in Firefox 4+, + * Safari 5, and Chrome. + */ + +h1 { + font-size: 2em; +} + +/* + * Addresses styling not present in IE 8/9, Safari 5, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/* + * Addresses style set to `bolder` in Firefox 4+, Safari 5, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +/* + * Addresses styling not present in Safari 5 and Chrome. + */ + +dfn { + font-style: italic; +} + +/* + * Addresses styling not present in IE 8/9. + */ + +mark { + background: #ff0; + color: #000; +} + + +/* + * Corrects font family set oddly in Safari 5 and Chrome. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, serif; + font-size: 1em; +} + +/* + * Improves readability of pre-formatted text in all browsers. + */ + +pre { + white-space: pre; + white-space: pre-wrap; + word-wrap: break-word; +} + +/* + * Sets consistent quote types. + */ + +q { + quotes: "\201C" "\201D" "\2018" "\2019"; +} + +/* + * Addresses inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/* + * Prevents `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +/* ========================================================================== + Embedded content + ========================================================================== */ + +/* + * Removes border when inside `a` element in IE 8/9. + */ + +img { + border: 0; +} + +/* + * Corrects overflow displayed oddly in IE 9. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* ========================================================================== + Figures + ========================================================================== */ + +/* + * Addresses margin not present in IE 8/9 and Safari 5. + */ + +figure { + margin: 0; +} + +/* ========================================================================== + Forms + ========================================================================== */ + +/* + * Define consistent border, margin, and padding. + */ + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/* + * 1. Corrects color not being inherited in IE 8/9. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + */ + +legend { + border: 0; /* 1 */ + padding: 0; /* 2 */ +} + +/* + * 1. Corrects font family not being inherited in all browsers. + * 2. Corrects font size not being inherited in all browsers. + * 3. Addresses margins set differently in Firefox 4+, Safari 5, and Chrome + */ + +button, +input, +select, +textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 2 */ + margin: 0; /* 3 */ +} + +/* + * Addresses Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +button, +input { + line-height: normal; +} + +/* + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Corrects inability to style clickable `input` types in iOS. + * 3. Improves usability and consistency of cursor style between image-type + * `input` and others. + */ + +button, +html input[type="button"], /* 1 */ +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ +} + +/* + * Re-set default cursor for disabled elements. + */ + +button[disabled], +input[disabled] { + cursor: default; +} + +/* + * 1. Addresses box sizing set to `content-box` in IE 8/9. + * 2. Removes excess padding in IE 8/9. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/* + * 1. Addresses `appearance` set to `searchfield` in Safari 5 and Chrome. + * 2. Addresses `box-sizing` set to `border-box` in Safari 5 and Chrome + * (include `-moz` to future-proof). + */ + +input[type="search"] { + -webkit-appearance: textfield; /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; /* 2 */ + box-sizing: content-box; +} + +/* + * Removes inner padding and search cancel button in Safari 5 and Chrome + * on OS X. + */ + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/* + * Removes inner padding and border in Firefox 4+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/* + * 1. Removes default vertical scrollbar in IE 8/9. + * 2. Improves readability and alignment in all browsers. + */ + +textarea { + overflow: auto; /* 1 */ + vertical-align: top; /* 2 */ +} + +/* ========================================================================== + Tables + ========================================================================== */ + +/* + * Remove most spacing between table cells. + */ + +table { + border-collapse: collapse; + border-spacing: 0; +} \ No newline at end of file diff --git a/docs/start.html b/docs/start.html new file mode 100644 index 0000000..c922baf --- /dev/null +++ b/docs/start.html @@ -0,0 +1,157 @@ + + + + + start.S + + + + + +
+
+ + + + +
+ + diff --git a/nibbles.S b/nibbles.S index 4e41431..75ab419 100644 --- a/nibbles.S +++ b/nibbles.S @@ -1,50 +1,80 @@ +// by Simon Holmberg +// +// This is a document generated by [docco](http://jashkenas.github.io/docco/). +// My report is interleaved with the source code in the form of comments in +// [markdown](http://daringfireball.net/projects/markdown/) format. +// +// #define WIDTH 60 #define HEIGHT 40 +// .bss +// ==== .bss // Array of longs representing the game field +// +// `world` is an array of increasing time values. By having the snake head set +// the time value to 0 at its current position, the actual **snake** will be +// defined by the locations where the time value is lesser than the snake +// length. This makes the tail of the snake automatically "move" visually, and +// allows for a snake with an arbitrary length without complicated arrays of +// coordinates! +// +// **Apples** are defined by negative time values which do not get incremented +// each frame. If we wanted to, we could instead decrease this value and +// compare it with a lifetime value, to conveniently make apples disappear +// after a set amount of time. .align 4 world: .space WIDTH*HEIGHT*4 +// .data +// ===== .data // Current length of the snake snakeLength: .long 0 -// Snake position +// Snake position (starts in the middle of the field) snakePosX: .long WIDTH / 2 snakePosY: .long HEIGHT / 2 -// Snake direction +// Snake direction (start moving to the right) snakeDirX: .long 1 snakeDirY: .long 0 // Number of apples numApples: .long 0 -// Optional score-keeping -score: .long 0 -// Utility strings -snibbles: .ascii "NIBBLES" -snibbles_end: +// Game over message sgameover: .string " Game over! Score: %i " sgameover_end: +// Various utility strings mainly used for debugging string1: .string "Started with snake length %i and %i apples!\n" string2: .string "Snake position: (%i, %i)\n" stringi: .string "%i\n" stringtest: .string "> %i %i %c\n" +// .text +// ===== .text +// start_game +// ============ +// `start_game(int len, int n_apples)` .global start_game start_game: - // snakeLength = len + // Initialization + // -------------- + + // Save our function arguments for later + + // `snakeLength = len` movl 4(%esp), %eax movl %eax, snakeLength - // numApples = n_apples + // `numApples = n_apples` movl 8(%esp), %eax movl %eax, numApples - pushl %ebx - pushl %edi - + // Store all registers so we can restore their state before we return later + pusha + // Call nib_init call nib_init - // Seed randomness + // Seed randomness by calling `srand` with a time value from `time` pushl $0 call time addl $4, %esp @@ -52,22 +82,8 @@ start_game: call srand addl $4, %esp - // Print our arguments - //pushl numApples - //pushl snakeLength - //pushl $string1 - //call printf - //addl $4*3, %esp - - // Print worm position - //pushl snakePosY - //pushl snakePosX - //pushl $string2 - //call printf - //addl $4*3, %esp - - // Initialize the snake array - // Set every cell to a time value greater than the snake length + // Initialize the snake array by setting every cell to a time value greater + // than `snakeLength` movl $world, %edi movl snakeLength, %eax movl $WIDTH*HEIGHT, %ebx @@ -86,25 +102,33 @@ start_game: popl %ecx loop 1b - // Loop forever + // Game loop + // --------- loop: - // Sleep for a while + // Sleep for a while using `usleep` so the snake doesn't wiggle at the + // speed of light! pushl $250*1000 - pushl %ecx call usleep addl $4, %esp + // Jump to `tick`, our updating function, which later chain-jumps to `draw` jmp tick - popl %edi - popl %ebx + // Restore all our registers as they were before `start_game` was called + // and return + popa ret -// Update stuff +// tick +// ==== +// This is where we update the world. tick: movl $world, %edi // Increment cell times + // -------------------- + + // Loop movl snakeLength, %ebx xorl %ecx, %ecx 1: @@ -123,6 +147,9 @@ tick: jne 1b // Input + // ----- + + // Call nib_poll_kbd and check down, up, left and right in succession call nib_poll_kbd // Down movl $258, %ebx @@ -130,20 +157,20 @@ tick: jne 1f movl $0, snakeDirX movl $1, snakeDirY -1: // Up - movl $259, %ebx + // Up +1: movl $259, %ebx cmpl %eax, %ebx jne 1f movl $0, snakeDirX movl $-1, snakeDirY -1: // Left - movl $260, %ebx + // Left +1: movl $260, %ebx cmpl %eax, %ebx jne 1f movl $-1, snakeDirX movl $0, snakeDirY -1: // Right - movl $261, %ebx + // Right +1: movl $261, %ebx cmpl %eax, %ebx jne 1f movl $1, snakeDirX @@ -151,25 +178,32 @@ tick: 1: // Move snake - // snakePosX = (snakePosX + snakeDirY + WIDTH) % WIDTH + // ---------- + + // `snakePosX = (snakePosX + snakeDirY + WIDTH) % WIDTH` movl snakePosX, %eax movl snakeDirX, %ebx addl %ebx, %eax - addl $WIDTH, %eax // For modulo wrap-around + // Add width for modulo wrap-around + addl $WIDTH, %eax xorl %edx, %edx movl $WIDTH, %ecx divl %ecx mov %edx, snakePosX - // snakePosY = (snakePosY + snakeDirY + HEIGHT) % HEIGHT + // `snakePosY = (snakePosY + snakeDirY + HEIGHT) % HEIGHT` movl snakePosY, %eax movl snakeDirY, %ebx addl %ebx, %eax - addl $HEIGHT, %eax // For modulo wrap-around + // Add height for modulo wrap-around + addl $HEIGHT, %eax xorl %edx, %edx movl $HEIGHT, %ecx divl %ecx mov %edx, snakePosY + // Collision + // --------- + // Get value at head position movl snakePosY, %eax movl $WIDTH, %edx @@ -180,36 +214,42 @@ tick: // Collision with apple if negative test %edx, %edx js 1f - // No need to increment if it's already greater than snakeLength + // Compare value with `snakeLength` movl snakeLength, %ebx cmpl %ebx, %edx - jg 2f - // End the game when the snake collides with itself + // End the game if the snake collides with itself, i.e. `%edx < snakeLength` + jge 2f jmp gameOver -1: // Spawn a new apple - pushl %edi + // Spawn a new apple and extend the snake! +1: pushl %edi pushl %eax call spawnApple popl %eax popl %edi - // Extend the snake! incl snakeLength 2: + // Update world + // ------------ + // Set time value to 0 at snake head position - // i = x + y * WIDTH - // %edi = %ebx + %ecx * $WIDTH + // + // `i = x + y * WIDTH` + // + // `%edi = %ebx + %ecx * $WIDTH` movl $0, (%edi, %eax, 4) + // Proceed to `draw` jmp draw //jmp debug_draw -// Draw stuff +// draw +// ==== draw: - // Loop Y + // Loop on Y-axis movl $HEIGHT, %ecx 1: - // Loop X + // Loop on X-axis movl $WIDTH, %ebx 2: // Save loop registers @@ -218,10 +258,11 @@ draw: subl $1, %ecx subl $1, %ebx - // Call nib_put_scr + // Call `nib_put_scr` depending of the value in a cell - // i = x + y * WIDTH - // %eax = %ebx + %ecx * $WIDTH + // `i = x + y * WIDTH` + // + // `%eax = %ebx + %ecx * $WIDTH` movl %ecx, %eax movl $WIDTH, %edx mull %edx @@ -246,12 +287,15 @@ draw: 4: pushl $'o' 5: - movl %ecx, %eax // Y + // Push Y-coordinate + movl %ecx, %eax pushl %eax - movl %ebx, %eax // X + // Push X-coordinate + movl %ebx, %eax pushl %eax + // `nib_put_scr(int x, int y, int c)` call nib_put_scr addl $4*3, %esp @@ -259,13 +303,101 @@ draw: popl %ebx popl %ecx - decl %ebx // Decrement X - jnz 2b // End of X loop - loop 1b // End of Y loop + // Decrement X + decl %ebx + // End of X-loop + jnz 2b + // End of Y-loop + loop 1b + // Jump back to the start of our game loop! jmp loop -// Debug drawing +// gameOver +// ======== +// Called when the game ends. It displays a game over message +// and score, and quits after **3 seconds**. +gameOver: + // Calculate message position + // -------------------------- + + // Calculate string length + movl $sgameover_end, %eax + subl $sgameover, %eax + // Discout null terminator + subl $1, %eax + + // Calculate X-pos in the middle of the screen + movl $2, %ebx + xorl %edx, %edx + divl %ebx + negl %eax + addl $WIDTH/2, %eax + + // Print game over message + // ----------------------- + + // Push `snakeLength` as score + pushl snakeLength + // Push printf-string + pushl $sgameover + // Push X-coordinate + pushl %eax + // Push Y-coordinate + pushl $HEIGHT/2 + // `mvprintw(int y, int x, const char *fmt, ...)` + call mvprintw + add $4*3, %esp + // Call `refresh` to refresh the screen + call refresh + + // Sleep for 3 seconds before calling `nib_end` + pushl $3000*1000 + call usleep + addl $4, %esp + call nib_end + +// spawnApple +// ========== +// Spawns an **apple** in a random location in the `world`. +spawnApple: + pushl %ebx + + // `%ecx = rand() % HEIGHT` + call rand + xorl %edx, %edx + movl $HEIGHT, %ebx + divl %ebx + movl %edx, %ecx + // `%ebx = rand() % WIDTH` + pushl %ecx + call rand + xorl %edx, %edx + movl $WIDTH, %ebx + divl %ebx + movl %edx, %ebx + popl %ecx + + // `i = x + y * WIDTH` + // + // `%eax = %ebx + %ecx * $WIDTH` + movl %ecx, %eax + movl $WIDTH, %edx + mull %edx + addl %ebx, %eax + + // Set the cell negative to represent an apple + movl $world, %ecx + movl $-1, %edx + movl %edx, (%ecx, %eax, 4) + + popl %ebx + ret + +// debug_draw +// ============= +// This is basically the same as `draw`, except it draws the actual ASCII-value +// of the world for debugging purposes. debug_draw: // Loop Y movl $HEIGHT, %ecx @@ -281,8 +413,9 @@ debug_draw: // Call nib_put_scr - // i = x + y * WIDTH - // %edi = %ebx + %ecx * $WIDTH + // `i = x + y * WIDTH` + // + // `%edi = %ebx + %ecx * $WIDTH` movl %ecx, %eax movl $WIDTH, %edx mull %edx @@ -292,10 +425,12 @@ debug_draw: movl (%edi, %eax, 4), %eax pushl %eax - movl %ecx, %eax // Y + // Y coordinate + movl %ecx, %eax pushl %eax - movl %ebx, %eax // X + // X coordinate + movl %ebx, %eax pushl %eax call nib_put_scr @@ -305,68 +440,14 @@ debug_draw: popl %ebx popl %ecx - decl %ebx // Decrement X - jnz 2b // End of X loop - loop 1b // End of Y loop + // Decrement X + decl %ebx + // End of X-loop + jnz 2b + // End of Y-loop + loop 1b + + // Jump back to the start of our game loop! jmp loop -gameOver: - // Calculate string length - movl $sgameover_end, %eax - subl $sgameover, %eax - subl $1, %eax // Discount null terminator - - // Calculate X-pos - movl $2, %ebx - xorl %edx, %edx - divl %ebx - negl %eax - addl $WIDTH/2, %eax - - // Print game over message - pushl snakeLength - pushl $sgameover - pushl %eax // X - pushl $HEIGHT/2 // Y - call mvprintw - add $4*3, %esp - call refresh - - pushl $3000*1000 - call usleep - addl $4, %esp - call nib_end - -spawnApple: - pushl %ebx - - // %ecx = rand() % HEIGHT - call rand - xorl %edx, %edx - movl $HEIGHT, %ebx - divl %ebx - movl %edx, %ecx - // %ebx = rand() % WIDTH - pushl %ecx - call rand - xorl %edx, %edx - movl $WIDTH, %ebx - divl %ebx - movl %edx, %ebx - popl %ecx - - // i = x + y * WIDTH - // %eax = %ebx + %ecx * $WIDTH - movl %ecx, %eax - movl $WIDTH, %edx - mull %edx - addl %ebx, %eax - - // Set the cell negative to represent an apple - movl $world, %ecx - movl $-1, %edx - movl %edx, (%ecx, %eax, 4) - - popl %ebx - ret diff --git a/nibbles_asm b/nibbles_asm index 4475c38..22c6f52 100755 Binary files a/nibbles_asm and b/nibbles_asm differ diff --git a/nibbles_asm_start b/nibbles_asm_start index 79d8182..be9bb0e 100755 Binary files a/nibbles_asm_start and b/nibbles_asm_start differ diff --git a/nibbles_c b/nibbles_c index d2a5398..97fc96e 100755 Binary files a/nibbles_c and b/nibbles_c differ diff --git a/start.S b/start.S index 252d351..d5a7e2a 100644 --- a/start.S +++ b/start.S @@ -1,12 +1,17 @@ .text +// _start +// ====== +// The `_start` symbol. Calls `start_game` with "reasonable parameters". .global _start _start: - # n_apples + // `n_apples` pushl $10 - # len + // `len` pushl $3 + // `start_game(int len, int n_apples)` call start_game addl $4*2, %esp - - movl $0, %eax - ret + + // Exit cleanly with an exit code of 0 + pushl $0 + call _exit