Skip to content

Commit c6d7c2b

Browse files
evie-calicoISSOtmavivace
authored
Add Part 2 Chapter 3 (#33)
* Add Chapter 2 Lesson 2 Co-authored-by: Eldred Habert <eldredhabert0@gmail.com> Co-authored-by: Antonio Vivace <avivace4@gmail.com> * Update src/part2/objects.md Co-authored-by: Eldred Habert <eldredhabert0@gmail.com> * Apply suggestions from code review Co-authored-by: Eldred Habert <eldredhabert0@gmail.com> * Update objects.md * Update objects.md * Update objects.md * Remove JRs from chapter 2 * Remove JRs from chapter 1 * Add simplified pads.z80 * Add chapter 3 * f * Update src/part2/input.md Co-authored-by: Eldred Habert <eldredhabert0@gmail.com> * Update src/part2/input.md Co-authored-by: Eldred Habert <eldredhabert0@gmail.com> * Split input into functions and input * Add functions and input to SAMMARY * Split source code, remove "cargo-cult" message * Update src/part2/functions.md Co-authored-by: Antonio Vivace <avivace4@gmail.com> * Fix underscores in include anchors * Update functions.md * Fix underscores in include blocks * Turn the function modifications into a table I think they are easier to read that way * Update src/part2/functions.md Co-authored-by: Eldred Habert <eldredhabert0@gmail.com> * Apply suggestions from code review Co-authored-by: Eldred Habert <eldredhabert0@gmail.com> * Apply suggestions from code review Co-authored-by: Eldred Habert <eldredhabert0@gmail.com> * Update src/part2/functions.md Co-authored-by: Eldred Habert <eldredhabert0@gmail.com> * Update input.md * Update functions.md * Update src/part2/functions.md Co-authored-by: Eldred Habert <eldredhabert0@gmail.com> * Update input.md Co-authored-by: Eldred Habert <eldredhabert0@gmail.com> Co-authored-by: Antonio Vivace <avivace4@gmail.com>
1 parent 8a17f8e commit c6d7c2b

7 files changed

Lines changed: 1999 additions & 0 deletions

File tree

src/SUMMARY.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525

2626
- [Getting started](part2/getting-started.md)
2727
- [Objects](part2/objects.md)
28+
- [Functions](part2/functions.md)
29+
- [Input](part2/input.md)
2830
- [Work in progress](part2/wip.md)
2931

3032
# Part Ⅲ — Our second game

src/part2/functions.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Functions
2+
3+
So far, we have only written a single "flow" of code, but we can already spot some snippets that look redundant.
4+
Let's use **functions** to "factor out" code!
5+
6+
For example, in three places, we are copying chunks of memory around.
7+
Let's write a function below the `jp Main`, and let's call it `Memcpy`, like [the similar C function](https://man7.org/linux/man-pages/man3/memcpy.3.html):
8+
9+
```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/functions/main.asm:memcpy}}
10+
{{#include ../../unbricked/functions/main.asm:memcpy}}
11+
```
12+
13+
The new `ret` instruction should immediately catch our eye.
14+
It is, unsurprisingly, what makes execution *return* to where the function was *called* from.
15+
Importantly, many languages have a definite "end" to a function: in C or Rust, that's the closing brace `}`; in Pascal or Lua, the keyword `end`, and so on; the function implicitly returns when execution reaches its end.
16+
However, **this is not the case in assembly**, so you must remember to add a `ret` instruction at the end of the function to return from it!
17+
Otherwise, the results are unpredictable.
18+
19+
Notice the comment above the function, explaining which registers it takes as input.
20+
This comment is important so that you know how to interface with the function; assembly has no formal parameters, so comments explaining them are even more important than with other languages.
21+
We'll see more of those as we progress.
22+
23+
There are three places in the initialization code where we can use the `Memcpy` function.
24+
Find each of these copy loops and replace them with a call to `Memcpy`; for this, we use the `call` instruction.
25+
The registers serve as parameters to the function, so we'll leave them as-is.
26+
27+
<div class="table-wrapper"><table><thead><tr><th>Before</th><th>After</th></tr></thead><tbody><tr><td>
28+
29+
```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/getting-started/main.asm:copy_tiles}}
30+
{{#include ../../unbricked/getting-started/main.asm:copy_tiles}}
31+
```
32+
33+
</td><td>
34+
35+
```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/functions/main.asm:copy_tiles}}
36+
{{#include ../../unbricked/functions/main.asm:copy_tiles}}
37+
```
38+
39+
</td></tr><tr><td>
40+
41+
```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/getting-started/main.asm:copy_map}}
42+
{{#include ../../unbricked/getting-started/main.asm:copy_map}}
43+
```
44+
45+
</td><td>
46+
47+
```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/functions/main.asm:copy_map}}
48+
{{#include ../../unbricked/functions/main.asm:copy_map}}
49+
```
50+
51+
</td></tr><tr><td>
52+
53+
```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/objects/main.asm:copy-paddle}}
54+
{{#include ../../unbricked/objects/main.asm:copy-paddle}}
55+
```
56+
57+
</td><td>
58+
59+
```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/functions/main.asm:copy_paddle}}
60+
{{#include ../../unbricked/functions/main.asm:copy_paddle}}
61+
```
62+
63+
</td></tr></tbody></table></div>
64+
65+
In the next chapter, we'll write another function, this time to read player input.

src/part2/input.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Input
2+
3+
We have the building blocks of a game here, but we're still lacking player input.
4+
A game that plays itself isn't very much fun, so let's fix that.
5+
6+
Paste this code below your `Main` loop.
7+
Like `Memcpy`, this is a function that can be reused from different places, using the `call` instruction.
8+
9+
```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/input/main.asm:input-routine}}
10+
{{#include ../../unbricked/input/main.asm:input-routine}}
11+
```
12+
13+
Unfortunately, reading input on the Game Boy is fairly involved (as you can see!), and it would be quite difficult to explain what this function does right now.
14+
So, I ask that you make an exception, and trust me that this function *does* read input.
15+
Alright? Good!
16+
17+
Now that we know how to use functions, let's call the `UpdateKeys` function in our main loop to read user input.
18+
`UpdateKeys` writes the held buttons to a location in memory that we called `wCurKeys`, which we can read from after the function returns.
19+
Because of this, we only need to call `UpdateKeys` once per frame.
20+
21+
This is important, because not only is it faster to reload the inputs that we've already processed, but it also means that we will always act on the same inputs, even if the player presses or releases a button mid-frame.
22+
23+
We're going to use the `and` opcode, which we can use to set the zero flag (`z`) to the value of the bit.
24+
We can use this along with the `PADF` constants in hardware.inc to read a particular key.
25+
26+
```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/input/main.asm:main}}
27+
{{#include ../../unbricked/input/main.asm:main}}
28+
```
29+
30+
Now, if you compile the project, you should be able to move the paddle left and right using the d-pad!!
31+
Hooray, we have the beginnings of a game!

0 commit comments

Comments
 (0)