Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
f14ccac
Add Chapter 2 Lesson 2
evie-calico Aug 25, 2022
6085e0f
Update src/part2/objects.md
avivace Sep 18, 2022
f8ea013
Apply suggestions from code review
evie-calico Sep 18, 2022
497d522
Update objects.md
evie-calico Sep 18, 2022
25a1b8f
Update objects.md
evie-calico Sep 18, 2022
a749a67
Update objects.md
evie-calico Sep 18, 2022
e722217
Remove JRs from chapter 2
evie-calico Oct 5, 2022
024b558
Remove JRs from chapter 1
evie-calico Oct 5, 2022
32d48e7
Merge branch 'ISSOtm:master' into master
evie-calico Oct 5, 2022
d301884
Add simplified pads.z80
evie-calico Oct 6, 2022
b62df50
Add chapter 3
evie-calico Oct 6, 2022
26ec89e
Rebase branch
evie-calico Oct 18, 2022
53b4b74
f
evie-calico Oct 18, 2022
75a0db7
Update src/part2/input.md
avivace Oct 24, 2022
a7d07cf
Update src/part2/input.md
evie-calico Oct 24, 2022
4bab86d
Split input into functions and input
evie-calico Oct 24, 2022
92fe8e6
Add functions and input to SAMMARY
evie-calico Oct 24, 2022
d3d8a80
Split source code, remove "cargo-cult" message
evie-calico Oct 25, 2022
7d1c2fa
Update src/part2/functions.md
evie-calico Nov 2, 2022
f581463
Fix underscores in include anchors
ISSOtm Nov 13, 2022
f65319b
Update functions.md
evie-calico Nov 18, 2022
2e59646
Fix underscores in include blocks
ISSOtm Nov 22, 2022
5e849f7
Turn the function modifications into a table
ISSOtm Nov 22, 2022
639f7f3
Update src/part2/functions.md
avivace Nov 26, 2022
999648c
Apply suggestions from code review
avivace Nov 26, 2022
e17aa73
Apply suggestions from code review
evie-calico Nov 30, 2022
d7c6815
Update src/part2/functions.md
avivace Dec 3, 2022
6488ef6
Update input.md
evie-calico Dec 6, 2022
9a4487a
Merge branch 'ISSOtm:master' into part3
evie-calico Dec 6, 2022
95e17b0
Update functions.md
evie-calico Dec 6, 2022
a7fc0b8
Update src/part2/functions.md
evie-calico Dec 6, 2022
5e79007
Update input.md
evie-calico Dec 6, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@

- [Getting started](part2/getting-started.md)
- [Objects](part2/objects.md)
- [Functions](part2/functions.md)
- [Input](part2/input.md)
- [Work in progress](part2/wip.md)

# Part Ⅲ — Our second game
Expand Down
65 changes: 65 additions & 0 deletions src/part2/functions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Functions

So far, we have only written a single "flow" of code, but we can already spot some snippets that look redundant.
Let's use **functions** to "factor out" code!

For example, in three places, we are copying chunks of memory around.
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):

```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/functions/main.asm:memcpy}}
{{#include ../../unbricked/functions/main.asm:memcpy}}
```

The new `ret` instruction should immediately catch our eye.
It is, unsurprisingly, what makes execution *return* to where the function was *called* from.
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.
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!
Otherwise, the results are unpredictable.

Notice the comment above the function, explaining which registers it takes as input.
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.
We'll see more of those as we progress.

There are three places in the initialization code where we can use the `Memcpy` function.
Find each of these copy loops and replace them with a call to `Memcpy`; for this, we use the `call` instruction.
The registers serve as parameters to the function, so we'll leave them as-is.

<div class="table-wrapper"><table><thead><tr><th>Before</th><th>After</th></tr></thead><tbody><tr><td>

```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/getting-started/main.asm:copy_tiles}}
{{#include ../../unbricked/getting-started/main.asm:copy_tiles}}
```

</td><td>

```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/functions/main.asm:copy_tiles}}
{{#include ../../unbricked/functions/main.asm:copy_tiles}}
```

</td></tr><tr><td>

```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/getting-started/main.asm:copy_map}}
{{#include ../../unbricked/getting-started/main.asm:copy_map}}
```

</td><td>

```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/functions/main.asm:copy_map}}
{{#include ../../unbricked/functions/main.asm:copy_map}}
```

</td></tr><tr><td>

```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/objects/main.asm:copy-paddle}}
{{#include ../../unbricked/objects/main.asm:copy-paddle}}
```

</td><td>

```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/functions/main.asm:copy_paddle}}
{{#include ../../unbricked/functions/main.asm:copy_paddle}}
```

</td></tr></tbody></table></div>

In the next chapter, we'll write another function, this time to read player input.
31 changes: 31 additions & 0 deletions src/part2/input.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Input

We have the building blocks of a game here, but we're still lacking player input.
A game that plays itself isn't very much fun, so let's fix that.

Paste this code below your `Main` loop.
Like `Memcpy`, this is a function that can be reused from different places, using the `call` instruction.

```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/input/main.asm:input-routine}}
{{#include ../../unbricked/input/main.asm:input-routine}}
```

Comment thread
evie-calico marked this conversation as resolved.
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.
So, I ask that you make an exception, and trust me that this function *does* read input.
Alright? Good!

Now that we know how to use functions, let's call the `UpdateKeys` function in our main loop to read user input.
`UpdateKeys` writes the held buttons to a location in memory that we called `wCurKeys`, which we can read from after the function returns.
Because of this, we only need to call `UpdateKeys` once per frame.

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.

We're going to use the `and` opcode, which we can use to set the zero flag (`z`) to the value of the bit.
We can use this along with the `PADF` constants in hardware.inc to read a particular key.

```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/input/main.asm:main}}
{{#include ../../unbricked/input/main.asm:main}}
```

Now, if you compile the project, you should be able to move the paddle left and right using the d-pad!!
Hooray, we have the beginnings of a game!
Loading