Compare commits

..

1285 commits

Author SHA1 Message Date
Alex Janka 21e0cb309a remove .github folder 2024-11-16 10:40:06 +11:00
Alex Janka 22167ac608 add OwnedTileSet 2024-11-16 10:36:14 +11:00
Alex Janka 6d942b07d0 add link port uart 2024-11-16 10:11:49 +11:00
Gwilym Inzani 16c1fade94
Update Rust crate xmrs to v0.8.5 (#786)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [xmrs](https://codeberg.org/sbechet/xmrs) | dependencies | patch |
`=0.8.1` -> `=0.8.5` |

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4xMjAuMSIsInVwZGF0ZWRJblZlciI6IjM4LjEyMC4xIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbXX0=-->
2024-11-06 10:08:13 +00:00
Gwilym Inzani 0333a631f8 Don't divide by 64 any more 2024-11-06 09:59:34 +00:00
Gwilym Inzani 3be63230de Get it all compiling again 2024-11-06 09:51:15 +00:00
Gwilym Inzani 8e885a83b3
Update Javascript packages (non-major) (#803)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@types/node](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node)
([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node))
| [`22.8.4` ->
`22.9.0`](https://renovatebot.com/diffs/npm/@types%2fnode/22.8.4/22.9.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/22.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/22.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/22.8.4/22.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/22.8.4/22.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[eslint-config-next](https://nextjs.org/docs/app/building-your-application/configuring/eslint#eslint-config)
([source](https://redirect.github.com/vercel/next.js/tree/HEAD/packages/eslint-config-next))
| [`14.2.16` ->
`14.2.17`](https://renovatebot.com/diffs/npm/eslint-config-next/14.2.16/14.2.17)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/eslint-config-next/14.2.17?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/eslint-config-next/14.2.17?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/eslint-config-next/14.2.16/14.2.17?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/eslint-config-next/14.2.16/14.2.17?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [next](https://nextjs.org)
([source](https://redirect.github.com/vercel/next.js)) | [`14.2.16` ->
`14.2.17`](https://renovatebot.com/diffs/npm/next/14.2.16/14.2.17) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/next/14.2.17?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/next/14.2.17?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/next/14.2.16/14.2.17?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/next/14.2.16/14.2.17?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>vercel/next.js (eslint-config-next)</summary>

###
[`v14.2.17`](https://redirect.github.com/vercel/next.js/compare/v14.2.16...v14.2.17)

[Compare
Source](https://redirect.github.com/vercel/next.js/compare/v14.2.16...v14.2.17)

</details>

<details>
<summary>vercel/next.js (next)</summary>

###
[`v14.2.17`](https://redirect.github.com/vercel/next.js/compare/v14.2.16...v14.2.17)

[Compare
Source](https://redirect.github.com/vercel/next.js/compare/v14.2.16...v14.2.17)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any
time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4xNDIuNCIsInVwZGF0ZWRJblZlciI6IjM4LjE0Mi43IiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbXX0=-->
2024-11-06 09:38:18 +00:00
Gwilym Inzani 3e87a02d04
Update Rust crate thiserror to v2 (#804)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [thiserror](https://redirect.github.com/dtolnay/thiserror) |
dependencies | major | `1` -> `2` |

---

### Release Notes

<details>
<summary>dtolnay/thiserror (thiserror)</summary>

###
[`v2.0.0`](https://redirect.github.com/dtolnay/thiserror/releases/tag/2.0.0)

[Compare
Source](https://redirect.github.com/dtolnay/thiserror/compare/1.0.68...2.0.0)

#### Breaking changes

- Referencing keyword-named fields by a raw identifier like `{r#type}`
inside a format string is no longer accepted; simply use the unraw name
like `{type}`
([#&#8203;347](https://redirect.github.com/dtolnay/thiserror/issues/347))

This aligns thiserror with the standard library's formatting macros,
which gained support for implicit argument capture later than the
release of this feature in thiserror 1.x.

    ```rust
    #[derive(Error, Debug)]
    #[error("... {type} ...")]  // Before: {r#type}
    pub struct Error {
        pub r#type: Type,
    }
    ```

- Trait bounds are no longer inferred on fields whose value is shadowed
by an explicit named argument in a format message
([#&#8203;345](https://redirect.github.com/dtolnay/thiserror/issues/345))

    ```rust
    // Before: impl<T: Octal> Display for Error<T>
    // After: impl<T> Display for Error<T>
    #[derive(Error, Debug)]
    #[error("{thing:o}", thing = "...")]
    pub struct Error<T> {
        thing: T,
    }
    ```

- Tuple structs and tuple variants can no longer use numerical `{0}`
`{1}` access at the same time as supplying extra positional arguments
for a format message, as this makes it ambiguous whether the number
refers to a tuple field vs a different positional arg
([#&#8203;354](https://redirect.github.com/dtolnay/thiserror/issues/354))

    ```rust
    #[derive(Error, Debug)]
    #[error("ambiguous: {0} {}", $N)]
// ^^^ Not allowed, use #[error("... {0} {n}", n = $N)]
    pub struct TupleError(i32);
    ```

- Code containing invocations of thiserror's `derive(Error)` must now
have a direct dependency on the `thiserror` crate regardless of the
error data structure's contents
([#&#8203;368](https://redirect.github.com/dtolnay/thiserror/issues/368),
[#&#8203;369](https://redirect.github.com/dtolnay/thiserror/issues/369),
[#&#8203;370](https://redirect.github.com/dtolnay/thiserror/issues/370),
[#&#8203;372](https://redirect.github.com/dtolnay/thiserror/issues/372))

#### Features

- Support disabling thiserror's standard library dependency by disabling
the default "std" Cargo feature: `thiserror = { version = "2",
default-features = false }`
([#&#8203;373](https://redirect.github.com/dtolnay/thiserror/issues/373))

- Support using `r#source` as field name to opt out of a field named
"source" being treated as an error's `Error::source()`
([#&#8203;350](https://redirect.github.com/dtolnay/thiserror/issues/350))

    ```rust
    #[derive(Error, Debug)]
    #[error("{source} ==> {destination}")]
    pub struct Error {
        r#source: char,
        destination: char,
    }

    let error = Error { source: 'S', destination: 'D' };
    ```

- Infinite recursion in a generated Display impl now produces an
`unconditional_recursion` warning
([#&#8203;359](https://redirect.github.com/dtolnay/thiserror/issues/359))

    ```rust
    #[derive(Error, Debug)]
    #[error("??? {self}")]
    pub struct Error;
    ```

- A new attribute `#[error(fmt = path::to::myfmt)]` can be used to write
formatting logic for an enum variant out-of-line
([#&#8203;367](https://redirect.github.com/dtolnay/thiserror/issues/367))

    ```rust
    #[derive(Error, Debug)]
    pub enum Error {
        #[error(fmt = demo_fmt)]
        Demo { code: u16, message: Option<String> },
    }

fn demo_fmt(code: &u16, message: &Option<String>, formatter: &mut
fmt::Formatter) -> fmt::Result {
        write!(formatter, "{code}")?;
        if let Some(msg) = message {
            write!(formatter, " - {msg}")?;
        }
        Ok(())
    }
    ```

- Enums with an enum-level format message are now able to have
individual variants that are `transparent` to supersede the enum-level
message
([#&#8203;366](https://redirect.github.com/dtolnay/thiserror/issues/366))

    ```rust
    #[derive(Error, Debug)]
    #[error("my error {0}")]
    pub enum Error {
        Json(#[from] serde_json::Error),
        Yaml(#[from] serde_yaml::Error),
        #[error(transparent)]
        Other(#[from] anyhow::Error),
    }
    ```

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4xNDIuNyIsInVwZGF0ZWRJblZlciI6IjM4LjE0Mi43IiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbXX0=-->
2024-11-06 09:38:03 +00:00
renovate[bot] 8e6f5a2016
Update Rust crate thiserror to v2 2024-11-06 03:20:03 +00:00
renovate[bot] b7d794f18f
Update Javascript packages (non-major) 2024-11-06 02:16:34 +00:00
Gwilym Inzani 1cc2ffbc7f
Add some keywords to the main agb crates (#802)
Might be nice to have these keywords show up in crates.io

- [x] no changelog update needed
2024-10-30 11:53:33 +00:00
Gwilym Inzani 0c2c8eaeb5 Add some keywords to the main agb crates 2024-10-30 11:43:48 +00:00
Gwilym Inzani 25834705aa
Update Javascript packages (non-major) (#795)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@types/node](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node)
([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node))
| [`22.8.2` ->
`22.8.4`](https://renovatebot.com/diffs/npm/@types%2fnode/22.8.2/22.8.4)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/22.8.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/22.8.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/22.8.2/22.8.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/22.8.2/22.8.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@types/react](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react)
([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react))
| [`18.3.11` ->
`18.3.12`](https://renovatebot.com/diffs/npm/@types%2freact/18.3.11/18.3.12)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2freact/18.3.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2freact/18.3.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2freact/18.3.11/18.3.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2freact/18.3.11/18.3.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[eslint-config-next](https://nextjs.org/docs/app/building-your-application/configuring/eslint#eslint-config)
([source](https://redirect.github.com/vercel/next.js/tree/HEAD/packages/eslint-config-next))
| [`14.2.15` ->
`14.2.16`](https://renovatebot.com/diffs/npm/eslint-config-next/14.2.15/14.2.16)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/eslint-config-next/14.2.16?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/eslint-config-next/14.2.16?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/eslint-config-next/14.2.15/14.2.16?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/eslint-config-next/14.2.15/14.2.16?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [next](https://nextjs.org)
([source](https://redirect.github.com/vercel/next.js)) | [`14.2.15` ->
`14.2.16`](https://renovatebot.com/diffs/npm/next/14.2.15/14.2.16) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/next/14.2.16?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/next/14.2.16?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/next/14.2.15/14.2.16?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/next/14.2.15/14.2.16?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[react-syntax-highlighter](https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter)
| [`15.5.0` ->
`15.6.1`](https://renovatebot.com/diffs/npm/react-syntax-highlighter/15.5.0/15.6.1)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/react-syntax-highlighter/15.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/react-syntax-highlighter/15.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/react-syntax-highlighter/15.5.0/15.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/react-syntax-highlighter/15.5.0/15.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>vercel/next.js (eslint-config-next)</summary>

###
[`v14.2.16`](https://redirect.github.com/vercel/next.js/compare/v14.2.15...v14.2.16)

[Compare
Source](https://redirect.github.com/vercel/next.js/compare/v14.2.15...v14.2.16)

</details>

<details>
<summary>vercel/next.js (next)</summary>

###
[`v14.2.16`](https://redirect.github.com/vercel/next.js/compare/v14.2.15...v14.2.16)

[Compare
Source](https://redirect.github.com/vercel/next.js/compare/v14.2.15...v14.2.16)

</details>

<details>
<summary>react-syntax-highlighter/react-syntax-highlighter
(react-syntax-highlighter)</summary>

###
[`v15.6.1`](https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/blob/HEAD/CHANGELOG.MD#1561)

[Compare
Source](https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/compare/v15.6.0...v15.6.1)

- Fix: Allow override of `display:` styles when `wrapLongLines` is true

###
[`v15.6.0`](https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/blob/HEAD/CHANGELOG.MD#1560)

[Compare
Source](https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/compare/15.5.0...v15.6.0)

- Fix:
[#&#8203;561](https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/issues/561)
Fix bug with wrapLines that butchers highlighting
- Docs:
[#&#8203;559](https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/issues/559)
Adding languages
- Feat:
[#&#8203;555](https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/issues/555)
Add Vue language support
- Feat:
[#&#8203;534](https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/issues/534)
Add a11yOneLight theme

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any
time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4xMjAuMSIsInVwZGF0ZWRJblZlciI6IjM4LjEzNS4yIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbXX0=-->
2024-10-30 11:33:33 +00:00
Gwilym Inzani 0e1820e29a
Optional serde support agb hashmap (#801)
Probably worth having serde support in agb_hashmap.

- [x] Changelog updated
2024-10-30 11:33:17 +00:00
renovate[bot] 6351397256
Update Javascript packages (non-major) 2024-10-30 11:19:49 +00:00
Gwilym Inzani b9d8220509
Update dependency @types/node to v22 (#799)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@types/node](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node)
([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node))
| [`^20` ->
`^22.0.0`](https://renovatebot.com/diffs/npm/@types%2fnode/20.16.11/22.8.4)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/22.8.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/22.8.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/20.16.11/22.8.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/20.16.11/22.8.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4xMzMuMSIsInVwZGF0ZWRJblZlciI6IjM4LjEzMy4xIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbXX0=-->
2024-10-30 11:19:07 +00:00
Gwilym Inzani 246baabcf8 Changelog entry for serde support in agb-hashmap 2024-10-30 11:18:07 +00:00
Gwilym Inzani e1e0af7418 Ensure the hashmap tests get run with serde 2024-10-30 11:08:49 +00:00
Gwilym Inzani b71c544b9a implement serde for HashSet and tests 2024-10-30 10:56:19 +00:00
Gwilym Inzani 69219e3d73 Pull the hashmap Serialize/Deserialize impl into a module 2024-10-30 10:36:36 +00:00
Gwilym Inzani b2d0e93f8c Add serde support to agb_hashmap::HashMap 2024-10-30 10:35:48 +00:00
Gwilym Inzani 406964c28e
isqrt is now stable (#800)
This was causing the build to fail

- [x] no changelog update needed
2024-10-30 10:20:05 +00:00
Gwilym Inzani bdad7e101d isqrt is now stable 2024-10-30 10:12:45 +00:00
renovate[bot] 5d7bda21b1
Update dependency @types/node to v22 2024-10-29 00:16:32 +00:00
renovate[bot] 103dfd52db
Update Rust crate xmrs to v0.8.5 2024-10-20 22:39:55 +00:00
Gwilym Inzani 288789fce8
Update Javascript packages (non-major) (#782)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@types/node](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node)
([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node))
| [`20.16.10` ->
`20.16.11`](https://renovatebot.com/diffs/npm/@types%2fnode/20.16.10/20.16.11)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/20.16.11?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/20.16.11?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/20.16.10/20.16.11?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/20.16.10/20.16.11?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@types/react-dom](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react-dom)
([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom))
| [`18.3.0` ->
`18.3.1`](https://renovatebot.com/diffs/npm/@types%2freact-dom/18.3.0/18.3.1)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2freact-dom/18.3.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2freact-dom/18.3.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2freact-dom/18.3.0/18.3.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2freact-dom/18.3.0/18.3.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[eslint-config-next](https://nextjs.org/docs/app/building-your-application/configuring/eslint#eslint-config)
([source](https://redirect.github.com/vercel/next.js/tree/HEAD/packages/eslint-config-next))
| [`14.2.14` ->
`14.2.15`](https://renovatebot.com/diffs/npm/eslint-config-next/14.2.14/14.2.15)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/eslint-config-next/14.2.15?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/eslint-config-next/14.2.15?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/eslint-config-next/14.2.14/14.2.15?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/eslint-config-next/14.2.14/14.2.15?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [next](https://nextjs.org)
([source](https://redirect.github.com/vercel/next.js)) | [`14.2.14` ->
`14.2.15`](https://renovatebot.com/diffs/npm/next/14.2.14/14.2.15) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/next/14.2.15?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/next/14.2.15?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/next/14.2.14/14.2.15?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/next/14.2.14/14.2.15?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [typescript](https://www.typescriptlang.org/)
([source](https://redirect.github.com/microsoft/TypeScript)) | [`5.6.2`
-> `5.6.3`](https://renovatebot.com/diffs/npm/typescript/5.6.2/5.6.3) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/typescript/5.6.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/typescript/5.6.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/typescript/5.6.2/5.6.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/typescript/5.6.2/5.6.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>vercel/next.js (eslint-config-next)</summary>

###
[`v14.2.15`](https://redirect.github.com/vercel/next.js/releases/tag/v14.2.15)

[Compare
Source](https://redirect.github.com/vercel/next.js/compare/v14.2.14...v14.2.15)

> \[!NOTE]\
> This release is backporting bug fixes. It does **not** include all
pending features/changes on canary.

##### Core Changes

- support breadcrumb style catch-all parallel routes
[#&#8203;65063](https://redirect.github.com/vercel/next.js/issues/65063)
- Provide non-dynamic segments to catch-all parallel routes
[#&#8203;65233](https://redirect.github.com/vercel/next.js/issues/65233)
- Fix client reference access causing metadata missing
[#&#8203;70732](https://redirect.github.com/vercel/next.js/issues/70732)
- feat(next/image): add support for decoding prop
[#&#8203;70298](https://redirect.github.com/vercel/next.js/issues/70298)
- feat(next/image): add images.localPatterns config
[#&#8203;70529](https://redirect.github.com/vercel/next.js/issues/70529)
- fix(next/image): handle undefined images.localPatterns config in
images-manifest.json
- fix: Do not omit alt on getImgProps return type, ImgProps
[#&#8203;70608](https://redirect.github.com/vercel/next.js/issues/70608)
- \[i18n] Routing fix
[#&#8203;70761](https://redirect.github.com/vercel/next.js/issues/70761)

##### Credits

Huge thanks to [@&#8203;ztanner](https://redirect.github.com/ztanner),
[@&#8203;agadzik](https://redirect.github.com/agadzik),
[@&#8203;huozhi](https://redirect.github.com/huozhi),
[@&#8203;styfle](https://redirect.github.com/styfle),
[@&#8203;icyJoseph](https://redirect.github.com/icyJoseph) and
[@&#8203;wyattjoh](https://redirect.github.com/wyattjoh) for helping!

</details>

<details>
<summary>microsoft/TypeScript (typescript)</summary>

###
[`v5.6.3`](https://redirect.github.com/microsoft/TypeScript/compare/v5.6.2...d48a5cf89a62a62d6c6ed53ffa18f070d9458b85)

[Compare
Source](https://redirect.github.com/microsoft/TypeScript/compare/v5.6.2...v5.6.3)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any
time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC45Ny4wIiwidXBkYXRlZEluVmVyIjoiMzguMTIwLjEiLCJ0YXJnZXRCcmFuY2giOiJtYXN0ZXIiLCJsYWJlbHMiOltdfQ==-->
2024-10-15 20:40:58 +01:00
Gwilym Inzani dd9fd61723
Fix the xmrs version since we've had failures twice (#785)
Will need to release 0.21.2 after this is merged since current no
lockfile builds are failing.

- [x] change log updated
2024-10-15 20:40:48 +01:00
renovate[bot] 5ce6d586e8
Update Javascript packages (non-major) 2024-10-15 19:35:11 +00:00
Gwilym Inzani f49863a3d0 Add entry for xmrs breaking change in the changelog 2024-10-15 20:33:20 +01:00
Gwilym Inzani c81b8488db Fix the xmrs version since we've had failures twice 2024-10-15 19:58:14 +01:00
Gwilym Inzani 89403d0aae
Fix clippy lints from 2024-10-11 (#784)
Unnecessary conversions. Seems to have actually come from a minor
version bump of xmrs

- [x] no changelog update needed
2024-10-11 20:55:40 +01:00
Gwilym Inzani a45246a0e8 Fix clippy lints from 2024-10-11 2024-10-11 20:47:42 +01:00
Gwilym Inzani 06bd8d950c
Update Rust crate xmrs to v0.8.0 (#779)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [xmrs](https://codeberg.org/sbechet/xmrs) | dependencies | minor |
`0.7` -> `0.8` |
| [xmrs](https://codeberg.org/sbechet/xmrs) | dependencies | minor |
`0.7.2` -> `0.8.0` |

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these
updates again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC45Ny4wIiwidXBkYXRlZEluVmVyIjoiMzguOTcuMCIsInRhcmdldEJyYW5jaCI6Im1hc3RlciIsImxhYmVscyI6W119-->
2024-10-05 22:55:54 +01:00
Gwilym Inzani 4c44bbedd7 Add new import feature to xmrs 2024-10-05 22:48:38 +01:00
renovate[bot] 61634e143d
Update Rust crate xmrs to v0.8.0 2024-10-05 21:24:59 +00:00
Gwilym Inzani ebfe851287
Clippy wants us to elide lifetimes (#780)
Fixed with cargo clippy --fix

- [x] no changelog update needed
2024-10-05 22:24:01 +01:00
Gwilym Inzani d109f019eb More lifetimes elided 2024-10-05 22:13:38 +01:00
Gwilym Inzani 33c19c18fe For some reason cargo clippy --fix couldn't fix this one 2024-10-05 22:07:24 +01:00
Gwilym Inzani 9648d3e22a Fix clippy lints in games too 2024-10-05 22:02:10 +01:00
Gwilym Inzani 828339779b More clippy fixes 2024-10-05 21:50:46 +01:00
Gwilym Inzani 1972c83fc9 cargo clippy --fix 2024-10-05 21:48:44 +01:00
Gwilym Inzani 04e44ebac9 Release v0.21.1 2024-10-02 23:08:04 +01:00
Corwin 173a9aef03
Update Javascript packages (non-major) (#775) 2024-10-02 17:13:43 +01:00
renovate[bot] a15f462e97
Update Javascript packages (non-major) 2024-10-02 16:04:36 +00:00
Gwilym Inzani bfe3a02a50
Don't use ok_or_else for a copy value (#778)
Needed to fix today's clippy linting error

- [x]  no changelog update needed
2024-10-02 17:03:53 +01:00
Gwilym Inzani b7250f45e5 Don't use ok_or_else for a copy value 2024-10-02 16:56:12 +01:00
Corwin 93dabdb8ca
Improve web emulator audio quality (#776)
- [x] no changelog update needed
2024-10-01 20:06:28 +01:00
Corwin 10ee738f88
we now handle the frame timing in C, audio for me is now VERY stable 2024-10-01 18:44:12 +01:00
Gwilym Inzani 1faa1766a1
Fix build issue due to atomic u128s (#774)
Add fallback feature for portable-atomic.

This is needed since without it, we don't get anything that the platform
doesn't natively support, which is only up to 32 bits.

We newly need to change this because once_cell no longer imports with
default features.

- [x] no changelog update needed
2024-09-30 21:49:32 +01:00
Gwilym Inzani 2ab7e35630
Update dependency ubuntu to v24 (#772)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [ubuntu](https://redirect.github.com/actions/runner-images) |
github-runner | major | `22.04` -> `24.04` |

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC45Ny4wIiwidXBkYXRlZEluVmVyIjoiMzguOTcuMCIsInRhcmdldEJyYW5jaCI6Im1hc3RlciIsImxhYmVscyI6W119-->
2024-09-30 21:43:08 +01:00
Gwilym Inzani 7bb9d951c6 Add fallback feature
This is needed since without it, we don't get anything that the platform
doesn't natively support, which is only up to 32 bits.

We newly need to change this because once_cell no longer imports with
default features.
2024-09-30 21:41:23 +01:00
Corwin 1a9d5901cc
add dungeon tactics and khieras quest (#773)
- [x]  no changelog update needed
2024-09-27 00:42:51 +01:00
Corwin 90ddf45a57
add dungeon tactics and khieras quest 2024-09-27 00:35:15 +01:00
renovate[bot] c3418bfa49
Update dependency ubuntu to v24 2024-09-26 22:51:07 +00:00
Corwin f3d5590aff
remove empty lines (#771)
- [x] no changelog update needed
2024-09-26 19:10:11 +01:00
Corwin a49317442f
remove empty lines 2024-09-26 19:02:30 +01:00
Gwilym Inzani a2a00aa94f
Add hashset (#770)
There have been at least 2 times we wanted a HashSet. So here is one.

- [x] Changelog updated
2024-09-25 16:17:20 +01:00
Gwilym Inzani 42beac5574 Add changelog entry for hashset 2024-09-25 15:22:24 +01:00
Gwilym Inzani d459f6d0b9 Add an implementation of HashSet 2024-09-25 15:18:25 +01:00
Gwilym Inzani c97f75a593
Add quickcheck tests for agb_hashmap (#769)
Thought I'd add a quick property test for the hashmap. Inspired by
Jonhoo's most recent stream

- [x] no changelog update needed
2024-09-25 13:52:32 +01:00
Gwilym Inzani d17c14c7d3 Add quickcheck tests for agb_hashmap 2024-09-25 13:44:47 +01:00
Gwilym Inzani 7202fc0119
Improve palette optimiser (#768)
Make the whole thing more consistent and better at creating optimal
palettes.

- [x] Changelog updated / no changelog update needed
2024-09-25 13:31:29 +01:00
Gwilym Inzani 62020e692f Use btrees to make everything more consistent 2024-09-25 13:13:51 +01:00
Gwilym Inzani afa9d47f0c Add a changelog entry for changing how palettes are optimised 2024-09-25 13:05:52 +01:00
Gwilym Inzani 40987f8977 Slightly easier debugging 2024-09-25 12:13:28 +01:00
Gwilym Inzani edb628d0b2 Extract method for checking palette invariants 2024-09-25 11:44:16 +01:00
Gwilym Inzani c834e2907d Ensure that transparent colours always come first 2024-09-25 11:40:54 +01:00
Gwilym Inzani 7b6556b381 Use a better optimisation method 2024-09-25 11:33:51 +01:00
Gwilym Inzani db908bb2da Explain why this works 2024-09-25 10:53:25 +01:00
Gwilym Inzani fb186809a9 Add a really basic quickcheck 2024-09-25 10:47:17 +01:00
Gwilym Inzani d6bc6f49b4
Upgrade xmrs which gives us s3m and mod file support (#767)
Closes #742

Turns out XMRS will do the conversion for us, which means we can 'just
support' s3m and mod file formats for free which is nice.

- [x] Changelog updated / no changelog update needed
2024-09-25 10:33:37 +01:00
Gwilym Inzani 282e070216 Use version 0.7.2 2024-09-24 21:04:51 +01:00
Gwilym Inzani 89eb11d5ef Add changelog entry for s3m and mod format 2024-09-24 21:03:09 +01:00
Gwilym Inzani 40fd424205 Export the include_s3m and include_mod macros 2024-09-24 21:02:37 +01:00
Gwilym Inzani a7e7455c57 Add macros for include_s3m and include_mod 2024-09-24 21:02:37 +01:00
Gwilym Inzani 2d69b2a7a4 Make agb_xm_core generic on parsing 2024-09-24 21:02:37 +01:00
Gwilym Inzani 5b9332556d Add s3m and mod support to the desktop player 2024-09-24 21:02:36 +01:00
renovate[bot] 05b5b3e882 Update Rust crate xmrs to v0.7.2 2024-09-24 21:02:05 +01:00
Corwin d07970a7c0
Release v0.21.0 2024-09-24 20:38:33 +01:00
Corwin dd5ab9b475
Fix release script (#766)
Causes the release script to update build-dependencies and the desktop
tracker

- [x] no changelog update needed
2024-09-24 20:37:12 +01:00
Corwin 1f6c7157be
also update build-dependencies 2024-09-24 20:27:15 +01:00
Corwin 49ad674d93
Update dependency @types/react to v18.3.9 (#765) 2024-09-24 19:56:54 +01:00
renovate[bot] 6f01435498
Update dependency @types/react to v18.3.9 2024-09-24 15:27:08 +00:00
Corwin cfe31db934
Update Javascript packages (non-major) (#760) 2024-09-23 22:36:40 +01:00
renovate[bot] 51d3814539
Update Javascript packages (non-major) 2024-09-23 21:26:43 +00:00
Corwin 1f6766e286
Fix the CI issues with static mut access (#763)
- [x] no changelog update needed
2024-09-23 22:25:26 +01:00
Corwin bd27e80daa
allow improper ctypes 2024-09-22 18:29:05 +01:00
Corwin 3da5c21813
use SyncUnsafeCell rather than static muts 2024-09-22 16:22:08 +01:00
Corwin 051d9ab85d
use export name 2024-09-22 16:20:18 +01:00
Corwin 56e3de3c62
add SyncUnsafeCell implementation 2024-09-22 16:19:00 +01:00
Gwilym Inzani 18572658cb
Mark the generated entry as doc(hidden) (#761)
Should hopefully fix the currently failing build

- [x] no changelog update needed
2024-09-18 18:32:25 +01:00
Gwilym Inzani ab46121934
Mark the generated entry as doc(hidden) 2024-09-18 18:24:23 +01:00
Gwilym Inzani 7a2ef4338c
Update Javascript packages (non-major) (#758)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@types/node](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node)
([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node))
| [`20.16.2` ->
`20.16.4`](https://renovatebot.com/diffs/npm/@types%2fnode/20.16.2/20.16.4)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/20.16.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/20.16.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/20.16.2/20.16.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/20.16.2/20.16.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@types/react](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react)
([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react))
| [`18.3.4` ->
`18.3.5`](https://renovatebot.com/diffs/npm/@types%2freact/18.3.4/18.3.5)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2freact/18.3.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2freact/18.3.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2freact/18.3.4/18.3.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2freact/18.3.4/18.3.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [styled-components](https://styled-components.com)
([source](https://redirect.github.com/styled-components/styled-components))
| [`6.1.12` ->
`6.1.13`](https://renovatebot.com/diffs/npm/styled-components/6.1.12/6.1.13)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/styled-components/6.1.13?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/styled-components/6.1.13?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/styled-components/6.1.12/6.1.13?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/styled-components/6.1.12/6.1.13?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>styled-components/styled-components
(styled-components)</summary>

###
[`v6.1.13`](https://redirect.github.com/styled-components/styled-components/compare/v6.1.12...99c02f52d69e8e509c0bf012cadee7f8e819a6dd)

[Compare
Source](https://redirect.github.com/styled-components/styled-components/compare/v6.1.12...v6.1.13)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any
time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC41OS4yIiwidXBkYXRlZEluVmVyIjoiMzguNTkuMiIsInRhcmdldEJyYW5jaCI6Im1hc3RlciIsImxhYmVscyI6W119-->
2024-09-04 16:29:22 +01:00
renovate[bot] 69fe5a3c32
Update Javascript packages (non-major) 2024-09-04 01:34:42 +00:00
Gwilym Inzani 9cbf29ed98
Even more tracker commands (#757)
Adds support for some of `Retrigger` and `Sample Offset`

- [x] Changelog updated
2024-09-01 13:33:50 +01:00
Gwilym Inzani d4a2d9357f Change out the examples 2024-08-28 17:46:35 +01:00
Gwilym Inzani fee2575cb7 Retrigger with volume 2024-08-28 17:38:24 +01:00
Gwilym Inzani 48f7020f2c Should track previous retriggers for retrigger of 0 2024-08-28 17:00:19 +01:00
Gwilym Inzani 5f76fcc316 May as well support 0xE8 2024-08-28 16:48:28 +01:00
Gwilym Inzani 9fa171b712 E9 is the same as R0x 2024-08-28 16:46:08 +01:00
Gwilym Inzani 54a31934b2 Add support for retrigger command 2024-08-28 16:43:59 +01:00
Gwilym Inzani 559367f607 Add sample offset command support 2024-08-28 16:32:28 +01:00
Gwilym Inzani ea792f4768 Print the actual effect character 2024-08-28 16:10:26 +01:00
Gwilym Inzani 6c4e83197d
Add a method to stop the tracker (#756)
I've done some horrible hacks for this in our jam games. Better to have
a first-party solution to stopping channels in the tracker.

- [x] Changelog updated
2024-08-28 15:58:02 +01:00
Gwilym Inzani 040d3d5604 Changelog entry about stopping the tracker 2024-08-28 15:49:38 +01:00
Gwilym Inzani 8cec568a5b Add a method to stop the tracker 2024-08-28 15:48:43 +01:00
Gwilym Inzani 84a3c0b6a0
Allowing imported graphics to be exposed as pub mod (#738)
- [X] Changelog updated

This PR adds the possibility for graphics imported through
`include_background_gfx!` to be used as public modules, e.g.:
```rust
/// graphics.rs
agb::include_background_gfx!(pub background, "d77bba", tiles256 => 256 "map.aseprite");

/// main.rs
#![no_std]
#![no_main]

use agb::display::Priority;
use agb::display::tiled::RegularBackgroundSize::Background64x64;
use agb::display::tiled::{TiledMap, TileFormat};

mod graphics;


#[agb::entry]
fn main(mut gba: agb::Gba) -> ! {
    let (tiled, mut vram) = gba.display.video.tiled1();
    let vblank = agb::interrupt::VBlank::get();
    let tileset = &graphics::background::tiles256.tiles;

    vram.set_background_palettes(graphics::background::PALETTES);

    let mut bg = tiled.regular(Priority::P2, Background64x64, TileFormat::EightBpp);

    for y in 0..64u16 {
        for x in 0..64u16 {
            bg.set_tile(&mut vram, (x, y), tileset, graphics::background::tiles256.tile_settings[1]);
        }
    }
    bg.set_visible(true);
    bg.commit(&mut vram);

    loop {
        vblank.wait_for_vblank();
    }
}
```
2024-08-28 15:02:41 +01:00
Gwilym Inzani f25fe7f707 Add docs for pub exports of backgrounds 2024-08-28 14:55:12 +01:00
Gwilym Inzani a0d5a2c269
Update Javascript packages (non-major) (#746)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@types/node](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node)
([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node))
| [`20.14.12` ->
`20.16.2`](https://renovatebot.com/diffs/npm/@types%2fnode/20.14.12/20.16.2)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/20.16.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/20.16.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/20.14.12/20.16.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/20.14.12/20.16.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@types/react](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react)
([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react))
| [`18.3.3` ->
`18.3.4`](https://renovatebot.com/diffs/npm/@types%2freact/18.3.3/18.3.4)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2freact/18.3.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2freact/18.3.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2freact/18.3.3/18.3.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2freact/18.3.3/18.3.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[eslint-config-next](https://nextjs.org/docs/app/building-your-application/configuring/eslint#eslint-config)
([source](https://togithub.com/vercel/next.js/tree/HEAD/packages/eslint-config-next))
| [`14.2.5` ->
`14.2.7`](https://renovatebot.com/diffs/npm/eslint-config-next/14.2.5/14.2.7)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/eslint-config-next/14.2.7?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/eslint-config-next/14.2.7?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/eslint-config-next/14.2.5/14.2.7?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/eslint-config-next/14.2.5/14.2.7?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [next](https://nextjs.org)
([source](https://togithub.com/vercel/next.js)) | [`14.2.5` ->
`14.2.7`](https://renovatebot.com/diffs/npm/next/14.2.5/14.2.7) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/next/14.2.7?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/next/14.2.7?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/next/14.2.5/14.2.7?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/next/14.2.5/14.2.7?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [sharp](https://sharp.pixelplumbing.com)
([source](https://togithub.com/lovell/sharp),
[changelog](https://togithub.com/lovell/sharp/blob/main/docs/changelog.md))
| [`0.33.4` ->
`0.33.5`](https://renovatebot.com/diffs/npm/sharp/0.33.4/0.33.5) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/sharp/0.33.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/sharp/0.33.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/sharp/0.33.4/0.33.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/sharp/0.33.4/0.33.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>vercel/next.js (eslint-config-next)</summary>

###
[`v14.2.7`](https://togithub.com/vercel/next.js/compare/v14.2.6...v14.2.7)

[Compare
Source](https://togithub.com/vercel/next.js/compare/v14.2.6...v14.2.7)

###
[`v14.2.6`](https://togithub.com/vercel/next.js/compare/v14.2.5...v14.2.6)

[Compare
Source](https://togithub.com/vercel/next.js/compare/v14.2.5...v14.2.6)

</details>

<details>
<summary>vercel/next.js (next)</summary>

###
[`v14.2.7`](https://togithub.com/vercel/next.js/compare/v14.2.6...v14.2.7)

[Compare
Source](https://togithub.com/vercel/next.js/compare/v14.2.6...v14.2.7)

###
[`v14.2.6`](https://togithub.com/vercel/next.js/compare/v14.2.5...v14.2.6)

[Compare
Source](https://togithub.com/vercel/next.js/compare/v14.2.5...v14.2.6)

</details>

<details>
<summary>lovell/sharp (sharp)</summary>

###
[`v0.33.5`](https://togithub.com/lovell/sharp/compare/v0.33.4...v0.33.5)

[Compare
Source](https://togithub.com/lovell/sharp/compare/v0.33.4...v0.33.5)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any
time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config help](https://togithub.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View the
[repository job log](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40NDAuNyIsInVwZGF0ZWRJblZlciI6IjM4LjU2LjAiLCJ0YXJnZXRCcmFuY2giOiJtYXN0ZXIiLCJsYWJlbHMiOltdfQ==-->
2024-08-28 14:52:41 +01:00
Gwilym Inzani 6212ce0baf
Update Rust crate bindgen to 0.70 (#750)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [bindgen](https://rust-lang.github.io/rust-bindgen/)
([source](https://togithub.com/rust-lang/rust-bindgen)) |
build-dependencies | minor | `0.69` -> `0.70` |

---

### Release Notes

<details>
<summary>rust-lang/rust-bindgen (bindgen)</summary>

###
[`v0.70.1`](https://togithub.com/rust-lang/rust-bindgen/blob/HEAD/CHANGELOG.md#0701-2024-08-20)

[Compare
Source](https://togithub.com/rust-lang/rust-bindgen/compare/v0.70.0...v0.70.1)

#### Added

#### Changed

#### Removed

#### Fixed

- Fix regression where the `const` layout tests were triggering the
`unnecessary_operation` and `identity_op` clippy warnings.

#### Security

###
[`v0.70.0`](https://togithub.com/rust-lang/rust-bindgen/blob/HEAD/CHANGELOG.md#0700-2024-08-16)

[Compare
Source](https://togithub.com/rust-lang/rust-bindgen/compare/v0.69.4...v0.70.0)

#### Added

-   Add target mappings for riscv64imac and riscv32imafc.
- Add a complex macro fallback API
([#&#8203;2779](https://togithub.com/rust-lang/rust-bindgen/issues/2779)).
- Add option to use DST structs for flexible arrays (--flexarray-dst,
[#&#8203;2772](https://togithub.com/rust-lang/rust-bindgen/issues/2772)).
- Add option to dynamically load variables
([#&#8203;2812](https://togithub.com/rust-lang/rust-bindgen/issues/2812)).
- Add option in CLI to use rustified non-exhaustive enums
(--rustified-non-exhaustive-enum,
[#&#8203;2847](https://togithub.com/rust-lang/rust-bindgen/issues/2847)).

#### Changed

- Remove which and lazy-static dependencies
([#&#8203;2809](https://togithub.com/rust-lang/rust-bindgen/issues/2809),
[#&#8203;2817](https://togithub.com/rust-lang/rust-bindgen/issues/2817)).
- Generate compile-time layout tests
([#&#8203;2787](https://togithub.com/rust-lang/rust-bindgen/issues/2787)).
- Print `bindgen-cli` errors to stderr instead of stdout
([#&#8203;2840](https://togithub.com/rust-lang/rust-bindgen/issues/2840))

#### Removed

#### Fixed

- Fix `--formatter=prettyplease` not working in `bindgen-cli` by adding
`prettyplease` feature and
enabling it by default for `bindgen-cli`
([#&#8203;2789](https://togithub.com/rust-lang/rust-bindgen/issues/2789))
.
- Fix `--allowlist-item` so anonymous enums are no longer ignored
([#&#8203;2827](https://togithub.com/rust-lang/rust-bindgen/issues/2827)).
- Use clang_getFileLocation instead of clang_getSpellingLocation to fix
clang-trunk
([#&#8203;2824](https://togithub.com/rust-lang/rust-bindgen/issues/2824)).
- Fix generated constants: `f64::INFINITY`, `f64::NEG_ INFINITY`,
`f64::NAN`
([#&#8203;2854](https://togithub.com/rust-lang/rust-bindgen/issues/2854)).

#### Security

- Update `tempfile` and `rustix` due to
[GHSA-c827-hfw6-qwvm](https://togithub.com/advisories/GHSA-c827-hfw6-qwvm).

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View the
[repository job log](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4yNi4xIiwidXBkYXRlZEluVmVyIjoiMzguNTYuMCIsInRhcmdldEJyYW5jaCI6Im1hc3RlciIsImxhYmVscyI6W119-->
2024-08-28 12:51:49 +01:00
Gwilym Inzani 605173bf65
It doesn't appear to be an error to have an invalid instrument index (#755)
I've seen an xm file that plays fine in milkytracker and other places,
but has instrument indexes which are too high. They are just treated as
non-existent :)

- [x] no changelog update needed
2024-08-28 12:34:55 +01:00
Gwilym Inzani d617bd10d0
Jam 2024 changes (#752)
- [ ] Changelog updated / no changelog update needed
2024-08-28 12:34:20 +01:00
renovate[bot] 0d9bcc61cd
Update Rust crate bindgen to 0.70 2024-08-28 11:28:32 +00:00
renovate[bot] adb70ddc82
Update Javascript packages (non-major) 2024-08-28 11:28:27 +00:00
Gwilym Inzani 7d0ad0d497 State that this is text 2024-08-28 12:27:27 +01:00
Gwilym Inzani 2614fd1af0 Make affine map indexes u16 2024-08-28 12:27:27 +01:00
Corwin 974b08989a add docs 2024-08-28 12:27:27 +01:00
Corwin e1cc3d7773 make affine stuff public, there's no invariant we want to maintain 2024-08-28 12:27:27 +01:00
Gwilym Inzani 60073c4a89
Merge branch 'master' into allow-invalid-instrument-xm 2024-08-28 12:27:18 +01:00
Gwilym Inzani 716147ebae
Shorten the first paragraphs (#754)
Clippy was complaining that our first paragraphs were too long

- [x] no changelog update needed
2024-08-28 12:16:08 +01:00
Gwilym Inzani 53182d8122 It doesn't appear to be an error to have an invalid instrument index 2024-08-28 12:13:08 +01:00
Gwilym Inzani d045b8c8f2 Shorten the first paragraphs 2024-08-28 12:08:24 +01:00
Gwilym Inzani a79829068c
Update tracker to support PatternBreak and PositionJump (#748)
This pull request adds support for pattern breaks and position jumps to
the music tracker module. This PR only adds functionality for XM input
files for now. However, these changes would also be applicable to other
types of music modules, such as Amiga modules.

In `agb-xm-core`: 
* handle effects Bxx, Dxx, and their combination

In `agb-tracker-interop`: 
* represent jump using a `PatternEffect`

In `agb-tracker`:
* keep track of any applicable jump in `TrackerInner`, and handle it in
`increment_frame()` when needed
2024-08-24 23:23:21 +01:00
Gwilym Inzani 79f93fe2d2
asm_const is no longer nightly (#751)
- [x] no changelog update needed
2024-08-17 08:46:52 +01:00
Gwilym Inzani 6da89991aa asm_const is no longer nightly 2024-08-17 08:39:07 +01:00
wysiwys da92ec3b8b Update tracker to support PatternBreak and PositionJump 2024-08-02 21:23:36 -04:00
Gwilym Inzani 4a3792b248
Add template to workspace exclude (#745)
Avoids a warning in rust-analyzer and is the correct thing to do

- [x] no changelog update needed
2024-07-24 17:25:30 +01:00
Gwilym Inzani 8193134c5f
Update Javascript packages (non-major) (#741)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@types/node](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node)
([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node))
| [`20.14.10` ->
`20.14.12`](https://renovatebot.com/diffs/npm/@types%2fnode/20.14.10/20.14.12)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/20.14.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/20.14.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/20.14.10/20.14.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/20.14.10/20.14.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [styled-components](https://styled-components.com)
([source](https://togithub.com/styled-components/styled-components)) |
[`6.1.11` ->
`6.1.12`](https://renovatebot.com/diffs/npm/styled-components/6.1.11/6.1.12)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/styled-components/6.1.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/styled-components/6.1.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/styled-components/6.1.11/6.1.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/styled-components/6.1.11/6.1.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [typescript](https://www.typescriptlang.org/)
([source](https://togithub.com/Microsoft/TypeScript)) | [`5.5.3` ->
`5.5.4`](https://renovatebot.com/diffs/npm/typescript/5.5.3/5.5.4) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/typescript/5.5.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/typescript/5.5.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/typescript/5.5.3/5.5.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/typescript/5.5.3/5.5.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>styled-components/styled-components
(styled-components)</summary>

###
[`v6.1.12`](https://togithub.com/styled-components/styled-components/releases/tag/v6.1.12)

[Compare
Source](https://togithub.com/styled-components/styled-components/compare/v6.1.11...v6.1.12)

#### What's Changed

- Export rehydrate from StyleSheet by
[@&#8203;hamidrezahanafi](https://togithub.com/hamidrezahanafi) in
[https://github.com/styled-components/styled-components/pull/4328](https://togithub.com/styled-components/styled-components/pull/4328)
- Prevent ServerStyleSheet generating empty style tags/elements by
[@&#8203;hamidrezahanafi](https://togithub.com/hamidrezahanafi) in
[https://github.com/styled-components/styled-components/pull/4327](https://togithub.com/styled-components/styled-components/pull/4327)

#### New Contributors

- [@&#8203;hamidrezahanafi](https://togithub.com/hamidrezahanafi) made
their first contribution in
[https://github.com/styled-components/styled-components/pull/4328](https://togithub.com/styled-components/styled-components/pull/4328)

**Full Changelog**:
https://github.com/styled-components/styled-components/compare/v6.1.11...v6.1.12

</details>

<details>
<summary>Microsoft/TypeScript (typescript)</summary>

###
[`v5.5.4`](https://togithub.com/Microsoft/TypeScript/compare/v5.5.3...c8a7d589e647e19c94150d9892909f3aa93e48eb)

[Compare
Source](https://togithub.com/Microsoft/TypeScript/compare/v5.5.3...v5.5.4)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any
time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config help](https://togithub.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View the
[repository job log](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MzEuNCIsInVwZGF0ZWRJblZlciI6IjM3LjQzOC4wIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbXX0=-->
2024-07-24 17:24:16 +01:00
renovate[bot] 1a7edf54ed
Update Javascript packages (non-major) 2024-07-24 16:16:46 +00:00
Gwilym Inzani 0cb5e18c3c Add template to workspace exclude 2024-07-24 17:16:39 +01:00
Gwilym Inzani 0554f16c24
Remove unnecessary unsafe block (#744)
Needed to fix the build

- [x] no changelog update needed
2024-07-24 17:15:46 +01:00
Gwilym Inzani 178018c0f0 Remove unnecessary unsafe block 2024-07-24 17:08:02 +01:00
Gwilym Inzani db9fdb77e3
Refactor tracker core (#719)
I thought it would be fun to try and write the tracker in such a way
that it could be used locally too.

- [x] changelog updated
2024-07-16 20:11:04 +01:00
Gwilym Inzani e4025caef9
Update Rust crate addr2line to 0.24 (#739)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [addr2line](https://togithub.com/gimli-rs/addr2line) | dependencies |
minor | `0.23` -> `0.24` |

---

### Release Notes

<details>
<summary>gimli-rs/addr2line (addr2line)</summary>

###
[`v0.24.0`](https://togithub.com/gimli-rs/addr2line/blob/HEAD/CHANGELOG.md#0240-20240716)

[Compare
Source](https://togithub.com/gimli-rs/addr2line/compare/0.23.0...0.24.0)

##### Breaking changes

-   Updated `gimli` dependency.

##### Changed

- Changed the order of ranges returned by
`Context::find_location_range`, and
    fixed handling in rare situations.
    [#&#8203;303](https://togithub.com/gimli-rs/addr2line/pull/303)
    [#&#8203;304](https://togithub.com/gimli-rs/addr2line/pull/304)
    [#&#8203;306](https://togithub.com/gimli-rs/addr2line/pull/306)

-   Improved the performance of `Context::find_location`.
    [#&#8203;305](https://togithub.com/gimli-rs/addr2line/pull/305)

##### Added

-   Added `LoaderReader`.
    [#&#8203;307](https://togithub.com/gimli-rs/addr2line/pull/307)

-   Added `--all` option to `addr2line`.
    [#&#8203;307](https://togithub.com/gimli-rs/addr2line/pull/307)

***

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MzEuNCIsInVwZGF0ZWRJblZlciI6IjM3LjQzMS40IiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbXX0=-->
2024-07-16 19:45:38 +01:00
Gwilym Inzani 2c1d8fc904 Also update gimli 2024-07-16 19:37:59 +01:00
renovate[bot] 88ee2a74e8
Update Rust crate addr2line to 0.24 2024-07-16 09:27:13 +00:00
kouta bc979d7299 Update changelog 2024-07-11 19:41:26 -03:00
kouta ce80dd0442 Fix linting issues 2024-07-11 19:39:55 -03:00
kouta 98ec2c5629 Allow exporting included background
(cherry picked from commit 0f6548cc8cb4fabec868a234488f064c12961cd8)
2024-07-11 19:33:01 -03:00
Gwilym Inzani 7833561be1
Update Javascript packages (non-major) (#734)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@types/node](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node)
([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node))
| [`20.14.9` ->
`20.14.10`](https://renovatebot.com/diffs/npm/@types%2fnode/20.14.9/20.14.10)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/20.14.10?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/20.14.10?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/20.14.9/20.14.10?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/20.14.9/20.14.10?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[eslint-config-next](https://nextjs.org/docs/app/building-your-application/configuring/eslint#eslint-config)
([source](https://togithub.com/vercel/next.js/tree/HEAD/packages/eslint-config-next))
| [`14.2.4` ->
`14.2.5`](https://renovatebot.com/diffs/npm/eslint-config-next/14.2.4/14.2.5)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/eslint-config-next/14.2.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/eslint-config-next/14.2.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/eslint-config-next/14.2.4/14.2.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/eslint-config-next/14.2.4/14.2.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [next](https://nextjs.org)
([source](https://togithub.com/vercel/next.js)) | [`14.2.4` ->
`14.2.5`](https://renovatebot.com/diffs/npm/next/14.2.4/14.2.5) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/next/14.2.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/next/14.2.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/next/14.2.4/14.2.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/next/14.2.4/14.2.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>vercel/next.js (eslint-config-next)</summary>

###
[`v14.2.5`](https://togithub.com/vercel/next.js/compare/v14.2.4...v14.2.5)

[Compare
Source](https://togithub.com/vercel/next.js/compare/v14.2.4...v14.2.5)

</details>

<details>
<summary>vercel/next.js (next)</summary>

###
[`v14.2.5`](https://togithub.com/vercel/next.js/compare/v14.2.4...v14.2.5)

[Compare
Source](https://togithub.com/vercel/next.js/compare/v14.2.4...v14.2.5)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any
time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config help](https://togithub.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MjUuMSIsInVwZGF0ZWRJblZlciI6IjM3LjQyNS4xIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbXX0=-->
2024-07-11 22:10:00 +01:00
Gwilym Inzani a604f269bc Update changelog 2024-07-11 21:59:28 +01:00
Gwilym Inzani c7482f54ab This feels more correct 2024-07-11 21:58:44 +01:00
Gwilym Inzani 8fa595f7f7 Handle RampDown 2024-07-11 21:58:44 +01:00
Gwilym Inzani 3bd8b9019d Handle vibrato in the instrument too 2024-07-11 21:58:44 +01:00
Gwilym Inzani d15063373d Implement vibrato correctly and add a small test case 2024-07-11 21:58:44 +01:00
Gwilym Inzani 431833b216 Correct vibrato code generation 2024-07-11 21:58:44 +01:00
Gwilym Inzani c1eaae64e1 Support fine portamentos 2024-07-11 21:58:44 +01:00
Gwilym Inzani 31ca8f631f Add vibrato 2024-07-11 21:58:44 +01:00
Gwilym Inzani f6e7625bb1 Start hooking in waves 2024-07-11 21:58:44 +01:00
Gwilym Inzani f3cc62db6f Massive refactor ahead of waveforms 2024-07-11 21:58:44 +01:00
Gwilym Inzani 0daeba1876 Generate lookup and add waveform to interop 2024-07-11 21:58:44 +01:00
Gwilym Inzani 9c2d02f161 We now need alsa to build the desktop player 2024-07-11 21:58:44 +01:00
Gwilym Inzani 2785df56ca The xm feature is enabled by default 2024-07-11 21:58:44 +01:00
Gwilym Inzani 45f8a52eb5 try_recv to remove unwrap 2024-07-11 21:58:44 +01:00
Gwilym Inzani afddd77ce8 Don't require leaking the track 2024-07-11 21:58:44 +01:00
Gwilym Inzani 71a7b6431c Don't force a pointless lifetime on the tracker 2024-07-11 21:58:44 +01:00
Gwilym Inzani a6fca49f7b Missing minus sign 2024-07-11 21:58:44 +01:00
Gwilym Inzani 2fa574684c Number of channel is configurable 2024-07-11 21:58:44 +01:00
Gwilym Inzani 8899a56f65 Allow the clippy lint 2024-07-11 21:58:44 +01:00
Gwilym Inzani 72598d0232 Enable midi and xm by default 2024-07-11 21:58:44 +01:00
Gwilym Inzani 6076a1bd23 Fix the DPL tracker usage 2024-07-11 21:58:44 +01:00
Gwilym Inzani 7332c8a5f0 Don't know why this is in there twice 2024-07-11 21:58:44 +01:00
Gwilym Inzani afa8a11b3f Ensure that the 'quote' feature is included 2024-07-11 21:58:44 +01:00
Gwilym Inzani f452070154 Do the same changes for midi 2024-07-11 21:58:44 +01:00
Gwilym Inzani 3a755107aa Get the desktop player actually playing music 2024-07-11 21:58:44 +01:00
Gwilym Inzani c863b94f49 Hello world for desktop player 2024-07-11 21:58:44 +01:00
Gwilym Inzani d0925f6787 Make agb optional for the tracker 2024-07-11 21:58:44 +01:00
Gwilym Inzani 3305ca0ff2 Make the tracker generic on the mixer 2024-07-11 21:58:44 +01:00
Gwilym Inzani d00de7b2a4 Make agb-xm-core return the interop rather than the tokens 2024-07-11 21:58:44 +01:00
Gwilym Inzani 5829d71b6b
Fix tilemap gaps in affine graphic modes #733 (#735)
- [x] Changelog updated
Fixes issue #733 where affine tilemaps have a gap.
2024-07-11 21:32:52 +01:00
kouta faa46a4f32 Fix linting issues 2024-07-11 14:56:43 -03:00
kouta a9a4a052a9 Remove priority() from TiledMapPrivate as it can now be accessed straight from the underlying type. 2024-07-11 14:34:12 -03:00
kouta 41979460f6 Merge remote-tracking branch 'refs/remotes/raworigin/master' into hotfix/affine-tiles 2024-07-11 14:27:37 -03:00
renovate[bot] d07e1265e1
Update Javascript packages (non-major) 2024-07-10 15:48:34 +00:00
kouta 1340b992cb Code review 2024-07-10 09:29:07 -03:00
Gwilym Inzani 476adafeb4
Fix two build issues with latest rust version (#736)
- [x] no changelog update needed
2024-07-10 09:17:54 +01:00
Gwilym Inzani 741c3dedee Fix two build issues with latest rust version 2024-07-10 09:06:52 +01:00
kouta-kun 8c6e1ae0a9
Update CHANGELOG.md 2024-07-09 16:59:30 -03:00
kouta cf2b8be6e0 Fix affine matrix tile setting 2024-07-07 00:53:52 -03:00
Corwin 919a4046b7
Update Javascript packages (non-major) (#731) 2024-07-02 19:10:37 +01:00
renovate[bot] 81734745e1
Update Javascript packages (non-major) 2024-07-01 19:50:42 +00:00
Corwin 1257fbbf79
Update Javascript packages (non-major) (#728) 2024-06-20 21:07:24 +01:00
renovate[bot] 7ad88d405b
Update Javascript packages (non-major) 2024-06-20 19:57:31 +00:00
Corwin a4d6ba5bc9
Release v0.20.5 2024-06-18 17:49:56 +01:00
Corwin aa2edf131e
update changelog 2024-06-18 17:47:19 +01:00
Corwin cd8c058b13
Fix xmrs minor version breakage (#727)
- [x] no changelog update needed
2024-06-17 20:50:40 +01:00
Corwin 592e6dce09
fix xmrs minor version breakage 2024-06-17 20:37:32 +01:00
Corwin ac2e6b5046
Release v0.20.4 2024-06-13 23:13:02 +01:00
Corwin bc061f676f
move some functions under more general generics (#726)
- [x] Changelog updated
2024-06-13 22:56:47 +01:00
Corwin f6ff13e1b2
add changelog entry 2024-06-13 22:49:39 +01:00
Corwin bc63776b9e
Exclude tests / examples / benches from the published packages (#589)
The package published to crates.io should not include tests / examples /
benches. Previously we ran into issues with having a too large package
from example data, but we avoided this by making the examples smaller. A
better way to avoid this is to not include them at all.

- [x] no changelog update needed
2024-06-13 22:48:00 +01:00
Corwin 4e0334f29c
move some functions under more general generics 2024-06-13 22:47:03 +01:00
Corwin a6e4be0577
Release v0.20.3 2024-06-12 17:57:39 +01:00
Corwin 5ca9cd5480
fix the overflow bug on kerning / xmin on a new sprite (#725)
- [x] Changelog updated
2024-06-12 17:40:46 +01:00
Corwin 547c6b1ebe
Expose graphics mode (#723)
- [x] Changelog updated
2024-06-12 17:37:37 +01:00
Corwin cbf0fa0a23
add changelog entry 2024-06-12 17:33:46 +01:00
Corwin 53f0901ceb
fix the overflow bug on kerning / xmin on a new sprite 2024-06-12 17:29:39 +01:00
Corwin 7292748848
add changelog entry 2024-06-12 17:18:36 +01:00
Corwin 50f2ad6f52
exclude tests / examples / benches from the published packages 2024-06-12 01:19:18 +01:00
Corwin 9ef4a8efcc
Update dependency @types/node to v20.14.2 (#722) 2024-06-11 20:59:21 +01:00
Corwin fed560b41b
expose graphics mode 2024-06-11 17:50:22 +01:00
renovate[bot] 29454c5752
Update dependency @types/node to v20.14.2 2024-06-11 01:45:15 +00:00
Gwilym Inzani 062eb1154e
The link register points to the next instruction, not the current one (#718)
agb-debug was producing some bad backtraces which was being caused by
the fact that we were producing slightly incorrect values which made
bigger examples of backtraces completely useless.

I could fix this in agb-debug, but I feel like the correct place to do
this is just fixing agb.

- [x] Changelog updated
2024-06-04 21:47:16 +01:00
Gwilym Inzani 32c6ed4e35 Ensure the frame pointer is always 0 2024-06-04 21:39:58 +01:00
Gwilym Inzani b405a04a4a Add a changelog entry 2024-06-04 21:19:29 +01:00
Gwilym Inzani d9243ded6b The link register points to the next instruction 2024-06-04 21:18:10 +01:00
Gwilym Inzani fafa4ba7ea
Update Rust crate xmrs to 0.6 (#716)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [xmrs](https://codeberg.org/sbechet/xmrs) | dependencies | minor |
`0.5` -> `0.6` |

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4zNzcuOCIsInVwZGF0ZWRJblZlciI6IjM3LjM3Ny44IiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbXX0=-->
2024-06-04 20:19:30 +01:00
Corwin d6b52f8ce8
Update dependency @types/node to v20.14.1 (#717) 2024-06-04 20:03:34 +01:00
renovate[bot] cb6e8edb99
Update dependency @types/node to v20.14.1 2024-06-04 01:13:58 +00:00
Corwin 8d1e5ee192
Update dependency @types/react to v18.3.3 (#715) 2024-05-29 18:01:53 +01:00
renovate[bot] dd15cb2ee0
Update Rust crate xmrs to 0.6 2024-05-29 16:36:06 +00:00
renovate[bot] 886874ffd0
Update dependency @types/react to v18.3.3 2024-05-28 01:30:25 +00:00
Gwilym Inzani 2de07342d7
Fix affine background matrix creation outside of the 1st quadrant (#714)
- [x] Changelog updated
2024-05-27 16:46:59 +01:00
Gwilym Inzani 6b58280e81 Add changelog entry for affine background positions 2024-05-27 14:47:17 +01:00
Gwilym Inzani fde444e253 Fix affine background matrix creation outside of the 1st quadrant 2024-05-27 14:46:55 +01:00
Gwilym Inzani 27ee9c7b85
Revert "Remove lifetime from dma transfer handle" (#713)
Reverts agbrs/agb#712

This wasn't for the data but for the DMA itself
2024-05-27 14:24:02 +01:00
Gwilym Inzani 21658b9b15
Revert "Remove lifetime from dma transfer handle" 2024-05-27 14:16:24 +01:00
Gwilym Inzani dc06aabb19
Remove lifetime from dma transfer handle (#712)
The lifetime here is pointless since we copy the data anyway. And this
makes a bunch of stuff not unsafe any more which is really nice.

- [x] Changelog updated / no changelog update needed
2024-05-27 13:39:27 +01:00
Gwilym Inzani e91e7a84e7 Add changelog entry for less unsafe 2024-05-27 13:25:52 +01:00
Gwilym Inzani c4719a5ce0 Remove unsafe from examples 2024-05-27 13:24:58 +01:00
Gwilym Inzani e9ce8cd2ad hblack_transfer doesn't need to be unsafe 2024-05-27 13:23:49 +01:00
Gwilym Inzani 248f71dbfa Remove lifetime from DMA transfer handle 2024-05-27 13:20:13 +01:00
Gwilym Inzani 97d474e989
Update Rust crate addr2line to 0.23 (#709)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [addr2line](https://togithub.com/gimli-rs/addr2line) | dependencies |
minor | `0.22` -> `0.23` |

---

### Release Notes

<details>
<summary>gimli-rs/addr2line (addr2line)</summary>

###
[`v0.23.0`](https://togithub.com/gimli-rs/addr2line/blob/HEAD/CHANGELOG.md#0230-20240526)

[Compare
Source](https://togithub.com/gimli-rs/addr2line/compare/0.22.0...0.23.0)

##### Breaking changes

-   Updated `gimli` dependency.

- Deleted `Context::new`, `Context::new_with_sup`, and
`builtin_split_dwarf_loader`.
    Use `Context::from_dwarf` or `Loader::new` instead.
    This removes `object` from the public API.
    [#&#8203;296](https://togithub.com/gimli-rs/addr2line/pull/296)

##### Changed

-   Fixed handling of column 0 in the line table.
    [#&#8203;290](https://togithub.com/gimli-rs/addr2line/pull/290)

- Moved `addr2line` from `examples` to `bin`. Requires the `bin`
feature.
    [#&#8203;291](https://togithub.com/gimli-rs/addr2line/pull/291)

-   Split up `lib.rs` into smaller modules.
    [#&#8203;292](https://togithub.com/gimli-rs/addr2line/pull/292)

##### Added

-   Added `Loader`. Requires the `loader` feature.
    [#&#8203;296](https://togithub.com/gimli-rs/addr2line/pull/296)
    [#&#8203;297](https://togithub.com/gimli-rs/addr2line/pull/297)

-   Added unpacked Mach-O support to `Loader`.
    [#&#8203;298](https://togithub.com/gimli-rs/addr2line/pull/298)

***

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4zNjguMTAiLCJ1cGRhdGVkSW5WZXIiOiIzNy4zNjguMTAiLCJ0YXJnZXRCcmFuY2giOiJtYXN0ZXIiLCJsYWJlbHMiOltdfQ==-->
2024-05-27 10:06:11 +01:00
Gwilym Inzani 587e3cb521 Fix build errors by importing the crates manually 2024-05-27 09:58:23 +01:00
renovate[bot] 2ac49ace06
Update Rust crate addr2line to 0.23 2024-05-26 07:04:06 +00:00
Gwilym Inzani a243bf4078
Nicer test logo (#707)
With the new examples page on the website, I thought it was probably
time to update the logo we use there to a nicer one.

I've also added a basic one to make the background colour change example
nicer, and sometimes you might want the less busy one.

- [x] Changelog updated

![image](https://github.com/agbrs/agb/assets/460842/062bb473-1b2f-4db0-a712-6d264240be9a)
2024-05-25 21:19:04 +01:00
Gwilym Inzani 30e3718797 Include drawing a leviathan 2024-05-25 21:11:32 +01:00
Gwilym Inzani 24e15f8786 Add a basic version of the example_logo for certain examples 2024-05-25 21:11:32 +01:00
Gwilym Inzani b208133564 Add changelog entry for new functions 2024-05-25 21:11:28 +01:00
Gwilym Inzani da9ad6d496 Add a 256 colour variant too 2024-05-25 21:11:02 +01:00
Gwilym Inzani bf4a6887a5 Update the background example to search for the colour 2024-05-25 21:11:02 +01:00
Gwilym Inzani b219e00454 Update the test_logo to be a bit nicer 2024-05-25 21:11:02 +01:00
Corwin d05965b98f
Release v0.20.2 2024-05-25 13:20:03 +01:00
Corwin fb85d7ba14
Fix qrcode generation (#708)
- [x] Changelog updated
2024-05-25 13:05:49 +01:00
Corwin b3d7642071
extract code generation and add test 2024-05-25 12:22:38 +01:00
Corwin cfc3c3a93c
add changelog entry 2024-05-25 12:10:35 +01:00
Corwin 2d34099afc
resize the buffer 2024-05-25 12:07:23 +01:00
Corwin 51b1f909c5
clear screen and handle message overlap 2024-05-25 12:07:23 +01:00
Corwin e06230efd0
Agb examples site (#705)
![image](https://github.com/agbrs/agb/assets/8143879/12163f27-1097-49fd-810c-a00f6cf5d8bf)
2024-05-22 20:56:59 +01:00
Corwin 04181a4253
include the source code for each example 2024-05-22 17:18:29 +01:00
Corwin abf7e9dc7f
fix justfile 2024-05-22 12:45:39 +01:00
Corwin 66d750fb84
make the webpage 2024-05-22 02:21:37 +01:00
Corwin a2dea3cab5
generate roms and screenshots 2024-05-22 02:21:30 +01:00
Corwin 81621c3b5e
add screenshot generator tool 2024-05-22 02:21:19 +01:00
Corwin e25a1c7158
remove just build that is non standard 2024-05-22 02:20:39 +01:00
Gwilym Inzani f047b6de94
Put https://agbrs.dev as the homepage for the crate (#704)
- [x] no changelog update needed
2024-05-21 23:51:31 +01:00
Gwilym Inzani 627c6dad1f
Use pointers rather than pin to simplify the mixers buffer handling (#703)
Mentioned by @corwinkuiper that this might be a nicer way of handling
this

- [x] no changelog update needed
2024-05-21 23:48:39 +01:00
Gwilym Inzani 864fd08ec3 Put https://agbrs.dev as the homepage for the crate 2024-05-21 23:43:45 +01:00
Gwilym Inzani ddc3770c70 Use pointers rather than pin to simplify the mixers buffer handling 2024-05-21 23:17:39 +01:00
Gwilym Inzani 2edb5e745b
Update dependency sharp to v0.33.4 (#702)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [sharp](https://sharp.pixelplumbing.com)
([source](https://togithub.com/lovell/sharp),
[changelog](https://togithub.com/lovell/sharp/blob/main/docs/changelog.md))
| [`0.33.3` ->
`0.33.4`](https://renovatebot.com/diffs/npm/sharp/0.33.3/0.33.4) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/sharp/0.33.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/sharp/0.33.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/sharp/0.33.3/0.33.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/sharp/0.33.3/0.33.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>lovell/sharp (sharp)</summary>

###
[`v0.33.4`](https://togithub.com/lovell/sharp/compare/v0.33.3...v0.33.4)

[Compare
Source](https://togithub.com/lovell/sharp/compare/v0.33.3...v0.33.4)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any
time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4zNjguMTAiLCJ1cGRhdGVkSW5WZXIiOiIzNy4zNjguMTAiLCJ0YXJnZXRCcmFuY2giOiJtYXN0ZXIiLCJsYWJlbHMiOltdfQ==-->
2024-05-21 20:33:04 +01:00
renovate[bot] a261ada116
Update dependency sharp to v0.33.4 2024-05-21 07:11:20 +00:00
Corwin 6a5346026a
Release v0.20.1 2024-05-17 23:09:16 +01:00
Corwin c5ae7f1c2b
Be less specific for version numbers (#700)
Some more places where version numbers were specified too much
2024-05-17 12:14:10 +01:00
Corwin cd7bdffba4
be less specific 2024-05-17 12:05:14 +01:00
Gwilym Inzani bcafe7be75
Add note delay and fix envelopes (#698)
Adds support for the effect EDx (note delay) although it isn't
completely correct. And envelopes were too short so I've fixed that too.

- [x] no changelog update needed
2024-05-16 23:12:00 +01:00
Gwilym Inzani 93a3bc8e56 just fmt 2024-05-16 23:04:26 +01:00
Gwilym Inzani 352b352b27 Properly implement delay and envelopes 2024-05-16 00:27:20 +01:00
Gwilym Inzani 5494ae29e1 Get the envelopes correct 2024-05-15 23:47:37 +01:00
Corwin 5a80acd501
Add dot and cross product (#695)
Docs:

![image](https://github.com/agbrs/agb/assets/8143879/88f10d03-27c6-43b3-baf3-b79469ed7a12)


- [x] Changelog updated
2024-05-15 22:40:09 +01:00
Corwin 2887791109
clarify it's only the z component 2024-05-15 22:32:28 +01:00
Gwilym Inzani 2e0f89978a Add note delay support (effect EDx) 2024-05-15 22:30:13 +01:00
Corwin f99a564f89
add changelog entry for dot/cross 2024-05-15 22:29:22 +01:00
Corwin 72eb7189be
add dot and cross product 2024-05-15 22:28:29 +01:00
Gwilym Inzani c099fc9a61
Notes are 1 indexed, not 0 indexed (#696)
Versions of xmrs below 0.4.1 (unreleased, 0.4.2 is on crates.io but
0.4.1 is in the repo) have a bug where they swap linear and amiga
frequencies. This caused all old versions of agb (which were using
version 0.3) to use the amiga frequency table rather than the linear
one. Technically it sounds slightly wrong but it is kinda hard to tell.

Since agb 0.20.0, we are now using xmrs 0.5, which correctly reports the
frequency type for the XM file. That pointed out an error in the
note_to_speed method for linear frequencies (since those are now being
used). It turns out that the formula for calculating the frequency
expects a 0 based index for the note, but we were passing a 1 based
index for the note. Moving this down a note fixes the issue where things
were being played at the wrong frequency.

- [x] Changelog updated

We should release 0.20.1 to fix this issue pretty soon.
2024-05-15 22:02:40 +01:00
Gwilym Inzani b5fc27d243 Spell amiga correctly 2024-05-15 21:54:31 +01:00
Gwilym Inzani dac17ec28e Add a changelog entry for fixing the tracker 2024-05-15 21:38:57 +01:00
Gwilym Inzani 2ab3fa79e1 Notes are 1 indexed, not 0 indexed
Versions of xmrs below 0.4.1 (unreleased, 0.4.2 is on crates.io but
0.4.1 is in the repo) have a bug where they swap linear and amiga
frequencies. This caused all old versions of agb (which were using
version 0.3) to use the amiga frequency table rather than the linear
one. Technically it sounds slightly wrong but it is kinda hard to tell.

Since agb 0.20.0, we are now using xmrs 0.5, which correctly reports the
frequency type for the XM file. That pointed out an error in the
note_to_speed method for linear frequencies (since those are now being
used). It turns out that the formula for calculating the frequency
expects a 0 based index for the note, but we were passing a 1 based
index for the note. Moving this down a note fixes the issue where things
were being played at the wrong frequency.
2024-05-15 21:35:03 +01:00
Corwin 737b547343
Release v0.20.0 2024-05-14 22:57:40 +01:00
Corwin a0a587ac05
Allocator api feature for agb hashmap (#694)
This means hashmap can be used in stable.
2024-05-14 22:47:18 +01:00
Corwin a2c127b72b
pull out allocator_api feature 2024-05-14 22:38:42 +01:00
Corwin b316ce2cbc
remove distance_histogram 2024-05-14 22:35:39 +01:00
Gwilym Inzani 30ff065dc0
Handle failure to allocate QR code on panic (#693)
If the allocation for the working space and the result of the QR code
fails, then we don't want to panic but just not render the QR code.

- [x] no changelog update needed
2024-05-14 21:46:03 +01:00
Gwilym Inzani ae2eb5b448 Use the correct padding 2024-05-14 21:38:11 +01:00
Gwilym Inzani 94729e45ec Handle failure to allocate QR code on panic 2024-05-14 21:36:55 +01:00
Gwilym Inzani f80b180fda
Avoid double panic (#643)
Double panics could produce some interesting results, so we should
probably avoid them to avoid breaking the state too much :)

- [x] no changelog update needed
2024-05-14 21:07:30 +01:00
Corwin 7e14de0b76
Continue book (#639) 2024-05-14 20:56:16 +01:00
Gwilym Inzani b71c1d22c3
Add windows instructions (#692)
Closes #691

* Added Windows instruction for the setup
* fixed the path to the example, adjusted to the cargo-project name
* fixed broken code in the example

Original PR contains an extra merge commit we don't want, so this avoids
that.

- [x] no changelog update needed
2024-05-14 20:55:06 +01:00
Gwilym Inzani 5d44c4a658
Remove references to mac on the windows getting started instructions 2024-05-14 20:39:02 +01:00
Gwilym Inzani 9b52572235
Update Javascript packages (non-major) (#688)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@types/node](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node)
([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node))
| [`20.12.11` ->
`20.12.12`](https://renovatebot.com/diffs/npm/@types%2fnode/20.12.11/20.12.12)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/20.12.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/20.12.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/20.12.11/20.12.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/20.12.11/20.12.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@types/react](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react)
([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react))
| [`18.3.1` ->
`18.3.2`](https://renovatebot.com/diffs/npm/@types%2freact/18.3.1/18.3.2)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2freact/18.3.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2freact/18.3.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2freact/18.3.1/18.3.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2freact/18.3.1/18.3.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [styled-components](https://styled-components.com)
([source](https://togithub.com/styled-components/styled-components)) |
[`6.1.10` ->
`6.1.11`](https://renovatebot.com/diffs/npm/styled-components/6.1.10/6.1.11)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/styled-components/6.1.11?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/styled-components/6.1.11?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/styled-components/6.1.10/6.1.11?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/styled-components/6.1.10/6.1.11?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>styled-components/styled-components
(styled-components)</summary>

###
[`v6.1.11`](https://togithub.com/styled-components/styled-components/compare/v6.1.10...v6.1.11)

[Compare
Source](https://togithub.com/styled-components/styled-components/compare/v6.1.10...v6.1.11)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any
time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config help](https://togithub.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4zNTEuMiIsInVwZGF0ZWRJblZlciI6IjM3LjM1MS4yIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbXX0=-->
2024-05-14 20:14:39 +01:00
Gwilym Inzani 85c3fd2a2d
Update Rust crate fontdue to 0.9 (#689)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [fontdue](https://togithub.com/mooman219/fontdue) | dependencies |
minor | `0.8` -> `0.9` |

---

### Release Notes

<details>
<summary>mooman219/fontdue (fontdue)</summary>

###
[`v0.9.0`](https://togithub.com/mooman219/fontdue/blob/HEAD/CHANGELOG.md#090---2024-05-13)

##### Added

-   Flag to conditionally use std hashmap over `hashbrown`

##### Changes

-   Update `ttf-parser` to 0.21
-   Update `rayon` to 1.10

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4zNTEuMiIsInVwZGF0ZWRJblZlciI6IjM3LjM1MS4yIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbXX0=-->
2024-05-14 20:14:20 +01:00
tolik518 3e962f2e35 fixed the sprite example to be compilable 2024-05-14 20:36:10 +02:00
tolik518 e4b6c62445 fixed wrong executable name in path 2024-05-14 19:47:50 +02:00
tolik518 74e1ca879a added windows instructions for setup 2024-05-14 19:47:24 +02:00
renovate[bot] f9a0b8f788
Update Javascript packages (non-major) 2024-05-14 08:12:38 +00:00
renovate[bot] 90ce0b0775
Update Rust crate fontdue to 0.9 2024-05-14 00:56:14 +00:00
Corwin 38f3dfd339
Fix colour picker conversion (#687)
got it the wrong way around
2024-05-12 20:35:26 +01:00
Corwin 5f0d2d01a5
got it the wrong way around 2024-05-12 20:15:18 +01:00
Corwin bdc799af36
Web/make dpl redirect (#685) 2024-05-12 15:52:51 +01:00
Corwin f84d9aa1d3
fix the build (#686) 2024-05-12 15:44:38 +01:00
Corwin 4f18f1bc62
remove special characters in sluggification 2024-05-12 15:41:31 +01:00
Corwin 1665167e1a
fix the build 2024-05-12 15:36:25 +01:00
Corwin 839ee3b6f7
setup redirect 2024-05-12 15:27:48 +01:00
Corwin 2e78a6178e
Fix dpl page (#684) 2024-05-12 15:21:02 +01:00
Corwin e9b65e3423
this is not the colour picker 2024-05-12 15:16:58 +01:00
Corwin 617c036c8f
fix dpl page 2024-05-12 15:13:05 +01:00
Gwilym Inzani 8c2e079ec2 Mark the fact that it was a double panic in the fatal message 2024-05-12 14:08:03 +01:00
Gwilym Inzani 642c3c1b79 Better comments around the panic handler 2024-05-12 14:06:42 +01:00
Gwilym Inzani 18b25e242e Handle this in both panic handlers 2024-05-12 14:06:41 +01:00
Gwilym Inzani 9fe526d0bc Prevent a double panic 2024-05-12 14:06:14 +01:00
Gwilym Inzani 72d53244e8 Fix warnings in pong code 2024-05-12 14:03:16 +01:00
Corwin af170bdccf
Update Javascript packages (non-major) (#681) 2024-05-08 20:52:03 +01:00
renovate[bot] 79f7638a24
Update Javascript packages (non-major) 2024-05-08 15:09:36 +00:00
Corwin 0cb39662d6
Update Javascript packages (non-major) (#680) 2024-05-07 11:19:00 +01:00
renovate[bot] 55377f89fa
Update Javascript packages (non-major) 2024-05-07 00:02:02 +00:00
Corwin e2469b0de7
switch back to the orangey colour (#666)
![image](https://github.com/agbrs/agb/assets/8143879/1147fd1d-7446-437f-a4a8-0330f253830f)

![image](https://github.com/agbrs/agb/assets/8143879/c0a952e2-7b64-4da5-bcd3-0235bca859cc)
2024-05-01 01:17:43 +01:00
Corwin c19786edf0
triadic colour 2024-04-30 23:49:09 +01:00
Corwin c3a7ce9182
switch back to the orangey colour 2024-04-30 23:28:26 +01:00
Corwin 98c284a1c1
add drawing a leviathan (#665) 2024-04-30 21:36:54 +01:00
Corwin deba835a17
add drawing a leviathan 2024-04-30 21:28:30 +01:00
Gwilym Inzani 6049593aa7
Add a set_next method on OamIterator (#664)
It was annoying me how often I had to write this

- [x] Changelog updated
2024-04-30 21:28:07 +01:00
Gwilym Inzani 8ede32ea7b Mark the test as no_run rather than rust 2024-04-30 20:53:06 +01:00
Corwin 737a1582dd
Start showcase pages (#657) 2024-04-30 20:52:20 +01:00
Gwilym Inzani 609e55155b Add changelog entry for set_next 2024-04-30 20:41:01 +01:00
Gwilym Inzani 37e9fe5066 Add a set_next method on OamIterator 2024-04-30 20:39:50 +01:00
Gwilym Inzani 9501506c08
Update repo folder descriptions (#656)
I noticed that a few of the directories weren't documented. Also did a
quick edit pass

- [x] no changelog update needed
2024-04-30 20:31:24 +01:00
Gwilym Inzani ceab4302d4 Can just refer to the emulator directly once 2024-04-30 20:23:49 +01:00
Gwilym Inzani c97de67fa6 Correct command to update rustup 2024-04-30 20:23:49 +01:00
Gwilym Inzani 86f8cc45d4 Update the website link 2024-04-30 20:23:49 +01:00
Gwilym Inzani 13ef5d4ce2 Include the tracker in the headline features 2024-04-30 20:23:49 +01:00
Gwilym Inzani e9a7a80baf Update the description of the folders 2024-04-30 20:23:49 +01:00
Corwin b886ad55ae
Update Rust crate libc to 0.2.154 (#660) 2024-04-30 18:35:26 +01:00
renovate[bot] 73d84f8370
Update Rust crate libc to 0.2.154 2024-04-30 17:27:00 +00:00
Corwin 12a253b427
Update Javascript packages (non-major) (#661) 2024-04-30 18:26:27 +01:00
Corwin 543ce32339
Use book of the most recently published agb (#663) 2024-04-30 18:03:19 +01:00
Corwin 598e4b7286
fetch all history 2024-04-30 17:55:43 +01:00
Corwin 4144f05cb7
use most recent book 2024-04-30 17:41:34 +01:00
renovate[bot] e3e1e4b0c9
Update Javascript packages (non-major) 2024-04-30 02:05:52 +00:00
Corwin 9c00be8d6a
extract content block kind 2024-04-30 02:16:56 +01:00
Corwin 3587c599ac
not optional pixel ratio 2024-04-30 02:16:42 +01:00
Corwin c71ad00f1a
put body inside registry 2024-04-30 02:16:20 +01:00
Corwin b7aa9a8157
unify naming scheme 2024-04-29 02:17:41 +01:00
Corwin c14b4dfc35
link back to where you left off 2024-04-29 02:17:41 +01:00
Corwin 917d7b3d5a
pixel perfect scaling even on high density screens 2024-04-29 02:17:41 +01:00
Corwin 1991fbf056
add dpl 2024-04-29 02:17:41 +01:00
Corwin 7590a35921
add hyperspace roll 2024-04-29 02:17:41 +01:00
Corwin 6d7e6f934a
some sweeping changes that at some level involves adding a showcase 2024-04-29 02:17:41 +01:00
Corwin 3d0de3535e
use docker instead of podman (#659)
Use docker instead of podman for github actions build
2024-04-29 02:08:38 +01:00
Corwin 384c2a6ae8
pass variable before recipe 2024-04-29 02:00:02 +01:00
Corwin 23ae3788f6
use docker instead of podman 2024-04-29 01:57:32 +01:00
Gwilym Inzani 4f84c0767f
GBA has a 240x160px screen, not 144 (that's the original gameboy) (#655)
- [x] no changelog update needed
2024-04-24 14:30:09 +01:00
Gwilym Inzani ce9d3b2934 GBA has a 240x160px screen, not 144 (that's the original gameboy) 2024-04-24 11:26:12 +01:00
Corwin 412cd374b7
Expand how to do the things we said you could do (#653) 2024-04-23 22:35:14 +01:00
Corwin 9dacca0baa
add colour converter (#654) 2024-04-23 22:28:10 +01:00
Corwin cf8f410a5e
we want quot 2024-04-23 22:27:37 +01:00
Corwin ce4f27fa27
quote the variable
Co-authored-by: Gwilym Inzani <email@gwilym.dev>
2024-04-23 22:20:15 +01:00
Corwin b2096daeca
add colour converter 2024-04-23 22:19:23 +01:00
Corwin 804846e573
expand description with how to do these things 2024-04-23 20:59:22 +01:00
Corwin fe972850e3
Allow customisation of the backtrace website (#647) 2024-04-23 20:38:46 +01:00
Corwin a65f6402be
fix url to point to us 2024-04-23 20:30:40 +01:00
Gwilym Inzani 866ffaaa0f
Update Javascript packages (non-major) to v14.2.2 (#652)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[eslint-config-next](https://nextjs.org/docs/app/building-your-application/configuring/eslint#eslint-config)
([source](https://togithub.com/vercel/next.js/tree/HEAD/packages/eslint-config-next))
| [`14.2.1` ->
`14.2.2`](https://renovatebot.com/diffs/npm/eslint-config-next/14.2.1/14.2.2)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/eslint-config-next/14.2.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/eslint-config-next/14.2.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/eslint-config-next/14.2.1/14.2.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/eslint-config-next/14.2.1/14.2.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [next](https://nextjs.org)
([source](https://togithub.com/vercel/next.js)) | [`14.2.1` ->
`14.2.2`](https://renovatebot.com/diffs/npm/next/14.2.1/14.2.2) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/next/14.2.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/next/14.2.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/next/14.2.1/14.2.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/next/14.2.1/14.2.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>vercel/next.js (eslint-config-next)</summary>

###
[`v14.2.2`](https://togithub.com/vercel/next.js/compare/v14.2.1...c850e4a69a8ff62502753e2ff15bbabcea94b556)

[Compare
Source](https://togithub.com/vercel/next.js/compare/v14.2.1...v14.2.2)

</details>

<details>
<summary>vercel/next.js (next)</summary>

###
[`v14.2.2`](https://togithub.com/vercel/next.js/compare/v14.2.1...c850e4a69a8ff62502753e2ff15bbabcea94b556)

[Compare
Source](https://togithub.com/vercel/next.js/compare/v14.2.1...v14.2.2)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any
time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these
updates again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4zMTMuMSIsInVwZGF0ZWRJblZlciI6IjM3LjMxMy4xIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbXX0=-->
2024-04-23 20:09:35 +01:00
Corwin 1c9e829bd1
have website not be an option 2024-04-23 20:09:35 +01:00
renovate[bot] c9b5a19829
Update Javascript packages (non-major) to v14.2.2 2024-04-23 00:56:46 +00:00
Corwin 1f1ba909c6
expand backtrace if large (#651) 2024-04-22 13:00:41 +01:00
Corwin 237b95c460
expand backtrace if large 2024-04-22 12:52:33 +01:00
Gwilym Inzani 4243592f63
Make backtraces optional (#648)
You probably don't want backtraces if you're doing multiboot and in a
few other cases.

Also #646 broke the build if you didn't use the `testing` feature, so
I've updated the `justfile` so that a CI run checks that agb builds
correctly both without the `testing` feature and without the `backtrace`
feature. The `backtrace` feature implies the testing feature to make
things a bit simpler.

- [x] Changelog updated
2024-04-21 20:07:02 +01:00
Corwin a957a812c7
Fix: Exclusive range (#650) 2024-04-21 16:39:20 +01:00
Corwin 2560f2e15e
exclusive range 2024-04-21 16:31:41 +01:00
Corwin b402a8c23d
Update rust-wasm-bindgen monorepo (#649) 2024-04-20 22:51:39 +01:00
renovate[bot] 40fbcf830f
Update rust-wasm-bindgen monorepo 2024-04-20 21:42:45 +00:00
Corwin 8c8581e19c
Crash page (#644)
* Uses agb_debug in wasm to show addresses and more with additional
debug information!
2024-04-20 22:42:22 +01:00
Corwin 04f1d5c2ff
use library functions to get address info 2024-04-20 21:49:05 +01:00
Corwin 528fe889fa
Merge remote-tracking branch 'upstream/master' into crash-page 2024-04-20 21:41:09 +01:00
Gwilym Inzani 300d834cfa Update changelog entry 2024-04-20 20:42:38 +01:00
Gwilym Inzani 96ad727b55 Ensure feature flag combinations are built in CI and tested 2024-04-20 20:37:03 +01:00
Gwilym Inzani 580afa9335 Make the backtrace feature optional 2024-04-20 20:28:10 +01:00
Corwin b317602c6b
Get saving working (#631)
- [ ] Changelog updated / no changelog update needed
2024-04-20 16:43:35 +01:00
Corwin 4022e8413e
load gba rom as a url to let next handle cache invalidation 2024-04-20 16:19:07 +01:00
Corwin dc44d20627
save to separate areas 2024-04-20 16:18:42 +01:00
Corwin 6aee9ba154
placeholder 2024-04-20 15:38:55 +01:00
Corwin 91da2c926a
allow customisation of the backtrace website 2024-04-20 14:52:08 +01:00
Corwin 103085684a
get value that depends on being run in the client in an effect 2024-04-20 13:43:59 +01:00
Corwin bc689cbbd2
function style 2024-04-20 13:35:33 +01:00
Corwin 1adf31d140
report when there's no information for an address 2024-04-20 13:30:14 +01:00
Corwin 8352d20d73
add errors for file decoding 2024-04-20 13:27:00 +01:00
Gwilym Inzani 4899ccd5aa Avoid awkward wrapping 2024-04-20 12:48:31 +01:00
Gwilym Inzani 141a77af80 Prettier 2024-04-20 12:40:07 +01:00
Gwilym Inzani 7bbb52c449 Put the game developer summary in a details block 2024-04-20 12:38:44 +01:00
Gwilym Inzani dcdbf1069e The address isn't necessarily unique 2024-04-20 12:33:24 +01:00
Gwilym Inzani 911ea848df Allow typing in the backtrace 2024-04-20 12:31:20 +01:00
Corwin 4419dfb0b5
Split mgba log if too big (#646)
- [x] Changelog updated
2024-04-20 00:21:11 +01:00
Corwin 84d68470e4
add changelog entry 2024-04-20 00:12:36 +01:00
Corwin 7044c08100
large logs get split into multiple prints 2024-04-20 00:09:20 +01:00
Corwin e660d9257b
Add bounds check for panic writer (#645)
Can cause double panic by writing OOB.
- [x] no changelog update needed
2024-04-20 00:07:43 +01:00
Corwin e1a8b04616
add bounds check 2024-04-19 23:59:58 +01:00
Corwin 162bc17add
shift content around to make backtrace more apparent 2024-04-19 23:55:41 +01:00
Corwin 853c008ff7
cleanup duplicate text 2024-04-19 21:49:34 +01:00
Corwin 04d368edf0
move out backtrace decoding 2024-04-19 21:49:16 +01:00
Corwin 8433b23967
copy to backtrace 2024-04-19 21:49:00 +01:00
Corwin e82d7f7ce5
remove log 2024-04-19 21:12:50 +01:00
Corwin f5bbee01b7
move agb-wasm to website directory 2024-04-19 21:12:46 +01:00
Corwin 9b773524d6
setup wasm 2024-04-18 19:39:27 +01:00
Corwin 0d4005f163
make backtrace view fancy 2024-04-18 19:10:53 +01:00
Corwin 55394640b0
correct inline logic 2024-04-18 19:10:39 +01:00
Corwin 1a3b4319bc
correct justfile 2024-04-18 00:53:20 +01:00
Corwin 1cdbf13814
correct the text 2024-04-18 00:53:15 +01:00
Corwin 121ebe312c
add debug information to the crash page 2024-04-18 00:50:13 +01:00
Corwin 1d9a7d51a3
expose as wasm 2024-04-18 00:44:13 +01:00
Corwin f269e6364a
thiserror + expose some as lib 2024-04-18 00:43:47 +01:00
Corwin 72e7850152
backtrace page with more detail 2024-04-17 19:44:31 +01:00
Gwilym Inzani 9fc52000fe
Update Javascript packages (non-major) (#642)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@types/react](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react)
([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react))
| [`18.2.78` ->
`18.2.79`](https://renovatebot.com/diffs/npm/@types%2freact/18.2.78/18.2.79)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2freact/18.2.79?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2freact/18.2.79?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2freact/18.2.78/18.2.79?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2freact/18.2.78/18.2.79?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[eslint-config-next](https://nextjs.org/docs/app/building-your-application/configuring/eslint#eslint-config)
([source](https://togithub.com/vercel/next.js/tree/HEAD/packages/eslint-config-next))
| [`14.2.0` ->
`14.2.1`](https://renovatebot.com/diffs/npm/eslint-config-next/14.2.0/14.2.1)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/eslint-config-next/14.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/eslint-config-next/14.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/eslint-config-next/14.2.0/14.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/eslint-config-next/14.2.0/14.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [next](https://nextjs.org)
([source](https://togithub.com/vercel/next.js)) | [`14.2.0` ->
`14.2.1`](https://renovatebot.com/diffs/npm/next/14.2.0/14.2.1) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/next/14.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/next/14.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/next/14.2.0/14.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/next/14.2.0/14.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>vercel/next.js (eslint-config-next)</summary>

###
[`v14.2.1`](https://togithub.com/vercel/next.js/compare/v14.2.0...v14.2.1)

[Compare
Source](https://togithub.com/vercel/next.js/compare/v14.2.0...v14.2.1)

</details>

<details>
<summary>vercel/next.js (next)</summary>

###
[`v14.2.1`](https://togithub.com/vercel/next.js/compare/v14.2.0...v14.2.1)

[Compare
Source](https://togithub.com/vercel/next.js/compare/v14.2.0...v14.2.1)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any
time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config help](https://togithub.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4zMDEuNCIsInVwZGF0ZWRJblZlciI6IjM3LjMwMS40IiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbXX0=-->
2024-04-17 14:38:28 +01:00
renovate[bot] 55e60d0183
Update Javascript packages (non-major) 2024-04-16 19:31:04 +00:00
Gwilym Inzani 5c9767a201
Group JS updates to reduce PR spam a little (#641)
Make renovate only update js dependencies once per week and to group
them all in one PR.

Apparently with this branch name, renovate will validate the config for
me which is fancy

- [x]  no changelog update needed
2024-04-16 20:30:13 +01:00
Gwilym Inzani 8bdabb03dc Add justfile target to validate the renovate config 2024-04-16 20:19:57 +01:00
Gwilym Inzani d7255186be Update renovate config to group minor js dependencies and only apply them once per week 2024-04-16 20:19:38 +01:00
Corwin 8646af7536
whoops, it's oammanaged 2024-04-14 21:51:02 +01:00
Corwin 698e3ff523
use object managed 2024-04-14 21:50:08 +01:00
Corwin 4bbc1eb415
add teaser 2024-04-14 17:32:57 +01:00
Corwin b8a6cdde3a
add meta sprites chapter 2024-04-14 17:19:21 +01:00
Corwin 28aa676d17
Update dependency @types/react to v18.2.78 (#638) 2024-04-13 18:36:57 +01:00
Gwilym Inzani e7bf7bba94
Update Rust crate addr2line to 0.22 (#633)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [addr2line](https://togithub.com/gimli-rs/addr2line) | dependencies |
minor | `0.21` -> `0.22` |

---

### Release Notes

<details>
<summary>gimli-rs/addr2line (addr2line)</summary>

###
[`v0.22.0`](https://togithub.com/gimli-rs/addr2line/blob/HEAD/CHANGELOG.md#0220-20240411)

[Compare
Source](https://togithub.com/gimli-rs/addr2line/compare/0.21.0...0.22.0)

##### Breaking changes

-   Updated `gimli` and `object` dependencies.

***

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yNjkuMiIsInVwZGF0ZWRJblZlciI6IjM3LjI2OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-04-13 16:06:13 +01:00
Gwilym Inzani 7f493e922e Simplify the declaration a little 2024-04-13 15:58:30 +01:00
Gwilym Inzani 66e55890e2 Only need 1 lifetime here 2024-04-13 15:56:00 +01:00
renovate[bot] 19cf20bff8
Update dependency @types/react to v18.2.78 2024-04-13 13:46:48 +00:00
Corwin 81d9db5c36
Update dependency @types/react to v18.2.77 (#635) 2024-04-11 23:17:05 +01:00
Corwin bfe0cb31d6
Update nextjs monorepo to v14.2.0 (#636) 2024-04-11 23:16:51 +01:00
renovate[bot] 4c665a49a8
Update nextjs monorepo to v14.2.0 2024-04-11 21:54:10 +00:00
renovate[bot] 5fdd18927d
Update dependency @types/react to v18.2.77 2024-04-11 21:53:47 +00:00
Corwin 80ef7fb7f1
Update react monorepo to v18.2.76 (#634) 2024-04-11 22:52:56 +01:00
renovate[bot] 009d10da43
Update react monorepo to v18.2.76 2024-04-11 19:04:05 +00:00
renovate[bot] 0b63284c7b
Update Rust crate addr2line to 0.22 2024-04-11 10:29:52 +00:00
Corwin 418f792ef2
get saving working 2024-04-10 23:24:44 +01:00
Corwin 5365ce6188
remove hard reset 2024-04-10 20:50:55 +01:00
Corwin 27ad5d1184
Add controller support (#630)
Simple use of gamepad apis to add controller support.
2024-04-10 20:38:54 +01:00
Corwin 99789c369d
Update dependency typescript to v5.4.5 (#629) 2024-04-10 18:33:52 +01:00
Corwin 4e4e323002
format ts files 2024-04-10 18:31:24 +01:00
Corwin c29a9a4a2b
add controller support 2024-04-10 18:30:12 +01:00
renovate[bot] b6dc67dd24
Update dependency typescript to v5.4.5 2024-04-10 16:36:12 +00:00
Corwin 5f37e9f442
Update dependency @types/node to v20.12.7 (#628) 2024-04-09 22:30:35 +01:00
renovate[bot] fe7fae1c04
Update dependency @types/node to v20.12.7 2024-04-09 21:24:31 +00:00
Corwin 2bacef161b
Use portable atomics and other similar libraries (#565)
I tried switching out our statics to use the standard portable atomics,
critical section, and once cell crates.
One of the save test fails in release mode for me, not sure why but
these tests failing always suggests magic is going on.

- [x] Changelog updated / no changelog update needed
2024-04-09 22:23:40 +01:00
Corwin 413a889488
add changelog entry 2024-04-09 22:17:31 +01:00
Corwin a0895635ab
use portable atomic from agb 2024-04-09 22:08:55 +01:00
Corwin c632eb4ea3
type use of rng 2024-04-09 22:03:33 +01:00
Corwin 32eb34f226
fix panic renderer 2024-04-09 21:58:49 +01:00
Corwin d6b32e511d
pub them in external mod 2024-04-09 21:57:26 +01:00
Corwin 7ade79e132
update other projects 2024-04-09 21:52:54 +01:00
Corwin fb247aa8f2
move single file module out of directory 2024-04-09 21:52:04 +01:00
Corwin 10575f28a6
delay cell 2024-04-09 21:52:04 +01:00
Corwin 9fbd420089
add test that atomic read / write works 2024-04-09 21:52:04 +01:00
Corwin 2b4c4459e0
use portable atomics and other similar libraries 2024-04-09 21:52:00 +01:00
Gwilym Inzani 11b51e0a75
Workspaces (#626)
We can put everything except 'agb' and the 'agb-tracker' crates in a
workspace for hopefully easier management :)

- [x] no changelog update needed
2024-04-09 21:45:59 +01:00
Gwilym Inzani b963065ad6 Update the justfile 2024-04-09 21:06:21 +01:00
Gwilym Inzani 7a059b2142 This is called agb-debug 2024-04-09 21:06:16 +01:00
Gwilym Inzani 36cdc9e28d Don't need this workspace any more 2024-04-09 21:06:08 +01:00
Gwilym Inzani 65388e01f5 Fix more clippy lints in the emulator 2024-04-09 20:56:19 +01:00
Gwilym Inzani 08ad8765de Fix clippy lint and fmt in the emulator 2024-04-09 20:55:21 +01:00
Gwilym Inzani 52ddd97a2e Switch to cargo workspaces for every crate we support 2024-04-09 20:54:12 +01:00
Corwin 0dab252379
RFC: Remove Cargo lockfiles (#621)
Maintaining the lockfiles has proven to be an annoyance with regular
"update lockfiles" commits. We don't actually care what's in the
lockfiles.

The problem is that they're not kept in sync with each other. We really
want a workspace to have one lockfile for the whole project, but
limitations is workspaces means this is not currently possible.
2024-04-09 20:51:28 +01:00
Corwin c8abf33c8f
remove update lockfiles workflow 2024-04-09 20:43:31 +01:00
Corwin b7ec8a77d5
ignore Cargo lockfiles 2024-04-09 20:42:11 +01:00
Corwin bf3e708f6f
remove all lockfiles 2024-04-09 20:42:09 +01:00
Corwin 6c60b770b5
Implement signed for our fix num (#578)
* Integrates num_traits more closely.
* Implements signed for our num, and the vector2d / rect abs now can use
our fixnum.
* This is potentially breaking.
2024-04-09 20:41:00 +01:00
Corwin 7d0e05c9b5
update changelog 2024-04-09 20:33:26 +01:00
Corwin 57681f1084
use num traits for and implement signed 2024-04-09 20:26:15 +01:00
Corwin cddb85df05
use num traits 2024-04-09 20:26:15 +01:00
Gwilym Inzani e8aed8e376
Backtraces (#590)
Implements a very basic backtrace and the ability to format them

If you run the panic example and press A, you get:

```
[ERROR] GBA Debug: [failed]
[ERROR] GBA Debug: debug data: ce3-1ee7-1fb7-24d-1ad
[FATAL] GBA Debug: Error: panicked at src/memory_mapped.rs:101:24:
index out of bounds: the len is 240 but the index is 240
```

which you can then prettify with:

```
> agb-addr2line ../target/thumbv4t-none-eabi/debug/examples/panic 0ce3-1f57-2027-024d-01ad
0:	rust_begin_unwind <agb>/lib.rs:321
1:	core::panicking::panic_nounwind <core>/panicking.rs:151
2:	core::panicking::assert_failed_inner <core>/panicking.rs:321
3:	agb::memory_mapped::MemoryMapped2DArray<T,_,_>::set <agb>/memory_mapped.rs:101
	(inlined by) agb::display::bitmap3::Bitmap3::draw_point <agb>/display/bitmap3.rs:31
4:	main /home/gwilym/Projects/agb/agb/examples/panic.rs:15
```

- [ ] Changelog updated / no changelog update needed
2024-04-09 20:25:15 +01:00
Corwin 646b7947e9
Enforce functions (#625) 2024-04-09 20:22:28 +01:00
Gwilym Inzani 5f8c1a4634
Update peaceiris/actions-mdbook action to v2 (#617)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[peaceiris/actions-mdbook](https://togithub.com/peaceiris/actions-mdbook)
| action | major | `v1` -> `v2` |

---

### Release Notes

<details>
<summary>peaceiris/actions-mdbook (peaceiris/actions-mdbook)</summary>

###
[`v2`](https://togithub.com/peaceiris/actions-mdbook/compare/v1...v2)

[Compare
Source](https://togithub.com/peaceiris/actions-mdbook/compare/v1...v2)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yNjkuMiIsInVwZGF0ZWRJblZlciI6IjM3LjI2OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-04-09 20:18:02 +01:00
Gwilym Inzani c77ed7fa56 Update the justfile target 2024-04-09 20:15:33 +01:00
Gwilym Inzani 966fda443a Rename agb-addr2line to agb-debug 2024-04-09 20:13:20 +01:00
Gwilym Inzani eca511bc83 Add a changelog entry for the new backtraces 2024-04-09 20:09:52 +01:00
Corwin 754435ad1e
show mobile controls on a small screen (#624) 2024-04-09 12:48:21 +01:00
Corwin dcd632d3e6
Update dependency @types/node to v20.12.6 (#623)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@types/node](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node)
([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node))
| [`20.12.5` ->
`20.12.6`](https://renovatebot.com/diffs/npm/@types%2fnode/20.12.5/20.12.6)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/20.12.6?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/20.12.6?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/20.12.5/20.12.6?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/20.12.5/20.12.6?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yNjkuMiIsInVwZGF0ZWRJblZlciI6IjM3LjI2OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-04-09 12:47:01 +01:00
Corwin eb30a7a825
prefer regular functions over named arrow functions 2024-04-09 12:46:13 +01:00
Corwin 12316dbe6a
show mobile controls on a small screen 2024-04-09 12:15:11 +01:00
renovate[bot] 8b396fc576
Update dependency @types/node to v20.12.6 2024-04-09 07:21:24 +00:00
Corwin abd5e44ede
Press to start on mobile (#622) 2024-04-09 02:46:10 +01:00
Corwin bbdcdfeb95
readd hover border on help links 2024-04-09 02:38:22 +01:00
Corwin f6c703060f
Update dependency @types/react to v18.2.75 (#618) 2024-04-09 02:34:13 +01:00
Corwin 73d4346964
nicer height calculation 2024-04-09 02:32:36 +01:00
Corwin 9ad67ae494
on mobile devices require a touch to start the emulator loading 2024-04-09 02:31:17 +01:00
GBA bot ef694ad776 Update lockfiles 2024-04-09 00:04:04 +00:00
renovate[bot] 143afc961e
Update dependency @types/react to v18.2.75 2024-04-09 00:03:25 +00:00
Corwin 362e0d864f
make website with nextjs (#619) 2024-04-09 01:01:40 +01:00
Corwin 07e0608949
cache next build 2024-04-09 00:41:28 +01:00
Corwin a9c6723a3b
make website with nextjs 2024-04-09 00:33:32 +01:00
GBA bot ef378905fe Update lockfiles 2024-04-08 19:56:04 +00:00
renovate[bot] 0970bc1b92
Update peaceiris/actions-mdbook action to v2 2024-04-08 19:55:29 +00:00
Corwin 7206b8f925
Update dependency @testing-library/react to v14.3.0 (#616)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@testing-library/react](https://togithub.com/testing-library/react-testing-library)
| [`14.2.2` ->
`14.3.0`](https://renovatebot.com/diffs/npm/@testing-library%2freact/14.2.2/14.3.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@testing-library%2freact/14.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@testing-library%2freact/14.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@testing-library%2freact/14.2.2/14.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@testing-library%2freact/14.2.2/14.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>testing-library/react-testing-library
(@&#8203;testing-library/react)</summary>

###
[`v14.3.0`](https://togithub.com/testing-library/react-testing-library/compare/v14.2.2...9c4a46d5b9923c21c936d206614a8febcc939fc2)

[Compare
Source](https://togithub.com/testing-library/react-testing-library/compare/v14.2.2...9c4a46d5b9923c21c936d206614a8febcc939fc2)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yNjkuMiIsInVwZGF0ZWRJblZlciI6IjM3LjI2OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-04-08 17:05:16 +01:00
GBA bot 2cfb5b576c Update lockfiles 2024-04-08 14:53:37 +00:00
renovate[bot] b46a5ba43d
Update dependency @testing-library/react to v14.3.0 2024-04-08 14:53:01 +00:00
Corwin 8ddc55284c
Compress combo rom (#615)
GitHub pages, for whatever reason, doesn't compress the combo ROM and
instead serves it uncompressed. Therefore, we explicitly compress it
using the highest compression level at build time and explicitly
decompress it.

Previously we would download 14.69MB, now we download 7.84MB.
Approximately 50% savings.
2024-04-08 03:38:46 +01:00
Corwin b830410e39
remove log statement 2024-04-08 03:24:06 +01:00
Corwin f1ef67ad1e
use the gzip compressed combo rom 2024-04-08 03:23:55 +01:00
Corwin f0ee5a081c
make emulator wrapper be able to decompress gzip compressed roms 2024-04-08 03:23:47 +01:00
Corwin 582cce78c8
compress the combo rom 2024-04-08 03:23:19 +01:00
Corwin 9b36ae62e0
Manually handle frameskipping for better audio on non multiple of 60hz screens (#613)
* We want to always use animation frames as our time to call the main
loop because otherwise the timing is inconsistent leading to very bad
audio.
* We don't want to call the main loop every frame otherwise > 60hz
screens will play too fast.
* We can't emscripten's frameskipping becuase it only allows for
integers whereas screeens come in many other framerates such as 75hz,
90hz, 144hz, etc.
* Therefore we manually manage frameskipping by ~~ab~~using pause and
resume game which internally just enable and disable the emscripten's
calling of the main loop. (see
27dede256b/src/platform/wasm/main.c (L183)).
* We could modify the code to let us call the main loop ourselves and
take full control over this, but for now this is okay.
2024-04-06 20:24:44 +01:00
Corwin 290387af16
Update dependency @types/node to v20.12.5 (#612)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@types/node](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node)
([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node))
| [`20.12.4` ->
`20.12.5`](https://renovatebot.com/diffs/npm/@types%2fnode/20.12.4/20.12.5)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/20.12.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/20.12.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/20.12.4/20.12.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/20.12.4/20.12.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yNjkuMiIsInVwZGF0ZWRJblZlciI6IjM3LjI2OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-04-06 19:47:40 +01:00
Corwin 7f0de5f87b
manually handle frameskipping for better audio on non multiple of 60hz screens 2024-04-06 19:42:44 +01:00
Corwin b47dc28f6f
Fix controls (#610)
* Controls were broken on mobile because dpad movement was interpreted
as a/b button presses.
* Fixes it to:
  * Handle multiple fingers using the dpad / a / b buttons
* A dpad movement must start on the dpad, and a/b presses must start on
a/b.
2024-04-06 03:33:42 +01:00
Corwin 3b2ebe6001
dynamically choose frameskip or timeout 2024-04-06 03:26:06 +01:00
GBA bot ba85226cb3 Update lockfiles 2024-04-06 01:54:49 +00:00
renovate[bot] be25491f15
Update dependency @types/node to v20.12.5 2024-04-06 01:54:17 +00:00
Corwin 6704b96fda
Fix clippy lints (#611) 2024-04-06 02:53:25 +01:00
Corwin 559b53456f
use clamp 2024-04-06 02:45:54 +01:00
Corwin 0d609f6d4a
satisfy linter 2024-04-06 02:36:02 +01:00
Corwin 61a7e2fa64
force full reset which can get audio working on mobile 2024-04-06 02:34:39 +01:00
Corwin f053915c65
fix controls 2024-04-06 02:24:10 +01:00
Corwin 92c8877201
we should be overwriting max width 2024-04-06 02:17:01 +01:00
Corwin 3461052193
handle multiple dpad touches 2024-04-06 02:14:15 +01:00
Corwin b9a67e6b0f
handle many button presses and fix to use targetTouches 2024-04-06 02:12:39 +01:00
Corwin 85f5a8493c
Website fixes (#609) 2024-04-05 22:31:16 +01:00
Corwin 3a1f1691f9
swap start and select 2024-04-05 22:23:47 +01:00
Corwin e61fdb7f97
make wider on mobile 2024-04-05 22:23:35 +01:00
Corwin c433dbefdc
Mobile support for website (#607)
Adds mobile control scheme that sort of works.
I feel like it doesn't quite work.

Also, frame rate problems on mobile.

- [ ] Changelog updated / no changelog update needed
2024-04-05 20:24:29 +01:00
Corwin 7893437109
add docs link (#608) 2024-04-05 20:01:37 +01:00
Corwin a1e8ac76fe
add docs link 2024-04-05 19:53:38 +01:00
Corwin 34c66cc61e
specify dependency array 2024-04-05 19:50:12 +01:00
Corwin 48373faa17
finish adding mobile controls 2024-04-05 19:47:04 +01:00
Corwin 552f8f878d
more mobile stuff 2024-04-05 17:09:50 +01:00
Corwin e43d2d5a3e
make widths work on mobile 2024-04-05 12:09:13 +01:00
Corwin 3dc828bae7
make start and select work by default (#606)
Enter and Shift should be not all upper case by default (at least on my
machine).
2024-04-05 01:04:39 +01:00
Corwin 994e1fe717
make start and select work by default 2024-04-05 00:58:38 +01:00
Corwin edd381796f
make combo movement faster as the old bug has been fixed (#605) 2024-04-05 00:48:53 +01:00
Corwin 835f167d14
add node modules to cache (#604) 2024-04-05 00:47:28 +01:00
Corwin b0f9e65d66
make combo movement faster as the old bug has been fixed 2024-04-05 00:43:19 +01:00
Corwin ac9f93f261
add node modules to cache 2024-04-05 00:41:38 +01:00
Corwin 549c90b746
Update dependency @testing-library/jest-dom to v6 (#601)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@testing-library/jest-dom](https://togithub.com/testing-library/jest-dom)
| [`^5.16.5` ->
`^6.0.0`](https://renovatebot.com/diffs/npm/@testing-library%2fjest-dom/5.17.0/6.4.2)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@testing-library%2fjest-dom/6.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@testing-library%2fjest-dom/6.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@testing-library%2fjest-dom/5.17.0/6.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@testing-library%2fjest-dom/5.17.0/6.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>testing-library/jest-dom
(@&#8203;testing-library/jest-dom)</summary>

###
[`v6.4.2`](https://togithub.com/testing-library/jest-dom/releases/tag/v6.4.2)

[Compare
Source](https://togithub.com/testing-library/jest-dom/compare/v6.4.1...v6.4.2)

##### Bug Fixes

- Remove errant export of GetByRoleMatcher, fixing type checking in some
TS configurations
([#&#8203;575](https://togithub.com/testing-library/jest-dom/issues/575))
([a93c0c4](a93c0c4a20))

###
[`v6.4.1`](https://togithub.com/testing-library/jest-dom/releases/tag/v6.4.1)

[Compare
Source](https://togithub.com/testing-library/jest-dom/compare/v6.4.0...v6.4.1)

##### Bug Fixes

- Export type `TestingLibraryMatchers` from "./matchers"
([#&#8203;576](https://togithub.com/testing-library/jest-dom/issues/576))
([dd1c4dd](dd1c4dd504))

###
[`v6.4.0`](https://togithub.com/testing-library/jest-dom/releases/tag/v6.4.0)

[Compare
Source](https://togithub.com/testing-library/jest-dom/compare/v6.3.0...v6.4.0)

##### Features

- Add toHaveRole matcher
([#&#8203;572](https://togithub.com/testing-library/jest-dom/issues/572))
([f7dc673](f7dc673dbc))

###
[`v6.3.0`](https://togithub.com/testing-library/jest-dom/releases/tag/v6.3.0)

[Compare
Source](https://togithub.com/testing-library/jest-dom/compare/v6.2.1...v6.3.0)

##### Features

- Support for regular expressions in toHaveClass
([#&#8203;563](https://togithub.com/testing-library/jest-dom/issues/563))
([9787ed5](9787ed59fc))

###
[`v6.2.1`](https://togithub.com/testing-library/jest-dom/releases/tag/v6.2.1)

[Compare
Source](https://togithub.com/testing-library/jest-dom/compare/v6.2.0...v6.2.1)

##### Bug Fixes

- Standalone types for "./matchers" export and add Bun support
([#&#8203;566](https://togithub.com/testing-library/jest-dom/issues/566))
([5675b86](5675b8668c))

###
[`v6.2.0`](https://togithub.com/testing-library/jest-dom/releases/tag/v6.2.0)

[Compare
Source](https://togithub.com/testing-library/jest-dom/compare/v6.1.6...v6.2.0)

##### Features

- toHaveAccessibleDescription supports aria-description
([#&#8203;565](https://togithub.com/testing-library/jest-dom/issues/565))
([1fb156c](1fb156c2b5))

###
[`v6.1.6`](https://togithub.com/testing-library/jest-dom/releases/tag/v6.1.6)

[Compare
Source](https://togithub.com/testing-library/jest-dom/compare/v6.1.5...v6.1.6)

##### Bug Fixes

- Upgrade
[@&#8203;adobe/css-tools](https://togithub.com/adobe/css-tools) to
v4.3.2
([#&#8203;553](https://togithub.com/testing-library/jest-dom/issues/553))
([b64b953](b64b953f76))

###
[`v6.1.5`](https://togithub.com/testing-library/jest-dom/releases/tag/v6.1.5)

[Compare
Source](https://togithub.com/testing-library/jest-dom/compare/v6.1.4...v6.1.5)

##### Bug Fixes

- support uppercase custom props in toHaveStyle
([#&#8203;552](https://togithub.com/testing-library/jest-dom/issues/552))
([b7b7c6a](b7b7c6a965))

###
[`v6.1.4`](https://togithub.com/testing-library/jest-dom/releases/tag/v6.1.4)

[Compare
Source](https://togithub.com/testing-library/jest-dom/compare/v6.1.3...v6.1.4)

##### Bug Fixes

- upgrade `@adobe/css-tools` to `4.3.1` to address vulnerability
([#&#8203;532](https://togithub.com/testing-library/jest-dom/issues/532))
([44f1eab](44f1eabc79))

###
[`v6.1.3`](https://togithub.com/testing-library/jest-dom/releases/tag/v6.1.3)

[Compare
Source](https://togithub.com/testing-library/jest-dom/compare/v6.1.2...v6.1.3)

##### Bug Fixes

- proper [@&#8203;jest/globals](https://togithub.com/jest/globals)
import
([#&#8203;530](https://togithub.com/testing-library/jest-dom/issues/530))
([5b492ac](5b492ace23))

###
[`v6.1.2`](https://togithub.com/testing-library/jest-dom/releases/tag/v6.1.2)

[Compare
Source](https://togithub.com/testing-library/jest-dom/compare/v6.1.1...v6.1.2)

##### Bug Fixes

- bump [@&#8203;adobe/css-tools](https://togithub.com/adobe/css-tools)
for ESM support
([#&#8203;525](https://togithub.com/testing-library/jest-dom/issues/525))
([b959a68](b959a68138))

###
[`v6.1.1`](https://togithub.com/testing-library/jest-dom/releases/tag/v6.1.1)

[Compare
Source](https://togithub.com/testing-library/jest-dom/compare/v6.1.0...v6.1.1)

##### Bug Fixes

- **package.json:** update main and module file paths
([#&#8203;523](https://togithub.com/testing-library/jest-dom/issues/523))
([853a3e5](853a3e51ba))

###
[`v6.1.0`](https://togithub.com/testing-library/jest-dom/releases/tag/v6.1.0)

[Compare
Source](https://togithub.com/testing-library/jest-dom/compare/v6.0.1...v6.1.0)

##### Features

- Publish ESM and CJS
([https://github.com/testing-library/jest-dom/pull/519](https://togithub.com/testing-library/jest-dom/pull/519))

###
[`v6.0.1`](https://togithub.com/testing-library/jest-dom/releases/tag/v6.0.1)

[Compare
Source](https://togithub.com/testing-library/jest-dom/compare/v6.0.0...v6.0.1)

##### Bug Fixes

- matchers type is making the global expect unsafe
([#&#8203;513](https://togithub.com/testing-library/jest-dom/issues/513))
([bdb34f1](bdb34f1295))

###
[`v6.0.0`](https://togithub.com/testing-library/jest-dom/releases/tag/v6.0.0)

[Compare
Source](https://togithub.com/testing-library/jest-dom/compare/v5.17.0...v6.0.0)

##### Features

- local types, supporting jest,
[@&#8203;jest/globals](https://togithub.com/jest/globals), vitest
([#&#8203;511](https://togithub.com/testing-library/jest-dom/issues/511))
([4b764b9](4b764b9f6a))

##### BREAKING CHANGES

-   Removes the extend-expect script. Users should use
    the default import path or one of the new test platform-specific
    paths to automatically extend the appropriate "expect" instance.

extend-expect was not documented in the Readme, so this change should
have minimal impact.

Users can now use the following import paths to automatically extend
"expect" for their chosen test platform:

-
[@&#8203;testing-library/jest-dom](https://togithub.com/testing-library/jest-dom)
- jest ([@&#8203;types/jest](https://togithub.com/types/jest))
- @&#8203;testing-library/jest-dom/jest-globals -
[@&#8203;jest/globals](https://togithub.com/jest/globals)
-   @&#8203;testing-library/jest-dom/vitest - vitest

For example:

import '@&#8203;testing-library/jest-dom/jest-globals'

Importing from one of the above paths will augment the appropriate
matcher interface for the given test platform, assuming the import
is done in a .ts file that is included in the user's tsconfig.json.

It's also (still) possible to import the matchers directly without
side effects:

import \* as matchers from '@&#8203;testing-library/jest-dom/matchers'

-   Update kcd-scripts
-   Drop node < 14

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yNjkuMiIsInVwZGF0ZWRJblZlciI6IjM3LjI2OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-04-04 22:54:34 +00:00
renovate[bot] 2877ea2177
Update dependency @testing-library/jest-dom to v6 2024-04-04 22:47:37 +00:00
Corwin b9c76511a2
Update dependency prettier to v3 (#602)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [prettier](https://prettier.io)
([source](https://togithub.com/prettier/prettier)) | [`2.8.8` ->
`3.2.5`](https://renovatebot.com/diffs/npm/prettier/2.8.8/3.2.5) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/prettier/3.2.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/prettier/3.2.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/prettier/2.8.8/3.2.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/prettier/2.8.8/3.2.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>prettier/prettier (prettier)</summary>

###
[`v3.2.5`](https://togithub.com/prettier/prettier/blob/HEAD/CHANGELOG.md#325)

[Compare
Source](https://togithub.com/prettier/prettier/compare/3.2.4...3.2.5)

[diff](https://togithub.com/prettier/prettier/compare/3.2.4...3.2.5)

##### Support Angular inline styles as single template literal
([#&#8203;15968](https://togithub.com/prettier/prettier/pull/15968) by
[@&#8203;sosukesuzuki](https://togithub.com/sosukesuzuki))

[Angular
v17](https://blog.angular.io/introducing-angular-v17-4d7033312e4b)
supports single string inline styles.

<!-- prettier-ignore -->

```ts
// Input
@&#8203;Component({
  template: `<div>...</div>`,
  styles: `h1 { color: blue; }`,
})
export class AppComponent {}

// Prettier 3.2.4
@&#8203;Component({
  template: `<div>...</div>`,
  styles: `h1 { color: blue; }`,
})
export class AppComponent {}

// Prettier 3.2.5
@&#8203;Component({
  template: `<div>...</div>`,
  styles: `
    h1 {
      color: blue;
    }
  `,
})
export class AppComponent {}

```

##### Unexpected embedded formatting for Angular template
([#&#8203;15969](https://togithub.com/prettier/prettier/pull/15969) by
[@&#8203;JounQin](https://togithub.com/JounQin))

Computed template should not be considered as Angular component template

<!-- prettier-ignore -->

```ts
// Input
const template = "foobar";

@&#8203;Component({
  [template]: `<h1>{{       hello }}</h1>`,
})
export class AppComponent {}

// Prettier 3.2.4
const template = "foobar";

@&#8203;Component({
  [template]: `<h1>{{ hello }}</h1>`,
})
export class AppComponent {}

// Prettier 3.2.5
const template = "foobar";

@&#8203;Component({
  [template]: `<h1>{{       hello }}</h1>`,
})
export class AppComponent {}
```

##### Use `"json"` parser for `tsconfig.json` by default
([#&#8203;16012](https://togithub.com/prettier/prettier/pull/16012) by
[@&#8203;sosukesuzuki](https://togithub.com/sosukesuzuki))

In
[v2.3.0](https://prettier.io/blog/2024/01/12/3.2.0#new-jsonc-parser-added-15831httpsgithubcomprettierprettierpull15831-by-fiskerhttpsgithubcomfisker),
we introduced `"jsonc"` parser which adds trialing comma **by default**.

When adding a new parser we also define how it will be used based on the
[`linguist-languages`](https://www.npmjs.com/package/linguist-languages)
data.

`tsconfig.json` is a special file used by
[TypeScript](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#using-tsconfigjson-or-jsconfigjson),
it uses `.json` file extension, but it actually uses the [JSON with
Comments](https://code.visualstudio.com/docs/languages/json#\_json-with-comments)
syntax. However, we found that there are many third-party tools not
recognize it correctly because of the confusing `.json` file extension.

We decide to treat it as a JSON file for now to avoid the extra
configuration step.

To keep using the `"jsonc"` parser for your `tsconfig.json` files, add
the following to your `.pretterrc` file

```json
{
  "overrides": [
    {
      "files": ["tsconfig.json", "jsconfig.json"],
      "options": {
        "parser": "jsonc"
      }
    }
  ]
}
```

<!-- prettier-ignore -->

```
```

###
[`v3.2.4`](https://togithub.com/prettier/prettier/blob/HEAD/CHANGELOG.md#324)

[Compare
Source](https://togithub.com/prettier/prettier/compare/3.2.3...3.2.4)

[diff](https://togithub.com/prettier/prettier/compare/3.2.3...3.2.4)

##### Fix incorrect parser inference
([#&#8203;15947](https://togithub.com/prettier/prettier/pull/15947) by
[@&#8203;fisker](https://togithub.com/fisker))

Files like `.eslintrc.json` were incorrectly formatted as JSONC files.

<!-- prettier-ignore -->

```jsx
// Input
prettier --file-info .eslintrc.json
{ "ignored": false, "inferredParser": "jsonc" }

// Prettier 3.2.4
prettier --file-info .eslintrc.json
{ "ignored": false, "inferredParser": "json" }
```

###
[`v3.2.3`](https://togithub.com/prettier/prettier/blob/HEAD/CHANGELOG.md#323)

[Compare
Source](https://togithub.com/prettier/prettier/compare/3.2.2...3.2.3)

[diff](https://togithub.com/prettier/prettier/compare/3.2.2...3.2.3)

##### Throw errors for invalid code
([#&#8203;15881](https://togithub.com/prettier/prettier/pull/15881) by
[@&#8203;fisker](https://togithub.com/fisker),
[@&#8203;Josh-Cena](https://togithub.com/Josh-Cena),
[@&#8203;auvred](https://togithub.com/auvred))

<!-- prettier-ignore -->

```ts
// Input
1++;

// Prettier 3.2.2
1++;

// Prettier 3.2.3
SyntaxError: Invalid left-hand side expression in unary operation (1:1)
> 1 | 1++;
    | ^
```

<!-- prettier-ignore -->

```ts
// Input
try {} catch (error = 1){}

// Prettier 3.2.2
try {
} catch (error) {}

// Prettier 3.2.3
SyntaxError: Catch clause variable cannot have an initializer. (1:23)
> 1 | try {} catch (error = 1){}
    |                       ^
```

##### Fix parser inference
([#&#8203;15927](https://togithub.com/prettier/prettier/pull/15927) by
[@&#8203;fisker](https://togithub.com/fisker))

<!-- prettier-ignore -->

```console
// Prettier 3.2.2
prettier --file-info tsconfig.json
{ "ignored": false, "inferredParser": "json" }

// Prettier 3.2.3
prettier --file-info tsconfig.json
{ "ignored": false, "inferredParser": "jsonc" }
```

###
[`v3.2.2`](https://togithub.com/prettier/prettier/blob/HEAD/CHANGELOG.md#322)

[Compare
Source](https://togithub.com/prettier/prettier/compare/3.2.1...3.2.2)

[diff](https://togithub.com/prettier/prettier/compare/3.2.1...3.2.2)

##### Fix crash when parsing template literal CSS in a JSX style tag
using a spread attribute
([#&#8203;15896](https://togithub.com/prettier/prettier/pull/15896) by
[@&#8203;eelco](https://togithub.com/eelco))

For example this code would crash before:

<!-- prettier-ignore -->

```jsx
<style {...spread}>{`.{}`}</style>
```

##### Fix formatting error on optional call expression and member chain
([#&#8203;15920](https://togithub.com/prettier/prettier/pull/15920) by
[@&#8203;sosukesuzuki](https://togithub.com/sosukesuzuki))

<!-- prettier-ignore -->

```jsx
// Input
a(() => {}, c?.d());

// Prettier 3.2.1
TypeError: Cannot read properties of undefined (reading 'type')

// Prettier 3.2.2
a(() => {}, c?.d());
```

###
[`v3.2.1`](https://togithub.com/prettier/prettier/blob/HEAD/CHANGELOG.md#321)

[Compare
Source](https://togithub.com/prettier/prettier/compare/3.2.0...3.2.1)

[diff](https://togithub.com/prettier/prettier/compare/3.2.0...3.2.1)

##### Fix formatting error on member chain
([#&#8203;15915](https://togithub.com/prettier/prettier/pull/15915) by
[@&#8203;sosukesuzuki](https://togithub.com/sosukesuzuki))

<!-- prettier-ignore -->

```jsx
// Input
test().test2().test2(thing?.something);

// Prettier 3.2.0
TypeError: Cannot read properties of undefined (reading 'type')

// Prettier 3.2.1
test().test2().test2(thing?.something);

```

###
[`v3.2.0`](https://togithub.com/prettier/prettier/blob/HEAD/CHANGELOG.md#320)

[Compare
Source](https://togithub.com/prettier/prettier/compare/3.1.1...3.2.0)

[diff](https://togithub.com/prettier/prettier/compare/3.1.1...3.2.0)

🔗 [Release Notes](https://prettier.io/blog/2024/01/13/3.2.0.html)

###
[`v3.1.1`](https://togithub.com/prettier/prettier/blob/HEAD/CHANGELOG.md#311)

[Compare
Source](https://togithub.com/prettier/prettier/compare/3.1.0...3.1.1)

[diff](https://togithub.com/prettier/prettier/compare/3.1.0...3.1.1)

##### Fix config file search
([#&#8203;15363](https://togithub.com/prettier/prettier/pull/15363) by
[@&#8203;fisker](https://togithub.com/fisker))

Previously, we start search for config files from the filePath as a
directory, if it happened to be a directory and contains config file, it
will be used by mistake.

```text
├─ .prettierrc
└─ test.js         (A directory)
  └─ .prettierrc
```

```js
// Prettier 3.1.0
await prettier.resolveConfigFile(new URL("./test.js", import.meta.url));
// <CWD>/test.js/.prettierrc

// Prettier 3.1.1
await prettier.resolveConfigFile(new URL("./test.js", import.meta.url));
// <CWD>/.prettierrc
```

##### Skip explicitly passed symbolic links with
`--no-error-on-unmatched-pattern`
([#&#8203;15533](https://togithub.com/prettier/prettier/pull/15533) by
[@&#8203;sanmai-NL](https://togithub.com/sanmai-NL))

Since Prettier v3, we stopped following symbolic links, however in some
use cases, the symbolic link patterns can't be filtered out, and there
is no way to prevent Prettier from throwing errors.

In Prettier 3.1.1, you can use `--no-error-on-unmatched-pattern` to
simply skip symbolic links.

##### Consistently use tabs in ternaries when `useTabs` is `true`
([#&#8203;15662](https://togithub.com/prettier/prettier/pull/15662) by
[@&#8203;auvred](https://togithub.com/auvred))

<!-- prettier-ignore -->

```jsx
// Input
aaaaaaaaaaaaaaa
	? bbbbbbbbbbbbbbbbbb
	: ccccccccccccccc
	  ? ddddddddddddddd
	  : eeeeeeeeeeeeeee
	    ? fffffffffffffff
	    : gggggggggggggggg;

// Prettier 3.1.0
aaaaaaaaaaaaaaa
	? bbbbbbbbbbbbbbbbbb
	: ccccccccccccccc
	  ? ddddddddddddddd
	  : eeeeeeeeeeeeeee
	    ? fffffffffffffff
	    : gggggggggggggggg;

// Prettier 3.1.1
aaaaaaaaaaaaaaa
	? bbbbbbbbbbbbbbbbbb
	: ccccccccccccccc
		? ddddddddddddddd
		: eeeeeeeeeeeeeee
			? fffffffffffffff
			: gggggggggggggggg;
```

##### Improve config file search
([#&#8203;15663](https://togithub.com/prettier/prettier/pull/15663) by
[@&#8203;fisker](https://togithub.com/fisker))

The Prettier config file search performance has been improved by more
effective cache strategy.

##### Fix unstable and ugly formatting for comments in destructuring
patterns
([#&#8203;15708](https://togithub.com/prettier/prettier/pull/15708) by
[@&#8203;sosukesuzuki](https://togithub.com/sosukesuzuki))

<!-- prettier-ignore -->

```tsx
// Input
const {
  foo,
  // bar
  // baz
}: Foo = expr;

// Prettier 3.1.0
const {
  foo1,
} // bar
// baz
: Foo = expr;

// Prettier 3.1.0 second output
const {
  foo1, // bar
} // baz
: Foo = expr;

// Prettier 3.1.1
const {
  foo1,
  // bar
  // baz
}: Foo = expr;
```

##### Support "Import Attributes"
([#&#8203;15718](https://togithub.com/prettier/prettier/pull/15718) by
[@&#8203;fisker](https://togithub.com/fisker))

[TypeScript
5.3](https://devblogs.microsoft.com/typescript/announcing-typescript-5-3/#import-attributes)
supports the latest updates to the [import
attributes](https://togithub.com/tc39/proposal-import-attributes)
proposal.

```tsx
import something from "./something.json" with { type: "json" };
```

##### Fix false claim in docs that cursorOffset is incompatible with
rangeStart/rangeEnd
([#&#8203;15750](https://togithub.com/prettier/prettier/pull/15750) by
[@&#8203;ExplodingCabbage](https://togithub.com/ExplodingCabbage))

The cursorOffset option has in fact been compatible with
rangeStart/rangeEnd for over 5 years, thanks to work by
[@&#8203;ds300](https://togithub.com/ds300). However, Prettier's
documentation (including the CLI `--help` text) continued to claim
otherwise, falsely. The documentation is now fixed.

##### Keep curly braces and `from` keyword in empty `import` statements
([#&#8203;15756](https://togithub.com/prettier/prettier/pull/15756) by
[@&#8203;fisker](https://togithub.com/fisker))

<!-- prettier-ignore -->

```js
// Input
import { } from 'foo';
import { /* comment */ } from 'bar';

// Prettier 3.1.0
import {} from "foo";
import /* comment */ "bar";

// Prettier 3.1.1
import {} from "foo";
import {} from /* comment */ "bar";
```

##### Keep empty import attributes and assertions
([#&#8203;15757](https://togithub.com/prettier/prettier/pull/15757) by
[@&#8203;fisker](https://togithub.com/fisker))

<!-- prettier-ignore -->

```js
// Input
import foo from "foo" with {};
import bar from "bar" assert {};

// Prettier 3.1.0
import foo from "foo";
import bar from "bar";

// Prettier 3.1.1
import foo from "foo" with {};
import bar from "bar" assert {};
```

###
[`v3.1.0`](https://togithub.com/prettier/prettier/blob/HEAD/CHANGELOG.md#310)

[Compare
Source](https://togithub.com/prettier/prettier/compare/3.0.3...3.1.0)

[diff](https://togithub.com/prettier/prettier/compare/3.0.3...3.1.0)

🔗 [Release Notes](https://prettier.io/blog/2023/11/13/3.1.0.html)

###
[`v3.0.3`](https://togithub.com/prettier/prettier/blob/HEAD/CHANGELOG.md#303)

[Compare
Source](https://togithub.com/prettier/prettier/compare/3.0.2...3.0.3)

[diff](https://togithub.com/prettier/prettier/compare/3.0.2...3.0.3)

##### Add `preferUnplugged: true` to `package.json`
([#&#8203;15169](https://togithub.com/prettier/prettier/pull/15169) by
[@&#8203;fisker](https://togithub.com/fisker) and
[@&#8203;so1ve](https://togithub.com/so1ve))

Prettier v3 uses dynamic imports, user [will need to unplug
Prettier](https://togithub.com/yarnpkg/berry/pull/5411#issuecomment-1523502224)
when Yarn's PnP mode is enabled, add [`preferUnplugged:
true`](https://yarnpkg.com/configuration/manifest#preferUnplugged) to
`package.json`, so Yarn will install Prettier as unplug by default.

##### Support shared config that forbids `require()`
([#&#8203;15233](https://togithub.com/prettier/prettier/pull/15233) by
[@&#8203;fisker](https://togithub.com/fisker))

If an external shared config package is used, and the package `exports`
don't have `require` or `default` export.

In Prettier 3.0.2 Prettier fails when attempt to `require()` the
package, and throws an error.

```text
Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" main defined in <packageName>/package.json
```

##### Allow argument of `require()` to break
([#&#8203;15256](https://togithub.com/prettier/prettier/pull/15256) by
[@&#8203;fisker](https://togithub.com/fisker))

<!-- prettier-ignore -->

```jsx
// Input
const plugin = require(
  global.STANDALONE
    ? path.join(__dirname, "../standalone.js")
    : path.join(__dirname, "..")
);

// Prettier 3.0.2
const plugin = require(global.STANDALONE
  ? path.join(__dirname, "../standalone.js")
  : path.join(__dirname, ".."));

// Prettier 3.0.3
const plugin = require(
  global.STANDALONE
    ? path.join(__dirname, "../standalone.js")
    : path.join(__dirname, "..")
);
```

##### Do not print trailing commas in arrow function type parameter
lists in `ts` code blocks
([#&#8203;15286](https://togithub.com/prettier/prettier/pull/15286) by
[@&#8203;sosukesuzuki](https://togithub.com/sosukesuzuki))

<!-- prettier-ignore -->

````md
<!-- Input -->
```ts
const foo = <T>() => {}
```

<!-- Prettier 3.0.2 -->
```ts
const foo = <T,>() => {}
```

<!-- Prettier 3.0.3 -->
```ts
const foo = <T>() => {}
```
````

##### Support TypeScript 5.2 `using` / `await using` declaration
([#&#8203;15321](https://togithub.com/prettier/prettier/pull/15321) by
[@&#8203;sosukesuzuki](https://togithub.com/sosukesuzuki))

Support for the upcoming Explicit Resource Management feature in
ECMAScript. [`using` / `await using`
declaration](https://devblogs.microsoft.com/typescript/announcing-typescript-5-2/#using-declarations-and-explicit-resource-management)

<!-- prettier-ignore -->

```tsx
{
   using foo = new Foo();
   await using bar = new Bar();
}
```

###
[`v3.0.2`](https://togithub.com/prettier/prettier/blob/HEAD/CHANGELOG.md#302)

[Compare
Source](https://togithub.com/prettier/prettier/compare/3.0.1...3.0.2)

[diff](https://togithub.com/prettier/prettier/compare/3.0.1...3.0.2)

##### Break after `=` of assignment if RHS is poorly breakable
AwaitExpression or YieldExpression
([#&#8203;15204](https://togithub.com/prettier/prettier/pull/15204) by
[@&#8203;seiyab](https://togithub.com/seiyab))

<!-- prettier-ignore -->

```js
// Input
const { section, rubric, authors, tags } = await utils.upsertCommonData(mainData);

// Prettier 3.0.1
const { section, rubric, authors, tags } = await utils.upsertCommonData(
  mainData,
);

// Prettier 3.0.2
const { section, rubric, authors, tags } =
  await utils.upsertCommonData(mainData);
```

##### Do not add trailing comma for grouped scss comments
([#&#8203;15217](https://togithub.com/prettier/prettier/pull/15217) by
[@&#8203;auvred](https://togithub.com/auvred))

<!-- prettier-ignore -->

```scss
/* Input */
$foo: (
	'property': (),
	// comment 1
	// comment 2
)

/* Prettier 3.0.1 */
$foo: (
  "property": (),
  // comment 1
  // comment 2,
);

/* Prettier 3.0.2 */
$foo: (
  "property": (),
  // comment 1
  // comment 2
);
```

##### Print `declare` and `export` keywords for nested namespace
([#&#8203;15249](https://togithub.com/prettier/prettier/pull/15249) by
[@&#8203;sosukesuzuki](https://togithub.com/sosukesuzuki))

<!-- prettier-ignore -->

```tsx
// Input
declare namespace abc1.def {}
export namespace abc2.def {}

// Prettier 3.0.1
namespace abc1.def {}
namespace abc2.def {}

// Prettier 3.0.2
declare namespace abc1.def {}
export namespace abc2.def {}
```

###
[`v3.0.1`](https://togithub.com/prettier/prettier/blob/HEAD/CHANGELOG.md#301)

[Compare
Source](https://togithub.com/prettier/prettier/compare/3.0.0...3.0.1)

[diff](https://togithub.com/prettier/prettier/compare/3.0.0...3.0.1)

##### Fix cursor positioning for a special case
([#&#8203;14812](https://togithub.com/prettier/prettier/pull/14812) by
[@&#8203;fisker](https://togithub.com/fisker))

<!-- prettier-ignore -->

```js
// <|> is the cursor position

/* Input */
// All messages are represented in JSON.
// So, the prettier.py controls a subprocess which spawns "node {this_file}".
import {<|>  } from "fs"

/* Prettier 3.0.0 */
// All messages are represented in JSON.
// So, the prettier.py <|>controls a subprocess which spawns "node {this_file}".
import {} from "fs"

/* Prettier 3.0.1 */
// All messages are represented in JSON.
// So, the prettier.py controls a subprocess which spawns "node {this_file}".
import {<|>} from "fs"
```

##### Fix plugins/estree.d.ts to make it a module
([#&#8203;15018](https://togithub.com/prettier/prettier/pull/15018) by
[@&#8203;kingyue737](https://togithub.com/kingyue737))

Add `export {}` in `plugins/estree.d.ts` to fix the "File is not a
module" error

##### Add parenthesis around leading multiline comment in return
statement
([#&#8203;15037](https://togithub.com/prettier/prettier/pull/15037) by
[@&#8203;auvred](https://togithub.com/auvred))

<!-- prettier-ignore -->

```jsx
// Input
function fn() {
  return (
    /**
     * @&#8203;type {...}
     */ expresssion
  )
}

// Prettier 3.0.0
function fn() {
  return /**
   * @&#8203;type {...}
   */ expresssion;
}

// Prettier 3.0.1
function fn() {
  return (
    /**
     * @&#8203;type {...}
     */ expresssion
  );
}
```

##### Add support for Vue "Generic Components"
([#&#8203;15066](https://togithub.com/prettier/prettier/pull/15066) by
[@&#8203;auvred](https://togithub.com/auvred))

https://blog.vuejs.org/posts/vue-3-3#generic-components

<!-- prettier-ignore -->

```vue
<!-- Input -->
<script setup lang="ts" generic="T extends Type1 & Type2 & (Type3 | Type4), U extends string | number | boolean"></script>

<!-- Prettier 3.0.0 -->
<script
  setup
  lang="ts"
  generic="T extends Type1 & Type2 & (Type3 | Type4), U extends string | number | boolean"
></script>

<!-- Prettier 3.0.1 -->
<script
  setup
  lang="ts"
  generic="
    T extends Type1 & Type2 & (Type3 | Type4),
    U extends string | number | boolean
  "
></script>
```

##### Fix comments print in `IfStatement`
([#&#8203;15076](https://togithub.com/prettier/prettier/pull/15076) by
[@&#8203;fisker](https://togithub.com/fisker))

<!-- prettier-ignore -->

```js
function a(b) {
  if (b) return 1; // comment
  else return 2;
}

/* Prettier 3.0.0 */
Error: Comment "comment" was not printed. Please report this error!

/* Prettier 3.0.1 */
function a(b) {
  if (b) return 1; // comment
  else return 2;
}
```

##### Add missing type definition for `printer.preprocess`
([#&#8203;15123](https://togithub.com/prettier/prettier/pull/15123) by
[@&#8203;so1ve](https://togithub.com/so1ve))

```diff
export interface Printer<T = any> {
  // ...
+ preprocess?:
+   | ((ast: T, options: ParserOptions<T>) => T | Promise<T>)
+   | undefined;
}
```

##### Add missing `getVisitorKeys` method type definition for `Printer`
([#&#8203;15125](https://togithub.com/prettier/prettier/pull/15125) by
[@&#8203;auvred](https://togithub.com/auvred))

```tsx
const printer: Printer = {
  print: () => [],
  getVisitorKeys(node, nonTraversableKeys) {
    return ["body"];
  },
};
```

##### Add typing to support `readonly` array properties of AST Node
([#&#8203;15127](https://togithub.com/prettier/prettier/pull/15127) by
[@&#8203;auvred](https://togithub.com/auvred))

<!-- prettier-ignore -->

```tsx
// Input
interface TestNode {
  readonlyArray: readonly string[];
}

declare const path: AstPath<TestNode>;

path.map(() => "", "readonlyArray");

// Prettier 3.0.0
interface TestNode {
  readonlyArray: readonly string[];
}

declare const path: AstPath<TestNode>;

path.map(() => "", "readonlyArray");
//                  ^ Argument of type '"readonlyArray"' is not assignable to parameter of type '"regularArray"'. ts(2345)

// Prettier 3.0.1
interface TestNode {
  readonlyArray: readonly string[];
}

declare const path: AstPath<TestNode>;

path.map(() => "", "readonlyArray");
```

##### Add space before unary minus followed by a function call
([#&#8203;15129](https://togithub.com/prettier/prettier/pull/15129) by
[@&#8203;pamelalozano](https://togithub.com/pamelalozano))

<!-- prettier-ignore -->

```less
// Input
div {
  margin: - func();
}

// Prettier 3.0.0
div {
  margin: -func();
}

// Prettier 3.0.1
div {
  margin: - func();
}
```

###
[`v3.0.0`](https://togithub.com/prettier/prettier/blob/HEAD/CHANGELOG.md#300)

[Compare
Source](https://togithub.com/prettier/prettier/compare/2.8.8...3.0.0)

[diff](https://togithub.com/prettier/prettier/compare/3.0.0-alpha.6...3.0.0)

🔗 [Release Notes](https://prettier.io/blog/2023/07/05/3.0.0.html)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yNjkuMiIsInVwZGF0ZWRJblZlciI6IjM3LjI2OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-04-04 22:33:36 +00:00
Corwin e57df6f03f
Update dependency web-vitals to v3.5.2 (#600)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [web-vitals](https://togithub.com/GoogleChrome/web-vitals) | [`3.3.2`
-> `3.5.2`](https://renovatebot.com/diffs/npm/web-vitals/3.3.2/3.5.2) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/web-vitals/3.5.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/web-vitals/3.5.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/web-vitals/3.3.2/3.5.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/web-vitals/3.3.2/3.5.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>GoogleChrome/web-vitals (web-vitals)</summary>

###
[`v3.5.2`](https://togithub.com/GoogleChrome/web-vitals/blob/HEAD/CHANGELOG.md#v352-2024-01-25)

[Compare
Source](https://togithub.com/GoogleChrome/web-vitals/compare/v3.5.1...v3.5.2)

- Pick the first non-null `target` for INP attribution
([#&#8203;421](https://togithub.com/GoogleChrome/web-vitals/pull/421))

###
[`v3.5.1`](https://togithub.com/GoogleChrome/web-vitals/blob/HEAD/CHANGELOG.md#v351-2023-12-27)

[Compare
Source](https://togithub.com/GoogleChrome/web-vitals/compare/v3.5.0...v3.5.1)

- Add extra guard for `PerformanceEventTiming` not existing
([#&#8203;403](https://togithub.com/GoogleChrome/web-vitals/pull/403))

###
[`v3.5.0`](https://togithub.com/GoogleChrome/web-vitals/blob/HEAD/CHANGELOG.md#v350-2023-09-28)

[Compare
Source](https://togithub.com/GoogleChrome/web-vitals/compare/v3.4.0...v3.5.0)

- Run `onLCP` callback in separate task
([#&#8203;386](https://togithub.com/GoogleChrome/web-vitals/pull/386))
- Fix INP durationThreshold bug when set to 0
([#&#8203;372](https://togithub.com/GoogleChrome/web-vitals/pull/372))
- Prevent FID entries being emitted as INP for non-supporting browsers
([#&#8203;368](https://togithub.com/GoogleChrome/web-vitals/pull/368))

###
[`v3.4.0`](https://togithub.com/GoogleChrome/web-vitals/blob/HEAD/CHANGELOG.md#v340-2023-07-11)

[Compare
Source](https://togithub.com/GoogleChrome/web-vitals/compare/v3.3.2...v3.4.0)

- Make `bindReporter` generic over metric type
([#&#8203;359](https://togithub.com/GoogleChrome/web-vitals/pull/359))
- Update INP status in README
([#&#8203;362](https://togithub.com/GoogleChrome/web-vitals/pull/362))
- Fix Metric types for better TypeScript support
([#&#8203;356](https://togithub.com/GoogleChrome/web-vitals/pull/356))
- Fix selector for SVGs for attribution build
([#&#8203;354](https://togithub.com/GoogleChrome/web-vitals/pull/354))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yNjkuMiIsInVwZGF0ZWRJblZlciI6IjM3LjI2OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-04-04 22:32:17 +00:00
Corwin 658b4c387b
Update dependency styled-components to v6.1.8 (#599)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [styled-components](https://styled-components.com)
([source](https://togithub.com/styled-components/styled-components)) |
[`6.0.2` ->
`6.1.8`](https://renovatebot.com/diffs/npm/styled-components/6.0.2/6.1.8)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/styled-components/6.1.8?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/styled-components/6.1.8?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/styled-components/6.0.2/6.1.8?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/styled-components/6.0.2/6.1.8?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>styled-components/styled-components
(styled-components)</summary>

###
[`v6.1.8`](https://togithub.com/styled-components/styled-components/releases/tag/v6.1.8)

[Compare
Source](https://togithub.com/styled-components/styled-components/compare/v6.1.7...v6.1.8)

Revert adding `peerDependencies` from v6.1.7; apparently some build
tools do not respect `peerDependenciesMeta[package].optional` which is
[causing
issues](https://togithub.com/styled-components/styled-components/pull/4243#issuecomment-1881571372).
Will revisit at a later date if possible.

**Full Changelog**:
https://github.com/styled-components/styled-components/compare/v6.1.7...v6.1.8

###
[`v6.1.7`](https://togithub.com/styled-components/styled-components/releases/tag/v6.1.7)

[Compare
Source](https://togithub.com/styled-components/styled-components/compare/v6.1.6...v6.1.7)

##### What's Changed

- chore: add all missing peer dependency statements by
[@&#8203;quantizor](https://togithub.com/quantizor) in
[https://github.com/styled-components/styled-components/pull/4243](https://togithub.com/styled-components/styled-components/pull/4243)

NOTE: this change may cause some installed dependency duplication until
[this NPM bug](https://togithub.com/npm/cli/issues/7106) is addressed
but yarn and pnpm have correct behavior. Bun also has [a similar
bug](https://togithub.com/oven-sh/bun/issues/7869).

Overall these changes ensure that styled-components is specifying a
known working version of all utilized libraries, while instructing the
client package manager that higher semver-compliant versions are
*permissible and should work*, assuming the relevant libraries are
compliant in practice.

**Full Changelog**:
https://github.com/styled-components/styled-components/compare/v6.1.6...v6.1.7

###
[`v6.1.6`](https://togithub.com/styled-components/styled-components/releases/tag/v6.1.6)

[Compare
Source](https://togithub.com/styled-components/styled-components/compare/v6.1.5...v6.1.6)

##### What's Changed

- fix: bump stylis to 4.3.1 to resolve issue with leaking nested
selectors by [@&#8203;quantizor](https://togithub.com/quantizor) in
[https://github.com/styled-components/styled-components/pull/4245](https://togithub.com/styled-components/styled-components/pull/4245)

**Full Changelog**:
https://github.com/styled-components/styled-components/compare/v6.1.5...v6.1.6

###
[`v6.1.5`](https://togithub.com/styled-components/styled-components/releases/tag/v6.1.5)

[Compare
Source](https://togithub.com/styled-components/styled-components/compare/v6.1.4...v6.1.5)

##### What's Changed

- fix: further constrain self-referencing to match v5 behavior by
[@&#8203;quantizor](https://togithub.com/quantizor) in
[https://github.com/styled-components/styled-components/pull/4244](https://togithub.com/styled-components/styled-components/pull/4244)

**Full Changelog**:
https://github.com/styled-components/styled-components/compare/v6.1.4...v6.1.5

###
[`v6.1.4`](https://togithub.com/styled-components/styled-components/releases/tag/v6.1.4)

[Compare
Source](https://togithub.com/styled-components/styled-components/compare/v6.1.3...v6.1.4)

#### What's Changed

- fix: allow using `attrs` to provide a custom `theme` prop to child
components by [@&#8203;quantizor](https://togithub.com/quantizor) in
[https://github.com/styled-components/styled-components/pull/4242](https://togithub.com/styled-components/styled-components/pull/4242)

**Full Changelog**:
https://github.com/styled-components/styled-components/compare/v6.1.3...v6.1.4

###
[`v6.1.3`](https://togithub.com/styled-components/styled-components/releases/tag/v6.1.3)

[Compare
Source](https://togithub.com/styled-components/styled-components/compare/v6.1.2...v6.1.3)

#### What's Changed

- fix(types): missing type declarations by
[@&#8203;benjaminrae](https://togithub.com/benjaminrae) in
[https://github.com/styled-components/styled-components/pull/4237](https://togithub.com/styled-components/styled-components/pull/4237)
- fix(deps): pin dependencies to exact versions prior to bun migration
by [@&#8203;quantizor](https://togithub.com/quantizor) in
[https://github.com/styled-components/styled-components/pull/4238](https://togithub.com/styled-components/styled-components/pull/4238)
- fix(types): nested styled with additional prop types by
[@&#8203;justinbhopper](https://togithub.com/justinbhopper) in
[https://github.com/styled-components/styled-components/pull/4236](https://togithub.com/styled-components/styled-components/pull/4236)

#### New Contributors

- [@&#8203;benjaminrae](https://togithub.com/benjaminrae) made their
first contribution in
[https://github.com/styled-components/styled-components/pull/4237](https://togithub.com/styled-components/styled-components/pull/4237)

**Full Changelog**:
https://github.com/styled-components/styled-components/compare/v6.1.2...v6.1.3

###
[`v6.1.2`](https://togithub.com/styled-components/styled-components/releases/tag/v6.1.2)

[Compare
Source](https://togithub.com/styled-components/styled-components/compare/v6.1.1...v6.1.2)

#### What's Changed

- fix(types): StyledObject type to allow nested selectors by
[@&#8203;maximebiloe](https://togithub.com/maximebiloe) in
[https://github.com/styled-components/styled-components/pull/4212](https://togithub.com/styled-components/styled-components/pull/4212)
- feat(types): expose FastOmit to improve emit performance by
[@&#8203;justinbhopper](https://togithub.com/justinbhopper) in
[https://github.com/styled-components/styled-components/pull/4230](https://togithub.com/styled-components/styled-components/pull/4230)

#### New Contributors

- [@&#8203;maximebiloe](https://togithub.com/maximebiloe) made their
first contribution in
[https://github.com/styled-components/styled-components/pull/4212](https://togithub.com/styled-components/styled-components/pull/4212)

**Full Changelog**:
https://github.com/styled-components/styled-components/compare/v6.1.1...v6.1.2

###
[`v6.1.1`](https://togithub.com/styled-components/styled-components/releases/tag/v6.1.1)

[Compare
Source](https://togithub.com/styled-components/styled-components/compare/v6.1.0...v6.1.1)

#### What's Changed

- fix(types): remove duplicated type by
[@&#8203;takurinton](https://togithub.com/takurinton) in
[https://github.com/styled-components/styled-components/pull/4200](https://togithub.com/styled-components/styled-components/pull/4200)
- fix(native): image unsupported border color style by
[@&#8203;nazmeln](https://togithub.com/nazmeln) in
[https://github.com/styled-components/styled-components/pull/4195](https://togithub.com/styled-components/styled-components/pull/4195)
- fix(styled): add displayName in all environments by
[@&#8203;delijah](https://togithub.com/delijah) in
[https://github.com/styled-components/styled-components/pull/4208](https://togithub.com/styled-components/styled-components/pull/4208)
- fix(ssr): correctly place new rules after hydrated rules by
[@&#8203;probablyup](https://togithub.com/probablyup) in
[https://github.com/styled-components/styled-components/pull/4210](https://togithub.com/styled-components/styled-components/pull/4210)

#### New Contributors

- [@&#8203;nazmeln](https://togithub.com/nazmeln) made their first
contribution in
[https://github.com/styled-components/styled-components/pull/4195](https://togithub.com/styled-components/styled-components/pull/4195)
- [@&#8203;delijah](https://togithub.com/delijah) made their first
contribution in
[https://github.com/styled-components/styled-components/pull/4208](https://togithub.com/styled-components/styled-components/pull/4208)

**Full Changelog**:
https://github.com/styled-components/styled-components/compare/v6.1.0...v6.1.1

###
[`v6.1.0`](https://togithub.com/styled-components/styled-components/releases/tag/v6.1.0)

[Compare
Source](https://togithub.com/styled-components/styled-components/compare/v6.0.9...v6.1.0)

#### What's Changed

- fix(native): bump postcss version from 8.4.23 to 8.4.31 by
[@&#8203;davidlacasse](https://togithub.com/davidlacasse) in
[https://github.com/styled-components/styled-components/pull/4188](https://togithub.com/styled-components/styled-components/pull/4188)
- fix(native): solve ts warning by
[@&#8203;krudos](https://togithub.com/krudos) in
[https://github.com/styled-components/styled-components/pull/4190](https://togithub.com/styled-components/styled-components/pull/4190)
- chore: remove babel macro due to lack of usage by
[@&#8203;probablyup](https://togithub.com/probablyup) in
[https://github.com/styled-components/styled-components/pull/4193](https://togithub.com/styled-components/styled-components/pull/4193)

#### New Contributors

- [@&#8203;davidlacasse](https://togithub.com/davidlacasse) made their
first contribution in
[https://github.com/styled-components/styled-components/pull/4188](https://togithub.com/styled-components/styled-components/pull/4188)

**Full Changelog**:
https://github.com/styled-components/styled-components/compare/v6.0.9...v6.1.0

###
[`v6.0.9`](https://togithub.com/styled-components/styled-components/releases/tag/v6.0.9)

[Compare
Source](https://togithub.com/styled-components/styled-components/compare/v6.0.8...v6.0.9)

fix bundling to not hardcode `window` (should fix some testing use cases
that were incorrectly assuming a server environment when JSDOM and
similar are in use)

**Full Changelog**:
https://github.com/styled-components/styled-components/compare/v6.0.8...v6.0.9

###
[`v6.0.8`](https://togithub.com/styled-components/styled-components/releases/tag/v6.0.8)

[Compare
Source](https://togithub.com/styled-components/styled-components/compare/v6.0.7...v6.0.8)

#### What's Changed

- feat(native): add `toStyleSheet` function by
[@&#8203;krudos](https://togithub.com/krudos) in
[https://github.com/styled-components/styled-components/pull/4124](https://togithub.com/styled-components/styled-components/pull/4124)
- fix: prevent `StyleSheetManager` updating context on every render by
[@&#8203;keeganstreet](https://togithub.com/keeganstreet) in
[https://github.com/styled-components/styled-components/pull/4159](https://togithub.com/styled-components/styled-components/pull/4159)
- fix(types): ensure typing for static properties defined on third-party
components wrapped by styled-components by
[@&#8203;MartinPELCAT](https://togithub.com/MartinPELCAT) in
[https://github.com/styled-components/styled-components/pull/4141](https://togithub.com/styled-components/styled-components/pull/4141)
- fix: production mode inconsistent CSS rendering when dynamic property
values are the same but property names are different by
[@&#8203;bcole808](https://togithub.com/bcole808) in
[https://github.com/styled-components/styled-components/pull/4132](https://togithub.com/styled-components/styled-components/pull/4132)
- fix(types): decrease type complexity by moving off of
`JSX.IntrinsicElements` for the supported element list by
[@&#8203;RJWadley](https://togithub.com/RJWadley) in
[https://github.com/styled-components/styled-components/pull/4149](https://togithub.com/styled-components/styled-components/pull/4149)
- fix(types): adopt ref typing from forwardedAs by
[@&#8203;probablyup](https://togithub.com/probablyup) in
[https://github.com/styled-components/styled-components/pull/4163](https://togithub.com/styled-components/styled-components/pull/4163)
- chore: update typescript reference on issue template by
[@&#8203;chilled-capybara](https://togithub.com/chilled-capybara) in
[https://github.com/styled-components/styled-components/pull/4150](https://togithub.com/styled-components/styled-components/pull/4150)
- chore(types): add type exports for `StyleFunction`, `Interpolation` by
[@&#8203;bcole808](https://togithub.com/bcole808) in
[https://github.com/styled-components/styled-components/pull/4140](https://togithub.com/styled-components/styled-components/pull/4140)
- chore: updated Contributing guide benchmark instructions by
[@&#8203;bcole808](https://togithub.com/bcole808) in
[https://github.com/styled-components/styled-components/pull/4137](https://togithub.com/styled-components/styled-components/pull/4137)
- chore(types): add missing types `CSSProperties`, `CSSObject`,
`CSSPseudos` and `CSSKeyframes` by
[@&#8203;takurinton](https://togithub.com/takurinton) in
[https://github.com/styled-components/styled-components/pull/4117](https://togithub.com/styled-components/styled-components/pull/4117)

#### New Contributors

- [@&#8203;takurinton](https://togithub.com/takurinton) made their first
contribution in
[https://github.com/styled-components/styled-components/pull/4117](https://togithub.com/styled-components/styled-components/pull/4117)
- [@&#8203;krudos](https://togithub.com/krudos) made their first
contribution in
[https://github.com/styled-components/styled-components/pull/4124](https://togithub.com/styled-components/styled-components/pull/4124)
- [@&#8203;chilled-capybara](https://togithub.com/chilled-capybara) made
their first contribution in
[https://github.com/styled-components/styled-components/pull/4150](https://togithub.com/styled-components/styled-components/pull/4150)
- [@&#8203;MartinPELCAT](https://togithub.com/MartinPELCAT) made their
first contribution in
[https://github.com/styled-components/styled-components/pull/4141](https://togithub.com/styled-components/styled-components/pull/4141)
- [@&#8203;RJWadley](https://togithub.com/RJWadley) made their first
contribution in
[https://github.com/styled-components/styled-components/pull/4149](https://togithub.com/styled-components/styled-components/pull/4149)

**Full Changelog**:
https://github.com/styled-components/styled-components/compare/v6.0.7...v6.0.8

###
[`v6.0.7`](https://togithub.com/styled-components/styled-components/releases/tag/v6.0.7)

[Compare
Source](https://togithub.com/styled-components/styled-components/compare/v6.0.6...v6.0.7)

#### What's Changed

- refactor(types): enable `exactOptionalPropertyTypes` check by
[@&#8203;aspirisen](https://togithub.com/aspirisen) in
[https://github.com/styled-components/styled-components/pull/3993](https://togithub.com/styled-components/styled-components/pull/3993)
- fix(types): allow number for height/width/etc
([#&#8203;4090](https://togithub.com/styled-components/styled-components/issues/4090))
by [@&#8203;drewbrend](https://togithub.com/drewbrend) in
[https://github.com/styled-components/styled-components/pull/4111](https://togithub.com/styled-components/styled-components/pull/4111)

#### New Contributors

- [@&#8203;aspirisen](https://togithub.com/aspirisen) made their first
contribution in
[https://github.com/styled-components/styled-components/pull/3993](https://togithub.com/styled-components/styled-components/pull/3993)
- [@&#8203;drewbrend](https://togithub.com/drewbrend) made their first
contribution in
[https://github.com/styled-components/styled-components/pull/4111](https://togithub.com/styled-components/styled-components/pull/4111)

**Full Changelog**:
https://github.com/styled-components/styled-components/compare/v6.0.6...v6.0.7

###
[`v6.0.6`](https://togithub.com/styled-components/styled-components/releases/tag/v6.0.6)

[Compare
Source](https://togithub.com/styled-components/styled-components/compare/v6.0.5...v6.0.6)

#### What's Changed

- fix(types): issues with StyleFunctions and StyledObjects by
[@&#8203;bcole808](https://togithub.com/bcole808) in
[https://github.com/styled-components/styled-components/pull/4107](https://togithub.com/styled-components/styled-components/pull/4107)

#### New Contributors

- [@&#8203;bcole808](https://togithub.com/bcole808) made their first
contribution in
[https://github.com/styled-components/styled-components/pull/4107](https://togithub.com/styled-components/styled-components/pull/4107)

**Full Changelog**:
https://github.com/styled-components/styled-components/compare/v6.0.5...v6.0.6

###
[`v6.0.5`](https://togithub.com/styled-components/styled-components/releases/tag/v6.0.5)

[Compare
Source](https://togithub.com/styled-components/styled-components/compare/v6.0.4...v6.0.5)

#### What's Changed

- Fix createGlobalStyle not removing styles on unmount by
[@&#8203;mdeschamps](https://togithub.com/mdeschamps) in
[https://github.com/styled-components/styled-components/pull/4101](https://togithub.com/styled-components/styled-components/pull/4101)

#### New Contributors

- [@&#8203;mdeschamps](https://togithub.com/mdeschamps) made their first
contribution in
[https://github.com/styled-components/styled-components/pull/4101](https://togithub.com/styled-components/styled-components/pull/4101)

**Full Changelog**:
https://github.com/styled-components/styled-components/compare/v6.0.4...v6.0.5

###
[`v6.0.4`](https://togithub.com/styled-components/styled-components/releases/tag/v6.0.4)

[Compare
Source](https://togithub.com/styled-components/styled-components/compare/v6.0.3...v6.0.4)

#### What's Changed

- refactor: dev warning on unknown props retargeted specifically toward
HTML targets rather than other React components by
[@&#8203;woodreamz](https://togithub.com/woodreamz) in
[https://github.com/styled-components/styled-components/pull/4084](https://togithub.com/styled-components/styled-components/pull/4084)
- fix: untyped event handler callbacks by
[@&#8203;ziolekjj](https://togithub.com/ziolekjj) in
[https://github.com/styled-components/styled-components/pull/4086](https://togithub.com/styled-components/styled-components/pull/4086)

#### New Contributors

- [@&#8203;woodreamz](https://togithub.com/woodreamz) made their first
contribution in
[https://github.com/styled-components/styled-components/pull/4084](https://togithub.com/styled-components/styled-components/pull/4084)
- [@&#8203;ziolekjj](https://togithub.com/ziolekjj) made their first
contribution in
[https://github.com/styled-components/styled-components/pull/4086](https://togithub.com/styled-components/styled-components/pull/4086)

**Full Changelog**:
https://github.com/styled-components/styled-components/compare/v6.0.3...v6.0.4

###
[`v6.0.3`](https://togithub.com/styled-components/styled-components/releases/tag/v6.0.3)

[Compare
Source](https://togithub.com/styled-components/styled-components/compare/v6.0.2...v6.0.3)

#### What's Changed

- fix: StyleSheetManager missing Stylis types by
[@&#8203;MattIPv4](https://togithub.com/MattIPv4) in
[https://github.com/styled-components/styled-components/pull/4078](https://togithub.com/styled-components/styled-components/pull/4078)

#### New Contributors

- [@&#8203;MattIPv4](https://togithub.com/MattIPv4) made their first
contribution in
[https://github.com/styled-components/styled-components/pull/4078](https://togithub.com/styled-components/styled-components/pull/4078)

**Full Changelog**:
https://github.com/styled-components/styled-components/compare/v6.0.2...v6.0.3

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yNjkuMiIsInVwZGF0ZWRJblZlciI6IjM3LjI2OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-04-04 22:31:40 +00:00
Corwin 702036d5ae
Update dependency @types/node to v20.12.4 (#598)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@types/node](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node)
([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node))
| [`20.3.3` ->
`20.12.4`](https://renovatebot.com/diffs/npm/@types%2fnode/20.3.3/20.12.4)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/20.12.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/20.12.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/20.3.3/20.12.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/20.3.3/20.12.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yNjkuMiIsInVwZGF0ZWRJblZlciI6IjM3LjI2OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-04-04 22:31:30 +00:00
Corwin 653e52d3bf
Only deploy on push (#603) 2024-04-04 23:40:28 +01:00
Corwin 205b811e13
only deploy on push 2024-04-04 23:39:05 +01:00
Corwin 14e7eaedf7
Update dependency @testing-library/react to v14.2.2 (#596)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@testing-library/react](https://togithub.com/testing-library/react-testing-library)
| [`14.0.0` ->
`14.2.2`](https://renovatebot.com/diffs/npm/@testing-library%2freact/14.0.0/14.2.2)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@testing-library%2freact/14.2.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@testing-library%2freact/14.2.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@testing-library%2freact/14.0.0/14.2.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@testing-library%2freact/14.0.0/14.2.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>testing-library/react-testing-library
(@&#8203;testing-library/react)</summary>

###
[`v14.2.2`](https://togithub.com/testing-library/react-testing-library/compare/v14.2.1...3da62fd9741ca74bcd0d2bc668ba76a2d8f3751f)

[Compare
Source](https://togithub.com/testing-library/react-testing-library/compare/v14.2.1...v14.2.2)

###
[`v14.2.1`](https://togithub.com/testing-library/react-testing-library/releases/tag/v14.2.1)

[Compare
Source](https://togithub.com/testing-library/react-testing-library/compare/v14.2.0...v14.2.1)

##### Bug Fixes

- Update types to support all possible react component return values
([#&#8203;1272](https://togithub.com/testing-library/react-testing-library/issues/1272))
([55e79c2](55e79c290d))

###
[`v14.2.0`](https://togithub.com/testing-library/react-testing-library/releases/tag/v14.2.0)

[Compare
Source](https://togithub.com/testing-library/react-testing-library/compare/v14.1.2...v14.2.0)

##### Features

- add `reactStrictMode` option to enable strict mode render
([#&#8203;1241](https://togithub.com/testing-library/react-testing-library/issues/1241))
([0880eba](0880eba4a0))

###
[`v14.1.2`](https://togithub.com/testing-library/react-testing-library/releases/tag/v14.1.2)

[Compare
Source](https://togithub.com/testing-library/react-testing-library/compare/v14.1.1...v14.1.2)

##### Bug Fixes

- revert missing hooks warnings
([#&#8203;1255](https://togithub.com/testing-library/react-testing-library/issues/1255))
([1c67477](1c67477443))

###
[`v14.1.1`](https://togithub.com/testing-library/react-testing-library/releases/tag/v14.1.1)

[Compare
Source](https://togithub.com/testing-library/react-testing-library/compare/v14.1.0...v14.1.1)

##### Bug Fixes

- log globals warning only once
([#&#8203;1252](https://togithub.com/testing-library/react-testing-library/issues/1252))
([fd52a59](fd52a593a7)),
closes
[#&#8203;1249](https://togithub.com/testing-library/react-testing-library/issues/1249)

###
[`v14.1.0`](https://togithub.com/testing-library/react-testing-library/releases/tag/v14.1.0)

[Compare
Source](https://togithub.com/testing-library/react-testing-library/compare/v14.0.0...v14.1.0)

##### Features

- add warnings when globals are missing
([#&#8203;1244](https://togithub.com/testing-library/react-testing-library/issues/1244))
([d80319f](d80319f569))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yNjkuMiIsInVwZGF0ZWRJblZlciI6IjM3LjI2OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-04-04 22:30:47 +00:00
Corwin 3964c75c24
Update dependency @testing-library/jest-dom to v5.17.0 (#595)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@testing-library/jest-dom](https://togithub.com/testing-library/jest-dom)
| [`5.16.5` ->
`5.17.0`](https://renovatebot.com/diffs/npm/@testing-library%2fjest-dom/5.16.5/5.17.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@testing-library%2fjest-dom/5.17.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@testing-library%2fjest-dom/5.17.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@testing-library%2fjest-dom/5.16.5/5.17.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@testing-library%2fjest-dom/5.16.5/5.17.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>testing-library/jest-dom
(@&#8203;testing-library/jest-dom)</summary>

###
[`v5.17.0`](https://togithub.com/testing-library/jest-dom/releases/tag/v5.17.0)

[Compare
Source](https://togithub.com/testing-library/jest-dom/compare/v5.16.5...v5.17.0)

##### Features

- New `toHaveAccessibleErrorMessage` better implementing the spec,
deprecate `toHaveErrorMessage`
([#&#8203;503](https://togithub.com/testing-library/jest-dom/issues/503))
([d717c66](d717c66cb4))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yNjkuMiIsInVwZGF0ZWRJblZlciI6IjM3LjI2OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-04-04 22:30:25 +00:00
Corwin 0d8ac19871
Update dependency @testing-library/user-event to v14.5.2 (#597)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@testing-library/user-event](https://togithub.com/testing-library/user-event)
| [`14.4.3` ->
`14.5.2`](https://renovatebot.com/diffs/npm/@testing-library%2fuser-event/14.4.3/14.5.2)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@testing-library%2fuser-event/14.5.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@testing-library%2fuser-event/14.5.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@testing-library%2fuser-event/14.4.3/14.5.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@testing-library%2fuser-event/14.4.3/14.5.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>testing-library/user-event
(@&#8203;testing-library/user-event)</summary>

###
[`v14.5.2`](https://togithub.com/testing-library/user-event/releases/tag/v14.5.2)

[Compare
Source](https://togithub.com/testing-library/user-event/compare/v14.5.1...v14.5.2)

##### Bug Fixes

- remove interop and deep DTL imports
([6a3c896](6a3c896bd2))

###
[`v14.5.1`](https://togithub.com/testing-library/user-event/releases/tag/v14.5.1)

[Compare
Source](https://togithub.com/testing-library/user-event/compare/v14.5.0...v14.5.1)

##### Bug Fixes

- incorrect default import from
[@&#8203;testing-library/dom](https://togithub.com/testing-library/dom)
([#&#8203;1162](https://togithub.com/testing-library/user-event/issues/1162))
([d7483f0](d7483f049a))

###
[`v14.5.0`](https://togithub.com/testing-library/user-event/releases/tag/v14.5.0)

[Compare
Source](https://togithub.com/testing-library/user-event/compare/v14.4.3...v14.5.0)

##### Bug Fixes

- **exports:** add a named export for userEvent
([4019cee](4019ceeaba)),
closes
[#&#8203;1146](https://togithub.com/testing-library/user-event/issues/1146)

##### Features

- **types:** Add additional type exports for UserEvent & Options
([#&#8203;1112](https://togithub.com/testing-library/user-event/issues/1112))
([da00e8d](da00e8d610))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yNjkuMiIsInVwZGF0ZWRJblZlciI6IjM3LjI2OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-04-04 22:30:25 +00:00
Corwin 503655a78b
Update dependency @types/jest to v29.5.12 (#592)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@types/jest](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/jest)
([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest))
| [`29.5.2` ->
`29.5.12`](https://renovatebot.com/diffs/npm/@types%2fjest/29.5.2/29.5.12)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fjest/29.5.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fjest/29.5.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fjest/29.5.2/29.5.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fjest/29.5.2/29.5.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yNjkuMiIsInVwZGF0ZWRJblZlciI6IjM3LjI2OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-04-04 22:29:44 +00:00
Corwin 3014fa10e1
Update react monorepo (#594)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@types/react](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react)
([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react))
| [`18.2.14` ->
`18.2.74`](https://renovatebot.com/diffs/npm/@types%2freact/18.2.14/18.2.74)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2freact/18.2.74?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2freact/18.2.74?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2freact/18.2.14/18.2.74?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2freact/18.2.14/18.2.74?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@types/react-dom](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react-dom)
([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom))
| [`18.2.6` ->
`18.2.24`](https://renovatebot.com/diffs/npm/@types%2freact-dom/18.2.6/18.2.24)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2freact-dom/18.2.24?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2freact-dom/18.2.24?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2freact-dom/18.2.6/18.2.24?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2freact-dom/18.2.6/18.2.24?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config help](https://togithub.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yNjkuMiIsInVwZGF0ZWRJblZlciI6IjM3LjI2OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-04-04 22:29:36 +00:00
renovate[bot] 78e153840f
Update dependency prettier to v3 2024-04-04 22:27:30 +00:00
renovate[bot] 06632a2885
Update dependency web-vitals to v3.5.2 2024-04-04 22:26:52 +00:00
renovate[bot] d4eb3a09e0
Update dependency styled-components to v6.1.8 2024-04-04 22:26:29 +00:00
renovate[bot] b5d028fdce
Update dependency @types/node to v20.12.4 2024-04-04 22:26:16 +00:00
renovate[bot] 9e54fdbe42
Update dependency @testing-library/user-event to v14.5.2 2024-04-04 22:25:19 +00:00
renovate[bot] 27a6bd98f6
Update dependency @testing-library/react to v14.2.2 2024-04-04 22:25:05 +00:00
renovate[bot] 68bb3ee463
Update dependency @testing-library/jest-dom to v5.17.0 2024-04-04 22:24:52 +00:00
renovate[bot] 3930c2f168
Update react monorepo 2024-04-04 22:24:39 +00:00
renovate[bot] 5d7712aee9
Update dependency @types/jest to v29.5.12 2024-04-04 22:24:25 +00:00
Corwin 13645f075d
Update dependency @types/styled-components to v5.1.34 (#593)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@types/styled-components](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/styled-components)
([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/styled-components))
| [`5.1.26` ->
`5.1.34`](https://renovatebot.com/diffs/npm/@types%2fstyled-components/5.1.26/5.1.34)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fstyled-components/5.1.34?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fstyled-components/5.1.34?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fstyled-components/5.1.26/5.1.34?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fstyled-components/5.1.26/5.1.34?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yNjkuMiIsInVwZGF0ZWRJblZlciI6IjM3LjI2OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-04-04 23:15:39 +01:00
GBA bot 4a0aa0e9d7 Update lockfiles 2024-04-04 20:58:42 +00:00
renovate[bot] 990fe578c9
Update dependency @types/styled-components to v5.1.34 2024-04-04 20:58:09 +00:00
Corwin 17b3bd08f9
Start of website with mgba (#413)
Make a new website
2024-04-04 21:57:01 +01:00
Corwin 2760a8451f
I'm 92% sure this is intentional 2024-04-04 19:59:19 +01:00
Corwin 36f204958e
remove unused import 2024-04-04 19:51:49 +01:00
Corwin 942418298e
install packages 2024-04-04 19:45:26 +01:00
Corwin 63f0335a64
update podman? 2024-04-04 19:34:28 +01:00
Corwin 22483fd49e
use proper names 2024-04-04 18:09:10 +01:00
Corwin 9bd59a1eca
build site on PR too 2024-04-04 18:08:26 +01:00
Corwin 9686ac5be0
stop building and deploying book 2024-04-04 17:58:13 +01:00
Corwin 713fc168ae
load game based on path hash 2024-04-04 17:57:06 +01:00
Corwin 3574253df8
pointless margins 2024-04-04 17:47:53 +01:00
Corwin b2b93be33d
clean up the edges 2024-04-04 17:46:11 +01:00
Corwin 374b45be48
make crash the index 2024-04-04 01:31:26 +01:00
Corwin 36a749160c
add website build action 2024-04-04 01:24:26 +01:00
Corwin 366b135b0f
Revert "update homepage"
This reverts commit 903f793874.
2024-04-04 01:09:58 +01:00
Corwin 903f793874
update homepage 2024-04-04 01:08:49 +01:00
Corwin 98ce760d77
remove unused import 2024-04-04 01:07:29 +01:00
Corwin 8cb306a9b7
add book 2024-04-04 01:07:10 +01:00
Corwin 662cdc73d6
ignore game 2024-04-04 00:57:10 +01:00
Corwin 190f5c7600
remove game 2024-04-04 00:57:05 +01:00
Corwin f8d4620ed5
update site 2024-04-04 00:54:23 +01:00
Corwin e1453cb4c8
build mgba wasm 2024-04-04 00:54:23 +01:00
Corwin a7de8c07d2
move mgba app to own directory 2024-04-04 00:54:23 +01:00
Corwin dc2d969930
auto overflow 2024-04-04 00:54:23 +01:00
Corwin fb5414a036
itch specific changes 2024-04-04 00:54:23 +01:00
Corwin 064a919bd6
handle overflow of dialog 2024-04-04 00:54:23 +01:00
Corwin 7665135329
refer to local paths 2024-04-04 00:54:23 +01:00
Corwin cb68d8c695
add depdendency array 2024-04-04 00:54:23 +01:00
Gwilym Inzani f354cff108
Add a mute button 2024-04-04 00:54:23 +01:00
Gwilym Inzani 489e95de9f
replace slider with a better behaved one 2024-04-04 00:54:23 +01:00
Gwilym Inzani 3323d6a4e7
Force interaction to start 2024-04-04 00:54:23 +01:00
Gwilym Inzani f944f35b61
Add itch.io scrolling protection 2024-04-04 00:54:23 +01:00
Gwilym Inzani 91dfb63fbd
Properly fullscreen 2024-04-04 00:54:23 +01:00
Gwilym Inzani 683afbf133
Make useLocalStorage actually work 2024-04-04 00:54:23 +01:00
Gwilym Inzani 472d641cfc
Remove another console log 2024-04-04 00:54:23 +01:00
Gwilym Inzani bb47bc21a5
Remove console log 2024-04-04 00:54:23 +01:00
Gwilym Inzani 7decbccbcd
Localstorage 2024-04-04 00:54:23 +01:00
Gwilym Inzani bf722ecdfa
Nicer key rebinding 2024-04-04 00:54:23 +01:00
Gwilym Inzani ce75b15716
Sort out some of the canvas CSS 2024-04-04 00:54:23 +01:00
Gwilym Inzani baab2582b5
Play the game by default 2024-04-04 00:54:23 +01:00
Gwilym Inzani 361060da6a
Use the actual defaults 2024-04-04 00:54:23 +01:00
Gwilym Inzani 203dc0cff7
Upgrade everything 2024-04-04 00:54:23 +01:00
Gwilym Inzani a1c1671b0b
Only set settings when the game loads 2024-04-04 00:54:23 +01:00
Gwilym Inzani 845a4b9244
Pause the game while you're choosing key bindings 2024-04-04 00:54:23 +01:00
Gwilym Inzani 2106c4cefd
Key just works on weird keyboard layouts 2024-04-04 00:54:22 +01:00
Corwin b97280edd4
experiment with bindings 2024-04-04 00:54:22 +01:00
Corwin 4a630fe85b
prettier'd 2024-04-04 00:54:22 +01:00
Corwin f2e5bf432b
reload doens't take a value 2024-04-04 00:54:22 +01:00
Corwin 7098e6937b
a start of a wrapper around mgba 2024-04-04 00:54:22 +01:00
Corwin ef1af49a5a
delete node env 2024-04-04 00:54:22 +01:00
Corwin 40fec52702
add vendored mgba 2024-04-04 00:54:22 +01:00
Corwin c610465ace
delete junk 2024-04-04 00:54:22 +01:00
Corwin 96f02f4917
react new app 2024-04-04 00:54:22 +01:00
Gwilym Inzani 87676b534d Fix build error 2024-04-03 14:32:30 +01:00
Gwilym Inzani b3e18d130f Use a different footer to announce the file type 2024-04-03 14:19:28 +01:00
Gwilym Inzani 5366fc252b Don't need special release stuff here to make local testing faster 2024-04-03 14:19:09 +01:00
Gwilym Inzani e9455d6031 Fix justfile to produce a file in the correct place 2024-04-03 14:18:54 +01:00
Gwilym Inzani 89f6a2782b Allow loading of the dwarf information from the gba rom 2024-04-03 14:03:42 +01:00
Gwilym Inzani 25e15baa2b Compress the debug data for quite a large saving 2024-04-03 13:38:49 +01:00
Gwilym Inzani 2475b5676a Include the debug info in the rom (optionally) 2024-04-03 13:33:50 +01:00
Gwilym Inzani 4144a2be0a Use the ? operator instead 2024-04-03 11:16:44 +01:00
Gwilym Inzani 37ecd48a40 Add a message about the fact that the game crashed 2024-04-03 11:16:34 +01:00
Gwilym Inzani 5e298cb582 Don't need the commented out encoding any more since it is in the test 2024-04-03 11:10:55 +01:00
Gwilym Inzani f633b04d3c Allow passing the URL too since that's easier to copy-paste 2024-04-03 11:08:31 +01:00
Gwilym Inzani fe78711736 Alphabet should be static 2024-04-03 10:58:25 +01:00
Gwilym Inzani e21d06994f Add some tests which showed issues with the decoder 2024-04-03 10:58:06 +01:00
Gwilym Inzani 219fc1e0bc Extract gwilym_encoding into its own file 2024-04-03 10:35:05 +01:00
Gwilym Inzani 51de2ffa60 Don't need to import this macro 2024-04-02 23:38:43 +01:00
Gwilym Inzani e0d68eec15 Correctly render in release mode 2024-04-02 23:31:02 +01:00
Gwilym Inzani e5a8b39924 Print some extra useful information 2024-04-02 23:19:09 +01:00
Gwilym Inzani 6c9c23f79e Change what's being printed slightly 2024-04-02 22:37:23 +01:00
Gwilym Inzani e36145552f gwilym_encode the stack trace and generate a qr code for debugging 2024-04-02 22:24:58 +01:00
Gwilym Inzani 335d69395a
Update Rust crate xmrs to 0.5 (#591)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [xmrs](https://codeberg.org/sbechet/xmrs) | dependencies | minor |
`0.4` -> `0.5` |

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yNjkuMiIsInVwZGF0ZWRJblZlciI6IjM3LjI2OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-04-02 20:13:28 +01:00
GBA bot 5f24660b27 Update lockfiles 2024-04-02 12:10:47 +00:00
renovate[bot] 0b7e3464ab
Update Rust crate xmrs to 0.5 2024-04-02 12:10:08 +00:00
Gwilym Inzani 71bdb085be Include the new option in all the config.tomls 2024-04-01 17:02:59 +01:00
Gwilym Inzani 07a6857354 into feels better 2024-04-01 16:56:18 +01:00
Gwilym Inzani fc6e1d5e09 Warn if the file was modified more recently than the elf file 2024-04-01 16:41:05 +01:00
Gwilym Inzani 4b0622f6fb Always include the code 2024-04-01 16:37:06 +01:00
Gwilym Inzani 087228d946 Don't show as much information for uninteresting functions 2024-04-01 16:36:05 +01:00
Gwilym Inzani d729591c0e Include the source code too 2024-04-01 16:30:36 +01:00
Gwilym Inzani ac49855937 Prettify the path 2024-04-01 14:22:41 +01:00
Gwilym Inzani fb9159d2cf Prettify the output furter 2024-04-01 14:16:13 +01:00
Gwilym Inzani 726b400463 Slightly prettier output 2024-04-01 14:10:23 +01:00
Gwilym Inzani 3f374f3e9c Print the entire backtrace 2024-04-01 14:05:22 +01:00
Gwilym Inzani 8453b46eab Prettify the output a little 2024-04-01 13:43:08 +01:00
Gwilym Inzani 3ab6d08c7f Start to implement an agb-addr2line 2024-04-01 13:26:48 +01:00
Gwilym Inzani 7708398981 Basic implementation of backtraces on panic 2024-04-01 13:05:39 +01:00
Gwilym Inzani 6fdd961b61
Kerning support (#588)
Some fonts look a bit weird if you don't do kerning.

@corwinkuiper can you check if I've done the correct thing for object
font rendering? I'm not entirely sure... Although it does render
correctly in my tests :D

- [x] Changelog updated / no changelog update needed
2024-03-29 15:17:18 +00:00
Corwin 9cbddfec80
Use static rather than const (#529) 2024-03-29 14:51:11 +00:00
Corwin ce4882a56c
add changelog entry 2024-03-29 14:43:36 +00:00
Corwin 184b11ed81
use static rather than const 2024-03-29 14:41:08 +00:00
Gwilym Inzani 58c0e02b48 Add a changelog entry for kerning 2024-03-27 11:12:23 +00:00
Gwilym Inzani 2833045322 Add kerning support to the font rendering 2024-03-27 11:01:26 +00:00
Gwilym Inzani 92c39ecc5d
Unicode font support (#587)
![image](https://github.com/agbrs/agb/assets/460842/52dcd161-d8e4-4588-8f3e-c8dd8c2540aa)

Doesn't correctly handle accents or modifiers like that. Ligatures are
also not supported. But does correctly render any character directly in
the font :)

- [x] Changelog updated / no changelog update needed
2024-03-27 09:53:11 +00:00
Gwilym Inzani 232e5670d4 Say hello in japanese for the object_text_render example 2024-03-27 09:44:40 +00:00
Gwilym Inzani a7b017e7e7 Add a changelog entry for initial unicode support 2024-03-27 09:32:34 +00:00
Gwilym Inzani fa1de1fab7 Should be static 2024-03-27 09:30:41 +00:00
Gwilym Inzani f4efaf67a4 Add a japanese text rendering example 2024-03-27 09:26:11 +00:00
Gwilym Inzani a61fe79a6f Allow any character supported by the font 2024-03-27 09:21:06 +00:00
Gwilym Inzani dc8a6e3884 Add a japanese font to the examples ready for testing 2024-03-27 09:09:40 +00:00
Gwilym Inzani 0142decb92
Document -> DocumentMut (#586)
Build started failing last night because of this
2024-03-20 13:34:14 +00:00
Gwilym Inzani b28f3872c0 Document -> DocumentMut 2024-03-20 13:26:02 +00:00
Gwilym Inzani 33bc38a094
Update Rust crate asefile to 0.3.8 (#585)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [asefile](https://togithub.com/alpine-alpaca/asefile) | dependencies |
patch | `0.3.7` -> `0.3.8` |

---

### Release Notes

<details>
<summary>alpine-alpaca/asefile (asefile)</summary>

###
[`v0.3.8`](https://togithub.com/alpine-alpaca/asefile/blob/HEAD/CHANGELOG.md#038)

[Compare
Source](https://togithub.com/alpine-alpaca/asefile/compare/v0.3.7...v0.3.8)

-   Parse `repeat` property of a tag. [#&#8203;23]
-   Upgrade Rust edition and `bitflags` dependency [#&#8203;24]

[#&#8203;23]: https://togithub.com/alpine-alpaca/asefile/pull/23

[#&#8203;24]: https://togithub.com/alpine-alpaca/asefile/pull/24

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yNDUuMCIsInVwZGF0ZWRJblZlciI6IjM3LjI0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-03-19 23:41:19 +00:00
GBA bot 4bf1778dec Update lockfiles 2024-03-19 23:30:08 +00:00
renovate[bot] 2a418ed38a
Update Rust crate asefile to 0.3.8 2024-03-19 23:29:33 +00:00
Gwilym Inzani f36a888771
Add changelog entry (#584)
Forgot to push the changelog entry
2024-03-13 15:45:33 +00:00
Gwilym Inzani 09ad7c2c5d Add changelog entry 2024-03-13 15:36:46 +00:00
Gwilym Inzani 0c21f70c46
Make dma module public (#583)
I was trying to use DMA in a less trivial case than the examples and
couldn't because I couldn't write the types (since I'd forgotten to
export the module).

This will likely just be 0.19.2 with the extra `pub mod` :)

- [x] Changelog updated
2024-03-13 14:38:13 +00:00
Gwilym Inzani b25302f133 Add required doc comments 2024-03-13 14:28:48 +00:00
Gwilym Inzani 3c28324e83 Make the DMA module public 2024-03-13 14:24:14 +00:00
Gwilym Inzani 95b5e85f57
Update Rust crate xmrs to 0.4 (#579)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [xmrs](https://codeberg.org/sbechet/xmrs) | dependencies | minor |
`0.3` -> `0.4` |

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yMzAuMCIsInVwZGF0ZWRJblZlciI6IjM3LjIzMC4wIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-03-09 16:22:56 +00:00
GBA bot 0b669e513e Update lockfiles 2024-03-09 15:28:03 +00:00
renovate[bot] 5093c94eac
Update Rust crate xmrs to 0.4 2024-03-09 15:27:29 +00:00
Gwilym Inzani d804edb1ec
Fix clippy lint in agb tools (#581)
Clippy lint was getting upset that we were pointlessly cloning. So stop
doing that (even though the lint seems to have a bug, but I'd like the
build to start working again).

- [x]  no changelog update needed
2024-03-09 12:18:38 +00:00
Gwilym Inzani 622887bcdc Don't clone unnecessarily 2024-03-09 12:09:34 +00:00
Corwin 9e63b2c46c
Release v0.19.1 2024-03-06 19:11:47 +00:00
Corwin 2e87a77b79
Fix out by one in infinite scroll (#577)
Fix out by one in infinite scroll
2024-03-06 17:22:09 +00:00
Gwilym Inzani 7ebebb2942 Fix out by one in infinite scroll 2024-03-06 15:42:48 +00:00
Gwilym Inzani 75320ed3e0
Fix the incorrect copying of map tiles issue (#576)
* A very old issue that meant you couldn't move more than one tile per
frame.
* This fixes the logic so we can move maps quickly.

- [x] Changelog updated
2024-03-06 14:30:21 +00:00
Gwilym Inzani f8e24a3ee3 Add changelog entry 2024-03-06 14:24:58 +00:00
Corwin 78146bc963
fix the incorrect copying of map tiles issue 2024-03-06 12:40:53 +00:00
Corwin 20a74fe319
introduce vector and rect abs 2024-03-06 12:40:53 +00:00
Gwilym Inzani 66ec762855 Release v0.19.0 2024-03-06 09:33:58 +00:00
Gwilym Inzani ec2bbb3eca Changelog should say 'changed' 2024-03-06 09:26:47 +00:00
Gwilym Inzani 5bdc782e78
Add an into_inner() function on infinite scrolled map (#575)
Adds a useful into_inner function which we need at the moment.

Will add a changelog and documentation later

- [x] Changelog updated
2024-03-06 09:11:08 +00:00
Gwilym Inzani 90fe94424f Add a doc entry for into_inner 2024-03-06 09:02:40 +00:00
Gwilym Inzani 98d9c133c7 Add a changelog entry for into_inner 2024-03-06 09:00:28 +00:00
Gwilym Inzani 569a1c0425 Add an into_inner() function on infinite scrolled map 2024-03-06 08:59:29 +00:00
Corwin 0e7716b4ee
Bump asefile version (#573) 2024-03-03 16:23:53 +00:00
Corwin 7a84eb3cd5
update lockfiles 2024-03-03 15:59:15 +00:00
Corwin 7515a192f4
remove unused import 2024-03-03 15:59:06 +00:00
Corwin c4d06b6e7f
bump asefile version 2024-03-03 15:58:59 +00:00
Gwilym Inzani 2c8cb646ac
Default implementations (#571)
Add some implementations of `Default` for classes with empty new
constructors

- [x] Changelog updated
2024-02-28 10:17:03 +00:00
Gwilym Inzani 42eadde631 Also add default implementation for InitOnce 2024-02-28 10:09:12 +00:00
Gwilym Inzani 0f19093465
Update extractions/setup-just action to v2 (#570)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [extractions/setup-just](https://togithub.com/extractions/setup-just)
| action | major | `v1` -> `v2` |

---

### Release Notes

<details>
<summary>extractions/setup-just (extractions/setup-just)</summary>

### [`v2`](https://togithub.com/extractions/setup-just/compare/v1...v2)

[Compare
Source](https://togithub.com/extractions/setup-just/compare/v1...v2)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yMTIuMCIsInVwZGF0ZWRJblZlciI6IjM3LjIxMi4wIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-02-28 09:58:18 +00:00
Gwilym Inzani 661eb7155f Add changelog entry for default implementations 2024-02-28 09:56:23 +00:00
Gwilym Inzani 941eb4ade1 Add missing default implementations 2024-02-28 09:55:55 +00:00
GBA bot 6dbf946ca3 Update lockfiles 2024-02-27 22:05:08 +00:00
renovate[bot] dbaea5a341
Update extractions/setup-just action to v2 2024-02-27 22:04:35 +00:00
Gwilym Inzani b5c97afe61
Manually copy the first value when you set up hblank (#569)
Fixes the weird lines on the hblank demos

- [x] No changelog update needed
2024-02-27 20:50:14 +00:00
Gwilym Inzani 4ebab07d47 Manually copy the value when you set up hblank 2024-02-27 20:40:20 +00:00
Gwilym Inzani cdafc3c139
DMA abstraction (#491)
It would be nice to have an easy way to add DMA effects to games.

- [x] Changelog updated
2024-02-21 14:44:41 +00:00
Gwilym Inzani 2fa33ede16
Implement num traits for fixnum (#568)
from_str_radix is implemented incredibly lazily, but should hopefully be
okay since you shouldn't be putting that in the critical path anyway :)

- [x] Changelog updated
2024-02-21 14:37:29 +00:00
Gwilym Inzani 3e47a49198 Make the changelog entry more accurate 2024-02-21 14:36:45 +00:00
Gwilym Inzani 23550e579a More .into() 2024-02-21 14:27:48 +00:00
Gwilym Inzani d6319ed409 Add a changelog entry for implementing num 2024-02-21 13:59:53 +00:00
Gwilym Inzani cfd3135d76 Implement num::Num for fixnum::Num 2024-02-21 13:58:27 +00:00
Gwilym Inzani b357acbba8 Don't need this .into() either 2024-02-21 13:01:03 +00:00
Gwilym Inzani 74451f819c More impl Into<Vector2D<_>> and fix compile errors 2024-02-21 12:59:02 +00:00
Gwilym Inzani f96b0e772b Add a changelog entry for dma effects 2024-02-21 12:40:50 +00:00
Gwilym Inzani 4ef08a1273 Add an example of doing circular windows 2024-02-21 12:39:03 +00:00
Gwilym Inzani a0700b3a51 Move the id storage to the window itself 2024-02-21 12:13:00 +00:00
Gwilym Inzani a3f772c7a3 Split the examples into 2 different ones 2024-02-21 12:03:46 +00:00
Gwilym Inzani de0c4ca4f4 Allow recolouring of the background using DMA 2024-02-21 11:56:49 +00:00
Gwilym Inzani edcd37c203 transfer should have a lifetime on the item you're passing in 2024-02-21 11:33:09 +00:00
Gwilym Inzani de15538d42 Add basic dma effect stuff 2024-02-21 11:28:20 +00:00
Gwilym Inzani 43718773d7 Don't use DMA outside of the eeprom case 2024-02-21 11:28:20 +00:00
Gwilym Inzani eaf5a83076
Midi support (#516)
Start working on MIDI file support for agb-tracker. Far from complete,
but at least it is a start :).

- [x] Changelog updated / no changelog update needed
2024-02-20 22:35:38 +00:00
Gwilym Inzani 6a0f0a30c4 Should be 0.18.1 2024-02-20 22:27:29 +00:00
Gwilym Inzani ff9f336be3 Do pitch bend correctly 2024-02-20 22:27:29 +00:00
Gwilym Inzani a36b06b35c Correctly handle no sample set 2024-02-20 22:27:29 +00:00
Gwilym Inzani b583ba22a9 Use Default::default which is nicer 2024-02-20 22:27:29 +00:00
Gwilym Inzani 2e453e8e0f Envelopes for MIDI 2024-02-20 22:27:29 +00:00
Gwilym Inzani 0a13b54e12 Pitch bending 2024-02-20 22:27:29 +00:00
Gwilym Inzani bf79b09e6a Avoid double panning correction 2024-02-20 22:27:29 +00:00
Gwilym Inzani 817ba12ea7 Format the let-else 2024-02-20 22:27:29 +00:00
Gwilym Inzani 9f60b61289 Changelog entry for midi tracker 2024-02-20 22:27:29 +00:00
Gwilym Inzani b82ec0ca1c Disable the MIDI feature in dungeon-puzzlers-lament 2024-02-20 22:27:29 +00:00
Gwilym Inzani 54ade5af2d Add a note about midi support being experimental 2024-02-20 22:27:29 +00:00
Gwilym Inzani cf50223dfc It seems to do better without the tune for some reason 2024-02-20 22:27:29 +00:00
Gwilym Inzani 0e685ce7e8 That's the longest out by one I've ever had to debug
Thanks Corwin for helping!
2024-02-20 22:27:29 +00:00
Gwilym Inzani 85e358874c HELP! 2024-02-20 22:27:29 +00:00
Gwilym Inzani 7f200a21ad This works better than before 2024-02-20 22:27:29 +00:00
Gwilym Inzani a55b106106 Better looping 2024-02-20 22:27:29 +00:00
Gwilym Inzani e103468b86 Vaguely get the correct beat and the patterns correct 2024-02-20 22:27:29 +00:00
Gwilym Inzani 64976deeb5 Export maybe something? 2024-02-20 22:27:29 +00:00
Gwilym Inzani 7868094f7e Maybe exporting something useful? 2024-02-20 22:27:29 +00:00
Gwilym Inzani 32aaaef4cd It actually builds now 2024-02-20 22:27:29 +00:00
Gwilym Inzani 5768b56028 Fix unused warning 2024-02-20 22:27:29 +00:00
Gwilym Inzani 797fc8394f Boilerplate for midi support 2024-02-20 22:27:29 +00:00
Gwilym Inzani 0975530e5c
Remove unnecessary imports (#567)
Fix for latest clippy / nightly upgrade

- [x] no changelog update needed
2024-02-20 22:27:00 +00:00
Gwilym Inzani 8e25f011b4 Remove unnecessary imports 2024-02-20 22:15:31 +00:00
Corwin f99da581da
Expose hflip, vflip, priority, position (#566)
This exposes expose the `hflip`, `vflip`, `priority` and `position`
object attribute to remove the need for storing them in separate
variables.
I think it might also be worth to update the pong tutorial and maybe
some of the examples to highlight this.

- [x] Changelog updated / no changelog update needed
2024-02-17 16:51:34 +00:00
Constantin 1d0a25bc43 Expose hflip, vflip, priority, position 2024-02-17 16:28:43 +01:00
Gwilym Inzani e610a1cbf6
Add priority set / get and set_visible / is_visible to maps (#563)
Adds `.priority()`, `.set_priority()` and `.is_visible()` and replace
`show` and `hide` with `.set_visible()` in `RegularMap`, `AffineMap` and
`InfiniteScrolledMap`.

- [x] Changelog updated / no changelog update needed
2024-02-16 21:07:01 +00:00
Gwilym Inzani 34b5b5f8f8 This should be hiding not showing 2024-02-16 20:56:57 +00:00
Constantin da84131de6 Add priority set / get and set_visible / is_visible to maps 2024-02-16 11:21:27 +01:00
Gwilym Inzani 77dba9f38e
Update Rust crate pkg-config to 0.3.30 (#562)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [pkg-config](https://togithub.com/rust-lang/pkg-config-rs) |
build-dependencies | patch | `0.3.29` -> `0.3.30` |

---

### Release Notes

<details>
<summary>rust-lang/pkg-config-rs (pkg-config)</summary>

###
[`v0.3.30`](https://togithub.com/rust-lang/pkg-config-rs/blob/HEAD/CHANGELOG.md#0330---2024-02-14)

##### Changed

- Update documentation for cross-compilation
([#&#8203;161](https://togithub.com/rust-lang/pkg-config-rs/issues/161)).

- Update GitHub Action CI
([#&#8203;160](https://togithub.com/rust-lang/pkg-config-rs/issues/160)).

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4xNzMuMCIsInVwZGF0ZWRJblZlciI6IjM3LjE3My4wIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-02-15 22:20:11 +00:00
Gwilym Inzani 0a35fa4629 Update lockfiles (again) 2024-02-15 22:12:04 +00:00
Gwilym Inzani c1a19888c3 Be less specific about the pkg-config version 2024-02-15 22:11:14 +00:00
GBA bot 2289a533de Update lockfiles 2024-02-14 11:02:19 +00:00
renovate[bot] 7e7b5f6a18
Update Rust crate pkg-config to 0.3.30 2024-02-14 11:01:49 +00:00
Corwin f3734f43c9
Changes the default runner to log to console (#557)
- [ x] Changelog updated / no changelog update needed

This closes issue #554 and allows the template project have logging to
console on by default when you run `cargo run`
2024-02-13 21:27:29 +00:00
Corwin f91a464a89
Cleanup allocators (#558)
Perform some cleanup of the allocators
2024-02-13 21:29:01 +00:00
Corwin fb33422039
run workflow on merge queue (#559) 2024-02-13 21:58:33 +00:00
Corwin 8ff80a6ac2 run workflow on merge queue 2024-02-13 21:49:35 +00:00
Corwin 90be23a192
remove block counting to no longer attempt to detect memory leaks
remove checking blocks

Signed-off-by: Corwin <corwin@kuiper.dev>
2024-02-13 21:18:14 +00:00
Corwin 844f3b29d3
Remove global alloc support from the bump allocator
Signed-off-by: Corwin <corwin@kuiper.dev>
2024-02-13 21:18:14 +00:00
Bailey Townsend d8fe616d90 Change default runner to log to console 2024-02-12 17:32:44 -06:00
Gwilym Inzani 5f0d86e2e3
Update ahash in the cargo.lock files. (#556)
Fixes #553 and allows building on latest nightly again.

- [x] no changelog update needed
2024-02-11 16:27:08 +00:00
Gwilym Inzani 7d6ea45670 Update ahash in the cargo.lock files.
Fixes #553 and allows building on latest nightly again.
2024-02-11 16:17:59 +00:00
Gwilym Inzani ee432d05a6
rustc-hash isn't needed in agb itself any more (#552)
- [x] no changelog update needed
2024-02-09 22:05:36 +00:00
Gwilym Inzani ff235a75f3 rustc_hash isn't needed in agb itself any more 2024-02-09 21:58:42 +00:00
Gwilym Inzani e73d864d07
px_offset_x and px_offset_y were unused (#551)
These methods were unused and breaking the build

- [x] Changelog updated / no changelog update needed
2024-02-09 21:49:21 +00:00
Gwilym Inzani bd4ae7d2fb px_offset_x and px_offset_y were unused 2024-02-09 21:38:43 +00:00
Gwilym Inzani c59a36b96e
Update Rust crate toml_edit to 0.22 (#549)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [toml_edit](https://togithub.com/toml-rs/toml) | dependencies | minor
| `0.21` -> `0.22` |

---

### Release Notes

<details>
<summary>toml-rs/toml (toml_edit)</summary>

###
[`v0.22.2`](https://togithub.com/toml-rs/toml/compare/v0.22.1...v0.22.2)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.22.1...v0.22.2)

###
[`v0.22.1`](https://togithub.com/toml-rs/toml/compare/v0.22.0...v0.22.1)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.22.0...v0.22.1)

###
[`v0.22.0`](https://togithub.com/toml-rs/toml/compare/v0.21.1...v0.22.0)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.21.1...v0.22.0)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4xNzMuMCIsInVwZGF0ZWRJblZlciI6IjM3LjE3My4wIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-02-07 08:08:58 +00:00
GBA bot 5d82f96396 Update lockfiles 2024-02-06 22:49:04 +00:00
renovate[bot] 09295d9785
Update Rust crate toml_edit to 0.22 2024-02-06 22:48:37 +00:00
Gwilym Inzani 3f607b379a Release v0.18.1 2024-02-06 22:36:11 +00:00
Gwilym Inzani a87a4099d3
Pause channels (#548)
Requested here: https://github.com/agbrs/agb/discussions/547

Added methods to pause and resume playback of audio channels, and you
can use it with the mixer_basic example to prove it works.

- [x] Changelog updated / no changelog update needed
2024-02-03 22:18:08 +01:00
Gwilym Inzani e3c299c13a Add a changelog entry for pause and resume 2024-02-03 21:10:27 +00:00
Gwilym Inzani fec06e0c69 Include pause and resume in the example 2024-02-03 21:09:37 +00:00
Gwilym Inzani d8110243f4 Add pausing and resuming for sound channels 2024-02-03 21:09:37 +00:00
Gwilym Inzani ac8e7d84f7
Expand $OUT_DIR in include_aseprite and include_background_gfx (#545)
As discussed in https://github.com/agbrs/agb/discussions/544, this
expand $OUT_DIR when used in the **include_aseprite** and
**include_background_gfx** macros in order to support including from the
out directory.

Example usage:
`const SPRITE_0: &Graphics =
include_aseprite!("$OUT_DIR/sprite_0.aseprite");`

- [x] Changelog updated / no changelog update needed
2024-02-03 21:29:57 +01:00
Gwilym Inzani ade1ba5718 Also include the docs in the agb lib itself 2024-02-03 20:22:06 +00:00
Constantin 03fb125d52 Changelog update 2024-02-03 13:41:27 +01:00
Constantin b03268f363 Added macro doc 2024-02-03 13:40:59 +01:00
Gwilym Inzani c5cbe957ab
Update Rust crate libc to 0.2.153 (#546)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [libc](https://togithub.com/rust-lang/libc) | dependencies | patch |
`0.2.152` -> `0.2.153` |

---

### Release Notes

<details>
<summary>rust-lang/libc (libc)</summary>

###
[`v0.2.153`](https://togithub.com/rust-lang/libc/releases/tag/0.2.153)

[Compare
Source](https://togithub.com/rust-lang/libc/compare/0.2.152...0.2.153)

##### What's Changed

- Add SOMAXCONN to vita on 0.2 (to fix std) by
[@&#8203;pheki](https://togithub.com/pheki) in
[https://github.com/rust-lang/libc/pull/3552](https://togithub.com/rust-lang/libc/pull/3552)
- Fix CI for v0.2 by [@&#8203;JohnTitor](https://togithub.com/JohnTitor)
in
[https://github.com/rust-lang/libc/pull/3557](https://togithub.com/rust-lang/libc/pull/3557)
- \[Backport
[#&#8203;3548](https://togithub.com/rust-lang/libc/issues/3548)] Add
ioctl FS_IOC\_{G,S}{ETVERSION,ETFLAGS} for LoongArch64 by
[@&#8203;heiher](https://togithub.com/heiher) in
[https://github.com/rust-lang/libc/pull/3570](https://togithub.com/rust-lang/libc/pull/3570)
- Add MFD_NOEXEC_SEAL and MFD_EXEC by
[@&#8203;rusty-snake](https://togithub.com/rusty-snake) in
[https://github.com/rust-lang/libc/pull/3553](https://togithub.com/rust-lang/libc/pull/3553)
- Backport of
[#&#8203;3546](https://togithub.com/rust-lang/libc/issues/3546) and
update crate version to 0.2.153 by
[@&#8203;GuillaumeGomez](https://togithub.com/GuillaumeGomez) in
[https://github.com/rust-lang/libc/pull/3554](https://togithub.com/rust-lang/libc/pull/3554)

##### New Contributors

- [@&#8203;rusty-snake](https://togithub.com/rusty-snake) made their
first contribution in
[https://github.com/rust-lang/libc/pull/3553](https://togithub.com/rust-lang/libc/pull/3553)

**Full Changelog**:
https://github.com/rust-lang/libc/compare/0.2.152...0.2.153

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4xNTMuMiIsInVwZGF0ZWRJblZlciI6IjM3LjE1My4yIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-02-02 23:08:17 +01:00
GBA bot cc0853518b Update lockfiles 2024-01-31 23:15:12 +00:00
renovate[bot] bfd38f425b
Update Rust crate libc to 0.2.153 2024-01-31 23:14:44 +00:00
Constantin 3cd71b120f Names update 2024-01-24 20:17:04 +01:00
Constantin 3fcab53f52 Expand $OUT_DIR in background and sprite include macros 2024-01-24 19:19:30 +01:00
Gwilym Inzani 356adb60e9
Update Rust crate pkg-config to 0.3.29 (#542)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [pkg-config](https://togithub.com/rust-lang/pkg-config-rs) |
build-dependencies | patch | `0.3.28` -> `0.3.29` |

---

### Release Notes

<details>
<summary>rust-lang/pkg-config-rs (pkg-config)</summary>

###
[`v0.3.29`](https://togithub.com/rust-lang/pkg-config-rs/blob/HEAD/CHANGELOG.md#0329---2024-01-17)

[Compare
Source](https://togithub.com/rust-lang/pkg-config-rs/compare/0.3.28...0.3.29)

##### Fixed

- Detection and usage of Windows static libraries
([#&#8203;154](https://togithub.com/rust-lang/pkg-config-rs/issues/154)).

- Passing `-Wl,-u` to the linker if specified in the pkg-config file
([#&#8203;154](https://togithub.com/rust-lang/pkg-config-rs/issues/154)).

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4xMzUuMCIsInVwZGF0ZWRJblZlciI6IjM3LjEzNS4wIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-01-23 20:46:12 +00:00
Gwilym Inzani 42ec1520d7
Update actions/cache action to v4 (#543)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [actions/cache](https://togithub.com/actions/cache) | action | major |
`v3` -> `v4` |

---

### Release Notes

<details>
<summary>actions/cache (actions/cache)</summary>

### [`v4`](https://togithub.com/actions/cache/compare/v3...v4)

[Compare Source](https://togithub.com/actions/cache/compare/v3...v4)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4xMzUuMCIsInVwZGF0ZWRJblZlciI6IjM3LjEzNS4wIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-01-23 20:45:56 +00:00
GBA bot 7a7aa5c57b Update lockfiles 2024-01-17 17:23:23 +00:00
GBA bot eb3b9b3c4a Update lockfiles 2024-01-17 17:23:16 +00:00
renovate[bot] 94263ae20b
Update actions/cache action to v4 2024-01-17 17:22:50 +00:00
renovate[bot] f6eade6c02
Update Rust crate pkg-config to 0.3.29 2024-01-17 17:22:45 +00:00
Corwin 863afbbe23
fix ewram name (#541)
- [ ] Changelog updated / no changelog update needed
2024-01-13 14:54:03 +00:00
Corwin 7c752b2e97
fix ewram name 2024-01-13 14:34:59 +00:00
Corwin 156fe0fe7d
Fix clippy and use nightly for CI builds (#540) 2024-01-13 10:46:06 +00:00
Corwin e35bfd0636
use nightly explicitly 2024-01-13 10:36:10 +00:00
Corwin 8e367ab6b6
allow dead code of an enum parameter only used in a debug print 2024-01-13 10:31:33 +00:00
Corwin 3840c4ce80
remove unused enum parameter 2024-01-13 10:31:09 +00:00
Corwin e13d844f1f
use cloned rather than a map that clones 2024-01-13 10:31:00 +00:00
Corwin 1132bc2383
use addr_of_mut rather than mut reference 2024-01-13 10:30:44 +00:00
Corwin 5e711ebb5f
use latest nightly 2024-01-13 10:06:12 +00:00
Corwin 85671edd4f
add projects to workspace 2024-01-13 10:05:04 +00:00
Corwin 018643f652
Remove autoscrolling from Purple Night (#539)
- [x] no changelog update needed
2024-01-09 21:53:28 +00:00
Corwin 8029e938f4
not autoscroll 2024-01-07 21:19:11 +00:00
Gwilym Inzani 004116969c
Update Rust crate libc to 0.2.152 (#538)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [libc](https://togithub.com/rust-lang/libc) | dependencies | patch |
`0.2.151` -> `0.2.152` |

---

### Release Notes

<details>
<summary>rust-lang/libc (libc)</summary>

###
[`v0.2.152`](https://togithub.com/rust-lang/libc/releases/tag/0.2.152)

[Compare
Source](https://togithub.com/rust-lang/libc/compare/0.2.151...0.2.152)

##### What's Changed

- openbsd: syscall() has been removed in upcoming OpenBSD 7.5 by
[@&#8203;semarie](https://togithub.com/semarie) in
[https://github.com/rust-lang/libc/pull/3479](https://togithub.com/rust-lang/libc/pull/3479)
- adding tcp_info to openbsd by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3481](https://togithub.com/rust-lang/libc/pull/3481)
- iadding yser_fpxregs_struct data to linux/musl i686. by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3477](https://togithub.com/rust-lang/libc/pull/3477)
- strftime\* api for \*BSD by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3483](https://togithub.com/rust-lang/libc/pull/3483)
- strftime_l for Linux glibc/musl by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3484](https://togithub.com/rust-lang/libc/pull/3484)
- adding iocb data for io_submit syscall for linux/glibc. by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3486](https://togithub.com/rust-lang/libc/pull/3486)
- Re-enable `i686-pc-windows-gnu` CI by
[@&#8203;JohnTitor](https://togithub.com/JohnTitor) in
[https://github.com/rust-lang/libc/pull/3489](https://togithub.com/rust-lang/libc/pull/3489)
- Stop testing on FreeBSD 12 by
[@&#8203;asomers](https://togithub.com/asomers) in
[https://github.com/rust-lang/libc/pull/3475](https://togithub.com/rust-lang/libc/pull/3475)
- Add `ifreq`, `ifconf` and related constants to Android by
[@&#8203;arctic-alpaca](https://togithub.com/arctic-alpaca) in
[https://github.com/rust-lang/libc/pull/3487](https://togithub.com/rust-lang/libc/pull/3487)
- Add waitid function for OpenBSD by
[@&#8203;lcheylus](https://togithub.com/lcheylus) in
[https://github.com/rust-lang/libc/pull/3490](https://togithub.com/rust-lang/libc/pull/3490)
- adding SOMAXCONN to redox by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3491](https://togithub.com/rust-lang/libc/pull/3491)
- Fix typos in comments by
[@&#8203;asomers](https://togithub.com/asomers) in
[https://github.com/rust-lang/libc/pull/3492](https://togithub.com/rust-lang/libc/pull/3492)
- fix typos in libc by
[@&#8203;Takashiidobe](https://togithub.com/Takashiidobe) in
[https://github.com/rust-lang/libc/pull/3496](https://togithub.com/rust-lang/libc/pull/3496)
- apple adding tcp_connection_info struct by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3482](https://togithub.com/rust-lang/libc/pull/3482)
- Improve the version parser of Emscripten by
[@&#8203;kleisauke](https://togithub.com/kleisauke) in
[https://github.com/rust-lang/libc/pull/3498](https://togithub.com/rust-lang/libc/pull/3498)
- Add constants from \<include/linux/sched.h> by
[@&#8203;GuillaumeGomez](https://togithub.com/GuillaumeGomez) in
[https://github.com/rust-lang/libc/pull/3505](https://togithub.com/rust-lang/libc/pull/3505)
- Define `TFD_TIMER_*` constants on FreeBSD. by
[@&#8203;sunfishcode](https://togithub.com/sunfishcode) in
[https://github.com/rust-lang/libc/pull/3506](https://togithub.com/rust-lang/libc/pull/3506)
- Add support for posix_spawn on OpenBSD by
[@&#8203;nuudlman](https://togithub.com/nuudlman) in
[https://github.com/rust-lang/libc/pull/3502](https://togithub.com/rust-lang/libc/pull/3502)
- clock_nanosleep for dragonflybsd, moving constants freebsd only too.
by [@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3509](https://togithub.com/rust-lang/libc/pull/3509)
- solarish add fcntl's O_DIRECT constant. by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3503](https://togithub.com/rust-lang/libc/pull/3503)
- Unpin cc dependency version by
[@&#8203;JohnTitor](https://togithub.com/JohnTitor) in
[https://github.com/rust-lang/libc/pull/3511](https://togithub.com/rust-lang/libc/pull/3511)
- redox: add openpty, login_tty, TIOCSCTTY, and organize functions by
[@&#8203;jackpot51](https://togithub.com/jackpot51) in
[https://github.com/rust-lang/libc/pull/3512](https://togithub.com/rust-lang/libc/pull/3512)
- Move all seccomp consts and structs into top-level mod by
[@&#8203;boustrophedon](https://togithub.com/boustrophedon) in
[https://github.com/rust-lang/libc/pull/3343](https://togithub.com/rust-lang/libc/pull/3343)
- freebsd 15 support proposal. by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3508](https://togithub.com/rust-lang/libc/pull/3508)
- Prepare workflow for merge queue by
[@&#8203;JohnTitor](https://togithub.com/JohnTitor) in
[https://github.com/rust-lang/libc/pull/3514](https://togithub.com/rust-lang/libc/pull/3514)
- Allow dead_code on `clockid_t` by
[@&#8203;JohnTitor](https://togithub.com/JohnTitor) in
[https://github.com/rust-lang/libc/pull/3516](https://togithub.com/rust-lang/libc/pull/3516)
- Add more items from `include/linux/sched.h` header by
[@&#8203;GuillaumeGomez](https://togithub.com/GuillaumeGomez) in
[https://github.com/rust-lang/libc/pull/3515](https://togithub.com/rust-lang/libc/pull/3515)
- fix typo by [@&#8203;shuoer86](https://togithub.com/shuoer86) in
[https://github.com/rust-lang/libc/pull/3517](https://togithub.com/rust-lang/libc/pull/3517)
- Add sigsuspend to more targets: bsd, haiku, and solarish by
[@&#8203;asomers](https://togithub.com/asomers) in
[https://github.com/rust-lang/libc/pull/3518](https://togithub.com/rust-lang/libc/pull/3518)
- Tweak libc-0.2 CI by
[@&#8203;JohnTitor](https://togithub.com/JohnTitor) in
[https://github.com/rust-lang/libc/pull/3519](https://togithub.com/rust-lang/libc/pull/3519)
- fuchsia adding pthread_set/getname_np by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3520](https://togithub.com/rust-lang/libc/pull/3520)
- Prepare docs for libc v0.3 by
[@&#8203;JohnTitor](https://togithub.com/JohnTitor) in
[https://github.com/rust-lang/libc/pull/3510](https://togithub.com/rust-lang/libc/pull/3510)
- Merge main into libc-0.2 by
[@&#8203;JohnTitor](https://togithub.com/JohnTitor) in
[https://github.com/rust-lang/libc/pull/3521](https://togithub.com/rust-lang/libc/pull/3521)
- Prepare release for v0.2.152 by
[@&#8203;JohnTitor](https://togithub.com/JohnTitor) in
[https://github.com/rust-lang/libc/pull/3522](https://togithub.com/rust-lang/libc/pull/3522)

##### New Contributors

- [@&#8203;Takashiidobe](https://togithub.com/Takashiidobe) made their
first contribution in
[https://github.com/rust-lang/libc/pull/3496](https://togithub.com/rust-lang/libc/pull/3496)
- [@&#8203;nuudlman](https://togithub.com/nuudlman) made their first
contribution in
[https://github.com/rust-lang/libc/pull/3502](https://togithub.com/rust-lang/libc/pull/3502)
- [@&#8203;boustrophedon](https://togithub.com/boustrophedon) made their
first contribution in
[https://github.com/rust-lang/libc/pull/3343](https://togithub.com/rust-lang/libc/pull/3343)
- [@&#8203;shuoer86](https://togithub.com/shuoer86) made their first
contribution in
[https://github.com/rust-lang/libc/pull/3517](https://togithub.com/rust-lang/libc/pull/3517)

**Full Changelog**:
https://github.com/rust-lang/libc/compare/0.2.151...0.2.152

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4xMjEuMCIsInVwZGF0ZWRJblZlciI6IjM3LjEyMS4wIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2024-01-07 21:09:25 +00:00
GBA bot 4fdd0e0263 Update lockfiles 2024-01-07 15:10:41 +00:00
renovate[bot] d1d4139813
Update Rust crate libc to 0.2.152 2024-01-07 15:10:06 +00:00
Gwilym Inzani 64989249c9
Update actions/upload-artifact action to v4 (#530)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[actions/upload-artifact](https://togithub.com/actions/upload-artifact)
| action | major | `v3` -> `v4` |

---

### Release Notes

<details>
<summary>actions/upload-artifact (actions/upload-artifact)</summary>

### [`v4`](https://togithub.com/actions/upload-artifact/compare/v3...v4)

[Compare
Source](https://togithub.com/actions/upload-artifact/compare/v3...v4)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy45My4xIiwidXBkYXRlZEluVmVyIjoiMzcuMTAzLjEiLCJ0YXJnZXRCcmFuY2giOiJtYXN0ZXIifQ==-->
2023-12-28 22:47:17 +00:00
renovate[bot] 04d1b9ebe0
Update actions/upload-artifact action to v4 2023-12-28 22:39:14 +00:00
Gwilym Inzani 2c4455ab6d
Update Rust crate libc to 0.2.151 (#528)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [libc](https://togithub.com/rust-lang/libc) | dependencies | patch |
`0.2.150` -> `0.2.151` |

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy44Ny4yIiwidXBkYXRlZEluVmVyIjoiMzcuMTAzLjEiLCJ0YXJnZXRCcmFuY2giOiJtYXN0ZXIifQ==-->
2023-12-28 22:38:45 +00:00
GBA bot 91154a897e Update lockfiles 2023-12-28 22:33:58 +00:00
renovate[bot] f617532a74
Update Rust crate libc to 0.2.151 2023-12-28 22:33:31 +00:00
Gwilym Inzani e8f5132c02
Add docs for priority (#526)
- [x] no changelog update needed
2023-12-28 22:33:06 +00:00
Gwilym Inzani 0faa5a5df3
Update Rust crate pkg-config to 0.3.28 (#531)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [pkg-config](https://togithub.com/rust-lang/pkg-config-rs) |
build-dependencies | patch | `0.3.27` -> `0.3.28` |

---

### Release Notes

<details>
<summary>rust-lang/pkg-config-rs (pkg-config)</summary>

###
[`v0.3.28`](https://togithub.com/rust-lang/pkg-config-rs/blob/HEAD/CHANGELOG.md#0328---2023-12-20)

[Compare
Source](https://togithub.com/rust-lang/pkg-config-rs/compare/0.3.27...0.3.28)

##### Fixed

- Pass -l:libfoo.a to linker directly
([#&#8203;149](https://togithub.com/rust-lang/pkg-config-rs/issues/149)).

##### Changed

- Improve error message when library not found
([#&#8203;158](https://togithub.com/rust-lang/pkg-config-rs/issues/158)).

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4xMDMuMSIsInVwZGF0ZWRJblZlciI6IjM3LjEwMy4xIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIn0=-->
2023-12-26 21:42:23 +00:00
GBA bot 05851558df Update lockfiles 2023-12-20 17:09:12 +00:00
renovate[bot] d8c19d81dc
Update Rust crate pkg-config to 0.3.28 2023-12-20 17:08:43 +00:00
Corwin 7a6043839e
add docs for priority 2023-12-09 20:48:46 +00:00
Corwin 90952b3de5
Override nightly versions if repo variable set for non scheduled runs (#524)
- [x] no changelog update needed
2023-12-05 22:09:13 +00:00
Corwin 7d09207d5c
override nightly version for non scheduled runs 2023-12-05 22:04:21 +00:00
Corwin 5fe4b8dfa5
format 2023-12-05 21:06:39 +00:00
Gwilym Inzani 62b5052b41
Update Rust crate fontdue to 0.8 (#518)
[![Mend Renovate logo
banner](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [fontdue](https://togithub.com/mooman219/fontdue) | dependencies |
minor | `0.7` -> `0.8` |

---

### Release Notes

<details>
<summary>mooman219/fontdue (fontdue)</summary>

###
[`v0.8.0`](https://togithub.com/mooman219/fontdue/blob/HEAD/CHANGELOG.md#080---2023-11-25)

##### Added

-   `Font.has_glyph()` for convenience.

##### Changes

- The 0.7.4 breaks semver by adding a field to FontSettings. 0.7.4 is
yanked and republished as 0.8.0

###
[`v0.7.4`](https://togithub.com/mooman219/fontdue/blob/HEAD/CHANGELOG.md#074---2023-11-25)

##### Added

-   Support Loading Ligature & Substitution Glyphs.

##### Changes

-   Update `ttf-parser` to 0.20
-   Update `hashbrown` to 0.14

##### Fixed

-   Fixed a potential unaligned read on x86.

###
[`v0.7.3`](https://togithub.com/mooman219/fontdue/blob/HEAD/CHANGELOG.md#073---2023-04-16)

##### Added

-   Expose layout settings on `Layout`
-   Add a line height option to LayoutSettings

##### Changes

-   Relicense to MIT OR Apache-2.0 OR Zlib
-   Update `hashbrown` to 0.13
- Refactored development related artifacts into the `dev` folder. This
reduces pollution in the main crate.
-   Removed some needless unsafe, documented other uses.

##### Fixed

-   More doc typos.

###
[`v0.7.2`](https://togithub.com/mooman219/fontdue/blob/HEAD/CHANGELOG.md#072---2022-03-03)

##### Added

-   Added `byte_offset` to GlyphPosition

##### Changes

- Breaking - Renamed `line_start`/`line_end` to
`glyph_start`/`glyph_end`

##### Fixed

-   More doc typos.
-   `line_start`/`glyph_start` skipping spacing characters.

###
[`v0.7.1`](https://togithub.com/mooman219/fontdue/blob/HEAD/CHANGELOG.md#071---2022-02-25)

##### Changes

-   `ttf-parser` updated to 0.15

##### Fixed

-   `LinePosition` doc typo.
-   Benign compiler error in debug mode in layout.

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy41OS44IiwidXBkYXRlZEluVmVyIjoiMzcuNTkuOCIsInRhcmdldEJyYW5jaCI6Im1hc3RlciJ9-->
2023-12-05 20:57:15 +00:00
GBA bot 382d465f3e Update lockfiles 2023-12-05 20:51:29 +00:00
Gwilym Inzani 522183b3ab Use ..Default::default() to make it clearer what we're changing 2023-12-05 20:50:33 +00:00
Gwilym Inzani 904c702e49
Ensure that the affine background example looks consistent (#523)
Fixes #522

- [x] Changelog updated / no changelog update needed
2023-12-05 20:48:12 +00:00
Gwilym Inzani 35c601d4e9 Ensure that the affine background example looks consistent 2023-12-05 20:33:00 +00:00
GBA bot b1df507fa6 Update lockfiles 2023-11-26 04:15:22 +00:00
renovate[bot] f615f9cf9f
Update Rust crate fontdue to 0.8 2023-11-26 04:14:47 +00:00
Gwilym Inzani 5e8e816294
Update Rust crate libc to 0.2.150 (#514)
[![Mend Renovate logo
banner](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [libc](https://togithub.com/rust-lang/libc) | dependencies | patch |
`0.2.149` -> `0.2.150` |

---

### Release Notes

<details>
<summary>rust-lang/libc (libc)</summary>

###
[`v0.2.150`](https://togithub.com/rust-lang/libc/releases/tag/0.2.150)

[Compare
Source](https://togithub.com/rust-lang/libc/compare/0.2.149...0.2.150)

#### What's Changed

- feat: closefrom() and close_range() for FreeBSD by
[@&#8203;SteveLauC](https://togithub.com/SteveLauC) in
[https://github.com/rust-lang/libc/pull/3374](https://togithub.com/rust-lang/libc/pull/3374)
- adding apple ifreq by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3375](https://togithub.com/rust-lang/libc/pull/3375)
- Add pthread_once by [@&#8203;0xcaff](https://togithub.com/0xcaff) in
[https://github.com/rust-lang/libc/pull/3376](https://togithub.com/rust-lang/libc/pull/3376)
- netbsd: Add SO_NOSIGPIPE by
[@&#8203;taiki-e](https://togithub.com/taiki-e) in
[https://github.com/rust-lang/libc/pull/3377](https://togithub.com/rust-lang/libc/pull/3377)
- Say goodbye to GH Pages in favor of docs.rs by
[@&#8203;JohnTitor](https://togithub.com/JohnTitor) in
[https://github.com/rust-lang/libc/pull/3378](https://togithub.com/rust-lang/libc/pull/3378)
- bugfix for teeos use Option by
[@&#8203;Sword-Destiny](https://togithub.com/Sword-Destiny) in
[https://github.com/rust-lang/libc/pull/3379](https://togithub.com/rust-lang/libc/pull/3379)
- openbsd/netbsd sharing execvpe definition by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3382](https://togithub.com/rust-lang/libc/pull/3382)
- ifreq for apple follow-up fix case when in non libc_union case by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3385](https://togithub.com/rust-lang/libc/pull/3385)
- NetBSD's mod.rs: fix cpuid_t definition. by
[@&#8203;he32](https://togithub.com/he32) in
[https://github.com/rust-lang/libc/pull/3386](https://togithub.com/rust-lang/libc/pull/3386)
- ifconf addition to apple. fixing freebsd's implementation while at it.
by [@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3388](https://togithub.com/rust-lang/libc/pull/3388)
- adding exect/execvP for FreeBSD/DragonflyBSD by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3381](https://togithub.com/rust-lang/libc/pull/3381)
- adding execvP for apple by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3383](https://togithub.com/rust-lang/libc/pull/3383)
- adding ifreq struct for openbsd by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3384](https://togithub.com/rust-lang/libc/pull/3384)
- Add `MCL_ONFAULT` constants by
[@&#8203;newpavlov](https://togithub.com/newpavlov) in
[https://github.com/rust-lang/libc/pull/3380](https://togithub.com/rust-lang/libc/pull/3380)
- Add time namespace constant by
[@&#8203;cd-work](https://togithub.com/cd-work) in
[https://github.com/rust-lang/libc/pull/3352](https://togithub.com/rust-lang/libc/pull/3352)
- adding few more CLONE_\* constant for Linux/Android. by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3034](https://togithub.com/rust-lang/libc/pull/3034)
- android add handful lock free stdio calls by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3290](https://togithub.com/rust-lang/libc/pull/3290)
- hurd: Fix msghdr's msg_iov field type by
[@&#8203;sthibaul](https://togithub.com/sthibaul) in
[https://github.com/rust-lang/libc/pull/3389](https://togithub.com/rust-lang/libc/pull/3389)
- Adding missing macros from linux/if_tun.h by
[@&#8203;BrandonMFong](https://togithub.com/BrandonMFong) in
[https://github.com/rust-lang/libc/pull/3320](https://togithub.com/rust-lang/libc/pull/3320)
- vxworks: Add mman.h consts and shm functions by
[@&#8203;jdygert-spok](https://togithub.com/jdygert-spok) in
[https://github.com/rust-lang/libc/pull/3406](https://togithub.com/rust-lang/libc/pull/3406)
- Reenable FreeBSD 14 CI, and update definitions to match 14.0-RC1. by
[@&#8203;asomers](https://togithub.com/asomers) in
[https://github.com/rust-lang/libc/pull/3355](https://togithub.com/rust-lang/libc/pull/3355)
- Use new check-cfg syntax in newer nightly by
[@&#8203;Urgau](https://togithub.com/Urgau) in
[https://github.com/rust-lang/libc/pull/3410](https://togithub.com/rust-lang/libc/pull/3410)
- musl fixes and musl+riscv32 fixes by
[@&#8203;akiernan](https://togithub.com/akiernan) in
[https://github.com/rust-lang/libc/pull/3302](https://togithub.com/rust-lang/libc/pull/3302)
- Add various constants from OpenBSD's sys/exec_elf.h. by
[@&#8203;ltratt](https://togithub.com/ltratt) in
[https://github.com/rust-lang/libc/pull/3409](https://togithub.com/rust-lang/libc/pull/3409)
- riscv64/musl: Add landlock syscalls by
[@&#8203;marv](https://togithub.com/marv) in
[https://github.com/rust-lang/libc/pull/3398](https://togithub.com/rust-lang/libc/pull/3398)
- Add stat64at function declaration to AIX by
[@&#8203;ecnelises](https://togithub.com/ecnelises) in
[https://github.com/rust-lang/libc/pull/3324](https://togithub.com/rust-lang/libc/pull/3324)
- adding getmntinfo/getmntvinfo for DragonFlyBSD. by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3394](https://togithub.com/rust-lang/libc/pull/3394)
- adding MOVE_MOUNT\* constants for linux to use with SYS_move_mount by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3391](https://togithub.com/rust-lang/libc/pull/3391)
- freebsd adding PROT_MAX|PROT_MAX_EXTRACT mmap flags by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3399](https://togithub.com/rust-lang/libc/pull/3399)
- linux/android adding few if_alg.h constants. by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3404](https://togithub.com/rust-lang/libc/pull/3404)
- Setup Dependabot for GitHub Actions by
[@&#8203;JohnTitor](https://togithub.com/JohnTitor) in
[https://github.com/rust-lang/libc/pull/3411](https://togithub.com/rust-lang/libc/pull/3411)
- For NetBSD: add entry for NetBSD/riscv64. by
[@&#8203;he32](https://togithub.com/he32) in
[https://github.com/rust-lang/libc/pull/3291](https://togithub.com/rust-lang/libc/pull/3291)
- adding more recent pthread_get/setname_np calls to
freebsd/dragonflybsd by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3412](https://togithub.com/rust-lang/libc/pull/3412)
- NetBSD/mipsel: add support. by
[@&#8203;he32](https://togithub.com/he32) in
[https://github.com/rust-lang/libc/pull/3416](https://togithub.com/rust-lang/libc/pull/3416)
- feat: add new constants from fanotify linux api by
[@&#8203;ad0](https://togithub.com/ad0) in
[https://github.com/rust-lang/libc/pull/3408](https://togithub.com/rust-lang/libc/pull/3408)
- linux: add PTRACE_GETSIGMASK and PTRACE_SETSIGMASK by
[@&#8203;mbyzhang](https://togithub.com/mbyzhang) in
[https://github.com/rust-lang/libc/pull/3163](https://togithub.com/rust-lang/libc/pull/3163)
- Add a few declarations for Apple systems by
[@&#8203;vincentisambart](https://togithub.com/vincentisambart) in
[https://github.com/rust-lang/libc/pull/3328](https://togithub.com/rust-lang/libc/pull/3328)
- feat: Added ifconf struct by
[@&#8203;Brijeshkrishna](https://togithub.com/Brijeshkrishna) in
[https://github.com/rust-lang/libc/pull/3393](https://togithub.com/rust-lang/libc/pull/3393)
- Upgrade Docker images to Ubuntu 23.10 by
[@&#8203;JohnTitor](https://togithub.com/JohnTitor) in
[https://github.com/rust-lang/libc/pull/3418](https://togithub.com/rust-lang/libc/pull/3418)
- redox: Add remaining `grp.h` functions by
[@&#8203;ids1024](https://togithub.com/ids1024) in
[https://github.com/rust-lang/libc/pull/3421](https://togithub.com/rust-lang/libc/pull/3421)
- netbsd/openbsd adding more accessors to siginfo_t. by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3400](https://togithub.com/rust-lang/libc/pull/3400)
- Prepare release for v0.2.150 by
[@&#8203;JohnTitor](https://togithub.com/JohnTitor) in
[https://github.com/rust-lang/libc/pull/3424](https://togithub.com/rust-lang/libc/pull/3424)

#### New Contributors

- [@&#8203;0xcaff](https://togithub.com/0xcaff) made their first
contribution in
[https://github.com/rust-lang/libc/pull/3376](https://togithub.com/rust-lang/libc/pull/3376)
- [@&#8203;he32](https://togithub.com/he32) made their first
contribution in
[https://github.com/rust-lang/libc/pull/3386](https://togithub.com/rust-lang/libc/pull/3386)
- [@&#8203;sthibaul](https://togithub.com/sthibaul) made their first
contribution in
[https://github.com/rust-lang/libc/pull/3389](https://togithub.com/rust-lang/libc/pull/3389)
- [@&#8203;BrandonMFong](https://togithub.com/BrandonMFong) made their
first contribution in
[https://github.com/rust-lang/libc/pull/3320](https://togithub.com/rust-lang/libc/pull/3320)
- [@&#8203;jdygert-spok](https://togithub.com/jdygert-spok) made their
first contribution in
[https://github.com/rust-lang/libc/pull/3406](https://togithub.com/rust-lang/libc/pull/3406)
- [@&#8203;Urgau](https://togithub.com/Urgau) made their first
contribution in
[https://github.com/rust-lang/libc/pull/3410](https://togithub.com/rust-lang/libc/pull/3410)
- [@&#8203;akiernan](https://togithub.com/akiernan) made their first
contribution in
[https://github.com/rust-lang/libc/pull/3302](https://togithub.com/rust-lang/libc/pull/3302)
- [@&#8203;marv](https://togithub.com/marv) made their first
contribution in
[https://github.com/rust-lang/libc/pull/3398](https://togithub.com/rust-lang/libc/pull/3398)
- [@&#8203;ad0](https://togithub.com/ad0) made their first contribution
in
[https://github.com/rust-lang/libc/pull/3408](https://togithub.com/rust-lang/libc/pull/3408)
- [@&#8203;vincentisambart](https://togithub.com/vincentisambart) made
their first contribution in
[https://github.com/rust-lang/libc/pull/3328](https://togithub.com/rust-lang/libc/pull/3328)

**Full Changelog**:
https://github.com/rust-lang/libc/compare/0.2.149...0.2.150

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4zMS41IiwidXBkYXRlZEluVmVyIjoiMzcuNDYuMCIsInRhcmdldEJyYW5jaCI6Im1hc3RlciJ9-->
2023-11-14 20:06:36 +00:00
GBA bot 323dbd8f01 Update lockfiles 2023-11-14 20:04:00 +00:00
renovate[bot] d1135d544d
Update Rust crate libc to 0.2.150 2023-11-14 20:03:31 +00:00
Gwilym Inzani d9f8e5f14f
Update Rust crate toml_edit to 0.21 (#515)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [toml_edit](https://togithub.com/toml-rs/toml) | dependencies | minor
| `0.20` -> `0.21` |

---

### Release Notes

<details>
<summary>toml-rs/toml (toml_edit)</summary>

###
[`v0.21.0`](https://togithub.com/toml-rs/toml/compare/v0.20.7...v0.21.0)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.20.7...v0.21.0)

###
[`v0.20.7`](https://togithub.com/toml-rs/toml/compare/v0.20.6...v0.20.7)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.20.6...v0.20.7)

###
[`v0.20.6`](https://togithub.com/toml-rs/toml/compare/v0.20.5...v0.20.6)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.20.5...v0.20.6)

###
[`v0.20.5`](https://togithub.com/toml-rs/toml/compare/v0.20.4...v0.20.5)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.20.4...v0.20.5)

###
[`v0.20.4`](https://togithub.com/toml-rs/toml/compare/v0.20.3...v0.20.4)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.20.3...v0.20.4)

###
[`v0.20.3`](https://togithub.com/toml-rs/toml/compare/v0.20.2...v0.20.3)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.20.2...v0.20.3)

###
[`v0.20.2`](https://togithub.com/toml-rs/toml/compare/v0.20.1...v0.20.2)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.20.1...v0.20.2)

###
[`v0.20.1`](https://togithub.com/toml-rs/toml/compare/v0.20.0...v0.20.1)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.20.0...v0.20.1)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40Ni4wIiwidXBkYXRlZEluVmVyIjoiMzcuNDYuMCIsInRhcmdldEJyYW5jaCI6Im1hc3RlciJ9-->
2023-11-14 20:00:46 +00:00
GBA bot cc0400e6a3 Update lockfiles 2023-11-09 20:10:08 +00:00
renovate[bot] 1f1de83564
Update Rust crate toml_edit to 0.21 2023-11-09 20:09:30 +00:00
Gwilym Inzani 198afdf8ce
Update Rust crate bindgen to 0.69 (#513)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [bindgen](https://rust-lang.github.io/rust-bindgen/)
([source](https://togithub.com/rust-lang/rust-bindgen)) |
build-dependencies | minor | `0.68` -> `0.69` |

---

### Release Notes

<details>
<summary>rust-lang/rust-bindgen (bindgen)</summary>

###
[`v0.69.0`](https://togithub.com/rust-lang/rust-bindgen/blob/HEAD/CHANGELOG.md#0690-2023-11-01)

[Compare
Source](https://togithub.com/rust-lang/rust-bindgen/compare/v0.68.1...v0.69.0)

#### Added

- Added the `ParseCallbacks::header_file` callback which runs on every
filename passed to `Builder::header`.
- Added the `CargoCallbacks::new` constructor which emits a cargo-rerun
line
    for every input header file by default.
- Added the `CargoCallbacks::rerun_on_header_files` method to configure
whether
    a cargo-rerun line should be emitted for every input header file.

#### Changed

- The `--wrap-static-fns` feature was updated so function types that has
no
    argument use `void` as its sole argument.
-   `CargoCallbacks` is no longer a [unit-like
struct](https://doc.rust-lang.org/reference/items/structs.html) and the
`CargoCallbacks` constant was added to mitigate the breaking nature of
this
change. This constant has been marked as deprecated and users will have
to
    use the new `CargoCallbacks::new` method in the future.

#### Removed

#### Fixed

-   Allow compiling `bindgen-cli` with a static libclang.
- Emit an opaque integer type for pointer types that don't have the same
size
    as the target's pointer size.
- Avoid escaping Objective-C method names unless they are `Self`,
`self`,
    `crate` or `super`.

#### Security

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4zMS41IiwidXBkYXRlZEluVmVyIjoiMzcuMzEuNSIsInRhcmdldEJyYW5jaCI6Im1hc3RlciJ9-->
2023-11-09 20:08:43 +00:00
GBA bot 7425afdf75 Update lockfiles 2023-11-01 19:22:41 +00:00
renovate[bot] f793ea4f01
Update Rust crate bindgen to 0.69 2023-11-01 19:22:02 +00:00
Gwilym Inzani 7c6eaf324b Release v0.18.0 2023-10-31 20:35:14 +00:00
Gwilym Inzani 9f2087735c
Add a symlink for the readme to the agb directory (#512)
This is an attempt to make the readme show up on crates.io

- [x] no changelog update needed
2023-10-31 20:20:15 +00:00
Gwilym Inzani fbd138a0cf Add a symlink for the readme to the agb directory
This is an attempt to make the readme show up on crates.io
2023-10-31 20:04:18 +00:00
Gwilym Inzani 95721e2b77
Update lockfiles (#509)
Build is getting slow, this seems to be a pretty good way to fix that

- [x] no changelog update needed
2023-10-26 22:40:52 +01:00
Gwilym Inzani e8eb216ff4 Update lockfiles 2023-10-26 22:27:19 +01:00
Gwilym Inzani 88eb89f821
Nicer instruments for dungeon puzzlers lament (#508)
Found some nice samples on http://legowelt.org/samples/ so decided to
put them in the dungeon puzzlers lament. Sounds a lot nicer now that I'm
not using pure square / saw waves :D

- [x] no changelog update needed
2023-10-26 21:24:15 +01:00
Gwilym Inzani 79184c9457 Delete the theme we're not using 2023-10-26 21:09:42 +01:00
Gwilym Inzani f345e6c46b Some nicer instruments for dpl 2023-10-26 21:09:26 +01:00
Gwilym Inzani 4199e22c5e
Fix the combo rom (#507)
Previously amplitude could not be played!
This will make sure that we don't mess up as easily as the old version.
2023-10-24 22:20:46 +01:00
Corwin afcce9bb1c
use a single structure for both the tile and game launch 2023-10-24 22:04:50 +01:00
Gwilym Inzani c47bef8983
Add clear and draw wide point functions to bitmap4 (#505)
- Adds a proper clear and draw wide point functions to bitmap4 for
consistency.
- I must save the bitmap modes from being removed
2023-10-24 21:57:02 +01:00
Corwin 4ad93d134e
fix the combo rom 2023-10-24 21:39:05 +01:00
Gwilym Inzani df716a9d9a
Add missing #[cfg(test)] (#506)
Linter updates caused it to start complaining.

- [x] no changelog update needed
2023-10-24 20:42:44 +01:00
Gwilym Inzani 85a8540d44 Add missing #[cfg(test)] 2023-10-24 20:22:43 +01:00
xokz fdab4a3e6f
Update bitmap4.rs 2023-10-23 17:28:22 -04:00
xokz fe90d4d8d7
Update bitmap4.rs 2023-10-23 17:26:20 -04:00
Gwilym Inzani b3693401b6
Allow TileSetting palette to be set (#502)
This PR adds the ability for a palette to be set on a TileSetting
struct. This is useful when doing more advanced palette tricks on a
background. For example, changing the palette for only a portion of a
background or manually managing screen palettes.

- [x] Changelog updated
2023-10-21 14:15:30 +01:00
Brandon Atkinson 2f1ad07e43 allow TileSetting palette to be set 2023-10-18 23:28:13 -06:00
Gwilym Inzani 1a468e7b55
Fixing up the linker scripts (#503)
* Builds upon #501 with related improvements we wanted to make.
* Fixes multiboot to work, and to work on mgba.
* Remove the need for copying the linker scripts into your repo


- [x] Changelog updated
2023-10-18 13:12:06 +01:00
Gwilym Inzani 469db44ad1 Correct the pluralisation 2023-10-18 12:28:41 +01:00
Gwilym Inzani 4ed2ea3784 Move the linkers scripts to the src directory so agb itself can change its script 2023-10-18 12:26:50 +01:00
Gwilym Inzani 721aba3c76 Remove linker script consistency checks and helpers 2023-10-18 12:09:01 +01:00
Gwilym Inzani 00631b2166 Delete all the gba.ld files 2023-10-18 12:08:25 +01:00
Gwilym Inzani eff075f50b Remove the need for a linker script and move multiboot to a feature 2023-10-18 12:08:12 +01:00
Corwin 0e0cc6f909
update changelog to include linker script changes 2023-10-18 00:48:10 +01:00
Corwin 41e192eff2
set interrupt handler to its own section 2023-10-18 00:17:24 +01:00
Gwilym Inzani 48b9eb3775 Update all the remaining linker scripts 2023-10-17 23:52:04 +01:00
Gwilym Inzani ce233f7d62 Always check the address to make sure that things work as expected 2023-10-17 23:51:40 +01:00
Gwilym Inzani 5feb67285d Add a test that multiboot works 2023-10-17 23:49:57 +01:00
Gwilym Inzani aa33a46919 Remove trailing spaces 2023-10-17 23:45:08 +01:00
Gwilym Inzani 41bda0036f Make sure mgba recognises this as a GBA rom 2023-10-17 23:44:48 +01:00
Gwilym Inzani c9c8d9e879 Don't put the entrypoint in the .text section 2023-10-17 23:22:04 +01:00
Gwilym Inzani 1c0e9f9a2a Maybe get multiboot to work? 2023-10-17 23:15:51 +01:00
Gwilym Inzani ec6774ca6b Split into regular, multiboot and common 2023-10-17 23:14:18 +01:00
Gwilym Inzani 243e810150 Rename crt0 section to entrypoint 2023-10-17 22:22:48 +01:00
Gwilym Inzani 7afa19965c Rename to entrypoint.s 2023-10-17 22:12:50 +01:00
Corwin 8091e22b10
use macro for the grabbing linker variable 2023-10-17 22:09:15 +01:00
Corwin 0b747508a8
fixup the multiboot 2023-10-17 21:54:54 +01:00
Corwin 8e547c6783
derive the data ends 2023-10-17 21:53:50 +01:00
Corwin f7434a4bf3
run linker script update script 2023-10-17 20:29:12 +01:00
jmaargh 4a13d52faf Resolve TODOs about linker symbols 2023-10-16 22:50:53 +01:00
jmaargh 7a1f554b72 Fix symbols for RAM section locations
Using the ld functions is not only more readable, but more accurate.
Previous use of the `.` variable could occasionally have off-by-one
errors.
2023-10-16 22:46:27 +01:00
jmaargh 9040844854 Reserve IWRAM space for BIOS use 2023-10-16 22:45:59 +01:00
Corwin cd6e8d1346
Fix cos term (#498)
One of the finer cosine terms was not correct. By using the num macro
(not available at the time of this functions initial writing) we can
avoid issues of incorrect constants.

Fixes #497

- [x] Changelog updated
2023-10-10 20:14:51 +01:00
Corwin 09331d1cb5
make 16 bit precision work 2023-10-09 19:16:24 +01:00
Corwin 71e680f365
update changelog 2023-10-08 15:04:57 +01:00
Corwin e894367c52
use proper implementation of cos to check against 2023-10-08 14:56:32 +01:00
Corwin 548dd9ff67
fix cos function 2023-10-08 14:23:04 +01:00
Corwin 539caf7ad9
add test showing inaccuracy 2023-10-08 14:22:50 +01:00
Gwilym Inzani 5dbf13d4b9
Update Rust crate libc to 0.2.149 (#494)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [libc](https://togithub.com/rust-lang/libc) | dependencies | patch |
`0.2.148` -> `0.2.149` |

---

### Release Notes

<details>
<summary>rust-lang/libc (libc)</summary>

###
[`v0.2.149`](https://togithub.com/rust-lang/libc/releases/tag/0.2.149)

[Compare
Source](https://togithub.com/rust-lang/libc/compare/0.2.148...0.2.149)

#### What's Changed

- libc 0.2.148 by
[@&#8203;joshtriplett](https://togithub.com/joshtriplett) in
[https://github.com/rust-lang/libc/pull/3351](https://togithub.com/rust-lang/libc/pull/3351)
- update libc-test and its libc dependency to 0.2.148 by
[@&#8203;chenx97](https://togithub.com/chenx97) in
[https://github.com/rust-lang/libc/pull/3314](https://togithub.com/rust-lang/libc/pull/3314)
- Disable 1.13 CI by [@&#8203;JohnTitor](https://togithub.com/JohnTitor)
in
[https://github.com/rust-lang/libc/pull/3358](https://togithub.com/rust-lang/libc/pull/3358)
- Add teeos libc by
[@&#8203;Sword-Destiny](https://togithub.com/Sword-Destiny) in
[https://github.com/rust-lang/libc/pull/3333](https://togithub.com/rust-lang/libc/pull/3333)
- Added SIOCSIFNAME by
[@&#8203;Brijeshkrishna](https://togithub.com/Brijeshkrishna) in
[https://github.com/rust-lang/libc/pull/3354](https://togithub.com/rust-lang/libc/pull/3354)
- copyfile apple api update by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3346](https://togithub.com/rust-lang/libc/pull/3346)
- Hermit updates by [@&#8203;mkroening](https://togithub.com/mkroening)
in
[https://github.com/rust-lang/libc/pull/3348](https://togithub.com/rust-lang/libc/pull/3348)
- Add the LoongArch64 HWCAP values by
[@&#8203;heiher](https://togithub.com/heiher) in
[https://github.com/rust-lang/libc/pull/3344](https://togithub.com/rust-lang/libc/pull/3344)
- Add F_PUNCHHOLE and fpunchhole_t by
[@&#8203;anacrolix](https://togithub.com/anacrolix) in
[https://github.com/rust-lang/libc/pull/3337](https://togithub.com/rust-lang/libc/pull/3337)
- Fix compatibility with Emscripten >= 3.1.44 by
[@&#8203;kleisauke](https://togithub.com/kleisauke) in
[https://github.com/rust-lang/libc/pull/3308](https://togithub.com/rust-lang/libc/pull/3308)
- freebsd adding few mmap constants related to page alignment by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3326](https://togithub.com/rust-lang/libc/pull/3326)
- Redox pthreads by [@&#8203;4lDO2](https://togithub.com/4lDO2) in
[https://github.com/rust-lang/libc/pull/3347](https://togithub.com/rust-lang/libc/pull/3347)
- linux MADV_COLLAPSE addition by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3340](https://togithub.com/rust-lang/libc/pull/3340)
- android adding few more pthread api calls. by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3288](https://togithub.com/rust-lang/libc/pull/3288)
- Declare `pthread_attr_setguardsize` and `pthread_attr_getstacksize`.
by [@&#8203;sunfishcode](https://togithub.com/sunfishcode) in
[https://github.com/rust-lang/libc/pull/3330](https://togithub.com/rust-lang/libc/pull/3330)
- Add missing PS Vita definitions, fix some unused ones by
[@&#8203;pheki](https://togithub.com/pheki) in
[https://github.com/rust-lang/libc/pull/3284](https://togithub.com/rust-lang/libc/pull/3284)
- Drop `armv7-apple-ios` target support by
[@&#8203;JohnTitor](https://togithub.com/JohnTitor) in
[https://github.com/rust-lang/libc/pull/3362](https://togithub.com/rust-lang/libc/pull/3362)
- backtrace definitions and support for getmntinfo and getvfsstat by
[@&#8203;0323pin](https://togithub.com/0323pin) in
[https://github.com/rust-lang/libc/pull/3368](https://togithub.com/rust-lang/libc/pull/3368)
- apple fcntl update. by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3365](https://togithub.com/rust-lang/libc/pull/3365)
- Added socketpair and pipe2 for Vita target by
[@&#8203;nikarh](https://togithub.com/nikarh) in
[https://github.com/rust-lang/libc/pull/3366](https://togithub.com/rust-lang/libc/pull/3366)
- Added additional Ethernet Protocol Ids for fuchsia by
[@&#8203;w1redch4d](https://togithub.com/w1redch4d) in
[https://github.com/rust-lang/libc/pull/3332](https://togithub.com/rust-lang/libc/pull/3332)
- timerfd api for freebsd 14. by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3341](https://togithub.com/rust-lang/libc/pull/3341)
- haiku adding pthread GNU part by
[@&#8203;devnexen](https://togithub.com/devnexen) in
[https://github.com/rust-lang/libc/pull/3364](https://togithub.com/rust-lang/libc/pull/3364)
- add execveat for glibc by
[@&#8203;SteveLauC](https://togithub.com/SteveLauC) in
[https://github.com/rust-lang/libc/pull/3372](https://togithub.com/rust-lang/libc/pull/3372)
- added support for GNU/Hurd by
[@&#8203;Vtewari2311](https://togithub.com/Vtewari2311) in
[https://github.com/rust-lang/libc/pull/3325](https://togithub.com/rust-lang/libc/pull/3325)
- Fix apple tvos support by
[@&#8203;lcruz99](https://togithub.com/lcruz99) in
[https://github.com/rust-lang/libc/pull/3370](https://togithub.com/rust-lang/libc/pull/3370)
- Remove deprecation from SA_ONSTACK; fix hexagon-unknown-linux-musl by
[@&#8203;androm3da](https://togithub.com/androm3da) in
[https://github.com/rust-lang/libc/pull/3335](https://togithub.com/rust-lang/libc/pull/3335)
- feat: add close_range for glibc by
[@&#8203;SteveLauC](https://togithub.com/SteveLauC) in
[https://github.com/rust-lang/libc/pull/3373](https://togithub.com/rust-lang/libc/pull/3373)
- Update crate version to 0.2.149 by
[@&#8203;nikarh](https://togithub.com/nikarh) in
[https://github.com/rust-lang/libc/pull/3360](https://togithub.com/rust-lang/libc/pull/3360)

#### New Contributors

- [@&#8203;Sword-Destiny](https://togithub.com/Sword-Destiny) made their
first contribution in
[https://github.com/rust-lang/libc/pull/3333](https://togithub.com/rust-lang/libc/pull/3333)
- [@&#8203;Brijeshkrishna](https://togithub.com/Brijeshkrishna) made
their first contribution in
[https://github.com/rust-lang/libc/pull/3354](https://togithub.com/rust-lang/libc/pull/3354)
- [@&#8203;anacrolix](https://togithub.com/anacrolix) made their first
contribution in
[https://github.com/rust-lang/libc/pull/3337](https://togithub.com/rust-lang/libc/pull/3337)
- [@&#8203;4lDO2](https://togithub.com/4lDO2) made their first
contribution in
[https://github.com/rust-lang/libc/pull/3347](https://togithub.com/rust-lang/libc/pull/3347)
- [@&#8203;pheki](https://togithub.com/pheki) made their first
contribution in
[https://github.com/rust-lang/libc/pull/3284](https://togithub.com/rust-lang/libc/pull/3284)
- [@&#8203;0323pin](https://togithub.com/0323pin) made their first
contribution in
[https://github.com/rust-lang/libc/pull/3368](https://togithub.com/rust-lang/libc/pull/3368)
- [@&#8203;w1redch4d](https://togithub.com/w1redch4d) made their first
contribution in
[https://github.com/rust-lang/libc/pull/3332](https://togithub.com/rust-lang/libc/pull/3332)
- [@&#8203;Vtewari2311](https://togithub.com/Vtewari2311) made their
first contribution in
[https://github.com/rust-lang/libc/pull/3325](https://togithub.com/rust-lang/libc/pull/3325)
- [@&#8203;lcruz99](https://togithub.com/lcruz99) made their first
contribution in
[https://github.com/rust-lang/libc/pull/3370](https://togithub.com/rust-lang/libc/pull/3370)

**Full Changelog**:
https://github.com/rust-lang/libc/compare/0.2.148...0.2.149

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4wLjMiLCJ1cGRhdGVkSW5WZXIiOiIzNy4wLjMiLCJ0YXJnZXRCcmFuY2giOiJtYXN0ZXIifQ==-->
2023-10-07 21:58:25 +01:00
GBA bot c4116aeade Update lockfiles 2023-10-07 20:35:21 +00:00
renovate[bot] 994a36fdd8
Update Rust crate libc to 0.2.149 2023-10-07 20:34:42 +00:00
Gwilym Inzani 3f225a2b59
Fix clippy lint 2023/10/07 (#495)
Fix the most recent batch of clippy lints

- [x] no changelog update needed
2023-10-07 20:54:52 +01:00
Gwilym Inzani 534a357d85 Add another missing import 2023-10-07 20:39:13 +01:00
Gwilym Inzani 7454563325 Tests must come at the end 2023-10-07 20:28:09 +01:00
Gwilym Inzani 845e3d027a Remove pointless import 2023-10-07 20:27:36 +01:00
Gwilym Inzani 426890e856 Don't manually implement hash_one 2023-10-07 20:26:10 +01:00
Gwilym Inzani 53685b0410 Release v0.17.1 2023-10-05 22:18:04 +01:00
Gwilym Inzani 2a6234bab7 Add a changelog entry for 0.17.1 2023-10-05 22:14:25 +01:00
Gwilym Inzani f6fdcc8991
Update Cargo.toml files so docs.rs is happy (#492)
docs.rs is unhappy. I've updated the cargo-args so that it builds
correctly. Tested locally and it works with this change.

- [x] no changelog update needed
2023-10-04 16:51:19 +01:00
Gwilym Inzani c280316fa2 Update Cargo.toml files so docs.rs is happy 2023-10-04 16:36:46 +01:00
Gwilym Inzani cc6807fcd2 Update agb-tracker for dpl 2023-10-03 22:58:38 +01:00
Gwilym Inzani 3dddf9761d Ensure the tracker gets updated too 2023-10-03 22:48:06 +01:00
Gwilym Inzani f3e3b6a244 Update agb-tracker to version 0.17 2023-10-03 22:47:30 +01:00
Gwilym Inzani b6916d7e74 Release v0.17.0 2023-10-03 22:33:10 +01:00
Gwilym Inzani c6e98ea2dd Update lockfiles 2023-10-03 22:23:24 +01:00
Corwin a909edd3d1
Corrected position of fix (#488) 2023-09-28 22:48:14 +01:00
Corwin 3cebb5c3e8
fix.. again.. 2023-09-28 22:37:28 +01:00
Corwin ce12ca20a4
corrected position of fix 2023-09-28 22:31:21 +01:00
Corwin fc721ea060
Bitmap4 fix (#487)
Expands on #486 by updating example and updating changelog.

- [x] Changelog updated
2023-09-28 21:35:21 +01:00
Corwin e2bff6dfff
update changelog 2023-09-28 21:20:56 +01:00
Corwin 74ccdfcd7f
update example to excersise the broken case 2023-09-28 21:19:07 +01:00
xokz 575976bf52
Update bitmap4.rs 2023-09-28 15:03:24 -04:00
xokz cf80e313b1
Update bitmap4.rs
colors of lower values can now overwrite colors of higher values.
2023-09-28 14:46:32 -04:00
Gwilym Inzani 3539bf2fdc
Update actions/checkout digest to 8ade135 (#485)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [actions/checkout](https://togithub.com/actions/checkout) | action |
digest | `3df4ab1` -> `8ade135` |

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNi45Ny4xIiwidXBkYXRlZEluVmVyIjoiMzYuOTcuMSIsInRhcmdldEJyYW5jaCI6Im1hc3RlciJ9-->
2023-09-26 21:27:10 +01:00
GBA bot 2516a6f831 Update lockfiles 2023-09-26 20:25:56 +00:00
Gwilym Inzani 4ef019f183 Refer to v4 instead 2023-09-26 21:23:56 +01:00
GBA bot 81aae96d18 Update lockfiles 2023-09-22 18:27:01 +00:00
renovate[bot] 57ea649549
Update actions/checkout digest to 8ade135 2023-09-22 18:26:22 +00:00
Corwin b670ad4a1e
Add ice and movable blocks (#476) 2023-09-14 14:58:41 +02:00
Corwin 8283924c39
Update Rust crate toml_edit to 0.20 (#482)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [toml_edit](https://togithub.com/toml-rs/toml) | dependencies | minor
| `0.19` -> `0.20` |

---

### Release Notes

<details>
<summary>toml-rs/toml (toml_edit)</summary>

###
[`v0.20.0`](https://togithub.com/toml-rs/toml/compare/v0.19.15...v0.20.0)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.19.15...v0.20.0)

###
[`v0.19.15`](https://togithub.com/toml-rs/toml/compare/v0.19.14...v0.19.15)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.19.14...v0.19.15)

###
[`v0.19.14`](https://togithub.com/toml-rs/toml/compare/v0.19.13...v0.19.14)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.19.13...v0.19.14)

###
[`v0.19.13`](https://togithub.com/toml-rs/toml/compare/v0.19.12...v0.19.13)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.19.12...v0.19.13)

###
[`v0.19.12`](https://togithub.com/toml-rs/toml/compare/v0.19.11...v0.19.12)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.19.11...v0.19.12)

###
[`v0.19.11`](https://togithub.com/toml-rs/toml/compare/v0.19.10...v0.19.11)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.19.10...v0.19.11)

###
[`v0.19.10`](https://togithub.com/toml-rs/toml/compare/v0.19.9...v0.19.10)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.19.9...v0.19.10)

###
[`v0.19.9`](https://togithub.com/toml-rs/toml/compare/v0.19.8...v0.19.9)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.19.8...v0.19.9)

###
[`v0.19.8`](https://togithub.com/toml-rs/toml/compare/v0.19.7...v0.19.8)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.19.7...v0.19.8)

###
[`v0.19.7`](https://togithub.com/toml-rs/toml/compare/v0.19.6...v0.19.7)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.19.6...v0.19.7)

###
[`v0.19.6`](https://togithub.com/toml-rs/toml/compare/v0.19.5...v0.19.6)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.19.5...v0.19.6)

###
[`v0.19.5`](https://togithub.com/toml-rs/toml/compare/v0.19.4...v0.19.5)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.19.4...v0.19.5)

###
[`v0.19.4`](https://togithub.com/toml-rs/toml/compare/v0.19.3...v0.19.4)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.19.3...v0.19.4)

###
[`v0.19.3`](https://togithub.com/toml-rs/toml/compare/v0.19.2...v0.19.3)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.19.2...v0.19.3)

###
[`v0.19.2`](https://togithub.com/toml-rs/toml/compare/v0.19.1...v0.19.2)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.19.1...v0.19.2)

###
[`v0.19.1`](https://togithub.com/toml-rs/toml/compare/v0.19.0...v0.19.1)

[Compare
Source](https://togithub.com/toml-rs/toml/compare/v0.19.0...v0.19.1)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNi44My4wIiwidXBkYXRlZEluVmVyIjoiMzYuODMuMCIsInRhcmdldEJyYW5jaCI6Im1hc3RlciJ9-->
2023-09-14 14:54:25 +02:00
Corwin 0e5063a9f0
Merge remote-tracking branch 'upstream/master' into dungeon/simulation 2023-09-14 13:50:00 +01:00
GBA bot 226fdf63c9 Update lockfiles 2023-09-14 12:40:22 +00:00
renovate[bot] 74df6db8a9
Update Rust crate toml_edit to 0.20 2023-09-14 12:39:40 +00:00
Corwin f0f58741b0
Add safety comments to public unsafe functions (#484)
- [x] Changelog updated / no changelog update needed
2023-09-14 14:38:45 +02:00
Corwin 473181718b
remove outer loop 2023-09-14 13:28:00 +01:00
Corwin c12ae4b5d9
add safety comments to public unsafe functions 2023-09-14 12:44:34 +01:00
Corwin 71559a28d2
Update Rust crate libc to 0.2.148 (#483)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [libc](https://togithub.com/rust-lang/libc) | dependencies | patch |
`0.2.147` -> `0.2.148` |

---

### Release Notes

<details>
<summary>rust-lang/libc (libc)</summary>

###
[`v0.2.148`](https://togithub.com/rust-lang/libc/compare/0.2.147...0.2.148)

[Compare
Source](https://togithub.com/rust-lang/libc/compare/0.2.147...0.2.148)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNi44My4wIiwidXBkYXRlZEluVmVyIjoiMzYuODMuMCIsInRhcmdldEJyYW5jaCI6Im1hc3RlciJ9-->
2023-09-14 13:30:12 +02:00
Corwin 6a8106977d
run tests for dpl in ci 2023-09-14 12:29:13 +01:00
GBA bot c7540a440d Update lockfiles 2023-09-13 13:17:49 +00:00
renovate[bot] 8828137aeb
Update Rust crate libc to 0.2.148 2023-09-13 13:17:10 +00:00
Gwilym Inzani ece557ed56
Update Rust crate bindgen to 0.68 (#481)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [bindgen](https://rust-lang.github.io/rust-bindgen/)
([source](https://togithub.com/rust-lang/rust-bindgen)) |
build-dependencies | minor | `0.66` -> `0.68` |

---

### Release Notes

<details>
<summary>rust-lang/rust-bindgen (bindgen)</summary>

###
[`v0.68.1`](https://togithub.com/rust-lang/rust-bindgen/blob/HEAD/CHANGELOG.md#0681)

[Compare
Source](https://togithub.com/rust-lang/rust-bindgen/compare/v0.68.0...v0.68.1)

#### Fixed

-   Fixed errors on the windows artifact build process.

###
[`v0.68.0`](https://togithub.com/rust-lang/rust-bindgen/blob/HEAD/CHANGELOG.md#0680)

[Compare
Source](https://togithub.com/rust-lang/rust-bindgen/compare/v0.66.1...v0.68.0)

#### Added

- The `system` ABI is now supported as an option for the
`--override-abi` flag.
- The `allowlist_item` method and the `--allowlist-item` flag have been
    included to filter items regardless or their kind.
-   Include installers as release artifacts on Github.

#### Changed

- The `Clone` implementation for `_BindgenUnionField` has been changed
to pass
    the `incorrect_clone_impl_on_copy_type` Clippy lint.
- The `c_unwind` ABI can be used without a feature gate for any Rust
target version
    equal to or greater than 1.71.
    This comes as a result of the ABI being stabilised (in Rust 1.71).
- Formatting changes when using prettyplease as a formatter due to a new
    prettyplease version.
- Avoid generating invalid `CStr` constants when using the
`--generate-cstr`
    option.

#### Removed

- The `extra_assert` and `extra_assert_eq` macros are no longer
exported.

#### Fixed

- Bindgen no longer panics when parsing an objective-C header that
includes a
Rust keyword that cannot be a raw identifier, such as: `self`, `crate`,
    `super` or `Self`.

###
[`v0.66.1`](https://togithub.com/rust-lang/rust-bindgen/blob/HEAD/CHANGELOG.md#0661)

[Compare
Source](https://togithub.com/rust-lang/rust-bindgen/compare/v0.66.0...v0.66.1)

#### Removed

- Revert source order sorting
([#&#8203;2543](https://togithub.com/rust-lang/rust-bindgen/issues/2543))
due to correctness regressions
[#&#8203;2558](https://togithub.com/rust-lang/rust-bindgen/issues/2558).

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNi44My4wIiwidXBkYXRlZEluVmVyIjoiMzYuODMuMCIsInRhcmdldEJyYW5jaCI6Im1hc3RlciJ9-->
2023-09-12 14:28:29 +01:00
GBA bot 17a62bf0f2 Update lockfiles 2023-09-06 21:29:51 +00:00
renovate[bot] f2a407975b
Update Rust crate bindgen to 0.68 2023-09-06 21:29:19 +00:00
Gwilym Inzani 7edc6d16ab
Use 32768Hz for the tracker (#479)
Sounds way better and we can get away with it in DPL

- [x]  no changelog update needed
2023-09-06 09:56:28 +01:00
Gwilym Inzani 0900121273 Update docs 2023-09-06 09:41:13 +01:00
Gwilym Inzani 9350027fa2
Make image converter produce tile sets (#480)
Removes loads of duplicated code. There's no reason why this couldn't
create regular tile sets.

- [x] Changelog updated
2023-09-06 09:40:17 +01:00
Gwilym Inzani 5b3248ec5a Massively improve the code generation around tile sizes 2023-09-06 08:51:47 +01:00
Gwilym Inzani ed2e7dec5c Let rust do the register allocation 2023-09-06 08:34:14 +01:00
Gwilym Inzani bb57298c54 This has better code generation 2023-09-06 00:37:23 +01:00
Gwilym Inzani 77445b304f Custom assembly as thumb 2023-09-06 00:23:01 +01:00
Gwilym Inzani e504b93fe3 Write a custom tile copy command 2023-09-05 23:52:35 +01:00
Gwilym Inzani c04d674101 Extend changelog entry to allow for tile set 2023-09-05 23:24:53 +01:00
Gwilym Inzani 0c19988699 Use 32768Hz for the tracker 2023-09-05 23:22:50 +01:00
Corwin 11fc38d840
report mismatch counts 2023-09-05 23:02:49 +01:00
Corwin 5fc302dec9
make names better 2023-09-05 22:53:10 +01:00
Corwin 962b503751
test all the levels 2023-09-05 22:52:10 +01:00
Gwilym Inzani ff4154699a
Update actions/checkout action to v4 (#478)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [actions/checkout](https://togithub.com/actions/checkout) | action |
major | `v3` -> `v4` |

---

### Release Notes

<details>
<summary>actions/checkout (actions/checkout)</summary>

###
[`v4`](https://togithub.com/actions/checkout/blob/HEAD/CHANGELOG.md#v400)

[Compare Source](https://togithub.com/actions/checkout/compare/v3...v4)

- [Support fetching without the --progress
option](https://togithub.com/actions/checkout/pull/1067)
-   [Update to node20](https://togithub.com/actions/checkout/pull/1436)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNi43OC44IiwidXBkYXRlZEluVmVyIjoiMzYuNzguOCIsInRhcmdldEJyYW5jaCI6Im1hc3RlciJ9-->
2023-09-05 20:06:18 +01:00
GBA bot ab07ed31db Update lockfiles 2023-09-04 12:36:38 +00:00
renovate[bot] c0964d23b1
Update actions/checkout action to v4 2023-09-04 12:35:54 +00:00
Corwin 98d2dc0022
another simple snail level 2023-09-02 18:32:02 +01:00
Corwin cc5e805d82
show movement options of the snail 2023-09-01 22:43:09 +01:00
Corwin 832605ff22
improve snail sprites 2023-09-01 21:42:09 +01:00
Corwin 9757608ab4
add snail rotator 2023-09-01 17:56:50 +01:00
Corwin a97248cd68
add hole and rotating enemy 2023-09-01 00:42:43 +01:00
Gwilym Inzani 7431086b14 Try using memcpy4 for copying the tile data 2023-08-31 07:53:08 +01:00
Gwilym Inzani d3c32ce351 Minor optimisation for the show entire screen case 2023-08-31 07:53:01 +01:00
Corwin 73a0b482a5
fix unintended solution 2023-08-30 19:55:43 +01:00
Corwin 1bcbeb056e
more advanced movement system 2023-08-30 17:43:24 +01:00
Gwilym Inzani 4642a74a0f Update the examples with the new tileset importing 2023-08-30 17:07:14 +01:00
Gwilym Inzani 2c556f9ce8 Fix docs for real this time 2023-08-30 17:02:06 +01:00
Gwilym Inzani dc04785669 Fix doc examples 2023-08-30 16:46:05 +01:00
Gwilym Inzani 11fe4d92ac Delete the old toml file 2023-08-30 16:25:16 +01:00
Gwilym Inzani 3a1f8ed8ed Add a convienence fill_with method 2023-08-30 16:22:55 +01:00
Gwilym Inzani f0ddfc96b4 Reference the TRANSPARENT_TILE_INDEX in the definition of BLANK 2023-08-30 16:18:08 +01:00
Gwilym Inzani 6853d36a9c Dynamic tile can also return the setting directly 2023-08-30 16:14:51 +01:00
Gwilym Inzani 5cfa64030a Generate the tileset directly 2023-08-30 16:08:43 +01:00
Corwin 025e76b8bd
you can only turn around if this is your first movement 2023-08-30 00:55:25 +01:00
Corwin c142184bc0
add ice levels 2023-08-30 00:54:00 +01:00
Corwin b29fc6bb6c
update laments 2023-08-30 00:53:31 +01:00
Corwin 20794d152c
a more basic ice level 2023-08-30 00:49:46 +01:00
Corwin c44b131d73
another not so good ice level 2023-08-30 00:43:39 +01:00
Corwin cfa846ddd3
add both levels 2023-08-30 00:08:57 +01:00
Corwin a0b87d50c6
I have no idea what I have just made 2023-08-30 00:08:57 +01:00
Corwin 45a9dbfeac
fix block pushing on ice 2023-08-30 00:08:57 +01:00
Gwilym Inzani 7f10cdb869 Less square 2023-08-29 23:54:58 +01:00
Gwilym Inzani c784cd759c Level with multiple ice 2023-08-29 23:52:51 +01:00
Corwin 36e8fca49a
really bad ice level 2023-08-29 23:36:30 +01:00
Corwin 0b24fdebd0
teleporters are on the ground 2023-08-29 23:10:09 +01:00
Corwin 50495d88b7
remove cheese 2023-08-29 23:10:09 +01:00
Gwilym Inzani f357787711 Neaten up the slime_teleporter a little 2023-08-29 23:08:17 +01:00
Corwin 32eee32fb1
make teleporter_2 better 2023-08-29 22:58:59 +01:00
Gwilym Inzani 3c08880b5d add a slime + teleport level 2023-08-29 22:57:09 +01:00
Corwin 45059029fa
another teleporter level 2023-08-29 22:56:05 +01:00
Gwilym Inzani be316a305b BAD CORWIN! 2023-08-29 22:35:41 +01:00
Corwin b78f7345b9
replace existing animation for pushed entity 2023-08-29 22:32:03 +01:00
Corwin f3d0757fa3
squid hero phasing 2023-08-29 22:28:00 +01:00
Corwin 36e912bcb0
nothing should get killed from overlapping the hero 2023-08-29 22:28:00 +01:00
Gwilym Inzani 7af1b01006 Add a level where a squid teleports 2023-08-29 22:26:47 +01:00
Gwilym Inzani a8e8f30f91 Remove invalid solution for glove_key 2023-08-29 22:26:19 +01:00
Corwin 7d907d014f
the check should be for one entity 2023-08-29 22:03:42 +01:00
Corwin b7c10742af
add teleporter to build.rs 2023-08-29 21:58:02 +01:00
Corwin da89a8a6cb
add teleporter shadow 2023-08-29 21:53:10 +01:00
Gwilym Inzani 8cb4f0c40f Make the reason the solution works not the wall 2023-08-29 21:47:40 +01:00
Gwilym Inzani 657637aa8e Make just rocks more interesting 2023-08-29 21:47:40 +01:00
Corwin 70cbc7a608
ignore tiled session 2023-08-29 21:45:11 +01:00
Corwin 712301bd2e
teleporter level 2023-08-29 21:45:11 +01:00
Corwin 8b8f94ae7f
teleporters 2023-08-29 21:45:11 +01:00
Gwilym Inzani 2ce7d91c74 Add a level with just rocks 2023-08-29 21:43:37 +01:00
Gwilym Inzani 86607eeab0 Glove and key 2023-08-29 21:33:21 +01:00
Corwin df2f45797b
only hero and squid can pick up items 2023-08-29 21:31:36 +01:00
Corwin 07c5afb990
add teleporter entity type 2023-08-29 21:24:30 +01:00
Gwilym Inzani a7cbb60b20 Add a squid rock level 2023-08-29 21:13:57 +01:00
Corwin 98c96080f9
environment variable to run specific level 2023-08-29 21:11:58 +01:00
Corwin 56f1b68055
allow with justification 2023-08-29 21:01:35 +01:00
Corwin 078f4f22a9
make obtuse return values understandable 2023-08-29 20:59:03 +01:00
Gwilym Inzani 15d075a1c8 Maybe we'll have this many levels one day 2023-08-29 20:56:29 +01:00
Gwilym Inzani fef393c39c We can now make a lot more levels 2023-08-29 20:54:31 +01:00
Gwilym Inzani f72ff39867 Make the spikes more obvious 2023-08-29 20:52:09 +01:00
Corwin 346f62f328
resolve overlaps after all moves 2023-08-29 20:52:07 +01:00
Gwilym Inzani d781a41357 Add teleporter 2023-08-29 20:38:02 +01:00
Corwin b5da20d748
blocks can't intersect heros or enemies 2023-08-29 20:11:55 +01:00
Gwilym Inzani dc5bf9de98
Deduplicate background tiles (#477)
This started as an attempt to get dungeon puzzler in the combo rom,
ended up fixing a _load_ of 256 colour bugs and the ability to
deduplicate tiles you import.

Fixes #448

- [x] Changelog updated / no changelog update needed
2023-08-29 20:02:38 +01:00
Gwilym Inzani 6422ed63f1 Give purple night the deduplication treatment 2023-08-29 16:33:11 +01:00
Gwilym Inzani 54237c0fce Remove trailing whitespace 2023-08-29 16:28:57 +01:00
Gwilym Inzani 345a27a7d9 Remove useless cast 2023-08-29 16:25:16 +01:00
Gwilym Inzani b25ebf4a94 Add a changelog entry about the new flip methods 2023-08-29 16:21:28 +01:00
Gwilym Inzani 9abfa7f8e1 Update documentation 2023-08-29 16:20:54 +01:00
Gwilym Inzani eede8c3719 Add changelog entries 2023-08-29 16:19:15 +01:00
Gwilym Inzani 3eb7aabe37 Add dungeon puzzler to combo 2023-08-29 16:17:14 +01:00
Gwilym Inzani b5991d3ccc Copy all the tiles for a 256 colour map 2023-08-29 16:14:05 +01:00
Gwilym Inzani a865240308 Start fixing 256 colours 2023-08-29 16:07:50 +01:00
Gwilym Inzani 9db4230aee Better error if we run out of VRam 2023-08-29 15:34:07 +01:00
Gwilym Inzani c25cd74f43 Correctly use deduplication for combo rom 2023-08-29 15:20:41 +01:00
Gwilym Inzani c9bf56755a Also deduplicate for the dungeon puzzler 2023-08-29 15:17:50 +01:00
Gwilym Inzani a73e817f02 Deduplicate everything in hatwiz 2023-08-29 15:05:57 +01:00
Gwilym Inzani 201a127673 Use deduplicated tiles for hatwiz splash screens 2023-08-29 14:55:23 +01:00
Gwilym Inzani b39f99990c Use deduplication in hyperspace roll 2023-08-29 14:52:20 +01:00
Gwilym Inzani 6d56e72d66 Fix palette assignment 2023-08-29 14:39:41 +01:00
Gwilym Inzani 3d7d3f25a2 Update agb repo 2023-08-29 14:13:40 +01:00
Gwilym Inzani b5af3a3aff Generate tile settings instead of palette assignments 2023-08-29 14:07:19 +01:00
Gwilym Inzani f097e152cc Pass deduplicate one step further 2023-08-29 13:18:14 +01:00
Gwilym Inzani 8158bc1ff3 Allow deduplicating background tiles 2023-08-29 13:16:57 +01:00
Gwilym Inzani afed1542fe Move the new sprites to the correct place 2023-08-29 09:50:00 +01:00
Corwin b275db90da
make correct solution more obvious 2023-08-28 23:05:35 +01:00
Corwin 31c5519bc8
base update order on initial positions 2023-08-28 15:59:20 +01:00
Corwin 2a02da1c2f
simplify entity update loop 2023-08-28 14:00:39 +01:00
Corwin 0b45c006c8
ice on bottom 2023-08-28 11:45:29 +01:00
Corwin 4bd175cd7b
defined update order 2023-08-28 11:45:21 +01:00
Corwin dacecef900
fix bug where the ice is the one to get moved 2023-08-28 11:38:04 +01:00
Corwin ae0b86c7b9
fix lints 2023-08-28 11:36:22 +01:00
Corwin 5846a1c024
fix wonky ice animation next to wall 2023-08-28 11:34:08 +01:00
Gwilym Inzani 04ee5646ef
Add some new sprites for Corwin 2023-08-28 11:06:59 +01:00
Corwin 248cdae7a3
change squid change direction behaviour 2023-08-27 20:34:20 +01:00
Corwin 36603d5446
add block 2023-08-27 19:49:37 +01:00
Corwin a0ab3e9fb4
add ice level 2023-08-27 18:31:30 +01:00
Corwin e33eee7d11
fix mistakes copy over 2023-08-27 17:27:43 +01:00
Corwin b9e6e09fe1
add ice 2023-08-27 16:47:00 +01:00
Gwilym Inzani dd119604d8
If r2 < 4 don't overwrite all memory (#475)
Rare case, but we probably shouldn't break everything if it happens :)

- [x] Changelog updated / no changelog update needed
2023-08-26 14:25:12 +01:00
Gwilym Inzani dc46cfef45 If r2 < 4 don't overwrite all memory 2023-08-22 20:15:26 +01:00
Gwilym Inzani 9a6f96b2ba
Update dependency ubuntu to v22 (#473)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [ubuntu](https://togithub.com/actions/runner-images) | github-runner |
major | `20.04` -> `22.04` |

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNi40MC4zIiwidXBkYXRlZEluVmVyIjoiMzYuNDAuMyIsInRhcmdldEJyYW5jaCI6Im1hc3RlciJ9-->
2023-08-13 13:12:55 +01:00
GBA bot c29ba6e9ec Update lockfiles 2023-08-13 10:36:46 +00:00
renovate[bot] 10da95b2e3
Update dependency ubuntu to v22 2023-08-13 10:36:09 +00:00
Gwilym Inzani ec7d1447d8
Replace mgba-test-runner with better bindings (#471)
- [ ] Changelog updated / no changelog update needed
2023-08-13 11:35:32 +01:00
Corwin 5eb240068a
video buffer using unsafe cell across ffi boundary 2023-08-09 21:06:54 +01:00
Corwin d9a0ab1a9f
make non rust trait parts of vfile private 2023-08-08 09:48:10 +01:00
Corwin ad1f70e6e5
use less specific versions of clap and anyhow 2023-08-08 09:48:10 +01:00
Corwin 29c7ee9929
change emulator directory notes 2023-08-08 09:48:10 +01:00
Corwin 246e4da99e
run tests for emulator workspace 2023-08-08 09:48:10 +01:00
Corwin 987928a9a8
initialise to the no logger iff no other logger has been loaded 2023-08-08 09:48:10 +01:00
Corwin 3430668bdd
change name of cycle measure function and remove from public api 2023-08-08 09:48:10 +01:00
Corwin d4c1dc1730
use same target for everything 2023-08-08 09:48:10 +01:00
Corwin 59efa29225
include mgba's include directory 2023-08-08 09:48:10 +01:00
Corwin f873ca2c6b
remove pointless ignore 2023-08-08 09:48:10 +01:00
Corwin c75ddf0942
fix path 2023-08-08 09:48:10 +01:00
Corwin 4acf98bcbd
replace mgba-test-runner with better bindings 2023-08-08 09:48:07 +01:00
Gwilym Inzani 5fb928adb8
Update Rust crate bilge to 0.2 (#467)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [bilge](https://togithub.com/hecatia-elegua/bilge) | dependencies |
minor | `0.1` -> `0.2` |

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log [here](https://developer.mend.io/github/agbrs/agb).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNi4yNC4yIiwidXBkYXRlZEluVmVyIjoiMzYuMjQuMiIsInRhcmdldEJyYW5jaCI6Im1hc3RlciJ9-->
2023-08-07 21:10:27 +01:00
Gwilym Inzani b8ceb26bff Also only git add if passed --commit 2023-08-06 21:06:29 +01:00
Gwilym Inzani 6607ea3f1f Update lockfiles 2023-08-06 21:06:12 +01:00
Gwilym Inzani b45668f5e9 Make it easier to run update-lockfiles locally 2023-08-06 21:04:58 +01:00
Gwilym Inzani 11f71371e2 Be less happy with what we allow 2023-08-06 21:02:15 +01:00
Gwilym Inzani 46c9ebb855 Derive default to make bilge 2.0 happy (and may as well) 2023-08-06 21:02:15 +01:00
renovate[bot] 24070fdd18 Update Rust crate bilge to 0.2 2023-08-06 21:02:15 +01:00
Gwilym Inzani 18a161269e
Envelopes (#469)
A combination of the previous PR (#468) and support for volume envelopes
in the tracker

- [x] Changelog updated / no changelog update needed
2023-08-06 20:48:35 +01:00
Gwilym Inzani 136f551a98 Add changelog entry for from_f32 and from_f64 2023-08-06 20:27:09 +01:00
Gwilym Inzani 2d69a4682b Should let the fadeout take over once the envelope has finished 2023-08-06 20:25:31 +01:00
Gwilym Inzani eda11073ed Introduce fixnum::from_f(32|64) 2023-08-06 20:24:59 +01:00
Corwin 9c96880a5f
Upload games as build outputs (#472)
- [x] no changelog update needed
2023-08-06 13:44:01 +02:00
Corwin 3be7dd91d6
upload artifacts from build process 2023-08-06 11:10:56 +01:00
Gwilym Inzani 4f7fb7125b Fix crash for some files 2023-08-05 23:51:26 +01:00
Gwilym Inzani 67de2d5833 Implement fadeout 2023-08-05 23:51:12 +01:00
Gwilym Inzani f6ed1c484b Implement global volume 2023-08-05 22:55:03 +01:00
Gwilym Inzani 3976fd93ea Correctly interpret F00 2023-08-05 22:29:31 +01:00
Corwin ddc925ca7e
Add example for saving (#470)
Adds a quick example for saving a some numbers in sram.

- [x] no changelog update needed
2023-08-05 12:07:05 +01:00
Corwin ba62aca590
add example for saving 2023-08-05 11:53:14 +01:00
Gwilym Inzani db75d8b048 Minor fixes when trying other tracks 2023-08-05 01:33:48 +01:00
Gwilym Inzani ff5d324356 Reuse envelopes if they are the same 2023-08-05 00:58:39 +01:00
Gwilym Inzani aabfb1b083 This sounds pretty decent now 2023-08-05 00:24:11 +01:00
Gwilym Inzani 47455a0377 First pass at implementing envelope playing 2023-08-05 00:02:50 +01:00
Gwilym Inzani ca4cb55b39 Add boilerplate for exporting the envelopes 2023-08-04 23:25:48 +01:00
Gwilym Inzani d29a641a44 Specify that it is the volume envelope 2023-08-04 23:19:07 +01:00
Gwilym Inzani 826fdd881a Add data structure 2023-08-04 23:17:59 +01:00
Gwilym Inzani 9d299f3e66 Fix out by one error with instrument samples 2023-08-04 23:07:19 +01:00
Gwilym Inzani fa4b2ebd5d Implement F command 2023-08-04 22:30:49 +01:00
Gwilym Inzani 43d7350c2f Remove some of the volume slides 2023-08-04 21:30:09 +01:00
Gwilym Inzani 0a851e296a Some music updates 2023-08-04 21:24:45 +01:00
Gwilym Inzani 6731fa88a0 I prefer this a bit slower 2023-08-02 17:18:27 +01:00
Gwilym Inzani 8177366c6b Remove dbg 2023-08-02 16:49:30 +01:00
Gwilym Inzani 4b145d3194 Try composing my own theme (with some bug fixes) 2023-08-02 16:48:41 +01:00
Gwilym Inzani 70e763cc11 Add some panning for some more audio interest 2023-08-01 22:34:33 +01:00
Gwilym Inzani ea29c2a9f9 Make all the sound effects louder 2023-08-01 21:59:27 +01:00
Gwilym Inzani f49d3d3700 Actually include the new music and delete the old 2023-08-01 21:42:45 +01:00
Gwilym Inzani f4214b5da8 Use new music for dungeon puzzler's lament and fix tracker bugs 2023-08-01 21:41:33 +01:00
Gwilym Inzani f3a6bead13 Actually update the gbafix licence 2023-07-28 21:54:36 +01:00
Gwilym Inzani 92a1478327
Update lockfiles (#466)
Updating lockfiles speeds up the build :)
2023-07-26 11:42:32 +01:00
GBA bot e08024ae5b Update lockfiles 2023-07-26 11:31:26 +01:00
Gwilym Inzani a2dc536d49
Use my new married name in all the places it appeared (#465)
- [x] no changelog update needed
2023-07-26 10:42:31 +01:00
Gwilym Inzani a30bb9a774
Use own gbafix implementation (#464)
Breaks the dependency on the gbafix crate and implements the header
fixing code internally.

Also, relicence `agb-gbafix` to MPL to match everything else.

- [x] Changelog updated
2023-07-26 10:39:26 +01:00
Gwilym Inzani e4dd95fbf2
16x16 levels (#462)
When we wrote our gmtk game jam 23 entry, we used 8x8 tiles in our maps.
But it made a lot of things quite annoying, so here is my attempt at
using 16x16 tiles instead and handling the pain just once in build.rs

- [x] no changelog update needed
2023-07-26 10:30:36 +01:00
Gwilym Inzani 3da10f11be Use my new married name in all the places it appeared 2023-07-26 10:29:03 +01:00
Gwilym Inzani a399415930 Add changelog entry for licence change 2023-07-26 10:25:02 +01:00
Gwilym Inzani 61c4b03f7d Update the licence to be MPL since we have no GPL dependency any more 2023-07-26 10:23:34 +01:00
Gwilym Inzani d9fc333644 Implement the padding flag 2023-07-26 10:21:54 +01:00
Gwilym Inzani 9eee5a03f2 Implement our own gba header 2023-07-26 10:18:28 +01:00
Gwilym Inzani eb31a98f29 Extract write_gba_file to lib.rs 2023-07-26 09:53:32 +01:00
Gwilym Inzani 6c7f415fb6
Channel counts as finished if the channel position reaches the end of the effect (#463)
Fixes an issue where you could only play 8 sounds until it would stop
entirely.

- [x] no changelog update needed
2023-07-25 23:33:39 +01:00
Gwilym Inzani 9445a57f48 Channel counts as finished if the channel position reaches the end of the effect 2023-07-25 23:24:40 +01:00
Gwilym Inzani a5ad0129ed Don't need to call it levels16 any more 2023-07-25 23:22:08 +01:00
Gwilym Inzani 15ea1427df Delete the old 8x8 levels 2023-07-25 23:16:00 +01:00
Gwilym Inzani ea3ba89f92 16x16 levels!! 2023-07-25 23:15:34 +01:00
Gwilym Inzani 999a73439c Migrate the first 6 levels 2023-07-25 22:34:09 +01:00
Gwilym Inzani 3bd5ae2313 level 1 implemented 2023-07-25 22:23:32 +01:00
Corwin b80c85f1d9
Import dungeon puzzler's lament (#459)
Includes dungeon keepers lament in the examples

- [x] no changelog update needed
2023-07-25 20:52:48 +01:00
Corwin 748f061856
remove unused method 2023-07-25 20:41:16 +01:00
Corwin 95c4368df6
remove unused resolution 2023-07-25 20:41:05 +01:00
Corwin e7fe866036
remove sound files for unused effects 2023-07-25 20:40:16 +01:00
Corwin 9ee98cf0bf
remove unused sounds 2023-07-25 20:39:14 +01:00
Corwin c461b581b5
emit sword hit 2023-07-25 20:39:06 +01:00
Gwilym Inzani bddb77f5c9
XM tracker (#461)
Closes #446

One big problem with our games so far is that they are 95% music files.
If we want to add a game with more music, we can't at the moment.

This adds a tracker player which can play XM files easily in your games.
A lot of features from tracker files aren't supported yet, but enough to
make the examples sound at least half decent.

- [x] Changelog updated
2023-07-25 20:29:31 +01:00
Corwin b806fa8e66
fix names 2023-07-25 20:27:03 +01:00
Gwilym Inzani a4a7089251 Add changelog entry and update readme 2023-07-25 20:18:21 +01:00
Gwilym Inzani e8e5b31d42 No need to use a generic here any more 2023-07-25 00:50:47 +01:00
Gwilym Inzani f7b3aa8ecb Don't need lr to be saved since we're not using it 2023-07-25 00:27:20 +01:00
Gwilym Inzani 49b9a07a87 Give the same assembly treatment to mono sounds 2023-07-25 00:18:48 +01:00
Gwilym Inzani de666a54f9 Core loop for the tracker in assembly 2023-07-24 23:59:54 +01:00
Gwilym Inzani df75d1ce8c Fix build errors 2023-07-23 23:39:52 +01:00
Gwilym Inzani 25ee876932 Fix a bunch of bugs after playing with different tracks 2023-07-23 23:37:14 +01:00
Gwilym Inzani a4df095031 Improve accuracy of the panning and volume until the last second 2023-07-23 22:15:30 +01:00
Gwilym Inzani d233a2539c Improve accuracy of the volume 2023-07-23 22:10:25 +01:00
Gwilym Inzani 095723bbf8 FineVolumeSlide 2023-07-23 22:03:32 +01:00
Gwilym Inzani f6a05178db Fix slides and add the portamento one 2023-07-23 21:36:02 +01:00
Gwilym Inzani 0911ca44c5 Try a new song and add memory support 2023-07-23 20:54:24 +01:00
Gwilym Inzani 1a25268285 Do the correct type of building for the tracker 2023-07-23 20:36:54 +01:00
Gwilym Inzani 21d1d1385a Remove unused tracker files and add where I found db_toffe 2023-07-23 20:31:46 +01:00
Gwilym Inzani 70d34f1fc8 Rename to include_xm to match the rest of agb 2023-07-23 20:22:22 +01:00
Gwilym Inzani 6cb8f68104 Write some simple docs for agb_tracker 2023-07-23 20:21:04 +01:00
Gwilym Inzani e2f14094fc Update my name 2023-07-23 20:00:31 +01:00
Gwilym Inzani b593b90701 Get the docs building 2023-07-23 19:52:11 +01:00
Gwilym Inzani 352658f23f Fix clippy lints 2023-07-23 19:08:51 +01:00
Gwilym Inzani 85561de1ca Attempt to update the tools to the new folder 2023-07-23 18:35:50 +01:00
Gwilym Inzani 992ce37464 Update justfile to support the tracker crates 2023-07-23 00:31:12 +01:00
Gwilym Inzani 1aa8e5fd33 Reintroduce the first special casing 2023-07-22 23:40:09 +01:00
Gwilym Inzani d6384a6886 This improves mixing performance by about 20% 2023-07-22 23:27:21 +01:00
Corwin 2d53977c49
add energy to amplitude (#457)
- [x] no changelog update needed
2023-07-19 20:36:54 +01:00
Corwin 67435b31e0
update justfile 2023-07-19 17:54:41 +01:00
Corwin 41a0c773dd
clean up other examples 2023-07-19 17:54:41 +01:00
Corwin 0fac43746f
add the dungeon keeper's lament 2023-07-19 17:54:41 +01:00
Gwilym Inzani ff0e8f659e Better tracking of speed 2023-07-19 13:53:46 +01:00
Gwilym Inzani b6cccf3b5a Add Portamento 2023-07-19 13:38:32 +01:00
Gwilym Inzani 1b8f4bbdc9 NoteCut support 2023-07-19 13:22:26 +01:00
Gwilym Inzani a9236531c7 Simplify the basic example and make a timing example 2023-07-19 12:31:59 +01:00
Gwilym Inzani 6f8633861d Use 32-bit numbers more for more performance (and start tracking that) 2023-07-18 22:49:56 +01:00
Gwilym Inzani b8adf08382 Don't hold arpeggios 2023-07-18 22:17:17 +01:00
Gwilym Inzani 03b5f2fafd Remove unused methods 2023-07-18 21:51:38 +01:00
Gwilym Inzani c2e7a3b9b4 Update to 0.16 2023-07-18 21:51:31 +01:00
Gwilym Inzani a91069eac2 Consider the global volume 2023-07-18 21:37:01 +01:00
Gwilym Inzani de085fc1ff Use wrapping add and mul 2023-07-18 21:37:01 +01:00
Gwilym Inzani 8b296794fe Should only decrease the volume after the first tick 2023-07-18 21:37:01 +01:00
Gwilym Inzani 652173c08e Reduce size of pattern by 4 bytes per slot 2023-07-18 21:37:01 +01:00
Gwilym Inzani 515bcb13ca Reset the volume each time a new sound is played 2023-07-18 21:37:01 +01:00
Gwilym Inzani 07b00f11e1 Use relative notes to make it sound almost correct 2023-07-18 21:37:01 +01:00
Gwilym Inzani 4d699e9000 Volume slides - ish 2023-07-18 21:37:01 +01:00
Gwilym Inzani 203b1a4026 Actually make arpeggios work 2023-07-18 21:37:01 +01:00
Gwilym Inzani 9b94b2a2cb Remove commented code 2023-07-18 21:37:01 +01:00
Gwilym Inzani aa635e9aa6 Refactor to effects 2023-07-18 21:37:01 +01:00
Gwilym Inzani 7861571a96 Correctly track restart point 2023-07-18 21:37:01 +01:00
Gwilym Inzani 1dd4c9fb83 Add a concept of a restart point 2023-07-18 21:37:01 +01:00
Gwilym Inzani a0be2a333e Attempt to calculate the speed to play more correctly 2023-07-18 21:37:01 +01:00
Gwilym Inzani c66f495cc7 Don't need loop labels any more 2023-07-18 21:37:01 +01:00
Gwilym Inzani d929a1689a Extract methods 2023-07-18 21:37:01 +01:00
Gwilym Inzani 938f05f8d1 Compile in release and make actually safe 2023-07-18 21:37:01 +01:00
Gwilym Inzani d4b2a2bc1a Fix crackly audio 2023-07-18 21:37:01 +01:00
Gwilym Inzani 8191de3546 Try a pure rust implementation to allow for looping correctly 2023-07-18 21:37:01 +01:00
Gwilym Inzani a61069fb60 Handle non multiple of 4 buffer sizes for mono 2023-07-18 21:37:01 +01:00
Gwilym Inzani eb8cb667c1 Extract to macros 2023-07-18 21:37:01 +01:00
Gwilym Inzani fc4632ca8a Only need to load the buffer size once 2023-07-18 21:37:01 +01:00
Gwilym Inzani d38fea7f7a Pass the buffer size rather than using the global variable for it 2023-07-18 21:37:01 +01:00
Gwilym Inzani 86db9d15bf Don't assume agb-tracker-interop dependency 2023-07-18 21:37:01 +01:00
Gwilym Inzani a8d751a0ef Panning effect 2023-07-18 21:37:01 +01:00
Gwilym Inzani 989d376056 Amega frequencies and effects 2023-07-18 21:37:01 +01:00
Gwilym Inzani cf1f3965d8 Improvements 2023-07-18 21:37:01 +01:00
Gwilym Inzani 436b49c80d Get closer to some reasonable sounding 2023-07-18 21:37:01 +01:00
Gwilym Inzani 308cb3a19c Really basic playing 2023-07-18 21:37:01 +01:00
Gwilym Inzani a77b536e69 Really basic export 2023-07-18 21:37:01 +01:00
Gwilym Inzani f3e3c243a4 Use the recommended layout for proc macros 2023-07-18 21:37:01 +01:00
Gwilym Inzani af0cf7170e Move everything to a tracker directory 2023-07-18 21:37:01 +01:00
Gwilym Inzani aefa842624 Add a std feature instead 2023-07-18 21:37:01 +01:00
Gwilym Inzani d903aa164b Need an interop crate too 2023-07-18 21:37:01 +01:00
Gwilym Inzani 7e4a2f2e20 Create skeleton projects 2023-07-18 21:37:01 +01:00
Corwin a7f9fdf011
Release v0.16.0 2023-07-18 18:55:12 +01:00
Corwin b12692511e
Allow new clippy lint (#458)
New clippy lint introduced that would break safety if followed.

- [x] no changelog update needed
2023-07-18 18:44:03 +01:00
Corwin 1db3a61ee3
allow new clippy lint 2023-07-18 18:34:56 +01:00
Corwin c60d0215d6
add energy to amplitude 2023-07-17 17:38:34 +01:00
Corwin f9a9de5823
Fix issue with 16x16 sprites with more than 15 colours (#456)
Should fix https://github.com/agbrs/agb/issues/455

- [x] Changelog updated / no changelog update needed
2023-07-14 01:08:37 +01:00
Gwilym Inzani ebf1f82026 Add changelog entry for > 15 colours bug 2023-07-12 11:54:56 +01:00
Gwilym Inzani 868e7d4339 VSCode wants the changelog formatted like this now 2023-07-12 11:54:43 +01:00
Gwilym Inzani 682a63b055 Fix issue with 16x16 sprites with more than 15 colours 2023-07-12 11:52:59 +01:00
Corwin 1eb0505e50
Object based font rendering (#450)
* Pulled out of something else I was working on.

- [x] Changelog updated / no changelog update needed
2023-07-04 23:02:11 +01:00
Corwin 636e31aa91
uncomment out code 2023-07-04 22:35:12 +01:00
Corwin 551fbfab4a
update changelog 2023-07-04 22:29:28 +01:00
Corwin 3687f9b1a5
Merge remote-tracking branch 'upstream/master' into font-renderer 2023-07-04 22:27:06 +01:00
Gwilym Inzani a8544a9b41
Fix clippy lints from 04/07/2023 (#454)
Fixes the latest batch of build failures

- [x] no changelog update needed
2023-07-04 21:35:36 +01:00
Corwin 0cd469866c
font get optimisation 2023-07-04 21:35:00 +01:00
Corwin 991bb644f9
timers around area of interest 2023-07-04 21:34:51 +01:00
Gwilym Inzani 284e30078f Fix clippy lint in purple night 2023-07-04 21:24:44 +01:00
Gwilym Inzani 14c6542e7b Clippy fix didn't delete a space 2023-07-04 20:37:26 +01:00
Gwilym Inzani 6fb7b74b35 Fix clippy lints from 04/07/2023 2023-07-04 20:10:01 +01:00
Corwin c5a7e9a25b
Merge remote-tracking branch 'upstream/master' into font-renderer 2023-07-02 14:59:07 +01:00
Corwin 318ee03c12
fix doclinks 2023-07-02 14:57:01 +01:00
Corwin b82ed16cc2
update test image 2023-07-02 14:55:30 +01:00
Corwin 5c0f855e1b
use newer rustfmt 2023-07-02 14:32:09 +01:00
Corwin 698396f6ad
Update Rust crate asefile to 0.3.6 (#452) 2023-07-02 13:10:01 +01:00
Corwin fa7a71e0d3
add docs and export 2023-07-02 13:08:54 +01:00
Corwin 66a212f29a
remove unused 2023-07-02 13:08:44 +01:00
Corwin 9388098318
JUSTIFY 2023-07-02 00:38:52 +01:00
Corwin 9edbca582e
magic colour changing 2023-07-02 00:24:54 +01:00
Corwin 5f12040752
the proper nice okay working text rendering 2023-07-01 23:36:58 +01:00
Corwin ec3003c81d
garbage renderer 2023-07-01 19:12:39 +01:00
GBA bot 78a7c8d1c0 Update lockfiles 2023-07-01 14:21:55 +00:00
renovate[bot] b758ff1fe5
Update Rust crate asefile to 0.3.6 2023-07-01 14:21:18 +00:00
Gwilym Inzani 4fc4eab83b Give amplitude the same build settings as the other games
Makes the build faster
2023-06-30 22:09:06 +01:00
GBA bot 28683e701f Update lockfiles 2023-06-30 22:03:31 +01:00
Corwin 93024f6bab
remove some unused bits 2023-06-29 20:04:27 +01:00
Corwin cf400029f5
caching layout 2023-06-29 00:10:21 +01:00
Corwin f947d82049
text rendering that supports different alignments 2023-06-28 20:29:09 +01:00
Gwilym Inzani 92e31aef35
Save useless zeroing of buffer (#451)
I realised we don't need to zero the buffer or read the current buffer
value for the first sound that we're writing per frame. Gets us from
17728 cycles per frame for 32768Hz down to 15291 cycles per frame.

From tests (and theory), this reduces the number of cycles per frame by
2,000 for 32768Hz.

- [x] No changelog update needed - already mentioned mixer improvements
there
2023-06-27 23:52:05 +01:00
Gwilym Inzani 13f5fe01d7 Actually use the new first methods 2023-06-27 22:34:45 +01:00
Corwin d5d3d1a658
strip to bare renderer 2023-06-27 22:00:34 +01:00
Corwin 22b3497bb3
fix 2023-06-27 21:56:26 +01:00
Corwin fd82b259cc
dynamic sprite allocate directly into sprite vram 2023-06-27 21:56:09 +01:00
Gwilym Inzani 3b35061a3a Extract iterator to a variable 2023-06-27 21:51:59 +01:00
Gwilym Inzani 38868cb269 Extract even more from the loop body 2023-06-27 21:50:46 +01:00
Gwilym Inzani 57f0a8c889 Remove is_done check in for loop 2023-06-27 21:49:30 +01:00
Gwilym Inzani f4779208e3 Implement first cases for the non stereo 2023-06-27 21:48:01 +01:00
Gwilym Inzani e1d03929f9 Use local labels 2023-06-27 21:33:56 +01:00
Gwilym Inzani 306be59cde Add implementation for if this is the first 2023-06-27 21:31:06 +01:00
Corwin ce7bcacb3c
somewhat mad left align renderer 2023-06-26 23:47:19 +01:00
Corwin b75303863d
buffered text render 2023-06-26 17:10:42 +01:00
Corwin 87ac2fe53c
reuse dynamic sprite 2023-06-26 17:10:42 +01:00
Corwin b99fff7c8e
some object based text rendering 2023-06-26 17:10:03 +01:00
Corwin aa38a03ac9
add read pixel method 2023-06-26 17:10:03 +01:00
Gwilym Inzani 938b052997
Schedule nightly run to be at 6:10 rather than 5:10
Occasionally, miri was't available yet. So we go with a 6:10 run to give it a chance to be installed.
2023-06-25 16:07:59 +01:00
Gwilym Inzani c3268e3de2
Even faster mixer (#447)
If you do an ldmia for loading lots of samples at once, the mixer uses
significantly less CPU (10% compared to previous, 19800 cycles per frame
-> 17701 cycles per frame for 32768Hz).

I've also added a really simple unit test for the `collapse` function to
at least gain some confidence in it.

- [x] Changelog updated / no changelog update needed
2023-06-20 22:04:16 +01:00
Corwin dbf7715e67 use assert_eq and collect 2023-06-20 21:52:07 +01:00
Corwin 389e3ecadb make test not reliant on coincidence alignment 2023-06-20 21:52:07 +01:00
Gwilym Inzani 0e3fe2c49a add a changelog entry 2023-06-18 16:43:00 +01:00
Gwilym Inzani 5a374ba4f0 Add collapse test and fix bug uncovered by it 2023-06-18 16:29:02 +01:00
Gwilym Inzani b2dcd8c854 Pass buffer size as an argument 2023-06-18 16:02:14 +01:00
Gwilym Inzani ba18a0bf4a ldmia again 2023-06-16 23:43:37 +01:00
Gwilym Inzani e72de28961 Can I use movne here instead? 2023-06-16 23:41:15 +01:00
Gwilym Inzani ceb57eb002 r12 is a scratch register 2023-06-16 22:22:03 +01:00
Gwilym Inzani 334e70c664 Do multiple loads at once 2023-06-16 22:19:56 +01:00
Gwilym Inzani 9e08303e62 Extract a macro for this 2023-06-16 22:15:45 +01:00
Gwilym Inzani 6cf3ecaf36 Don't need to save r9 2023-06-16 22:11:44 +01:00
Corwin 20a7c262e9
add optimisation for 64 bit upcast multiply (#444)
This is really good now!


- [x] Changelog updated / no changelog update needed
2023-06-06 23:15:38 +01:00
Corwin 2a21c5fdab
add optimisation for 64 bit upcast multiply 2023-06-06 23:00:17 +01:00
Corwin 28e3a7faf4
Resolve stutter upon switching to dice customise screen (#442)
1. Dealloc now uses the normal dealloc procedure.
    * Better because normalisation is quick, O(1).
    * More normalisation means inserting into the list is faster.
2. Run sfx frame during the generation of upgrades (which can take an
unbounded amount of time).

* Both of these are required to remove the stuttering.
* It sounds really weird now that it works right :/

- [ ] Changelog updated / no changelog update needed
2023-06-05 21:01:12 +01:00
Corwin 80051a163a
Modify the enemy health rng by using a dice roll distribution (#438)
- [ ] Changelog updated / no changelog update needed
2023-06-05 21:01:04 +01:00
Corwin a7269ed65f
Add precision support for fixnums (#437)
- [ ] Changelog updated / no changelog update needed
2023-06-05 21:00:54 +01:00
Corwin 53937b4fa8
Upcast multiply (#436)
- [ ] Changelog updated / no changelog update needed
2023-06-05 21:00:46 +01:00
Corwin 6b84833c4f
remove dealloc_no_normalise 2023-06-05 00:12:36 +01:00
Corwin 95a8804094
reset the number of attempts 2023-06-05 00:12:36 +01:00
Corwin cbb0b7d2a0
resolve stutter 2023-06-05 00:12:36 +01:00
Corwin 083fd43ea3
just dealloc in gc 2023-06-05 00:12:36 +01:00
Corwin 80f5812039
make the letter "R" better (#441)
Hyperspace roll has a not great looking letter "R". Uses change made by
Gwilym.

- [x] no changelog update needed
2023-06-03 23:56:43 +01:00
Corwin 2b94ef0ac7
make the letter "R" better 2023-06-03 23:45:55 +01:00
Corwin 492643d0b5
Show health in hyperspace roll (#440)
Shows health in hyperspace roll

- [x] no changelog update needed
2023-06-03 23:39:04 +01:00
Corwin 95b28983ff
show health 2023-06-03 23:29:54 +01:00
Corwin 1c58a419ec
Hide objects by default (#439)
Fixes bug introduced in #430 
- [x] no changelog update needed
2023-06-03 23:25:28 +01:00
Corwin 77c4741ee7
hide objects by default 2023-06-03 16:06:23 +01:00
Corwin c011e58ec7
separate tests 2023-06-02 18:18:18 +01:00
Corwin ae23f6fdf4
round towards nearest 2023-06-02 11:57:35 +01:00
Corwin 1d7acfb070
modify the enemy health rng by using a distribution 2023-06-02 01:24:37 +01:00
Corwin 6e0d58a674
add precision support for fixnums 2023-06-02 00:03:27 +01:00
Corwin b5704afe5e
remove usize 2023-06-01 18:52:03 +01:00
Corwin 9fa8f75202
upcast multiply 2023-05-30 22:21:12 +01:00
Gwilym Inzani da5aed83e3
Use bilge rather than modular-bitfield (#430)
Thought I'd give bilge a go rather than modular bitfield after reading
this blog post:
https://hecatia-elegua.github.io/blog/no-more-bit-fiddling/

- [ ] Changelog updated / no changelog update needed
2023-05-30 20:41:46 +01:00
Corwin a178e28b77
Optimise Normalisation (#435)
This only optimises the relevant blocks during normalisation.

The benchmark in CI goes from 12023166 cycles to 9260517 cycles, a
decrease of 23%.

- [x] no changelog update needed
2023-05-26 18:23:33 +01:00
Corwin 7e111e0327
remove unused import 2023-05-25 19:30:38 +01:00
Corwin 9c15adf6c8
only normalise the relevant blocks 2023-05-25 19:25:26 +01:00
Corwin 1b687b787d
Inline always in new_from_parts (#433)
Mentioned here that we should probably do it:
https://github.com/agbrs/agb/discussions/370#discussioncomment-4650702

From decompiling, it seems that this normally happens, but lets at least
ensure it if you don't have lto enabled.

- [x] no changelog update needed
2023-05-24 01:47:03 +01:00
Gwilym Inzani 8c1c725dfa Inline always in new_from_parts 2023-05-23 21:46:25 +01:00
Gwilym Inzani 98484783b4
Minor speed up for tiles (#432)
We currently do lots of redundant hash calculations while changing a
tile in vram. We can cache the value and then use the entry API to reuse
it.

- [x] no changelog update needed
2023-05-23 21:41:25 +01:00
Gwilym Inzani 9ec0836da9 Put the capacity check back in 2023-05-23 21:29:05 +01:00
Gwilym Inzani 903157325f Don't recalculate the hash 2023-05-23 21:20:49 +01:00
Gwilym Inzani d393ad7e99 Bypass some duplicated work if you use the entry API 2023-05-23 21:10:27 +01:00
Corwin 1bb70aa24b
Remove workarounds (#426)
Removes some workaronds for rust bugs

- [x] no changelog update needed
2023-05-23 20:29:35 +01:00
Corwin 6b7088773e
remove codegen units 2023-05-23 20:12:42 +01:00
Corwin d638134d37
remove codegen-units
these were added as a workaround for rust bugs
2023-05-23 20:10:24 +01:00
Corwin 37c30586c3
remove profiles from some projects
these projects are not tested or run on the gba or
are dependencies and therefore follow the binaries settings
2023-05-23 20:10:21 +01:00
Gwilym Inzani 6e441efe92
Remove the need for binutils (#425)
Just uses `global_asm!` instead.

- [x] Changelog updated / no changelog update needed
2023-05-21 20:35:06 +01:00
Gwilym Inzani 7cf66e67e5 Update agb version in amplitude 2023-05-21 16:49:06 +01:00
Gwilym Inzani 0278fc8158 Add changelog entry for removing binutils dependency 2023-05-21 16:38:06 +01:00
Gwilym Inzani 1b27bf4613 Remove codegen-units = 1 since it won't be needed any more 2023-05-21 16:37:35 +01:00
Gwilym Inzani 958f32b177 Include macros.inc properly 2023-05-21 16:37:35 +01:00
Gwilym Inzani 78bad29f88 Add codegen-units=1 to prevent miscompiles 2023-05-21 16:37:35 +01:00
Gwilym Inzani fe23bee18b Prevent multiple include errors 2023-05-21 16:37:35 +01:00
Gwilym Inzani 878402a5b6 Don't install arm-none-eabi-binutils 2023-05-21 16:37:35 +01:00
Gwilym Inzani 2de1b08f42 Remove references to arm-none-eabi 2023-05-21 16:37:35 +01:00
Gwilym Inzani 5ab0176ddb Entirely remove the need for binutils 2023-05-21 16:37:34 +01:00
Gwilym Inzani 644e94f8ed Use bilge rather than modular-bitfield 2023-05-17 15:01:22 +01:00
453 changed files with 26777 additions and 12026 deletions

BIN
.github/logo.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8 KiB

View file

@ -1,3 +0,0 @@
- [ ] Changelog updated / no changelog update needed

View file

@ -1,9 +0,0 @@
{
"extends": [
"config:base"
],
"ignorePresets": [
":prHourlyLimit2"
],
"dependencyDashboardAutoclose": true
}

View file

@ -1,20 +0,0 @@
#!/usr/bin/env bash
function update_lockfiles() {
find . -name Cargo.lock -execdir cargo update \;
}
update_lockfiles
update_lockfiles
update_lockfiles
update_lockfiles
git add -u
if [ "$(git diff --cached --name-only)" == '' ]; then
echo "No files updated"
exit 0
fi
git -c user.name="GBA bot" -c user.email="gw@ilym.me" commit -m 'Update lockfiles'
git push

View file

@ -1,27 +0,0 @@
#!/usr/bin/env bash
set -e # Fail if any command fails
set -x # print every command before it runs
# Updates the template repository to the content of the template directory
# Requires environment variable
# - GITHUB_USERNAME = a user who has push access to the template repository
# - API_TOKEN_GITHUB = an API token for the user
CLONE_DIR=$(mktemp -d)
git clone --single-branch --branch master "https://$GITHUB_USERNAME:$API_TOKEN_GITHUB@github.com/agbrs/template.git" "$CLONE_DIR"
# Copy the .git directory to a different place so we can ensure that only the relevant template stuff stays
TEMP_DIR=$(mktemp -d)
mv "$CLONE_DIR/.git" "$TEMP_DIR/.git"
cp -rva template/. "$TEMP_DIR"
# git describe will give a unique, friendly name for the current commit to make it easier to track where this came from
VERSION=$(git describe --tags)
COMMIT_MESSAGE="Update to $VERSION"
git -C "$TEMP_DIR" add .
git -C "$TEMP_DIR" -c user.email="gw@ilym.me" -c user.name="GBA bot" commit -m "$COMMIT_MESSAGE"
git -C "$TEMP_DIR" push origin HEAD

View file

@ -1,47 +0,0 @@
name: Rust
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
schedule:
- cron: '10 5 * * *'
env:
CARGO_TERM_COLOR: always
jobs:
build:
name: Just CI
runs-on: ubuntu-20.04
steps:
- name: Install build tools
run: sudo apt-get update && sudo apt-get install build-essential binutils-arm-none-eabi libelf-dev zip -y
- name: Install Miri
run: |
rustup toolchain install nightly --component miri
rustup override set nightly
cargo miri setup
- uses: actions/checkout@v3
- name: Cache
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
~/target
mgba-test-runner/target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: install mgba-test-runner
run: cargo install --path mgba-test-runner --verbose
- name: Set CARGO_TARGET_DIR
run: echo "CARGO_TARGET_DIR=$HOME/target" >> $GITHUB_ENV
- uses: extractions/setup-just@v1
- name: Setup mdBook
uses: peaceiris/actions-mdbook@v1
with:
mdbook-version: '0.4.13'
- name: Build and test all crates
run: just ci

View file

@ -1,54 +0,0 @@
name: Publish agb
on:
push:
tags:
- v*
jobs:
build:
runs-on: ubuntu-20.04
steps:
- name: Install build tools
run: sudo apt-get update && sudo apt-get install build-essential binutils-arm-none-eabi zip -y
- name: Check out repository
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Login to crates.io
run: cargo login ${{ secrets.CRATE_API }}
- uses: extractions/setup-just@v1
- name: Publish crates
run: just publish
- name: Update template repo
env:
GITHUB_USERNAME: gwilymk
API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }}
run: bash .github/scripts/update-template-repo.sh
- name: Build the examples
run: just build-roms
- name: Upload examples to the release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: examples/target/examples.zip
asset_name: examples.zip
tag: ${{ github.ref }}
overwrite: true
- name: Setup mdBook
uses: peaceiris/actions-mdbook@v1
with:
mdbook-version: '0.4.13'
- name: Build the book
run: just build-book
- name: Deploy the book
uses: JamesIves/github-pages-deploy-action@v4
with:
branch: gh-pages
folder: book/book

View file

@ -1,22 +0,0 @@
name: Update lockfiles
on:
push:
branches: [ 'renovate/*' ]
pull_request:
branches: [ 'renovate/*' ]
env:
CARGO_TERM_COLOR: always
jobs:
build:
runs-on: ubuntu-20.04
steps:
- name: Set CARGO_TARGET_DIR
run: echo "CARGO_TARGET_DIR=$HOME/target" >> $GITHUB_ENV
- name: Check out repository
uses: actions/checkout@v3
- uses: extractions/setup-just@v1
- name: Update lock files
run: just update-lockfiles

5
.gitignore vendored
View file

@ -1,4 +1,5 @@
target target
/out /out
template/Cargo.lock *.tiled-session
agb*/Cargo.lock website/build
Cargo.lock

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "emulator/mgba-sys/mgba"]
path = emulator/mgba-sys/mgba
url = https://github.com/mgba-emu/mgba.git

View file

@ -44,6 +44,12 @@
}, },
{ {
"path": "../agb-hashmap" "path": "../agb-hashmap"
},
{
"path": "../examples/amplitude"
},
{
"path": "../examples/the-dungeon-puzzlers-lament"
} }
] ]
} }

View file

@ -1,4 +1,5 @@
# Changelog # Changelog
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
@ -7,29 +8,237 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
### Added ### Added
- New `include_palette` macro for including every colour in an image as a `u16` slice.
- Optional serde support for agb-hashmap via the `serde` feature flag
### Fixed
- Fixed build error due to breaking change in `xmrs`.
## [0.21.1] - 2024/10/02
### Added
- Added support for s3m and mod format files to `agb-tracker`.
- Added a `HashSet` implementation in `agb::hashmap`.
### Changed ### Changed
- Changed how 16 colour palettes are optimised to give better average case results. You should find that
either your palettes will always import, or never import correctly.
## [0.21.0] - 2024/09/24
### Added
- Added support for vibrato in `agb-tracker`'s XM format
- Method to stop the tracker
### Changed
- `agb-tracker` now has an `agb` feature which you must enable to use it with `agb`. You won't notice
unless you've been using `default-features = false` in which case we recommend removing that from your `Cargo.toml`.
### Fixed
- There are no longer gaps between tiles in affine graphics modes.
### Added
- Added option to export imported background graphics from `include_background_gfx` as pub.
## [0.20.5] - 2024/06/18
### Fixed
- Resolved incompatibility with a dependency's update in `agb-tracker`. If you
are already using `agb-tracker`, then this won't yet cause an issue as your
lockfile will maintain the working version. However if start a new project, or
update dependencies, cargo will choose the later incompatible version.
## [0.20.4] - 2024/06/13
### Changed
- `manhattan_distance` and `magnitude_squared` no longer require the fixed point number.
## [0.20.3] - 2024/06/12
### Added
- Added `find_colour_index_16` and `find_colour_index_256` to the `VRamManager` to find where a colour is in a palette.
- Added `set_graphics_mode` to unmanaged sprites. This allows you to change to the blending and window modes.
### Fixed
- Affine background center position didn't work outside of the upper left quadrant of the gba's screen.
- Fixed backtrace pointing to the wrong line of code (being out by one).
- Fixes overflow caused by certain font characteristics on boundaries of sprites in the object text renderer.
## [0.20.2] - 2024/05/25
### Fixed
- Fixed the crash screen to show debug text even if the qr code fails to generate.
- Fixed the crash screen to prevent the qr code always failing to generate.
## [0.20.1] - 2024/05/17
### Added
- Added `dot` and `cross` product methods for `Vector2D`.
### Fixed
- Fixed an issue with agb tracker where XM files with linear frequencies were playing the wrong notes
## [0.20.0] - 2024/05/14
### Added
- Added a new crash screen which provides a mechanism for seeing a full stack trace of your program when it panics.
This requires a change to your `.cargo/config.toml`. You must add the rust flag `"-Cforce-frame-pointers=yes"` to
your rustflags field. This can also be disabled by removing the `backtrace` feature.
- Initial unicode support for font rendering.
- Kerning support for font rendering.
- Added `set_next` method to `OamIterator` to avoid repeated boilerplate when dealing with unmanaged objects.
### Fixed
- Export the `dma` module correctly so you can write the types from it and use it in more complex cases.
### Changed
- Many macros now emit statics rather than consts OR can be used as statics OR
have had examples changed to use statics. You should use statics where possible
for assets as consts can lead to them being included multiple times in the
ROM.
- Fixnums are now implemented with `num_traits` trait definitions.
- Rather than having our own sync with Statics, use the standard portable
atomics crate. These are reexported for convenience.
- `Mgba` no longer implements `Write`. You're unlikely to notice as
`agb::println!` is unchanged.
- Writes of long messages to mgba are split over multiple log messages if they
overflow mgba's buffer. On a panic, only the final message will be Fatal with
the preceding ones (if needed) being Info.
## [0.19.1] - 2024/03/06
### Added
- `.abs()` on `Vector2D` and `Rect`
### Fixed
- `InfiniteScrolledMap` can now scroll more than 1 tile in a single frame without corrupting.
## [0.19.0] - 2024/03/06
### Added
- Added `.priority()`, `.set_priority()` and `.is_visible()` to `RegularMap`, `AffineMap` and `InfiniteScrolledMap`.
- Replaced `.show()` and `.hide()` with `.set_visible()`in `RegularMap`, `AffineMap` and `InfiniteScrolledMap`.
- Added `.into_inner()` to `InfiniteScrolledMap` to get the map back once you are done using it in the `InfiniteScrolledMap`.
- Added `.hflip()`, `.vflip()`, `.priority()`, `.position()` to `ObjectUnmanaged` and `Object`.
- An abstraction over hblank DMA to allow for cool effects like gradients and circular windows. See the dma_effect\* examples.
- Expermental and incomplete support for MIDI files with agb-tracker.
- Fixnum now implements [`num::Num`](https://docs.rs/num/0.4/num/trait.Num.html) from the [`num`](https://crates.io/crates/num) crate.
- `Default` implementations for `RandomNumberGenerator`, `InitOnce` and `RawMutex`.
### Changed
- A few functions which previously accepted a `Vector<u16>` now accept an `impl Into<Vector2D<u16>>` instead.
## [0.18.1] - 2024/02/06
### Added
- You can now use include_aseprite and include_background_gfx to include files from the out directory using the `$OUT_DIR` token.
- Added `.pause()` and `.resume()` methods to `SoundChannels` to let you pause and resume from where you left off.
## [0.18.0] - 2023/10/31
### Added
- There is now a multiboot feature which you can use to easily make multiboot ROMs.
- Can now set palette on a TileSetting struct.
### Changed
- You no longer need the gba.ld or gba_mb.ld files in your repository. You should delete these when upgrading.
### Fixed
- Multiboot builds now work on mgba.
- Fixed inaccuracy in cosine implementation caused by accidentally multiplying correction term by zero.
## [0.17.1] - 2023/10/05
### Fixed
- Fixed the build on docs.rs.
## [0.17.0] - 2023/10/03
### Added
- New tracker for playing XM files (see the `agb-tracker` crate).
- You can now declare where looping sound channels should restart.
- Fixnums now have constructors from_f32 and from_f64. This is mainly useful if using agb-fixnum outside of the Game Boy Advance e.g. in build scripts or macros.
- New option when loading a background to automatically deduplicate tiles.
- Methods on tile_setting to toggle its hflip and vflip status.
### Changed
- Sound channel panning and volume options are now `Num<i16, 8>` rather than `Num<i16, 4>` for improved precision and sound quality.
- Due to dependency changes, agb-gbafix is now released under MPL rather than GPL.
- `include_background_gfx!` now produces tile sets and tile settings directly.
### Fixed
- 256-colour backgrounds are better supported.
- Mono looping samples will now correctly play to the end if it doesn't perfectly align with a buffer boundry and short samples now also loop correctly.
- Fixed a bug in bitmap4 that caused setting pixels to be always incorrect.
## [0.16.0] - 2023/07/18
### Added
- New `include_palette` macro for including every colour in an image as a `u16` slice.
- New object based text renderer.
### Changed
- Changed the default template game. - Changed the default template game.
- `DynamicSprite` has a new API which changes the constructor and adds a `set_pixel` method. - `DynamicSprite` has a new API which changes the constructor and adds a `set_pixel` and `clear` methods.
- You no longer need to install arm-none-eabi-binutils. In order to write games using `agb`, you now only need to install rust nightly.
- 10% performance improvement with the software mixer.
### Fixed
- Compile error if you tried to import a larger sprite which uses more than 15 colours between frames.
## [0.15.0] - 2023/04/25 ## [0.15.0] - 2023/04/25
### Added ### Added
- You can now import aseprite files directly (in addition to the already supported png and bmp files) when importing background tiles. - You can now import aseprite files directly (in addition to the already supported png and bmp files) when importing background tiles.
- New additional unmanaged object API for interacting with a more straightforward manner with the underlying hardware. - New additional unmanaged object API for interacting with a more straightforward manner with the underlying hardware.
### Changed ### Changed
- Importing background tiles has been improved. You no longer need to use `include_background_gfx!` with the toml file. Instead, use `include_background_gfx`. See the documentation for usage.
- The hashmap implementation is now it its own crate, `agb-hashmap`. There is no change in API, but you can now use this for interop between non-agb code and agb code - Importing background tiles has been improved. You no longer need to use `include_gfx!` with the toml file. Instead, use `include_background_gfx`. See the documentation for usage.
- The hashmap implementation is now it its own crate, `agb-hashmap`. There is no change in API, but you can now use this for interop between non-agb code and agb code.
- Moved the existing object API to be the OamManaged API. The old names persist with deprecated notices on them. - Moved the existing object API to be the OamManaged API. The old names persist with deprecated notices on them.
## [0.14.0] - 2023/04/11 ## [0.14.0] - 2023/04/11
### Added ### Added
- Added custom `gbafix` implementation which can take the elf file produced by `cargo build` directly, removing the need for the objcopy step. - Added custom `gbafix` implementation which can take the elf file produced by `cargo build` directly, removing the need for the objcopy step.
### Changed ### Changed
- Made Vector2D::new a const function. - Made Vector2D::new a const function.
- The template now uses rust 2021 edition by default. - The template now uses rust 2021 edition by default.
- All objects which should only be created once now have the correct lifetimes to only allow one to exist. - All objects which should only be created once now have the correct lifetimes to only allow one to exist.
@ -38,7 +247,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Soundness issues with interrupts resolved which makes them unsafe and require the closure to be static (breaking change). - Soundness issues with interrupts resolved which makes them unsafe and require the closure to be static (breaking change).
### Fixed ### Fixed
- Alpha channel is now considered by `include_background_gfx!()` even when `transparent_colour` is absent.
- Alpha channel is now considered by `include_gfx!()` even when `transparent_colour` is absent.
- 256 colour backgrounds are now correctly rendered (breaking change). - 256 colour backgrounds are now correctly rendered (breaking change).
- The `#[agb::entry]` macro now reports errors better. - The `#[agb::entry]` macro now reports errors better.
- Added the shstrtab section to the linker to ensure that agb builds with lld. - Added the shstrtab section to the linker to ensure that agb builds with lld.
@ -46,14 +256,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [0.13.0] - 2023/01/19 ## [0.13.0] - 2023/01/19
### Added ### Added
- Added missed implementations of `regular()` and `affine()` to `Tiled1` which made `Tiled1` impossible to use. - Added missed implementations of `regular()` and `affine()` to `Tiled1` which made `Tiled1` impossible to use.
### Changed ### Changed
- Text renderer can now be re-used which is useful for rpg style character/word at a time text boxes. - Text renderer can now be re-used which is useful for rpg style character/word at a time text boxes.
- Audio now automatically uses interrupts, so you can remove the `setup_interrupt_handler` or `after_vblank` calls to the mixer. - Audio now automatically uses interrupts, so you can remove the `setup_interrupt_handler` or `after_vblank` calls to the mixer.
- If a vblank happens outside of `wait_for_vblank`, then next call will immediately return. - If a vblank happens outside of `wait_for_vblank`, then next call will immediately return.
### Fixed ### Fixed
- Zero volume now plays no sound. - Zero volume now plays no sound.
- Fixed issue where volume was incorrect for volumes which were powers of 2. - Fixed issue where volume was incorrect for volumes which were powers of 2.
@ -62,6 +275,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
This is a minor release to fix an alignment issue with background tiles. This is a minor release to fix an alignment issue with background tiles.
### Fixed ### Fixed
- Corrected alignment of background tiles which was causing issues with rendering tiles in some cases. - Corrected alignment of background tiles which was causing issues with rendering tiles in some cases.
## [0.12.1] - 2022/10/12 ## [0.12.1] - 2022/10/12
@ -69,6 +283,7 @@ This is a minor release to fix an alignment issue with background tiles.
This is a minor release to fix the build of the docs on [docs.rs/agb](https://docs.rs/agb). This is a minor release to fix the build of the docs on [docs.rs/agb](https://docs.rs/agb).
### Fixed ### Fixed
- Fixed the agb crate's docs.rs build - Fixed the agb crate's docs.rs build
## [0.12.0] - 2022/10/11 ## [0.12.0] - 2022/10/11
@ -81,6 +296,7 @@ This version of `agb` has some exciting new features we'd like to highlight and
We also had a contribution by @ijc8. We can't thank you all enough! We also had a contribution by @ijc8. We can't thank you all enough!
### Added ### Added
- Custom allocator support using the `Allocator` trait for `HashMap`. This means the `HashMap` can be used with `InternalAllocator` to allocate to IWRAM or the `ExternalAllocator` to explicitly allocate to EWRAM. - Custom allocator support using the `Allocator` trait for `HashMap`. This means the `HashMap` can be used with `InternalAllocator` to allocate to IWRAM or the `ExternalAllocator` to explicitly allocate to EWRAM.
- Support for using windows on the GBA. Windows are used to selectively enable rendering of certain layers or effects. - Support for using windows on the GBA. Windows are used to selectively enable rendering of certain layers or effects.
- Support for the blend mode of the GBA. Blending allows for alpha blending between layers and fading to black and white. - Support for the blend mode of the GBA. Blending allows for alpha blending between layers and fading to black and white.
@ -93,6 +309,7 @@ We also had a contribution by @ijc8. We can't thank you all enough!
- Added support for dynamic sprites generated at runtime, some parts of this may change significantly so breaking changes are expected here. - Added support for dynamic sprites generated at runtime, some parts of this may change significantly so breaking changes are expected here.
### Changed ### Changed
- Many of the places that originally disabled IRQs now use the `sync` module, reducing the chance of missed interrupts. - Many of the places that originally disabled IRQs now use the `sync` module, reducing the chance of missed interrupts.
- HashMap iterators now implement `size_hint` which should result in slightly better generation of code using those iterators. - HashMap iterators now implement `size_hint` which should result in slightly better generation of code using those iterators.
- Transparency of backgrounds is now set once in the toml file rather than once for every image. - Transparency of backgrounds is now set once in the toml file rather than once for every image.
@ -101,6 +318,7 @@ We also had a contribution by @ijc8. We can't thank you all enough!
- `testing` is now a default feature, so you no longer need to add a separate `dev-dependencies` line for `agb` in order to enable unit tests for your project. - `testing` is now a default feature, so you no longer need to add a separate `dev-dependencies` line for `agb` in order to enable unit tests for your project.
### Fixed ### Fixed
- Fixed the fast magnitude function in agb_fixnum. This is also used in fast_normalise. Previously only worked for positive (x, y). - Fixed the fast magnitude function in agb_fixnum. This is also used in fast_normalise. Previously only worked for positive (x, y).
- Fixed formatting of fixed point numbers in the range (-1, 0), which previously appeared positive. - Fixed formatting of fixed point numbers in the range (-1, 0), which previously appeared positive.
@ -109,14 +327,17 @@ We also had a contribution by @ijc8. We can't thank you all enough!
Version 0.11.1 brings documentation for fixed point numbers. We recommend all users upgrade to this version since it also includes fixes to a few functions in fixnum. See changed section for breaking changes. Version 0.11.1 brings documentation for fixed point numbers. We recommend all users upgrade to this version since it also includes fixes to a few functions in fixnum. See changed section for breaking changes.
### Added ### Added
- Support for sprites that are not square. - Support for sprites that are not square.
- Docs for fixed point numbers. - Docs for fixed point numbers.
### Changed ### Changed
- `Rect::contains_point` now considers points on the boundary to be part of the rectangle. - `Rect::contains_point` now considers points on the boundary to be part of the rectangle.
- Signature of `Rect::overlapping_rect` changed to return an Option. Returns None if rectangles don't overlap. - Signature of `Rect::overlapping_rect` changed to return an Option. Returns None if rectangles don't overlap.
### Fixed ### Fixed
- Fixed point sine calculates the sine correctly. - Fixed point sine calculates the sine correctly.
## [0.10.0] - 2022/07/31 ## [0.10.0] - 2022/07/31
@ -124,6 +345,7 @@ Version 0.11.1 brings documentation for fixed point numbers. We recommend all us
Version 0.10.0 brings about many new features. As with most `agb` upgrades, you will need to update your `gba.ld` and `gba_mb.ld` files which you can find in the [template repo](https://github.com/agbrs/template). We would also recommend copying the `[profile.dev]` and `[profile.release]` sections from `Cargo.toml` if you don't have these values already. Version 0.10.0 brings about many new features. As with most `agb` upgrades, you will need to update your `gba.ld` and `gba_mb.ld` files which you can find in the [template repo](https://github.com/agbrs/template). We would also recommend copying the `[profile.dev]` and `[profile.release]` sections from `Cargo.toml` if you don't have these values already.
### Added ### Added
- [Hyperspace roll](https://lostimmortal.itch.io/hyperspace-roll), a new game built for the GMTK Game Jam 2022 using `agb`. The source code can be found in the `examples` directory. - [Hyperspace roll](https://lostimmortal.itch.io/hyperspace-roll), a new game built for the GMTK Game Jam 2022 using `agb`. The source code can be found in the `examples` directory.
- Started using GitHub discussions as a forum - Started using GitHub discussions as a forum
- Many functions previously undocumented are now documented - Many functions previously undocumented are now documented
@ -140,6 +362,7 @@ Version 0.10.0 brings about many new features. As with most `agb` upgrades, you
- Random number generator in agb::rng - Random number generator in agb::rng
### Changed ### Changed
- Audio system optimisations - reduced CPU usage by more than 50% - Audio system optimisations - reduced CPU usage by more than 50%
- Background tiles are now removed from Video RAM during `commit()` if they are no longer used rather than immediately reducing flickering - Background tiles are now removed from Video RAM during `commit()` if they are no longer used rather than immediately reducing flickering
- Improved the README for both the main agb crate and the template - Improved the README for both the main agb crate and the template
@ -149,9 +372,11 @@ Version 0.10.0 brings about many new features. As with most `agb` upgrades, you
- A few methods accepting `Num<..>` have been changed to accept `impl Into<Num<..>>` to make them easier to use - A few methods accepting `Num<..>` have been changed to accept `impl Into<Num<..>>` to make them easier to use
### Removed ### Removed
- The ability to use timer0 and timer1 through the `timer` module. This was done in order to fully support 32kHz audio - The ability to use timer0 and timer1 through the `timer` module. This was done in order to fully support 32kHz audio
### Fixed ### Fixed
- Sprite data is now correctly aligned so fast copies will always work - Sprite data is now correctly aligned so fast copies will always work
- A few methods which should really be internal have had `pub` removed - A few methods which should really be internal have had `pub` removed
- The crate now compiles (but does not run) doctests in CI which pointed out a large number of non-compiling examples - The crate now compiles (but does not run) doctests in CI which pointed out a large number of non-compiling examples

49
Cargo.toml Normal file
View file

@ -0,0 +1,49 @@
[workspace]
resolver = "2"
# unfortunately we can't include 'agb' or anything which compiles to non-native code
# in the workspace here, and they need to be tracked separately.
members = [
# "agb"
"agb-debug",
"agb-fixnum",
"agb-gbafix",
"agb-hashmap",
"agb-image-converter",
"agb-macros",
"agb-sound-converter",
"tracker/agb-midi",
"tracker/agb-midi-core",
"tracker/agb-tracker-interop",
# "tracker/agb-tracker",
"tracker/agb-xm",
"tracker/agb-xm-core",
"tracker/desktop-player",
"tools",
"emulator/mgba",
"emulator/mgba-sys",
"emulator/test-runner",
"emulator/screenshot-generator",
"website/backtrace",
]
exclude = [
"agb",
"tracker/agb-tracker",
"examples/amplitude",
"examples/combo",
"examples/hyperspace-roll",
"examples/the-dungeon-puzzlers-lament",
"examples/the-hat-chooses-the-wizard",
"examples/the-purple-night",
"book/games/pong",
"template",
]

View file

@ -16,11 +16,11 @@ without needing to have extensive knowledge of its low-level implementation.
agb provides the following features: agb provides the following features:
* Simple build process with minimal dependencies - Simple build process with minimal dependencies
* Built in importing of sprites, backgrounds, music and sound effects - Built in importing of sprites, backgrounds, music and sound effects
* High performance audio mixer - High performance audio mixer and optional tracker which can play `.xm` files
* Easy to use sprite and tiled background usage - Easy to use sprite and tiled background usage
* A global allocator allowing for use of both `core` and `alloc` - A global allocator allowing for use of both `core` and `alloc`
The documentation for the latest release can be found on The documentation for the latest release can be found on
[docs.rs](https://docs.rs/agb/latest/agb/). [docs.rs](https://docs.rs/agb/latest/agb/).
@ -32,7 +32,7 @@ The best way to get started with agb is to use the template, either within the
Once you have done this, you will find further instructions within the README in the template. Once you have done this, you will find further instructions within the README in the template.
There is an (in progress) tutorial which you can find on the [project website](https://agbrs.github.io/agb/). There is an (in progress) tutorial which you can find on the [project website](https://agbrs.dev/).
## Help / Support ## Help / Support
@ -41,35 +41,29 @@ is a great place to get help from the creators and contributors.
Feel free to [create a new discussion in the Q&A category](https://github.com/agbrs/agb/discussions/new?category=Q-A) and we'll do our best to help! Feel free to [create a new discussion in the Q&A category](https://github.com/agbrs/agb/discussions/new?category=Q-A) and we'll do our best to help!
## Contributing to agb itself ## Contributing to agb itself
In order to contribute to agb itself, you will need a few extra tools on top of what you would need In order to contribute to agb itself, you will need a few extra tools on top of what you would need
to just write games for the Game Boy Advance using this library: to just write games for the Game Boy Advance using this library:
* Recent rustup, see [the rust website](https://www.rust-lang.org/tools/install) - Recent rustup, see [the rust website](https://www.rust-lang.org/tools/install)
for instructions for your operating system. for instructions for your operating system.
* You can update rustup with `rustup update`, or using your package manager - You can update rustup with `rustup self update`, or using your package manager
if you obtained rustup in this way. if you obtained rustup in this way.
* arm eabi binutils - libelf and cmake
* Debian and derivatives: `sudo apt install binutils-arm-none-eabi` - Debian and derivatives: `sudo apt install libelf-dev cmake`
* Arch Linux and derivatives: `pacman -S arm-none-eabi-binutils` - Arch Linux and derivatives: `pacman -S libelf cmake`
* Windows can apparently use the [GNU Arm Embedded Toolchain](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads). - mgba-test-runner
Make sure to select "Add path to environment variable" during the install. - Run `cargo install --path emulator/test-runner` inside this directory
* This process has only been tested on Ubuntu and Arch Linux. - [The 'just' build tool](https://github.com/casey/just)
* libelf and cmake - Install with `cargo install just`
* Debian and derivatives: `sudo apt install libelf-dev cmake` - [mdbook](https://rust-lang.github.io/mdBook/index.html)
* Arch Linux and derivatives: `pacman -S libelf cmake` - Install with `cargo install mdbook`
* mgba-test-runner - [miri](https://github.com/rust-lang/miri)
* Run `cargo install --path mgba-test-runner` inside this directory - Some of the unsafe code is tested using miri, install with `rustup component add miri`
* [The 'just' build tool](https://github.com/casey/just)
* Install with `cargo install just`
* [mdbook](https://rust-lang.github.io/mdBook/index.html)
* Install with `cargo install mdbook`
* [miri](https://github.com/rust-lang/miri)
* Some of the unsafe code is tested using miri, install with `rustup component add miri`
With all of this installed, you should be able to run a full build of agb using by running With all of this installed, you should be able to run a full build of agb using by running
```sh ```sh
just ci just ci
``` ```
@ -78,17 +72,21 @@ Note that before you create a PR, please file an issue so we can discuss what yo
## Structure of the repo ## Structure of the repo
`agb-debug` - a tool you can use to decode agb stacktraces
`agb-fixnum` - a simple fixed point number storage since the GBA doesn't have a floating point unit, so required `agb-fixnum` - a simple fixed point number storage since the GBA doesn't have a floating point unit, so required
for performant decimals. for performant decimals.
`agb-gbafix` - a clean-room reimplementation of the gbafix utility that accepts elf files rather than binaries
`agb-hashmap` - an no_std hashmap implementation tuned for use on the game boy advance
`agb-image-converter` - a crate which converts images in normal formats to a format supported by the game boy advance `agb-image-converter` - a crate which converts images in normal formats to a format supported by the game boy advance
`agb-macros` - miscellaneous proc-macros which have to be in a different crate `agb-macros` - miscellaneous proc-macros which have to be in a different crate
`agb-sound-converter` - a crate which converts wav files into a format supported by the game boy advance `agb-sound-converter` - a crate which converts wav files into a format supported by the game boy advance
`agb-hashmap` - an no_std hashmap implementation tuned for use on the game boy advance
`agb` - the main library code `agb` - the main library code
`agb/examples` - basic examples often targeting 1 feature, you can run these using `just run-example <example-name>` `agb/examples` - basic examples often targeting 1 feature, you can run these using `just run-example <example-name>`
@ -97,12 +95,18 @@ for performant decimals.
`book/games` - games made as part of the tutorial `book/games` - games made as part of the tutorial
`emulator` - Rust bindings for the [mgba](https://mgba.io) emulator along with the test runner you can use to run unit tests
`examples` - bigger examples of a complete game, made during game jams `examples` - bigger examples of a complete game, made during game jams
`mgba-test-runner` - a wrapper around the [mgba](https://mgba.io) emulator which allows us to write unit tests in rust
`template` - the source for the [template repository](https://github.com/agbrs/template) `template` - the source for the [template repository](https://github.com/agbrs/template)
`tools` - misc. tools used in the development of `agb` itself
`tracker` - crates that make up the `agb-tracker` library which allows playing of tracker files
`website` - the source of [the website](https://agbrs.dev)
## Stability ## Stability
While agb is in the pre-1.0 phase, we follow a semi-semantic versioning scheme to ensure compatibility between minor releases. While agb is in the pre-1.0 phase, we follow a semi-semantic versioning scheme to ensure compatibility between minor releases.
@ -114,17 +118,14 @@ Once agb reaches version 1.0, we will transition to stronger semantic versioning
agb would not be possible without the help from the following (non-exhaustive) list of projects: agb would not be possible without the help from the following (non-exhaustive) list of projects:
* The amazing work of the [rust-console](https://github.com/rust-console) for making this all possible in the first place - The amazing work of the [rust-console](https://github.com/rust-console) for making this all possible in the first place
* The [asefile](https://crates.io/crates/asefile) crate for loading aseprite files - The [asefile](https://crates.io/crates/asefile) crate for loading aseprite files
* [agbabi](https://github.com/felixjones/agbabi) for providing high performance alternatives to common methods - [agbabi](https://github.com/felixjones/agbabi) for providing high performance alternatives to common methods
* [mgba](https://mgba.io) for all the useful debugging / developer tools built in to the emulator - [mgba](https://mgba.io) for all the useful debugging / developer tools built in to the emulator
## Licence ## Licence
agb and all its subcrates (except agb-gbafix) are released under MPL version 2.0. See full licence agb and all its subcrates are released under MPL version 2.0. See full licence text in the `LICENSE` file.
text in the `LICENSE` file.
agb-gbafix is released under GPL version 3.0. See the full licence in the agb-gbafix/LICENSE file
agb contains a subset of the code from [agbabi](https://github.com/felixjones/agbabi) which is released under a zlib style licence, agb contains a subset of the code from [agbabi](https://github.com/felixjones/agbabi) which is released under a zlib style licence,
details for which you can find under `agb/src/agbabi`. details for which you can find under `agb/src/agbabi`.

19
agb-debug/Cargo.toml Normal file
View file

@ -0,0 +1,19 @@
[package]
name = "agb-debug"
version = "0.21.1"
edition = "2021"
authors = ["Gwilym Inzani <email@gwilym.dev>"]
license = "MPL-2.0"
description = "CLI utility to convert agb stack trace dumps into human readable stack traces"
repository = "https://github.com/agbrs/agb"
[dependencies]
addr2line = { version = "0.24", default-features = false, features = ["rustc-demangle"] }
gimli = { version = "0.31", default-features = false, features = ["endian-reader", "std"] }
object = { version = "0.36", default-features = false, features = ["read"] }
thiserror = "2"
clap = { version = "4", features = ["derive"] }
colored = "2"
rmp-serde = "1"
lz4_flex = "0.11"

View file

@ -0,0 +1,166 @@
use std::{slice::ChunksExact, sync::OnceLock};
use thiserror::Error;
const ALPHABET: &[u8] = b"0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";
#[derive(Debug, Error)]
pub enum GwilymDecodeError {
#[error("Does not contain version")]
NoVersion,
#[error("Only version 1 is supported")]
WrongVersion,
#[error("Input must be a multiple of 3 but have {0}")]
LengthWrong(usize),
}
pub fn gwilym_decode(input: &str) -> Result<GwilymDecodeIter<'_>, GwilymDecodeError> {
GwilymDecodeIter::new(input)
}
pub struct GwilymDecodeIter<'a> {
chunks: ChunksExact<'a, u8>,
}
impl<'a> GwilymDecodeIter<'a> {
fn new(input: &'a str) -> Result<Self, GwilymDecodeError> {
let input = input
.strip_prefix("https://agbrs.dev/crash#")
.unwrap_or(input);
let Some((input, version)) = input.rsplit_once('v') else {
return Err(GwilymDecodeError::NoVersion);
};
if version != "1" {
return Err(GwilymDecodeError::WrongVersion);
}
if input.len() % 3 != 0 {
return Err(GwilymDecodeError::LengthWrong(input.len()));
}
Ok(Self {
chunks: input.as_bytes().chunks_exact(3),
})
}
}
impl Iterator for GwilymDecodeIter<'_> {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
let chunk = self.chunks.next()?;
let value = decode_chunk(chunk);
if value & (1 << 16) != 0 {
let upper_bits = value << 16;
let lower_bits = self.next().unwrap_or(0) & 0xffff;
return Some(upper_bits | lower_bits);
}
Some(value | 0x0800_0000)
}
}
fn decode_chunk(chunk: &[u8]) -> u32 {
let a = get_value_for_char(chunk[0]);
let b = get_value_for_char(chunk[1]);
let c = get_value_for_char(chunk[2]);
(a << (16 - 5)) | (b << (16 - 10)) | c
}
fn get_value_for_char(input: u8) -> u32 {
static REVERSE_ALHPABET: OnceLock<[u8; 128]> = OnceLock::new();
REVERSE_ALHPABET.get_or_init(|| {
let mut result = [0; 128];
for (i, &c) in ALPHABET.iter().enumerate() {
result[c as usize] = i as u8;
}
result
})[input as usize] as u32
}
#[cfg(test)]
mod test {
use super::*;
use std::fmt::Write;
#[test]
fn should_correctly_decode_16s() -> Result<(), GwilymDecodeError> {
assert_eq!(
&gwilym_decode("2QI65Q69306Kv1")?.collect::<Vec<_>>(),
&[0x0800_16d3, 0x0800_315b, 0x0800_3243, 0x0800_0195]
);
Ok(())
}
fn encode_16(input: u16) -> [u8; 3] {
let input = input as usize;
[
ALPHABET[input >> (16 - 5)],
ALPHABET[(input >> (16 - 10)) & 0b11111],
ALPHABET[input & 0b111111],
]
}
fn encode_32(input: u32) -> [u8; 6] {
let input = input as usize;
let output_lower_16 = encode_16(input as u16);
let input_upper_16 = input >> 16;
[
ALPHABET[(input_upper_16 >> (16 - 5)) | (1 << 5)],
ALPHABET[(input_upper_16 >> (16 - 10)) & 0b11111],
ALPHABET[input_upper_16 & 0b111111],
output_lower_16[0],
output_lower_16[1],
output_lower_16[2],
]
}
#[test]
fn should_correctly_decode_16s_and_32s() -> Result<(), Box<dyn std::error::Error>> {
let trace: &[u32] = &[
0x0300_2990,
0x0800_3289,
0x0500_2993,
0x3829_2910,
0xffff_ffff,
0x0000_0000,
];
let mut result = String::new();
for &ip in trace {
if ip & 0xFFFF_0000 == 0x0800_0000 {
let encoded = encode_16(ip as u16);
let encoded_s = std::str::from_utf8(&encoded)?;
write!(&mut result, "{encoded_s}")?
} else {
let encoded = encode_32(ip);
let encoded_s = std::str::from_utf8(&encoded)?;
write!(&mut result, "{encoded_s}")?
}
}
write!(&mut result, "v1")?;
assert_eq!(&gwilym_decode(&result)?.collect::<Vec<_>>(), trace);
Ok(())
}
#[test]
fn should_strip_the_agbrsdev_prefix() -> Result<(), Box<dyn std::error::Error>> {
assert_eq!(
&gwilym_decode("https://agbrs.dev/crash#2QI65Q69306Kv1")?.collect::<Vec<_>>(),
&[0x0800_16d3, 0x0800_315b, 0x0800_3243, 0x0800_0195]
);
Ok(())
}
}

93
agb-debug/src/lib.rs Normal file
View file

@ -0,0 +1,93 @@
mod gwilym_encoding;
mod load_dwarf;
use addr2line::gimli;
pub use gwilym_encoding::{gwilym_decode, GwilymDecodeError};
pub use load_dwarf::{load_dwarf, GimliDwarf, LoadDwarfError};
use thiserror::Error;
pub use addr2line;
pub struct AddressInfo {
pub location: Location,
pub is_interesting: bool,
pub is_inline: bool,
pub function: String,
}
#[derive(Debug, Error)]
pub enum AddressInfoError {
#[error(transparent)]
Gimli(#[from] gimli::Error),
}
pub struct Location {
pub filename: String,
pub line: u32,
pub col: u32,
}
pub type Addr2LineContext = addr2line::Context<gimli::EndianRcSlice<gimli::RunTimeEndian>>;
impl Default for Location {
fn default() -> Self {
Self {
filename: "??".to_string(),
line: 0,
col: 0,
}
}
}
pub fn address_info(
ctx: &Addr2LineContext,
address: u64,
) -> Result<Vec<AddressInfo>, AddressInfoError> {
let mut frames = ctx.find_frames(address).skip_all_loads()?;
let mut is_first = true;
let mut infos = Vec::new();
while let Some(frame) = frames.next()? {
let function_name = if let Some(ref func) = frame.function {
func.demangle()?.into_owned()
} else {
"unknown function".to_string()
};
let location = frame
.location
.as_ref()
.map(|location| Location {
filename: location.file.unwrap_or("??").to_owned(),
line: location.line.unwrap_or(0),
col: location.column.unwrap_or(0),
})
.unwrap_or_default();
let is_interesting = is_interesting_function(&function_name, &location.filename);
infos.push(AddressInfo {
location,
is_interesting,
is_inline: !is_first,
function: function_name,
});
is_first = false;
}
Ok(infos)
}
fn is_interesting_function(function_name: &str, path: &str) -> bool {
if function_name == "rust_begin_unwind" {
return false; // this is the unwind exception call
}
if path.ends_with("panicking.rs") {
return false; // probably part of rust's internal panic mechanisms
}
true
}

View file

@ -0,0 +1,95 @@
use std::{borrow::Cow, collections::HashMap, io::Cursor, rc::Rc};
use addr2line::gimli;
use object::Object;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum LoadDwarfError {
#[error("Gba file is empty")]
GbaFileEmpty,
#[error("Failed to load debug information from ROM file, it might not have been included?")]
NoDebugInformation,
#[error("Failed to load debug information: {0}")]
DeserializationError(#[from] rmp_serde::decode::Error),
#[error(transparent)]
GimliError(#[from] gimli::Error),
}
pub type GimliDwarf = gimli::Dwarf<gimli::EndianRcSlice<gimli::RunTimeEndian>>;
pub fn load_dwarf(file_content: &[u8]) -> Result<GimliDwarf, LoadDwarfError> {
if let Ok(object) = object::File::parse(file_content) {
return Ok(load_from_object(&object)?);
}
// the file might have been padded, so ensure we skip any padding before continuing
let last_non_zero_byte = file_content
.iter()
.rposition(|&b| b != 0)
.ok_or(LoadDwarfError::GbaFileEmpty)?;
let file_content = &file_content[..last_non_zero_byte + 1];
let last_8_bytes = &file_content[file_content.len() - 8..];
let len = u32::from_le_bytes(
last_8_bytes[0..4]
.try_into()
.or(Err(LoadDwarfError::NoDebugInformation))?,
) as usize;
let version = &last_8_bytes[4..];
if version != b"agb1" {
return Err(LoadDwarfError::NoDebugInformation);
}
let compressed_debug_data = &file_content[file_content.len() - len - 8..file_content.len() - 8];
let decompressing_reader =
lz4_flex::frame::FrameDecoder::new(Cursor::new(compressed_debug_data));
let debug_info: HashMap<String, Vec<u8>> = rmp_serde::decode::from_read(decompressing_reader)?;
let dwarf = gimli::Dwarf::load(|id| {
let data = debug_info
.get(id.name())
.map(|data| Cow::Borrowed(data.as_slice()))
.unwrap_or(Cow::Borrowed(&[]));
Result::<_, gimli::Error>::Ok(gimli::EndianRcSlice::new(
Rc::from(&*data),
gimli::RunTimeEndian::Little,
))
})?;
Ok(dwarf)
}
fn load_from_object<'file>(
object: &object::File<'file, &'file [u8]>,
) -> Result<GimliDwarf, gimli::Error> {
let endian = if object.is_little_endian() {
gimli::RunTimeEndian::Little
} else {
gimli::RunTimeEndian::Big
};
fn load_section<'data, Endian>(
id: gimli::SectionId,
file: &impl object::Object<'data>,
endian: Endian,
) -> Result<gimli::EndianRcSlice<Endian>, gimli::Error>
where
Endian: gimli::Endianity,
{
use object::ObjectSection;
let data = file
.section_by_name(id.name())
.and_then(|section| section.uncompressed_data().ok())
.unwrap_or(Cow::Borrowed(&[]));
Ok(gimli::EndianRcSlice::new(Rc::from(&*data), endian))
}
let dwarf = gimli::Dwarf::load(|id| load_section(id, object, endian))?;
Ok(dwarf)
}

123
agb-debug/src/main.rs Normal file
View file

@ -0,0 +1,123 @@
use std::{
borrow::Cow,
error::Error,
fs::{self, File},
io::Read,
path::PathBuf,
time::SystemTime,
};
use agb_debug::{address_info, AddressInfo, Location};
use clap::Parser;
use colored::Colorize;
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Args {
/// The filename of the elf file
elf_path: PathBuf,
/// The output of agb's dump
dump: String,
}
fn main() -> Result<(), Box<dyn Error>> {
let cli = Args::parse();
let modification_time = fs::metadata(&cli.elf_path)?
.modified()
.unwrap_or(SystemTime::UNIX_EPOCH);
let file = fs::read(&cli.elf_path)?;
let dwarf = agb_debug::load_dwarf(&file)?;
let ctx = addr2line::Context::from_dwarf(dwarf)?;
for (i, address) in agb_debug::gwilym_decode(&cli.dump)?.enumerate() {
let infos = address_info(&ctx, address.into())?;
for info in infos {
print_address_info(&info, i, modification_time)?;
}
}
Ok(())
}
fn print_address_info(
info: &AddressInfo,
index: usize,
elf_modification_time: SystemTime,
) -> Result<(), Box<dyn Error>> {
let function_name_to_print = &info.function;
if !info.is_inline {
print!("{index}:\t{function_name_to_print}");
} else {
print!("\t(inlined into) {function_name_to_print}");
}
println!(
" {}:{}",
prettify_path(&info.location.filename).green(),
info.location.line.to_string().green()
);
if info.location.line != 0 && info.is_interesting {
print_line_of_code(&info.location, elf_modification_time)?;
}
Ok(())
}
fn print_line_of_code(
location: &Location,
elf_modification_time: SystemTime,
) -> Result<(), Box<dyn Error>> {
let filename = &location.filename;
let Ok(mut file) = File::open(filename) else {
return Ok(());
};
let modification_time = fs::metadata(filename)?
.modified()
.unwrap_or(SystemTime::UNIX_EPOCH);
if modification_time > elf_modification_time {
eprintln!("Warning: File {filename} modified more recently than the binary, line info may be incorrect");
}
let mut content = String::new();
file.read_to_string(&mut content)?;
let Some(line_of_code) = content.split('\n').nth(location.line as usize - 1) else {
eprintln!("File {filename} does not have line {}", location.line);
return Ok(());
};
let trimmed = line_of_code.trim_start();
let trimmed_len = line_of_code.len() - trimmed.len();
println!("\t\t{}", trimmed);
if location.col != 0 {
println!(
"\t\t{}{}",
" ".repeat(location.col as usize - trimmed_len - 1),
"^".bright_blue()
);
}
Ok(())
}
fn prettify_path(path: &str) -> Cow<'_, str> {
if let Some(src_index) = path.rfind("/src/") {
let crate_name_start = path[0..src_index].rfind('/');
let crate_name = crate_name_start
.map(|crate_name_start| &path[crate_name_start + 1..src_index])
.unwrap_or("<crate>");
Cow::Owned(format!("<{crate_name}>/{}", &path[src_index + 5..]))
} else {
Cow::Borrowed(path)
}
}

View file

@ -1,20 +1,12 @@
[package] [package]
name = "agb_fixnum" name = "agb_fixnum"
version = "0.15.0" version = "0.21.1"
edition = "2021" edition = "2021"
license = "MPL-2.0" license = "MPL-2.0"
description = "Library for abstracting over fixed precision numbers. Designed for use with the agb library for the Game Boy Advance" description = "Library for abstracting over fixed precision numbers. Designed for use with the agb library for the Game Boy Advance"
repository = "https://github.com/agbrs/agb" repository = "https://github.com/agbrs/agb"
keywords = ["no-std", "no-std::no-alloc"]
[dependencies] [dependencies]
agb_macros = { version = "0.15.0", path = "../agb-macros" } agb_macros = { version = "0.21.1", path = "../agb-macros" }
num-traits = { version = "0.2", default-features = false }
[profile.dev]
opt-level = 3
debug = true
[profile.release]
opt-level = 3
lto = "fat"
debug = true
codegen-units = 1

View file

@ -11,6 +11,7 @@ use core::{
Sub, SubAssign, Sub, SubAssign,
}, },
}; };
use num_traits::Signed;
#[doc(hidden)] #[doc(hidden)]
/// Used internally by the [num!] macro which should be used instead. /// Used internally by the [num!] macro which should be used instead.
@ -32,73 +33,41 @@ macro_rules! num {
/// A trait for everything required to use as the internal representation of the /// A trait for everything required to use as the internal representation of the
/// fixed point number. /// fixed point number.
pub trait Number: pub trait Number: Copy + PartialOrd + Ord + num_traits::Num {}
Sized
+ Copy
+ PartialOrd
+ Ord
+ PartialEq
+ Eq
+ Add<Output = Self>
+ Sub<Output = Self>
+ Rem<Output = Self>
+ Div<Output = Self>
+ Mul<Output = Self>
{
}
impl<I: FixedWidthUnsignedInteger, const N: usize> Number for Num<I, N> {} impl<I: FixedWidthUnsignedInteger, const N: usize> Number for Num<I, N> {}
impl<I: FixedWidthUnsignedInteger> Number for I {} impl<I: FixedWidthUnsignedInteger> Number for I {}
/// A trait for integers that don't implement unary negation /// A trait for integers that don't implement unary negation
pub trait FixedWidthUnsignedInteger: pub trait FixedWidthUnsignedInteger:
Sized Copy
+ Copy
+ PartialOrd + PartialOrd
+ Ord + Ord
+ PartialEq
+ Eq
+ Shl<usize, Output = Self> + Shl<usize, Output = Self>
+ Shr<usize, Output = Self> + Shr<usize, Output = Self>
+ Add<Output = Self>
+ Sub<Output = Self>
+ Not<Output = Self>
+ BitAnd<Output = Self> + BitAnd<Output = Self>
+ Rem<Output = Self>
+ Div<Output = Self>
+ Mul<Output = Self>
+ From<u8> + From<u8>
+ Debug + Debug
+ Display + Display
+ num_traits::Num
+ Not<Output = Self>
{ {
/// Returns the representation of zero
fn zero() -> Self;
/// Returns the representation of one
fn one() -> Self;
/// Returns the representation of ten /// Returns the representation of ten
fn ten() -> Self; fn ten() -> Self;
/// Converts an i32 to it's own representation, panics on failure /// Converts an i32 to it's own representation, panics on failure
fn from_as_i32(v: i32) -> Self; fn from_as_i32(v: i32) -> Self;
/// Returns (a * b) >> N
fn upcast_multiply(a: Self, b: Self, n: usize) -> Self;
} }
/// Trait for an integer that includes negation /// Trait for an integer that includes negation
pub trait FixedWidthSignedInteger: FixedWidthUnsignedInteger + Neg<Output = Self> { pub trait FixedWidthSignedInteger: FixedWidthUnsignedInteger + num_traits::sign::Signed {}
#[must_use]
/// Returns the absolute value of the number impl<I: FixedWidthUnsignedInteger + Signed> FixedWidthSignedInteger for I {}
fn fixed_abs(self) -> Self;
}
macro_rules! fixed_width_unsigned_integer_impl { macro_rules! fixed_width_unsigned_integer_impl {
($T: ty) => { ($T: ty, $Upcast: ident) => {
impl FixedWidthUnsignedInteger for $T { impl FixedWidthUnsignedInteger for $T {
#[inline(always)]
fn zero() -> Self {
0
}
#[inline(always)]
fn one() -> Self {
1
}
#[inline(always)] #[inline(always)]
fn ten() -> Self { fn ten() -> Self {
10 10
@ -107,36 +76,88 @@ macro_rules! fixed_width_unsigned_integer_impl {
fn from_as_i32(v: i32) -> Self { fn from_as_i32(v: i32) -> Self {
v as $T v as $T
} }
upcast_multiply_impl!($T, $Upcast);
} }
}; };
} }
macro_rules! fixed_width_signed_integer_impl { macro_rules! upcast_multiply_impl {
($T: ty) => { ($T: ty, optimised_64_bit) => {
impl FixedWidthSignedInteger for $T {
#[inline(always)] #[inline(always)]
fn fixed_abs(self) -> Self { fn upcast_multiply(a: Self, b: Self, n: usize) -> Self {
self.abs() use num_traits::One;
let mask = (Self::one() << n).wrapping_sub(1);
let a_floor = a >> n;
let a_frac = a & mask;
let b_floor = b >> n;
let b_frac = b & mask;
(a_floor.wrapping_mul(b_floor) << n)
.wrapping_add(
a_floor
.wrapping_mul(b_frac)
.wrapping_add(b_floor.wrapping_mul(a_frac)),
)
.wrapping_add(((a_frac as u32).wrapping_mul(b_frac as u32) >> n) as $T)
} }
};
($T: ty, $Upcast: ty) => {
#[inline(always)]
fn upcast_multiply(a: Self, b: Self, n: usize) -> Self {
(((a as $Upcast) * (b as $Upcast)) >> n) as $T
} }
}; };
} }
fixed_width_unsigned_integer_impl!(u8); fixed_width_unsigned_integer_impl!(u8, u32);
fixed_width_unsigned_integer_impl!(i16); fixed_width_unsigned_integer_impl!(i16, i32);
fixed_width_unsigned_integer_impl!(u16); fixed_width_unsigned_integer_impl!(u16, u32);
fixed_width_unsigned_integer_impl!(i32);
fixed_width_unsigned_integer_impl!(u32);
fixed_width_unsigned_integer_impl!(usize);
fixed_width_signed_integer_impl!(i16); fixed_width_unsigned_integer_impl!(i32, optimised_64_bit);
fixed_width_signed_integer_impl!(i32); fixed_width_unsigned_integer_impl!(u32, optimised_64_bit);
/// A fixed point number represented using `I` with `N` bits of fractional precision /// A fixed point number represented using `I` with `N` bits of fractional precision
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)] #[repr(transparent)]
pub struct Num<I: FixedWidthUnsignedInteger, const N: usize>(I); pub struct Num<I: FixedWidthUnsignedInteger, const N: usize>(I);
impl<I: FixedWidthUnsignedInteger, const N: usize> num_traits::Zero for Num<I, N> {
fn zero() -> Self {
Self::new(I::zero())
}
fn is_zero(&self) -> bool {
self.to_raw() == I::zero()
}
}
impl<I: FixedWidthUnsignedInteger, const N: usize> num_traits::One for Num<I, N> {
fn one() -> Self {
Self::new(I::one())
}
}
impl<I: FixedWidthUnsignedInteger + num_traits::Num, const N: usize> num_traits::Num for Num<I, N> {
type FromStrRadixErr = <f64 as num_traits::Num>::FromStrRadixErr;
fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
// for some reason, if I don't have this it's an error, and if I do it is unused
#[allow(unused_imports)]
use num_traits::float::FloatCore;
let v: f64 = f64::from_str_radix(str, radix)?;
let integer = v.trunc();
let fractional = v.fract() * (1u64 << 30) as f64;
Ok(Self::new_from_parts((integer as i32, fractional as i32)))
}
}
/// An often convenient representation for the Game Boy Advance using word sized /// An often convenient representation for the Game Boy Advance using word sized
/// internal representation for maximum efficiency /// internal representation for maximum efficiency
pub type FixedNum<const N: usize> = Num<i32, N>; pub type FixedNum<const N: usize> = Num<i32, N>;
@ -204,9 +225,7 @@ where
{ {
type Output = Self; type Output = Self;
fn mul(self, rhs: Num<I, N>) -> Self::Output { fn mul(self, rhs: Num<I, N>) -> Self::Output {
Num(((self.floor() * rhs.floor()) << N) Num(I::upcast_multiply(self.0, rhs.0, N))
+ (self.floor() * rhs.frac() + rhs.floor() * self.frac())
+ ((self.frac() * rhs.frac()) >> N))
} }
} }
@ -345,6 +364,20 @@ impl<I: FixedWidthUnsignedInteger, const N: usize> Num<I, N> {
self.0 self.0
} }
/// Lossily transforms an f32 into a fixed point representation. This is not const
/// because you cannot currently do floating point operations in const contexts, so
/// you should use the `num!` macro from agb-macros if you want a const from_f32/f64
pub fn from_f32(input: f32) -> Self {
Self::from_raw(I::from_as_i32((input * (1 << N) as f32) as i32))
}
/// Lossily transforms an f64 into a fixed point representation. This is not const
/// because you cannot currently do floating point operations in const contexts, so
/// you should use the `num!` macro from agb-macros if you want a const from_f32/f64
pub fn from_f64(input: f64) -> Self {
Self::from_raw(I::from_as_i32((input * (1 << N) as f64) as i32))
}
/// Truncates the fixed point number returning the integral part /// Truncates the fixed point number returning the integral part
/// ```rust /// ```rust
/// # use agb_fixnum::*; /// # use agb_fixnum::*;
@ -416,6 +449,7 @@ impl<I: FixedWidthUnsignedInteger, const N: usize> Num<I, N> {
} }
#[doc(hidden)] #[doc(hidden)]
#[inline(always)]
/// Called by the [num!] macro in order to create a fixed point number /// Called by the [num!] macro in order to create a fixed point number
pub fn new_from_parts(num: (i32, i32)) -> Self { pub fn new_from_parts(num: (i32, i32)) -> Self {
Self(I::from_as_i32(((num.0) << N) + (num.1 >> (30 - N)))) Self(I::from_as_i32(((num.0) << N) + (num.1 >> (30 - N))))
@ -467,7 +501,7 @@ impl<I: FixedWidthSignedInteger, const N: usize> Num<I, N> {
/// assert_eq!(n.abs(), num!(5.5)); /// assert_eq!(n.abs(), num!(5.5));
/// ``` /// ```
pub fn abs(self) -> Self { pub fn abs(self) -> Self {
Num(self.0.fixed_abs()) Num(self.0.abs())
} }
/// Calculates the cosine of a fixed point number with the domain of [0, 1]. /// Calculates the cosine of a fixed point number with the domain of [0, 1].
@ -487,17 +521,10 @@ impl<I: FixedWidthSignedInteger, const N: usize> Num<I, N> {
/// ``` /// ```
#[must_use] #[must_use]
pub fn cos(self) -> Self { pub fn cos(self) -> Self {
let one: Self = I::one().into();
let mut x = self; let mut x = self;
let four: I = 4.into(); x -= num!(0.25) + (x + num!(0.25)).floor();
let two: I = 2.into(); x *= (x.abs() - num!(0.5)) * num!(16.);
let sixteen: I = 16.into(); x += x * (x.abs() - num!(1.)) * num!(0.225);
let nine: I = 9.into();
let forty: I = 40.into();
x -= one / four + (x + one / four).floor();
x *= (x.abs() - one / two) * sixteen;
x += x * (x.abs() - one) * (nine / forty);
x x
} }
@ -523,6 +550,28 @@ impl<I: FixedWidthSignedInteger, const N: usize> Num<I, N> {
} }
} }
impl<I: FixedWidthSignedInteger, const N: usize> num_traits::sign::Signed for Num<I, N> {
fn abs(&self) -> Self {
Self::abs(*self)
}
fn abs_sub(&self, other: &Self) -> Self {
Self(self.0.abs_sub(&other.0))
}
fn signum(&self) -> Self {
Self(self.0.signum())
}
fn is_positive(&self) -> bool {
self.0.is_positive()
}
fn is_negative(&self) -> bool {
self.0.is_negative()
}
}
impl<I: FixedWidthUnsignedInteger, const N: usize> Display for Num<I, N> { impl<I: FixedWidthUnsignedInteger, const N: usize> Display for Num<I, N> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let mut integral = self.0 >> N; let mut integral = self.0 >> N;
@ -535,16 +584,44 @@ impl<I: FixedWidthUnsignedInteger, const N: usize> Display for Num<I, N> {
// //
// But if you think of a negative number, you'd like it to be `negative number - non negative fraction` // But if you think of a negative number, you'd like it to be `negative number - non negative fraction`
// So we have to add 1 to the integral bit, and take 1 - fractional bit // So we have to add 1 to the integral bit, and take 1 - fractional bit
if fractional != I::zero() && integral < I::zero() { let sign = if fractional != I::zero() && integral < I::zero() {
integral = integral + I::one(); integral = integral + I::one();
if integral == I::zero() {
// If the number is in the range (-1, 0), then we just bumped `integral` from -1 to 0,
// so we need to compensate for the missing negative sign.
write!(f, "-")?;
}
fractional = (I::one() << N) - fractional; fractional = (I::one() << N) - fractional;
-1
} else {
1
};
if let Some(precision) = f.precision() {
let precision_multiplier = I::from_as_i32(10_i32.pow(precision as u32));
let fractional_as_integer = fractional * precision_multiplier * I::ten();
let mut fractional_as_integer = fractional_as_integer >> N;
if fractional_as_integer % I::ten() >= I::from_as_i32(5) {
fractional_as_integer = fractional_as_integer + I::ten();
} }
let mut fraction_to_write = fractional_as_integer / I::ten();
if fraction_to_write >= precision_multiplier {
integral = integral + I::from_as_i32(sign);
fraction_to_write = fraction_to_write - precision_multiplier;
}
if sign == -1 && integral == I::zero() && fraction_to_write != I::zero() {
write!(f, "-")?;
}
write!(f, "{integral}")?;
if precision != 0 {
write!(f, ".{:#0width$}", fraction_to_write, width = precision)?;
}
} else {
if sign == -1 && integral == I::zero() {
write!(f, "-")?;
}
write!(f, "{integral}")?; write!(f, "{integral}")?;
if fractional != I::zero() { if fractional != I::zero() {
@ -556,6 +633,7 @@ impl<I: FixedWidthUnsignedInteger, const N: usize> Display for Num<I, N> {
write!(f, "{}", (fractional & !mask) >> N)?; write!(f, "{}", (fractional & !mask) >> N)?;
fractional = fractional & mask; fractional = fractional & mask;
} }
}
Ok(()) Ok(())
} }
@ -570,7 +648,7 @@ impl<I: FixedWidthUnsignedInteger, const N: usize> Debug for Num<I, N> {
} }
/// A vector of two points: (x, y) represented by integers or fixed point numbers /// A vector of two points: (x, y) represented by integers or fixed point numbers
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)] #[derive(Clone, Copy, PartialEq, Eq, Debug, Default, Hash)]
pub struct Vector2D<T: Number> { pub struct Vector2D<T: Number> {
/// The x coordinate /// The x coordinate
pub x: T, pub x: T,
@ -658,6 +736,27 @@ impl<T: Number> SubAssign<Self> for Vector2D<T> {
} }
} }
impl<T: Number + Signed> Vector2D<T> {
/// Calculates the absolute value of the x and y components.
pub fn abs(self) -> Self {
Self {
x: self.x.abs(),
y: self.y.abs(),
}
}
#[must_use]
/// Calculates the manhattan distance, x.abs() + y.abs().
/// ```
/// # use agb_fixnum::*;
/// let v1: Vector2D<Num<i32, 8>> = (num!(3.), num!(4.)).into();
/// assert_eq!(v1.manhattan_distance(), 7.into());
/// ```
pub fn manhattan_distance(self) -> T {
self.x.abs() + self.y.abs()
}
}
impl<I: FixedWidthUnsignedInteger, const N: usize> Vector2D<Num<I, N>> { impl<I: FixedWidthUnsignedInteger, const N: usize> Vector2D<Num<I, N>> {
#[must_use] #[must_use]
/// Truncates the x and y coordinate, see [Num::trunc] /// Truncates the x and y coordinate, see [Num::trunc]
@ -702,28 +801,6 @@ impl<I: FixedWidthUnsignedInteger, const N: usize> Vector2D<Num<I, N>> {
} }
impl<const N: usize> Vector2D<Num<i32, N>> { impl<const N: usize> Vector2D<Num<i32, N>> {
#[must_use]
/// Calculates the magnitude squared, ie (x*x + y*y)
/// ```
/// # use agb_fixnum::*;
/// let v1: Vector2D<Num<i32, 8>> = (num!(3.), num!(4.)).into();
/// assert_eq!(v1.magnitude_squared(), 25.into());
/// ```
pub fn magnitude_squared(self) -> Num<i32, N> {
self.x * self.x + self.y * self.y
}
#[must_use]
/// Calculates the manhattan distance, x.abs() + y.abs().
/// ```
/// # use agb_fixnum::*;
/// let v1: Vector2D<Num<i32, 8>> = (num!(3.), num!(4.)).into();
/// assert_eq!(v1.manhattan_distance(), 7.into());
/// ```
pub fn manhattan_distance(self) -> Num<i32, N> {
self.x.abs() + self.y.abs()
}
#[must_use] #[must_use]
/// Calculates the magnitude by square root /// Calculates the magnitude by square root
/// ``` /// ```
@ -819,7 +896,7 @@ impl<I: FixedWidthUnsignedInteger, const N: usize> From<Vector2D<I>> for Vector2
} }
} }
#[derive(Debug, PartialEq, Eq, Clone, Copy)] #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
/// A rectangle with a position in 2d space and a 2d size /// A rectangle with a position in 2d space and a 2d size
pub struct Rect<T: Number> { pub struct Rect<T: Number> {
/// The position of the rectangle /// The position of the rectangle
@ -972,6 +1049,20 @@ impl<T: FixedWidthUnsignedInteger> Rect<T> {
} }
} }
impl<T: Number + Signed> Rect<T> {
/// Makes a rectangle that represents the equivalent location in space but with a positive size
pub fn abs(self) -> Self {
Self {
position: (
self.position.x + self.size.x.min(T::zero()),
self.position.y + self.size.y.min(T::zero()),
)
.into(),
size: self.size.abs(),
}
}
}
impl<T: Number> Vector2D<T> { impl<T: Number> Vector2D<T> {
/// Created a vector from the given coordinates /// Created a vector from the given coordinates
/// ``` /// ```
@ -1011,6 +1102,48 @@ impl<T: Number> Vector2D<T> {
} }
} }
#[doc(alias = "scalar_product")]
/// Calculates the dot product / scalar product of two vectors
/// ```
/// use agb_fixnum::Vector2D;
///
/// let v1 = Vector2D::new(3, 5);
/// let v2 = Vector2D::new(7, 11);
///
/// let dot = v1.dot(v2);
/// assert_eq!(dot, 76);
/// ```
/// The dot product for vectors *A* and *B* is defined as
/// > *A*<sub>*x*</sub> × *B*<sub>*x*</sub> + *A*<sub>*y*</sub> × *B*<sub>*y*</sub>.
pub fn dot(self, b: Self) -> T {
self.x * b.x + self.y * b.y
}
#[doc(alias = "vector_product")]
/// Calculates the *z* component of the cross product / vector product of two
/// vectors
/// ```
/// use agb_fixnum::Vector2D;
///
/// let v1 = Vector2D::new(3, 5);
/// let v2 = Vector2D::new(7, 11);
///
/// let dot = v1.cross(v2);
/// assert_eq!(dot, -2);
/// ```
/// The *z* component cross product for vectors *A* and *B* is defined as
/// > *A*<sub>*x*</sub> × *B*<sub>*y*</sub> - *A*<sub>*y*</sub> × *B*<sub>*x*</sub>.
///
///
/// Normally the cross product / vector product is itself a vector. This is
/// in the 3D case where the cross product of two vectors is perpendicular
/// to both vectors. The only vector perpendicular to two 2D vectors is
/// purely in the *z* direction, hence why this method only returns that
/// component. The *x* and *y* components are always zero.
pub fn cross(self, b: Self) -> T {
self.x * b.y - self.y * b.x
}
#[must_use] #[must_use]
/// Swaps the x and y coordinate /// Swaps the x and y coordinate
/// ``` /// ```
@ -1024,6 +1157,17 @@ impl<T: Number> Vector2D<T> {
y: self.x, y: self.x,
} }
} }
#[must_use]
/// Calculates the magnitude squared, ie (x*x + y*y)
/// ```
/// # use agb_fixnum::*;
/// let v1: Vector2D<Num<i32, 8>> = (num!(3.), num!(4.)).into();
/// assert_eq!(v1.magnitude_squared(), 25.into());
/// ```
pub fn magnitude_squared(self) -> T {
self.x * self.x + self.y * self.y
}
} }
impl<T: Number + Neg<Output = T>> Neg for Vector2D<T> { impl<T: Number + Neg<Output = T>> Neg for Vector2D<T> {
@ -1041,6 +1185,7 @@ mod tests {
use super::*; use super::*;
use alloc::format; use alloc::format;
use num_traits::Num as _;
#[test] #[test]
fn formats_whole_numbers_correctly() { fn formats_whole_numbers_correctly() {
@ -1065,6 +1210,51 @@ mod tests {
assert_eq!(format!("{d}"), "-0.25"); assert_eq!(format!("{d}"), "-0.25");
} }
mod precision {
use super::*;
macro_rules! num_ {
($n: literal) => {{
let a: Num<i32, 20> = num!($n);
a
}};
}
macro_rules! test_precision {
($TestName: ident, $Number: literal, $Expected: literal) => {
test_precision! { $TestName, $Number, $Expected, 2 }
};
($TestName: ident, $Number: literal, $Expected: literal, $Digits: literal) => {
#[test]
fn $TestName() {
assert_eq!(
format!("{:.width$}", num_!($Number), width = $Digits),
$Expected
);
}
};
}
test_precision!(positive_down, 1.2345678, "1.23");
test_precision!(positive_round_up, 1.237, "1.24");
test_precision!(negative_round_down, -1.237, "-1.24");
test_precision!(trailing_zero, 1.5, "1.50");
test_precision!(leading_zero, 1.05, "1.05");
test_precision!(positive_round_to_next_integer, 3.999, "4.00");
test_precision!(negative_round_to_next_integer, -3.999, "-4.00");
test_precision!(negative_round_to_1, -0.999, "-1.00");
test_precision!(positive_round_to_1, 0.999, "1.00");
test_precision!(positive_round_to_zero, 0.001, "0.00");
test_precision!(negative_round_to_zero, -0.001, "0.00");
test_precision!(zero_precision_negative, -0.001, "0", 0);
test_precision!(zero_precision_positive, 0.001, "0", 0);
}
#[test] #[test]
fn sqrt() { fn sqrt() {
for x in 1..1024 { for x in 1..1024 {
@ -1114,6 +1304,26 @@ mod tests {
test_base::<11>(); test_base::<11>();
} }
#[test]
fn check_cos_accuracy() {
let n: Num<i32, 8> = Num::new(1) / 32;
assert_eq!(
n.cos(),
Num::from_f64((2. * core::f64::consts::PI / 32.).cos())
);
}
#[test]
fn check_16_bit_precision_i32() {
let a: Num<i32, 16> = num!(1.923);
let b = num!(2.723);
assert_eq!(
a * b,
Num::from_raw(((a.to_raw() as i64 * b.to_raw() as i64) >> 16) as i32)
)
}
#[test] #[test]
fn test_numbers() { fn test_numbers() {
// test addition // test addition
@ -1292,4 +1502,48 @@ mod tests {
] ]
); );
} }
#[test]
fn test_str_radix() {
use alloc::string::ToString;
macro_rules! str_radix_test {
($val:tt) => {
assert_eq!(
Num::<i32, 8>::from_str_radix(stringify!($val), 10).unwrap(),
num!($val)
);
};
(-$val:tt) => {
assert_eq!(
Num::<i32, 8>::from_str_radix(&("-".to_string() + stringify!($val)), 10)
.unwrap(),
num!(-$val)
);
};
}
str_radix_test!(0.1);
str_radix_test!(0.100000);
str_radix_test!(0000.1000);
str_radix_test!(000000.100000);
str_radix_test!(000000.1);
str_radix_test!(138.229);
str_radix_test!(-138.229);
str_radix_test!(-1321.229231);
}
#[cfg(not(debug_assertions))]
#[test]
fn test_all_multiplies() {
use super::*;
for i in 0..u32::MAX {
let fix_num: Num<_, 7> = Num::from_raw(i);
let upcasted = ((i as u64 * i as u64) >> 7) as u32;
assert_eq!((fix_num * fix_num).to_raw(), upcasted);
}
}
} }

View file

@ -1 +0,0 @@
!Cargo.lock

290
agb-gbafix/Cargo.lock generated
View file

@ -1,290 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "agb-gbafix"
version = "0.15.0"
dependencies = [
"anyhow",
"bytemuck",
"clap",
"elf",
"gbafix",
]
[[package]]
name = "anstream"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e579a7752471abc2a8268df8b20005e3eadd975f585398f17efcfd8d4927371"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is-terminal",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d"
[[package]]
name = "anstyle-parse"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bcd8291a340dd8ac70e18878bc4501dd7b4ff970cfa21c207d36ece51ea88fd"
dependencies = [
"anstyle",
"windows-sys",
]
[[package]]
name = "anyhow"
version = "1.0.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bytemuck"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
[[package]]
name = "cc"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[package]]
name = "clap"
version = "4.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "956ac1f6381d8d82ab4684768f89c0ea3afe66925ceadb4eeb3fc452ffc55d62"
dependencies = [
"clap_builder",
]
[[package]]
name = "clap_builder"
version = "4.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84080e799e54cff944f4b4a4b0e71630b0e0443b25b985175c7dddc1a859b749"
dependencies = [
"anstream",
"anstyle",
"bitflags",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_lex"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1"
[[package]]
name = "colorchoice"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "elf"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2b183d6ce6ca4cf30e3db37abf5b52568b5f9015c97d9fbdd7026aa5dcdd758"
[[package]]
name = "errno"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
dependencies = [
"errno-dragonfly",
"libc",
"windows-sys",
]
[[package]]
name = "errno-dragonfly"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "gbafix"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7e47af9d5377b8b0def53d9916f6c28521f2e5b97c5fec137797417c26ab4b7"
dependencies = [
"bytemuck",
]
[[package]]
name = "hermit-abi"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
[[package]]
name = "io-lifetimes"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
dependencies = [
"hermit-abi",
"libc",
"windows-sys",
]
[[package]]
name = "is-terminal"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
dependencies = [
"hermit-abi",
"io-lifetimes",
"rustix",
"windows-sys",
]
[[package]]
name = "libc"
version = "0.2.142"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317"
[[package]]
name = "linux-raw-sys"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b085a4f2cde5781fc4b1717f2e86c62f5cda49de7ba99a7c2eae02b61c9064c"
[[package]]
name = "rustix"
version = "0.37.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f79bef90eb6d984c72722595b5b1348ab39275a5e5123faca6863bf07d75a4e0"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "utf8parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
[[package]]
name = "windows_i686_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
[[package]]
name = "windows_i686_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"

View file

@ -1,25 +1,15 @@
[package] [package]
name = "agb-gbafix" name = "agb-gbafix"
version = "0.15.0" version = "0.21.1"
edition = "2021" edition = "2021"
authors = ["Gwilym Inzani <email@gwilym.dev>"] authors = ["Gwilym Inzani <email@gwilym.dev>"]
license = "GPL-3.0" license = "MPL-2.0"
description = "CLI utility to convert ELF file to valid GBA ROM" description = "CLI utility to convert ELF file to valid GBA ROM"
repository = "https://github.com/agbrs/agb" repository = "https://github.com/agbrs/agb"
[dependencies] [dependencies]
elf = "0.7" elf = "0.7"
gbafix = "1"
bytemuck = "1"
anyhow = "1" anyhow = "1"
clap = "4" clap = "4"
rmp-serde = "1"
[profile.dev] lz4_flex = "0.11"
opt-level = 3
debug = true
[profile.release]
opt-level = 3
lto = "fat"
debug = true
codegen-units = 1

View file

@ -1,674 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

179
agb-gbafix/src/lib.rs Normal file
View file

@ -0,0 +1,179 @@
use anyhow::{anyhow, bail, ensure, Result};
use std::{collections::HashMap, io::Write};
const GBA_HEADER_SIZE: usize = 192;
const NINTENDO_LOGO: &[u8] = &[
0x24, 0xFF, 0xAE, 0x51, 0x69, 0x9A, 0xA2, 0x21, 0x3D, 0x84, 0x82, 0x0A, 0x84, 0xE4, 0x09, 0xAD,
0x11, 0x24, 0x8B, 0x98, 0xC0, 0x81, 0x7F, 0x21, 0xA3, 0x52, 0xBE, 0x19, 0x93, 0x09, 0xCE, 0x20,
0x10, 0x46, 0x4A, 0x4A, 0xF8, 0x27, 0x31, 0xEC, 0x58, 0xC7, 0xE8, 0x33, 0x82, 0xE3, 0xCE, 0xBF,
0x85, 0xF4, 0xDF, 0x94, 0xCE, 0x4B, 0x09, 0xC1, 0x94, 0x56, 0x8A, 0xC0, 0x13, 0x72, 0xA7, 0xFC,
0x9F, 0x84, 0x4D, 0x73, 0xA3, 0xCA, 0x9A, 0x61, 0x58, 0x97, 0xA3, 0x27, 0xFC, 0x03, 0x98, 0x76,
0x23, 0x1D, 0xC7, 0x61, 0x03, 0x04, 0xAE, 0x56, 0xBF, 0x38, 0x84, 0x00, 0x40, 0xA7, 0x0E, 0xFD,
0xFF, 0x52, 0xFE, 0x03, 0x6F, 0x95, 0x30, 0xF1, 0x97, 0xFB, 0xC0, 0x85, 0x60, 0xD6, 0x80, 0x25,
0xA9, 0x63, 0xBE, 0x03, 0x01, 0x4E, 0x38, 0xE2, 0xF9, 0xA2, 0x34, 0xFF, 0xBB, 0x3E, 0x03, 0x44,
0x78, 0x00, 0x90, 0xCB, 0x88, 0x11, 0x3A, 0x94, 0x65, 0xC0, 0x7C, 0x63, 0x87, 0xF0, 0x3C, 0xAF,
0xD6, 0x25, 0xE4, 0x8B, 0x38, 0x0A, 0xAC, 0x72, 0x21, 0xD4, 0xF8, 0x07,
];
#[derive(Debug, Default)]
pub struct GbaHeader {
pub start_code: [u8; 4],
pub game_title: [u8; 12],
pub game_code: [u8; 4],
pub maker_code: [u8; 2],
pub software_version: u8,
}
impl GbaHeader {
fn produce_header(&self) -> Vec<u8> {
let mut header_result = vec![];
header_result.extend_from_slice(&self.start_code);
header_result.extend_from_slice(NINTENDO_LOGO);
header_result.extend_from_slice(&self.game_title);
header_result.extend_from_slice(&self.game_code);
header_result.extend_from_slice(&self.maker_code);
header_result.push(0x96); // must be 96
header_result.push(0); // main unit code (0 for current GBA models)
header_result.push(0); // device type, usually 0
header_result.extend_from_slice(&[0; 7]); // reserved area, should be zero filled
header_result.push(self.software_version);
let checksum = Self::calculate_checksum(&header_result);
header_result.push(checksum); // checksum
header_result.extend_from_slice(&[0; 2]); // reserved area, should be zero filled
assert_eq!(header_result.len(), GBA_HEADER_SIZE);
header_result
}
fn calculate_checksum(header: &[u8]) -> u8 {
let mut chk = 0u8;
for value in header.iter().take(0xBC).skip(0xA0) {
chk = chk.wrapping_sub(*value);
}
chk = chk.wrapping_sub(0x19);
chk
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum PaddingBehaviour {
Pad,
#[default]
DoNotPad,
}
pub fn write_gba_file<W: Write>(
input: &[u8],
mut header: GbaHeader,
padding_behaviour: PaddingBehaviour,
include_debug: bool,
output: &mut W,
) -> Result<()> {
let elf_file = elf::ElfBytes::<elf::endian::AnyEndian>::minimal_parse(input)?;
let section_headers = elf_file
.section_headers()
.ok_or_else(|| anyhow!("Failed to parse as elf file"))?;
let mut bytes_written = 0;
for section_header in section_headers {
const SHT_NOBITS: u32 = 8;
const SHT_NULL: u32 = 0;
const SHF_ALLOC: u64 = 2;
if (section_header.sh_type == SHT_NOBITS || section_header.sh_type == SHT_NULL)
|| section_header.sh_flags & SHF_ALLOC == 0
{
continue;
}
let align = bytes_written % section_header.sh_addralign;
if align != 0 {
for _ in 0..(section_header.sh_addralign - align) {
output.write_all(&[0])?;
bytes_written += 1;
}
}
let (mut data, compression) = elf_file.section_data(&section_header)?;
if let Some(compression) = compression {
bail!("Cannot decompress elf content, but got compression header {compression:?}");
}
if bytes_written == 0 {
ensure!(
data.len() > GBA_HEADER_SIZE,
"first section must be at least as big as the gba header"
);
header.start_code = data[0..4].try_into().unwrap();
let header_bytes = header.produce_header();
output.write_all(&header_bytes)?;
data = &data[GBA_HEADER_SIZE..];
bytes_written += GBA_HEADER_SIZE as u64;
}
output.write_all(data)?;
bytes_written += data.len() as u64;
}
if include_debug {
bytes_written += write_debug(&elf_file, output)?;
}
if !bytes_written.is_power_of_two() && padding_behaviour == PaddingBehaviour::Pad {
let required_padding = bytes_written.next_power_of_two() - bytes_written;
for _ in 0..required_padding {
output.write_all(&[0])?;
}
}
Ok(())
}
fn write_debug<W: Write>(
elf_file: &elf::ElfBytes<'_, elf::endian::AnyEndian>,
output: &mut W,
) -> Result<u64> {
let (Some(section_headers), Some(string_table)) = elf_file.section_headers_with_strtab()?
else {
bail!("Could not find either the section headers or the string table");
};
let mut debug_sections = HashMap::new();
for section_header in section_headers {
let section_name = string_table.get(section_header.sh_name as usize)?;
if !section_name.starts_with(".debug") {
continue;
}
let (data, compression) = elf_file.section_data(&section_header)?;
if compression.is_some() {
bail!("Do not support compression in elf files, section {section_name} was compressed");
}
debug_sections.insert(section_name.to_owned(), data);
}
let mut debug_data = vec![];
{
let mut compressed_writer = lz4_flex::frame::FrameEncoder::new(&mut debug_data);
rmp_serde::encode::write(&mut compressed_writer, &debug_sections)?;
compressed_writer.flush()?;
}
output.write_all(&debug_data)?;
output.write_all(&(debug_data.len() as u32).to_le_bytes())?;
output.write_all(b"agb1")?;
Ok(debug_data.len() as u64 + 4)
}

View file

@ -1,4 +1,4 @@
use anyhow::{anyhow, bail, ensure, Result}; use anyhow::{anyhow, bail, Result};
use clap::{arg, value_parser}; use clap::{arg, value_parser};
use std::{ use std::{
@ -7,6 +7,8 @@ use std::{
path::PathBuf, path::PathBuf,
}; };
use agb_gbafix::{write_gba_file, GbaHeader, PaddingBehaviour};
fn main() -> Result<()> { fn main() -> Result<()> {
let matches = clap::Command::new("agb-gbafix") let matches = clap::Command::new("agb-gbafix")
.about("Convert elf files directly to a valid GBA ROM") .about("Convert elf files directly to a valid GBA ROM")
@ -16,7 +18,8 @@ fn main() -> Result<()> {
.arg(arg!(-c --gamecode <GAME_CODE> "Sets the game code, 4 bytes")) .arg(arg!(-c --gamecode <GAME_CODE> "Sets the game code, 4 bytes"))
.arg(arg!(-m --makercode <MAKER_CODE> "Set the maker code, 2 bytes")) .arg(arg!(-m --makercode <MAKER_CODE> "Set the maker code, 2 bytes"))
.arg(arg!(-r --gameversion <VERSION> "Set the version of the game, 0-255").value_parser(value_parser!(u8))) .arg(arg!(-r --gameversion <VERSION> "Set the version of the game, 0-255").value_parser(value_parser!(u8)))
.arg(arg!(-p --padding "Ignored for compatibility with gbafix")) .arg(arg!(-p --padding "Pad the ROM to the next power of 2 in size"))
.arg(arg!(-g --debug "Include debug information directly in the ROM"))
.get_matches(); .get_matches();
let input = matches.get_one::<PathBuf>("INPUT").unwrap(); let input = matches.get_one::<PathBuf>("INPUT").unwrap();
@ -25,7 +28,7 @@ fn main() -> Result<()> {
None => input.with_extension("gba"), None => input.with_extension("gba"),
}; };
let mut header = gbafix::GBAHeader::default(); let mut header = GbaHeader::default();
{ {
let title = if let Some(title) = matches.get_one::<String>("title") { let title = if let Some(title) = matches.get_one::<String>("title") {
@ -39,7 +42,7 @@ fn main() -> Result<()> {
}; };
for (i, &c) in title.as_bytes().iter().enumerate().take(12) { for (i, &c) in title.as_bytes().iter().enumerate().take(12) {
header.title[i] = c; header.game_title[i] = c;
} }
} }
@ -59,7 +62,7 @@ fn main() -> Result<()> {
} }
if let Some(game_version) = matches.get_one::<u8>("gameversion") { if let Some(game_version) = matches.get_one::<u8>("gameversion") {
header.version = *game_version; header.software_version = *game_version;
} }
if let Some(game_code) = matches.get_one::<String>("gamecode") { if let Some(game_code) = matches.get_one::<String>("gamecode") {
@ -68,81 +71,27 @@ fn main() -> Result<()> {
} }
} }
let include_debug = matches.get_flag("debug");
let pad = matches.get_flag("padding");
let pad = if pad {
PaddingBehaviour::Pad
} else {
PaddingBehaviour::DoNotPad
};
let mut output = BufWriter::new(fs::File::create(output)?); let mut output = BufWriter::new(fs::File::create(output)?);
let file_data = fs::read(input)?; let file_data = fs::read(input)?;
write_gba_file(file_data.as_slice(), header, &mut output)?; write_gba_file(
file_data.as_slice(),
header,
pad,
include_debug,
&mut output,
)?;
output.flush()?; output.flush()?;
Ok(()) Ok(())
} }
fn write_gba_file<W: Write>(
input: &[u8],
mut header: gbafix::GBAHeader,
output: &mut W,
) -> Result<()> {
let elf_file = elf::ElfBytes::<elf::endian::AnyEndian>::minimal_parse(input)?;
let section_headers = elf_file
.section_headers()
.ok_or_else(|| anyhow!("Failed to parse as elf file"))?;
let mut bytes_written = 0;
for section_header in section_headers.iter() {
const SHT_NOBITS: u32 = 8;
const SHT_NULL: u32 = 0;
const SHF_ALLOC: u64 = 2;
if (section_header.sh_type == SHT_NOBITS || section_header.sh_type == SHT_NULL)
|| section_header.sh_flags & SHF_ALLOC == 0
{
continue;
}
let align = bytes_written % section_header.sh_addralign;
if align != 0 {
for _ in 0..(section_header.sh_addralign - align) {
output.write_all(&[0])?;
bytes_written += 1;
}
}
let (mut data, compression) = elf_file.section_data(&section_header)?;
if let Some(compression) = compression {
bail!("Cannot decompress elf content, but got compression header {compression:?}");
}
if bytes_written == 0 {
const GBA_HEADER_SIZE: usize = 192;
ensure!(
data.len() > GBA_HEADER_SIZE,
"first section must be at least as big as the gba header"
);
header.start_code = data[0..4].try_into().unwrap();
header.update_checksum();
let header_bytes = bytemuck::bytes_of(&header);
output.write_all(header_bytes)?;
data = &data[GBA_HEADER_SIZE..];
bytes_written += GBA_HEADER_SIZE as u64;
}
output.write_all(data)?;
bytes_written += data.len() as u64;
}
if !bytes_written.is_power_of_two() {
let required_padding = bytes_written.next_power_of_two() - bytes_written;
for _ in 0..required_padding {
output.write_all(&[0])?;
}
}
Ok(())
}

View file

@ -1,24 +1,23 @@
[package] [package]
name = "agb_hashmap" name = "agb_hashmap"
version = "0.15.0" version = "0.21.1"
edition = "2021" edition = "2021"
license = "MPL-2.0" license = "MPL-2.0"
description = "A simple no_std hashmap implementation intended for use in the `agb` library" description = "A simple no_std hashmap implementation intended for use in the `agb` library"
repository = "https://github.com/agbrs/agb" repository = "https://github.com/agbrs/agb"
exclude = ["/benches"]
keywords = ["no-std", "data-structures"]
[features]
allocator_api = []
serde = ["dep:serde"]
[dependencies] [dependencies]
rustc-hash = { version = "1", default-features = false } rustc-hash = { version = "1", default-features = false }
serde = { version = "1", default-features = false, optional = true }
[dev-dependencies] [dev-dependencies]
rand = { version = "0.8", default-features = false, features = ["small_rng"] } rand = { version = "0.8", default-features = false, features = ["small_rng"] }
lazy_static = "1.4" lazy_static = "1.4"
quickcheck = "1"
[profile.dev] serde_json = { version = "1", default-features = false, features = ["alloc"] }
opt-level = 3
debug = true
[profile.release]
opt-level = 3
lto = "fat"
debug = true
codegen-units = 1

441
agb-hashmap/src/hash_set.rs Normal file
View file

@ -0,0 +1,441 @@
use crate::{Allocator, ClonableAllocator, Global};
use core::{borrow::Borrow, fmt::Debug, hash::Hash};
use super::HashMap;
/// A `HashSet` is implemented as a [`HashMap`] where the value is `()`.
///
/// As with the [`HashMap`] type, a `HashSet` requires that the elements implement the
/// [`Eq`] and [`Hash`] traits, although this is frequently achieved by using
/// `#[derive(PartialEq, Eq, Hash)]`. If you implement these yourself, it is important
/// that the following property holds:
///
/// It is a logic error for the key to be modified in such a way that the key's hash, as
/// determined by the [`Hash`] trait, or its equality as determined by the [`Eq`] trait,
/// changes while it is in the map. The behaviour for such a logic error is not specified,
/// but will not result in undefined behaviour. This could include panics, incorrect results,
/// aborts, memory leaks and non-termination.
///
/// The API surface provided is incredibly similar to the
/// [`std::collections::HashSet`](https://doc.rust-lang.org/std/collections/struct.HashMap.html)
/// implementation with fewer guarantees, and better optimised for the `GameBoy Advance`.
///
/// [`Eq`]: https://doc.rust-lang.org/core/cmp/trait.Eq.html
/// [`Hash`]: https://doc.rust-lang.org/core/hash/trait.Hash.html
///
/// # Example
///
/// ```
/// use agb_hashmap::HashSet;
///
/// // Type inference lets you omit the type signature (which would be HashSet<String> in this example)
/// let mut games = HashSet::new();
///
/// // Add some games
/// games.insert("Pokemon Emerald".to_string());
/// games.insert("Golden Sun".to_string());
/// games.insert("Super Dodge Ball Advance".to_string());
///
/// // Check for a specific game
/// if !games.contains("Legend of Zelda: The Minish Cap") {
/// println!("We've got {} games, but The Minish Cap ain't one", games.len());
/// }
///
/// // Remove a game
/// games.remove("Golden Sun");
///
/// // Iterate over everything
/// for game in &games {
/// println!("{game}");
/// }
/// ```
#[derive(Clone)]
pub struct HashSet<K, ALLOCATOR: Allocator = Global> {
map: HashMap<K, (), ALLOCATOR>,
}
impl<K> HashSet<K> {
/// Creates a `HashSet`
#[must_use]
pub fn new() -> Self {
Self::new_in(Global)
}
/// Creates an empty `HashSet` with specified internal size. The size must be a power of 2
#[must_use]
pub fn with_size(size: usize) -> Self {
Self::with_size_in(size, Global)
}
/// Creates an empty `HashSet` which can hold at least `capacity` elements before resizing. The actual
/// internal size may be larger as it must be a power of 2
#[must_use]
pub fn with_capacity(capacity: usize) -> Self {
Self::with_capacity_in(capacity, Global)
}
}
impl<K, ALLOCATOR: ClonableAllocator> HashSet<K, ALLOCATOR> {
/// Creates an empty `HashSet` with specified internal size using the specified allocator.
/// The size must be a power of 2
#[must_use]
pub fn with_size_in(size: usize, alloc: ALLOCATOR) -> Self {
Self {
map: HashMap::with_size_in(size, alloc),
}
}
/// Creates a `HashSet` with a specified allocator
#[must_use]
pub fn new_in(alloc: ALLOCATOR) -> Self {
Self::with_size_in(16, alloc)
}
/// Creates an empty `HashSet` which can hold at least `capacity` elements before resizing. The actual
/// internal size may be larger as it must be a power of 2
///
/// # Panics
///
/// Panics if capacity is larger than 2^32 * .85
#[must_use]
pub fn with_capacity_in(capacity: usize, alloc: ALLOCATOR) -> Self {
Self {
map: HashMap::with_capacity_in(capacity, alloc),
}
}
/// Returns a reference to the underlying allocator
pub fn allocator(&self) -> &ALLOCATOR {
self.map.allocator()
}
/// Returns the number of elements in the set
#[must_use]
pub fn len(&self) -> usize {
self.map.len()
}
/// Returns whether or not the set is empty
#[must_use]
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
/// Returns the number of elements the set can hold without resizing
#[must_use]
pub fn capacity(&self) -> usize {
self.map.capacity()
}
/// Removes all elements from the set
pub fn clear(&mut self) {
self.map.clear();
}
/// An iterator visiting all the values in the set
pub fn iter(&self) -> impl Iterator<Item = &'_ K> {
self.map.keys()
}
/// Retains only the elements specified by the predicate `f`
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&K) -> bool,
{
self.map.retain(|k, _| f(k));
}
}
impl<K> Default for HashSet<K> {
fn default() -> Self {
Self::new()
}
}
impl<K, ALLOCATOR: ClonableAllocator> HashSet<K, ALLOCATOR>
where
K: Eq + Hash,
{
/// Inserts a value into the set. This does not replace the value if it already existed.
///
/// Returns whether the value was newly inserted, that is:
///
/// * If the set did not previously contain this value, `true` is returned
/// * If the set already contained this value, `false` is returned.
///
/// # Examples
///
/// ```
/// use agb_hashmap::HashSet;
///
/// let mut set = HashSet::new();
/// assert_eq!(set.insert(2), true);
/// assert_eq!(set.insert(2), false);
/// assert_eq!(set.len(), 1);
/// ```
pub fn insert(&mut self, value: K) -> bool {
self.map.insert(value, ()).is_none()
}
/// Removes a value from the set. Returns whether the value was present in the set.
///
/// # Examples
/// ```
/// use agb_hashmap::HashSet;
///
/// let mut set = HashSet::new();
/// set.insert(2);
///
/// assert_eq!(set.remove(&2), true);
/// assert_eq!(set.remove(&2), false);
/// assert!(set.is_empty());
/// ```
pub fn remove<Q>(&mut self, value: &Q) -> bool
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
self.map.remove(value).is_some()
}
/// Returns `true` if the set contains the value `value`.
///
/// # Examples
///
/// ```
/// use agb_hashmap::HashSet;
///
/// let set = HashSet::from([1, 2, 3]);
/// assert_eq!(set.contains(&1), true);
/// assert_eq!(set.contains(&4), false);
/// ```
pub fn contains<Q>(&self, value: &Q) -> bool
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
self.map.contains_key(value)
}
/// Visits the values reperesting the difference i.e. the values that are in `self` but not in `other`.
///
/// # Examples
///
/// ```
/// use agb_hashmap::HashSet;
///
/// let a = HashSet::from([1, 2, 3]);
/// let b = HashSet::from([4, 2, 3, 4]);
///
/// // Can be seen as `a - b`
/// let diff: HashSet<_> = a.difference(&b).collect();
/// assert_eq!(diff, HashSet::from([&1]));
///
/// // Difference is not symmetric. `b - a` means something different
/// let diff: HashSet<_> = b.difference(&a).collect();
/// assert_eq!(diff, HashSet::from([&4]));
/// ``````
pub fn difference<'a>(
&'a self,
other: &'a HashSet<K, ALLOCATOR>,
) -> impl Iterator<Item = &'a K> {
self.iter().filter(|k| !other.contains(k))
}
/// Visits the values which are in `self` or `other` but not both.
///
/// # Examples
///
/// ```
/// use agb_hashmap::HashSet;
///
/// let a = HashSet::from([1, 2, 3]);
/// let b = HashSet::from([4, 2, 3, 4]);
///
/// let diff1: HashSet<_> = a.symmetric_difference(&b).collect();
/// let diff2: HashSet<_> = b.symmetric_difference(&a).collect();
///
/// assert_eq!(diff1, diff2);
/// assert_eq!(diff1, HashSet::from([&1, &4]));
/// ```
pub fn symmetric_difference<'a>(
&'a self,
other: &'a HashSet<K, ALLOCATOR>,
) -> impl Iterator<Item = &'a K> {
self.iter()
.filter(|k| !other.contains(k))
.chain(other.iter().filter(|k| !self.contains(k)))
}
/// Visits the values in the intersection of `self` and `other`.
///
/// When an equal element is present in `self` and `other`, then the resulting intersection may
/// yield references to one or the other. This can be relevant if `K` contains fields which are not
/// covered by the `Eq` implementation.
///
/// # Examples
///
/// ```
/// use agb_hashmap::HashSet;
///
/// let a = HashSet::from([1, 2, 3]);
/// let b = HashSet::from([4, 2, 3, 4]);
///
/// let intersection: HashSet<_> = a.intersection(&b).collect();
/// assert_eq!(intersection, HashSet::from([&2, &3]));
/// ```
pub fn intersection<'a>(
&'a self,
other: &'a HashSet<K, ALLOCATOR>,
) -> impl Iterator<Item = &'a K> {
let (smaller, larger) = if self.len() < other.len() {
(self, other)
} else {
(other, self)
};
smaller.iter().filter(|k| larger.contains(k))
}
/// Visits the values in self and other without duplicates.
///
/// When an equal element is present in `self` and `other`, then the resulting union may
/// yield references to one or the other. This can be relevant if `K` contains fields which are not
/// covered by the `Eq` implementation.
///
/// # Examples
///
/// ```
/// use agb_hashmap::HashSet;
///
/// let a = HashSet::from([1, 2, 3]);
/// let b = HashSet::from([4, 2, 3, 4]);
///
/// let union: Vec<_> = a.union(&b).collect();
/// assert_eq!(union.len(), 4);
/// assert_eq!(HashSet::from_iter(union), HashSet::from([&1, &2, &3, &4]));
/// ```
pub fn union<'a>(&'a self, other: &'a HashSet<K, ALLOCATOR>) -> impl Iterator<Item = &'a K> {
let (smaller, larger) = if self.len() < other.len() {
(self, other)
} else {
(other, self)
};
larger.iter().chain(smaller.difference(self))
}
}
impl<K, ALLOCATOR: ClonableAllocator> IntoIterator for HashSet<K, ALLOCATOR> {
type Item = K;
type IntoIter = IterOwned<K, ALLOCATOR>;
fn into_iter(self) -> Self::IntoIter {
IterOwned {
map_iter: self.map.into_iter(),
}
}
}
/// An iterator over the entries of a [`HashSet`].
///
/// This struct is created using the `into_iter()` method on [`HashSet`] as part of its implementation
/// of the `IntoIterator` trait.
pub struct IterOwned<K, ALLOCATOR: ClonableAllocator> {
map_iter: super::IterOwned<K, (), ALLOCATOR>,
}
impl<K, ALLOCATOR: ClonableAllocator> Iterator for IterOwned<K, ALLOCATOR> {
type Item = K;
fn next(&mut self) -> Option<Self::Item> {
self.map_iter.next().map(|(k, _)| k)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.map_iter.size_hint()
}
}
impl<K, ALLOCATOR: ClonableAllocator> ExactSizeIterator for IterOwned<K, ALLOCATOR> {}
impl<'a, K, ALLOCATOR: ClonableAllocator> IntoIterator for &'a HashSet<K, ALLOCATOR> {
type Item = &'a K;
type IntoIter = Iter<'a, K, ALLOCATOR>;
fn into_iter(self) -> Self::IntoIter {
Iter {
map_iter: (&self.map).into_iter(),
}
}
}
pub struct Iter<'a, K, ALLOCATOR: ClonableAllocator> {
map_iter: super::Iter<'a, K, (), ALLOCATOR>,
}
impl<'a, K, ALLOCATOR: ClonableAllocator> Iterator for Iter<'a, K, ALLOCATOR> {
type Item = &'a K;
fn next(&mut self) -> Option<Self::Item> {
self.map_iter.next().map(|(k, _)| k)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.map_iter.size_hint()
}
}
impl<K, ALLOCATOR: ClonableAllocator> ExactSizeIterator for Iter<'_, K, ALLOCATOR> {}
impl<K> FromIterator<K> for HashSet<K>
where
K: Eq + Hash,
{
fn from_iter<T: IntoIterator<Item = K>>(iter: T) -> Self {
let mut set = HashSet::new();
set.extend(iter);
set
}
}
impl<K> Extend<K> for HashSet<K>
where
K: Eq + Hash,
{
fn extend<T: IntoIterator<Item = K>>(&mut self, iter: T) {
for k in iter {
self.insert(k);
}
}
}
impl<K, ALLOCATOR: ClonableAllocator> PartialEq for HashSet<K, ALLOCATOR>
where
K: Eq + Hash,
{
fn eq(&self, other: &Self) -> bool {
self.map == other.map
}
}
impl<K, ALLOCATOR: ClonableAllocator> Eq for HashSet<K, ALLOCATOR> where K: Eq + Hash {}
impl<K, ALLOCATOR: ClonableAllocator> Debug for HashSet<K, ALLOCATOR>
where
K: Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_set().entries(self.iter()).finish()
}
}
impl<K, const N: usize> From<[K; N]> for HashSet<K>
where
K: Eq + Hash,
{
fn from(value: [K; N]) -> Self {
HashSet::from_iter(value)
}
}

View file

@ -1,7 +1,7 @@
//! A lot of the documentation for this module was copied straight out of the rust //! A lot of the documentation for this module was copied straight out of the rust
//! standard library. The implementation however is not. //! standard library. The implementation however is not.
#![no_std] #![no_std]
#![feature(allocator_api)] #![cfg_attr(feature = "allocator_api", feature(allocator_api))]
#![deny(clippy::all)] #![deny(clippy::all)]
#![deny(clippy::must_use_candidate)] #![deny(clippy::must_use_candidate)]
#![deny(missing_docs)] #![deny(missing_docs)]
@ -26,25 +26,46 @@
extern crate alloc; extern crate alloc;
use alloc::{alloc::Global, vec::Vec}; pub(crate) use allocate::{Allocator, Global};
#[cfg(not(feature = "allocator_api"))]
mod allocate {
pub trait Allocator {}
#[derive(Copy, Clone)]
pub struct Global;
impl Allocator for Global {}
}
#[cfg(feature = "allocator_api")]
mod allocate {
pub(crate) use alloc::alloc::Global;
pub(crate) use core::alloc::Allocator;
}
#[cfg(feature = "serde")]
mod serde;
use core::{ use core::{
alloc::Allocator,
borrow::Borrow, borrow::Borrow,
fmt::Debug, fmt::Debug,
hash::{BuildHasher, BuildHasherDefault, Hash, Hasher}, hash::{BuildHasher, BuildHasherDefault, Hash},
iter::FromIterator,
num::Wrapping, num::Wrapping,
ops::Index, ops::Index,
}; };
use rustc_hash::FxHasher; use rustc_hash::FxHasher;
mod hash_set;
mod node; mod node;
mod node_storage; mod node_storage;
use node::Node; use node::Node;
use node_storage::NodeStorage; use node_storage::NodeStorage;
pub use hash_set::HashSet;
// # Robin Hood Hash Tables // # Robin Hood Hash Tables
// //
// The problem with regular hash tables where failing to find a slot for a specific // The problem with regular hash tables where failing to find a slot for a specific
@ -175,12 +196,6 @@ impl<K, V> HashMap<K, V> {
pub fn with_capacity(capacity: usize) -> Self { pub fn with_capacity(capacity: usize) -> Self {
Self::with_capacity_in(capacity, Global) Self::with_capacity_in(capacity, Global)
} }
#[doc(hidden)]
#[must_use]
pub fn distance_histogram(&self) -> (Vec<usize>, usize) {
self.nodes.distance_histogram()
}
} }
impl<K, V, ALLOCATOR: ClonableAllocator> HashMap<K, V, ALLOCATOR> { impl<K, V, ALLOCATOR: ClonableAllocator> HashMap<K, V, ALLOCATOR> {
@ -338,23 +353,12 @@ where
} }
} }
fn insert_and_get(&mut self, key: K, value: V) -> &'_ mut V { unsafe fn insert_new_and_get(&mut self, key: K, value: V, hash: HashType) -> &'_ mut V {
let hash = self.hash(&key);
let location = if let Some(location) = self.nodes.location(&key, hash) {
// SAFETY: location is valid due to the above
unsafe {
self.nodes
.replace_at_location_unchecked(location, key, value);
}
location
} else {
if self.nodes.capacity() <= self.len() { if self.nodes.capacity() <= self.len() {
self.resize(self.nodes.backing_vec_size() * 2); self.resize(self.nodes.backing_vec_size() * 2);
} }
self.nodes.insert_new(key, value, hash) let location = self.nodes.insert_new(key, value, hash);
};
// SAFETY: location is always valid // SAFETY: location is always valid
unsafe { unsafe {
@ -481,9 +485,7 @@ where
K: Borrow<Q>, K: Borrow<Q>,
Q: Hash + ?Sized, Q: Hash + ?Sized,
{ {
let mut hasher = self.hasher.build_hasher(); let result = self.hasher.hash_one(key);
key.hash(&mut hasher);
let result = hasher.finish();
// we want to allow truncation here since we're reducing 64 bits to 32 // we want to allow truncation here since we're reducing 64 bits to 32
#[allow(clippy::cast_possible_truncation)] #[allow(clippy::cast_possible_truncation)]
@ -529,6 +531,8 @@ impl<'a, K, V, ALLOCATOR: ClonableAllocator> Iterator for Iter<'a, K, V, ALLOCAT
} }
} }
impl<K, V, ALLOCATOR: ClonableAllocator> ExactSizeIterator for Iter<'_, K, V, ALLOCATOR> {}
impl<'a, K, V, ALLOCATOR: ClonableAllocator> IntoIterator for &'a HashMap<K, V, ALLOCATOR> { impl<'a, K, V, ALLOCATOR: ClonableAllocator> IntoIterator for &'a HashMap<K, V, ALLOCATOR> {
type Item = (&'a K, &'a V); type Item = (&'a K, &'a V);
type IntoIter = Iter<'a, K, V, ALLOCATOR>; type IntoIter = Iter<'a, K, V, ALLOCATOR>;
@ -579,6 +583,8 @@ impl<K, V, ALLOCATOR: ClonableAllocator> Iterator for IterOwned<K, V, ALLOCATOR>
} }
} }
impl<K, V, ALLOCATOR: ClonableAllocator> ExactSizeIterator for IterOwned<K, V, ALLOCATOR> {}
/// An iterator over entries of a [`HashMap`] /// An iterator over entries of a [`HashMap`]
/// ///
/// This struct is created using the `into_iter()` method on [`HashMap`] as part of its implementation /// This struct is created using the `into_iter()` method on [`HashMap`] as part of its implementation
@ -597,9 +603,10 @@ impl<K, V, ALLOCATOR: ClonableAllocator> IntoIterator for HashMap<K, V, ALLOCATO
} }
mod entries { mod entries {
use core::{alloc::Allocator, hash::Hash}; use crate::allocate::Allocator;
use core::hash::Hash;
use super::{ClonableAllocator, HashMap}; use super::{ClonableAllocator, HashMap, HashType};
/// A view into an occupied entry in a `HashMap`. This is part of the [`crate::Entry`] enum. /// A view into an occupied entry in a `HashMap`. This is part of the [`crate::Entry`] enum.
pub struct OccupiedEntry<'a, K: 'a, V: 'a, ALLOCATOR: Allocator> { pub struct OccupiedEntry<'a, K: 'a, V: 'a, ALLOCATOR: Allocator> {
@ -695,11 +702,16 @@ mod entries {
pub struct VacantEntry<'a, K: 'a, V: 'a, ALLOCATOR: Allocator> { pub struct VacantEntry<'a, K: 'a, V: 'a, ALLOCATOR: Allocator> {
key: K, key: K,
map: &'a mut HashMap<K, V, ALLOCATOR>, map: &'a mut HashMap<K, V, ALLOCATOR>,
hash: HashType,
} }
impl<'a, K: 'a, V: 'a, ALLOCATOR: ClonableAllocator> VacantEntry<'a, K, V, ALLOCATOR> { impl<'a, K: 'a, V: 'a, ALLOCATOR: ClonableAllocator> VacantEntry<'a, K, V, ALLOCATOR> {
pub(crate) fn new(key: K, map: &'a mut HashMap<K, V, ALLOCATOR>) -> Self { pub(crate) unsafe fn new(
Self { key, map } key: K,
hash: HashType,
map: &'a mut HashMap<K, V, ALLOCATOR>,
) -> Self {
Self { key, map, hash }
} }
/// Gets a reference to the key that would be used when inserting a value through `VacantEntry` /// Gets a reference to the key that would be used when inserting a value through `VacantEntry`
@ -717,7 +729,8 @@ mod entries {
where where
K: Hash + Eq, K: Hash + Eq,
{ {
self.map.insert_and_get(self.key, value) // SAFETY: by construction, this doesn't already exist in the hashmap and we were given the hash and key
unsafe { self.map.insert_new_and_get(self.key, value, self.hash) }
} }
} }
} }
@ -832,7 +845,10 @@ where
unsafe { OccupiedEntry::new(key, self, location) }, unsafe { OccupiedEntry::new(key, self, location) },
) )
} else { } else {
Entry::Vacant(VacantEntry::new(key, self)) Entry::Vacant(
// SAFETY: item doesn't exist yet and the hash is correct here
unsafe { VacantEntry::new(key, hash, self) },
)
} }
} }
} }
@ -951,7 +967,7 @@ impl core::ops::Add<i32> for HashType {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use core::cell::RefCell; use core::{cell::RefCell, hash::Hasher};
use alloc::vec::Vec; use alloc::vec::Vec;
@ -1447,4 +1463,19 @@ mod test {
assert_eq!(format!("{empty:?}"), "{}"); assert_eq!(format!("{empty:?}"), "{}");
} }
} }
#[cfg(not(miri))]
quickcheck::quickcheck! {
fn test_against_btree_map(entries: Vec<(u8, u32)>) -> bool {
let std_hashmap = alloc::collections::BTreeMap::from_iter(entries.clone());
let agb_hashmap = HashMap::from_iter(entries);
if std_hashmap.len() != agb_hashmap.len() {
return false;
}
std_hashmap.iter().all(|(key, value)| agb_hashmap.get(key) == Some(value)) &&
agb_hashmap.iter().all(|(key, value)| std_hashmap.get(key) == Some(value))
}
}
} }

View file

@ -1,12 +1,14 @@
use core::{alloc::Allocator, borrow::Borrow, mem}; use core::{borrow::Borrow, mem};
use alloc::{alloc::Global, vec::Vec};
use crate::allocate::{Allocator, Global};
use crate::{node::Node, number_before_resize, ClonableAllocator, HashType}; use crate::{node::Node, number_before_resize, ClonableAllocator, HashType};
mod vec;
use vec::MyVec;
#[derive(Clone)] #[derive(Clone)]
pub(crate) struct NodeStorage<K, V, ALLOCATOR: Allocator = Global> { pub(crate) struct NodeStorage<K, V, ALLOCATOR: Allocator = Global> {
nodes: Vec<Node<K, V>, ALLOCATOR>, nodes: MyVec<Node<K, V>, ALLOCATOR>,
max_distance_to_initial_bucket: i32, max_distance_to_initial_bucket: i32,
number_of_items: usize, number_of_items: usize,
@ -17,7 +19,7 @@ impl<K, V, ALLOCATOR: ClonableAllocator> NodeStorage<K, V, ALLOCATOR> {
pub(crate) fn with_size_in(capacity: usize, alloc: ALLOCATOR) -> Self { pub(crate) fn with_size_in(capacity: usize, alloc: ALLOCATOR) -> Self {
assert!(capacity.is_power_of_two(), "Capacity must be a power of 2"); assert!(capacity.is_power_of_two(), "Capacity must be a power of 2");
let mut nodes = Vec::with_capacity_in(capacity, alloc); let mut nodes = MyVec::with_capacity_in(capacity, alloc);
for _ in 0..capacity { for _ in 0..capacity {
nodes.push(Node::new()); nodes.push(Node::new());
} }
@ -202,22 +204,6 @@ impl<K, V, ALLOCATOR: ClonableAllocator> NodeStorage<K, V, ALLOCATOR> {
self.nodes.get_unchecked_mut(at) self.nodes.get_unchecked_mut(at)
} }
pub(crate) fn distance_histogram(&self) -> (Vec<usize>, usize) {
let mut ret = Vec::new();
for node in self.nodes.iter() {
let distance = node.distance();
if distance >= 0 {
let distance = distance as usize;
ret.resize(ret.len().max(distance + 1), 0);
ret[distance] += 1;
}
}
(ret, self.max_distance_to_initial_bucket as usize)
}
pub(crate) fn clear(&mut self) { pub(crate) fn clear(&mut self) {
self.max_distance_to_initial_bucket = 0; self.max_distance_to_initial_bucket = 0;
self.number_of_items = 0; self.number_of_items = 0;

View file

@ -0,0 +1,66 @@
use core::ops::{Deref, DerefMut};
use alloc::vec::Vec;
use crate::{Allocator, Global};
pub(crate) use inner::MyVec;
#[cfg(not(feature = "allocator_api"))]
mod inner {
use super::*;
#[derive(Clone)]
pub(crate) struct MyVec<T, A: Allocator = Global>(Vec<T>, A);
impl<T, A: Allocator> MyVec<T, A> {
pub(crate) fn with_capacity_in(capacity: usize, allocator: A) -> Self {
Self(Vec::with_capacity(capacity), allocator)
}
pub(crate) fn allocator(&self) -> &A {
&self.1
}
}
impl<T, A: Allocator> Deref for MyVec<T, A> {
type Target = Vec<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T, A: Allocator> DerefMut for MyVec<T, A> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
}
#[cfg(feature = "allocator_api")]
mod inner {
use super::*;
#[derive(Clone)]
pub(crate) struct MyVec<T, A: Allocator = Global>(Vec<T, A>);
impl<T, A: Allocator> MyVec<T, A> {
pub(crate) fn with_capacity_in(capacity: usize, allocator: A) -> Self {
Self(Vec::with_capacity_in(capacity, allocator))
}
}
impl<T, A: Allocator> Deref for MyVec<T, A> {
type Target = Vec<T, A>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T, A: Allocator> DerefMut for MyVec<T, A> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
}

198
agb-hashmap/src/serde.rs Normal file
View file

@ -0,0 +1,198 @@
use core::{hash::Hash, marker::PhantomData};
use serde::{
de::{MapAccess, SeqAccess, Visitor},
ser::SerializeMap,
Deserialize, Serialize,
};
use crate::{ClonableAllocator, HashMap, HashSet};
mod hashmap {
use super::*;
impl<K: Serialize, V: Serialize, ALLOCATOR: ClonableAllocator> Serialize
for HashMap<K, V, ALLOCATOR>
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut map = serializer.serialize_map(Some(self.len()))?;
for (key, value) in self {
map.serialize_entry(key, value)?;
}
map.end()
}
}
impl<'de, K, V> Deserialize<'de> for HashMap<K, V>
where
K: Deserialize<'de> + Hash + Eq,
V: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_map(HashMapVisitor::new())
}
}
struct HashMapVisitor<K, V> {
_marker: PhantomData<fn() -> HashMap<K, V>>,
}
impl<K, V> HashMapVisitor<K, V> {
fn new() -> Self {
Self {
_marker: PhantomData,
}
}
}
impl<'de, K, V> Visitor<'de> for HashMapVisitor<K, V>
where
K: Deserialize<'de> + Hash + Eq,
V: Deserialize<'de>,
{
type Value = HashMap<K, V>;
fn expecting(&self, formatter: &mut alloc::fmt::Formatter) -> alloc::fmt::Result {
formatter.write_str("an agb::HashMap")
}
fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
where
M: MapAccess<'de>,
{
let mut map = HashMap::with_capacity(access.size_hint().unwrap_or(8));
while let Some((key, value)) = access.next_entry()? {
map.insert(key, value);
}
Ok(map)
}
}
}
mod hashset {
use super::*;
impl<K: Serialize, ALLOCATOR: ClonableAllocator> Serialize for HashSet<K, ALLOCATOR> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.collect_seq(self)
}
}
struct HashSetVisitor<K> {
_marker: PhantomData<fn() -> HashSet<K>>,
}
impl<K> HashSetVisitor<K> {
fn new() -> Self {
Self {
_marker: PhantomData,
}
}
}
impl<'de, K> Visitor<'de> for HashSetVisitor<K>
where
K: Deserialize<'de> + Hash + Eq,
{
type Value = HashSet<K>;
fn expecting(&self, formatter: &mut alloc::fmt::Formatter) -> alloc::fmt::Result {
formatter.write_str("an agb::HashSet")
}
fn visit_seq<A>(self, mut access: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut set = HashSet::with_capacity(access.size_hint().unwrap_or(8));
while let Some(value) = access.next_element()? {
set.insert(value);
}
Ok(set)
}
}
impl<'de, K> Deserialize<'de> for HashSet<K>
where
K: Deserialize<'de> + Hash + Eq,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_seq(HashSetVisitor::new())
}
}
}
#[cfg(test)]
mod test {
use alloc::{
string::{String, ToString},
vec::Vec,
};
use crate::{HashMap, HashSet};
#[test]
fn deserialize_map() {
let json = r#"
{
"three": 3,
"seven": 7
}
"#;
let map = serde_json::from_str::<HashMap<String, i32>>(json).unwrap();
assert_eq!(
map,
HashMap::from_iter([("three".to_string(), 3), ("seven".to_string(), 7)])
);
}
#[test]
fn serialize_map() {
let map = HashMap::from_iter([("three".to_string(), 3), ("seven".to_string(), 7)]);
let json = serde_json::to_string(&map).unwrap();
let possibilities = &[r#"{"three":3,"seven":7}"#, r#"{"seven":7,"three":3}"#];
assert!(possibilities.contains(&json.as_str()));
}
#[test]
fn deserialize_hashset() {
let json = "[1, 2, 5, 8, 9, 3, 4]";
let set = serde_json::from_str::<HashSet<i32>>(json).unwrap();
assert_eq!(set, HashSet::from_iter([1, 2, 3, 4, 5, 8, 9]));
}
#[test]
fn serialize_hashset() {
let set = HashSet::from_iter([1, 2, 3, 5, 8, 9, 10]);
let serialized = serde_json::to_string(&set).unwrap();
let mut deserialized = serde_json::from_str::<Vec<i32>>(&serialized).unwrap();
deserialized.sort();
assert_eq!(deserialized, &[1, 2, 3, 5, 8, 9, 10]);
}
}

View file

@ -1,7 +1,7 @@
[package] [package]
name = "agb_image_converter" name = "agb_image_converter"
version = "0.15.0" version = "0.21.1"
authors = ["Gwilym Kuiper <gw@ilym.me>"] authors = ["Gwilym Inzani <gw@ilym.me>"]
edition = "2021" edition = "2021"
license = "MPL-2.0" license = "MPL-2.0"
description = "Library for converting graphics for use on the Game Boy Advance" description = "Library for converting graphics for use on the Game Boy Advance"
@ -11,19 +11,16 @@ repository = "https://github.com/agbrs/agb"
proc-macro = true proc-macro = true
[dependencies] [dependencies]
image = { version = "0.23", default-features = false, features = [ "png", "bmp" ] } image = { version = "0.24", default-features = false, features = [
"png",
"bmp",
] }
syn = { version = "2", features = ["proc-macro", "parsing"] } syn = { version = "2", features = ["proc-macro", "parsing"] }
proc-macro2 = "1" proc-macro2 = "1"
quote = "1" quote = "1"
asefile = "0.3.5" asefile = "0.3.8"
fontdue = "0.7" fontdue = "0.9"
pagination-packing = "2.1.0"
[profile.dev] [dev-dependencies]
opt-level = 3 quickcheck = "1"
debug = true
[profile.release]
opt-level = 3
lto = "fat"
debug = true
codegen-units = 1

View file

@ -1,6 +1,6 @@
use std::str::FromStr; use std::{fmt, str::FromStr};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Colour { pub struct Colour {
pub r: u8, pub r: u8,
pub g: u8, pub g: u8,
@ -8,6 +8,18 @@ pub struct Colour {
pub a: u8, pub a: u8,
} }
impl fmt::Debug for Colour {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "#{:02x}{:02x}{:02x}", self.r, self.g, self.b)?;
if self.a != 0xff {
write!(f, "{:02x}", self.a)?;
}
Ok(())
}
}
impl Colour { impl Colour {
pub fn from_rgb(r: u8, g: u8, b: u8, a: u8) -> Self { pub fn from_rgb(r: u8, g: u8, b: u8, a: u8) -> Self {
Colour { r, g, b, a } Colour { r, g, b, a }
@ -38,3 +50,26 @@ impl FromStr for Colour {
Ok(Colour::from_rgb(r, g, b, 255)) Ok(Colour::from_rgb(r, g, b, 255))
} }
} }
#[cfg(test)]
impl quickcheck::Arbitrary for Colour {
fn arbitrary(g: &mut quickcheck::Gen) -> Self {
Self::from_rgb(
quickcheck::Arbitrary::arbitrary(g),
quickcheck::Arbitrary::arbitrary(g),
quickcheck::Arbitrary::arbitrary(g),
quickcheck::Arbitrary::arbitrary(g),
)
}
fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
Box::new(
vec![
Colour::from_rgb(0, 0, 0, 0),
Colour::from_rgb(self.r, self.g, self.b, 0),
*self,
]
.into_iter(),
)
}
}

View file

@ -11,4 +11,5 @@ pub(crate) trait Config {
pub(crate) trait Image { pub(crate) trait Image {
fn filename(&self) -> String; fn filename(&self) -> String;
fn colours(&self) -> Colours; fn colours(&self) -> Colours;
fn deduplicate(&self) -> bool;
} }

View file

@ -0,0 +1,141 @@
use std::collections::BTreeMap;
use crate::{colour::Colour, image_loader::Image};
pub struct Transformation {
pub vflip: bool,
pub hflip: bool,
}
impl Transformation {
pub fn none() -> Self {
Self {
vflip: false,
hflip: false,
}
}
pub fn vflipped() -> Self {
Self {
vflip: true,
hflip: false,
}
}
pub fn hflipped() -> Self {
Self {
vflip: false,
hflip: true,
}
}
pub fn vhflipped() -> Self {
Self {
vflip: true,
hflip: true,
}
}
}
pub struct DeduplicatedData {
pub new_index: usize,
pub transformation: Transformation,
}
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
struct Tile {
data: [Colour; 64],
}
impl Tile {
fn split_image(input: &Image) -> Vec<Self> {
let mut ret = vec![];
for y in 0..(input.height / 8) {
for x in 0..(input.width / 8) {
let mut tile_data = Vec::with_capacity(64);
for j in 0..8 {
for i in 0..8 {
tile_data.push(input.colour(x * 8 + i, y * 8 + j));
}
}
ret.push(Tile {
data: tile_data.try_into().unwrap(),
});
}
}
ret
}
fn vflipped(&self) -> Self {
let mut new_data = self.data;
for y in 0..4 {
for x in 0..8 {
new_data.swap(y * 8 + x, (7 - y) * 8 + x);
}
}
Self { data: new_data }
}
fn hflipped(&self) -> Self {
let mut new_data = self.data;
for y in 0..8 {
for x in 0..4 {
new_data.swap(y * 8 + x, y * 8 + (7 - x));
}
}
Self { data: new_data }
}
}
pub(crate) fn deduplicate_image(input: &Image, can_flip: bool) -> (Image, Vec<DeduplicatedData>) {
let mut resulting_tiles = vec![];
let mut deduplication_data = vec![];
let all_tiles = Tile::split_image(input);
let mut existing_tiles = BTreeMap::new();
for tile in all_tiles {
let (tile, transformation) = if can_flip {
let vflipped = tile.vflipped();
let hflipped = tile.hflipped();
let vhflipped = vflipped.hflipped();
let minimum = (&tile).min(&vflipped).min(&hflipped).min(&vhflipped);
if minimum == &tile {
(tile, Transformation::none())
} else if minimum == &vflipped {
(vflipped, Transformation::vflipped())
} else if minimum == &hflipped {
(hflipped, Transformation::hflipped())
} else {
(vhflipped, Transformation::vhflipped())
}
} else {
(tile, Transformation::none())
};
let index = *existing_tiles.entry(tile.clone()).or_insert_with(|| {
resulting_tiles.push(tile);
resulting_tiles.len() - 1
});
deduplication_data.push(DeduplicatedData {
new_index: index,
transformation,
});
}
let image_data = resulting_tiles
.iter()
.flat_map(|tile| tile.data)
.collect::<Vec<_>>();
(Image::from_colour_data(image_data), deduplication_data)
}

View file

@ -3,21 +3,28 @@ use quote::quote;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
struct KerningData {
previous_character: char,
amount: f32,
}
struct LetterData { struct LetterData {
character: char,
width: usize, width: usize,
height: usize, height: usize,
xmin: i32, xmin: i32,
ymin: i32, ymin: i32,
advance_width: f32, advance_width: f32,
rendered: Vec<u8>, rendered: Vec<u8>,
kerning_data: Vec<KerningData>,
} }
pub fn load_font(font_data: &[u8], pixels_per_em: f32) -> TokenStream { pub fn load_font(font_data: &[u8], pixels_per_em: f32) -> TokenStream {
let font = fontdue::Font::from_bytes( let font = fontdue::Font::from_bytes(
font_data, font_data,
fontdue::FontSettings { fontdue::FontSettings {
collection_index: 0,
scale: pixels_per_em, scale: pixels_per_em,
..Default::default()
}, },
) )
.expect("Invalid font data"); .expect("Invalid font data");
@ -25,11 +32,13 @@ pub fn load_font(font_data: &[u8], pixels_per_em: f32) -> TokenStream {
let line_metrics = font.horizontal_line_metrics(pixels_per_em).unwrap(); let line_metrics = font.horizontal_line_metrics(pixels_per_em).unwrap();
let line_height = line_metrics.new_line_size as i32; let line_height = line_metrics.new_line_size as i32;
let ascent = line_metrics.ascent as i32; let mut ascent = line_metrics.ascent as i32;
let font = (0..128) let mut letters: Vec<_> = font
.map(|i| font.rasterize(char::from_u32(i).unwrap(), pixels_per_em)) .chars()
.map(|(metrics, bitmap)| { .iter()
.map(|(&c, &index)| (c, index, font.rasterize(c, pixels_per_em)))
.map(|(c, index, (metrics, bitmap))| {
let width = metrics.width; let width = metrics.width;
let height = metrics.height; let height = metrics.height;
@ -47,31 +56,78 @@ pub fn load_font(font_data: &[u8], pixels_per_em: f32) -> TokenStream {
}) })
.collect(); .collect();
let mut kerning_data: Vec<_> = font
.chars()
.iter()
.filter_map(|(&left_char, &left_index)| {
let kerning = font.horizontal_kern_indexed(
left_index.into(),
index.into(),
pixels_per_em,
)?;
Some(KerningData {
previous_character: left_char,
amount: kerning,
})
})
.collect();
kerning_data.sort_unstable_by_key(|kd| kd.previous_character);
LetterData { LetterData {
character: c,
width, width,
height, height,
rendered, rendered,
xmin: metrics.xmin, xmin: metrics.xmin,
ymin: metrics.ymin, ymin: metrics.ymin,
advance_width: metrics.advance_width, advance_width: metrics.advance_width,
kerning_data,
} }
}) })
.map(|letter_data| { .collect();
letters.sort_unstable_by_key(|letter| letter.character);
let maximum_above_line = letters
.iter()
.map(|x| (x.height as i32 + x.ymin))
.max()
.unwrap();
if (ascent - maximum_above_line) < 0 {
ascent = maximum_above_line;
}
let font = letters.iter().map(|letter_data| {
let character = letter_data.character;
let data_raw = ByteString(&letter_data.rendered); let data_raw = ByteString(&letter_data.rendered);
let height = letter_data.height as u8; let height = letter_data.height as u8;
let width = letter_data.width as u8; let width = letter_data.width as u8;
let xmin = letter_data.xmin as i8; let xmin = letter_data.xmin as i8;
let ymin = letter_data.ymin as i8; let ymin = letter_data.ymin as i8;
let advance_width = letter_data.advance_width.ceil() as u8; let advance_width = letter_data.advance_width.ceil() as u8;
let kerning_amounts = letter_data.kerning_data.iter().map(|kerning_data| {
let amount = kerning_data.amount as i8;
let c = kerning_data.previous_character;
quote! {
(#c, #amount)
}
});
quote!( quote!(
display::FontLetter::new( display::FontLetter::new(
#character,
#width, #width,
#height, #height,
#data_raw, #data_raw,
#xmin, #xmin,
#ymin, #ymin,
#advance_width, #advance_width,
&[
#(#kerning_amounts),*
]
) )
) )
}); });

View file

@ -4,6 +4,7 @@ use image::{DynamicImage, GenericImageView};
use crate::colour::Colour; use crate::colour::Colour;
#[derive(Clone)]
pub(crate) struct Image { pub(crate) struct Image {
pub width: usize, pub width: usize,
pub height: usize, pub height: usize,
@ -42,6 +43,14 @@ impl Image {
} }
} }
pub fn from_colour_data(colour_data: Vec<Colour>) -> Self {
Self {
height: colour_data.len() / 8,
colour_data,
width: 8,
}
}
pub fn colour(&self, x: usize, y: usize) -> Colour { pub fn colour(&self, x: usize, y: usize) -> Colour {
self.colour_data[x + y * self.width] self.colour_data[x + y * self.width]
} }

View file

@ -15,13 +15,13 @@ use quote::{format_ident, quote, ToTokens};
mod aseprite; mod aseprite;
mod colour; mod colour;
mod config; mod config;
mod deduplicator;
mod font_loader; mod font_loader;
mod image_loader; mod image_loader;
mod palette16; mod palette16;
mod palette256; mod palette256;
mod rust_generator; mod rust_generator;
use image::GenericImageView;
use image_loader::Image; use image_loader::Image;
use colour::Colour; use colour::Colour;
@ -36,16 +36,23 @@ struct BackgroundGfxOption {
module_name: String, module_name: String,
file_name: String, file_name: String,
colours: Colours, colours: Colours,
deduplicate: bool,
} }
impl config::Image for BackgroundGfxOption { impl config::Image for BackgroundGfxOption {
fn filename(&self) -> String { fn filename(&self) -> String {
self.file_name.clone() self.file_name
.clone()
.replace(OUT_DIR_TOKEN, &get_out_dir(&self.file_name))
} }
fn colours(&self) -> Colours { fn colours(&self) -> Colours {
self.colours self.colours
} }
fn deduplicate(&self) -> bool {
self.deduplicate
}
} }
impl Parse for BackgroundGfxOption { impl Parse for BackgroundGfxOption {
@ -72,18 +79,37 @@ impl Parse for BackgroundGfxOption {
Colours::Colours16 Colours::Colours16
}; };
let lookahead = input.lookahead1();
let deduplicate = if lookahead.peek(syn::Ident) {
let deduplicate: syn::Ident = input.parse()?;
if deduplicate == "deduplicate" {
true
} else {
return Err(syn::Error::new_spanned(
deduplicate,
"Must either be the literal deduplicate or missing",
));
}
} else {
false
};
let file_name: syn::LitStr = input.parse()?; let file_name: syn::LitStr = input.parse()?;
Ok(Self { Ok(Self {
module_name: module_name.to_string(), module_name: module_name.to_string(),
file_name: file_name.value(), file_name: file_name.value(),
colours, colours,
deduplicate,
}) })
} }
} }
struct IncludeBackgroundGfxInput { struct IncludeBackgroundGfxInput {
module_name: syn::Ident, module_name: syn::Ident,
as_pub: bool,
crate_prefix: String, crate_prefix: String,
transparent_colour: Colour, transparent_colour: Colour,
background_gfx_options: Vec<BackgroundGfxOption>, background_gfx_options: Vec<BackgroundGfxOption>,
@ -101,6 +127,15 @@ impl Parse for IncludeBackgroundGfxInput {
format_ident!("agb") format_ident!("agb")
}; };
let lookahead = input.lookahead1();
let as_pub = if lookahead.peek(Token![pub]) {
let _: Token![pub] = input.parse()?;
true
} else {
false
};
let module_name: syn::Ident = input.parse()?; let module_name: syn::Ident = input.parse()?;
let _: Token![,] = input.parse()?; let _: Token![,] = input.parse()?;
@ -121,6 +156,7 @@ impl Parse for IncludeBackgroundGfxInput {
Ok(Self { Ok(Self {
module_name, module_name,
as_pub,
crate_prefix: crate_prefix.to_string(), crate_prefix: crate_prefix.to_string(),
transparent_colour, transparent_colour,
background_gfx_options: background_gfx_options.into_iter().collect(), background_gfx_options: background_gfx_options.into_iter().collect(),
@ -145,6 +181,15 @@ impl config::Config for IncludeBackgroundGfxInput {
} }
} }
/// Including from the out directory is supported through the `$OUT_DIR` token.
///
/// ```rust,ignore
/// # #![no_std]
/// # #![no_main]
/// # use agb::include_background_gfx;
/// include_background_gfx!(generated_background, "000000", DATA => "$OUT_DIR/generated_background.aseprite");
/// ```
///
#[proc_macro] #[proc_macro]
pub fn include_background_gfx(input: TokenStream) -> TokenStream { pub fn include_background_gfx(input: TokenStream) -> TokenStream {
let config = Box::new(parse_macro_input!(input as IncludeBackgroundGfxInput)); let config = Box::new(parse_macro_input!(input as IncludeBackgroundGfxInput));
@ -152,11 +197,13 @@ pub fn include_background_gfx(input: TokenStream) -> TokenStream {
let root = std::env::var("CARGO_MANIFEST_DIR").expect("Failed to get cargo manifest dir"); let root = std::env::var("CARGO_MANIFEST_DIR").expect("Failed to get cargo manifest dir");
let module_name = config.module_name.clone(); let module_name = config.module_name.clone();
include_background_gfx_from_config(config, module_name, Path::new(&root)) let as_pub = config.as_pub;
include_gfx_from_config(config, as_pub, module_name, Path::new(&root))
} }
fn include_background_gfx_from_config( fn include_gfx_from_config(
config: Box<dyn config::Config>, config: Box<dyn config::Config>,
as_pub: bool,
module_name: syn::Ident, module_name: syn::Ident,
parent: &Path, parent: &Path,
) -> TokenStream { ) -> TokenStream {
@ -183,6 +230,7 @@ fn include_background_gfx_from_config(
&mut optimiser, &mut optimiser,
&image, &image,
tile_size, tile_size,
tile_size,
config.transparent_colour(), config.transparent_colour(),
); );
@ -196,7 +244,9 @@ fn include_background_gfx_from_config(
} }
} }
let optimisation_results = optimiser.optimise_palettes(); let optimisation_results = optimiser
.optimise_palettes()
.expect("Failed to optimised palettes");
let optimisation_results = palette256.extend_results(&optimisation_results); let optimisation_results = palette256.extend_results(&optimisation_results);
let mut image_code = vec![]; let mut image_code = vec![];
@ -220,12 +270,22 @@ fn include_background_gfx_from_config(
let palette_code = let palette_code =
rust_generator::generate_palette_code(&optimisation_results, &config.crate_prefix()); rust_generator::generate_palette_code(&optimisation_results, &config.crate_prefix());
let module = quote! { let module = if as_pub {
quote! {
pub mod #module_name {
#palette_code
#(#image_code)*
}
}
} else {
quote! {
mod #module_name { mod #module_name {
#palette_code #palette_code
#(#image_code)* #(#image_code)*
} }
}
}; };
TokenStream::from(module) TokenStream::from(module)
@ -268,6 +328,8 @@ pub fn include_colours_inner(input: TokenStream) -> TokenStream {
#[proc_macro] #[proc_macro]
pub fn include_aseprite_inner(input: TokenStream) -> TokenStream { pub fn include_aseprite_inner(input: TokenStream) -> TokenStream {
let out_dir_path = get_out_dir(&input.to_string());
let parser = Punctuated::<LitStr, syn::Token![,]>::parse_terminated; let parser = Punctuated::<LitStr, syn::Token![,]>::parse_terminated;
let parsed = match parser.parse(input) { let parsed = match parser.parse(input) {
Ok(e) => e, Ok(e) => e,
@ -285,6 +347,7 @@ pub fn include_aseprite_inner(input: TokenStream) -> TokenStream {
let filenames: Vec<PathBuf> = parsed let filenames: Vec<PathBuf> = parsed
.iter() .iter()
.map(|s| s.value()) .map(|s| s.value())
.map(|s| s.replace(OUT_DIR_TOKEN, &out_dir_path))
.map(|s| Path::new(&root).join(&*s)) .map(|s| Path::new(&root).join(&*s))
.collect(); .collect();
@ -305,12 +368,20 @@ pub fn include_aseprite_inner(input: TokenStream) -> TokenStream {
); );
let image = Image::load_from_dyn_image(frame); let image = Image::load_from_dyn_image(frame);
add_to_optimiser(&mut optimiser, &image, 8, Some(transparent_colour)); add_to_optimiser(
&mut optimiser,
&image,
width as usize,
height as usize,
Some(transparent_colour),
);
images.push(image); images.push(image);
} }
} }
let optimised_results = optimiser.optimise_palettes(); let optimised_results = optimiser
.optimise_palettes()
.expect("Failed to optimise palettes");
let (palette_data, tile_data, assignments) = palette_tile_data(&optimised_results, &images); let (palette_data, tile_data, assignments) = palette_tile_data(&optimised_results, &images);
@ -370,15 +441,15 @@ pub fn include_aseprite_inner(input: TokenStream) -> TokenStream {
#(#include_paths)* #(#include_paths)*
const PALETTES: &[Palette16] = &[ static PALETTES: &[Palette16] = &[
#(#palette_data),* #(#palette_data),*
]; ];
pub const SPRITES: &[Sprite] = &[ static SPRITES: &[Sprite] = &[
#(#sprites),* #(#sprites),*
]; ];
const TAGS: &TagMap = &TagMap::new( static TAGS: TagMap = TagMap::new(
&[ &[
#(#tags),* #(#tags),*
] ]
@ -399,6 +470,7 @@ fn convert_image(
) -> proc_macro2::TokenStream { ) -> proc_macro2::TokenStream {
let image_filename = &parent.join(settings.filename()); let image_filename = &parent.join(settings.filename());
let image = Image::load_from_file(image_filename); let image = Image::load_from_file(image_filename);
let deduplicate = settings.deduplicate();
rust_generator::generate_code( rust_generator::generate_code(
variable_name, variable_name,
@ -407,25 +479,27 @@ fn convert_image(
&image_filename.to_string_lossy(), &image_filename.to_string_lossy(),
crate_prefix.to_owned(), crate_prefix.to_owned(),
assignment_offset, assignment_offset,
deduplicate,
) )
} }
fn add_to_optimiser( fn add_to_optimiser(
palette_optimiser: &mut palette16::Palette16Optimiser, palette_optimiser: &mut palette16::Palette16Optimiser,
image: &Image, image: &Image,
tile_size: usize, tile_width: usize,
tile_height: usize,
transparent_colour: Option<Colour>, transparent_colour: Option<Colour>,
) { ) {
let tiles_x = image.width / tile_size; let tiles_x = image.width / tile_width;
let tiles_y = image.height / tile_size; let tiles_y = image.height / tile_height;
for y in 0..tiles_y { for y in 0..tiles_y {
for x in 0..tiles_x { for x in 0..tiles_x {
let mut palette = palette16::Palette16::new(); let mut palette = palette16::Palette16::new();
for j in 0..tile_size { for j in 0..tile_height {
for i in 0..tile_size { for i in 0..tile_width {
let colour = image.colour(x * tile_size + i, y * tile_size + j); let colour = image.colour(x * tile_width + i, y * tile_height + j);
palette.add_colour(match (colour.is_transparent(), transparent_colour) { palette.add_colour(match (colour.is_transparent(), transparent_colour) {
(true, Some(transparent_colour)) => transparent_colour, (true, Some(transparent_colour)) => transparent_colour,
@ -460,7 +534,14 @@ fn palette_tile_data(
let mut tile_data = Vec::new(); let mut tile_data = Vec::new();
for (image_idx, image) in images.iter().enumerate() { for (image_idx, image) in images.iter().enumerate() {
add_image_to_tile_data(&mut tile_data, image, optimiser, image_idx) add_image_to_tile_data(
&mut tile_data,
image,
optimiser,
image_idx,
true,
&(0..images.len()).collect::<Vec<_>>(),
);
} }
let tile_data = collapse_to_4bpp(&tile_data); let tile_data = collapse_to_4bpp(&tile_data);
@ -482,6 +563,8 @@ fn add_image_to_tile_data(
image: &Image, image: &Image,
optimiser: &Palette16OptimisationResults, optimiser: &Palette16OptimisationResults,
assignment_offset: usize, assignment_offset: usize,
is_sprite: bool,
remap_index: &[usize],
) { ) {
let tile_size = 8; let tile_size = 8;
let tiles_x = image.width / tile_size; let tiles_x = image.width / tile_size;
@ -489,7 +572,13 @@ fn add_image_to_tile_data(
for y in 0..tiles_y { for y in 0..tiles_y {
for x in 0..tiles_x { for x in 0..tiles_x {
let palette_index = optimiser.assignments[y * tiles_x + x + assignment_offset]; let assignment = if is_sprite {
assignment_offset
} else {
remap_index[y * tiles_x + x] + assignment_offset
};
let palette_index = optimiser.assignments[assignment];
let palette = &optimiser.optimised_palettes[palette_index]; let palette = &optimiser.optimised_palettes[palette_index];
for inner_y in 0..tile_size / 8 { for inner_y in 0..tile_size / 8 {
@ -614,6 +703,16 @@ fn valid_sprite_size(width: u32, height: u32) -> bool {
} }
} }
const OUT_DIR_TOKEN: &str = "$OUT_DIR";
fn get_out_dir(raw_input: &str) -> String {
if raw_input.contains(OUT_DIR_TOKEN) {
std::env::var("OUT_DIR").expect("Failed to get OUT_DIR")
} else {
String::new()
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use asefile::AnimationDirection; use asefile::AnimationDirection;

View file

@ -1,10 +1,13 @@
use crate::colour::Colour; use crate::colour::Colour;
use std::collections::HashSet; use std::{
collections::{BTreeSet, HashSet},
fmt,
};
const MAX_COLOURS: usize = 256; const MAX_COLOURS: usize = 256;
const MAX_COLOURS_PER_PALETTE: usize = 16; const MAX_COLOURS_PER_PALETTE: usize = 16;
#[derive(Debug, Clone, Eq, PartialEq, Hash)] #[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
pub(crate) struct Palette16 { pub(crate) struct Palette16 {
colours: Vec<Colour>, colours: Vec<Colour>,
} }
@ -62,12 +65,15 @@ impl Palette16 {
self.colours.iter() self.colours.iter()
} }
fn union_length(&self, other: &Palette16) -> usize { fn with_transparent(&self, transparent_colour: Colour) -> Self {
self.colours let mut new_colours = self.colours.clone();
let transparent_colour_index = new_colours
.iter() .iter()
.chain(&other.colours) .position(|&c| c == transparent_colour)
.collect::<HashSet<_>>() .expect("Could not find tranparent colour in palette");
.len() new_colours.swap(0, transparent_colour_index);
Self::from(&new_colours)
} }
fn is_satisfied_by(&self, other: &Palette16) -> bool { fn is_satisfied_by(&self, other: &Palette16) -> bool {
@ -87,6 +93,20 @@ impl IntoIterator for Palette16 {
} }
} }
impl<'a, T> From<T> for Palette16
where
T: IntoIterator<Item = &'a Colour>,
{
fn from(value: T) -> Self {
let mut palette = Palette16::new();
for colour in value.into_iter() {
palette.add_colour(*colour);
}
palette
}
}
pub(crate) struct Palette16Optimiser { pub(crate) struct Palette16Optimiser {
palettes: Vec<Palette16>, palettes: Vec<Palette16>,
colours: Vec<Colour>, colours: Vec<Colour>,
@ -125,28 +145,42 @@ impl Palette16Optimiser {
} }
} }
pub fn optimise_palettes(&self) -> Palette16OptimisationResults { pub fn optimise_palettes(&self) -> Result<Palette16OptimisationResults, DoesNotFitError> {
let mut assignments = vec![0; self.palettes.len()]; let transparent_colour = self
let mut optimised_palettes = vec![]; .transparent_colour
.unwrap_or_else(|| Colour::from_rgb(255, 0, 255, 0));
let mut unsatisfied_palettes = self let palettes_to_optimise = self
.palettes .palettes
.iter() .iter()
.cloned() .cloned()
.collect::<HashSet<Palette16>>(); .map(|mut palette| {
// ensure each palette we're creating the covering for has the transparent colour in it
palette.add_colour(transparent_colour);
palette
})
.collect::<BTreeSet<Palette16>>()
.into_iter()
.map(|palette| palette.colours)
.collect::<Vec<_>>();
while !unsatisfied_palettes.is_empty() { let packed_palettes =
let palette = self.find_maximal_palette_for(&unsatisfied_palettes); pagination_packing::overload_and_remove::<_, _, Vec<_>>(&palettes_to_optimise, 16);
unsatisfied_palettes.retain(|test_palette| !test_palette.is_satisfied_by(&palette)); let optimised_palettes = packed_palettes
.iter()
.map(|packed_palette| {
let colours = packed_palette.unique_symbols(&palettes_to_optimise);
Palette16::from(colours).with_transparent(transparent_colour)
})
.collect::<Vec<_>>();
optimised_palettes.push(palette); if optimised_palettes.len() > 16 {
return Err(DoesNotFitError(packed_palettes.len()));
if optimised_palettes.len() == MAX_COLOURS / MAX_COLOURS_PER_PALETTE {
panic!("Failed to find covering palettes");
}
} }
let mut assignments = vec![0; self.palettes.len()];
for (i, overall_palette) in self.palettes.iter().enumerate() { for (i, overall_palette) in self.palettes.iter().enumerate() {
assignments[i] = optimised_palettes assignments[i] = optimised_palettes
.iter() .iter()
@ -154,59 +188,86 @@ impl Palette16Optimiser {
.unwrap(); .unwrap();
} }
Palette16OptimisationResults { Ok(Palette16OptimisationResults {
optimised_palettes, optimised_palettes,
assignments, assignments,
transparent_colour: self.transparent_colour, transparent_colour: self.transparent_colour,
})
} }
} }
fn find_maximal_palette_for(&self, unsatisfied_palettes: &HashSet<Palette16>) -> Palette16 { pub struct DoesNotFitError(pub usize);
impl fmt::Display for DoesNotFitError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Could not fit colours into palette, needed {} bins but can have at most 16",
self.0
)
}
}
impl fmt::Debug for DoesNotFitError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{self}")
}
}
#[cfg(test)]
mod test {
use quickcheck::{quickcheck, Arbitrary};
use super::*;
quickcheck! {
fn less_than_256_colours_always_fits(palettes: Vec<Palette16>, transparent_colour: Colour) -> bool {
let mut optimiser = Palette16Optimiser::new(Some(transparent_colour));
for palette in palettes.clone().into_iter().take(16) {
optimiser.add_palette(palette);
}
let Ok(optimisation_results) = optimiser.optimise_palettes() else {
return false
};
check_palette_invariants(palettes.iter().take(16), optimisation_results, transparent_colour)
}
}
fn check_palette_invariants<'a>(
palettes: impl Iterator<Item = &'a Palette16>,
optimisation_results: Palette16OptimisationResults,
transparent_colour: Colour,
) -> bool {
for (i, palette) in palettes.enumerate() {
let optimised_palette =
&optimisation_results.optimised_palettes[optimisation_results.assignments[i]];
if !palette.is_satisfied_by(optimised_palette) {
return false;
}
if optimised_palette.colour_index(transparent_colour) != 0 {
return false;
}
}
true
}
impl Arbitrary for Palette16 {
fn arbitrary(g: &mut quickcheck::Gen) -> Self {
let mut palette = Palette16::new(); let mut palette = Palette16::new();
palette.add_colour( let size: usize = Arbitrary::arbitrary(g);
self.transparent_colour // never entirely fill the palette, will give at most 15 colours
.unwrap_or_else(|| Colour::from_rgb(255, 0, 255, 0)), let size = size.rem_euclid(16);
);
loop { for _ in 0..size {
let mut colour_usage = vec![0; MAX_COLOURS]; palette.add_colour(Arbitrary::arbitrary(g));
let mut a_colour_is_used = false;
for current_palette in unsatisfied_palettes {
if palette.union_length(current_palette) > MAX_COLOURS_PER_PALETTE {
continue;
} }
for colour in &current_palette.colours { palette
if palette.colours.contains(colour) {
continue;
}
if let Some(colour_index) = self.colours.iter().position(|c| c == colour) {
colour_usage[colour_index] += 1;
a_colour_is_used = true;
}
}
}
if !a_colour_is_used {
return palette;
}
let best_index = colour_usage
.iter()
.enumerate()
.max_by(|(_, usage1), (_, usage2)| usage1.cmp(usage2))
.unwrap()
.0;
let best_colour = self.colours[best_index];
palette.add_colour(best_colour);
if palette.colours.len() == MAX_COLOURS_PER_PALETTE {
return palette;
}
} }
} }
} }

View file

@ -1,4 +1,4 @@
use std::{collections::HashSet, iter::FromIterator}; use std::collections::BTreeSet;
use crate::{ use crate::{
colour::Colour, colour::Colour,
@ -7,13 +7,13 @@ use crate::{
}; };
pub struct Palette256 { pub struct Palette256 {
colours: HashSet<Colour>, colours: BTreeSet<Colour>,
} }
impl Palette256 { impl Palette256 {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
colours: HashSet::new(), colours: BTreeSet::new(),
} }
} }
@ -41,8 +41,8 @@ impl Palette256 {
.cloned() .cloned()
.collect(); .collect();
let current_colours_set = HashSet::from_iter(optimised_palette_colours.iter().cloned()); let current_colours_set = BTreeSet::from_iter(optimised_palette_colours.iter().cloned());
let new_colours: HashSet<_> = self let new_colours: BTreeSet<_> = self
.colours .colours
.symmetric_difference(&current_colours_set) .symmetric_difference(&current_colours_set)
.collect(); .collect();

View file

@ -1,3 +1,4 @@
use crate::deduplicator::{DeduplicatedData, Transformation};
use crate::palette16::Palette16OptimisationResults; use crate::palette16::Palette16OptimisationResults;
use crate::{add_image_256_to_tile_data, add_image_to_tile_data, collapse_to_4bpp}; use crate::{add_image_256_to_tile_data, add_image_to_tile_data, collapse_to_4bpp};
use crate::{image_loader::Image, ByteString}; use crate::{image_loader::Image, ByteString};
@ -5,6 +6,7 @@ use crate::{image_loader::Image, ByteString};
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use quote::{format_ident, quote}; use quote::{format_ident, quote};
use std::collections::BTreeMap;
use std::iter; use std::iter;
pub(crate) fn generate_palette_code( pub(crate) fn generate_palette_code(
@ -29,7 +31,7 @@ pub(crate) fn generate_palette_code(
}); });
quote! { quote! {
pub const PALETTES: &[#crate_prefix::display::palette16::Palette16] = &[#(#palettes),*]; pub static PALETTES: &[#crate_prefix::display::palette16::Palette16] = &[#(#palettes),*];
} }
} }
@ -40,41 +42,87 @@ pub(crate) fn generate_code(
image_filename: &str, image_filename: &str,
crate_prefix: String, crate_prefix: String,
assignment_offset: Option<usize>, assignment_offset: Option<usize>,
deduplicate: bool,
) -> TokenStream { ) -> TokenStream {
let crate_prefix = format_ident!("{}", crate_prefix); let crate_prefix = format_ident!("{}", crate_prefix);
let output_variable_name = format_ident!("{}", output_variable_name); let output_variable_name = format_ident!("{}", output_variable_name);
let (image, dedup_data) = if deduplicate {
let (new_image, dedup_data) =
crate::deduplicator::deduplicate_image(image, assignment_offset.is_some());
(new_image, dedup_data)
} else {
(
image.clone(),
(0..(image.width * image.height / 8 / 8))
.map(|i| DeduplicatedData {
new_index: i,
transformation: Transformation::none(),
})
.collect(),
)
};
let remap_index = dedup_data
.iter()
.enumerate()
.map(|(i, data)| (data.new_index, i))
.collect::<BTreeMap<_, _>>(); // BTreeMap so that values below is in order
let remap_index = remap_index.values().cloned().collect::<Vec<_>>();
let (tile_data, assignments) = if let Some(assignment_offset) = assignment_offset { let (tile_data, assignments) = if let Some(assignment_offset) = assignment_offset {
let mut tile_data = Vec::new(); let mut tile_data = Vec::new();
add_image_to_tile_data(&mut tile_data, image, results, assignment_offset); add_image_to_tile_data(
&mut tile_data,
&image,
results,
assignment_offset,
false,
&remap_index,
);
let tile_data = collapse_to_4bpp(&tile_data); let tile_data = collapse_to_4bpp(&tile_data);
let num_tiles = image.width * image.height / 8usize.pow(2); let num_tiles = image.width * image.height / 8usize.pow(2);
let assignments = results let all_assignments = &results.assignments[assignment_offset..];
.assignments let assignments = (0..num_tiles)
.iter() .map(|tile_id| all_assignments[remap_index[tile_id]] as u8)
.skip(assignment_offset)
.take(num_tiles)
.map(|&x| x as u8)
.collect(); .collect();
(tile_data, assignments) (tile_data, assignments)
} else { } else {
let mut tile_data = Vec::new(); let mut tile_data = Vec::new();
add_image_256_to_tile_data(&mut tile_data, image, results); add_image_256_to_tile_data(&mut tile_data, &image, results);
(tile_data, vec![]) (tile_data, vec![])
}; };
let tile_settings = dedup_data.iter().map(|data| {
let palette_assignment = assignments.get(data.new_index).unwrap_or(&0);
let vflipped = data.transformation.vflip;
let hflipped = data.transformation.hflip;
let index = data.new_index as u16;
quote! {
#crate_prefix::display::tiled::TileSetting::new(#index, #hflipped, #vflipped, #palette_assignment)
}
});
let data = ByteString(&tile_data); let data = ByteString(&tile_data);
let tile_format = if assignment_offset.is_some() {
quote! { #crate_prefix::display::tiled::TileFormat::FourBpp }
} else {
quote! { #crate_prefix::display::tiled::TileFormat::EightBpp }
};
quote! { quote! {
#[allow(non_upper_case_globals)] #[allow(non_upper_case_globals)]
pub const #output_variable_name: #crate_prefix::display::tile_data::TileData = { pub static #output_variable_name: #crate_prefix::display::tile_data::TileData = {
const _: &[u8] = include_bytes!(#image_filename); const _: &[u8] = include_bytes!(#image_filename);
const TILE_DATA: &[u8] = { const TILE_DATA: &[u8] = {
@ -83,7 +131,7 @@ pub(crate) fn generate_code(
pub bytes: Bytes, pub bytes: Bytes,
} }
const ALIGNED: &AlignedAs<u16, [u8]> = &AlignedAs { const ALIGNED: &AlignedAs<u32, [u8]> = &AlignedAs {
_align: [], _align: [],
bytes: *#data, bytes: *#data,
}; };
@ -91,11 +139,13 @@ pub(crate) fn generate_code(
&ALIGNED.bytes &ALIGNED.bytes
}; };
const PALETTE_ASSIGNMENT: &[u8] = &[ const TILE_SET: #crate_prefix::display::tiled::TileSet = #crate_prefix::display::tiled::TileSet::new(TILE_DATA, #tile_format);
#(#assignments),*
const TILE_SETTINGS: &[#crate_prefix::display::tiled::TileSetting] = &[
#(#tile_settings),*
]; ];
#crate_prefix::display::tile_data::TileData::new(TILE_DATA, PALETTE_ASSIGNMENT) #crate_prefix::display::tile_data::TileData::new(TILE_SET, TILE_SETTINGS)
}; };
} }
} }

View file

@ -1,7 +1,7 @@
[package] [package]
name = "agb_macros" name = "agb_macros"
version = "0.15.0" version = "0.21.1"
authors = ["Gwilym Kuiper <gw@ilym.me>"] authors = ["Gwilym Inzani <gw@ilym.me>"]
edition = "2021" edition = "2021"
license = "MPL-2.0" license = "MPL-2.0"
description = "Macro for declaring the entry point for a game using the agb library" description = "Macro for declaring the entry point for a game using the agb library"
@ -14,13 +14,3 @@ proc-macro = true
syn = { version = "2", features = ["full", "extra-traits"] } syn = { version = "2", features = ["full", "extra-traits"] }
proc-macro2 = "1" proc-macro2 = "1"
quote = "1" quote = "1"
[profile.dev]
opt-level = 3
debug = true
[profile.release]
opt-level = 3
lto = "fat"
debug = true
codegen-units = 1

View file

@ -103,6 +103,7 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
quote!( quote!(
#[cfg(not(test))] #[cfg(not(test))]
#[export_name = "main"] #[export_name = "main"]
#[doc(hidden)]
#(#attrs)* #(#attrs)*
pub extern "C" fn #fn_name() -> ! { pub extern "C" fn #fn_name() -> ! {
let #mutable #argument_name = unsafe { #argument_type ::new_in_entry() }; let #mutable #argument_name = unsafe { #argument_type ::new_in_entry() };
@ -112,6 +113,7 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
#[cfg(test)] #[cfg(test)]
#[export_name = "main"] #[export_name = "main"]
#[doc(hidden)]
#(#attrs)* #(#attrs)*
pub extern "C" fn #fn_name() -> ! { pub extern "C" fn #fn_name() -> ! {
let mut #argument_name = unsafe { #argument_type ::new_in_entry() }; let mut #argument_name = unsafe { #argument_type ::new_in_entry() };

View file

@ -1,7 +1,7 @@
[package] [package]
name = "agb_sound_converter" name = "agb_sound_converter"
version = "0.15.0" version = "0.21.1"
authors = ["Gwilym Kuiper <gw@ilym.me>"] authors = ["Gwilym Inzani <gw@ilym.me>"]
edition = "2021" edition = "2021"
license = "MPL-2.0" license = "MPL-2.0"
description = "Library for converting wavs for use on the Game Boy Advance" description = "Library for converting wavs for use on the Game Boy Advance"
@ -15,13 +15,3 @@ hound = "3.5"
syn = "2" syn = "2"
proc-macro2 = "1" proc-macro2 = "1"
quote = "1" quote = "1"
[profile.dev]
opt-level = 3
debug = true
[profile.release]
opt-level = 3
lto = "fat"
debug = true
codegen-units = 1

View file

@ -6,9 +6,17 @@ build-std-features = ["compiler-builtins-mem"]
target = "thumbv4t-none-eabi" target = "thumbv4t-none-eabi"
[target.thumbv4t-none-eabi] [target.thumbv4t-none-eabi]
rustflags = ["-Clink-arg=-Tgba.ld", "-Ctarget-cpu=arm7tdmi"] rustflags = [
"-Clink-arg=-Tgba.ld",
"-Ctarget-cpu=arm7tdmi",
"-Cforce-frame-pointers=yes",
]
runner = "mgba-test-runner" runner = "mgba-test-runner"
[target.armv4t-none-eabi] [target.armv4t-none-eabi]
rustflags = ["-Clink-arg=-Tgba.ld", "-Ctarget-cpu=arm7tdmi"] rustflags = [
"-Clink-arg=-Tgba.ld",
"-Ctarget-cpu=arm7tdmi",
"-Cforce-frame-pointers=yes",
]
runner = "mgba-test-runner" runner = "mgba-test-runner"

View file

@ -1,32 +1,46 @@
[package] [package]
name = "agb" name = "agb"
version = "0.15.0" version = "0.21.1"
authors = ["Corwin Kuiper <corwin@kuiper.dev>", "Gwilym Kuiper <gw@ilym.me>"] authors = ["Corwin Kuiper <corwin@kuiper.dev>", "Gwilym Inzani <gw@ilym.me>"]
edition = "2021" edition = "2021"
description = "Library for Game Boy Advance Development" description = "Library for Game Boy Advance Development"
license = "MPL-2.0" license = "MPL-2.0"
repository = "https://github.com/agbrs/agb" repository = "https://github.com/agbrs/agb"
homepage = "https://agbrs.dev"
exclude = ["/tests", "/examples"]
keywords = ["game-engines", "embedded"]
[features] [features]
default = ["testing"] default = ["backtrace", "testing"]
backtrace = ["testing", "dep:qrcodegen-no-heap"]
testing = [] testing = []
multiboot = []
[dependencies] [dependencies]
bitflags = "2" bitflags = "2"
agb_image_converter = { version = "0.15.0", path = "../agb-image-converter" } agb_image_converter = { version = "0.21.1", path = "../agb-image-converter" }
agb_sound_converter = { version = "0.15.0", path = "../agb-sound-converter" } agb_sound_converter = { version = "0.21.1", path = "../agb-sound-converter" }
agb_macros = { version = "0.15.0", path = "../agb-macros" } agb_macros = { version = "0.21.1", path = "../agb-macros" }
agb_fixnum = { version = "0.15.0", path = "../agb-fixnum" } agb_fixnum = { version = "0.21.1", path = "../agb-fixnum" }
agb_hashmap = { version = "0.15.0", path = "../agb-hashmap" } agb_hashmap = { version = "0.21.1", path = "../agb-hashmap", features = [
bare-metal = "1" "allocator_api",
modular-bitfield = "0.11" ] }
rustc-hash = { version = "1", default-features = false } bilge = "0.2"
qrcodegen-no-heap = { version = "1.8", optional = true }
portable-atomic = { version = "1.6.0", default-features = false, features = [
"unsafe-assume-single-core",
"fallback",
] }
once_cell = { version = "1.20.1", default-features = false, features = [
"critical-section",
] }
critical-section = { version = "1.1.2", features = ["restore-state-u16"] }
embedded-hal = "0.2.7" embedded-hal = "0.2.7"
nb = "1.1" nb = "1.1"
[package.metadata.docs.rs] [package.metadata.docs.rs]
default-target = "thumbv6m-none-eabi" default-target = "thumbv4t-none-eabi"
targets = [] cargo-args = ["-Zbuild-std=core,alloc"]
[profile.dev] [profile.dev]
opt-level = 3 opt-level = 3
@ -36,4 +50,3 @@ debug = true
opt-level = 3 opt-level = 3
lto = "fat" lto = "fat"
debug = true debug = true
codegen-units = 1

1
agb/README.md Symbolic link
View file

@ -0,0 +1 @@
../README.md

View file

@ -1,76 +1,20 @@
use std::path; use std::{env, error::Error, fs, path::PathBuf};
fn main() { fn main() -> Result<(), Box<dyn Error>> {
let asm = &[ let out = &PathBuf::from(env::var("OUT_DIR").unwrap());
"src/crt0.s", let linker_script = if env::var("CARGO_FEATURE_MULTIBOOT").is_ok() {
"src/interrupt_handler.s", include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/gba_mb.ld")).as_slice()
"src/sound/mixer/mixer.s", } else {
"src/agbabi/memset.s", include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/gba.ld")).as_slice()
"src/agbabi/memcpy.s", };
"src/save/asm_routines.s",
];
println!("cargo:rerun-if-changed=gba.ld"); fs::write(out.join("gba.ld"), linker_script)?;
println!("cargo:rerun-if-changed=gba_mb.ld"); println!("cargo:rustc-link-search={}", out.display());
println!("cargo:rerun-if-changed=src/asm_include.s");
println!("cargo:rerun-if-changed=src/agbabi/macros.inc");
println!("cargo:rerun-if-changed=gfx/test_logo.png");
println!("cargo:rerun-if-changed=src/gba.ld");
println!("cargo:rerun-if-changed=src/gba_mb.ld");
println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_MULTIBOOT");
let out_dir = std::env::var("OUT_DIR").expect("OUT_DIR environment variable must be specified"); Ok(())
let mut o_files = vec![];
for &a in asm.iter() {
println!("cargo:rerun-if-changed={a}");
let filename = path::Path::new(a);
let filename = filename.with_extension("o");
let filename = filename
.file_name()
.expect("should have filename")
.to_str()
.expect("Please make it valid utf-8");
let out_file_path = format!("{out_dir}/{filename}");
let out = std::process::Command::new("arm-none-eabi-as")
.arg("-mthumb-interwork")
.arg("-mcpu=arm7tdmi")
.arg("-g")
.args(["-o", out_file_path.as_str()])
.arg(a)
.output()
.unwrap_or_else(|_| panic!("failed to compile {a}"));
assert!(
out.status.success(),
"{}",
String::from_utf8_lossy(&out.stderr)
);
for warning_line in String::from_utf8_lossy(&out.stderr).split('\n') {
if !warning_line.is_empty() {
println!("cargo:warning={warning_line}");
}
}
o_files.push(out_file_path);
}
let archive = format!("{out_dir}/agb.a");
let _ = std::fs::remove_file(&archive);
let ar_out = std::process::Command::new("arm-none-eabi-ar")
.arg("-crs")
.arg(&archive)
.args(&o_files)
.output()
.expect("Failed to create static library");
assert!(
ar_out.status.success(),
"{}",
String::from_utf8_lossy(&ar_out.stderr)
);
println!("cargo:rustc-link-search={out_dir}");
} }

View file

@ -4,34 +4,34 @@
use agb::{ use agb::{
display::{ display::{
affine::AffineMatrixBackground, affine::AffineMatrixBackground,
tiled::{AffineBackgroundSize, TileFormat, TileSet, TiledMap}, tiled::{AffineBackgroundSize, TiledMap},
Priority, Priority,
}, },
fixnum::{num, Num}, fixnum::{num, Num},
include_background_gfx, include_background_gfx,
}; };
include_background_gfx!(affine_tiles, water_tiles => 256 "examples/water_tiles.png"); include_background_gfx!(affine_tiles, "3f3f74", water_tiles => 256 "examples/water_tiles.png");
#[agb::entry] #[agb::entry]
fn main(mut gba: agb::Gba) -> ! { fn main(mut gba: agb::Gba) -> ! {
let (gfx, mut vram) = gba.display.video.tiled2(); let (gfx, mut vram) = gba.display.video.tiled1();
let vblank = agb::interrupt::VBlank::get(); let vblank = agb::interrupt::VBlank::get();
let tileset = TileSet::new(affine_tiles::water_tiles.tiles, TileFormat::EightBpp); let tileset = &affine_tiles::water_tiles.tiles;
vram.set_background_palettes(affine_tiles::PALETTES); vram.set_background_palettes(affine_tiles::PALETTES);
let mut bg = gfx.background(Priority::P0, AffineBackgroundSize::Background32x32); let mut bg = gfx.affine(Priority::P0, AffineBackgroundSize::Background32x32);
for y in 0..32u16 { for y in 0..32u16 {
for x in 0..32u16 { for x in 0..32u16 {
bg.set_tile(&mut vram, (x, y).into(), &tileset, 1); bg.set_tile(&mut vram, (x, y), tileset, 1);
} }
} }
bg.commit(&mut vram); bg.commit(&mut vram);
bg.show(); bg.set_visible(true);
let mut rotation = num!(0.); let mut rotation = num!(0.);
let rotation_increase: Num<i32, 16> = num!(0.01); let rotation_increase: Num<i32, 16> = num!(0.01);
@ -43,17 +43,17 @@ fn main(mut gba: agb::Gba) -> ! {
loop { loop {
input.update(); input.update();
scroll_x += input.x_tri() as i32; scroll_x += input.x_tri() as i16;
scroll_y += input.y_tri() as i32; scroll_y += input.y_tri() as i16;
let scroll_pos = (scroll_x, scroll_y).into(); let scroll_pos = (scroll_x, scroll_y);
rotation += rotation_increase; rotation += rotation_increase;
rotation = rotation.rem_euclid(1.into()); rotation = rotation.rem_euclid(1.into());
let transformation = AffineMatrixBackground::from_scale_rotation_position( let transformation = AffineMatrixBackground::from_scale_rotation_position(
(0, 0).into(), (0, 0),
(1, 1).into(), (1, 1),
rotation, rotation,
scroll_pos, scroll_pos,
); );

View file

@ -3,7 +3,7 @@
use agb::{ use agb::{
display::{ display::{
tiled::{RegularBackgroundSize, TileFormat, TileSet, TileSetting, TiledMap}, tiled::{RegularBackgroundSize, TiledMap},
Priority, Priority,
}, },
include_background_gfx, include_background_gfx,
@ -16,35 +16,35 @@ fn main(mut gba: agb::Gba) -> ! {
let (gfx, mut vram) = gba.display.video.tiled0(); let (gfx, mut vram) = gba.display.video.tiled0();
let vblank = agb::interrupt::VBlank::get(); let vblank = agb::interrupt::VBlank::get();
let tileset = TileSet::new(water_tiles::water_tiles.tiles, TileFormat::FourBpp); let tileset = &water_tiles::water_tiles.tiles;
vram.set_background_palettes(water_tiles::PALETTES); vram.set_background_palettes(water_tiles::PALETTES);
let mut bg = gfx.background( let mut bg = gfx.background(
Priority::P0, Priority::P0,
RegularBackgroundSize::Background32x32, RegularBackgroundSize::Background32x32,
TileFormat::FourBpp, tileset.format(),
); );
for y in 0..20u16 { for y in 0..20u16 {
for x in 0..30u16 { for x in 0..30u16 {
bg.set_tile( bg.set_tile(
&mut vram, &mut vram,
(x, y).into(), (x, y),
&tileset, tileset,
TileSetting::new(0, false, false, 0), water_tiles::water_tiles.tile_settings[0],
); );
} }
} }
bg.commit(&mut vram); bg.commit(&mut vram);
bg.show(); bg.set_visible(true);
let mut i = 0; let mut i = 0;
loop { loop {
i = (i + 1) % 8; i = (i + 1) % 8;
vram.replace_tile(&tileset, 0, &tileset, i); vram.replace_tile(tileset, 0, tileset, i);
vblank.wait_for_vblank(); vblank.wait_for_vblank();
} }

View file

@ -1,7 +1,7 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
use agb::display; use agb::display::{self, HEIGHT, WIDTH};
#[agb::entry] #[agb::entry]
fn main(mut gba: agb::Gba) -> ! { fn main(mut gba: agb::Gba) -> ! {
@ -11,25 +11,22 @@ fn main(mut gba: agb::Gba) -> ! {
bitmap.set_palette_entry(1, 0x001F); bitmap.set_palette_entry(1, 0x001F);
bitmap.set_palette_entry(2, 0x03E0); bitmap.set_palette_entry(2, 0x03E0);
bitmap.draw_point_page( for y in 0..HEIGHT {
display::WIDTH / 2, for x in 0..WIDTH {
display::HEIGHT / 2, bitmap.draw_point_page(x, y, 0xF, display::bitmap4::Page::Front);
1, bitmap.draw_point_page(x, y, 1, display::bitmap4::Page::Front);
display::bitmap4::Page::Front, bitmap.draw_point_page(x, y, 0xFF, display::bitmap4::Page::Back);
); bitmap.draw_point_page(x, y, 2, display::bitmap4::Page::Back);
bitmap.draw_point_page( }
display::WIDTH / 2 + 5, }
display::HEIGHT / 2,
2,
display::bitmap4::Page::Back,
);
let mut count = 0; let mut input = agb::input::ButtonController::new();
loop { loop {
vblank.wait_for_vblank(); vblank.wait_for_vblank();
count += 1; input.update();
if count % 6 == 0 {
if input.is_just_pressed(agb::input::Button::A) {
bitmap.flip_page(); bitmap.flip_page();
} }
} }

View file

@ -11,7 +11,6 @@ use agb::{
}, },
input::Button, input::Button,
}; };
use core::convert::TryInto;
#[derive(PartialEq, Eq)] #[derive(PartialEq, Eq)]
enum State { enum State {
@ -65,13 +64,13 @@ fn main(mut gba: agb::Gba) -> ! {
let i = i as u16; let i = i as u16;
background.set_tile( background.set_tile(
&mut vram, &mut vram,
(i % 32, i / 32).into(), (i % 32, i / 32),
&tileset, &tileset,
TileSetting::from_raw(tile), TileSetting::from_raw(tile),
); );
} }
background.show(); background.set_visible(true);
background.commit(&mut vram); background.commit(&mut vram);
let object = gba.display.object.get_managed(); let object = gba.display.object.get_managed();

View file

@ -0,0 +1,49 @@
#![no_std]
#![no_main]
extern crate alloc;
use alloc::boxed::Box;
use agb::{
display::{
example_logo,
tiled::{RegularBackgroundSize, TileFormat},
},
interrupt::VBlank,
};
#[agb::entry]
fn main(mut gba: agb::Gba) -> ! {
let (gfx, mut vram) = gba.display.video.tiled0();
let mut map = gfx.background(
agb::display::Priority::P0,
RegularBackgroundSize::Background32x32,
TileFormat::FourBpp,
);
let dma = gba.dma.dma().dma0;
example_logo::display_logo_basic(&mut map, &mut vram);
let vblank = VBlank::get();
let colours: Box<[_]> = (0..160).map(|i| ((i * 0xffff) / 160) as u16).collect();
let background_colour = 0x732b; // generated using `https://agbrs.dev/colour`
let background_colour_index = vram
.find_colour_index_16(0, background_colour)
.expect("Should contain colour 0x732b");
loop {
let _background_color_transfer = unsafe {
dma.hblank_transfer(
&vram.background_palette_colour_dma(0, background_colour_index),
&colours,
)
};
vblank.wait_for_vblank();
}
}

View file

@ -0,0 +1,46 @@
#![no_std]
#![no_main]
extern crate alloc;
use alloc::boxed::Box;
use agb::{
display::{
example_logo,
tiled::{RegularBackgroundSize, TileFormat},
},
interrupt::VBlank,
};
#[agb::entry]
fn main(mut gba: agb::Gba) -> ! {
let (gfx, mut vram) = gba.display.video.tiled0();
let mut map = gfx.background(
agb::display::Priority::P0,
RegularBackgroundSize::Background32x32,
TileFormat::FourBpp,
);
let dma = gba.dma.dma().dma0;
example_logo::display_logo(&mut map, &mut vram);
let vblank = VBlank::get();
let offsets: Box<[_]> = (0..160 * 2).collect();
let mut frame = 0;
loop {
let _x_scroll_transfer =
unsafe { dma.hblank_transfer(&map.x_scroll_dma(), &offsets[frame..]) };
vblank.wait_for_vblank();
frame += 1;
if frame > 160 {
frame = 0;
}
}
}

View file

@ -0,0 +1,96 @@
#![no_std]
#![no_main]
extern crate alloc;
use agb::{
display::{
example_logo,
tiled::{RegularBackgroundSize, TileFormat},
window::WinIn,
HEIGHT, WIDTH,
},
fixnum::{Num, Rect, Vector2D},
interrupt::VBlank,
};
use alloc::{boxed::Box, vec};
type FNum = Num<i32, 8>;
#[agb::entry]
fn entry(mut gba: agb::Gba) -> ! {
main(gba)
}
fn main(mut gba: agb::Gba) -> ! {
let (gfx, mut vram) = gba.display.video.tiled0();
let mut map = gfx.background(
agb::display::Priority::P0,
RegularBackgroundSize::Background32x32,
TileFormat::FourBpp,
);
let mut window = gba.display.window.get();
window
.win_in(WinIn::Win0)
.set_background_enable(map.background(), true)
.set_position(&Rect::new((10, 10).into(), (64, 64).into()))
.enable();
let dmas = gba.dma.dma();
example_logo::display_logo(&mut map, &mut vram);
let mut pos: Vector2D<FNum> = (10, 10).into();
let mut velocity: Vector2D<FNum> = Vector2D::new(1.into(), 1.into());
let vblank = VBlank::get();
let circle: Box<[_]> = (1..64i32)
.map(|i| {
let y = 32 - i;
let x = (32 * 32 - y * y).isqrt();
let x1 = 32 - x;
let x2 = 32 + x;
((x1 as u16) << 8) | (x2 as u16)
})
.collect();
let mut circle_poses = vec![0; 160];
loop {
pos += velocity;
if pos.x.floor() > WIDTH - 64 || pos.x.floor() < 0 {
velocity.x *= -1;
}
if pos.y.floor() > HEIGHT - 64 || pos.y.floor() < 0 {
velocity.y *= -1;
}
let x_pos = pos.x.floor().max(0) as u16;
let y_pos = pos.y.floor().max(0);
let x_adjustment = x_pos << 8 | x_pos;
for (i, value) in circle_poses.iter_mut().enumerate() {
let i = i as i32;
if i <= y_pos || i >= y_pos + 64 {
*value = 0;
continue;
}
*value = circle[(i - y_pos) as usize - 1] + x_adjustment;
}
window
.win_in(WinIn::Win0)
.set_position(&Rect::new(pos.floor(), (64, 65).into()));
window.commit();
let dma_controllable = window.win_in(WinIn::Win0).horizontal_position_dma();
let _transfer = unsafe { dmas.dma0.hblank_transfer(&dma_controllable, &circle_poses) };
vblank.wait_for_vblank();
}
}

View file

@ -3,7 +3,7 @@
use agb::display::{ use agb::display::{
palette16::Palette16, palette16::Palette16,
tiled::{RegularBackgroundSize, TileFormat, TileSetting, TiledMap}, tiled::{RegularBackgroundSize, TileFormat, TiledMap},
Priority, Priority,
}; };
@ -40,9 +40,9 @@ fn main(mut gba: agb::Gba) -> ! {
bg.set_tile( bg.set_tile(
&mut vram, &mut vram,
(x as u16, y as u16).into(), (x as u16, y as u16),
&dynamic_tile.tile_set(), &dynamic_tile.tile_set(),
TileSetting::from_raw(dynamic_tile.tile_index()), dynamic_tile.tile_setting(),
); );
vram.remove_dynamic_tile(dynamic_tile); vram.remove_dynamic_tile(dynamic_tile);
@ -50,7 +50,7 @@ fn main(mut gba: agb::Gba) -> ! {
} }
bg.commit(&mut vram); bg.commit(&mut vram);
bg.show(); bg.set_visible(true);
loop { loop {
vblank.wait_for_vblank(); vblank.wait_for_vblank();

94
agb/examples/font/OFL.txt Normal file
View file

@ -0,0 +1,94 @@
Copyright (c) 2021, TakWolf (https://takwolf.com),
with Reserved Font Name 'Ark Pixel'.
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

View file

@ -1,25 +0,0 @@
#![no_std]
#![no_main]
#[panic_handler]
fn panic_handler(_info: &core::panic::PanicInfo) -> ! {
loop {}
}
#[no_mangle]
pub extern "C" fn __RUST_INTERRUPT_HANDLER(_: u16) {}
// implementation of tonc's "My first GBA demo"
// https://coranac.com/tonc/text/first.htm
#[no_mangle]
pub fn main() -> ! {
unsafe {
*(0x0400_0000 as *mut u32) = 0x0403;
let video = 0x0600_0000 as *mut u16;
*video.offset(120 + 80 * 240) = 0x001F;
*video.offset(136 + 80 * 240) = 0x03E0;
*video.offset(120 + 96 * 240) = 0x7C00;
}
loop {}
}

View file

@ -3,9 +3,7 @@
use agb::{ use agb::{
display::{ display::{
tiled::{ tiled::{RegularBackgroundSize, RegularMap, TileFormat, TiledMap, VRamManager},
RegularBackgroundSize, RegularMap, TileFormat, TileSetting, TiledMap, VRamManager,
},
Font, Priority, Font, Priority,
}, },
include_font, include_wav, include_font, include_wav,
@ -16,9 +14,9 @@ use agb::{
use core::fmt::Write; use core::fmt::Write;
// Music - "Crazy glue" by Josh Woodward, free download at http://joshwoodward.com // Music - "Crazy glue" by Josh Woodward, free download at http://joshwoodward.com
const CRAZY_GLUE: &[u8] = include_wav!("examples/JoshWoodward-CrazyGlue.wav"); static CRAZY_GLUE: &[u8] = include_wav!("examples/JoshWoodward-CrazyGlue.wav");
const FONT: Font = include_font!("examples/font/yoster.ttf", 12); static FONT: Font = include_font!("examples/font/yoster.ttf", 12);
#[agb::entry] #[agb::entry]
fn main(mut gba: Gba) -> ! { fn main(mut gba: Gba) -> ! {
@ -33,7 +31,7 @@ fn main(mut gba: Gba) -> ! {
init_background(&mut bg, &mut vram); init_background(&mut bg, &mut vram);
let mut title_renderer = FONT.render_text((0u16, 3u16).into()); let mut title_renderer = FONT.render_text((0u16, 3u16));
let mut writer = title_renderer.writer(1, 0, &mut bg, &mut vram); let mut writer = title_renderer.writer(1, 0, &mut bg, &mut vram);
writeln!(&mut writer, "Crazy Glue by Josh Woodward").unwrap(); writeln!(&mut writer, "Crazy Glue by Josh Woodward").unwrap();
@ -41,7 +39,7 @@ fn main(mut gba: Gba) -> ! {
writer.commit(); writer.commit();
bg.commit(&mut vram); bg.commit(&mut vram);
bg.show(); bg.set_visible(true);
let timer_controller = gba.timers.timers(); let timer_controller = gba.timers.timers();
let mut timer = timer_controller.timer2; let mut timer = timer_controller.timer2;
@ -59,7 +57,7 @@ fn main(mut gba: Gba) -> ! {
let mut frame_counter = 0i32; let mut frame_counter = 0i32;
let mut has_written_frame_time = false; let mut has_written_frame_time = false;
let mut stats_renderer = FONT.render_text((0u16, 6u16).into()); let mut stats_renderer = FONT.render_text((0u16, 6u16));
loop { loop {
vblank_provider.wait_for_vblank(); vblank_provider.wait_for_vblank();
bg.commit(&mut vram); bg.commit(&mut vram);
@ -108,9 +106,9 @@ fn init_background(bg: &mut RegularMap, vram: &mut VRamManager) {
for x in 0..30u16 { for x in 0..30u16 {
bg.set_tile( bg.set_tile(
vram, vram,
(x, y).into(), (x, y),
&background_tile.tile_set(), &background_tile.tile_set(),
TileSetting::from_raw(background_tile.tile_index()), background_tile.tile_setting(),
); );
} }
} }

View file

@ -7,7 +7,7 @@ use agb::sound::mixer::{Frequency, SoundChannel};
use agb::{fixnum::num, include_wav, Gba}; use agb::{fixnum::num, include_wav, Gba};
// Music - "Dead Code" by Josh Woodward, free download at http://joshwoodward.com // Music - "Dead Code" by Josh Woodward, free download at http://joshwoodward.com
const DEAD_CODE: &[u8] = include_wav!("examples/JoshWoodward-DeadCode.wav"); static DEAD_CODE: &[u8] = include_wav!("examples/JoshWoodward-DeadCode.wav");
#[agb::entry] #[agb::entry]
fn main(mut gba: Gba) -> ! { fn main(mut gba: Gba) -> ! {
@ -25,8 +25,8 @@ fn main(mut gba: Gba) -> ! {
{ {
if let Some(channel) = mixer.channel(&channel_id) { if let Some(channel) = mixer.channel(&channel_id) {
let half: Num<i16, 4> = num!(0.5); let half: Num<i16, 8> = num!(0.5);
let half_usize: Num<usize, 8> = num!(0.5); let half_usize: Num<u32, 8> = num!(0.5);
match input.x_tri() { match input.x_tri() {
Tri::Negative => channel.panning(-half), Tri::Negative => channel.panning(-half),
Tri::Zero => channel.panning(0), Tri::Zero => channel.panning(0),
@ -46,6 +46,14 @@ fn main(mut gba: Gba) -> ! {
} else { } else {
channel.volume(1); channel.volume(1);
} }
if input.is_pressed(Button::A) {
channel.resume();
}
if input.is_pressed(Button::B) {
channel.pause();
}
} }
} }

View file

@ -0,0 +1,98 @@
#![no_std]
#![no_main]
use agb::{
display::{
object::{ChangeColour, ObjectTextRender, PaletteVram, Size, TextAlignment},
palette16::Palette16,
Font, HEIGHT, WIDTH,
},
include_font,
input::Button,
};
extern crate alloc;
use core::fmt::Write;
static FONT: Font = include_font!("examples/font/ark-pixel-10px-proportional-ja.ttf", 10);
#[agb::entry]
fn entry(gba: agb::Gba) -> ! {
main(gba);
}
fn main(mut gba: agb::Gba) -> ! {
let (mut unmanaged, _sprites) = gba.display.object.get_unmanaged();
let mut palette = [0x0; 16];
palette[1] = 0xFF_FF;
palette[2] = 0x00_FF;
let palette = Palette16::new(palette);
let palette = PaletteVram::new(&palette).unwrap();
let timer = gba.timers.timers();
let mut timer: agb::timer::Timer = timer.timer2;
timer.set_enabled(true);
timer.set_divider(agb::timer::Divider::Divider256);
let mut wr = ObjectTextRender::new(&FONT, Size::S16x16, palette);
let start = timer.value();
let player_name = "You";
let _ = writeln!(
wr,
"Woah!{change2} {player_name}! {change1}こんにちは! I have a bunch of text I want to show you. However, you will find that the amount of text I can display is limited. Who'd have thought! Good thing that my text system supports scrolling! It only took around 20 jank versions to get here!",
change2 = ChangeColour::new(2),
change1 = ChangeColour::new(1),
);
let end = timer.value();
agb::println!(
"Write took {} cycles",
256 * (end.wrapping_sub(start) as u32)
);
let vblank = agb::interrupt::VBlank::get();
let mut input = agb::input::ButtonController::new();
let start = timer.value();
wr.layout((WIDTH, 40), TextAlignment::Justify, 2);
let end = timer.value();
agb::println!(
"Layout took {} cycles",
256 * (end.wrapping_sub(start) as u32)
);
let mut line_done = false;
let mut frame = 0;
loop {
vblank.wait_for_vblank();
input.update();
let oam = &mut unmanaged.iter();
wr.commit(oam);
let start = timer.value();
if frame % 4 == 0 {
line_done = !wr.next_letter_group();
}
if line_done && input.is_just_pressed(Button::A) {
line_done = false;
wr.pop_line();
}
wr.update((0, HEIGHT - 40));
let end = timer.value();
frame += 1;
agb::println!(
"Took {} cycles, line done {}",
256 * (end.wrapping_sub(start) as u32),
line_done
);
}
}

View file

@ -1,17 +1,17 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
use agb::sync::Static; use portable_atomic::{AtomicU32, Ordering};
static COUNT: Static<u32> = Static::new(0); static COUNT: AtomicU32 = AtomicU32::new(0);
#[agb::entry] #[agb::entry]
fn main(_gba: agb::Gba) -> ! { fn main(_gba: agb::Gba) -> ! {
let _a = unsafe { let _a = unsafe {
agb::interrupt::add_interrupt_handler(agb::interrupt::Interrupt::VBlank, |_| { agb::interrupt::add_interrupt_handler(agb::interrupt::Interrupt::VBlank, |_| {
let cur_count = COUNT.read(); let cur_count = COUNT.load(Ordering::SeqCst);
agb::println!("Hello, world, frame = {}", cur_count); agb::println!("Hello, world, frame = {}", cur_count);
COUNT.write(cur_count + 1); COUNT.store(cur_count + 1, Ordering::SeqCst);
}) })
}; };
loop {} loop {}

View file

@ -16,7 +16,7 @@ fn main(mut gba: agb::Gba) -> ! {
} }
if input.is_just_pressed(agb::input::Button::B) { if input.is_just_pressed(agb::input::Button::B) {
#[allow(arithmetic_overflow)] #[allow(arithmetic_overflow)]
let _p = core::i32::MAX + 1; let _p = i32::MAX + 1;
} }
} }
} }

29
agb/examples/save.rs Normal file
View file

@ -0,0 +1,29 @@
#![no_std]
#![no_main]
use agb::save::Error;
extern crate alloc;
use alloc::vec::Vec;
#[agb::entry]
fn main(mut gba: agb::Gba) -> ! {
test_save(gba).unwrap();
panic!("example finished");
}
fn test_save(mut gba: agb::Gba) -> Result<(), Error> {
gba.save.init_sram();
let mut access = gba.save.access()?;
let mut is_save = 0;
access.read(0, core::slice::from_mut(&mut is_save))?;
if is_save != 0 {
access
.prepare_write(0..128)?
.write(0, &(0..128).collect::<Vec<_>>())?;
}
Ok(())
}

View file

@ -11,14 +11,14 @@ use agb::fixnum::num;
use agb_fixnum::Num; use agb_fixnum::Num;
use alloc::vec::Vec; use alloc::vec::Vec;
const GRAPHICS: &Graphics = agb::include_aseprite!( static GRAPHICS: &Graphics = agb::include_aseprite!(
"examples/gfx/objects.aseprite", "examples/gfx/objects.aseprite",
"examples/gfx/boss.aseprite", "examples/gfx/boss.aseprite",
"examples/gfx/wide.aseprite", "examples/gfx/wide.aseprite",
"examples/gfx/tall.aseprite" "examples/gfx/tall.aseprite"
); );
const SPRITES: &[Sprite] = GRAPHICS.sprites(); static SPRITES: &[Sprite] = GRAPHICS.sprites();
const TAG_MAP: &TagMap = GRAPHICS.tags(); static TAG_MAP: &TagMap = GRAPHICS.tags();
fn all_sprites(gfx: &OamManaged, rotation_speed: Num<i32, 16>) { fn all_sprites(gfx: &OamManaged, rotation_speed: Num<i32, 16>) {
let mut input = agb::input::ButtonController::new(); let mut input = agb::input::ButtonController::new();
@ -34,7 +34,7 @@ fn all_sprites(gfx: &OamManaged, rotation_speed: Num<i32, 16>) {
let mut obj = gfx.object_sprite(&SPRITES[0]); let mut obj = gfx.object_sprite(&SPRITES[0]);
obj.set_affine_matrix(matrix.clone()); obj.set_affine_matrix(matrix.clone());
obj.show_affine(object::AffineMode::Affine); obj.show_affine(object::AffineMode::Affine);
obj.set_position((x * 16 + 8, y * 16 + 8).into()); obj.set_position((x * 16 + 8, y * 16 + 8));
objs.push(obj); objs.push(obj);
} }
} }
@ -87,7 +87,7 @@ fn all_tags(gfx: &OamManaged) {
let (size_x, size_y) = (size_x as i32, size_y as i32); let (size_x, size_y) = (size_x as i32, size_y as i32);
let mut obj = gfx.object_sprite(sprite); let mut obj = gfx.object_sprite(sprite);
obj.show(); obj.show();
obj.set_position((x * 32 + 16 - size_x / 2, y * 32 + 16 - size_y / 2).into()); obj.set_position((x * 32 + 16 - size_x / 2, y * 32 + 16 - size_y / 2));
objs.push((obj, v)); objs.push((obj, v));
} }

View file

@ -3,9 +3,7 @@
use agb::{ use agb::{
display::{ display::{
tiled::{ tiled::{RegularBackgroundSize, RegularMap, TileFormat, TiledMap, VRamManager},
RegularBackgroundSize, RegularMap, TileFormat, TileSetting, TiledMap, VRamManager,
},
Font, Priority, Font, Priority,
}, },
include_font, include_wav, include_font, include_wav,
@ -16,9 +14,9 @@ use agb::{
use core::fmt::Write; use core::fmt::Write;
// Music - "Let it in" by Josh Woodward, free download at http://joshwoodward.com // Music - "Let it in" by Josh Woodward, free download at http://joshwoodward.com
const LET_IT_IN: &[u8] = include_wav!("examples/JoshWoodward-LetItIn.wav"); static LET_IT_IN: &[u8] = include_wav!("examples/JoshWoodward-LetItIn.wav");
const FONT: Font = include_font!("examples/font/yoster.ttf", 12); static FONT: Font = include_font!("examples/font/yoster.ttf", 12);
#[agb::entry] #[agb::entry]
fn main(mut gba: Gba) -> ! { fn main(mut gba: Gba) -> ! {
@ -33,7 +31,7 @@ fn main(mut gba: Gba) -> ! {
init_background(&mut bg, &mut vram); init_background(&mut bg, &mut vram);
let mut title_renderer = FONT.render_text((0u16, 3u16).into()); let mut title_renderer = FONT.render_text((0u16, 3u16));
let mut writer = title_renderer.writer(1, 0, &mut bg, &mut vram); let mut writer = title_renderer.writer(1, 0, &mut bg, &mut vram);
writeln!(&mut writer, "Let it in by Josh Woodward").unwrap(); writeln!(&mut writer, "Let it in by Josh Woodward").unwrap();
@ -41,7 +39,7 @@ fn main(mut gba: Gba) -> ! {
writer.commit(); writer.commit();
bg.commit(&mut vram); bg.commit(&mut vram);
bg.show(); bg.set_visible(true);
let timer_controller = gba.timers.timers(); let timer_controller = gba.timers.timers();
let mut timer = timer_controller.timer2; let mut timer = timer_controller.timer2;
@ -57,7 +55,7 @@ fn main(mut gba: Gba) -> ! {
let mut frame_counter = 0i32; let mut frame_counter = 0i32;
let mut has_written_frame_time = false; let mut has_written_frame_time = false;
let mut stats_renderer = FONT.render_text((0u16, 6u16).into()); let mut stats_renderer = FONT.render_text((0u16, 6u16));
loop { loop {
vblank_provider.wait_for_vblank(); vblank_provider.wait_for_vblank();
bg.commit(&mut vram); bg.commit(&mut vram);
@ -96,9 +94,9 @@ fn init_background(bg: &mut RegularMap, vram: &mut VRamManager) {
for x in 0..30u16 { for x in 0..30u16 {
bg.set_tile( bg.set_tile(
vram, vram,
(x, y).into(), (x, y),
&background_tile.tile_set(), &background_tile.tile_set(),
TileSetting::from_raw(background_tile.tile_index()), background_tile.tile_setting(),
); );
} }
} }

View file

@ -3,7 +3,7 @@
use agb::{ use agb::{
display::{ display::{
tiled::{RegularBackgroundSize, TileFormat, TileSetting, TiledMap}, tiled::{RegularBackgroundSize, TileFormat, TiledMap},
Font, Priority, Font, Priority,
}, },
include_font, include_font,
@ -11,7 +11,7 @@ use agb::{
use core::fmt::Write; use core::fmt::Write;
const FONT: Font = include_font!("examples/font/yoster.ttf", 12); static FONT: Font = include_font!("examples/font/ark-pixel-10px-proportional-ja.ttf", 10);
#[agb::entry] #[agb::entry]
fn main(mut gba: agb::Gba) -> ! { fn main(mut gba: agb::Gba) -> ! {
@ -35,30 +35,30 @@ fn main(mut gba: agb::Gba) -> ! {
for x in 0..30u16 { for x in 0..30u16 {
bg.set_tile( bg.set_tile(
&mut vram, &mut vram,
(x, y).into(), (x, y),
&background_tile.tile_set(), &background_tile.tile_set(),
TileSetting::from_raw(background_tile.tile_index()), background_tile.tile_setting(),
); );
} }
} }
vram.remove_dynamic_tile(background_tile); vram.remove_dynamic_tile(background_tile);
let mut renderer = FONT.render_text((0u16, 3u16).into()); let mut renderer = FONT.render_text((0u16, 3u16));
let mut writer = renderer.writer(1, 2, &mut bg, &mut vram); let mut writer = renderer.writer(1, 2, &mut bg, &mut vram);
writeln!(&mut writer, "Hello, World!").unwrap(); writeln!(&mut writer, "Hello, World! こんにちは 世界").unwrap();
writeln!(&mut writer, "This is a font rendering example").unwrap(); writeln!(&mut writer, "This is a font rendering example").unwrap();
writer.commit(); writer.commit();
bg.commit(&mut vram); bg.commit(&mut vram);
bg.show(); bg.set_visible(true);
let mut frame = 0; let mut frame = 0;
loop { loop {
let mut renderer = FONT.render_text((4u16, 0u16).into()); let mut renderer = FONT.render_text((4u16, 0u16));
let mut writer = renderer.writer(1, 2, &mut bg, &mut vram); let mut writer = renderer.writer(1, 2, &mut bg, &mut vram);
writeln!(&mut writer, "Frame {frame}").unwrap(); writeln!(&mut writer, "Frame {frame}").unwrap();

View file

@ -1,5 +0,0 @@
version = "1.0"
[image.water_tiles]
filename = "water_tiles.png"
tile_size = "8x8"

View file

@ -9,9 +9,9 @@ use agb::{
tiled::{RegularBackgroundSize, TileFormat}, tiled::{RegularBackgroundSize, TileFormat},
}, },
fixnum::FixedNum, fixnum::FixedNum,
interrupt::{free, Interrupt}, interrupt::Interrupt,
}; };
use bare_metal::{CriticalSection, Mutex}; use critical_section::{CriticalSection, Mutex};
struct BackCosines { struct BackCosines {
cosines: [u16; 32], cosines: [u16; 32],
@ -37,7 +37,7 @@ fn main(mut gba: agb::Gba) -> ! {
let _a = unsafe { let _a = unsafe {
agb::interrupt::add_interrupt_handler(Interrupt::HBlank, |key: CriticalSection| { agb::interrupt::add_interrupt_handler(Interrupt::HBlank, |key: CriticalSection| {
let mut back = BACK.borrow(key).borrow_mut(); let mut back = BACK.borrow_ref_mut(key);
let deflection = back.cosines[back.row % 32]; let deflection = back.cosines[back.row % 32];
((0x0400_0010) as *mut u16).write_volatile(deflection); ((0x0400_0010) as *mut u16).write_volatile(deflection);
back.row += 1; back.row += 1;
@ -49,8 +49,8 @@ fn main(mut gba: agb::Gba) -> ! {
loop { loop {
vblank.wait_for_vblank(); vblank.wait_for_vblank();
free(|key| { critical_section::with(|key| {
let mut back = BACK.borrow(key).borrow_mut(); let mut back = BACK.borrow_ref_mut(key);
back.row = 0; back.row = 0;
time += 1; time += 1;
for (r, a) in back.cosines.iter_mut().enumerate() { for (r, a) in back.cosines.iter_mut().enumerate() {

94
agb/fnt/OFL.txt Normal file
View file

@ -0,0 +1,94 @@
Copyright (c) 2021, TakWolf (https://takwolf.com),
with Reserved Font Name 'Ark Pixel'.
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

Binary file not shown.

BIN
agb/gfx/test_logo.aseprite Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
agb/gfx/test_logo_basic.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -6,7 +6,6 @@
use core::alloc::{Allocator, GlobalAlloc, Layout}; use core::alloc::{Allocator, GlobalAlloc, Layout};
use core::cell::UnsafeCell; use core::cell::UnsafeCell;
use core::convert::TryInto;
use core::ptr::NonNull; use core::ptr::NonNull;
use super::bump_allocator::{BumpAllocatorInner, StartEnd}; use super::bump_allocator::{BumpAllocatorInner, StartEnd};
@ -72,12 +71,6 @@ impl BlockAllocator {
f(inner) f(inner)
} }
#[doc(hidden)]
#[cfg(any(test, feature = "testing"))]
pub unsafe fn number_of_blocks(&self) -> u32 {
self.with_inner(|inner| inner.number_of_blocks())
}
pub unsafe fn alloc(&self, layout: Layout) -> Option<NonNull<u8>> { pub unsafe fn alloc(&self, layout: Layout) -> Option<NonNull<u8>> {
self.with_inner(|inner| inner.alloc(layout)) self.with_inner(|inner| inner.alloc(layout))
} }
@ -86,12 +79,6 @@ impl BlockAllocator {
self.with_inner(|inner| inner.dealloc(ptr, layout)); self.with_inner(|inner| inner.dealloc(ptr, layout));
} }
pub unsafe fn dealloc_no_normalise(&self, ptr: *mut u8, layout: Layout) {
self.with_inner(|inner| {
inner.dealloc_no_normalise(ptr, layout);
});
}
pub unsafe fn grow( pub unsafe fn grow(
&self, &self,
ptr: *mut u8, ptr: *mut u8,
@ -112,20 +99,6 @@ impl BlockAllocatorInner {
} }
} }
#[doc(hidden)]
#[cfg(any(test, feature = "testing"))]
pub unsafe fn number_of_blocks(&mut self) -> u32 {
let mut count = 0;
let mut list_ptr = &mut self.state.first_free_block;
while let Some(mut current) = list_ptr {
count += 1;
list_ptr = &mut current.as_mut().next;
}
count
}
/// Requests a brand new block from the inner bump allocator /// Requests a brand new block from the inner bump allocator
fn new_block(&mut self, layout: Layout) -> Option<NonNull<u8>> { fn new_block(&mut self, layout: Layout) -> Option<NonNull<u8>> {
let overall_layout = Block::either_layout(layout); let overall_layout = Block::either_layout(layout);
@ -133,29 +106,25 @@ impl BlockAllocatorInner {
} }
/// Merges blocks together to create a normalised list /// Merges blocks together to create a normalised list
unsafe fn normalise(&mut self) { unsafe fn normalise(&mut self, point_to_normalise: *mut Block) {
let mut list_ptr = &mut self.state.first_free_block; unsafe fn normalise_block(block_to_normalise: &mut Block) {
if let Some(next_block) = block_to_normalise.next {
while let Some(mut current) = list_ptr { let difference = next_block
if let Some(next_elem) = current.as_mut().next {
let difference = next_elem
.as_ptr() .as_ptr()
.cast::<u8>() .cast::<u8>()
.offset_from(current.as_ptr().cast::<u8>()); .offset_from((block_to_normalise as *mut Block).cast::<u8>());
let usize_difference: usize = difference if difference == block_to_normalise.size as isize {
.try_into() let next = next_block.as_ref();
.expect("distances in alloc'd blocks must be positive"); block_to_normalise.next = next.next;
block_to_normalise.size += next.size;
if usize_difference == current.as_mut().size { normalise_block(block_to_normalise);
let current = current.as_mut();
let next = next_elem.as_ref();
current.size += next.size;
current.next = next.next;
continue;
} }
} }
list_ptr = &mut current.as_mut().next; }
normalise_block(&mut *point_to_normalise);
if let Some(mut next_block) = (*point_to_normalise).next {
normalise_block(next_block.as_mut());
} }
} }
@ -279,8 +248,10 @@ impl BlockAllocatorInner {
} }
pub unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) { pub unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
self.dealloc_no_normalise(ptr, layout); let point_to_normalise = self.dealloc_no_normalise(ptr, layout);
self.normalise(); if let Some(block_to_normalise) = *point_to_normalise {
self.normalise(block_to_normalise.as_ptr());
}
} }
/// Returns a reference to the pointer to the next block /// Returns a reference to the pointer to the next block
@ -305,11 +276,16 @@ impl BlockAllocatorInner {
} }
} }
pub unsafe fn dealloc_no_normalise(&mut self, ptr: *mut u8, layout: Layout) { pub unsafe fn dealloc_no_normalise(
&mut self,
ptr: *mut u8,
layout: Layout,
) -> *mut Option<SendNonNull<Block>> {
let new_layout = Block::either_layout(layout).pad_to_align(); let new_layout = Block::either_layout(layout).pad_to_align();
// note that this is a reference to a pointer // note that this is a reference to a pointer
let mut list_ptr = &mut self.state.first_free_block; let mut list_ptr = &mut self.state.first_free_block;
let mut list_ptr_prev: *mut Option<SendNonNull<Block>> = list_ptr;
// This searches the free list until it finds a block further along // This searches the free list until it finds a block further along
// than the block that is being freed. The newly freed block is then // than the block that is being freed. The newly freed block is then
@ -327,6 +303,7 @@ impl BlockAllocatorInner {
*list_ptr = NonNull::new(ptr.cast()).map(SendNonNull); *list_ptr = NonNull::new(ptr.cast()).map(SendNonNull);
break; break;
} }
list_ptr_prev = list_ptr;
list_ptr = &mut current_block.as_mut().next; list_ptr = &mut current_block.as_mut().next;
} }
None => { None => {
@ -341,6 +318,8 @@ impl BlockAllocatorInner {
} }
} }
} }
list_ptr_prev
} }
} }

View file

@ -1,10 +1,7 @@
use core::alloc::{GlobalAlloc, Layout}; use core::alloc::Layout;
use core::cell::RefCell;
use core::ptr::NonNull; use core::ptr::NonNull;
use super::SendNonNull; use super::SendNonNull;
use crate::interrupt::free;
use bare_metal::Mutex;
pub(crate) struct StartEnd { pub(crate) struct StartEnd {
pub start: fn() -> usize, pub start: fn() -> usize,
@ -16,10 +13,6 @@ pub(crate) struct BumpAllocatorInner {
start_end: StartEnd, start_end: StartEnd,
} }
pub(crate) struct BumpAllocator {
inner: Mutex<RefCell<BumpAllocatorInner>>,
}
impl BumpAllocatorInner { impl BumpAllocatorInner {
pub const fn new(start_end: StartEnd) -> Self { pub const fn new(start_end: StartEnd) -> Self {
Self { Self {
@ -58,20 +51,3 @@ impl BumpAllocatorInner {
NonNull::new(resulting_ptr as *mut _) NonNull::new(resulting_ptr as *mut _)
} }
} }
impl BumpAllocator {
fn alloc_safe(&self, layout: Layout) -> Option<NonNull<u8>> {
free(|key| self.inner.borrow(key).borrow_mut().alloc(layout))
}
}
unsafe impl GlobalAlloc for BumpAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
match self.alloc_safe(layout) {
None => core::ptr::null_mut(),
Some(p) => p.as_ptr(),
}
}
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
}

View file

@ -1,4 +1,3 @@
use core::alloc::{Allocator, Layout};
use core::ops::{Deref, DerefMut}; use core::ops::{Deref, DerefMut};
use core::ptr::NonNull; use core::ptr::NonNull;
@ -14,7 +13,7 @@ unsafe impl<T> Send for SendNonNull<T> {}
impl<T> Clone for SendNonNull<T> { impl<T> Clone for SendNonNull<T> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
SendNonNull(self.0) *self
} }
} }
impl<T> Copy for SendNonNull<T> {} impl<T> Copy for SendNonNull<T> {}
@ -45,21 +44,27 @@ static GLOBAL_ALLOC: BlockAllocator = unsafe {
macro_rules! impl_zst_allocator { macro_rules! impl_zst_allocator {
($name_of_struct: ty, $name_of_static: ident) => { ($name_of_struct: ty, $name_of_static: ident) => {
unsafe impl Allocator for $name_of_struct { unsafe impl core::alloc::Allocator for $name_of_struct {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, core::alloc::AllocError> { fn allocate(
&self,
layout: core::alloc::Layout,
) -> Result<core::ptr::NonNull<[u8]>, core::alloc::AllocError> {
$name_of_static.allocate(layout) $name_of_static.allocate(layout)
} }
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) { unsafe fn deallocate(&self, ptr: core::ptr::NonNull<u8>, layout: core::alloc::Layout) {
$name_of_static.deallocate(ptr, layout) $name_of_static.deallocate(ptr, layout)
} }
} }
}; };
} }
/// This is the allocator for the External Working Ram. This is currently pub(crate) use impl_zst_allocator;
/// equivalent to the Global Allocator (where things are allocated if no allocator is provided). This implements the allocator trait, so
/// is meant to be used in specifying where certain structures should be /// This is the allocator for the External Working Ram.
///
/// This is currently equivalent to the Global Allocator (where things are allocated if no allocator is provided).
/// This implements the allocator trait, so is meant to be used in specifying where certain structures should be
/// allocated. /// allocated.
/// ///
/// ```rust,no_run /// ```rust,no_run
@ -115,29 +120,24 @@ static __IWRAM_ALLOC: BlockAllocator = unsafe {
}) })
}; };
#[cfg(any(test, feature = "testing"))]
pub(crate) unsafe fn number_of_blocks() -> u32 {
GLOBAL_ALLOC.number_of_blocks()
}
fn iwram_data_end() -> usize { fn iwram_data_end() -> usize {
extern "C" { extern "C" {
static __iwram_end: usize; static __iwram_end: u8;
} }
// TODO: This seems completely wrong, but without the &, rust generates // Symbols defined in the linker have an address *but no data or value*.
// a double dereference :/. Maybe a bug in nightly? // As strange as this looks, they are only useful to take the address of.
(unsafe { &__iwram_end }) as *const _ as usize core::ptr::addr_of!(__iwram_end) as usize
} }
fn data_end() -> usize { fn data_end() -> usize {
extern "C" { extern "C" {
static __ewram_data_end: usize; static __ewram_data_end: u8;
} }
// TODO: This seems completely wrong, but without the &, rust generates // Symbols defined in the linker have an address *but no data or value*.
// a double dereference :/. Maybe a bug in nightly? // As strange as this looks, they are only useful to take the address of.
(unsafe { &__ewram_data_end }) as *const _ as usize core::ptr::addr_of!(__ewram_data_end) as usize
} }
#[cfg(test)] #[cfg(test)]

View file

@ -11,8 +11,6 @@
=============================================================================== ===============================================================================
*/ */
.include "src/agbabi/macros.inc"
.arm .arm
.section .iwram.__aeabi_memcpy, "ax", %progbits .section .iwram.__aeabi_memcpy, "ax", %progbits
@ -32,14 +30,14 @@ __aeabi_memcpy:
joaobapt_test r3 joaobapt_test r3
// Copy byte head to align // Copy byte head to align
ldrmib r3, [r1], #1 ldrbmi r3, [r1], #1
strmib r3, [r0], #1 strbmi r3, [r0], #1
submi r2, r2, #1 submi r2, r2, #1
// r0, r1 are now half aligned // r0, r1 are now half aligned
// Copy half head to align // Copy half head to align
ldrcsh r3, [r1], #2 ldrhcs r3, [r1], #2
strcsh r3, [r0], #2 strhcs r3, [r0], #2
subcs r2, r2, #2 subcs r2, r2, #2
// r0, r1 are now word aligned // r0, r1 are now word aligned
@ -51,13 +49,13 @@ __aeabi_memcpy4:
blt .Lcopy_words blt .Lcopy_words
// Word aligned, 32-byte copy // Word aligned, 32-byte copy
push {r4-r10} push {{r4-r10}}
.Lloop_32: .Lloop_32:
subs r2, r2, #32 subs r2, r2, #32
ldmgeia r1!, {r3-r10} ldmiage r1!, {{r3-r10}}
stmgeia r0!, {r3-r10} stmiage r0!, {{r3-r10}}
bgt .Lloop_32 bgt .Lloop_32
pop {r4-r10} pop {{r4-r10}}
bxeq lr bxeq lr
// < 32 bytes remaining to be copied // < 32 bytes remaining to be copied
@ -77,40 +75,40 @@ __aeabi_memcpy4:
// This test still works when r2 is negative // This test still works when r2 is negative
joaobapt_test r2 joaobapt_test r2
// Copy half // Copy half
ldrcsh r3, [r1], #2 ldrhcs r3, [r1], #2
strcsh r3, [r0], #2 strhcs r3, [r0], #2
// Copy byte // Copy byte
ldrmib r3, [r1] ldrbmi r3, [r1]
strmib r3, [r0] strbmi r3, [r0]
bx lr bx lr
.Lcopy_halves: .Lcopy_halves:
// Copy byte head to align // Copy byte head to align
tst r0, #1 tst r0, #1
ldrneb r3, [r1], #1 ldrbne r3, [r1], #1
strneb r3, [r0], #1 strbne r3, [r0], #1
subne r2, r2, #1 subne r2, r2, #1
// r0, r1 are now half aligned // r0, r1 are now half aligned
.global __agbabi_memcpy2 .global __agbabi_memcpy2
__agbabi_memcpy2: __agbabi_memcpy2:
subs r2, r2, #2 subs r2, r2, #2
ldrgeh r3, [r1], #2 ldrhge r3, [r1], #2
strgeh r3, [r0], #2 strhge r3, [r0], #2
bgt __agbabi_memcpy2 bgt __agbabi_memcpy2
bxeq lr bxeq lr
// Copy byte tail // Copy byte tail
adds r2, r2, #1 adds r2, r2, #1
ldreqb r3, [r1] ldrbeq r3, [r1]
streqb r3, [r0] strbeq r3, [r0]
bx lr bx lr
.global __agbabi_memcpy1 .global __agbabi_memcpy1
__agbabi_memcpy1: __agbabi_memcpy1:
subs r2, r2, #1 subs r2, r2, #1
ldrgeb r3, [r1], #1 ldrbge r3, [r1], #1
strgeb r3, [r0], #1 strbge r3, [r0], #1
bgt __agbabi_memcpy1 bgt __agbabi_memcpy1
bx lr bx lr
@ -118,7 +116,7 @@ __agbabi_memcpy1:
.align 2 .align 2
.global memcpy .global memcpy
memcpy: memcpy:
push {r0, lr} push {{r0, lr}}
bl __aeabi_memcpy bl __aeabi_memcpy
pop {r0, lr} pop {{r0, lr}}
bx lr bx lr

View file

@ -40,9 +40,9 @@ __aeabi_memset:
// JoaoBapt carry & sign bit test // JoaoBapt carry & sign bit test
movs r1, r1, lsl #31 movs r1, r1, lsl #31
// Set byte and half // Set byte and half
strmib r2, [r0], #1 strbmi r2, [r0], #1
strcsb r2, [r0], #1 strbcs r2, [r0], #1
strcsb r2, [r0] strbcs r2, [r0]
bx lr bx lr
.LskipShortHead: .LskipShortHead:
@ -50,9 +50,9 @@ __aeabi_memset:
// JoaoBapt carry & sign bit test // JoaoBapt carry & sign bit test
movs r3, r3, lsl #31 movs r3, r3, lsl #31
// Set half and byte head // Set half and byte head
strmib r2, [r0], #1 strbmi r2, [r0], #1
submi r1, r1, #1 submi r1, r1, #1
strcsh r2, [r0], #2 strhcs r2, [r0], #2
subcs r1, r1, #2 subcs r1, r1, #2
b __agbabi_wordset4 b __agbabi_wordset4
@ -79,7 +79,7 @@ __agbabi_wordset4:
beq .Lskip32 beq .Lskip32
lsl r3, r12, #5 lsl r3, r12, #5
sub r1, r1, r3 sub r1, r1, r3
push {r4-r9} push {{r4-r9}}
mov r3, r2 mov r3, r2
mov r4, r2 mov r4, r2
mov r5, r2 mov r5, r2
@ -88,10 +88,10 @@ __agbabi_wordset4:
mov r8, r2 mov r8, r2
mov r9, r2 mov r9, r2
.LsetWords8: .LsetWords8:
stmia r0!, {r2-r9} stmia r0!, {{r2-r9}}
subs r12, r12, #1 subs r12, r12, #1
bne .LsetWords8 bne .LsetWords8
pop {r4-r9} pop {{r4-r9}}
.Lskip32: .Lskip32:
// Set words // Set words
@ -104,8 +104,8 @@ __agbabi_wordset4:
// Set half and byte tail // Set half and byte tail
// JoaoBapt carry & sign bit test // JoaoBapt carry & sign bit test
movs r3, r1, lsl #31 movs r3, r1, lsl #31
strcsh r2, [r0], #2 strhcs r2, [r0], #2
strmib r2, [r0] strbmi r2, [r0]
bx lr bx lr
.section .iwram.memset, "ax", %progbits .section .iwram.memset, "ax", %progbits
@ -115,7 +115,7 @@ memset:
mov r3, r1 mov r3, r1
mov r1, r2 mov r1, r2
mov r2, r3 mov r2, r3
push {r0, lr} push {{r0, lr}}
bl __aeabi_memset bl __aeabi_memset
pop {r0, lr} pop {{r0, lr}}
bx lr bx lr

View file

@ -1,3 +1,9 @@
use core::arch::global_asm;
global_asm!(include_str!("macros.inc"));
global_asm!(include_str!("memcpy.s"));
global_asm!(include_str!("memset.s"));
#[cfg(test)] #[cfg(test)]
mod test { mod test {
mod memset { mod memset {
@ -148,7 +154,7 @@ mod test {
#[test_case] #[test_case]
fn test_all_of_memcpy(_gba: &mut Gba) { fn test_all_of_memcpy(_gba: &mut Gba) {
let mut input = vec![0u8; 100]; let mut input = [0u8; 100];
let mut output = vec![0u8; 100]; let mut output = vec![0u8; 100];
for size in 0..80 { for size in 0..80 {

View file

@ -4,14 +4,14 @@
.align 2 .align 2
.global \functionName .global \functionName
.type \functionName, %function .type \functionName, %function
.func \functionName @ .func \functionName
\functionName: \functionName:
.endm .endm
.macro agb_arm_end functionName:req .macro agb_arm_end functionName:req
.pool .pool
.size \functionName,.-\functionName .size \functionName,.-\functionName
.endfunc @ .endfunc
.endm .endm
.macro agb_thumb_func functionName:req .macro agb_thumb_func functionName:req
@ -20,12 +20,12 @@
.align 1 .align 1
.global \functionName .global \functionName
.type \functionName, %function .type \functionName, %function
.func \functionName @ .func \functionName
\functionName: \functionName:
.endm .endm
.macro agb_thumb_end functionName:req .macro agb_thumb_end functionName:req
.pool .pool
.size \functionName,.-\functionName .size \functionName,.-\functionName
.endfunc @ .endfunc
.endm .endm

137
agb/src/backtrace.rs Normal file
View file

@ -0,0 +1,137 @@
use core::{arch::asm, ops::Index};
use alloc::vec::Vec;
// only works for code compiled as THUMB
#[repr(C)]
#[derive(Clone, Default, Debug)]
struct Context {
registers: [u32; 11],
}
pub struct Frames {
frames: Vec<u32>,
}
#[allow(unused)]
enum Register {
R0,
R1,
R2,
R3,
R4,
R5,
R6,
FP,
SP,
LR,
PC,
}
impl Index<Register> for Context {
type Output = u32;
fn index(&self, index: Register) -> &Self::Output {
&self.registers[index as usize]
}
}
#[inline(never)]
pub(crate) fn unwind_exception() -> Frames {
let mut context = Context::default();
unsafe {
let context_ptr = (&mut context) as *mut _;
asm!(
"
str r0, [r0, #0x00]
str r1, [r0, #0x04]
str r2, [r0, #0x08]
str r3, [r0, #0x0C]
str r4, [r0, #0x10]
str r5, [r0, #0x14]
str r6, [r0, #0x18]
str r7, [r0, #0x1C]
mov r7, sp
str r7, [r0, #0x20]
mov r7, lr
str r7, [r0, #0x24]
mov r7, pc
str r7, [r0, #0x28]
ldr r7, [r0, #0x1C]
",
in("r0") context_ptr
);
}
let mut frame_pointer = context[Register::FP];
let mut frames = Vec::new();
loop {
let sp = unsafe { *(frame_pointer as *const u32) };
let lr = unsafe { *((frame_pointer as *const u32).add(1)) };
if sp == 0 {
break;
}
// need to subtract 2 here since the link register points to the _next_ instruction
// to execute, not the one that is being branched from which is the one we care about
// in the stack trace.
frames.push(lr - 2);
frame_pointer = sp;
}
Frames { frames }
}
impl core::fmt::Display for Frames {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
for frame in &self.frames {
if frame & 0xFFFF_0000 == 0x0800_0000 {
let frame = *frame as u16; // intentionally truncate
let frame_encoded = gwilym_encoding::encode_16(frame);
let frame_str = unsafe { core::str::from_utf8_unchecked(&frame_encoded) };
write!(f, "{frame_str}")?;
} else {
let frame_encoded = gwilym_encoding::encode_32(*frame);
let frame_str = unsafe { core::str::from_utf8_unchecked(&frame_encoded) };
write!(f, "{frame_str}")?;
}
}
write!(f, "v1")
}
}
mod gwilym_encoding {
static ALPHABET: &[u8] = b"0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";
pub fn encode_16(input: u16) -> [u8; 3] {
let input = input as usize;
[
ALPHABET[input >> (16 - 5)],
ALPHABET[(input >> (16 - 10)) & 0b11111],
ALPHABET[input & 0b111111],
]
}
pub fn encode_32(input: u32) -> [u8; 6] {
let input = input as usize;
let output_lower_16 = encode_16(input as u16);
let input_upper_16 = input >> 16;
[
ALPHABET[(input_upper_16 >> (16 - 5)) | (1 << 5)],
ALPHABET[(input_upper_16 >> (16 - 10)) & 0b11111],
ALPHABET[input_upper_16 & 0b111111],
output_lower_16[0],
output_lower_16[1],
output_lower_16[2],
]
}
}

View file

@ -81,10 +81,7 @@
//! # } //! # }
//! ``` //! ```
use core::{ use core::ops::{Mul, MulAssign};
convert::TryFrom,
ops::{Mul, MulAssign},
};
use agb_fixnum::{Num, Vector2D}; use agb_fixnum::{Num, Vector2D};
@ -93,13 +90,20 @@ type AffineMatrixElement = Num<i32, 8>;
#[derive(Debug, PartialEq, Eq, Clone, Copy)] #[derive(Debug, PartialEq, Eq, Clone, Copy)]
/// An affine matrix stored in a way that is efficient for the GBA to perform /// An affine matrix stored in a way that is efficient for the GBA to perform
/// operations on. This implements multiplication. /// operations on. This implements multiplication.
///
/// ```txt
/// a b x
/// c d y
/// 0 0 0
/// ```
#[allow(missing_docs)]
pub struct AffineMatrix { pub struct AffineMatrix {
a: AffineMatrixElement, pub a: AffineMatrixElement,
b: AffineMatrixElement, pub b: AffineMatrixElement,
c: AffineMatrixElement, pub c: AffineMatrixElement,
d: AffineMatrixElement, pub d: AffineMatrixElement,
x: AffineMatrixElement, pub x: AffineMatrixElement,
y: AffineMatrixElement, pub y: AffineMatrixElement,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
@ -298,15 +302,15 @@ impl AffineMatrixBackground {
/// # } /// # }
/// ``` /// ```
pub fn from_scale_rotation_position( pub fn from_scale_rotation_position(
transform_origin: Vector2D<Num<i32, 8>>, transform_origin: impl Into<Vector2D<Num<i32, 8>>>,
scale: Vector2D<Num<i32, 8>>, scale: impl Into<Vector2D<Num<i32, 8>>>,
rotation: Num<i32, 16>, rotation: Num<i32, 16>,
position: Vector2D<Num<i32, 8>>, position: impl Into<Vector2D<i16>>,
) -> Self { ) -> Self {
crate::syscall::bg_affine_matrix( crate::syscall::bg_affine_matrix(
transform_origin, transform_origin.into(),
position.try_change_base::<i16, 8>().unwrap().floor(), position.into(),
scale.try_change_base().unwrap(), scale.into().try_change_base().unwrap(),
rotation.rem_euclid(1.into()).try_change_base().unwrap(), rotation.rem_euclid(1.into()).try_change_base().unwrap(),
) )
} }
@ -321,11 +325,17 @@ impl From<AffineMatrixBackground> for AffineMatrix {
#[derive(Debug, PartialEq, Eq, Clone, Copy)] #[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[repr(C, packed(4))] #[repr(C, packed(4))]
/// An affine matrix that can be used in affine objects /// An affine matrix that can be used in affine objects
///
/// ```txt
/// a b
/// c d
/// ```
#[allow(missing_docs)]
pub struct AffineMatrixObject { pub struct AffineMatrixObject {
a: Num<i16, 8>, pub a: Num<i16, 8>,
b: Num<i16, 8>, pub b: Num<i16, 8>,
c: Num<i16, 8>, pub c: Num<i16, 8>,
d: Num<i16, 8>, pub d: Num<i16, 8>,
} }
impl Default for AffineMatrixObject { impl Default for AffineMatrixObject {

View file

@ -4,7 +4,7 @@ use super::{
set_graphics_mode, set_graphics_settings, DisplayMode, GraphicsSettings, HEIGHT, WIDTH, set_graphics_mode, set_graphics_settings, DisplayMode, GraphicsSettings, HEIGHT, WIDTH,
}; };
use core::{convert::TryInto, marker::PhantomData}; use core::marker::PhantomData;
const BITMAP_MODE_3: MemoryMapped2DArray<u16, { WIDTH as usize }, { HEIGHT as usize }> = const BITMAP_MODE_3: MemoryMapped2DArray<u16, { WIDTH as usize }, { HEIGHT as usize }> =
unsafe { MemoryMapped2DArray::new(0x600_0000) }; unsafe { MemoryMapped2DArray::new(0x600_0000) };
@ -30,4 +30,19 @@ impl Bitmap3<'_> {
let y = y.try_into().unwrap(); let y = y.try_into().unwrap();
BITMAP_MODE_3.set(x, y, colour); BITMAP_MODE_3.set(x, y, colour);
} }
#[must_use]
pub fn read_point(&self, x: i32, y: i32) -> u16 {
let x = x.try_into().unwrap();
let y = y.try_into().unwrap();
BITMAP_MODE_3.get(x, y)
}
pub fn clear(&mut self, colour: u16) {
for y in 0..(HEIGHT as usize) {
for x in 0..(WIDTH as usize) {
BITMAP_MODE_3.set(x, y, colour);
}
}
}
} }

View file

@ -54,9 +54,9 @@ impl Bitmap4<'_> {
let c = addr.get(x_in_screen, y_in_screen); let c = addr.get(x_in_screen, y_in_screen);
if x & 0b1 != 0 { if x & 0b1 != 0 {
addr.set(x_in_screen, y_in_screen, c | u16::from(colour) << 8); addr.set(x_in_screen, y_in_screen, c & 0xff | u16::from(colour) << 8);
} else { } else {
addr.set(x_in_screen, y_in_screen, c | u16::from(colour)); addr.set(x_in_screen, y_in_screen, c & 0xff00 | u16::from(colour));
} }
} }
@ -88,4 +88,64 @@ impl Bitmap4<'_> {
let swapped = display ^ GraphicsSettings::PAGE_SELECT.bits(); let swapped = display ^ GraphicsSettings::PAGE_SELECT.bits();
DISPLAY_CONTROL.set(swapped); DISPLAY_CONTROL.set(swapped);
} }
/// Draws 2-pixel wide point on the non-current page at (x, y) coordinates with colour
/// index whose colour is specified in the background palette. Panics if (x,
/// y) is out of the bounds of the screen.
pub fn draw_wide_point(&mut self, x: i32, y: i32, colour: u8) {
let display = DISPLAY_CONTROL.get();
// get other page
let page = if display & GraphicsSettings::PAGE_SELECT.bits() != 0 {
Page::Front
} else {
Page::Back
};
self.draw_wide_point_page(x, y, colour, page);
}
/// Draws 2-pixel wide point on specified page at (x, y) coordinates with colour index
/// whose colour is specified in the background palette. Panics if (x, y) is
/// out of the bounds of the screen.
pub fn draw_wide_point_page(&mut self, x: i32, y: i32, colour: u8, page: Page) {
let addr = match page {
Page::Front => BITMAP_PAGE_FRONT_MODE_4,
Page::Back => BITMAP_PAGE_BACK_MODE_4,
};
let x_in_screen = (x / 2) as usize;
let y_in_screen = y as usize;
let c = u16::from(colour);
addr.set(x_in_screen, y_in_screen, c << 8 | c);
}
/// Fills specified page with color.
pub fn clear_page(&mut self, colour: u8, page: Page) {
let addr = match page {
Page::Front => BITMAP_PAGE_FRONT_MODE_4,
Page::Back => BITMAP_PAGE_BACK_MODE_4,
};
let c = u16::from(colour);
for x in 0..(WIDTH / 2) as usize {
for y in 0..(HEIGHT as usize) {
addr.set(x, y, c << 8 | c);
}
}
}
/// Fills non-current page with color.
pub fn clear(&mut self, colour: u8) {
let display = DISPLAY_CONTROL.get();
// get other page
let page = if display & GraphicsSettings::PAGE_SELECT.bits() != 0 {
Page::Front
} else {
Page::Back
};
self.clear_page(colour, page);
}
} }

View file

@ -60,7 +60,7 @@ pub struct BlendLayer<'blend, 'gba> {
layer: Layer, layer: Layer,
} }
impl<'gba> BlendLayer<'_, 'gba> { impl BlendLayer<'_, '_> {
/// Set whether a background is enabled for blending on this layer. /// Set whether a background is enabled for blending on this layer.
pub fn set_background_enable(&mut self, background: BackgroundID, enable: bool) -> &mut Self { pub fn set_background_enable(&mut self, background: BackgroundID, enable: bool) -> &mut Self {
self.blend self.blend

View file

@ -1,25 +1,24 @@
use super::tiled::{RegularMap, TileFormat, TileSet, TileSetting, TiledMap, VRamManager}; use super::tiled::{RegularMap, TiledMap, VRamManager};
crate::include_background_gfx!(crate, agb_logo, test_logo => "gfx/test_logo.png"); crate::include_background_gfx!(crate, agb_logo, test_logo => deduplicate "gfx/test_logo.png");
crate::include_background_gfx!(crate, agb_logo_basic, test_logo => deduplicate "gfx/test_logo_basic.png");
pub fn display_logo(map: &mut RegularMap, vram: &mut VRamManager) { pub fn display_logo(map: &mut RegularMap, vram: &mut VRamManager) {
vram.set_background_palettes(agb_logo::PALETTES); vram.set_background_palettes(agb_logo::PALETTES);
let background_tilemap = TileSet::new(agb_logo::test_logo.tiles, TileFormat::FourBpp); map.fill_with(vram, &agb_logo::test_logo);
for y in 0..20 {
for x in 0..30 {
let tile_id = y * 30 + x;
let palette_entry = agb_logo::test_logo.palette_assignments[tile_id as usize];
let tile_setting = TileSetting::new(tile_id, false, false, palette_entry);
map.set_tile(vram, (x, y).into(), &background_tilemap, tile_setting);
}
}
map.commit(vram); map.commit(vram);
map.show(); map.set_visible(true);
}
pub fn display_logo_basic(map: &mut RegularMap, vram: &mut VRamManager) {
vram.set_background_palettes(agb_logo_basic::PALETTES);
map.fill_with(vram, &agb_logo_basic::test_logo);
map.commit(vram);
map.set_visible(true);
} }
#[cfg(test)] #[cfg(test)]
@ -35,7 +34,7 @@ mod tests {
let mut map = gfx.background( let mut map = gfx.background(
Priority::P0, Priority::P0,
RegularBackgroundSize::Background32x32, RegularBackgroundSize::Background32x32,
TileFormat::FourBpp, agb_logo::test_logo.tiles.format(),
); );
display_logo(&mut map, &mut vram); display_logo(&mut map, &mut vram);

View file

@ -3,38 +3,63 @@ use core::fmt::{Error, Write};
use crate::fixnum::Vector2D; use crate::fixnum::Vector2D;
use crate::hash_map::HashMap; use crate::hash_map::HashMap;
use super::tiled::{DynamicTile, RegularMap, TileSetting, VRamManager}; use super::tiled::{DynamicTile, RegularMap, VRamManager};
/// The text renderer renders a variable width fixed size /// The text renderer renders a variable width fixed size
/// bitmap font using dynamic tiles as a rendering surface. /// bitmap font using dynamic tiles as a rendering surface.
/// Does not support any unicode features. /// Does not support any unicode features.
/// For usage see the `text_render.rs` example /// For usage see the `text_render.rs` example
pub struct FontLetter { pub struct FontLetter {
width: u8, pub(crate) character: char,
height: u8, pub(crate) width: u8,
data: &'static [u8], pub(crate) height: u8,
xmin: i8, pub(crate) data: &'static [u8],
ymin: i8, pub(crate) xmin: i8,
advance_width: u8, pub(crate) ymin: i8,
pub(crate) advance_width: u8,
kerning_amounts: &'static [(char, i8)],
} }
impl FontLetter { impl FontLetter {
#[must_use] #[must_use]
#[allow(clippy::too_many_arguments)] // only used in macro
pub const fn new( pub const fn new(
character: char,
width: u8, width: u8,
height: u8, height: u8,
data: &'static [u8], data: &'static [u8],
xmin: i8, xmin: i8,
ymin: i8, ymin: i8,
advance_width: u8, advance_width: u8,
kerning_amounts: &'static [(char, i8)],
) -> Self { ) -> Self {
Self { Self {
character,
width, width,
height, height,
data, data,
xmin, xmin,
ymin, ymin,
advance_width, advance_width,
kerning_amounts,
}
}
pub(crate) const fn bit_absolute(&self, x: usize, y: usize) -> bool {
let position = x + y * self.width as usize;
let byte = self.data[position / 8];
let bit = position % 8;
((byte >> bit) & 1) != 0
}
pub(crate) fn kerning_amount(&self, previous_char: char) -> i32 {
if let Ok(index) = self
.kerning_amounts
.binary_search_by_key(&previous_char, |kerning_data| kerning_data.0)
{
self.kerning_amounts[index].1 as i32
} else {
0
} }
} }
} }
@ -55,20 +80,36 @@ impl Font {
} }
} }
fn letter(&self, letter: char) -> &'static FontLetter { pub(crate) fn letter(&self, letter: char) -> &'static FontLetter {
&self.letters[letter as usize] let letter = self
.letters
.binary_search_by_key(&letter, |letter| letter.character);
match letter {
Ok(index) => &self.letters[index],
Err(_) => &self.letters[0],
}
}
pub(crate) fn ascent(&self) -> i32 {
self.ascent
}
pub(crate) fn line_height(&self) -> i32 {
self.line_height
} }
} }
impl Font { impl Font {
#[must_use] #[must_use]
/// Create renderer starting at the given tile co-ordinates. /// Create renderer starting at the given tile co-ordinates.
pub fn render_text(&self, tile_pos: Vector2D<u16>) -> TextRenderer<'_> { pub fn render_text(&self, tile_pos: impl Into<Vector2D<u16>>) -> TextRenderer<'_> {
TextRenderer { TextRenderer {
current_x_pos: 0, current_x_pos: 0,
current_y_pos: 0, current_y_pos: 0,
previous_character: None,
font: self, font: self,
tile_pos, tile_pos: tile_pos.into(),
tiles: Default::default(), tiles: Default::default(),
} }
} }
@ -78,6 +119,7 @@ impl Font {
pub struct TextRenderer<'a> { pub struct TextRenderer<'a> {
current_x_pos: i32, current_x_pos: i32,
current_y_pos: i32, current_y_pos: i32,
previous_character: Option<char>,
font: &'a Font, font: &'a Font,
tile_pos: Vector2D<u16>, tile_pos: Vector2D<u16>,
tiles: HashMap<(i32, i32), DynamicTile<'a>>, tiles: HashMap<(i32, i32), DynamicTile<'a>>,
@ -93,7 +135,7 @@ pub struct TextWriter<'a, 'b> {
bg: &'a mut RegularMap, bg: &'a mut RegularMap,
} }
impl<'a, 'b> Write for TextWriter<'a, 'b> { impl Write for TextWriter<'_, '_> {
fn write_str(&mut self, text: &str) -> Result<(), Error> { fn write_str(&mut self, text: &str) -> Result<(), Error> {
for c in text.chars() { for c in text.chars() {
self.text_renderer.write_char( self.text_renderer.write_char(
@ -108,7 +150,7 @@ impl<'a, 'b> Write for TextWriter<'a, 'b> {
} }
} }
impl<'a, 'b> TextWriter<'a, 'b> { impl TextWriter<'_, '_> {
pub fn commit(self) { pub fn commit(self) {
self.text_renderer.commit(self.bg, self.vram_manager); self.text_renderer.commit(self.bg, self.vram_manager);
} }
@ -213,9 +255,9 @@ impl<'a, 'b> TextRenderer<'b> {
for ((x, y), tile) in self.tiles.iter() { for ((x, y), tile) in self.tiles.iter() {
bg.set_tile( bg.set_tile(
vram_manager, vram_manager,
(self.tile_pos.x + *x as u16, self.tile_pos.y + *y as u16).into(), (self.tile_pos.x + *x as u16, self.tile_pos.y + *y as u16),
&tile.tile_set(), &tile.tile_set(),
TileSetting::from_raw(tile.tile_index()), tile.tile_setting(),
); );
} }
} }
@ -233,6 +275,12 @@ impl<'a, 'b> TextRenderer<'b> {
self.current_x_pos = 0; self.current_x_pos = 0;
} else { } else {
let letter = self.font.letter(c); let letter = self.font.letter(c);
if let Some(previous_character) = self.previous_character {
self.current_x_pos += letter.kerning_amount(previous_character);
}
self.previous_character = Some(c);
self.render_letter(letter, vram_manager, foreground_colour, background_colour); self.render_letter(letter, vram_manager, foreground_colour, background_colour);
self.current_x_pos += i32::from(letter.advance_width); self.current_x_pos += i32::from(letter.advance_width);
} }
@ -254,7 +302,7 @@ impl<'a, 'b> TextRenderer<'b> {
mod tests { mod tests {
use super::*; use super::*;
use crate::display::tiled::{TileFormat, TiledMap}; use crate::display::tiled::{TileFormat, TiledMap};
const FONT: Font = crate::include_font!("examples/font/yoster.ttf", 12); static FONT: Font = crate::include_font!("examples/font/yoster.ttf", 12);
#[test_case] #[test_case]
fn font_display(gba: &mut crate::Gba) { fn font_display(gba: &mut crate::Gba) {
@ -277,16 +325,16 @@ mod tests {
for x in 0..30u16 { for x in 0..30u16 {
bg.set_tile( bg.set_tile(
&mut vram, &mut vram,
(x, y).into(), (x, y),
&background_tile.tile_set(), &background_tile.tile_set(),
TileSetting::from_raw(background_tile.tile_index()), background_tile.tile_setting(),
); );
} }
} }
vram.remove_dynamic_tile(background_tile); vram.remove_dynamic_tile(background_tile);
let mut renderer = FONT.render_text((0u16, 3u16).into()); let mut renderer = FONT.render_text((0u16, 3u16));
// Test twice to ensure that clearing works // Test twice to ensure that clearing works
for _ in 0..2 { for _ in 0..2 {
@ -299,14 +347,14 @@ mod tests {
writeln!(&mut writer, "World!").unwrap(); writeln!(&mut writer, "World!").unwrap();
writer.commit(); writer.commit();
bg.commit(&mut vram); bg.commit(&mut vram);
bg.show(); bg.set_visible(true);
// Test writing with same renderer after showing background // Test writing with same renderer after showing background
let mut writer = renderer.writer(1, 2, &mut bg, &mut vram); let mut writer = renderer.writer(1, 2, &mut bg, &mut vram);
writeln!(&mut writer, "This is a font rendering example").unwrap(); writeln!(&mut writer, "This is a font rendering example").unwrap();
writer.commit(); writer.commit();
bg.commit(&mut vram); bg.commit(&mut vram);
bg.show(); bg.set_visible(true);
crate::test_runner::assert_image_output("examples/font/font-test-output.png"); crate::test_runner::assert_image_output("examples/font/font-test-output.png");
renderer.clear(&mut vram); renderer.clear(&mut vram);

View file

@ -1,7 +1,8 @@
use crate::memory_mapped::MemoryMapped; use crate::memory_mapped::MemoryMapped;
use bilge::prelude::*;
use bitflags::bitflags; use bitflags::bitflags;
use modular_bitfield::BitfieldSpecifier;
use video::Video; use video::Video;
use self::{ use self::{
@ -150,7 +151,6 @@ unsafe fn set_graphics_settings(settings: GraphicsSettings) {
DISPLAY_CONTROL.set(s); DISPLAY_CONTROL.set(s);
} }
#[allow(non_snake_case)]
/// Waits until vblank using a busy wait loop, this should almost never be used. /// Waits until vblank using a busy wait loop, this should almost never be used.
/// I only say almost because whilst I don't believe there to be a reason to use /// I only say almost because whilst I don't believe there to be a reason to use
/// this I can't rule it out. /// this I can't rule it out.
@ -159,8 +159,14 @@ pub fn busy_wait_for_vblank() {
while VCOUNT.get() < 160 {} while VCOUNT.get() < 160 {}
} }
#[derive(BitfieldSpecifier, Clone, Copy, Debug)] /// The priority of a background layer or object. A higher priority should be
/// thought of as rendering first, and so is behind that of a lower priority.
/// For an equal priority background layer and object, the background has a
/// higher priority and therefore is behind the object.
#[bitsize(2)]
#[derive(FromBits, PartialEq, Eq, Clone, Copy, Debug, Default)]
pub enum Priority { pub enum Priority {
#[default]
P0 = 0, P0 = 0,
P1 = 1, P1 = 1,
P2 = 2, P2 = 2,

View file

@ -9,6 +9,7 @@
//! harder to integrate into your games depending on how they are architectured. //! harder to integrate into your games depending on how they are architectured.
mod affine; mod affine;
mod font;
mod managed; mod managed;
mod sprites; mod sprites;
mod unmanaged; mod unmanaged;
@ -20,7 +21,11 @@ pub use sprites::{
pub use affine::AffineMatrixInstance; pub use affine::AffineMatrixInstance;
pub use managed::{OamManaged, Object}; pub use managed::{OamManaged, Object};
pub use unmanaged::{AffineMode, OamIterator, OamSlot, OamUnmanaged, ObjectUnmanaged}; pub use unmanaged::{
AffineMode, GraphicsMode, OamIterator, OamSlot, OamUnmanaged, ObjectUnmanaged,
};
pub use font::{ChangeColour, ObjectTextRender, TextAlignment};
use super::DISPLAY_CONTROL; use super::DISPLAY_CONTROL;

View file

@ -14,10 +14,12 @@ struct AffineMatrixData {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub(crate) struct AffineMatrixVram(Rc<AffineMatrixData>); pub(crate) struct AffineMatrixVram(Rc<AffineMatrixData>);
/// An affine matrix that can be used on objects. It is just in time copied to /// An affine matrix that can be used on objects.
/// vram, so you can have as many as you like of these but you can only use up ///
/// to 16 in one frame. They are reference counted (Cloning is cheap) and /// It is just in time copied to vram, so you can have as many as you like
/// immutable, if you want to change a matrix you must make a new one and set it /// of these but you can only use up to 16 in one frame. They are reference
/// counted (Cloning is cheap) and immutable, if you want to change a matrix
/// you must make a new one and set it
/// on all your objects. /// on all your objects.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct AffineMatrixInstance { pub struct AffineMatrixInstance {

View file

@ -0,0 +1,511 @@
use core::fmt::{Display, Write};
use agb_fixnum::{Num, Vector2D};
use alloc::{collections::VecDeque, vec::Vec};
use crate::display::Font;
use self::{
preprocess::{Line, Preprocessed, PreprocessedElement},
renderer::{Configuration, WordRender},
};
use super::{OamIterator, ObjectUnmanaged, PaletteVram, Size, SpriteVram};
mod preprocess;
mod renderer;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[non_exhaustive]
pub(crate) enum WhiteSpace {
NewLine,
Space,
}
impl WhiteSpace {
pub(crate) fn from_char(c: char) -> Self {
match c {
' ' => WhiteSpace::Space,
'\n' => WhiteSpace::NewLine,
_ => panic!("char not supported whitespace"),
}
}
}
struct BufferedRender<'font> {
char_render: WordRender,
preprocessor: Preprocessed,
buffered_chars: VecDeque<char>,
letters: Letters,
font: &'font Font,
}
#[derive(Debug, Default)]
struct Letters {
letters: VecDeque<SpriteVram>,
number_of_groups: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[non_exhaustive]
/// The text alignment of the layout
pub enum TextAlignment {
#[default]
/// Left aligned, the left edge of the text lines up
Left,
/// Right aligned, the right edge of the text lines up
Right,
/// Center aligned, the center of the text lines up
Center,
/// Justified, both the left and right edges line up with space width adapted to make it so.
Justify,
}
struct TextAlignmentSettings {
space_width: Num<i32, 10>,
start_x: i32,
}
impl TextAlignment {
fn settings(self, line: &Line, minimum_space_width: i32, width: i32) -> TextAlignmentSettings {
match self {
TextAlignment::Left => TextAlignmentSettings {
space_width: minimum_space_width.into(),
start_x: 0,
},
TextAlignment::Right => TextAlignmentSettings {
space_width: minimum_space_width.into(),
start_x: width - line.width(),
},
TextAlignment::Center => TextAlignmentSettings {
space_width: minimum_space_width.into(),
start_x: (width - line.width()) / 2,
},
TextAlignment::Justify => {
let space_width = if line.number_of_spaces() != 0 {
Num::new(
width - line.width() + line.number_of_spaces() as i32 * minimum_space_width,
) / line.number_of_spaces() as i32
} else {
minimum_space_width.into()
};
TextAlignmentSettings {
space_width,
start_x: 0,
}
}
}
}
}
impl<'font> BufferedRender<'font> {
#[must_use]
fn new(font: &'font Font, sprite_size: Size, palette: PaletteVram) -> Self {
let config = Configuration::new(sprite_size, palette);
BufferedRender {
char_render: WordRender::new(config),
preprocessor: Preprocessed::new(),
buffered_chars: VecDeque::new(),
letters: Default::default(),
font,
}
}
}
fn is_private_use(c: char) -> bool {
('\u{E000}'..'\u{F8FF}').contains(&c)
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
/// Changes the palette to use to draw characters.
/// ```rust,no_run
/// # #![no_std]
/// # #![no_main]
/// use agb::display::object::{ObjectTextRender, PaletteVram, ChangeColour, Size};
/// use agb::display::palette16::Palette16;
/// use agb::display::Font;
///
/// use core::fmt::Write;
///
/// static EXAMPLE_FONT: Font = agb::include_font!("examples/font/yoster.ttf", 12);
///
/// # fn foo() {
/// let mut palette = [0x0; 16];
/// palette[1] = 0xFF_FF;
/// palette[2] = 0x00_FF;
/// let palette = Palette16::new(palette);
/// let palette = PaletteVram::new(&palette).unwrap();
/// let mut writer = ObjectTextRender::new(&EXAMPLE_FONT, Size::S16x16, palette);
///
/// let _ = writeln!(writer, "Hello, {}World{}!", ChangeColour::new(2), ChangeColour::new(1));
/// # }
/// ```
pub struct ChangeColour(u8);
impl ChangeColour {
#[must_use]
/// Creates the colour changer. Colour is a palette index and must be in the range 0..16.
pub fn new(colour: usize) -> Self {
assert!(colour < 16, "paletted colour must be valid (0..=15)");
Self(colour as u8)
}
fn try_from_char(c: char) -> Option<Self> {
let c = c as u32 as usize;
if (0xE000..0xE000 + 16).contains(&c) {
Some(ChangeColour::new(c - 0xE000))
} else {
None
}
}
fn to_char(self) -> char {
char::from_u32(self.0 as u32 + 0xE000).unwrap()
}
}
impl Display for ChangeColour {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_char(self.to_char())
}
}
impl BufferedRender<'_> {
fn input_character(&mut self, character: char) {
if !is_private_use(character) {
self.preprocessor
.add_character(self.font, character, self.char_render.sprite_width());
}
self.buffered_chars.push_back(character);
}
fn process(&mut self) {
let Some(c) = self.buffered_chars.pop_front() else {
return;
};
match c {
' ' | '\n' => {
if let Some(group) = self.char_render.finalise_letter() {
self.letters.letters.push_back(group);
self.letters.number_of_groups += 1;
}
self.letters.number_of_groups += 1;
}
letter => {
if let Some(group) = self.char_render.render_char(self.font, letter) {
self.letters.letters.push_back(group);
self.letters.number_of_groups += 1;
}
}
}
}
}
/// The object text renderer. Uses objects to render and layout text. It's use is non trivial.
/// Changes the palette to use to draw characters.
/// ```rust,no_run
/// #![no_std]
/// #![no_main]
/// use agb::display::object::{ObjectTextRender, PaletteVram, TextAlignment, Size};
/// use agb::display::palette16::Palette16;
/// use agb::display::{Font, WIDTH};
///
/// use core::fmt::Write;
///
/// static EXAMPLE_FONT: Font = agb::include_font!("examples/font/yoster.ttf", 12);
///
/// #[agb::entry]
/// fn main(gba: &mut agb::Gba) -> ! {
/// let (mut unmanaged, _) = gba.display.object.get_unmanaged();
/// let vblank = agb::interrupt::VBlank::get();
///
/// let mut palette = [0x0; 16];
/// palette[1] = 0xFF_FF;
/// let palette = Palette16::new(palette);
/// let palette = PaletteVram::new(&palette).unwrap();
///
/// let mut writer = ObjectTextRender::new(&EXAMPLE_FONT, Size::S16x16, palette);
///
/// let _ = writeln!(writer, "Hello, World!");
/// writer.layout((WIDTH, 40), TextAlignment::Left, 2);
///
/// loop {
/// writer.next_letter_group();
/// writer.update((0, 0));
/// vblank.wait_for_vblank();
/// let oam = &mut unmanaged.iter();
/// writer.commit(oam);
/// }
/// }
/// ```
pub struct ObjectTextRender<'font> {
buffer: BufferedRender<'font>,
layout: LayoutCache,
number_of_objects: usize,
}
impl<'font> ObjectTextRender<'font> {
#[must_use]
/// Creates a new text renderer with a given font, sprite size, and palette.
/// You must ensure that the sprite size can accomodate the letters from the
/// font otherwise it will panic at render time.
pub fn new(font: &'font Font, sprite_size: Size, palette: PaletteVram) -> Self {
Self {
buffer: BufferedRender::new(font, sprite_size, palette),
number_of_objects: 0,
layout: LayoutCache {
positions: VecDeque::new(),
line_capacity: VecDeque::new(),
objects: Vec::new(),
objects_are_at_origin: (0, 0).into(),
area: (0, 0).into(),
},
}
}
}
impl Write for ObjectTextRender<'_> {
fn write_str(&mut self, s: &str) -> core::fmt::Result {
for c in s.chars() {
self.buffer.input_character(c);
}
Ok(())
}
}
impl ObjectTextRender<'_> {
/// Commits work already done to screen. You can commit to multiple places in the same frame.
pub fn commit(&mut self, oam: &mut OamIterator) {
for (object, slot) in self.layout.objects.iter().zip(oam) {
slot.set(object);
}
}
/// Force a relayout, must be called after writing.
pub fn layout(
&mut self,
area: impl Into<Vector2D<i32>>,
alignment: TextAlignment,
paragraph_spacing: i32,
) {
self.layout.create_positions(
self.buffer.font,
&self.buffer.preprocessor,
&LayoutSettings {
area: area.into(),
alignment,
paragraph_spacing,
},
);
}
/// Removes one complete line. Returns whether a line could be removed. You must call [`update`][ObjectTextRender::update] after this
pub fn pop_line(&mut self) -> bool {
let width = self.layout.area.x;
let space = self.buffer.font.letter(' ').advance_width as i32;
let line_height = self.buffer.font.line_height();
if let Some(line) = self.buffer.preprocessor.lines(width, space).next() {
// there is a line
if self.layout.objects.len() >= line.number_of_letter_groups() {
// we have enough rendered letter groups to count
self.number_of_objects -= line.number_of_letter_groups();
for _ in 0..line.number_of_letter_groups() {
self.buffer.letters.letters.pop_front();
self.layout.positions.pop_front();
}
self.layout.line_capacity.pop_front();
self.layout.objects.clear();
self.buffer.preprocessor.pop(&line);
for position in self.layout.positions.iter_mut() {
position.y -= line_height as i16;
}
return true;
}
}
false
}
/// Updates the internal state of the number of letters to write and popped
/// line. Should be called in the same frame as and after
/// [`next_letter_group`][ObjectTextRender::next_letter_group], [`next_line`][ObjectTextRender::next_line], and [`pop_line`][ObjectTextRender::pop_line].
pub fn update(&mut self, position: impl Into<Vector2D<i32>>) {
if !self.buffer.buffered_chars.is_empty()
&& self.buffer.letters.letters.len() <= self.number_of_objects + 5
{
self.buffer.process();
}
self.layout.update_objects_to_display_at_position(
position.into(),
self.buffer.letters.letters.iter(),
self.number_of_objects,
);
}
/// Causes the next letter group to be shown on the next update. Returns
/// whether another letter could be added in the space given.
pub fn next_letter_group(&mut self) -> bool {
if !self.can_render_another_element() {
return false;
}
self.number_of_objects += 1;
self.at_least_n_letter_groups(self.number_of_objects);
true
}
fn can_render_another_element(&self) -> bool {
let max_number_of_lines = (self.layout.area.y / self.buffer.font.line_height()) as usize;
let max_number_of_objects = self
.layout
.line_capacity
.iter()
.take(max_number_of_lines)
.sum::<usize>();
max_number_of_objects > self.number_of_objects
}
/// Causes the next line to be shown on the next update. Returns
/// whether another line could be added in the space given.
pub fn next_line(&mut self) -> bool {
let max_number_of_lines = (self.layout.area.y / self.buffer.font.line_height()) as usize;
// find current line
for (start, end) in self
.layout
.line_capacity
.iter()
.scan(0, |count, line_size| {
let start = *count;
*count += line_size;
Some((start, *count))
})
.take(max_number_of_lines)
{
if self.number_of_objects >= start && self.number_of_objects < end {
self.number_of_objects = end;
self.at_least_n_letter_groups(end);
return true;
}
}
false
}
fn at_least_n_letter_groups(&mut self, n: usize) {
while !self.buffer.buffered_chars.is_empty() && self.buffer.letters.letters.len() <= n {
self.buffer.process();
}
}
}
struct LayoutCache {
positions: VecDeque<Vector2D<i16>>,
line_capacity: VecDeque<usize>,
objects: Vec<ObjectUnmanaged>,
objects_are_at_origin: Vector2D<i32>,
area: Vector2D<i32>,
}
impl LayoutCache {
fn update_objects_to_display_at_position<'a>(
&mut self,
position: Vector2D<i32>,
letters: impl Iterator<Item = &'a SpriteVram>,
number_of_objects: usize,
) {
let already_done = if position == self.objects_are_at_origin {
self.objects.len()
} else {
self.objects.clear();
0
};
self.objects.extend(
self.positions
.iter()
.zip(letters)
.take(number_of_objects)
.skip(already_done)
.map(|(offset, letter)| {
let position = offset.change_base() + position;
let mut object = ObjectUnmanaged::new(letter.clone());
object.show().set_position(position);
object
}),
);
self.objects.truncate(number_of_objects);
self.objects_are_at_origin = position;
}
fn create_positions(
&mut self,
font: &Font,
preprocessed: &Preprocessed,
settings: &LayoutSettings,
) {
self.area = settings.area;
self.line_capacity.clear();
self.positions.clear();
for (line, line_positions) in Self::create_layout(font, preprocessed, settings) {
self.line_capacity.push_back(line.number_of_letter_groups());
self.positions
.extend(line_positions.map(|x| Vector2D::new(x.x as i16, x.y as i16)));
}
}
fn create_layout<'a>(
font: &Font,
preprocessed: &'a Preprocessed,
settings: &'a LayoutSettings,
) -> impl Iterator<Item = (Line, impl Iterator<Item = Vector2D<i32>> + 'a)> + 'a {
let minimum_space_width = font.letter(' ').advance_width as i32;
let width = settings.area.x;
let line_height = font.line_height();
let mut head_position: Vector2D<Num<i32, 10>> = (0, -line_height).into();
preprocessed
.lines_element(width, minimum_space_width)
.map(move |(line, line_elements)| {
let line_settings = settings
.alignment
.settings(&line, minimum_space_width, width);
head_position.y += line_height;
head_position.x = line_settings.start_x.into();
(
line,
line_elements.filter_map(move |element| match element.decode() {
PreprocessedElement::LetterGroup { width } => {
let this_position = head_position;
head_position.x += width as i32;
Some(this_position.floor())
}
PreprocessedElement::WhiteSpace(space) => {
match space {
WhiteSpace::NewLine => {
head_position.y += settings.paragraph_spacing;
}
WhiteSpace::Space => head_position.x += line_settings.space_width,
}
None
}
}),
)
})
}
}
#[derive(PartialEq, Eq, Default)]
struct LayoutSettings {
area: Vector2D<i32>,
alignment: TextAlignment,
paragraph_spacing: i32,
}

View file

@ -0,0 +1,252 @@
use alloc::collections::VecDeque;
use crate::display::Font;
use super::WhiteSpace;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct PreprocessedElementEncoded(u8);
impl PreprocessedElementEncoded {
pub(crate) fn decode(self) -> PreprocessedElement {
match self.0 {
255 => PreprocessedElement::WhiteSpace(WhiteSpace::NewLine),
254 => PreprocessedElement::WhiteSpace(WhiteSpace::Space),
width => PreprocessedElement::LetterGroup { width },
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum PreprocessedElement {
LetterGroup { width: u8 },
WhiteSpace(WhiteSpace),
}
impl PreprocessedElement {
fn encode(self) -> PreprocessedElementEncoded {
PreprocessedElementEncoded(match self {
PreprocessedElement::LetterGroup { width } => width,
PreprocessedElement::WhiteSpace(space) => match space {
WhiteSpace::NewLine => 255,
WhiteSpace::Space => 254,
},
})
}
}
#[derive(Default, Debug)]
pub(crate) struct Preprocessed {
widths: VecDeque<PreprocessedElementEncoded>,
preprocessor: Preprocessor,
}
#[derive(Debug, Default)]
struct Preprocessor {
previous_character: Option<char>,
width_in_sprite: i32,
}
impl Preprocessor {
fn add_character(
&mut self,
font: &Font,
character: char,
sprite_width: i32,
widths: &mut VecDeque<PreprocessedElementEncoded>,
) {
match character {
space @ (' ' | '\n') => {
if self.width_in_sprite != 0 {
widths.push_back(
PreprocessedElement::LetterGroup {
width: self.width_in_sprite as u8,
}
.encode(),
);
self.width_in_sprite = 0;
}
widths.push_back(
PreprocessedElement::WhiteSpace(WhiteSpace::from_char(space)).encode(),
);
}
letter => {
let letter = font.letter(letter);
if let Some(previous_character) = self.previous_character {
self.width_in_sprite += letter.kerning_amount(previous_character);
}
if self.width_in_sprite + letter.width as i32 > sprite_width {
widths.push_back(
PreprocessedElement::LetterGroup {
width: self.width_in_sprite as u8,
}
.encode(),
);
self.width_in_sprite = 0;
}
self.width_in_sprite += letter.xmin as i32;
if self.width_in_sprite < 0 {
if let Some(back) = widths.back_mut() {
back.0 -= (-self.width_in_sprite).try_into().unwrap_or(0);
}
self.width_in_sprite = 0;
}
self.width_in_sprite += letter.advance_width as i32;
}
}
self.previous_character = Some(character);
}
}
pub(crate) struct Lines<'preprocess> {
minimum_space_width: i32,
layout_width: i32,
data: &'preprocess VecDeque<PreprocessedElementEncoded>,
current_start_idx: usize,
}
pub(crate) struct Line {
width: i32,
number_of_text_elements: usize,
number_of_spaces: usize,
number_of_letter_groups: usize,
}
impl Line {
#[inline(always)]
pub(crate) fn width(&self) -> i32 {
self.width
}
#[inline(always)]
pub(crate) fn number_of_text_elements(&self) -> usize {
self.number_of_text_elements
}
#[inline(always)]
pub(crate) fn number_of_spaces(&self) -> usize {
self.number_of_spaces
}
#[inline(always)]
pub(crate) fn number_of_letter_groups(&self) -> usize {
self.number_of_letter_groups
}
}
impl Iterator for Lines<'_> {
type Item = Line;
fn next(&mut self) -> Option<Self::Item> {
if self.current_start_idx >= self.data.len() {
return None;
}
let mut line_idx_length = 0;
let mut current_line_width_pixels = 0;
let mut spaces_after_last_word_count = 0usize;
let mut start_of_current_word = usize::MAX;
let mut length_of_current_word_pixels = 0;
let mut length_of_current_word = 0;
let mut number_of_spaces = 0;
let mut number_of_letter_groups = 0;
while let Some(next) = self.data.get(self.current_start_idx + line_idx_length) {
match next.decode() {
PreprocessedElement::LetterGroup { width } => {
if start_of_current_word == usize::MAX {
start_of_current_word = line_idx_length;
}
length_of_current_word_pixels += width as i32;
length_of_current_word += 1;
if current_line_width_pixels
+ length_of_current_word_pixels
+ spaces_after_last_word_count as i32 * self.minimum_space_width
>= self.layout_width
{
line_idx_length = start_of_current_word;
break;
}
}
PreprocessedElement::WhiteSpace(space) => {
if start_of_current_word != usize::MAX {
// flush word
current_line_width_pixels += length_of_current_word_pixels
+ spaces_after_last_word_count as i32 * self.minimum_space_width;
number_of_spaces += spaces_after_last_word_count;
number_of_letter_groups += length_of_current_word;
// reset parser
length_of_current_word_pixels = 0;
length_of_current_word = 0;
start_of_current_word = usize::MAX;
spaces_after_last_word_count = 0;
}
match space {
WhiteSpace::NewLine => {
line_idx_length += 1;
break;
}
WhiteSpace::Space => {
spaces_after_last_word_count += 1;
}
}
}
};
line_idx_length += 1;
}
self.current_start_idx += line_idx_length;
Some(Line {
width: current_line_width_pixels,
number_of_text_elements: line_idx_length,
number_of_spaces,
number_of_letter_groups,
})
}
}
impl Preprocessed {
pub(crate) fn new() -> Self {
Default::default()
}
pub(crate) fn add_character(&mut self, font: &Font, c: char, sprite_width: i32) {
self.preprocessor
.add_character(font, c, sprite_width, &mut self.widths);
}
pub(crate) fn pop(&mut self, line: &Line) {
let elements = line.number_of_text_elements();
for _ in 0..elements {
self.widths.pop_front();
}
}
pub(crate) fn lines(&self, layout_width: i32, minimum_space_width: i32) -> Lines<'_> {
Lines {
minimum_space_width,
layout_width,
data: &self.widths,
current_start_idx: 0,
}
}
pub(crate) fn lines_element(
&self,
layout_width: i32,
minimum_space_width: i32,
) -> impl Iterator<Item = (Line, impl Iterator<Item = PreprocessedElementEncoded> + '_)> {
let mut idx = 0;
self.lines(layout_width, minimum_space_width).map(move |x| {
let length = x.number_of_text_elements;
let d = self.widths.range(idx..(idx + length)).copied();
idx += length;
(x, d)
})
}
}

View file

@ -0,0 +1,124 @@
use crate::display::{
object::{DynamicSprite, PaletteVram, Size, SpriteVram},
Font,
};
use super::ChangeColour;
struct WorkingLetter {
dynamic: DynamicSprite,
// where to render the letter from x_min to x_max
x_offset: i32,
}
impl WorkingLetter {
fn new(size: Size) -> Self {
Self {
dynamic: DynamicSprite::new(size),
x_offset: 0,
}
}
fn reset(&mut self) {
self.x_offset = 0;
}
}
pub struct Configuration {
sprite_size: Size,
palette: PaletteVram,
}
impl Configuration {
#[must_use]
pub fn new(sprite_size: Size, palette: PaletteVram) -> Self {
Self {
sprite_size,
palette,
}
}
}
pub(crate) struct WordRender {
working: WorkingLetter,
config: Configuration,
colour: usize,
previous_character: Option<char>,
}
impl WordRender {
pub(crate) fn sprite_width(&self) -> i32 {
self.config.sprite_size.to_width_height().0 as i32
}
#[must_use]
pub(crate) fn new(config: Configuration) -> Self {
WordRender {
working: WorkingLetter::new(config.sprite_size),
config,
colour: 1,
previous_character: None,
}
}
#[must_use]
pub(crate) fn finalise_letter(&mut self) -> Option<SpriteVram> {
if self.working.x_offset == 0 {
return None;
}
let mut new_sprite = DynamicSprite::new(self.config.sprite_size);
core::mem::swap(&mut self.working.dynamic, &mut new_sprite);
let sprite = new_sprite.to_vram(self.config.palette.clone());
self.working.reset();
Some(sprite)
}
#[must_use]
pub(crate) fn render_char(&mut self, font: &Font, c: char) -> Option<SpriteVram> {
if let Some(next_colour) = ChangeColour::try_from_char(c) {
self.colour = next_colour.0 as usize;
return None;
}
let font_letter: &crate::display::FontLetter = font.letter(c);
if let Some(previous_character) = self.previous_character {
self.working.x_offset += font_letter.kerning_amount(previous_character);
}
self.previous_character = Some(c);
// uses more than the sprite can hold
let group = if self.working.x_offset + font_letter.width as i32
> self.config.sprite_size.to_width_height().0 as i32
{
self.finalise_letter()
} else {
None
};
self.working.x_offset += font_letter.xmin as i32;
self.working.x_offset = self.working.x_offset.max(0);
let y_position = font.ascent() - font_letter.height as i32 - font_letter.ymin as i32;
for y in 0..font_letter.height as usize {
for x in 0..font_letter.width as usize {
let rendered = font_letter.bit_absolute(x, y);
if rendered {
self.working.dynamic.set_pixel(
x + self.working.x_offset as usize,
(y_position + y as i32) as usize,
self.colour,
);
}
}
}
self.working.x_offset += font_letter.advance_width as i32;
group
}
}

View file

@ -396,6 +396,7 @@ impl Object<'_> {
} }
/// Sets the horizontal flip, note that this only has a visible affect in Normal mode. /// Sets the horizontal flip, note that this only has a visible affect in Normal mode.
/// Use [hflip](Self::hflip) to get the value
pub fn set_hflip(&mut self, flip: bool) -> &mut Self { pub fn set_hflip(&mut self, flip: bool) -> &mut Self {
// safety: only have one of these, doesn't modify slotmap // safety: only have one of these, doesn't modify slotmap
unsafe { self.object().set_hflip(flip) }; unsafe { self.object().set_hflip(flip) };
@ -403,7 +404,15 @@ impl Object<'_> {
self self
} }
/// Returns the horizontal flip
/// Use [set_hflip](Self::set_hflip) to set the value
#[must_use]
pub fn hflip(&self) -> bool {
unsafe { self.object_shared().hflip() }
}
/// Sets the vertical flip, note that this only has a visible affect in Normal mode. /// Sets the vertical flip, note that this only has a visible affect in Normal mode.
/// Use [vflip](Self::vflip) to get the value
pub fn set_vflip(&mut self, flip: bool) -> &mut Self { pub fn set_vflip(&mut self, flip: bool) -> &mut Self {
// safety: only have one of these, doesn't modify slotmap // safety: only have one of these, doesn't modify slotmap
unsafe { self.object().set_vflip(flip) }; unsafe { self.object().set_vflip(flip) };
@ -411,7 +420,15 @@ impl Object<'_> {
self self
} }
/// Returns the vertical flip
/// Use [set_vflip](Self::set_vflip) to set the value
#[must_use]
pub fn vflip(&self) -> bool {
unsafe { self.object_shared().vflip() }
}
/// Sets the priority of the object relative to the backgrounds priority. /// Sets the priority of the object relative to the backgrounds priority.
/// Use [priority](Self::priority) to get the value
pub fn set_priority(&mut self, priority: Priority) -> &mut Self { pub fn set_priority(&mut self, priority: Priority) -> &mut Self {
// safety: only have one of these, doesn't modify slotmap // safety: only have one of these, doesn't modify slotmap
unsafe { self.object().set_priority(priority) }; unsafe { self.object().set_priority(priority) };
@ -419,6 +436,13 @@ impl Object<'_> {
self self
} }
/// Returns the priority of the object
/// Use [set_priority](Self::set_priority) to set the value
#[must_use]
pub fn priority(&self) -> Priority {
unsafe { self.object_shared().priority() }
}
/// Changes the sprite mode to be hidden, can be changed to Normal or Affine /// Changes the sprite mode to be hidden, can be changed to Normal or Affine
/// modes using [`show`][Object::show] and /// modes using [`show`][Object::show] and
/// [`show_affine`][Object::show_affine] respectively. /// [`show_affine`][Object::show_affine] respectively.
@ -430,6 +454,8 @@ impl Object<'_> {
} }
/// Sets the x position of the object. /// Sets the x position of the object.
/// Use [x](Self::x) to get the value
/// Use [set_position](Self::set_position) to set both `x` and `y`
pub fn set_x(&mut self, x: u16) -> &mut Self { pub fn set_x(&mut self, x: u16) -> &mut Self {
// safety: only have one of these, doesn't modify slotmap // safety: only have one of these, doesn't modify slotmap
unsafe { self.object().set_x(x) }; unsafe { self.object().set_x(x) };
@ -437,7 +463,16 @@ impl Object<'_> {
self self
} }
/// Returns the x position of the object
/// Use [set_x](Self::set_x) to set the value
#[must_use]
pub fn x(&self) -> u16 {
unsafe { self.object_shared().x() }
}
/// Sets the y position of the object. /// Sets the y position of the object.
/// Use [y](Self::y) to get the value
/// Use [set_position](Self::set_position) to set both `x` and `y`
pub fn set_y(&mut self, y: u16) -> &mut Self { pub fn set_y(&mut self, y: u16) -> &mut Self {
// safety: only have one of these, doesn't modify slotmap // safety: only have one of these, doesn't modify slotmap
unsafe { self.object().set_y(y) }; unsafe { self.object().set_y(y) };
@ -445,14 +480,29 @@ impl Object<'_> {
self self
} }
/// Returns the y position of the object
/// Use [set_y](Self::set_y) to set the value
#[must_use]
pub fn y(&self) -> u16 {
unsafe { self.object_shared().y() }
}
/// Sets the position of the object. /// Sets the position of the object.
pub fn set_position(&mut self, position: Vector2D<i32>) -> &mut Self { /// Use [position](Self::position) to get the value
pub fn set_position(&mut self, position: impl Into<Vector2D<i32>>) -> &mut Self {
// safety: only have one of these, doesn't modify slotmap // safety: only have one of these, doesn't modify slotmap
unsafe { self.object().set_position(position) }; unsafe { self.object().set_position(position.into()) };
self self
} }
/// Returns the position of the object
/// Use [set_position](Self::set_position) to set the value
#[must_use]
pub fn position(&self) -> Vector2D<i32> {
unsafe { self.object_shared().position() }
}
/// Sets the affine matrix. This only has an affect in Affine mode. /// Sets the affine matrix. This only has an affect in Affine mode.
pub fn set_affine_matrix(&mut self, affine_matrix: AffineMatrixInstance) -> &mut Self { pub fn set_affine_matrix(&mut self, affine_matrix: AffineMatrixInstance) -> &mut Self {
// safety: only have one of these, doesn't modify slotmap // safety: only have one of these, doesn't modify slotmap
@ -478,9 +528,9 @@ mod tests {
use super::*; use super::*;
const TEST_SPRITES: &Graphics = include_aseprite!("examples/gfx/tall.aseprite"); static TEST_SPRITES: &Graphics = include_aseprite!("examples/gfx/tall.aseprite");
const TEST_SPRITE: &Sprite = &TEST_SPRITES.sprites()[0]; static TEST_SPRITE: &Sprite = &TEST_SPRITES.sprites()[0];
#[test_case] #[test_case]
fn test_always_ordered(gba: &mut crate::Gba) { fn test_always_ordered(gba: &mut crate::Gba) {

Some files were not shown because too many files have changed in this diff Show more