diff --git a/.github/workflows/build-and-deploy.yml b/.github/workflows/build-and-deploy.yml index 6352bcf5..479a32d9 100644 --- a/.github/workflows/build-and-deploy.yml +++ b/.github/workflows/build-and-deploy.yml @@ -16,9 +16,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout gb-asm-tutorial - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: path: gb-asm-tutorial + submodules: recursive - name: Install mdbook uses: peaceiris/actions-mdbook@v1 diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..53925990 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "unbricked"] + path = unbricked + url = https://github.com/ISSOtm/unbricked diff --git a/Cargo.lock b/Cargo.lock index dd5df5dd..4bf9479a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -213,6 +213,8 @@ version = "1.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8691782945451c1c383942c4874dbe63814f61cb57ef773cda2972682b7bb3c0" dependencies = [ + "jobserver", + "libc", "shlex", ] @@ -689,6 +691,21 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +[[package]] +name = "git2" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2deb07a133b1520dc1a5690e9bd08950108873d7ed5de38dcc74d3b5ebffa110" +dependencies = [ + "bitflags 2.9.0", + "libc", + "libgit2-sys", + "log", + "openssl-probe", + "openssl-sys", + "url", +] + [[package]] name = "globset" version = "0.4.16" @@ -1128,6 +1145,16 @@ dependencies = [ "syn", ] +[[package]] +name = "jobserver" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +dependencies = [ + "getrandom 0.3.2", + "libc", +] + [[package]] name = "js-sys" version = "0.3.77" @@ -1180,6 +1207,20 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "libgit2-sys" +version = "0.18.1+1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1dcb20f84ffcdd825c7a311ae347cce604a6f084a767dec4a4929829645290e" +dependencies = [ + "cc", + "libc", + "libssh2-sys", + "libz-sys", + "openssl-sys", + "pkg-config", +] + [[package]] name = "libredox" version = "0.1.3" @@ -1191,6 +1232,32 @@ dependencies = [ "redox_syscall", ] +[[package]] +name = "libssh2-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "220e4f05ad4a218192533b300327f5150e809b54c4ec83b5a1d91833601811b9" +dependencies = [ + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "libz-sys" +version = "1.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "linux-raw-sys" version = "0.9.4" @@ -1437,6 +1504,24 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-sys" +version = "0.9.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e145e1651e858e820e4860f7b9c5e169bc1d8ce1c86043be79fa7b7634821847" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "parking_lot" version = "0.12.3" @@ -1649,6 +1734,7 @@ version = "0.1.0" dependencies = [ "anyhow", "clap 2.34.0", + "git2", "lazy_static", "mdbook", "pulldown-cmark 0.8.0", @@ -2311,6 +2397,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "vec_map" version = "0.8.2" diff --git a/preproc/Cargo.toml b/preproc/Cargo.toml index 65610920..6ba40495 100644 --- a/preproc/Cargo.toml +++ b/preproc/Cargo.toml @@ -17,3 +17,4 @@ pulldown-cmark-to-cmark = "6.0.0" regex = "1.5.4" termcolor = "1.1.2" serde_json = "1.0.59" +git2 = "0.20.2" diff --git a/preproc/src/git.rs b/preproc/src/git.rs new file mode 100644 index 00000000..dc7eb1cc --- /dev/null +++ b/preproc/src/git.rs @@ -0,0 +1,61 @@ +use std::{ + collections::{hash_map::Entry, HashMap}, + path::{Path, PathBuf}, +}; + +use anyhow::{anyhow, Context}; +use git2::{Blob, Oid, Repository}; + +#[derive(Default)] +pub struct Repos(HashMap); + +impl Repos { + pub fn open(&mut self, path: PathBuf) -> mdbook::errors::Result<&Repository> { + match self.0.entry(path) { + Entry::Occupied(occupied_entry) => Ok(occupied_entry.into_mut()), + Entry::Vacant(vacant_entry) => { + let repo = Repository::open(vacant_entry.key())?; + Ok(vacant_entry.insert(repo)) + } + } + } +} + +pub fn find_commit_by_msg(repo: &Repository, msg: &str) -> mdbook::errors::Result { + let head = repo.head().context("Failed to look up repo HEAD")?; + let mut commit = head + .peel_to_commit() + .context("Failed to get the commit pointed to by HEAD")?; + while !commit + .message() + .ok_or(anyhow!("Non-UTF-8 commit message!?"))? + .strip_prefix(msg) + .is_some_and(|rest| rest.is_empty() || rest.starts_with('\n')) + { + commit = commit + .parent(0) + .context("Failed to find a commit with specified message")?; + } + Ok(commit.id()) +} + +pub fn get_file<'repos>( + repos: &'repos Repos, + (repo_path, commit_id): &(PathBuf, Oid), + path: &Path, +) -> mdbook::errors::Result> { + let repo = &repos.0[repo_path]; + let commit = repo.find_commit(*commit_id).unwrap(); + let tree = commit + .tree() + .context("Unable to obtain the commit's tree")?; + let entry = tree + .get_path(path) + .context("Unable to find the specified file")?; + let object = entry + .to_object(repo) + .context("Unable to obtain the file's object in the repo")?; + object + .peel_to_blob() + .context("The specified path is not a file") +} diff --git a/preproc/src/links.rs b/preproc/src/links.rs index eea8a68d..fde718f6 100644 --- a/preproc/src/links.rs +++ b/preproc/src/links.rs @@ -7,17 +7,21 @@ * http://mozilla.org/MPL/2.0/. */ -use anyhow::Result; +use anyhow::{anyhow, bail, Context, Result}; +use git2::Oid; use lazy_static::lazy_static; use mdbook::errors::Error; use regex::{CaptureMatches, Captures, Regex}; use std::fs::File; use std::io::{BufRead, BufReader, Write}; -use std::path::Path; +use std::ops::Deref; +use std::path::{Path, PathBuf}; use std::str; use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; -pub fn replace_all>(s: &str, path: P1) -> String { +use crate::git::Repos; + +pub fn replace_all>(s: &str, name: &str, path: P1, repos: &mut Repos) -> String { // When replacing one thing in a string by something with a different length, // the indices after that will not correspond, // we therefore have to store the difference to correct this @@ -25,10 +29,12 @@ pub fn replace_all>(s: &str, path: P1) -> String { let mut previous_end_index = 0; let mut replaced = String::new(); + let mut commit = None; + for link in find_links(s) { replaced.push_str(&s[previous_end_index..link.start_index]); - match link.render_with_path(&path) { + match link.render_with_path(path, repos, &mut commit) { Ok(new_content) => { replaced.push_str(&new_content); previous_end_index = link.end_index; @@ -41,16 +47,10 @@ pub fn replace_all>(s: &str, path: P1) -> String { write!(&mut stderr, "error:").unwrap(); stderr.reset().unwrap(); - eprintln!(" Error updating \"{}\", {}", link.link_text, e); + eprintln!(" [{name}] Error rendering \"{}\":", link.link_text); + eprintln!(" {e}"); for cause in e.chain().skip(1) { - let mut stderr = StandardStream::stderr(ColorChoice::Auto); - stderr - .set_color(ColorSpec::new().set_fg(Some(Color::Yellow)).set_bold(true)) - .unwrap(); - write!(&mut stderr, "warning:").unwrap(); - stderr.reset().unwrap(); - - eprintln!(" Caused By: {}", cause); + eprintln!(" ...caused by: {}", cause); } // This should make sure we include the raw `{{# ... }}` snippet @@ -65,46 +65,95 @@ pub fn replace_all>(s: &str, path: P1) -> String { } #[derive(PartialEq, Debug, Clone)] -struct Link<'a> { +struct Link<'text> { start_index: usize, end_index: usize, - link_text: &'a str, - - regex: &'a str, - path: &'a str, + link_text: &'text str, + kind: LinkKind<'text>, +} +#[derive(Debug, Clone, PartialEq)] +enum LinkKind<'text> { + LineNoOf { regex: &'text str, path: &'text str }, + UseCommit { path: &'text str, msg: &'text str }, + IncludeGit { path: &'text str }, } -impl<'a> Link<'a> { - fn from_capture(capture: Captures<'a>) -> Link<'a> { +impl<'text> Link<'text> { + fn from_capture(capture: Captures<'text>) -> Link<'text> { let mat = capture.get(0).unwrap(); Link { start_index: mat.start(), end_index: mat.end(), link_text: mat.as_str(), - regex: capture.get(1).unwrap().as_str(), - path: capture.get(2).unwrap().as_str(), + kind: if let Some(regex) = capture.get(1) { + LinkKind::LineNoOf { + regex: regex.as_str(), + path: capture.get(2).unwrap().as_str(), + } + } else if let Some(path) = capture.get(3) { + LinkKind::UseCommit { + path: path.as_str(), + msg: capture.get(4).unwrap().as_str(), + } + } else { + LinkKind::IncludeGit { + path: capture.get(5).unwrap().as_str(), + } + }, + } + } + + fn render_with_path>( + &self, + base: P, + repos: &mut Repos, + commit: &mut Option<(PathBuf, Oid)>, + ) -> Result { + match self.kind { + LinkKind::LineNoOf { regex, path } => { + render_line_no_of(regex, path, base.as_ref(), repos, commit.as_ref()) + } + LinkKind::UseCommit { path, msg } => { + let repo_path = base.as_ref().join(path); + let repo = repos + .open(repo_path.clone()) + .context("Unable to open repository")?; + commit.replace((repo_path, crate::git::find_commit_by_msg(repo, msg)?)); + Ok(String::new()) + } + LinkKind::IncludeGit { path } => render_include_git(path, repos, commit.as_ref()), } } +} + +fn render_line_no_of( + regex: &str, + path: &str, + base: &Path, + repos: &Repos, + commit: Option<&(PathBuf, Oid)>, +) -> Result { + let regex = Regex::new(regex).context("Bad regex")?; + let mut parts = path.split(':'); + let path = parts.next().unwrap(); + let (begin, end, section) = parse_parts(parts)?; - fn render_with_path>(&self, base: P) -> Result { + fn process_lines( + mut input: R, + regex: Regex, + path: &str, + begin: Option, + end: Option, + section: Option<&str>, + ) -> Result { lazy_static! { static ref ANCHOR_START: Regex = Regex::new(r"ANCHOR:\s*([\w_-]+)").unwrap(); static ref ANCHOR_END: Regex = Regex::new(r"ANCHOR_END:\s*([\w_-]+)").unwrap(); } - let base = base.as_ref(); - let regex = Regex::new(&self.regex)?; - let mut parts = self.path.split(':'); - let path = parts.next().unwrap(); - let (begin, end, section) = parse_parts(parts)?; - let mut section: Option<(_, &Regex)> = if let Some(section) = section { - Some((section, &ANCHOR_START)) - } else { - None - }; + let mut section = section.map(|section| (section, ANCHOR_START.deref())); - let mut input = BufReader::new(File::open(base.join(path))?); let mut line = String::new(); let mut line_no = 0; let mut try_matching = section.is_none() && begin.is_none(); @@ -151,7 +200,7 @@ impl<'a> Link<'a> { Err(Error::msg(match (try_matching, begin, section) { // Failed to match, simply enough - (true, _, _) => format!("Could not match \"{}\" in \"{}\"", &self.regex, &self.path), + (true, _, _) => format!("Could not match \"{}\" in \"{}\"", ®ex, &path), // Never begun matching? (false, Some(begin), None) => { format!("{} is only {} lines long, not {}", path, line_no, begin) @@ -165,11 +214,114 @@ impl<'a> Link<'a> { (false, Some(_), Some(_)) => unreachable!(), })) } + + if let Some(path_in_repo) = path.strip_prefix("@GIT@/") { + let blob = crate::git::get_file( + repos, + commit.ok_or(anyhow!("Please specify `#use_commit` beforehand"))?, + path_in_repo.as_ref(), + )?; + process_lines(blob.content(), regex, path, begin, end, section) + } else { + process_lines( + BufReader::new(File::open(base.join(path))?), + regex, + path, + begin, + end, + section, + ) + } +} + +fn render_include_git( + path: &str, + repos: &Repos, + commit: Option<&(PathBuf, Oid)>, +) -> Result { + let mut parts = path.split(':'); + let path = parts.next().unwrap(); + let (begin, end, section) = parse_parts(parts)?; + let mut section = section.map(|section| (section, ANCHOR_START.deref())); + + let blob = crate::git::get_file( + repos, + commit.ok_or(anyhow!("Please specify `#use_commit` beforehand"))?, + path.as_ref(), + )?; + let mut input = blob.content(); + + // FIXME: don't duplicate this with `render_line_no_of` + lazy_static! { + static ref ANCHOR_START: Regex = Regex::new(r"ANCHOR:\s*([\w_-]+)").unwrap(); + static ref ANCHOR_END: Regex = Regex::new(r"ANCHOR_END:\s*([\w_-]+)").unwrap(); + } + + let mut line = String::new(); + let mut line_no = 0; + let mut include = section.is_none() && begin.is_none(); + let mut text = String::new(); + + loop { + line.clear(); + let len = input.read_line(&mut line)?; + if len == 0 { + break; + } + + if !ANCHOR_START.is_match(&line) && !ANCHOR_END.is_match(&line) { + line_no += 1; + if begin == Some(line_no) { + include = true; + } + if include { + text.push_str(&line); + } + } + + if let Some(sect_regex) = section.as_mut() { + // Check if this line begins or ends (depending on the regex) the section + match sect_regex.1.captures(&line) { + Some(caps) if &caps[1] == sect_regex.0 => { + if !include { + // Section start + sect_regex.1 = &ANCHOR_END; + include = true; + } else { + // Section end + break; + } + } + _ => (), + } + } + if end == Some(line_no) { + debug_assert!(include); // This should have been checked earlier + break; + } + } + text.truncate(text.trim_end().len()); + + match (include, begin, section) { + // Failed to match, simply enough + (true, _, _) => Ok(text), + // Never begun matching? + (false, Some(begin), None) => { + bail!("{path} is only {line_no} lines long, not {begin}") + } + (false, None, Some((section, _))) => { + bail!("{path} doesn't contain section \"{section}\"") + } + // Impossible, only reason not to be matching is for either start condition to exist + (false, None, None) => unreachable!(), + // Impossible, the conditions are mutually exclusive + (false, Some(_), Some(_)) => unreachable!(), + } } -fn parse_parts<'a, I: Iterator>( +fn parse_parts<'text, I: Iterator>( mut parts: I, -) -> Result<(Option, Option, Option<&'a str>)> { +) -> Result<(Option, Option, Option<&'text str>)> { if let Some(first) = parts.next() { if let Some(second) = parts.next() { if parts.next().is_some() { @@ -199,27 +351,37 @@ fn parse_parts<'a, I: Iterator>( } } -struct LinkIter<'a>(CaptureMatches<'a, 'a>); +struct LinkIter<'text>(CaptureMatches<'text, 'text>); -impl<'a> Iterator for LinkIter<'a> { - type Item = Link<'a>; - fn next(&mut self) -> Option> { +impl<'text> Iterator for LinkIter<'text> { + type Item = Link<'text>; + fn next(&mut self) -> Option> { self.0.next().map(Link::from_capture) } } fn find_links(contents: &str) -> LinkIter<'_> { - // lazily compute the following regex: - // r#"\{\{#line_no_of\s*"([^"]*)"\s+([^}]+)\}\}"#)?; lazy_static! { static ref RE: Regex = Regex::new( r#"(?x) # insignificant whitespace mode \{\{\s* # link opening parens and whitespace - \#line_no_of # link type - \s+ # separating whitespace - "([^"]*)" # regex being searched for - \s+ # separating whitespace - ([^}]+) # path to search + (?: + \#line_no_of # link type + \s+ # separating whitespace + "([^"]*)" # regex being searched for + \s+ # separating whitespace + ([^}]+) # path to search + | + \#use_commit # link type + \s+ # separating whitespace + (\S+) # path to repo + @ # separating at-sign + "([^"]+)" # commit name + | + \#include_git # link type + \s+ # separating whitespace + ([^}]+) # path to include + ) \}\} # link closing parens"# ) .unwrap(); diff --git a/preproc/src/main.rs b/preproc/src/main.rs index 3e022fcd..855784b0 100644 --- a/preproc/src/main.rs +++ b/preproc/src/main.rs @@ -14,9 +14,10 @@ use std::io; use std::process; mod admonitions; +mod git; +mod links; mod preproc; use preproc::GbAsmTut; -mod links; pub fn make_app() -> App<'static, 'static> { App::new("pandocs-preproc") @@ -65,7 +66,7 @@ fn handle_preprocessing(pre: &dyn Preprocessor) -> Result<(), Error> { fn handle_supports(pre: &dyn Preprocessor, sub_args: &ArgMatches) -> ! { let renderer = sub_args.value_of("renderer").expect("Required argument"); - let supported = pre.supports_renderer(&renderer); + let supported = pre.supports_renderer(renderer); // Signal whether the renderer is supported by exiting with 1 or 0. if supported { diff --git a/preproc/src/preproc.rs b/preproc/src/preproc.rs index 4d15416c..e938856a 100644 --- a/preproc/src/preproc.rs +++ b/preproc/src/preproc.rs @@ -7,6 +7,7 @@ * http://mozilla.org/MPL/2.0/. */ +use crate::git::Repos; use crate::links; use anyhow::Result; use mdbook::book::{Book, BookItem}; @@ -32,6 +33,7 @@ impl Preprocessor for GbAsmTut { fn run(&self, ctx: &PreprocessorContext, mut book: Book) -> Result { let src_dir = ctx.root.join(&ctx.config.book.src); + let mut repos = Repos::default(); let mut res = Ok(()); book.for_each_mut(|section: &mut BookItem| { @@ -46,7 +48,7 @@ impl Preprocessor for GbAsmTut { .map(|dir| src_dir.join(dir)) .expect("All book items have a parent"); - ch.content = links::replace_all(&ch.content, base); + ch.content = links::replace_all(&ch.content, &ch.name, base, &mut repos); if let Err(err) = self.process_admonitions(ch) { res = Err(err); } diff --git a/src/cheatsheet.md b/src/cheatsheet.md index b4770f82..8e008bce 100644 --- a/src/cheatsheet.md +++ b/src/cheatsheet.md @@ -44,10 +44,10 @@ Is there something common you think is missing? Check the [github repository](ht The `rLCDC` register controls all of the following: -- The screen -- The background -- The window -- Sprite objects +- The screen +- The background +- The window +- Sprite objects For more information on LCD control, refer to the [Pan Docs](https://gbdev.io/pandocs/LCDC.html) @@ -141,10 +141,10 @@ Which region the background uses is controlled by the 4th bit of the `rLCDC` reg You can use one of the 4 constants to specify which layer uses which region: -- LCDCF_WIN9800 -- LCDCF_WIN9C00 -- LCDCF_BG9800 -- LCDCF_BG9C00 +- LCDCF_WIN9800 +- LCDCF_WIN9C00 +- LCDCF_BG9800 +- LCDCF_BG9C00 :::tip Note @@ -307,20 +307,21 @@ Check out the Pan Docs for more info on the [WY, WX: Window Y position, X positi Reading joypad input is not a trivial task. For more info see [Tutorial #2](https://gbdev.io/gb-asm-tutorial/part2/input.html), or the [Joypad Input Page](https://gbdev.io/pandocs/Joypad_Input.html) in the Pan Docs. Paste this code somewhere in your project: -```rgbasm,linenos,start={{#line_no_of "" ../unbricked/input/main.asm:input-routine}} -{{#include ../unbricked/input/main.asm:input-routine}} +{{#use_commit ../unbricked@"Lesson 4: Input"}} + +```rgbasm +{{#include_git main.asm:input-routine}} ``` Next setup 2 variables in working ram: -```rgbasm,linenos,start={{#line_no_of "" ../unbricked/input/main.asm:vars}} -{{#include ../unbricked/input/main.asm:vars}} +```rgbasm +{{#include_git main.asm:vars}} ``` -Finally, during your game loop, be sure to call the `UpdateKeys` function during the Vertical Blank phase. +Finally, during your game loop, be sure to call the `UpdateKeys` function. ```rgbasm,linenos -; Check the current keys every frame and move left or right. call UpdateKeys ``` @@ -328,14 +329,14 @@ call UpdateKeys You can check if a button is down using any of the following constants from hardware.inc: -- PADF_DOWN -- PADF_UP -- PADF_LEFT -- PADF_RIGHT -- PADF_START -- PADF_SELECT -- PADF_B -- PADF_A +- PADF_DOWN +- PADF_UP +- PADF_LEFT +- PADF_RIGHT +- PADF_START +- PADF_SELECT +- PADF_B +- PADF_A You can check if the associataed button is down using the `wCurKeys` variable: @@ -359,11 +360,11 @@ jp nz, AWasJustPressed To wait **indefinitely** for a button press, create a loop where you: -- check if the button has JUST been pressed -- If not: - - Wait until the next vertical blank phase completes - - call the `UpdateKeys` function again - - Loop background to the beginning +- check if the button has JUST been pressed +- If not: + - Wait until the next vertical blank phase completes + - call the `UpdateKeys` function again + - Loop background to the beginning :::tip @@ -456,12 +457,12 @@ CHARMAP "z", 51 The above character mapping would convert (by the compiler) our `wScoreText` text to: -- s => 44 -- c => 28 -- o => 40 -- r => 43 -- e => 30 -- 255 +- s => 44 +- c => 28 +- o => 40 +- r => 43 +- e => 30 +- 255 With that setup, we would loop though the bytes of `wScoreText` and copy each byte to the background/window layer. After we copy each byte, we'll increment where we will copy to, and which byte in `wScoreText` we are reading. When we read 255, our code will end. @@ -501,9 +502,9 @@ DrawTextTilesLoop:: ### Draw a bottom HUD -- Enable the window (with a different tilemap than the background) -- Move the window downwards, so only 1 or 2 rows show at the bottom of the screen -- Draw your text, score, and icons on the top of the window layer. +- Enable the window (with a different tilemap than the background) +- Move the window downwards, so only 1 or 2 rows show at the bottom of the screen +- Draw your text, score, and icons on the top of the window layer. :::tip @@ -540,10 +541,10 @@ CopySpriteTileDataIntoVram_Loop: Each hardware sprite has 4 bytes: (in this order) -- Y position -- X Position -- Tile ID -- Flags/Props (priority, y flip, x flip, palette 0 [DMG], palette 1 [DMG], bank 0 [GBC], bank 1 [GBC]) +- Y position +- X Position +- Tile ID +- Flags/Props (priority, y flip, x flip, palette 0 [DMG], palette 1 [DMG], bank 0 [GBC], bank 1 [GBC]) Check out the Pan Docs page on [Object Attribute Memory (OAM)](https://gbdev.io/pandocs/OAM.html) for more info. @@ -644,8 +645,8 @@ ld [wShadowOAM], a If you want to save data in your game, your game's header needs to specify the correct MBC/cartridge type, and it needs to have a non-zero SRAM size. This should be done in your makefile by passing special parameters to [rgbfix](https://rgbds.gbdev.io/docs/rgbfix.1). -- Use the `-m` or `--mbc-type` parameters to set the mbc/cartidge type, 0x147, to a given value from 0 to 0xFF. [More Info](https://gbdev.io/pandocs/The_Cartridge_Header.html#0147--cartridge-type) -- Use the `-r` or `--ram-size` parameters to set the RAM size, 0x149, to a given value from 0 to 0xFF. [More Info](https://gbdev.io/pandocs/The_Cartridge_Header.html#0149--ram-size). +- Use the `-m` or `--mbc-type` parameters to set the mbc/cartidge type, 0x147, to a given value from 0 to 0xFF. [More Info](https://gbdev.io/pandocs/The_Cartridge_Header.html#0147--cartridge-type) +- Use the `-r` or `--ram-size` parameters to set the RAM size, 0x149, to a given value from 0 to 0xFF. [More Info](https://gbdev.io/pandocs/The_Cartridge_Header.html#0149--ram-size). To save data you need to store variables in Static RAM. This is done by creating a new SRAM "SECTION". [More Info](https://rgbds.gbdev.io/docs/rgbasm.5#SECTIONS) @@ -693,10 +694,10 @@ wCheckSum3:: db When initializing your save data, you'll need to -- enable SRAM access -- set your checksum bytes -- give your other variables default values -- disable SRAM access +- enable SRAM access +- set your checksum bytes +- give your other variables default values +- disable SRAM access ```rgbasm, linenos diff --git a/src/part2/bcd.md b/src/part2/bcd.md index 9c0cdfd2..7d19f931 100644 --- a/src/part2/bcd.md +++ b/src/part2/bcd.md @@ -1,5 +1,7 @@ # Decimal Numbers +{{#use_commit ../../unbricked@"Lesson 7: Decimal Numbers"}} + Now that we can make the bricks disappear on impact, we should probably get some reward, like points! We'll start off with a score of 0 and then increase the score by 1 point each time a brick gets destroyed. Then we can display the score on a scoreboard. @@ -20,21 +22,21 @@ For example the number 35 (my favorite Pokémon) contains the number 3 `%0011` a Now let's start by defining a global variable (memory location) for the score: -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/bcd/main.asm:score-variable}} -{{#include ../../unbricked/bcd/main.asm:score-variable}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:score-variable}} +{{#include_git main.asm:score-variable}} ``` And we'll set this to zero when initializing the other global variables. -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/bcd/main.asm:init-variables}} -{{#include ../../unbricked/bcd/main.asm:init-variables}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:init-variables}} +{{#include_git main.asm:init-variables}} ``` Now we'll write a function to increase the score, right behind the `IsWallTile` function. Don't worry about the call to `UpdateScoreBoard`, we'll get into that in a bit. -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/bcd/main.asm:increase-score}} -{{#include ../../unbricked/bcd/main.asm:increase-score}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:increase-score}} +{{#include_git main.asm:increase-score}} ``` Let's have a look at what's going on there: @@ -52,26 +54,26 @@ Then we store the score back into `wScore` and finally, we call a function that Of course, we still need to call it on impact. To do this, we add a call to `IncreaseScorePackedBCD` after each collision handler (we had a left and a right collision) in `CheckAndHandleBrick` -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/bcd/main.asm:check-for-brick}} -{{#include ../../unbricked/bcd/main.asm:check-for-brick}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:check-for-brick}} +{{#include_git main.asm:check-for-brick}} ``` ## Digit tiles -Before we can display the score we'll need to add some graphics for the numbers 0-9. We already have some ready-made digits for this project, so you can copy [this premade file](https://github.com/gbdev/gb-asm-tutorial/raw/master/unbricked/bcd/digit-tileset.asm), and paste it at the end of your tile set, just before the `TilesEnd` label. Your tile set will look like this: +Before we can display the score we'll need to add some graphics for the numbers 0-9. We already have some ready-made digits for this project, so you can copy [this premade file](digit-tileset.asm), and paste it at the end of your tile set, just before the `TilesEnd` label. Your tile set will look like this: ![Screenshot of tile set with digits added at the end](../assets/part2/img/bcd-tileset.png) So we can easily remember where the digits start, let's add a constant called `DIGIT_OFFSET` to point us to where the digits are relative to the start of the tile set: `$1A` -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/bcd/main.asm:digit-offset}} -{{#include ../../unbricked/bcd/main.asm:digit-offset}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:digit-offset}} +{{#include_git main.asm:digit-offset}} ``` Let's make an assumption, that we cannot get a score higher than 99 ([what could possibly go wrong](https://en.wikipedia.org/wiki/Year_2000_problem)) so two digits are enough. We can start with showing two zeroes (the tile at offset `$1A`) on our initial map. Let's put them on row 3, starting 4 tiles to the left. -You can copy-paste the tile set from [this file](https://github.com/gbdev/gb-asm-tutorial/raw/master/unbricked/bcd/tilemap.asm) +You can copy-paste the tile set from [this file](digit-tilemap.asm) This should make the tile set look like this on start up: @@ -82,15 +84,16 @@ This should make the tile set look like this on start up: Let's remember their positions by defining a constant for VRAM location of the 10s and the 1s at the top of our file, behind the other constants. -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/bcd/main.asm:score-tile-location}} -{{#include ../../unbricked/bcd/main.asm:score-tile-location}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:score-tile-location}} +{{#include_git main.asm:score-tile-location}} ``` + ## Displaying the score Now we need to write the missing `UpdateScoreBoard` function that will update the score board: -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/bcd/main.asm:update-score-board}} -{{#include ../../unbricked/bcd/main.asm:update-score-board}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:update-score-board}} +{{#include_git main.asm:update-score-board}} ``` First we load the score (stored in the wScore memory location) into register A. Recall that the score is stored in packed BCD format, where the upper nibble contains the tens digit and the lower nibble contains the ones digit. @@ -103,4 +106,4 @@ We then add the `DIGIT_OFFSET` constant to the tens digit to calculate the tile Finally, we repeat the process for the ones digit: We mask the tens digit from `A` using `and %00001111`, no need to rotate this time. -Now we can display the score on the screen! We'll need to call `UpdateScoreBoard` after each time the score is updated. We've already done this in the `IncreaseScorePackedBCD` function, so we're all set! \ No newline at end of file +Now we can display the score on the screen! We'll need to call `UpdateScoreBoard` after each time the score is updated. We've already done this in the `IncreaseScorePackedBCD` function, so we're all set! diff --git a/src/part2/bricks.md b/src/part2/bricks.md index e0e4b9a0..d24c3640 100644 --- a/src/part2/bricks.md +++ b/src/part2/bricks.md @@ -1,15 +1,18 @@ # Bricks +{{#use_commit ../../unbricked@"Lesson 6: Bricks"}} + Up until this point our ball hasn't done anything but bounce around, but now we're going to make it destroy the bricks. Before we start, let's go over a new concept: constants. We've already used some constants, like `rLCDC` from `hardware.inc`, but we can also create our own for anything we want. Let's make three constants at the top of our file, representing the tile IDs of left bricks, right bricks, and blank tiles. -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/bricks/main.asm:constants}} -{{#include ../../unbricked/bricks/main.asm:constants}} + +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:constants}} +{{#include_git main.asm:constants}} ``` -Constants are a kind of *symbol* (which is to say, "a thing with a name"). +Constants are a kind of _symbol_ (which is to say, "a thing with a name"). Writing a constant's name in an expression is equivalent to writing the number the constant is equal to, so `ld a, BRICK_LEFT` is the same as `ld a, $05`. But I think we can all agree that the former is much clearer, right? @@ -20,15 +23,15 @@ Our bricks are two tiles wide, so when we hit one we'll have to remove the adjac If we hit the left side of a brick (represented by `BRICK_LEFT`), we need to remove it and the tile to its right (which should be the right side). If we instead hit the right side, we need to remove the left! -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/bricks/main.asm:check-for-brick}} -{{#include ../../unbricked/bricks/main.asm:check-for-brick}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:check-for-brick}} +{{#include_git main.asm:check-for-brick}} ``` Just insert this function into each of your bounce checks now. Make sure you don't miss any! It should go right **before** the momentum is modified. -```diff,linenos,start={{#line_no_of "" ../../unbricked/bricks/main.asm:updated-bounce}} +```diff,linenos,start={{#line_no_of "" @GIT@/main.asm:updated-bounce}} BounceOnTop: ; Remember to offset the OAM position! ; (8, 16) in OAM coordinates is (0, 0) on the screen. diff --git a/src/part2/collision.md b/src/part2/collision.md index e53c8465..7ccf5cf5 100644 --- a/src/part2/collision.md +++ b/src/part2/collision.md @@ -1,35 +1,42 @@ # Collision +{{#use_commit ../../unbricked@"Lesson 5: Collision"}} + Being able to move around is great, but there's still one object we need for this game: a ball! Just like with the paddle, the first step is to create a tile for the ball and load it into VRAM. ## Graphics Add this to the bottom of your file along with the other graphics: -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/collision/main.asm:ball-sprite}} -{{#include ../../unbricked/collision/main.asm:ball-sprite}} + +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:ball-sprite}} +{{#include_git main.asm:ball-sprite}} ``` Now copy it to VRAM somewhere in your initialization code, e.g. after copying the paddle's tile. -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/collision/main.asm:ball-copy}} -{{#include ../../unbricked/collision/main.asm:ball-copy}} + +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:ball-copy}} +{{#include_git main.asm:ball-copy}} ``` In addition, we need to initialize an entry in OAM, following the code that initializes the paddle. -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/collision/main.asm:oam}} -{{#include ../../unbricked/collision/main.asm:oam}} + +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:oam}} +{{#include_git main.asm:oam}} ``` As the ball bounces around the screen its momentum will change, sending it in different directions. Let's create two new variables to track the ball's momentum in each axis: `wBallMomentumX` and `wBallMomentumY`. -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/collision/main.asm:ram}} -{{#include ../../unbricked/collision/main.asm:ram}} + +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:ram}} +{{#include_git main.asm:ram}} ``` We will need to initialize these before entering the game loop, so let's do so right after we write the ball to OAM. By setting the X momentum to 1, and the Y momentum to -1, the ball will start out by going up and to the right. -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/collision/main.asm:init}} -{{#include ../../unbricked/collision/main.asm:init}} + +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:init}} +{{#include_git main.asm:init}} ``` ## Prep work @@ -39,8 +46,9 @@ Add a bit of code at the beginning of your main loop that adds the momentum to t Notice that since this is the second OAM entry, we use `+ 4` for Y and `+ 5` for X. This can get pretty confusing, but luckily we only have two objects to keep track of. In the future, we'll go over a much easier way to use OAM. -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/collision/main.asm:momentum}} -{{#include ../../unbricked/collision/main.asm:momentum}} + +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:momentum}} +{{#include_git main.asm:momentum}} ``` You might want to compile your game again to see what this does. @@ -57,17 +65,18 @@ This way, we can check which tile our ball is touching so that we know when to b ::: -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/collision/main.asm:get-tile}} -{{#include ../../unbricked/collision/main.asm:get-tile}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:get-tile}} +{{#include_git main.asm:get-tile}} ``` The next function is called `IsWallTile`, and it's going to contain a list of tiles which the ball can bounce off of. -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/collision/main.asm:is-wall-tile}} -{{#include ../../unbricked/collision/main.asm:is-wall-tile}} + +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:is-wall-tile}} +{{#include_git main.asm:is-wall-tile}} ``` This function might look a bit strange at first. -Instead of returning its result in a *register*, like `a`, it returns it in [a *flag*](../part1/operations.md#flags): `Z`! +Instead of returning its result in a _register_, like `a`, it returns it in [a _flag_](../part1/operations.md#flags): `Z`! If at any point a tile matches, the function has found a wall and exits with `Z` set. If the target tile ID (in `a`) matches one of the wall tile IDs, the corresponding `cp` will leave `Z` set; if so, we return immediately (via `ret z`), with `Z` set. But if we reach the last comparison and it still doesn't set `Z`, then we will know that we haven't hit a wall and don't need to bounce. @@ -76,8 +85,9 @@ But if we reach the last comparison and it still doesn't set `Z`, then we will k Time to use these new functions to add collision detection! Add the following after the code that updates the ball's position: -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/collision/main.asm:first-tile-collision}} -{{#include ../../unbricked/collision/main.asm:first-tile-collision}} + +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:first-tile-collision}} +{{#include_git main.asm:first-tile-collision}} ``` You'll see that when we load the sprite's positions, we subtract from them before calling `GetTileByPixel`. @@ -86,10 +96,10 @@ These `sub` instructions undo this offset. However, there's a bit more to this: you might have noticed that we subtracted an extra pixel from the Y position. That's because (as the label suggests), this code is checking for a tile above the ball. -We actually need to check *all four* sides of the ball so we know how to change the momentum according to which side collided, so... let's add the rest! +We actually need to check _all four_ sides of the ball so we know how to change the momentum according to which side collided, so... let's add the rest! -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/collision/main.asm:tile-collision}} -{{#include ../../unbricked/collision/main.asm:tile-collision}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:tile-collision}} +{{#include_git main.asm:tile-collision}} ``` That was a lot, but now the ball bounces around your screen! @@ -98,7 +108,7 @@ There's just one last thing to do before this chapter is over, and thats ball-to ## Paddle bounce Unlike with the tilemap, there's no position conversions to do here, just straight comparisons. -However, for these, we will need [the *carry* flag](../part1/operations.md#flags). +However, for these, we will need [the _carry_ flag](../part1/operations.md#flags). The carry flag is notated as `C`, like how the zero flag is notated as `Z`, but don't confuse it with the `c` register! :::tip A refresher on comparisons @@ -111,8 +121,9 @@ For example, `cp a, b` sets `C` if `a < b`, and clears it if `a >= b`. ::: Armed with this knowledge, let's work through the paddle bounce code: -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/collision/main.asm:paddle-bounce}} -{{#include ../../unbricked/collision/main.asm:paddle-bounce}} + +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:paddle-bounce}} +{{#include_git main.asm:paddle-bounce}} ``` The Y position's check is simple, since our paddle is flat. @@ -212,7 +223,7 @@ Then we undo this by subtracting 16, and while we're at it, subtract another 8 p :::tip Paddle width You might be wondering why we checked 16 pixels to the right but only 8 pixels to the left. -Remember that OAM positions represent the upper-*left* corner of a sprite, so the center of our paddle is actually 4 pixels to the right of the position in OAM. +Remember that OAM positions represent the upper-_left_ corner of a sprite, so the center of our paddle is actually 4 pixels to the right of the position in OAM. When you consider this, we're actually checking 12 pixels out on either side from the center of the paddle. 12 pixels might seem like a lot, but it gives some tolerance to the player in case their positioning is off. @@ -228,7 +239,7 @@ Hint: you can do this with just a single instruction!
Answer: -```diff linenos,start={{#line_no_of "" ../../unbricked/collision/main.asm:paddle-bounce}} +```diff linenos,start={{#line_no_of "" @GIT@/main.asm:paddle-bounce}} ld a, [_OAMRAM] ld b, a ld a, [_OAMRAM + 4] diff --git a/unbricked/bcd/tilemap.asm b/src/part2/digit-tilemap.asm similarity index 100% rename from unbricked/bcd/tilemap.asm rename to src/part2/digit-tilemap.asm diff --git a/unbricked/bcd/digit-tileset.asm b/src/part2/digit-tileset.asm similarity index 100% rename from unbricked/bcd/digit-tileset.asm rename to src/part2/digit-tileset.asm diff --git a/unbricked/getting-started/duck.asm b/src/part2/duck.asm similarity index 100% rename from unbricked/getting-started/duck.asm rename to src/part2/duck.asm diff --git a/src/part2/functions.md b/src/part2/functions.md index 846ea649..1285401a 100644 --- a/src/part2/functions.md +++ b/src/part2/functions.md @@ -1,17 +1,19 @@ # Functions +{{#use_commit ../../unbricked@"Lesson 3: 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}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:memcpy}} +{{#include_git 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. +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. @@ -26,38 +28,50 @@ The registers serve as parameters to the function, so we'll leave them as-is.
BeforeAfter
-```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/getting-started/main.asm:copy_tiles}} -{{#include ../../unbricked/getting-started/main.asm:copy_tiles}} +{{#use_commit ../../unbricked@"Lesson 1: Getting Started"}} + +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:copy_tiles}} +{{#include_git main.asm:copy_tiles}} ``` -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/functions/main.asm:copy_tiles}} -{{#include ../../unbricked/functions/main.asm:copy_tiles}} +{{#use_commit ../../unbricked@"Lesson 3: Functions"}} + +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:copy_tiles}} +{{#include_git main.asm:copy_tiles}} ```
-```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/getting-started/main.asm:copy_map}} -{{#include ../../unbricked/getting-started/main.asm:copy_map}} +{{#use_commit ../../unbricked@"Lesson 1: Getting Started"}} + +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:copy_map}} +{{#include_git main.asm:copy_map}} ``` -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/functions/main.asm:copy_map}} -{{#include ../../unbricked/functions/main.asm:copy_map}} +{{#use_commit ../../unbricked@"Lesson 3: Functions"}} + +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:copy_map}} +{{#include_git main.asm:copy_map}} ```
-```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/objects/main.asm:copy-paddle}} -{{#include ../../unbricked/objects/main.asm:copy-paddle}} +{{#use_commit ../../unbricked@"Lesson 2: Objects"}} + +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:copy-paddle}} +{{#include_git main.asm:copy-paddle}} ``` -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/functions/main.asm:copy_paddle}} -{{#include ../../unbricked/functions/main.asm:copy_paddle}} +{{#use_commit ../../unbricked@"Lesson 3: Functions"}} + +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:copy_paddle}} +{{#include_git main.asm:copy_paddle}} ```
diff --git a/src/part2/getting-started.md b/src/part2/getting-started.md index d0f7c1d1..63e3bb36 100644 --- a/src/part2/getting-started.md +++ b/src/part2/getting-started.md @@ -1,21 +1,24 @@ # Getting started +{{#use_commit ../../unbricked@"Lesson 1: Getting Started"}} + In this lesson, we will start a new project from scratch. We will make a [Breakout](https://en.wikipedia.org/wiki/Breakout_%28video_game%29) / [Arkanoid](https://en.wikipedia.org/wiki/Arkanoid) clone, which we'll call "Unbricked"! -(Though you are free to give it any other name you like, as it will be *your* project.) +(Though you are free to give it any other name you like, as it will be _your_ project.) Open a terminal and make a new directory (`mkdir unbricked`), and then enter it (`cd unbricked`), just like you did for ["Hello, world!"](../part1/hello_world.md). Start by creating a file called `main.asm`, and include `hardware.inc` in your code. -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/getting-started/main.asm:includes}} -{{#include ../../unbricked/getting-started/main.asm:includes}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:includes}} +{{#include_git main.asm:includes}} ``` + You may be wondering what purpose `hardware.inc` serves. Well, the code we write only really affects the CPU, but does not do anything with the rest of the console (not directly, anyway). To interact with other components (like the graphics system, say), [Memory-Mapped I/O](https://en.wikipedia.org/wiki/Memory-mapped_I/O) (MMIO) is used: basically, [memory](../part1/memory.md) in a certain range (addresses $FF00–FF7F) does special things when accessed. -These bytes of memory being interfaces to the hardware, they are called *hardware registers* (not to be mistaken with [the CPU registers](../part1/registers.md)). +These bytes of memory being interfaces to the hardware, they are called _hardware registers_ (not to be mistaken with [the CPU registers](../part1/registers.md)). For example, the "PPU status" register is located at address $FF41. Reading from that address reports various bits of info regarding the graphics system, and writing to it allows changing some parameters. But, having to remember all the numbers ([non-exhaustive list](https://gbdev.io/pandocs/Power_Up_Sequence.html#hardware-registers)) would be very tedious—and this is where `hardware.inc` comes into play! @@ -32,14 +35,14 @@ By the way, the `r` stands for "register", and the `F` in `LCDCF` stands for "fl Next, make room for the header. [Remember from Part Ⅰ](../part1/header.md) that the header is where some information that the Game Boy relies on is stored, so you don't want to accidentally leave it out. -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/getting-started/main.asm:header}} -{{#include ../../unbricked/getting-started/main.asm:header}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:header}} +{{#include_git main.asm:header}} ``` The header jumps to `EntryPoint`, so let's write that now: -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/getting-started/main.asm:entry}} -{{#include ../../unbricked/getting-started/main.asm:entry}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:entry}} +{{#include_git main.asm:entry}} ``` The next few lines wait until "VBlank", which is the only time you can safely turn off the screen (doing so at the wrong time could damage a real Game Boy, so this is very crucial). @@ -49,8 +52,8 @@ Turning off the screen is important because loading new tiles while the screen i Speaking of tiles, we're going to load some into VRAM next, using the following code: -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/getting-started/main.asm:copy_tiles}} -{{#include ../../unbricked/getting-started/main.asm:copy_tiles}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:copy_tiles}} +{{#include_git main.asm:copy_tiles}} ``` This loop might be [reminiscent of part Ⅰ](../part1/jumps.md#conditional-jumps). @@ -63,8 +66,8 @@ We'll get to that later! Almost done now—next, write another loop, this time for copying [the tilemap](../part1/tilemap.md). -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/getting-started/main.asm:copy_map}} -{{#include ../../unbricked/getting-started/main.asm:copy_map}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:copy_map}} +{{#include_git main.asm:copy_map}} ``` Note that while this loop's body is exactly the same as `CopyTiles`'s, the 3 values loaded into `de`, `hl`, and `bc` are different. @@ -72,7 +75,7 @@ These determine the source, destination, and size of the copy, respectively. :::tip "Don't Repeat Yourself" -If you think that this is super redundant, you are not wrong, and we will see later how to write actual, reusable *functions*. +If you think that this is super redundant, you are not wrong, and we will see later how to write actual, reusable _functions_. But there is more to them than meets the eye, so we will start tackling them much later. ::: @@ -81,10 +84,10 @@ Finally, let's turn the screen back on, and set a [background palette](../part1/ Rather than writing the non-descript number `%10000001` (or $81 or 129, to taste), we make use of two constants graciously provided by `hardware.inc`: `LCDCF_ON` and `LCDCF_BGON`. When written to [`rLCDC`](https://gbdev.io/pandocs/LCDC), the former causes the PPU and screen to turn back on, and the latter enables the background to be drawn. (There are other elements that could be drawn, but we are not enabling them yet.) -Combining these constants must be done using `|`, the *binary "or"* operator; we'll see why later. +Combining these constants must be done using `|`, the _binary "or"_ operator; we'll see why later. -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/getting-started/main.asm:end}} -{{#include ../../unbricked/getting-started/main.asm:end}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:end}} +{{#include_git main.asm:end}} ``` There's one last thing we need before we can build the ROM, and that's the graphics. @@ -92,7 +95,7 @@ We will draw the following screen: ![Layout of unbricked](../assets/part2/img/tilemap.png) -In `hello-world.asm`, tile data had been written out by hand in hexadecimal; this was to let you see how the sausage is made at the lowest level, but *boy* is it impractical to write! +In `hello-world.asm`, tile data had been written out by hand in hexadecimal; this was to let you see how the sausage is made at the lowest level, but _boy_ is it impractical to write! This time, we will employ a more friendly way, which will let us write each row of pixels more easily. For each row of pixels, instead of writing [the bitplanes](../part1/tiles.md#encoding) directly, we will use a backtick (`` ` ``) followed by 8 characters. Each character defines a single pixel, intuitively from left to right; it must be one of 0, 1, 2, and 3, representing the corresponding color index in [the palette](../part1/palettes.md). @@ -111,9 +114,9 @@ For example: ``` You may have noticed that we are using `dw` instead of `db`; the difference between these two will be explained later. -We already have tiles made for this project, so you can copy [this premade file](https://github.com/gbdev/gb-asm-tutorial/raw/master/unbricked/getting-started/tileset.asm), and paste it at the end of your code. +We already have tiles made for this project, so you can copy [this premade file](tileset.asm), and paste it at the end of your code. -Then copy the tilemap from [this file](https://github.com/gbdev/gb-asm-tutorial/raw/master/unbricked/getting-started/tilemap.asm), and paste it after the `TilesEnd` label. +Then copy the tilemap from [this file](tilemap.asm), and paste it after the `TilesEnd` label. You can build the ROM now, by running the following commands in your terminal: @@ -130,8 +133,8 @@ If you run this in your emulator, you should see the following: That white square seems to be missing! You may have noticed this comment earlier, somewhere in the tile data: -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/getting-started/main.asm:custom_logo}} -{{#include ../../unbricked/getting-started/main.asm:custom_logo}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:custom_logo}} +{{#include_git main.asm:custom_logo}} ``` The logo tiles were left intentionally blank so that you can choose your own. @@ -141,18 +144,18 @@ You can use one of the following pre-made logos, or try coming up with your own! ![The RGBDS Logo](../assets/part2/img/rgbds.png) - [Source](https://github.com/gbdev/gb-asm-tutorial/raw/master/unbricked/getting-started/rgbds.asm) + [Source](rgbds.asm) - **Duck** ![A pixel-art duck](../assets/part2/img/duck.png) - [Source](https://github.com/gbdev/gb-asm-tutorial/raw/master/unbricked/getting-started/duck.asm) + [Source](duck.asm) - **Tail** ![A silhouette of a tail](../assets/part2/img/tail.png) - [Source](https://github.com/gbdev/gb-asm-tutorial/raw/master/unbricked/getting-started/tail.asm) + [Source](tail.asm) Add your chosen logo's data (click one of the "Source" links above) after the comment, build the game again, and you should see your logo of choice in the bottom-right! diff --git a/src/part2/input.md b/src/part2/input.md index f99074ce..c3ceccdc 100644 --- a/src/part2/input.md +++ b/src/part2/input.md @@ -1,17 +1,19 @@ # Input +{{#use_commit ../../unbricked@"Lesson 4: 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}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:input-routine}} +{{#include_git main.asm:input-routine}} ``` 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. +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. @@ -22,25 +24,25 @@ This is important, because not only is it faster to reload the inputs that we've First, let's set aside some room for the two variables that `UpdateKeys` will use; paste this at the end of the `main.asm`: -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/input/main.asm:vars}} -{{#include ../../unbricked/input/main.asm:vars}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:vars}} +{{#include_git main.asm:vars}} ``` Each variable must reside in RAM, and not ROM, because ROM is "Read-Only" (so you can't modify it). Additionally, each variable only needs to be one byte large, so we use `db` ("Define Byte") to reserve one byte of RAM for each. Before we read these variables we will also want to initialize them. -We can do that below our initialization of `wFrameCounter`. +We can do that below our initialization of `wFrameCounter`. -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/input/main.asm:initialize-vars}} -{{#include ../../unbricked/input/main.asm:initialize-vars}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:initialize-vars}} +{{#include_git main.asm:initialize-vars}} ``` 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}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:main}} +{{#include_git main.asm:main}} ``` Now, if you compile the project, you should be able to move the paddle left and right using the d-pad!! diff --git a/src/part2/objects.md b/src/part2/objects.md index ef79450c..53028bea 100644 --- a/src/part2/objects.md +++ b/src/part2/objects.md @@ -1,14 +1,16 @@ # Objects +{{#use_commit ../../unbricked@"Lesson 2: Objects"}} + The background is very useful when the whole screen should move at once, but this is not ideal for everything. -For example, a cursor in a menu, NPCs and the player in a RPG, bullets in a shmup, or balls in an *Arkanoid* clone... all need to move independently of the background. +For example, a cursor in a menu, NPCs and the player in a RPG, bullets in a shmup, or balls in an _Arkanoid_ clone... all need to move independently of the background. Thankfully, the Game Boy has a feature that's perfect for these! -In this lesson, we will talk about *objects* (sometimes called "OBJ"). +In this lesson, we will talk about _objects_ (sometimes called "OBJ"). :::tip The above description may have made you think of the term "sprite" instead of "object". -The term "sprite" has a *lot* of meanings depending on context, so, to avoid confusion, this tutorial tries to use specific alternatives instead, such as *object*, *metasprite*, *actor*, etc. +The term "sprite" has a _lot_ of meanings depending on context, so, to avoid confusion, this tutorial tries to use specific alternatives instead, such as _object_, _metasprite_, _actor_, etc. ::: @@ -19,6 +21,7 @@ We'll see more about them later. Just like how the tilemap is stored in VRAM, objects live in a region of memory called OAM, meaning **Object Attribute Memory**. Recall from above that an object consists of: + - Its on-screen position - A tile ID - The "attributes" @@ -26,8 +29,8 @@ Recall from above that an object consists of: These are stored in 4 bytes: one for the Y coordinate, one for the X coordinate, one for the tile ID, and one for the attributes. OAM is 160 bytes long, and since 160 ∕ 4 = 40, the Game Boy stores a total of **40** objects at any given time. -There is a catch, though: an object's Y and X coordinate bytes in OAM do *not* store its on-screen position! -Instead, the *on-screen* X position is the *stored* X position **minus 8**, and the *on-screen* Y position is the *stored* Y position **minus 16**. +There is a catch, though: an object's Y and X coordinate bytes in OAM do _not_ store its on-screen position! +Instead, the _on-screen_ X position is the _stored_ X position **minus 8**, and the _on-screen_ Y position is the _stored_ Y position **minus 16**. To stop displaying an object, we can simply put it off-screen, e.g. by setting its Y position to 0. :::tip @@ -45,16 +48,16 @@ First off, when the Game Boy is powered on, OAM is filled with a bunch of semi-r Let's fix that by first clearing OAM before enabling objects for the first time. Let's add the following just after the `CopyTilemap` loop: -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/objects/main.asm:clear-oam}} -{{#include ../../unbricked/objects/main.asm:clear-oam}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:clear-oam}} +{{#include_git main.asm:clear-oam}} ``` This is a good time to do that, since just like VRAM, the screen must be off to safely access OAM. Once OAM is clear, we can draw an object by writing its properties. -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/objects/main.asm:init-object}} -{{#include ../../unbricked/objects/main.asm:init-object}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:init-object}} +{{#include_git main.asm:init-object}} ``` Remember that each object in OAM is 4 bytes, in the order Y, X, Tile ID, Attributes. @@ -72,14 +75,14 @@ If you go to "Tools", then "Tile Viewer" in Emulicious' debugger, you should see Because we need to load this to a different area, we'll use the address $8000 and load a graphic for our game's paddle. Let's do so right after `CopyTilemap`: -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/objects/main.asm:copy-paddle}} -{{#include ../../unbricked/objects/main.asm:copy-paddle}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:copy-paddle}} +{{#include_git main.asm:copy-paddle}} ``` And don't forget to add `Paddle` to the bottom of your code. ```rgbasm -{{#include ../../unbricked/objects/main.asm:paddle-gfx}} +{{#include_git main.asm:paddle-gfx}} ``` Finally, let's enable objects and see the result. @@ -88,8 +91,8 @@ Objects must be enabled by the familiar `rLCDC` register, otherwise they just do We will also need to initialize one of the object palettes, `rOBP0`. There are actually two object palettes, but we're only going to use one. -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/objects/main.asm:enable-oam}} -{{#include ../../unbricked/objects/main.asm:enable-oam}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:enable-oam}} +{{#include_git main.asm:enable-oam}} ``` ## Movement @@ -98,7 +101,7 @@ Now that you have an object on the screen, let's move it around. Previously, the `Done` loop did nothing; let's rename it to `Main` and use it to move our object. We're going to wait for VBlank before changing OAM, just like we did before turning off the screen. -```rgbasm,linenos,start={{#line_no_of "^Main:" ../../unbricked/objects/main.asm}} +```rgbasm,linenos,start={{#line_no_of "^Main:" @GIT@/main.asm}} Main: ; Wait until it's *not* VBlank ld a, [rLY] @@ -125,7 +128,7 @@ Explaining why requires a more thorough explanation of the Game Boy's rendering, Now you should see the paddle moving... very quickly. Because it moves by a pixel every frame, it's going at a speed of 60 pixels per second! -To slow this down, we'll use a *variable*. +To slow this down, we'll use a _variable_. So far, we have only worked with the CPU registers, but you can create global variables too! To do this, let's create another section, but putting it in `WRAM0` instead of `ROM0`. @@ -133,16 +136,16 @@ Unlike ROM ("Read-Only Memory"), RAM ("Random-Access Memory") can be written to; Add this to the bottom of your file: -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/objects/main.asm:variables}} -{{#include ../../unbricked/objects/main.asm:variables}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:variables}} +{{#include_git main.asm:variables}} ``` Now we'll use the `wFrameCounter` variable to count how many frames have passed since we last moved the paddle. Every 15th frame, we'll move the paddle by one pixel, slowing it down to 4 pixels per second. Don't forget that RAM is filled with garbage values when the Game Boy starts, so we need to initialize our variables before first using them. -```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/objects/main.asm:main-loop}} -{{#include ../../unbricked/objects/main.asm:main-loop}} +```rgbasm,linenos,start={{#line_no_of "" @GIT@/main.asm:main-loop}} +{{#include_git main.asm:main-loop}} ``` Alright! diff --git a/unbricked/getting-started/rgbds.asm b/src/part2/rgbds.asm similarity index 100% rename from unbricked/getting-started/rgbds.asm rename to src/part2/rgbds.asm diff --git a/unbricked/getting-started/tail.asm b/src/part2/tail.asm similarity index 100% rename from unbricked/getting-started/tail.asm rename to src/part2/tail.asm diff --git a/unbricked/getting-started/tilemap.asm b/src/part2/tilemap.asm similarity index 100% rename from unbricked/getting-started/tilemap.asm rename to src/part2/tilemap.asm diff --git a/unbricked/getting-started/tileset.asm b/src/part2/tileset.asm similarity index 100% rename from unbricked/getting-started/tileset.asm rename to src/part2/tileset.asm diff --git a/unbricked b/unbricked new file mode 160000 index 00000000..31950268 --- /dev/null +++ b/unbricked @@ -0,0 +1 @@ +Subproject commit 31950268e184c1f7a9480704a7c2a7d80f1b6596 diff --git a/unbricked/2bpp2asm.c b/unbricked/2bpp2asm.c deleted file mode 100644 index bbf9fb10..00000000 --- a/unbricked/2bpp2asm.c +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#include - -int main(int argc, char ** argv) { - if (argc != 4) { - fprintf(stderr, "Expected 4 arguments\nUsage: %s ", argv[0]); - exit(1); - } - - FILE * infile = fopen(argv[2], "rb"); - FILE * outfile = fopen(argv[3], "w"); - - if (!infile) { - perror("infile"); - exit(1); - } - - if (!outfile) { - perror("outfile"); - exit(1); - } - - char * pixels = argv[1]; - - while (1) { - uint8_t light_row = fgetc(infile); - uint8_t dark_row = fgetc(infile); - if (feof(infile)) break; - fputs("\tdw `", outfile); - for (int i = 0; i < 8; i++) { - uint8_t shade = (light_row & 0x80) >> 7 | (dark_row & 0x80) >> 6; - fputc(pixels[shade], outfile); - light_row <<= 1; - dark_row <<= 1; - } - fputc('\n', outfile); - } -} \ No newline at end of file diff --git a/unbricked/audio/main.asm b/unbricked/audio/main.asm deleted file mode 100644 index 784f5de3..00000000 --- a/unbricked/audio/main.asm +++ /dev/null @@ -1,654 +0,0 @@ -; ANCHOR: constants -INCLUDE "hardware.inc" - -DEF BRICK_LEFT EQU $05 -DEF BRICK_RIGHT EQU $06 -DEF BLANK_TILE EQU $08 -; ANCHOR_END: constants - -SECTION "Header", ROM0[$100] - - jp EntryPoint - - ds $150 - @, 0 ; Make room for the header - -EntryPoint: - ; Do not turn the LCD off outside of VBlank -WaitVBlank: - ld a, [rLY] - cp 144 - jp c, WaitVBlank - - ; Turn the LCD off - ld a, 0 - ld [rLCDC], a - - ; Copy the tile data - ld de, Tiles - ld hl, $9000 - ld bc, TilesEnd - Tiles - call Memcopy - - ; Copy the tilemap - ld de, Tilemap - ld hl, $9800 - ld bc, TilemapEnd - Tilemap - call Memcopy - - ; Copy the paddle tile - ld de, Paddle - ld hl, $8000 - ld bc, PaddleEnd - Paddle - call Memcopy - - ; Copy the ball tile - ld de, Ball - ld hl, $8010 - ld bc, BallEnd - Ball - call Memcopy - - xor a, a - ld b, 160 - ld hl, _OAMRAM -ClearOam: - ld [hli], a - dec b - jp nz, ClearOam - - ; Initialize the paddle sprite in OAM - ld hl, _OAMRAM - ld a, 128 + 16 - ld [hli], a - ld a, 16 + 8 - ld [hli], a - ld a, 0 - ld [hli], a - ld [hli], a - ; Now initialize the ball sprite - ld a, 100 + 16 - ld [hli], a - ld a, 32 + 8 - ld [hli], a - ld a, 1 - ld [hli], a - ld a, 0 - ld [hli], a - - ; The ball starts out going up and to the right - ld a, 1 - ld [wBallMomentumX], a - ld a, -1 - ld [wBallMomentumY], a - - ; Turn the LCD on - ld a, LCDCF_ON | LCDCF_BGON | LCDCF_OBJON - ld [rLCDC], a - - ; During the first (blank) frame, initialize display registers - ld a, %11100100 - ld [rBGP], a - ld a, %11100100 - ld [rOBP0], a - - ld a, 0 - ld [wFrameCounter], a - -Main: - ld a, [rLY] - cp 144 - jp nc, Main -WaitVBlank2: - ld a, [rLY] - cp 144 - jp c, WaitVBlank2 - - ; Add the ball's momentum to its position in OAM. - ld a, [wBallMomentumX] - ld b, a - ld a, [_OAMRAM + 5] - add a, b - ld [_OAMRAM + 5], a - - ld a, [wBallMomentumY] - ld b, a - ld a, [_OAMRAM + 4] - add a, b - ld [_OAMRAM + 4], a - -; ANCHOR: updated-bounce -BounceOnTop: - ; Remember to offset the OAM position! - ; (8, 16) in OAM coordinates is (0, 0) on the screen. - ld a, [_OAMRAM + 4] - sub a, 16 + 1 - ld c, a - ld a, [_OAMRAM + 5] - sub a, 8 - ld b, a - call GetTileByPixel ; Returns tile address in hl - ld a, [hl] - call IsWallTile - jp nz, BounceOnRight - call CheckForBrick - ld a, 1 - ld [wBallMomentumY], a - call PlayBounceSound - -BounceOnRight: - ld a, [_OAMRAM + 4] - sub a, 16 - ld c, a - ld a, [_OAMRAM + 5] - sub a, 8 - 1 - ld b, a - call GetTileByPixel - ld a, [hl] - call IsWallTile - jp nz, BounceOnLeft - call CheckForBrick - ld a, -1 - ld [wBallMomentumX], a - call PlayBounceSound - -BounceOnLeft: - ld a, [_OAMRAM + 4] - sub a, 16 - ld c, a - ld a, [_OAMRAM + 5] - sub a, 8 + 1 - ld b, a - call GetTileByPixel - ld a, [hl] - call IsWallTile - jp nz, BounceOnBottom - call CheckForBrick - ld a, 1 - ld [wBallMomentumX], a - call PlayBounceSound - -BounceOnBottom: - ld a, [_OAMRAM + 4] - sub a, 16 - 1 - ld c, a - ld a, [_OAMRAM + 5] - sub a, 8 - ld b, a - call GetTileByPixel - ld a, [hl] - call IsWallTile - jp nz, BounceDone - call CheckForBrick - ld a, -1 - ld [wBallMomentumY], a - call PlayBounceSound -BounceDone: - - ; First, check if the ball is low enough to bounce off the paddle. - ld a, [_OAMRAM] - ld b, a - ld a, [_OAMRAM + 4] - cp a, b - jp nz, PaddleBounceDone - ; Now let's compare the X positions of the objects to see if they're touching. - ld a, [_OAMRAM + 1] - ld b, a - ld a, [_OAMRAM + 5] - add a, 16 - cp a, b - jp c, PaddleBounceDone - sub a, 16 + 8 - cp a, b - jp nc, PaddleBounceDone - - ld a, -1 - ld [wBallMomentumY], a - call PlayBounceSound - -PaddleBounceDone: -; ANCHOR_END: updated-bounce - - ; Check the current keys every frame and move left or right. - call Input - - ; First, check if the left button is pressed. -CheckLeft: - ld a, [wCurKeys] - and a, PADF_LEFT - jp z, CheckRight -Left: - ; Move the paddle one pixel to the left. - ld a, [_OAMRAM + 1] - dec a - ; If we've already hit the edge of the playfield, don't move. - cp a, 15 - jp z, Main - ld [_OAMRAM + 1], a - jp Main - -; Then check the right button. -CheckRight: - ld a, [wCurKeys] - and a, PADF_RIGHT - jp z, Main -Right: - ; Move the paddle one pixel to the right. - ld a, [_OAMRAM + 1] - inc a - ; If we've already hit the edge of the playfield, don't move. - cp a, 105 - jp z, Main - ld [_OAMRAM + 1], a - jp Main - -; Convert a pixel position to a tilemap address -; hl = $9800 + X + Y * 32 -; @param b: X -; @param c: Y -; @return hl: tile address -GetTileByPixel: - ; First, we need to divide by 8 to convert a pixel position to a tile position. - ; After this we want to multiply the Y position by 32. - ; These operations effectively cancel out so we only need to mask the Y value. - ld a, c - and a, %11111000 - ld l, a - ld h, 0 - ; Now we have the position * 8 in hl - add hl, hl ; position * 16 - add hl, hl ; position * 32 - ; Just add the X position and offset to the tilemap, and we're done. - ld a, b - srl a ; a / 2 - srl a ; a / 4 - srl a ; a / 8 - add a, l - ld l, a - adc a, h - sub a, l - ld h, a - ld bc, $9800 - add hl, bc - ret - -; @param a: tile ID -; @return z: set if a is a wall. -IsWallTile: - cp a, $00 - ret z - cp a, $01 - ret z - cp a, $02 - ret z - cp a, $04 - ret z - cp a, $05 - ret z - cp a, $06 - ret z - cp a, $07 - ret - -; ANCHOR: check-for-brick -; Checks if a brick was collided with and breaks it if possible. -; @param hl: address of tile. -CheckForBrick: - ld a, [hl] - cp a, BRICK_LEFT - jr nz, CheckForBrickRight - ; Break a brick from the left side. - call PlayBreakSound - ld [hl], BLANK_TILE - inc hl - ld [hl], BLANK_TILE -CheckForBrickRight: - cp a, BRICK_RIGHT - ret nz - ; Break a brick from the right side. - call PlayBreakSound - ld [hl], BLANK_TILE - dec hl - ld [hl], BLANK_TILE - ret -; ANCHOR_END: check-for-brick - -Input: - ; Poll half the controller - ld a, P1F_GET_BTN - call .onenibble - ld b, a ; B7-4 = 1; B3-0 = unpressed buttons - - ; Poll the other half - ld a, P1F_GET_DPAD - call .onenibble - swap a ; A3-0 = unpressed directions; A7-4 = 1 - xor a, b ; A = pressed buttons + directions - ld b, a ; B = pressed buttons + directions - - ; And release the controller - ld a, P1F_GET_NONE - ldh [rP1], a - - ; Combine with previous wCurKeys to make wNewKeys - ld a, [wCurKeys] - xor a, b ; A = keys that changed state - and a, b ; A = keys that changed to pressed - ld [wNewKeys], a - ld a, b - ld [wCurKeys], a - ret - -.onenibble - ldh [rP1], a ; switch the key matrix - call .knownret ; burn 10 cycles calling a known ret - ldh a, [rP1] ; ignore value while waiting for the key matrix to settle - ldh a, [rP1] - ldh a, [rP1] ; this read counts - or a, $F0 ; A7-4 = 1; A3-0 = unpressed keys -.knownret - ret - -; Copy bytes from one area to another. -; @param de: Source -; @param hl: Destination -; @param bc: Length -Memcopy: - ld a, [de] - ld [hli], a - inc de - dec bc - ld a, b - or a, c - jp nz, Memcopy - ret - -; ANCHOR: bounce-sound -PlayBounceSound: - ld a, $85 - ld [rNR21], a - ld a, $70 - ld [rNR22], a - ld a, $0d - ld [rNR23], a - ld a, $c3 - ld [rNR24], a - ret -; ANCHOR_END: bounce-sound - -; ANCHOR: break-sound -PlayBreakSound: - ld a, $01 - ld [rNR41], a - ld a, $f0 - ld [rNR42], a - ld a, $91 - ld [rNR43], a - ld a, $c0 - ld [rNR44], a - ret -; ANCHOR_END: break-sound - -Tiles: - dw `33333333 - dw `33333333 - dw `33333333 - dw `33322222 - dw `33322222 - dw `33322222 - dw `33322211 - dw `33322211 - dw `33333333 - dw `33333333 - dw `33333333 - dw `22222222 - dw `22222222 - dw `22222222 - dw `11111111 - dw `11111111 - dw `33333333 - dw `33333333 - dw `33333333 - dw `22222333 - dw `22222333 - dw `22222333 - dw `11222333 - dw `11222333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `22222222 - dw `20000000 - dw `20111111 - dw `20111111 - dw `20111111 - dw `20111111 - dw `22222222 - dw `33333333 - dw `22222223 - dw `00000023 - dw `11111123 - dw `11111123 - dw `11111123 - dw `11111123 - dw `22222223 - dw `33333333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `11001100 - dw `11111111 - dw `11111111 - dw `21212121 - dw `22222222 - dw `22322232 - dw `23232323 - dw `33333333 - ; My custom logo (tail) - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33302333 - dw `33333133 - dw `33300313 - dw `33300303 - dw `33013330 - dw `30333333 - dw `03333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `03333333 - dw `30333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333330 - dw `33333320 - dw `33333013 - dw `33330333 - dw `33100333 - dw `31001333 - dw `20001333 - dw `00000333 - dw `00000033 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33330333 - dw `33300333 - dw `33333333 - dw `33033333 - dw `33133333 - dw `33303333 - dw `33303333 - dw `33303333 - dw `33332333 - dw `33332333 - dw `33333330 - dw `33333300 - dw `33333300 - dw `33333100 - dw `33333000 - dw `33333000 - dw `33333100 - dw `33333300 - dw `00000001 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `10000333 - dw `00000033 - dw `00000003 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `33332333 - dw `33302333 - dw `32003333 - dw `00003333 - dw `00003333 - dw `00013333 - dw `00033333 - dw `00033333 - dw `33333300 - dw `33333310 - dw `33333330 - dw `33333332 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `30000000 - dw `33000000 - dw `33333000 - dw `33333333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000003 - dw `00000033 - dw `00003333 - dw `02333333 - dw `33333333 - dw `00333333 - dw `03333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 -TilesEnd: - -Tilemap: - db $00, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $02, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $0A, $0B, $0C, $0D, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $0E, $0F, $10, $11, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $12, $13, $14, $15, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $16, $17, $18, $19, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $09, $09, $09, $09, $09, $09, $09, $09, $09, $09, $09, $09, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 -TilemapEnd: - -Paddle: - dw `33333333 - dw `32222223 - dw `33333333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 -PaddleEnd: - -Ball: - dw `00330000 - dw `03223000 - dw `32222300 - dw `32222300 - dw `03223000 - dw `00330000 - dw `00000000 - dw `00000000 -BallEnd: - -SECTION "Counter", WRAM0 -wFrameCounter: db - -SECTION "Input Variables", WRAM0 -wCurKeys: db -wNewKeys: db - -SECTION "Ball Data", WRAM0 -wBallMomentumX: db -wBallMomentumY: db diff --git a/unbricked/bcd/main.asm b/unbricked/bcd/main.asm deleted file mode 100644 index ba623a32..00000000 --- a/unbricked/bcd/main.asm +++ /dev/null @@ -1,760 +0,0 @@ -INCLUDE "hardware.inc" -; ANCHOR: digit-offset -DEF BRICK_LEFT EQU $05 -DEF BRICK_RIGHT EQU $06 -DEF BLANK_TILE EQU $08 -DEF DIGIT_OFFSET EQU $1A -; ANCHOR_END: digit-offset -; ANCHOR: score-tile-location -DEF SCORE_TENS EQU $9870 -DEF SCORE_ONES EQU $9871 -; ANCHOR_END: score-tile-location - -SECTION "Header", ROM0[$100] - - jp EntryPoint - - ds $150 - @, 0 ; Make room for the header - -EntryPoint: - ; Do not turn the LCD off outside of VBlank -WaitVBlank: - ld a, [rLY] - cp 144 - jp c, WaitVBlank - - ; Turn the LCD off - ld a, 0 - ld [rLCDC], a - - ; Copy the tile data - ld de, Tiles - ld hl, $9000 - ld bc, TilesEnd - Tiles - call Memcopy - - ; Copy the tilemap - ld de, Tilemap - ld hl, $9800 - ld bc, TilemapEnd - Tilemap - call Memcopy - - ; Copy the paddle tile - ld de, Paddle - ld hl, $8000 - ld bc, PaddleEnd - Paddle - call Memcopy - - ; Copy the ball tile - ld de, Ball - ld hl, $8010 - ld bc, BallEnd - Ball - call Memcopy - - xor a, a - ld b, 160 - ld hl, _OAMRAM -ClearOam: - ld [hli], a - dec b - jp nz, ClearOam - - ; Initialize the paddle sprite in OAM - ld hl, _OAMRAM - ld a, 128 + 16 - ld [hli], a - ld a, 16 + 8 - ld [hli], a - ld a, 0 - ld [hli], a - ld [hli], a - ; Now initialize the ball sprite - ld a, 100 + 16 - ld [hli], a - ld a, 32 + 8 - ld [hli], a - ld a, 1 - ld [hli], a - ld a, 0 - ld [hli], a - - ; The ball starts out going up and to the right - ld a, 1 - ld [wBallMomentumX], a - ld a, -1 - ld [wBallMomentumY], a - - ; Turn the LCD on - ld a, LCDCF_ON | LCDCF_BGON | LCDCF_OBJON - ld [rLCDC], a - - ; During the first (blank) frame, initialize display registers - ld a, %11100100 - ld [rBGP], a - ld a, %11100100 - ld [rOBP0], a - ; ANCHOR: init-variables - ; Initialize global variables - ld a, 0 - ld [wFrameCounter], a - ld [wCurKeys], a - ld [wNewKeys], a - ld [wScore], a - ; ANCHOR_END: init-variables - -Main: - ld a, [rLY] - cp 144 - jp nc, Main -WaitVBlank2: - ld a, [rLY] - cp 144 - jp c, WaitVBlank2 - - ; Add the ball's momentum to its position in OAM. - ld a, [wBallMomentumX] - ld b, a - ld a, [_OAMRAM + 5] - add a, b - ld [_OAMRAM + 5], a - - ld a, [wBallMomentumY] - ld b, a - ld a, [_OAMRAM + 4] - add a, b - ld [_OAMRAM + 4], a - -BounceOnTop: - ; Remember to offset the OAM position! - ; (8, 16) in OAM coordinates is (0, 0) on the screen. - ld a, [_OAMRAM + 4] - sub a, 16 + 1 - ld c, a - ld a, [_OAMRAM + 5] - sub a, 8 - ld b, a - call GetTileByPixel ; Returns tile address in hl - ld a, [hl] - call IsWallTile - jp nz, BounceOnRight - call CheckAndHandleBrick - ld a, 1 - ld [wBallMomentumY], a - -BounceOnRight: - ld a, [_OAMRAM + 4] - sub a, 16 - ld c, a - ld a, [_OAMRAM + 5] - sub a, 8 - 1 - ld b, a - call GetTileByPixel - ld a, [hl] - call IsWallTile - jp nz, BounceOnLeft - call CheckAndHandleBrick - ld a, -1 - ld [wBallMomentumX], a - -BounceOnLeft: - ld a, [_OAMRAM + 4] - sub a, 16 - ld c, a - ld a, [_OAMRAM + 5] - sub a, 8 + 1 - ld b, a - call GetTileByPixel - ld a, [hl] - call IsWallTile - jp nz, BounceOnBottom - call CheckAndHandleBrick - ld a, 1 - ld [wBallMomentumX], a - -BounceOnBottom: - ld a, [_OAMRAM + 4] - sub a, 16 - 1 - ld c, a - ld a, [_OAMRAM + 5] - sub a, 8 - ld b, a - call GetTileByPixel - ld a, [hl] - call IsWallTile - jp nz, BounceDone - call CheckAndHandleBrick - ld a, -1 - ld [wBallMomentumY], a -BounceDone: - - ; First, check if the ball is low enough to bounce off the paddle. - ld a, [_OAMRAM] - ld b, a - ld a, [_OAMRAM + 4] - cp a, b - jp nz, PaddleBounceDone - ; Now let's compare the X positions of the objects to see if they're touching. - ld a, [_OAMRAM + 1] - ld b, a - ld a, [_OAMRAM + 5] - add a, 16 - cp a, b - jp c, PaddleBounceDone - sub a, 16 + 8 - cp a, b - jp nc, PaddleBounceDone - - ld a, -1 - ld [wBallMomentumY], a - -PaddleBounceDone: - - ; Check the current keys every frame and move left or right. - call Input - - ; First, check if the left button is pressed. -CheckLeft: - ld a, [wCurKeys] - and a, PADF_LEFT - jp z, CheckRight -Left: - ; Move the paddle one pixel to the left. - ld a, [_OAMRAM + 1] - dec a - ; If we've already hit the edge of the playfield, don't move. - cp a, 15 - jp z, Main - ld [_OAMRAM + 1], a - jp Main - -; Then check the right button. -CheckRight: - ld a, [wCurKeys] - and a, PADF_RIGHT - jp z, Main -Right: - ; Move the paddle one pixel to the right. - ld a, [_OAMRAM + 1] - inc a - ; If we've already hit the edge of the playfield, don't move. - cp a, 105 - jp z, Main - ld [_OAMRAM + 1], a - jp Main - -; Convert a pixel position to a tilemap address -; hl = $9800 + X + Y * 32 -; @param b: X -; @param c: Y -; @return hl: tile address -GetTileByPixel: - ; First, we need to divide by 8 to convert a pixel position to a tile position. - ; After this we want to multiply the Y position by 32. - ; These operations effectively cancel out so we only need to mask the Y value. - ld a, c - and a, %11111000 - ld l, a - ld h, 0 - ; Now we have the position * 8 in hl - add hl, hl ; position * 16 - add hl, hl ; position * 32 - ; Just add the X position and offset to the tilemap, and we're done. - ld a, b - srl a ; a / 2 - srl a ; a / 4 - srl a ; a / 8 - add a, l - ld l, a - adc a, h - sub a, l - ld h, a - ld bc, $9800 - add hl, bc - ret - -; @param a: tile ID -; @return z: set if a is a wall. -IsWallTile: - cp a, $00 - ret z - cp a, $01 - ret z - cp a, $02 - ret z - cp a, $04 - ret z - cp a, $05 - ret z - cp a, $06 - ret z - cp a, $07 - ret - -; ANCHOR: increase-score -; Increase score by 1 and store it as a 1 byte packed BCD number -; changes A and HL -IncreaseScorePackedBCD: - xor a ; clear carry flag and a - inc a ; a = 1 - ld hl, wScore ; load score - adc [hl] ; add 1 - daa ; convert to BCD - ld [hl], a ; store score - call UpdateScoreBoard - ret -; ANCHOR_END: increase-score - -; ANCHOR: update-score-board -; Read the packed BCD score from wScore and updates the score display -UpdateScoreBoard: - ld a, [wScore] ; Get the Packed score - and %11110000 ; Mask the lower nibble - rrca ; Move the upper nibble to the lower nibble (divide by 16) - rrca - rrca - rrca - add a, DIGIT_OFFSET ; Offset + add to get the digit tile - ld [SCORE_TENS], a ; Show the digit on screen - - ld a, [wScore] ; Get the packed score again - and %00001111 ; Mask the upper nibble - add a, DIGIT_OFFSET ; Offset + add to get the digit tile again - ld [SCORE_ONES], a ; Show the digit on screen - ret -; ANCHOR_END: update-score-board - -; ANCHOR: check-for-brick -; Checks if a brick was collided with and breaks it if possible. -; @param hl: address of tile. -CheckAndHandleBrick: - ld a, [hl] - cp a, BRICK_LEFT - jr nz, CheckAndHandleBrickRight - ; Break a brick from the left side. - ld [hl], BLANK_TILE - inc hl - ld [hl], BLANK_TILE - call IncreaseScorePackedBCD -CheckAndHandleBrickRight: - cp a, BRICK_RIGHT - ret nz - ; Break a brick from the right side. - ld [hl], BLANK_TILE - dec hl - ld [hl], BLANK_TILE - call IncreaseScorePackedBCD - ret -; ANCHOR_END: check-for-brick - -Input: - ; Poll half the controller - ld a, P1F_GET_BTN - call .onenibble - ld b, a ; B7-4 = 1; B3-0 = unpressed buttons - - ; Poll the other half - ld a, P1F_GET_DPAD - call .onenibble - swap a ; A3-0 = unpressed directions; A7-4 = 1 - xor a, b ; A = pressed buttons + directions - ld b, a ; B = pressed buttons + directions - - ; And release the controller - ld a, P1F_GET_NONE - ldh [rP1], a - - ; Combine with previous wCurKeys to make wNewKeys - ld a, [wCurKeys] - xor a, b ; A = keys that changed state - and a, b ; A = keys that changed to pressed - ld [wNewKeys], a - ld a, b - ld [wCurKeys], a - ret - -.onenibble - ldh [rP1], a ; switch the key matrix - call .knownret ; burn 10 cycles calling a known ret - ldh a, [rP1] ; ignore value while waiting for the key matrix to settle - ldh a, [rP1] - ldh a, [rP1] ; this read counts - or a, $F0 ; A7-4 = 1; A3-0 = unpressed keys -.knownret - ret - -; Copy bytes from one area to another. -; @param de: Source -; @param hl: Destination -; @param bc: Length -Memcopy: - ld a, [de] - ld [hli], a - inc de - dec bc - ld a, b - or a, c - jp nz, Memcopy - ret - -Tiles: - dw `33333333 - dw `33333333 - dw `33333333 - dw `33322222 - dw `33322222 - dw `33322222 - dw `33322211 - dw `33322211 - dw `33333333 - dw `33333333 - dw `33333333 - dw `22222222 - dw `22222222 - dw `22222222 - dw `11111111 - dw `11111111 - dw `33333333 - dw `33333333 - dw `33333333 - dw `22222333 - dw `22222333 - dw `22222333 - dw `11222333 - dw `11222333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `22222222 - dw `20000000 - dw `20111111 - dw `20111111 - dw `20111111 - dw `20111111 - dw `22222222 - dw `33333333 - dw `22222223 - dw `00000023 - dw `11111123 - dw `11111123 - dw `11111123 - dw `11111123 - dw `22222223 - dw `33333333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `11001100 - dw `11111111 - dw `11111111 - dw `21212121 - dw `22222222 - dw `22322232 - dw `23232323 - dw `33333333 - ; My custom logo (tail) - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33302333 - dw `33333133 - dw `33300313 - dw `33300303 - dw `33013330 - dw `30333333 - dw `03333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `03333333 - dw `30333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333330 - dw `33333320 - dw `33333013 - dw `33330333 - dw `33100333 - dw `31001333 - dw `20001333 - dw `00000333 - dw `00000033 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33330333 - dw `33300333 - dw `33333333 - dw `33033333 - dw `33133333 - dw `33303333 - dw `33303333 - dw `33303333 - dw `33332333 - dw `33332333 - dw `33333330 - dw `33333300 - dw `33333300 - dw `33333100 - dw `33333000 - dw `33333000 - dw `33333100 - dw `33333300 - dw `00000001 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `10000333 - dw `00000033 - dw `00000003 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `33332333 - dw `33302333 - dw `32003333 - dw `00003333 - dw `00003333 - dw `00013333 - dw `00033333 - dw `00033333 - dw `33333300 - dw `33333310 - dw `33333330 - dw `33333332 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `30000000 - dw `33000000 - dw `33333000 - dw `33333333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000003 - dw `00000033 - dw `00003333 - dw `02333333 - dw `33333333 - dw `00333333 - dw `03333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - - ; digits - ; 0 - dw `33333333 - dw `33000033 - dw `30033003 - dw `30033003 - dw `30033003 - dw `30033003 - dw `33000033 - dw `33333333 - ; 1 - dw `33333333 - dw `33300333 - dw `33000333 - dw `33300333 - dw `33300333 - dw `33300333 - dw `33000033 - dw `33333333 - ; 2 - dw `33333333 - dw `33000033 - dw `30330003 - dw `33330003 - dw `33000333 - dw `30003333 - dw `30000003 - dw `33333333 - ; 3 - dw `33333333 - dw `30000033 - dw `33330003 - dw `33000033 - dw `33330003 - dw `33330003 - dw `30000033 - dw `33333333 - ; 4 - dw `33333333 - dw `33000033 - dw `30030033 - dw `30330033 - dw `30330033 - dw `30000003 - dw `33330033 - dw `33333333 - ; 5 - dw `33333333 - dw `30000033 - dw `30033333 - dw `30000033 - dw `33330003 - dw `30330003 - dw `33000033 - dw `33333333 - ; 6 - dw `33333333 - dw `33000033 - dw `30033333 - dw `30000033 - dw `30033003 - dw `30033003 - dw `33000033 - dw `33333333 - ; 7 - dw `33333333 - dw `30000003 - dw `33333003 - dw `33330033 - dw `33300333 - dw `33000333 - dw `33000333 - dw `33333333 - ; 8 - dw `33333333 - dw `33000033 - dw `30333003 - dw `33000033 - dw `30333003 - dw `30333003 - dw `33000033 - dw `33333333 - ; 9 - dw `33333333 - dw `33000033 - dw `30330003 - dw `30330003 - dw `33000003 - dw `33330003 - dw `33000033 - dw `33333333 -TilesEnd: - -Tilemap: - db $00, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $02, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $07, $03, $03, $1A, $1A, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $0A, $0B, $0C, $0D, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $0E, $0F, $10, $11, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $12, $13, $14, $15, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $16, $17, $18, $19, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $09, $09, $09, $09, $09, $09, $09, $09, $09, $09, $09, $09, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 -TilemapEnd: - -Paddle: - dw `33333333 - dw `32222223 - dw `33333333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 -PaddleEnd: - -Ball: - dw `00330000 - dw `03223000 - dw `32222300 - dw `32222300 - dw `03223000 - dw `00330000 - dw `00000000 - dw `00000000 -BallEnd: - -SECTION "Counter", WRAM0 -wFrameCounter: db - -SECTION "Input Variables", WRAM0 -wCurKeys: db -wNewKeys: db - -SECTION "Ball Data", WRAM0 -wBallMomentumX: db -wBallMomentumY: db - -; ANCHOR: score-variable -SECTION "Score", WRAM0 -wScore: db -; ANCHOR_END: score-variable \ No newline at end of file diff --git a/unbricked/bricks/main.asm b/unbricked/bricks/main.asm deleted file mode 100644 index 8dcc8c18..00000000 --- a/unbricked/bricks/main.asm +++ /dev/null @@ -1,624 +0,0 @@ -; ANCHOR: constants -INCLUDE "hardware.inc" - -DEF BRICK_LEFT EQU $05 -DEF BRICK_RIGHT EQU $06 -DEF BLANK_TILE EQU $08 -; ANCHOR_END: constants - -SECTION "Header", ROM0[$100] - - jp EntryPoint - - ds $150 - @, 0 ; Make room for the header - -EntryPoint: - ; Do not turn the LCD off outside of VBlank -WaitVBlank: - ld a, [rLY] - cp 144 - jp c, WaitVBlank - - ; Turn the LCD off - ld a, 0 - ld [rLCDC], a - - ; Copy the tile data - ld de, Tiles - ld hl, $9000 - ld bc, TilesEnd - Tiles - call Memcopy - - ; Copy the tilemap - ld de, Tilemap - ld hl, $9800 - ld bc, TilemapEnd - Tilemap - call Memcopy - - ; Copy the paddle tile - ld de, Paddle - ld hl, $8000 - ld bc, PaddleEnd - Paddle - call Memcopy - - ; Copy the ball tile - ld de, Ball - ld hl, $8010 - ld bc, BallEnd - Ball - call Memcopy - - xor a, a - ld b, 160 - ld hl, _OAMRAM -ClearOam: - ld [hli], a - dec b - jp nz, ClearOam - - ; Initialize the paddle sprite in OAM - ld hl, _OAMRAM - ld a, 128 + 16 - ld [hli], a - ld a, 16 + 8 - ld [hli], a - ld a, 0 - ld [hli], a - ld [hli], a - ; Now initialize the ball sprite - ld a, 100 + 16 - ld [hli], a - ld a, 32 + 8 - ld [hli], a - ld a, 1 - ld [hli], a - ld a, 0 - ld [hli], a - - ; The ball starts out going up and to the right - ld a, 1 - ld [wBallMomentumX], a - ld a, -1 - ld [wBallMomentumY], a - - ; Turn the LCD on - ld a, LCDCF_ON | LCDCF_BGON | LCDCF_OBJON - ld [rLCDC], a - - ; During the first (blank) frame, initialize display registers - ld a, %11100100 - ld [rBGP], a - ld a, %11100100 - ld [rOBP0], a - - ; Initialize global variables - ld a, 0 - ld [wFrameCounter], a - ld [wCurKeys], a - ld [wNewKeys], a - -Main: - ld a, [rLY] - cp 144 - jp nc, Main -WaitVBlank2: - ld a, [rLY] - cp 144 - jp c, WaitVBlank2 - - ; Add the ball's momentum to its position in OAM. - ld a, [wBallMomentumX] - ld b, a - ld a, [_OAMRAM + 5] - add a, b - ld [_OAMRAM + 5], a - - ld a, [wBallMomentumY] - ld b, a - ld a, [_OAMRAM + 4] - add a, b - ld [_OAMRAM + 4], a - -; ANCHOR: updated-bounce -BounceOnTop: - ; Remember to offset the OAM position! - ; (8, 16) in OAM coordinates is (0, 0) on the screen. - ld a, [_OAMRAM + 4] - sub a, 16 + 1 - ld c, a - ld a, [_OAMRAM + 5] - sub a, 8 - ld b, a - call GetTileByPixel ; Returns tile address in hl - ld a, [hl] - call IsWallTile - jp nz, BounceOnRight - call CheckAndHandleBrick - ld a, 1 - ld [wBallMomentumY], a - -BounceOnRight: - ld a, [_OAMRAM + 4] - sub a, 16 - ld c, a - ld a, [_OAMRAM + 5] - sub a, 8 - 1 - ld b, a - call GetTileByPixel - ld a, [hl] - call IsWallTile - jp nz, BounceOnLeft - call CheckAndHandleBrick - ld a, -1 - ld [wBallMomentumX], a - -BounceOnLeft: - ld a, [_OAMRAM + 4] - sub a, 16 - ld c, a - ld a, [_OAMRAM + 5] - sub a, 8 + 1 - ld b, a - call GetTileByPixel - ld a, [hl] - call IsWallTile - jp nz, BounceOnBottom - call CheckAndHandleBrick - ld a, 1 - ld [wBallMomentumX], a - -BounceOnBottom: - ld a, [_OAMRAM + 4] - sub a, 16 - 1 - ld c, a - ld a, [_OAMRAM + 5] - sub a, 8 - ld b, a - call GetTileByPixel - ld a, [hl] - call IsWallTile - jp nz, BounceDone - call CheckAndHandleBrick - ld a, -1 - ld [wBallMomentumY], a -BounceDone: -; ANCHOR_END: updated-bounce - - ; First, check if the ball is low enough to bounce off the paddle. - ld a, [_OAMRAM] - ld b, a - ld a, [_OAMRAM + 4] - cp a, b - jp nz, PaddleBounceDone - ; Now let's compare the X positions of the objects to see if they're touching. - ld a, [_OAMRAM + 1] - ld b, a - ld a, [_OAMRAM + 5] - add a, 16 - cp a, b - jp c, PaddleBounceDone - sub a, 16 + 8 - cp a, b - jp nc, PaddleBounceDone - - ld a, -1 - ld [wBallMomentumY], a - -PaddleBounceDone: - - ; Check the current keys every frame and move left or right. - call Input - - ; First, check if the left button is pressed. -CheckLeft: - ld a, [wCurKeys] - and a, PADF_LEFT - jp z, CheckRight -Left: - ; Move the paddle one pixel to the left. - ld a, [_OAMRAM + 1] - dec a - ; If we've already hit the edge of the playfield, don't move. - cp a, 15 - jp z, Main - ld [_OAMRAM + 1], a - jp Main - -; Then check the right button. -CheckRight: - ld a, [wCurKeys] - and a, PADF_RIGHT - jp z, Main -Right: - ; Move the paddle one pixel to the right. - ld a, [_OAMRAM + 1] - inc a - ; If we've already hit the edge of the playfield, don't move. - cp a, 105 - jp z, Main - ld [_OAMRAM + 1], a - jp Main - -; Convert a pixel position to a tilemap address -; hl = $9800 + X + Y * 32 -; @param b: X -; @param c: Y -; @return hl: tile address -GetTileByPixel: - ; First, we need to divide by 8 to convert a pixel position to a tile position. - ; After this we want to multiply the Y position by 32. - ; These operations effectively cancel out so we only need to mask the Y value. - ld a, c - and a, %11111000 - ld l, a - ld h, 0 - ; Now we have the position * 8 in hl - add hl, hl ; position * 16 - add hl, hl ; position * 32 - ; Just add the X position and offset to the tilemap, and we're done. - ld a, b - srl a ; a / 2 - srl a ; a / 4 - srl a ; a / 8 - add a, l - ld l, a - adc a, h - sub a, l - ld h, a - ld bc, $9800 - add hl, bc - ret - -; @param a: tile ID -; @return z: set if a is a wall. -IsWallTile: - cp a, $00 - ret z - cp a, $01 - ret z - cp a, $02 - ret z - cp a, $04 - ret z - cp a, $05 - ret z - cp a, $06 - ret z - cp a, $07 - ret - -; ANCHOR: check-for-brick -; Checks if a brick was collided with and breaks it if possible. -; @param hl: address of tile. -CheckAndHandleBrick: - ld a, [hl] - cp a, BRICK_LEFT - jr nz, CheckAndHandleBrickRight - ; Break a brick from the left side. - ld [hl], BLANK_TILE - inc hl - ld [hl], BLANK_TILE -CheckAndHandleBrickRight: - cp a, BRICK_RIGHT - ret nz - ; Break a brick from the right side. - ld [hl], BLANK_TILE - dec hl - ld [hl], BLANK_TILE - ret -; ANCHOR_END: check-for-brick - -Input: - ; Poll half the controller - ld a, P1F_GET_BTN - call .onenibble - ld b, a ; B7-4 = 1; B3-0 = unpressed buttons - - ; Poll the other half - ld a, P1F_GET_DPAD - call .onenibble - swap a ; A3-0 = unpressed directions; A7-4 = 1 - xor a, b ; A = pressed buttons + directions - ld b, a ; B = pressed buttons + directions - - ; And release the controller - ld a, P1F_GET_NONE - ldh [rP1], a - - ; Combine with previous wCurKeys to make wNewKeys - ld a, [wCurKeys] - xor a, b ; A = keys that changed state - and a, b ; A = keys that changed to pressed - ld [wNewKeys], a - ld a, b - ld [wCurKeys], a - ret - -.onenibble - ldh [rP1], a ; switch the key matrix - call .knownret ; burn 10 cycles calling a known ret - ldh a, [rP1] ; ignore value while waiting for the key matrix to settle - ldh a, [rP1] - ldh a, [rP1] ; this read counts - or a, $F0 ; A7-4 = 1; A3-0 = unpressed keys -.knownret - ret - -; Copy bytes from one area to another. -; @param de: Source -; @param hl: Destination -; @param bc: Length -Memcopy: - ld a, [de] - ld [hli], a - inc de - dec bc - ld a, b - or a, c - jp nz, Memcopy - ret - -Tiles: - dw `33333333 - dw `33333333 - dw `33333333 - dw `33322222 - dw `33322222 - dw `33322222 - dw `33322211 - dw `33322211 - dw `33333333 - dw `33333333 - dw `33333333 - dw `22222222 - dw `22222222 - dw `22222222 - dw `11111111 - dw `11111111 - dw `33333333 - dw `33333333 - dw `33333333 - dw `22222333 - dw `22222333 - dw `22222333 - dw `11222333 - dw `11222333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `22222222 - dw `20000000 - dw `20111111 - dw `20111111 - dw `20111111 - dw `20111111 - dw `22222222 - dw `33333333 - dw `22222223 - dw `00000023 - dw `11111123 - dw `11111123 - dw `11111123 - dw `11111123 - dw `22222223 - dw `33333333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `11001100 - dw `11111111 - dw `11111111 - dw `21212121 - dw `22222222 - dw `22322232 - dw `23232323 - dw `33333333 - ; My custom logo (tail) - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33302333 - dw `33333133 - dw `33300313 - dw `33300303 - dw `33013330 - dw `30333333 - dw `03333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `03333333 - dw `30333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333330 - dw `33333320 - dw `33333013 - dw `33330333 - dw `33100333 - dw `31001333 - dw `20001333 - dw `00000333 - dw `00000033 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33330333 - dw `33300333 - dw `33333333 - dw `33033333 - dw `33133333 - dw `33303333 - dw `33303333 - dw `33303333 - dw `33332333 - dw `33332333 - dw `33333330 - dw `33333300 - dw `33333300 - dw `33333100 - dw `33333000 - dw `33333000 - dw `33333100 - dw `33333300 - dw `00000001 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `10000333 - dw `00000033 - dw `00000003 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `33332333 - dw `33302333 - dw `32003333 - dw `00003333 - dw `00003333 - dw `00013333 - dw `00033333 - dw `00033333 - dw `33333300 - dw `33333310 - dw `33333330 - dw `33333332 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `30000000 - dw `33000000 - dw `33333000 - dw `33333333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000003 - dw `00000033 - dw `00003333 - dw `02333333 - dw `33333333 - dw `00333333 - dw `03333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 -TilesEnd: - -Tilemap: - db $00, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $02, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $0A, $0B, $0C, $0D, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $0E, $0F, $10, $11, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $12, $13, $14, $15, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $16, $17, $18, $19, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $09, $09, $09, $09, $09, $09, $09, $09, $09, $09, $09, $09, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 -TilemapEnd: - -Paddle: - dw `33333333 - dw `32222223 - dw `33333333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 -PaddleEnd: - -Ball: - dw `00330000 - dw `03223000 - dw `32222300 - dw `32222300 - dw `03223000 - dw `00330000 - dw `00000000 - dw `00000000 -BallEnd: - -SECTION "Counter", WRAM0 -wFrameCounter: db - -SECTION "Input Variables", WRAM0 -wCurKeys: db -wNewKeys: db - -SECTION "Ball Data", WRAM0 -wBallMomentumX: db -wBallMomentumY: db diff --git a/unbricked/collision/main.asm b/unbricked/collision/main.asm deleted file mode 100644 index 51bca6b4..00000000 --- a/unbricked/collision/main.asm +++ /dev/null @@ -1,615 +0,0 @@ -INCLUDE "hardware.inc" - -SECTION "Header", ROM0[$100] - - jp EntryPoint - - ds $150 - @, 0 ; Make room for the header - -EntryPoint: - ; Do not turn the LCD off outside of VBlank -WaitVBlank: - ld a, [rLY] - cp 144 - jp c, WaitVBlank - - ; Turn the LCD off - ld a, 0 - ld [rLCDC], a - - ; Copy the tile data - ld de, Tiles - ld hl, $9000 - ld bc, TilesEnd - Tiles - call Memcopy - - ; Copy the tilemap - ld de, Tilemap - ld hl, $9800 - ld bc, TilemapEnd - Tilemap - call Memcopy - - ; Copy the paddle tile - ld de, Paddle - ld hl, $8000 - ld bc, PaddleEnd - Paddle - call Memcopy - -; ANCHOR: ball-copy - ; Copy the ball tile - ld de, Ball - ld hl, $8010 - ld bc, BallEnd - Ball - call Memcopy -; ANCHOR_END: ball-copy - - xor a, a - ld b, 160 - ld hl, _OAMRAM -ClearOam: - ld [hli], a - dec b - jp nz, ClearOam - -; ANCHOR: oam - ; Initialize the paddle sprite in OAM - ld hl, _OAMRAM - ld a, 128 + 16 - ld [hli], a - ld a, 16 + 8 - ld [hli], a - ld a, 0 - ld [hli], a - ld [hli], a -; ANCHOR: init - ; Now initialize the ball sprite - ld a, 100 + 16 - ld [hli], a - ld a, 32 + 8 - ld [hli], a - ld a, 1 - ld [hli], a - ld a, 0 - ld [hli], a -; ANCHOR_END: oam - - ; The ball starts out going up and to the right - ld a, 1 - ld [wBallMomentumX], a - ld a, -1 - ld [wBallMomentumY], a -; ANCHOR_END: init - - ; Turn the LCD on - ld a, LCDCF_ON | LCDCF_BGON | LCDCF_OBJON - ld [rLCDC], a - - ; During the first (blank) frame, initialize display registers - ld a, %11100100 - ld [rBGP], a - ld a, %11100100 - ld [rOBP0], a - - ; Initialize global variables - ld a, 0 - ld [wFrameCounter], a - ld [wCurKeys], a - ld [wNewKeys], a - -; ANCHOR: momentum -Main: - ld a, [rLY] - cp 144 - jp nc, Main -WaitVBlank2: - ld a, [rLY] - cp 144 - jp c, WaitVBlank2 - - ; Add the ball's momentum to its position in OAM. - ld a, [wBallMomentumX] - ld b, a - ld a, [_OAMRAM + 5] - add a, b - ld [_OAMRAM + 5], a - - ld a, [wBallMomentumY] - ld b, a - ld a, [_OAMRAM + 4] - add a, b - ld [_OAMRAM + 4], a -; ANCHOR_END: momentum - -; ANCHOR: first-tile-collision -BounceOnTop: - ; Remember to offset the OAM position! - ; (8, 16) in OAM coordinates is (0, 0) on the screen. - ld a, [_OAMRAM + 4] - sub a, 16 + 1 - ld c, a - ld a, [_OAMRAM + 5] - sub a, 8 - ld b, a - call GetTileByPixel ; Returns tile address in hl - ld a, [hl] - call IsWallTile - jp nz, BounceOnRight - ld a, 1 - ld [wBallMomentumY], a -; ANCHOR_END: first-tile-collision - -; ANCHOR: tile-collision -BounceOnRight: - ld a, [_OAMRAM + 4] - sub a, 16 - ld c, a - ld a, [_OAMRAM + 5] - sub a, 8 - 1 - ld b, a - call GetTileByPixel - ld a, [hl] - call IsWallTile - jp nz, BounceOnLeft - ld a, -1 - ld [wBallMomentumX], a - -BounceOnLeft: - ld a, [_OAMRAM + 4] - sub a, 16 - ld c, a - ld a, [_OAMRAM + 5] - sub a, 8 + 1 - ld b, a - call GetTileByPixel - ld a, [hl] - call IsWallTile - jp nz, BounceOnBottom - ld a, 1 - ld [wBallMomentumX], a - -BounceOnBottom: - ld a, [_OAMRAM + 4] - sub a, 16 - 1 - ld c, a - ld a, [_OAMRAM + 5] - sub a, 8 - ld b, a - call GetTileByPixel - ld a, [hl] - call IsWallTile - jp nz, BounceDone - ld a, -1 - ld [wBallMomentumY], a -BounceDone: -; ANCHOR_END: tile-collision - -; ANCHOR: paddle-bounce - ; First, check if the ball is low enough to bounce off the paddle. - ld a, [_OAMRAM] - ld b, a - ld a, [_OAMRAM + 4] - cp a, b - jp nz, PaddleBounceDone ; If the ball isn't at the same Y position as the paddle, it can't bounce. - ; Now let's compare the X positions of the objects to see if they're touching. - ld a, [_OAMRAM + 5] ; Ball's X position. - ld b, a - ld a, [_OAMRAM + 1] ; Paddle's X position. - sub a, 8 - cp a, b - jp nc, PaddleBounceDone - add a, 8 + 16 ; 8 to undo, 16 as the width. - cp a, b - jp c, PaddleBounceDone - - ld a, -1 - ld [wBallMomentumY], a - -PaddleBounceDone: -; ANCHOR_END: paddle-bounce - - ; Check the current keys every frame and move left or right. - call UpdateKeys - - ; First, check if the left button is pressed. -CheckLeft: - ld a, [wCurKeys] - and a, PADF_LEFT - jp z, CheckRight -Left: - ; Move the paddle one pixel to the left. - ld a, [_OAMRAM + 1] - dec a - ; If we've already hit the edge of the playfield, don't move. - cp a, 15 - jp z, Main - ld [_OAMRAM + 1], a - jp Main - -; Then check the right button. -CheckRight: - ld a, [wCurKeys] - and a, PADF_RIGHT - jp z, Main -Right: - ; Move the paddle one pixel to the right. - ld a, [_OAMRAM + 1] - inc a - ; If we've already hit the edge of the playfield, don't move. - cp a, 105 - jp z, Main - ld [_OAMRAM + 1], a - jp Main - -; ANCHOR: get-tile -; Convert a pixel position to a tilemap address -; hl = $9800 + X + Y * 32 -; @param b: X -; @param c: Y -; @return hl: tile address -GetTileByPixel: - ; First, we need to divide by 8 to convert a pixel position to a tile position. - ; After this we want to multiply the Y position by 32. - ; These operations effectively cancel out so we only need to mask the Y value. - ld a, c - and a, %11111000 - ld l, a - ld h, 0 - ; Now we have the position * 8 in hl - add hl, hl ; position * 16 - add hl, hl ; position * 32 - ; Convert the X position to an offset. - ld a, b - srl a ; a / 2 - srl a ; a / 4 - srl a ; a / 8 - ; Add the two offsets together. - add a, l - ld l, a - adc a, h - sub a, l - ld h, a - ; Add the offset to the tilemap's base address, and we are done! - ld bc, $9800 - add hl, bc - ret -; ANCHOR_END: get-tile - -; ANCHOR: is-wall-tile -; @param a: tile ID -; @return z: set if a is a wall. -IsWallTile: - cp a, $00 - ret z - cp a, $01 - ret z - cp a, $02 - ret z - cp a, $04 - ret z - cp a, $05 - ret z - cp a, $06 - ret z - cp a, $07 - ret -; ANCHOR_END: is-wall-tile - -UpdateKeys: - ; Poll half the controller - ld a, P1F_GET_BTN - call .onenibble - ld b, a ; B7-4 = 1; B3-0 = unpressed buttons - - ; Poll the other half - ld a, P1F_GET_DPAD - call .onenibble - swap a ; A3-0 = unpressed directions; A7-4 = 1 - xor a, b ; A = pressed buttons + directions - ld b, a ; B = pressed buttons + directions - - ; And release the controller - ld a, P1F_GET_NONE - ldh [rP1], a - - ; Combine with previous wCurKeys to make wNewKeys - ld a, [wCurKeys] - xor a, b ; A = keys that changed state - and a, b ; A = keys that changed to pressed - ld [wNewKeys], a - ld a, b - ld [wCurKeys], a - ret - -.onenibble - ldh [rP1], a ; switch the key matrix - call .knownret ; burn 10 cycles calling a known ret - ldh a, [rP1] ; ignore value while waiting for the key matrix to settle - ldh a, [rP1] - ldh a, [rP1] ; this read counts - or a, $F0 ; A7-4 = 1; A3-0 = unpressed keys -.knownret - ret - -; Copy bytes from one area to another. -; @param de: Source -; @param hl: Destination -; @param bc: Length -Memcopy: - ld a, [de] - ld [hli], a - inc de - dec bc - ld a, b - or a, c - jp nz, Memcopy - ret - -Tiles: - dw `33333333 - dw `33333333 - dw `33333333 - dw `33322222 - dw `33322222 - dw `33322222 - dw `33322211 - dw `33322211 - dw `33333333 - dw `33333333 - dw `33333333 - dw `22222222 - dw `22222222 - dw `22222222 - dw `11111111 - dw `11111111 - dw `33333333 - dw `33333333 - dw `33333333 - dw `22222333 - dw `22222333 - dw `22222333 - dw `11222333 - dw `11222333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `22222222 - dw `20000000 - dw `20111111 - dw `20111111 - dw `20111111 - dw `20111111 - dw `22222222 - dw `33333333 - dw `22222223 - dw `00000023 - dw `11111123 - dw `11111123 - dw `11111123 - dw `11111123 - dw `22222223 - dw `33333333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `11001100 - dw `11111111 - dw `11111111 - dw `21212121 - dw `22222222 - dw `22322232 - dw `23232323 - dw `33333333 - ; My custom logo (tail) - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33302333 - dw `33333133 - dw `33300313 - dw `33300303 - dw `33013330 - dw `30333333 - dw `03333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `03333333 - dw `30333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333330 - dw `33333320 - dw `33333013 - dw `33330333 - dw `33100333 - dw `31001333 - dw `20001333 - dw `00000333 - dw `00000033 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33330333 - dw `33300333 - dw `33333333 - dw `33033333 - dw `33133333 - dw `33303333 - dw `33303333 - dw `33303333 - dw `33332333 - dw `33332333 - dw `33333330 - dw `33333300 - dw `33333300 - dw `33333100 - dw `33333000 - dw `33333000 - dw `33333100 - dw `33333300 - dw `00000001 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `10000333 - dw `00000033 - dw `00000003 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `33332333 - dw `33302333 - dw `32003333 - dw `00003333 - dw `00003333 - dw `00013333 - dw `00033333 - dw `00033333 - dw `33333300 - dw `33333310 - dw `33333330 - dw `33333332 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `30000000 - dw `33000000 - dw `33333000 - dw `33333333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000003 - dw `00000033 - dw `00003333 - dw `02333333 - dw `33333333 - dw `00333333 - dw `03333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 -TilesEnd: - -Tilemap: - db $00, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $02, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $0A, $0B, $0C, $0D, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $0E, $0F, $10, $11, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $12, $13, $14, $15, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $16, $17, $18, $19, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $09, $09, $09, $09, $09, $09, $09, $09, $09, $09, $09, $09, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 -TilemapEnd: - -Paddle: - dw `33333333 - dw `32222223 - dw `33333333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 -PaddleEnd: - -; ANCHOR: ball-sprite -Ball: - dw `00033000 - dw `00322300 - dw `03222230 - dw `03222230 - dw `00322300 - dw `00033000 - dw `00000000 - dw `00000000 -BallEnd: -; ANCHOR_END: ball-sprite - -; ANCHOR: ram -SECTION "Counter", WRAM0 -wFrameCounter: db - -SECTION "Input Variables", WRAM0 -wCurKeys: db -wNewKeys: db - -SECTION "Ball Data", WRAM0 -wBallMomentumX: db -wBallMomentumY: db -; ANCHOR_END: ram diff --git a/unbricked/functions/main.asm b/unbricked/functions/main.asm deleted file mode 100644 index 00818e3a..00000000 --- a/unbricked/functions/main.asm +++ /dev/null @@ -1,367 +0,0 @@ -INCLUDE "hardware.inc" - -SECTION "Header", ROM0[$100] - - jp EntryPoint - - ds $150 - @, 0 ; Make room for the header - -EntryPoint: - ; Do not turn the LCD off outside of VBlank -WaitVBlank: - ld a, [rLY] - cp 144 - jp c, WaitVBlank - - ; Turn the LCD off - ld a, 0 - ld [rLCDC], a - -; ANCHOR: copy_tiles - ; Copy the tile data - ld de, Tiles - ld hl, $9000 - ld bc, TilesEnd - Tiles - call Memcopy -; ANCHOR_END: copy_tiles - -; ANCHOR: copy_map - ; Copy the tilemap - ld de, Tilemap - ld hl, $9800 - ld bc, TilemapEnd - Tilemap - call Memcopy -; ANCHOR_END: copy_map - -; ANCHOR: copy_paddle - ; Copy the paddle tile - ld de, Paddle - ld hl, $8000 - ld bc, PaddleEnd - Paddle - call Memcopy -; ANCHOR_END: copy_paddle - - xor a, a - ld b, 160 - ld hl, _OAMRAM -ClearOam: - ld [hli], a - dec b - jp nz, ClearOam - - ld hl, _OAMRAM - ld a, 128 + 16 - ld [hli], a - ld a, 16 + 8 - ld [hli], a - ld a, 0 - ld [hli], a - ld [hl], a - - ; Turn the LCD on - ld a, LCDCF_ON | LCDCF_BGON | LCDCF_OBJON - ld [rLCDC], a - - ; During the first (blank) frame, initialize display registers - ld a, %11100100 - ld [rBGP], a - ld a, %11100100 - ld [rOBP0], a - - ; Initialize global variables - ld a, 0 - ld [wFrameCounter], a - -; ANCHOR: main -Main: - ld a, [rLY] - cp 144 - jp nc, Main -WaitVBlank2: - ld a, [rLY] - cp 144 - jp c, WaitVBlank2 - - ld a, [wFrameCounter] - inc a - ld [wFrameCounter], a - cp a, 15 ; Every 15 frames (a quarter of a second), run the following code - jp nz, Main - - ; Reset the frame counter back to 0 - ld a, 0 - ld [wFrameCounter], a - - ; Move the paddle one pixel to the right. - ld a, [_OAMRAM + 1] - inc a - ld [_OAMRAM + 1], a - jp Main -; ANCHOR_END: main - -; ANCHOR: memcpy -; Copy bytes from one area to another. -; @param de: Source -; @param hl: Destination -; @param bc: Length -Memcopy: - ld a, [de] - ld [hli], a - inc de - dec bc - ld a, b - or a, c - jp nz, Memcopy - ret -; ANCHOR_END: memcpy - -Tiles: - dw `33333333 - dw `33333333 - dw `33333333 - dw `33322222 - dw `33322222 - dw `33322222 - dw `33322211 - dw `33322211 - dw `33333333 - dw `33333333 - dw `33333333 - dw `22222222 - dw `22222222 - dw `22222222 - dw `11111111 - dw `11111111 - dw `33333333 - dw `33333333 - dw `33333333 - dw `22222333 - dw `22222333 - dw `22222333 - dw `11222333 - dw `11222333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `22222222 - dw `20000000 - dw `20111111 - dw `20111111 - dw `20111111 - dw `20111111 - dw `22222222 - dw `33333333 - dw `22222223 - dw `00000023 - dw `11111123 - dw `11111123 - dw `11111123 - dw `11111123 - dw `22222223 - dw `33333333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `11001100 - dw `11111111 - dw `11111111 - dw `21212121 - dw `22222222 - dw `22322232 - dw `23232323 - dw `33333333 - ; My custom logo (tail) - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33302333 - dw `33333133 - dw `33300313 - dw `33300303 - dw `33013330 - dw `30333333 - dw `03333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `03333333 - dw `30333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333330 - dw `33333320 - dw `33333013 - dw `33330333 - dw `33100333 - dw `31001333 - dw `20001333 - dw `00000333 - dw `00000033 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33330333 - dw `33300333 - dw `33333333 - dw `33033333 - dw `33133333 - dw `33303333 - dw `33303333 - dw `33303333 - dw `33332333 - dw `33332333 - dw `33333330 - dw `33333300 - dw `33333300 - dw `33333100 - dw `33333000 - dw `33333000 - dw `33333100 - dw `33333300 - dw `00000001 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `10000333 - dw `00000033 - dw `00000003 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `33332333 - dw `33302333 - dw `32003333 - dw `00003333 - dw `00003333 - dw `00013333 - dw `00033333 - dw `00033333 - dw `33333300 - dw `33333310 - dw `33333330 - dw `33333332 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `30000000 - dw `33000000 - dw `33333000 - dw `33333333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000003 - dw `00000033 - dw `00003333 - dw `02333333 - dw `33333333 - dw `00333333 - dw `03333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 -TilesEnd: - -Tilemap: - db $00, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $02, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $0A, $0B, $0C, $0D, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $0E, $0F, $10, $11, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $12, $13, $14, $15, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $16, $17, $18, $19, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $09, $09, $09, $09, $09, $09, $09, $09, $09, $09, $09, $09, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 -TilemapEnd: - -Paddle: - dw `33333333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 -PaddleEnd: - -SECTION "Counter", WRAM0 -wFrameCounter: db - -SECTION "Input Variables", WRAM0 -wCurKeys: db -wNewKeys: db diff --git a/unbricked/getting-started/main.asm b/unbricked/getting-started/main.asm deleted file mode 100644 index 739879df..00000000 --- a/unbricked/getting-started/main.asm +++ /dev/null @@ -1,177 +0,0 @@ -; ANCHOR: dummy Lines beginning with `ANCHOR` and `ANCHOR_END` are used by mdBook -; ANCHOR_END: dummy Note that lines matching /^; ANCHOR/ are stripped from the online version -; ANCHOR: includes -INCLUDE "hardware.inc" -; ANCHOR_END: includes - -; ANCHOR: header -SECTION "Header", ROM0[$100] - - jp EntryPoint - - ds $150 - @, 0 ; Make room for the header -; ANCHOR_END: header - -; ANCHOR: entry -EntryPoint: - ; Do not turn the LCD off outside of VBlank -WaitVBlank: - ld a, [rLY] - cp 144 - jp c, WaitVBlank - - ; Turn the LCD off - ld a, 0 - ld [rLCDC], a -; ANCHOR_END: entry - -; ANCHOR: copy_tiles - ; Copy the tile data - ld de, Tiles - ld hl, $9000 - ld bc, TilesEnd - Tiles -CopyTiles: - ld a, [de] - ld [hli], a - inc de - dec bc - ld a, b - or a, c - jp nz, CopyTiles -; ANCHOR_END: copy_tiles - -; ANCHOR: copy_map - ; Copy the tilemap - ld de, Tilemap - ld hl, $9800 - ld bc, TilemapEnd - Tilemap -CopyTilemap: - ld a, [de] - ld [hli], a - inc de - dec bc - ld a, b - or a, c - jp nz, CopyTilemap -; ANCHOR_END: copy_map - -; ANCHOR: end - ; Turn the LCD on - ld a, LCDCF_ON | LCDCF_BGON - ld [rLCDC], a - - ; During the first (blank) frame, initialize display registers - ld a, %11100100 - ld [rBGP], a - -Done: - jp Done -; ANCHOR_END: end - -Tiles: - dw `33333333 - dw `33333333 - dw `33333333 - dw `33322222 - dw `33322222 - dw `33322222 - dw `33322211 - dw `33322211 - dw `33333333 - dw `33333333 - dw `33333333 - dw `22222222 - dw `22222222 - dw `22222222 - dw `11111111 - dw `11111111 - dw `33333333 - dw `33333333 - dw `33333333 - dw `22222333 - dw `22222333 - dw `22222333 - dw `11222333 - dw `11222333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `22222222 - dw `20000000 - dw `20111111 - dw `20111111 - dw `20111111 - dw `20111111 - dw `22222222 - dw `33333333 - dw `22222223 - dw `00000023 - dw `11111123 - dw `11111123 - dw `11111123 - dw `11111123 - dw `22222223 - dw `33333333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `11001100 - dw `11111111 - dw `11111111 - dw `21212121 - dw `22222222 -; ANCHOR: custom_logo - dw `22322232 - dw `23232323 - dw `33333333 - ; Paste your logo here: - -TilesEnd: -; ANCHOR_END: custom_logo - -Tilemap: - db $00, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $02, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $0A, $0B, $0C, $0D, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $0E, $0F, $10, $11, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $12, $13, $14, $15, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $16, $17, $18, $19, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $09, $09, $09, $09, $09, $09, $09, $09, $09, $09, $09, $09, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 -TilemapEnd: diff --git a/unbricked/hardware.inc b/unbricked/hardware.inc deleted file mode 100644 index 2e3be73b..00000000 --- a/unbricked/hardware.inc +++ /dev/null @@ -1,1069 +0,0 @@ -;* -;* Gameboy Hardware definitions -;* -;* Based on Jones' hardware.inc -;* And based on Carsten Sorensen's ideas. -;* -;* Rev 1.1 - 15-Jul-97 : Added define check -;* Rev 1.2 - 18-Jul-97 : Added revision check macro -;* Rev 1.3 - 19-Jul-97 : Modified for RGBASM V1.05 -;* Rev 1.4 - 27-Jul-97 : Modified for new subroutine prefixes -;* Rev 1.5 - 15-Aug-97 : Added _HRAM, PAD, CART defines -;* : and Nintendo Logo -;* Rev 1.6 - 30-Nov-97 : Added rDIV, rTIMA, rTMA, & rTAC -;* Rev 1.7 - 31-Jan-98 : Added _SCRN0, _SCRN1 -;* Rev 1.8 - 15-Feb-98 : Added rSB, rSC -;* Rev 1.9 - 16-Feb-98 : Converted I/O registers to $FFXX format -;* Rev 2.0 - : Added GBC registers -;* Rev 2.1 - : Added MBC5 & cart RAM enable/disable defines -;* Rev 2.2 - : Fixed NR42,NR43, & NR44 equates -;* Rev 2.3 - : Fixed incorrect _HRAM equate -;* Rev 2.4 - 27-Apr-13 : Added some cart defines (AntonioND) -;* Rev 2.5 - 03-May-15 : Fixed format (AntonioND) -;* Rev 2.6 - 09-Apr-16 : Added GBC OAM and cart defines (AntonioND) -;* Rev 2.7 - 19-Jan-19 : Added rPCMXX (ISSOtm) -;* Rev 2.8 - 03-Feb-19 : Added audio registers flags (Álvaro Cuesta) -;* Rev 2.9 - 28-Feb-20 : Added utility rP1 constants -;* Rev 3.0 - 27-Aug-20 : Register ordering, byte-based sizes, OAM additions, general cleanup (Blitter Object) -;* Rev 4.0 - 03-May-21 : Updated to use RGBDS 0.5.0 syntax, changed IEF_LCDC to IEF_STAT (Eievui) -;* Rev 4.1 - 16-Aug-21 : Added more flags, bit number defines, and offset constants for OAM and window positions (rondnelson99) -;* Rev 4.2 - 04-Sep-21 : Added CH3- and CH4-specific audio registers flags (ISSOtm) -;* Rev 4.3 - 07-Nov-21 : Deprecate VRAM address constants (Eievui) -;* Rev 4.4 - 11-Jan-22 : Deprecate VRAM CART_SRAM_2KB constant (avivace) -;* Rev 4.5 - 03-Mar-22 : Added bit number definitions for OCPS, BCPS and LCDC (sukus) -;* Rev 4.6 - 15-Jun-22 : Added MBC3 registers and special values -;* Rev 4.7.0 - 27-Jun-22 : Added alternate names for some constants -;* Rev 4.7.1 - 05-Jul-22 : Added RPB_LED_ON constant - -; NOTE: REVISION NUMBER CHANGES MUST BE REFLECTED -; IN `rev_Check_hardware_inc` BELOW! - -IF __RGBDS_MAJOR__ == 0 && __RGBDS_MINOR__ < 5 - FAIL "This version of 'hardware.inc' requires RGBDS version 0.5.0 or later." -ENDC - -; If all of these are already defined, don't do it again. - - IF !DEF(HARDWARE_INC) -DEF HARDWARE_INC EQU 1 - -; Usage: rev_Check_hardware_inc -; Examples: rev_Check_hardware_inc 4.1.2 -; rev_Check_hardware_inc 4.1 (equivalent to 4.1.0) -; rev_Check_hardware_inc 4 (equivalent to 4.0.0) -MACRO rev_Check_hardware_inc - DEF CUR_VER equs "4,7,1" ; ** UPDATE THIS LINE WHEN CHANGING THE REVISION NUMBER ** - DEF MIN_VER equs STRRPL("\1", ".", ",") - DEF INTERNAL_CHK equs """MACRO ___internal - IF \\1 != \\4 || \\2 < \\5 || (\\2 == \\5 && \\3 < \\6) - FAIL "Version \\1.\\2.\\3 of 'hardware.inc' is incompatible with requested version \\4.\\5.\\6" - ENDC -\nENDM""" - INTERNAL_CHK - ___internal {CUR_VER}, {MIN_VER},0,0 - PURGE CUR_VER, MIN_VER, INTERNAL_CHK, ___internal -ENDM - - -;*************************************************************************** -;* -;* General memory region constants -;* -;*************************************************************************** - -DEF _VRAM EQU $8000 ; $8000->$9FFF -DEF _SCRN0 EQU $9800 ; $9800->$9BFF -DEF _SCRN1 EQU $9C00 ; $9C00->$9FFF -DEF _SRAM EQU $A000 ; $A000->$BFFF -DEF _RAM EQU $C000 ; $C000->$CFFF / $C000->$DFFF -DEF _RAMBANK EQU $D000 ; $D000->$DFFF -DEF _OAMRAM EQU $FE00 ; $FE00->$FE9F -DEF _IO EQU $FF00 ; $FF00->$FF7F,$FFFF -DEF _AUD3WAVERAM EQU $FF30 ; $FF30->$FF3F -DEF _HRAM EQU $FF80 ; $FF80->$FFFE - - -;*************************************************************************** -;* -;* MBC registers -;* -;*************************************************************************** - -; *** Common *** - -; -- -; -- RAMG ($0000-$1FFF) -; -- Controls whether access to SRAM (and the MBC3 RTC registers) is allowed (W) -; -- -DEF rRAMG EQU $0000 - -DEF CART_SRAM_ENABLE EQU $0A -DEF CART_SRAM_DISABLE EQU $00 - - -; -- -; -- ROMB0 ($2000-$3FFF) -; -- Selects which ROM bank is mapped to the ROMX space ($4000-$7FFF) (W) -; -- -; -- The range of accepted values, as well as the behavior of writing $00, -; -- varies depending on the MBC. -; -- -DEF rROMB0 EQU $2000 - -; -- -; -- RAMB ($4000-$5FFF) -; -- Selects which SRAM bank is mapped to the SRAM space ($A000-$BFFF) (W) -; -- -; -- The range of accepted values varies depending on the cartridge configuration. -; -- -DEF rRAMB EQU $4000 - - -; *** MBC3-specific registers *** - -; Write one of these to rRAMG to map the corresponding RTC register to all SRAM space -DEF RTC_S EQU $08 ; Seconds (0-59) -DEF RTC_M EQU $09 ; Minutes (0-59) -DEF RTC_H EQU $0A ; Hours (0-23) -DEF RTC_DL EQU $0B ; Lower 8 bits of Day Counter ($00-$FF) -DEF RTC_DH EQU $0C ; Bit 7 - Day Counter Carry Bit (1=Counter Overflow) - ; Bit 6 - Halt (0=Active, 1=Stop Timer) - ; Bit 0 - Most significant bit of Day Counter (Bit 8) - - -; -- -; -- RTCLATCH ($6000-$7FFF) -; -- Write $00 then $01 to latch the current time into the RTC registers (W) -; -- -DEF rRTCLATCH EQU $6000 - - -; *** MBC5-specific register *** - -; -- -; -- ROMB1 ($3000-$3FFF) -; -- A 9th bit that "extends" ROMB0 if more than 256 banks are present (W) -; -- -; -- Also note that rROMB0 thus only spans $2000-$2FFF. -; -- -DEF rROMB1 EQU $3000 - - -; Bit 3 of RAMB enables the rumble motor (if any) -DEF CART_RUMBLE_ON EQU 1 << 3 - - -;*************************************************************************** -;* -;* Memory-mapped registers -;* -;*************************************************************************** - -; -- -; -- P1 ($FF00) -; -- Register for reading joy pad info. (R/W) -; -- -DEF rP1 EQU $FF00 - -DEF P1F_5 EQU %00100000 ; P15 out port, set to 0 to get buttons -DEF P1F_4 EQU %00010000 ; P14 out port, set to 0 to get dpad -DEF P1F_3 EQU %00001000 ; P13 in port -DEF P1F_2 EQU %00000100 ; P12 in port -DEF P1F_1 EQU %00000010 ; P11 in port -DEF P1F_0 EQU %00000001 ; P10 in port - -DEF P1F_GET_DPAD EQU P1F_5 -DEF P1F_GET_BTN EQU P1F_4 -DEF P1F_GET_NONE EQU P1F_4 | P1F_5 - - -; -- -; -- SB ($FF01) -; -- Serial Transfer Data (R/W) -; -- -DEF rSB EQU $FF01 - - -; -- -; -- SC ($FF02) -; -- Serial I/O Control (R/W) -; -- -DEF rSC EQU $FF02 - -DEF SCF_START EQU %10000000 ; Transfer Start Flag (1=Transfer in progress, or requested) -DEF SCF_SPEED EQU %00000010 ; Clock Speed (0=Normal, 1=Fast) ** CGB Mode Only ** -DEF SCF_SOURCE EQU %00000001 ; Shift Clock (0=External Clock, 1=Internal Clock) - -DEF SCB_START EQU 7 -DEF SCB_SPEED EQU 1 -DEF SCB_SOURCE EQU 0 - -; -- -; -- DIV ($FF04) -; -- Divider register (R/W) -; -- -DEF rDIV EQU $FF04 - - -; -- -; -- TIMA ($FF05) -; -- Timer counter (R/W) -; -- -DEF rTIMA EQU $FF05 - - -; -- -; -- TMA ($FF06) -; -- Timer modulo (R/W) -; -- -DEF rTMA EQU $FF06 - - -; -- -; -- TAC ($FF07) -; -- Timer control (R/W) -; -- -DEF rTAC EQU $FF07 - -DEF TACF_START EQU %00000100 -DEF TACF_STOP EQU %00000000 -DEF TACF_4KHZ EQU %00000000 -DEF TACF_16KHZ EQU %00000011 -DEF TACF_65KHZ EQU %00000010 -DEF TACF_262KHZ EQU %00000001 - -DEF TACB_START EQU 2 - - -; -- -; -- IF ($FF0F) -; -- Interrupt Flag (R/W) -; -- -DEF rIF EQU $FF0F - - -; -- -; -- AUD1SWEEP/NR10 ($FF10) -; -- Sweep register (R/W) -; -- -; -- Bit 6-4 - Sweep Time -; -- Bit 3 - Sweep Increase/Decrease -; -- 0: Addition (frequency increases???) -; -- 1: Subtraction (frequency increases???) -; -- Bit 2-0 - Number of sweep shift (# 0-7) -; -- Sweep Time: (n*7.8ms) -; -- -DEF rNR10 EQU $FF10 -DEF rAUD1SWEEP EQU rNR10 - -DEF AUD1SWEEP_UP EQU %00000000 -DEF AUD1SWEEP_DOWN EQU %00001000 - - -; -- -; -- AUD1LEN/NR11 ($FF11) -; -- Sound length/Wave pattern duty (R/W) -; -- -; -- Bit 7-6 - Wave Pattern Duty (00:12.5% 01:25% 10:50% 11:75%) -; -- Bit 5-0 - Sound length data (# 0-63) -; -- -DEF rNR11 EQU $FF11 -DEF rAUD1LEN EQU rNR11 - - -; -- -; -- AUD1ENV/NR12 ($FF12) -; -- Envelope (R/W) -; -- -; -- Bit 7-4 - Initial value of envelope -; -- Bit 3 - Envelope UP/DOWN -; -- 0: Decrease -; -- 1: Range of increase -; -- Bit 2-0 - Number of envelope sweep (# 0-7) -; -- -DEF rNR12 EQU $FF12 -DEF rAUD1ENV EQU rNR12 - - -; -- -; -- AUD1LOW/NR13 ($FF13) -; -- Frequency low byte (W) -; -- -DEF rNR13 EQU $FF13 -DEF rAUD1LOW EQU rNR13 - - -; -- -; -- AUD1HIGH/NR14 ($FF14) -; -- Frequency high byte (W) -; -- -; -- Bit 7 - Initial (when set, sound restarts) -; -- Bit 6 - Counter/consecutive selection -; -- Bit 2-0 - Frequency's higher 3 bits -; -- -DEF rNR14 EQU $FF14 -DEF rAUD1HIGH EQU rNR14 - - -; -- -; -- AUD2LEN/NR21 ($FF16) -; -- Sound Length; Wave Pattern Duty (R/W) -; -- -; -- see AUD1LEN for info -; -- -DEF rNR21 EQU $FF16 -DEF rAUD2LEN EQU rNR21 - - -; -- -; -- AUD2ENV/NR22 ($FF17) -; -- Envelope (R/W) -; -- -; -- see AUD1ENV for info -; -- -DEF rNR22 EQU $FF17 -DEF rAUD2ENV EQU rNR22 - - -; -- -; -- AUD2LOW/NR23 ($FF18) -; -- Frequency low byte (W) -; -- -DEF rNR23 EQU $FF18 -DEF rAUD2LOW EQU rNR23 - - -; -- -; -- AUD2HIGH/NR24 ($FF19) -; -- Frequency high byte (W) -; -- -; -- see AUD1HIGH for info -; -- -DEF rNR24 EQU $FF19 -DEF rAUD2HIGH EQU rNR24 - - -; -- -; -- AUD3ENA/NR30 ($FF1A) -; -- Sound on/off (R/W) -; -- -; -- Bit 7 - Sound ON/OFF (1=ON,0=OFF) -; -- -DEF rNR30 EQU $FF1A -DEF rAUD3ENA EQU rNR30 - -DEF AUD3ENA_OFF EQU %00000000 -DEF AUD3ENA_ON EQU %10000000 - - -; -- -; -- AUD3LEN/NR31 ($FF1B) -; -- Sound length (R/W) -; -- -; -- Bit 7-0 - Sound length -; -- -DEF rNR31 EQU $FF1B -DEF rAUD3LEN EQU rNR31 - - -; -- -; -- AUD3LEVEL/NR32 ($FF1C) -; -- Select output level -; -- -; -- Bit 6-5 - Select output level -; -- 00: 0/1 (mute) -; -- 01: 1/1 -; -- 10: 1/2 -; -- 11: 1/4 -; -- -DEF rNR32 EQU $FF1C -DEF rAUD3LEVEL EQU rNR32 - -DEF AUD3LEVEL_MUTE EQU %00000000 -DEF AUD3LEVEL_100 EQU %00100000 -DEF AUD3LEVEL_50 EQU %01000000 -DEF AUD3LEVEL_25 EQU %01100000 - - -; -- -; -- AUD3LOW/NR33 ($FF1D) -; -- Frequency low byte (W) -; -- -; -- see AUD1LOW for info -; -- -DEF rNR33 EQU $FF1D -DEF rAUD3LOW EQU rNR33 - - -; -- -; -- AUD3HIGH/NR34 ($FF1E) -; -- Frequency high byte (W) -; -- -; -- see AUD1HIGH for info -; -- -DEF rNR34 EQU $FF1E -DEF rAUD3HIGH EQU rNR34 - - -; -- -; -- AUD4LEN/NR41 ($FF20) -; -- Sound length (R/W) -; -- -; -- Bit 5-0 - Sound length data (# 0-63) -; -- -DEF rNR41 EQU $FF20 -DEF rAUD4LEN EQU rNR41 - - -; -- -; -- AUD4ENV/NR42 ($FF21) -; -- Envelope (R/W) -; -- -; -- see AUD1ENV for info -; -- -DEF rNR42 EQU $FF21 -DEF rAUD4ENV EQU rNR42 - - -; -- -; -- AUD4POLY/NR43 ($FF22) -; -- Polynomial counter (R/W) -; -- -; -- Bit 7-4 - Selection of the shift clock frequency of the (scf) -; -- polynomial counter (0000-1101) -; -- freq=drf*1/2^scf (not sure) -; -- Bit 3 - Selection of the polynomial counter's step -; -- 0: 15 steps -; -- 1: 7 steps -; -- Bit 2-0 - Selection of the dividing ratio of frequencies (drf) -; -- 000: f/4 001: f/8 010: f/16 011: f/24 -; -- 100: f/32 101: f/40 110: f/48 111: f/56 (f=4.194304 Mhz) -; -- -DEF rNR43 EQU $FF22 -DEF rAUD4POLY EQU rNR43 - -DEF AUD4POLY_15STEP EQU %00000000 -DEF AUD4POLY_7STEP EQU %00001000 - - -; -- -; -- AUD4GO/NR44 ($FF23) -; -- -; -- Bit 7 - Initial (when set, sound restarts) -; -- Bit 6 - Counter/consecutive selection -; -- -DEF rNR44 EQU $FF23 -DEF rAUD4GO EQU rNR44 - - -; -- -; -- AUDVOL/NR50 ($FF24) -; -- Channel control / ON-OFF / Volume (R/W) -; -- -; -- Bit 7 - Vin->SO2 ON/OFF (left) -; -- Bit 6-4 - SO2 output level (left speaker) (# 0-7) -; -- Bit 3 - Vin->SO1 ON/OFF (right) -; -- Bit 2-0 - SO1 output level (right speaker) (# 0-7) -; -- -DEF rNR50 EQU $FF24 -DEF rAUDVOL EQU rNR50 - -DEF AUDVOL_VIN_LEFT EQU %10000000 ; SO2 -DEF AUDVOL_VIN_RIGHT EQU %00001000 ; SO1 - - -; -- -; -- AUDTERM/NR51 ($FF25) -; -- Selection of Sound output terminal (R/W) -; -- -; -- Bit 7 - Output channel 4 to SO2 terminal (left) -; -- Bit 6 - Output channel 3 to SO2 terminal (left) -; -- Bit 5 - Output channel 2 to SO2 terminal (left) -; -- Bit 4 - Output channel 1 to SO2 terminal (left) -; -- Bit 3 - Output channel 4 to SO1 terminal (right) -; -- Bit 2 - Output channel 3 to SO1 terminal (right) -; -- Bit 1 - Output channel 2 to SO1 terminal (right) -; -- Bit 0 - Output channel 1 to SO1 terminal (right) -; -- -DEF rNR51 EQU $FF25 -DEF rAUDTERM EQU rNR51 - -; SO2 -DEF AUDTERM_4_LEFT EQU %10000000 -DEF AUDTERM_3_LEFT EQU %01000000 -DEF AUDTERM_2_LEFT EQU %00100000 -DEF AUDTERM_1_LEFT EQU %00010000 -; SO1 -DEF AUDTERM_4_RIGHT EQU %00001000 -DEF AUDTERM_3_RIGHT EQU %00000100 -DEF AUDTERM_2_RIGHT EQU %00000010 -DEF AUDTERM_1_RIGHT EQU %00000001 - - -; -- -; -- AUDENA/NR52 ($FF26) -; -- Sound on/off (R/W) -; -- -; -- Bit 7 - All sound on/off (sets all audio regs to 0!) -; -- Bit 3 - Sound 4 ON flag (read only) -; -- Bit 2 - Sound 3 ON flag (read only) -; -- Bit 1 - Sound 2 ON flag (read only) -; -- Bit 0 - Sound 1 ON flag (read only) -; -- -DEF rNR52 EQU $FF26 -DEF rAUDENA EQU rNR52 - -DEF AUDENA_ON EQU %10000000 -DEF AUDENA_OFF EQU %00000000 ; sets all audio regs to 0! - - -; -- -; -- LCDC ($FF40) -; -- LCD Control (R/W) -; -- -DEF rLCDC EQU $FF40 - -DEF LCDCF_OFF EQU %00000000 ; LCD Control Operation -DEF LCDCF_ON EQU %10000000 ; LCD Control Operation -DEF LCDCF_WIN9800 EQU %00000000 ; Window Tile Map Display Select -DEF LCDCF_WIN9C00 EQU %01000000 ; Window Tile Map Display Select -DEF LCDCF_WINOFF EQU %00000000 ; Window Display -DEF LCDCF_WINON EQU %00100000 ; Window Display -DEF LCDCF_BG8800 EQU %00000000 ; BG & Window Tile Data Select -DEF LCDCF_BG8000 EQU %00010000 ; BG & Window Tile Data Select -DEF LCDCF_BG9800 EQU %00000000 ; BG Tile Map Display Select -DEF LCDCF_BG9C00 EQU %00001000 ; BG Tile Map Display Select -DEF LCDCF_OBJ8 EQU %00000000 ; OBJ Construction -DEF LCDCF_OBJ16 EQU %00000100 ; OBJ Construction -DEF LCDCF_OBJOFF EQU %00000000 ; OBJ Display -DEF LCDCF_OBJON EQU %00000010 ; OBJ Display -DEF LCDCF_BGOFF EQU %00000000 ; BG Display -DEF LCDCF_BGON EQU %00000001 ; BG Display - -DEF LCDCB_ON EQU 7 ; LCD Control Operation -DEF LCDCB_WIN9C00 EQU 6 ; Window Tile Map Display Select -DEF LCDCB_WINON EQU 5 ; Window Display -DEF LCDCB_BG8000 EQU 4 ; BG & Window Tile Data Select -DEF LCDCB_BG9C00 EQU 3 ; BG Tile Map Display Select -DEF LCDCB_OBJ16 EQU 2 ; OBJ Construction -DEF LCDCB_OBJON EQU 1 ; OBJ Display -DEF LCDCB_BGON EQU 0 ; BG Display -; "Window Character Data Select" follows BG - - -; -- -; -- STAT ($FF41) -; -- LCDC Status (R/W) -; -- -DEF rSTAT EQU $FF41 - -DEF STATF_LYC EQU %01000000 ; LYC=LY Coincidence (Selectable) -DEF STATF_MODE10 EQU %00100000 ; Mode 10 -DEF STATF_MODE01 EQU %00010000 ; Mode 01 (V-Blank) -DEF STATF_MODE00 EQU %00001000 ; Mode 00 (H-Blank) -DEF STATF_LYCF EQU %00000100 ; Coincidence Flag -DEF STATF_HBL EQU %00000000 ; H-Blank -DEF STATF_VBL EQU %00000001 ; V-Blank -DEF STATF_OAM EQU %00000010 ; OAM-RAM is used by system -DEF STATF_LCD EQU %00000011 ; Both OAM and VRAM used by system -DEF STATF_BUSY EQU %00000010 ; When set, VRAM access is unsafe - -DEF STATB_LYC EQU 6 -DEF STATB_MODE10 EQU 5 -DEF STATB_MODE01 EQU 4 -DEF STATB_MODE00 EQU 3 -DEF STATB_LYCF EQU 2 -DEF STATB_BUSY EQU 1 - -; -- -; -- SCY ($FF42) -; -- Scroll Y (R/W) -; -- -DEF rSCY EQU $FF42 - - -; -- -; -- SCX ($FF43) -; -- Scroll X (R/W) -; -- -DEF rSCX EQU $FF43 - - -; -- -; -- LY ($FF44) -; -- LCDC Y-Coordinate (R) -; -- -; -- Values range from 0->153. 144->153 is the VBlank period. -; -- -DEF rLY EQU $FF44 - - -; -- -; -- LYC ($FF45) -; -- LY Compare (R/W) -; -- -; -- When LY==LYC, STATF_LYCF will be set in STAT -; -- -DEF rLYC EQU $FF45 - - -; -- -; -- DMA ($FF46) -; -- DMA Transfer and Start Address (W) -; -- -DEF rDMA EQU $FF46 - - -; -- -; -- BGP ($FF47) -; -- BG Palette Data (W) -; -- -; -- Bit 7-6 - Intensity for %11 -; -- Bit 5-4 - Intensity for %10 -; -- Bit 3-2 - Intensity for %01 -; -- Bit 1-0 - Intensity for %00 -; -- -DEF rBGP EQU $FF47 - - -; -- -; -- OBP0 ($FF48) -; -- Object Palette 0 Data (W) -; -- -; -- See BGP for info -; -- -DEF rOBP0 EQU $FF48 - - -; -- -; -- OBP1 ($FF49) -; -- Object Palette 1 Data (W) -; -- -; -- See BGP for info -; -- -DEF rOBP1 EQU $FF49 - - -; -- -; -- WY ($FF4A) -; -- Window Y Position (R/W) -; -- -; -- 0 <= WY <= 143 -; -- When WY = 0, the window is displayed from the top edge of the LCD screen. -; -- -DEF rWY EQU $FF4A - - -; -- -; -- WX ($FF4B) -; -- Window X Position (R/W) -; -- -; -- 7 <= WX <= 166 -; -- When WX = 7, the window is displayed from the left edge of the LCD screen. -; -- Values of 0-6 and 166 are unreliable due to hardware bugs. -; -- -DEF rWX EQU $FF4B - -DEF WX_OFS EQU 7 ; add this to a screen position to get a WX position - - -; -- -; -- SPEED ($FF4D) -; -- Select CPU Speed (R/W) -; -- -DEF rKEY1 EQU $FF4D -DEF rSPD EQU rKEY1 - -DEF KEY1F_DBLSPEED EQU %10000000 ; 0=Normal Speed, 1=Double Speed (R) -DEF KEY1F_PREPARE EQU %00000001 ; 0=No, 1=Prepare (R/W) - - -; -- -; -- VBK ($FF4F) -; -- Select Video RAM Bank (R/W) -; -- -; -- Bit 0 - Bank Specification (0: Specify Bank 0; 1: Specify Bank 1) -; -- -DEF rVBK EQU $FF4F - - -; -- -; -- HDMA1 ($FF51) -; -- High byte for Horizontal Blanking/General Purpose DMA source address (W) -; -- CGB Mode Only -; -- -DEF rHDMA1 EQU $FF51 - - -; -- -; -- HDMA2 ($FF52) -; -- Low byte for Horizontal Blanking/General Purpose DMA source address (W) -; -- CGB Mode Only -; -- -DEF rHDMA2 EQU $FF52 - - -; -- -; -- HDMA3 ($FF53) -; -- High byte for Horizontal Blanking/General Purpose DMA destination address (W) -; -- CGB Mode Only -; -- -DEF rHDMA3 EQU $FF53 - - -; -- -; -- HDMA4 ($FF54) -; -- Low byte for Horizontal Blanking/General Purpose DMA destination address (W) -; -- CGB Mode Only -; -- -DEF rHDMA4 EQU $FF54 - - -; -- -; -- HDMA5 ($FF55) -; -- Transfer length (in tiles minus 1)/mode/start for Horizontal Blanking, General Purpose DMA (R/W) -; -- CGB Mode Only -; -- -DEF rHDMA5 EQU $FF55 - -DEF HDMA5F_MODE_GP EQU %00000000 ; General Purpose DMA (W) -DEF HDMA5F_MODE_HBL EQU %10000000 ; HBlank DMA (W) -DEF HDMA5B_MODE EQU 7 ; DMA mode select (W) - -; -- Once DMA has started, use HDMA5F_BUSY to check when the transfer is complete -DEF HDMA5F_BUSY EQU %10000000 ; 0=Busy (DMA still in progress), 1=Transfer complete (R) - - -; -- -; -- RP ($FF56) -; -- Infrared Communications Port (R/W) -; -- CGB Mode Only -; -- -DEF rRP EQU $FF56 - -DEF RPF_ENREAD EQU %11000000 -DEF RPF_DATAIN EQU %00000010 ; 0=Receiving IR Signal, 1=Normal -DEF RPF_WRITE_HI EQU %00000001 -DEF RPF_WRITE_LO EQU %00000000 - -DEF RPB_LED_ON EQU 0 -DEF RPB_DATAIN EQU 1 - - -; -- -; -- BCPS/BGPI ($FF68) -; -- Background Color Palette Specification (aka Background Palette Index) (R/W) -; -- -DEF rBCPS EQU $FF68 -DEF rBGPI EQU rBCPS - -DEF BCPSF_AUTOINC EQU %10000000 ; Auto Increment (0=Disabled, 1=Increment after Writing) -DEF BCPSB_AUTOINC EQU 7 -DEF BGPIF_AUTOINC EQU BCPSF_AUTOINC -DEF BGPIB_AUTOINC EQU BCPSB_AUTOINC - - -; -- -; -- BCPD/BGPD ($FF69) -; -- Background Color Palette Data (aka Background Palette Data) (R/W) -; -- -DEF rBCPD EQU $FF69 -DEF rBGPD EQU rBCPD - - -; -- -; -- OCPS/OBPI ($FF6A) -; -- Object Color Palette Specification (aka Object Background Palette Index) (R/W) -; -- -DEF rOCPS EQU $FF6A -DEF rOBPI EQU rOCPS - -DEF OCPSF_AUTOINC EQU %10000000 ; Auto Increment (0=Disabled, 1=Increment after Writing) -DEF OCPSB_AUTOINC EQU 7 -DEF OBPIF_AUTOINC EQU OCPSF_AUTOINC -DEF OBPIB_AUTOINC EQU OCPSB_AUTOINC - - -; -- -; -- OCPD/OBPD ($FF6B) -; -- Object Color Palette Data (aka Object Background Palette Data) (R/W) -; -- -DEF rOCPD EQU $FF6B -DEF rOBPD EQU rOCPD - - -; -- -; -- SMBK/SVBK ($FF70) -; -- Select Main RAM Bank (R/W) -; -- -; -- Bit 2-0 - Bank Specification (0,1: Specify Bank 1; 2-7: Specify Banks 2-7) -; -- -DEF rSVBK EQU $FF70 -DEF rSMBK EQU rSVBK - - -; -- -; -- PCM12 ($FF76) -; -- Sound channel 1&2 PCM amplitude (R) -; -- -; -- Bit 7-4 - Copy of sound channel 2's PCM amplitude -; -- Bit 3-0 - Copy of sound channel 1's PCM amplitude -; -- -DEF rPCM12 EQU $FF76 - - -; -- -; -- PCM34 ($FF77) -; -- Sound channel 3&4 PCM amplitude (R) -; -- -; -- Bit 7-4 - Copy of sound channel 4's PCM amplitude -; -- Bit 3-0 - Copy of sound channel 3's PCM amplitude -; -- -DEF rPCM34 EQU $FF77 - - -; -- -; -- IE ($FFFF) -; -- Interrupt Enable (R/W) -; -- -DEF rIE EQU $FFFF - -DEF IEF_HILO EQU %00010000 ; Transition from High to Low of Pin number P10-P13 -DEF IEF_SERIAL EQU %00001000 ; Serial I/O transfer end -DEF IEF_TIMER EQU %00000100 ; Timer Overflow -DEF IEF_STAT EQU %00000010 ; STAT -DEF IEF_VBLANK EQU %00000001 ; V-Blank - -DEF IEB_HILO EQU 4 -DEF IEB_SERIAL EQU 3 -DEF IEB_TIMER EQU 2 -DEF IEB_STAT EQU 1 -DEF IEB_VBLANK EQU 0 - - -;*************************************************************************** -;* -;* Flags common to multiple sound channels -;* -;*************************************************************************** - -; -- -; -- Square wave duty cycle -; -- -; -- Can be used with AUD1LEN and AUD2LEN -; -- See AUD1LEN for more info -; -- -DEF AUDLEN_DUTY_12_5 EQU %00000000 ; 12.5% -DEF AUDLEN_DUTY_25 EQU %01000000 ; 25% -DEF AUDLEN_DUTY_50 EQU %10000000 ; 50% -DEF AUDLEN_DUTY_75 EQU %11000000 ; 75% - - -; -- -; -- Audio envelope flags -; -- -; -- Can be used with AUD1ENV, AUD2ENV, AUD4ENV -; -- See AUD1ENV for more info -; -- -DEF AUDENV_UP EQU %00001000 -DEF AUDENV_DOWN EQU %00000000 - - -; -- -; -- Audio trigger flags -; -- -; -- Can be used with AUD1HIGH, AUD2HIGH, AUD3HIGH -; -- See AUD1HIGH for more info -; -- -DEF AUDHIGH_RESTART EQU %10000000 -DEF AUDHIGH_LENGTH_ON EQU %01000000 -DEF AUDHIGH_LENGTH_OFF EQU %00000000 - - -;*************************************************************************** -;* -;* CPU values on bootup (a=type, b=qualifier) -;* -;*************************************************************************** - -DEF BOOTUP_A_DMG EQU $01 ; Dot Matrix Game -DEF BOOTUP_A_CGB EQU $11 ; Color GameBoy -DEF BOOTUP_A_MGB EQU $FF ; Mini GameBoy (Pocket GameBoy) - -; if a=BOOTUP_A_CGB, bit 0 in b can be checked to determine if real CGB or -; other system running in GBC mode -DEF BOOTUP_B_CGB EQU %00000000 -DEF BOOTUP_B_AGB EQU %00000001 ; GBA, GBA SP, Game Boy Player, or New GBA SP - - -;*************************************************************************** -;* -;* Header -;* -;*************************************************************************** - -;* -;* Nintendo scrolling logo -;* (Code won't work on a real GameBoy) -;* (if next lines are altered.) -MACRO NINTENDO_LOGO - DB $CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83,$00,$0C,$00,$0D - DB $00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6,$DD,$DD,$D9,$99 - DB $BB,$BB,$67,$63,$6E,$0E,$EC,$CC,$DD,$DC,$99,$9F,$BB,$B9,$33,$3E -ENDM - -; $0143 Color GameBoy compatibility code -DEF CART_COMPATIBLE_DMG EQU $00 -DEF CART_COMPATIBLE_DMG_GBC EQU $80 -DEF CART_COMPATIBLE_GBC EQU $C0 - -; $0146 GameBoy/Super GameBoy indicator -DEF CART_INDICATOR_GB EQU $00 -DEF CART_INDICATOR_SGB EQU $03 - -; $0147 Cartridge type -DEF CART_ROM EQU $00 -DEF CART_ROM_MBC1 EQU $01 -DEF CART_ROM_MBC1_RAM EQU $02 -DEF CART_ROM_MBC1_RAM_BAT EQU $03 -DEF CART_ROM_MBC2 EQU $05 -DEF CART_ROM_MBC2_BAT EQU $06 -DEF CART_ROM_RAM EQU $08 -DEF CART_ROM_RAM_BAT EQU $09 -DEF CART_ROM_MMM01 EQU $0B -DEF CART_ROM_MMM01_RAM EQU $0C -DEF CART_ROM_MMM01_RAM_BAT EQU $0D -DEF CART_ROM_MBC3_BAT_RTC EQU $0F -DEF CART_ROM_MBC3_RAM_BAT_RTC EQU $10 -DEF CART_ROM_MBC3 EQU $11 -DEF CART_ROM_MBC3_RAM EQU $12 -DEF CART_ROM_MBC3_RAM_BAT EQU $13 -DEF CART_ROM_MBC5 EQU $19 -DEF CART_ROM_MBC5_BAT EQU $1A -DEF CART_ROM_MBC5_RAM_BAT EQU $1B -DEF CART_ROM_MBC5_RUMBLE EQU $1C -DEF CART_ROM_MBC5_RAM_RUMBLE EQU $1D -DEF CART_ROM_MBC5_RAM_BAT_RUMBLE EQU $1E -DEF CART_ROM_MBC7_RAM_BAT_GYRO EQU $22 -DEF CART_ROM_POCKET_CAMERA EQU $FC -DEF CART_ROM_BANDAI_TAMA5 EQU $FD -DEF CART_ROM_HUDSON_HUC3 EQU $FE -DEF CART_ROM_HUDSON_HUC1 EQU $FF - -; $0148 ROM size -; these are kilobytes -DEF CART_ROM_32KB EQU $00 ; 2 banks -DEF CART_ROM_64KB EQU $01 ; 4 banks -DEF CART_ROM_128KB EQU $02 ; 8 banks -DEF CART_ROM_256KB EQU $03 ; 16 banks -DEF CART_ROM_512KB EQU $04 ; 32 banks -DEF CART_ROM_1024KB EQU $05 ; 64 banks -DEF CART_ROM_2048KB EQU $06 ; 128 banks -DEF CART_ROM_4096KB EQU $07 ; 256 banks -DEF CART_ROM_8192KB EQU $08 ; 512 banks -DEF CART_ROM_1152KB EQU $52 ; 72 banks -DEF CART_ROM_1280KB EQU $53 ; 80 banks -DEF CART_ROM_1536KB EQU $54 ; 96 banks - -; $0149 SRAM size -; these are kilobytes -DEF CART_SRAM_NONE EQU 0 -DEF CART_SRAM_8KB EQU 2 ; 1 bank -DEF CART_SRAM_32KB EQU 3 ; 4 banks -DEF CART_SRAM_128KB EQU 4 ; 16 banks - -; $014A Destination code -DEF CART_DEST_JAPANESE EQU $00 -DEF CART_DEST_NON_JAPANESE EQU $01 - - -;*************************************************************************** -;* -;* Keypad related -;* -;*************************************************************************** - -DEF PADF_DOWN EQU $80 -DEF PADF_UP EQU $40 -DEF PADF_LEFT EQU $20 -DEF PADF_RIGHT EQU $10 -DEF PADF_START EQU $08 -DEF PADF_SELECT EQU $04 -DEF PADF_B EQU $02 -DEF PADF_A EQU $01 - -DEF PADB_DOWN EQU $7 -DEF PADB_UP EQU $6 -DEF PADB_LEFT EQU $5 -DEF PADB_RIGHT EQU $4 -DEF PADB_START EQU $3 -DEF PADB_SELECT EQU $2 -DEF PADB_B EQU $1 -DEF PADB_A EQU $0 - - -;*************************************************************************** -;* -;* Screen related -;* -;*************************************************************************** - -DEF SCRN_X EQU 160 ; Width of screen in pixels -DEF SCRN_Y EQU 144 ; Height of screen in pixels. Also corresponds to the value in LY at the beginning of VBlank. -DEF SCRN_X_B EQU 20 ; Width of screen in bytes -DEF SCRN_Y_B EQU 18 ; Height of screen in bytes - -DEF SCRN_VX EQU 256 ; Virtual width of screen in pixels -DEF SCRN_VY EQU 256 ; Virtual height of screen in pixels -DEF SCRN_VX_B EQU 32 ; Virtual width of screen in bytes -DEF SCRN_VY_B EQU 32 ; Virtual height of screen in bytes - - -;*************************************************************************** -;* -;* OAM related -;* -;*************************************************************************** - -; OAM attributes -; each entry in OAM RAM is 4 bytes (sizeof_OAM_ATTRS) -RSRESET -DEF OAMA_Y RB 1 ; y pos plus 16 -DEF OAMA_X RB 1 ; x pos plus 8 -DEF OAMA_TILEID RB 1 ; tile id -DEF OAMA_FLAGS RB 1 ; flags (see below) -DEF sizeof_OAM_ATTRS RB 0 - -DEF OAM_Y_OFS EQU 16 ; add this to a screen-relative Y position to get an OAM Y position -DEF OAM_X_OFS EQU 8 ; add this to a screen-relative X position to get an OAM X position - -DEF OAM_COUNT EQU 40 ; number of OAM entries in OAM RAM - -; flags -DEF OAMF_PRI EQU %10000000 ; Priority -DEF OAMF_YFLIP EQU %01000000 ; Y flip -DEF OAMF_XFLIP EQU %00100000 ; X flip -DEF OAMF_PAL0 EQU %00000000 ; Palette number; 0,1 (DMG) -DEF OAMF_PAL1 EQU %00010000 ; Palette number; 0,1 (DMG) -DEF OAMF_BANK0 EQU %00000000 ; Bank number; 0,1 (GBC) -DEF OAMF_BANK1 EQU %00001000 ; Bank number; 0,1 (GBC) - -DEF OAMF_PALMASK EQU %00000111 ; Palette (GBC) - -DEF OAMB_PRI EQU 7 ; Priority -DEF OAMB_YFLIP EQU 6 ; Y flip -DEF OAMB_XFLIP EQU 5 ; X flip -DEF OAMB_PAL1 EQU 4 ; Palette number; 0,1 (DMG) -DEF OAMB_BANK1 EQU 3 ; Bank number; 0,1 (GBC) - - -; Deprecated constants. Please avoid using. - -DEF IEF_LCDC EQU %00000010 ; LCDC (see STAT) -DEF _VRAM8000 EQU _VRAM -DEF _VRAM8800 EQU _VRAM+$800 -DEF _VRAM9000 EQU _VRAM+$1000 -DEF CART_SRAM_2KB EQU 1 ; 1 incomplete bank - - - ENDC ;HARDWARE_INC \ No newline at end of file diff --git a/unbricked/input/input.asm b/unbricked/input/input.asm deleted file mode 100644 index 56c68c63..00000000 --- a/unbricked/input/input.asm +++ /dev/null @@ -1,45 +0,0 @@ -; This is a simplified version of pads.z80 by PinoBatch for use in gb-asm-tutorial -; All labels are intentionally not exported to avoid confusing the reader with unfamiliar syntax. -; Once linking is introduced in part 3, a new, exported version of this file will be provided. - -SECTION "Input Variables", WRAM0 -wCurKeys: db -wNewKeys: db - -SECTION "UpdateKeys", ROM0 - -UpdateKeys: - ; Poll half the controller - ld a, P1F_GET_BTN - call .onenibble - ld b, a ; B7-4 = 1; B3-0 = unpressed buttons - - ; Poll the other half - ld a, P1F_GET_DPAD - call .onenibble - swap a ; A3-0 = unpressed directions; A7-4 = 1 - xor a, b ; A = pressed buttons + directions - ld b, a ; B = pressed buttons + directions - - ; And release the controller - ld a, P1F_GET_NONE - ldh [rP1], a - - ; Combine with previous wCurKeys to make wNewKeys - ld a, [wCurKeys] - xor a, b ; A = keys that changed state - and a, b ; A = keys that changed to pressed - ld [wNewKeys], a - ld a, b - ld [wCurKeys], a - ret - -.onenibble - ldh [rP1], a ; switch the key matrix - call .knownret ; burn 10 cycles calling a known ret - ldh a, [rP1] ; ignore value while waiting for the key matrix to settle - ldh a, [rP1] - ldh a, [rP1] ; this read counts - or a, $F0 ; A7-4 = 1; A3-0 = unpressed keys -.knownret - ret diff --git a/unbricked/input/main.asm b/unbricked/input/main.asm deleted file mode 100644 index 7acef36d..00000000 --- a/unbricked/input/main.asm +++ /dev/null @@ -1,428 +0,0 @@ -INCLUDE "hardware.inc" - -SECTION "Header", ROM0[$100] - - jp EntryPoint - - ds $150 - @, 0 ; Make room for the header - -EntryPoint: - ; Do not turn the LCD off outside of VBlank -WaitVBlank: - ld a, [rLY] - cp 144 - jp c, WaitVBlank - - ; Turn the LCD off - ld a, 0 - ld [rLCDC], a - -; ANCHOR: copy_tiles - ; Copy the tile data - ld de, Tiles - ld hl, $9000 - ld bc, TilesEnd - Tiles - call Memcopy -; ANCHOR_END: copy_tiles - -; ANCHOR: copy_map - ; Copy the tilemap - ld de, Tilemap - ld hl, $9800 - ld bc, TilemapEnd - Tilemap - call Memcopy -; ANCHOR_END: copy_map - -; ANCHOR: copy_paddle - ; Copy the paddle tile - ld de, Paddle - ld hl, $8000 - ld bc, PaddleEnd - Paddle - call Memcopy -; ANCHOR_END: copy_paddle - - xor a, a - ld b, 160 - ld hl, _OAMRAM -ClearOam: - ld [hli], a - dec b - jp nz, ClearOam - - ld hl, _OAMRAM - ld a, 128 + 16 - ld [hli], a - ld a, 16 + 8 - ld [hli], a - ld a, 0 - ld [hli], a - ld [hl], a - - ; Turn the LCD on - ld a, LCDCF_ON | LCDCF_BGON | LCDCF_OBJON - ld [rLCDC], a - - ; During the first (blank) frame, initialize display registers - ld a, %11100100 - ld [rBGP], a - ld a, %11100100 - ld [rOBP0], a - - ; ANCHOR: initialize-vars - ; Initialize global variables - ld a, 0 - ld [wFrameCounter], a - ld [wCurKeys], a - ld [wNewKeys], a - ; ANCHOR_END: initialize-vars - -; ANCHOR: main -Main: - ld a, [rLY] - cp 144 - jp nc, Main -WaitVBlank2: - ld a, [rLY] - cp 144 - jp c, WaitVBlank2 - - ; Check the current keys every frame and move left or right. - call UpdateKeys - - ; First, check if the left button is pressed. -CheckLeft: - ld a, [wCurKeys] - and a, PADF_LEFT - jp z, CheckRight -Left: - ; Move the paddle one pixel to the left. - ld a, [_OAMRAM + 1] - dec a - ; If we've already hit the edge of the playfield, don't move. - cp a, 15 - jp z, Main - ld [_OAMRAM + 1], a - jp Main - -; Then check the right button. -CheckRight: - ld a, [wCurKeys] - and a, PADF_RIGHT - jp z, Main -Right: - ; Move the paddle one pixel to the right. - ld a, [_OAMRAM + 1] - inc a - ; If we've already hit the edge of the playfield, don't move. - cp a, 105 - jp z, Main - ld [_OAMRAM + 1], a - jp Main -; ANCHOR_END: main - -; ANCHOR: input-routine -UpdateKeys: - ; Poll half the controller - ld a, P1F_GET_BTN - call .onenibble - ld b, a ; B7-4 = 1; B3-0 = unpressed buttons - - ; Poll the other half - ld a, P1F_GET_DPAD - call .onenibble - swap a ; A7-4 = unpressed directions; A3-0 = 1 - xor a, b ; A = pressed buttons + directions - ld b, a ; B = pressed buttons + directions - - ; And release the controller - ld a, P1F_GET_NONE - ldh [rP1], a - - ; Combine with previous wCurKeys to make wNewKeys - ld a, [wCurKeys] - xor a, b ; A = keys that changed state - and a, b ; A = keys that changed to pressed - ld [wNewKeys], a - ld a, b - ld [wCurKeys], a - ret - -.onenibble - ldh [rP1], a ; switch the key matrix - call .knownret ; burn 10 cycles calling a known ret - ldh a, [rP1] ; ignore value while waiting for the key matrix to settle - ldh a, [rP1] - ldh a, [rP1] ; this read counts - or a, $F0 ; A7-4 = 1; A3-0 = unpressed keys -.knownret - ret -; ANCHOR_END: input-routine - -; ANCHOR: memcpy -; Copy bytes from one area to another. -; @param de: Source -; @param hl: Destination -; @param bc: Length -Memcopy: - ld a, [de] - ld [hli], a - inc de - dec bc - ld a, b - or a, c - jp nz, Memcopy - ret -; ANCHOR_END: memcpy - -Tiles: - dw `33333333 - dw `33333333 - dw `33333333 - dw `33322222 - dw `33322222 - dw `33322222 - dw `33322211 - dw `33322211 - dw `33333333 - dw `33333333 - dw `33333333 - dw `22222222 - dw `22222222 - dw `22222222 - dw `11111111 - dw `11111111 - dw `33333333 - dw `33333333 - dw `33333333 - dw `22222333 - dw `22222333 - dw `22222333 - dw `11222333 - dw `11222333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `22222222 - dw `20000000 - dw `20111111 - dw `20111111 - dw `20111111 - dw `20111111 - dw `22222222 - dw `33333333 - dw `22222223 - dw `00000023 - dw `11111123 - dw `11111123 - dw `11111123 - dw `11111123 - dw `22222223 - dw `33333333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `11001100 - dw `11111111 - dw `11111111 - dw `21212121 - dw `22222222 - dw `22322232 - dw `23232323 - dw `33333333 - ; My custom logo (tail) - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33302333 - dw `33333133 - dw `33300313 - dw `33300303 - dw `33013330 - dw `30333333 - dw `03333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `03333333 - dw `30333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333330 - dw `33333320 - dw `33333013 - dw `33330333 - dw `33100333 - dw `31001333 - dw `20001333 - dw `00000333 - dw `00000033 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33330333 - dw `33300333 - dw `33333333 - dw `33033333 - dw `33133333 - dw `33303333 - dw `33303333 - dw `33303333 - dw `33332333 - dw `33332333 - dw `33333330 - dw `33333300 - dw `33333300 - dw `33333100 - dw `33333000 - dw `33333000 - dw `33333100 - dw `33333300 - dw `00000001 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `10000333 - dw `00000033 - dw `00000003 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `33332333 - dw `33302333 - dw `32003333 - dw `00003333 - dw `00003333 - dw `00013333 - dw `00033333 - dw `00033333 - dw `33333300 - dw `33333310 - dw `33333330 - dw `33333332 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `30000000 - dw `33000000 - dw `33333000 - dw `33333333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000003 - dw `00000033 - dw `00003333 - dw `02333333 - dw `33333333 - dw `00333333 - dw `03333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 -TilesEnd: - -Tilemap: - db $00, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $02, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $0A, $0B, $0C, $0D, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $0E, $0F, $10, $11, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $12, $13, $14, $15, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $16, $17, $18, $19, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $09, $09, $09, $09, $09, $09, $09, $09, $09, $09, $09, $09, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 -TilemapEnd: - -Paddle: - dw `33333333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 -PaddleEnd: - -SECTION "Counter", WRAM0 -wFrameCounter: db - -; ANCHOR: vars -SECTION "Input Variables", WRAM0 -wCurKeys: db -wNewKeys: db -; ANCHOR_END: vars diff --git a/unbricked/map2asm.c b/unbricked/map2asm.c deleted file mode 100644 index b887180f..00000000 --- a/unbricked/map2asm.c +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include -#include - -int main(int argc, char ** argv) { - if (argc != 4) { - fprintf(stderr, "Expected 4 arguments\nUsage: %s ", argv[0]); - exit(1); - } - - FILE * infile = fopen(argv[1], "rb"); - FILE * outfile = fopen(argv[2], "w"); - - if (!infile) { - perror("infile"); - exit(1); - } - - if (!outfile) { - perror("outfile"); - exit(1); - } - - char * pixels = argv[1]; - - while (1) { - fputs("\tdb ", outfile); - for (int i = 0; i < 20; i++) { - int byte = fgetc(infile); - if (byte == EOF) exit(0); - fprintf(outfile, "$%X, ", byte); - } - fputs("0,0,0,0,0,0,0,0,0,0,0,0\n", outfile); - } -} diff --git a/unbricked/objects/main.asm b/unbricked/objects/main.asm deleted file mode 100644 index b0126daa..00000000 --- a/unbricked/objects/main.asm +++ /dev/null @@ -1,376 +0,0 @@ -; ANCHOR: dummy Lines beginning with `ANCHOR` and `ANCHOR_END` are used by mdBook -; ANCHOR_END: dummy Note that lines matching /^; ANCHOR/ are stripped from the online version -INCLUDE "hardware.inc" - -SECTION "Header", ROM0[$100] - - jp EntryPoint - - ds $150 - @, 0 ; Make room for the header - -EntryPoint: - ; Do not turn the LCD off outside of VBlank -WaitVBlank: - ld a, [rLY] - cp 144 - jp c, WaitVBlank - - ; Turn the LCD off - ld a, 0 - ld [rLCDC], a - - ; Copy the tile data - ld de, Tiles - ld hl, $9000 - ld bc, TilesEnd - Tiles -CopyTiles: - ld a, [de] - ld [hli], a - inc de - dec bc - ld a, b - or a, c - jp nz, CopyTiles - - ; Copy the tilemap - ld de, Tilemap - ld hl, $9800 - ld bc, TilemapEnd - Tilemap -CopyTilemap: - ld a, [de] - ld [hli], a - inc de - dec bc - ld a, b - or a, c - jp nz, CopyTilemap - -; ANCHOR: copy-paddle - ; Copy the paddle tile - ld de, Paddle - ld hl, $8000 - ld bc, PaddleEnd - Paddle -CopyPaddle: - ld a, [de] - ld [hli], a - inc de - dec bc - ld a, b - or a, c - jp nz, CopyPaddle -; ANCHOR_END: copy-paddle - -; ANCHOR: clear-oam - ld a, 0 - ld b, 160 - ld hl, _OAMRAM -ClearOam: - ld [hli], a - dec b - jp nz, ClearOam -; ANCHOR_END: clear-oam - -; ANCHOR: init-object - ld hl, _OAMRAM - ld a, 128 + 16 - ld [hli], a - ld a, 16 + 8 - ld [hli], a - ld a, 0 - ld [hli], a - ld [hli], a -; ANCHOR_END: init-object - -; ANCHOR: enable-oam - ; Turn the LCD on - ld a, LCDCF_ON | LCDCF_BGON | LCDCF_OBJON - ld [rLCDC], a - - ; During the first (blank) frame, initialize display registers - ld a, %11100100 - ld [rBGP], a - ld a, %11100100 - ld [rOBP0], a -; ANCHOR_END: enable-oam - -; ANCHOR: main-loop - ; Initialize global variables - ld a, 0 - ld [wFrameCounter], a - -Main: - ld a, [rLY] - cp 144 - jp nc, Main -WaitVBlank2: - ld a, [rLY] - cp 144 - jp c, WaitVBlank2 - - ld a, [wFrameCounter] - inc a - ld [wFrameCounter], a - cp a, 15 ; Every 15 frames (a quarter of a second), run the following code - jp nz, Main - - ; Reset the frame counter back to 0 - ld a, 0 - ld [wFrameCounter], a - - ; Move the paddle one pixel to the right. - ld a, [_OAMRAM + 1] - inc a - ld [_OAMRAM + 1], a - jp Main -; ANCHOR_END: main-loop - -Tiles: - dw `33333333 - dw `33333333 - dw `33333333 - dw `33322222 - dw `33322222 - dw `33322222 - dw `33322211 - dw `33322211 - dw `33333333 - dw `33333333 - dw `33333333 - dw `22222222 - dw `22222222 - dw `22222222 - dw `11111111 - dw `11111111 - dw `33333333 - dw `33333333 - dw `33333333 - dw `22222333 - dw `22222333 - dw `22222333 - dw `11222333 - dw `11222333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `33322211 - dw `22222222 - dw `20000000 - dw `20111111 - dw `20111111 - dw `20111111 - dw `20111111 - dw `22222222 - dw `33333333 - dw `22222223 - dw `00000023 - dw `11111123 - dw `11111123 - dw `11111123 - dw `11111123 - dw `22222223 - dw `33333333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `11222333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `11001100 - dw `11111111 - dw `11111111 - dw `21212121 - dw `22222222 - dw `22322232 - dw `23232323 - dw `33333333 - ; My custom logo (tail) - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33302333 - dw `33333133 - dw `33300313 - dw `33300303 - dw `33013330 - dw `30333333 - dw `03333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `03333333 - dw `30333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333330 - dw `33333320 - dw `33333013 - dw `33330333 - dw `33100333 - dw `31001333 - dw `20001333 - dw `00000333 - dw `00000033 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33330333 - dw `33300333 - dw `33333333 - dw `33033333 - dw `33133333 - dw `33303333 - dw `33303333 - dw `33303333 - dw `33332333 - dw `33332333 - dw `33333330 - dw `33333300 - dw `33333300 - dw `33333100 - dw `33333000 - dw `33333000 - dw `33333100 - dw `33333300 - dw `00000001 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `10000333 - dw `00000033 - dw `00000003 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `33332333 - dw `33302333 - dw `32003333 - dw `00003333 - dw `00003333 - dw `00013333 - dw `00033333 - dw `00033333 - dw `33333300 - dw `33333310 - dw `33333330 - dw `33333332 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `30000000 - dw `33000000 - dw `33333000 - dw `33333333 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000003 - dw `00000033 - dw `00003333 - dw `02333333 - dw `33333333 - dw `00333333 - dw `03333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 - dw `33333333 -TilesEnd: - -Tilemap: - db $00, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $02, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $05, $06, $05, $06, $05, $06, $05, $06, $05, $06, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $0A, $0B, $0C, $0D, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $0E, $0F, $10, $11, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $12, $13, $14, $15, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $08, $07, $03, $16, $17, $18, $19, $03, 0,0,0,0,0,0,0,0,0,0,0,0 - db $04, $09, $09, $09, $09, $09, $09, $09, $09, $09, $09, $09, $09, $07, $03, $03, $03, $03, $03, $03, 0,0,0,0,0,0,0,0,0,0,0,0 -TilemapEnd: - -; ANCHOR: paddle-gfx -Paddle: - dw `13333331 - dw `30000003 - dw `13333331 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 - dw `00000000 -PaddleEnd: -; ANCHOR_END: paddle-gfx - -; ANCHOR: variables -SECTION "Counter", WRAM0 -wFrameCounter: db -; ANCHOR_END: variables