git.y1.nz

gbdk-2020

GameBoy Development Kit
download: https://git.y1.nz/archives/gbdk.tar.gz
README | Files | Log | Refs | LICENSE

commit debcf48ca36bf575fc1350873467398ac52cf240
parent a7a24acb31e20f873dcb5e8a753217c91f1502ed
Author: bbbbbr <bbbbbr@users.noreply.github.com>
Date:   Wed,  1 May 2024 03:42:29 -0700

Merge pull request #652 from bbbbbr/docs_4_3

Docs: sms/gg banking notes, coding guidelines, GBDKDIR, etc
Diffstat:
Mdocs/README10+++++++---
Mdocs/pages/04_coding_guidelines.md18++++++++++++++++--
Mdocs/pages/05_banking_mbcs.md35+++++++++++++++++++++++++++++++++--
Mdocs/pages/06b_supported_consoles.md10++++++++--
4 files changed, 64 insertions(+), 9 deletions(-)

diff --git a/docs/README b/docs/README @@ -38,9 +38,13 @@ Setup: * Unzip to a folder of your choice (which you've probably already done) Suggested location: /opt/gbdk/ -* Recommended but not required: Add the gbdk 'bin' sub-directory to your shell path - Run from command line (only lasts for that session): export GBDKDIR=/opt/gbdk/ - Or add that to your shell defaults (permanent) +* Recommended but not required: + - Add the gbdk 'bin' sub-directory to your shell path. For example: export PATH=$PATH:/opt/gbdk/bin + - These can be set temporarily in the current shell or added to your shell defaults permanently. + +* Note: The GBDKDIR environment variable is not necessary to set in most cases. When lcc is + called it will attempt to determine the current working directory automatically on it's own. + When GBDKDIR is used it requires a trailing slash, for example: export GBDKDIR=/opt/gbdk/ * Open a command line and compile the examples by running "make" in the "examples/gb" sub-directory: diff --git a/docs/pages/04_coding_guidelines.md b/docs/pages/04_coding_guidelines.md @@ -59,6 +59,11 @@ https://gbdev.io/pandocs/STAT.html#stat-modes These are standard types defined in `stdint.h` (`#include <stdint.h>`) and `stdbool.h` (`#include <stdbool.h>`). - Global and local static variables are generally more efficient than local non-static variables (which go on the stack and are slower and can result in slower code). + - An exception to this when there are a small number of local variables (one or two) and the code is not complex. Then the compiler may allocate those variables to CPU registers instead which may be faster. + - Functions which use global or static local variables will loose re-entrancy. In most cases it is not a problem, but important to keep in mind. + - In particular avoid putting big arrays on the stack, consider static local or global. + + - Keep the number of arguments passed to functions small (ideally one or two arguments at most). When there are a large number of arguments they get pushed onto the stack and result in more overhead for function calls. See the Calling Conventions in the SDCC compiler manual for details. - @anchor const_array_data `const` keyword: use const for arrays, structs and variables with read-only (constant) data. It will reduce ROM, RAM and CPU usage significantly. Non-`const` values are loaded from ROM into RAM inefficiently, and there is no benefit in loading them into the limited available RAM if they aren't going to be changed. @@ -70,7 +75,7 @@ https://gbdev.io/pandocs/STAT.html#stat-modes - https://codeforwin.org/2017/11/constant-pointer-and-pointer-to-constant-in-c.html - https://stackoverflow.com/questions/21476869/constant-pointer-vs-pointer-to-constant - - For calculated values that don't change, pre-compute results once and store the result. Using lookup-tables and the like can improve speed and reduce code size. Macros can sometimes help. It may be beneficial to do the calculations with an outside tool and then include the result as C code in a const array. + - For calculated values that don't change, pre-compute results once and store the result. Using lookup-tables and similar approaches can improve speed and reduce code size. Macros can sometimes help. It may be beneficial to do the calculations with an outside tool and then include the result as C code in a const array. - Use an advancing pointer (`someStruct->var = x; someStruct++`) to loop through arrays of structs instead of using indexing each time in the loop `someStruct[i].var = x`. @@ -252,7 +257,16 @@ Also See: # When C isn't fast enough -For many applications C is fast enough but in intensive functions are sometimes better written in assembly. This section deals with interfacing your core C program with fast assembly sub routines. +For many applications C is fast enough but in intensive functions are sometimes better written in assembly. This section deals with interfacing your core C program with fast assembly sub routines. + +## Reusable Local Labels and Inline ASM + +When functions are written assembly it's generally better to not mix the inline ASM with C code and instead write the whole function in assembly. + +If they are mixed then descriptive named labels should not be used for inline ASM. This is due to descriptive labels interfering with the expected scope of the reusable local labels generated from the compiled C code. The compiler will not detect this problem and the resulting code may fail to execute correctly without warning. + +Instead use reusable local symbols/labels (for example `1$:`). To learn more about them check the SDAS manual section "1.3.3 Reusable Symbols" + ## Variables and registers <!-- C normally expects registers to be preserved across a function call. However in the case above as DE is used as the return value and HL is used for anything, only BC needs to be preserved. --> diff --git a/docs/pages/05_banking_mbcs.md b/docs/pages/05_banking_mbcs.md @@ -5,6 +5,7 @@ # ROM/RAM Banking and MBCs (Memory Bank Controllers) The standard Game Boy cartridge with no MBC has a fixed 32K bytes of ROM. In order to make cartridges with larger ROM sizes (to store more code and graphics) MBCs can be used. They allow switching between multiple ROM banks that use the same memory region. Only one of the banks can be selected as active at a given time, while all the other banks are inactive (and so, inaccessible). +The majority of this section about banking is focused on the Game Boy since that is the original GBDK platform. Much of it still applies for the Game Gear(GG) and Sega Master System(SMS). For additional details about banking specifically related to these two systems see the @ref sms_gg_banking "SMS/GG Banking" section. ## Non-banked cartridges Cartridges with no MBC controller are non-banked, they have 32K bytes of fixed ROM space and no switchable banks. For these cartridges the ROM space between `0000h and 7FFFh` can be treated as a single large bank of 32K bytes, or as two contiguous banks of 16K bytes in Bank `0` at `0000h - 3FFFh` and Bank `1` at `4000h to 7FFFh`. @@ -161,14 +162,14 @@ The bank number for a banked function, variable or source file can be stored and @anchor banked_keywords ### BANKED/NONBANKED Keywords for Functions - `BANKED` (is a calling convention): - - The function will use banked sdcc calls. + - The function will use banked (`far`) sdcc calls (which switch to the function's ROM bank automatically). - Placed in the bank selected by its source file (or compiler switches). - This keyword only specifies the __calling convention__ for the function, it does not set a bank itself. - `NONBANKED` (is a storage attribute): - Placed in the non-banked lower 16K region (bank 0), regardless of the bank selected by its source file. - Forces the .area to `_HOME`. - `<not-specified>`: - - The function does not use sdcc banked calls (`near` instead of `far`). + - The function does not use sdcc banked calls (`near` instead of `far`/ banked sdcc calls) - Placed in the bank selected by its source file (or compiler switches). @anchor banked_calls @@ -340,3 +341,33 @@ There are several projects in the GBDK 2020 examples folder which demonstrate di - `Banks_farptr`: using far pointers which have the bank number built into the pointer. - `Banks_autobank`: shows how to use the bank auto-assignment feature in GBDK 2020 4.0.2 or later, instead of having to manually specify which bank a source file will reside it. + +@anchor sms_gg_banking "SMS/GG Banking" section. +# SMS/Game Gear Banking + +The memory banking setup for SMS and Game Gear in GBDK is different than it is for the Game Boy. Instead of a single switchable bank in the `0x4000 - 0x7FFF` range, there are two switchable frames at different address ranges. The configuration is as follows: + +- Frame 0: Non-banked, at address `0x0000 - 0x3FFF` +- Frame 1: `CODE_<N>`, at address `0x4000 - 0x7FFF` + - Use for: Banked Code and Assets + - Example: `#pragma codeseg CODE_2` or `#pragma codeseg CODE_255` for autobanking (no leading underscore) + - Select the active bank using: @ref SWITCH_ROM(). The current active bank can be queried using @ref CURRENT_BANK or `MAP_FRAME1` +- Frame 2: `_LIT_<N>`, at address 0x8000- 0xBFFF + - Use for: Assets + - `_DATA_N` may also be mapped into Frame 2 (RAM) + - Example: `#pragma codeseg LIT_2` or `#pragma codeseg LIT_255` for autobanking (no leading underscore) + - Select the active bank using @ref SWITCH_ROM2(). The current active bank can be queried using `MAP_FRAME2` + +Banked code and any pointers associated with it will only work correctly when active in Frame 1 (at `0x4000`), so it must use `CODE_<N>`. Graphics and other assets may go in either Frame 1 (at `0x4000`) or, if designed for it then Frame 2 (at `0x8000`). + +## Auto-Banking +CODE and LIT cannot share the same bank number. For example, if `CODE` is assigned to `bank 3` then `LIT` cannot be in `bank 3` as well. + +@ref bankpack is aware of this requirement and will group `CODE` and `LIT` separately when packing for autobanking. It's process is as follows: + 1. Note: CODE and LIT are not sorted before packing + 2. Assign fixed banks first (for both `CODE` and `LIT`). An error will be generated if both types assigned to the same bank. Banks are marked exclusive to whichever type is assigned in them first. + 3. Then autobanked entries (both `CODE` and `LIT`) are assigned to banks, they are only assigned to banks of a matching type or an unused bank. Same as above, the first type to use a bank makes it exclusive to that type. + +The bankpack option `-banktype=` may be used to set a bank to use specific type (`CODE` or `LIT`). This will take effect before bankpack tries to perform any bank assignment. For example: `-banktype=2:LIT` (or `-Wb-banktype=2:LIT` when used with @ref lcc) sets bank 2 to exclusively use type `LIT`. + + diff --git a/docs/pages/06b_supported_consoles.md b/docs/pages/06b_supported_consoles.md @@ -234,7 +234,7 @@ NES/Famicom - See @ref nes_technical_details "NES technical details" @anchor using_cgb_features -# Using Game Boy Color (CGB) Features +# Using Game Boy Color (GBC/CGB) Features ## Differences Versus the Regular Game Boy (DMG/GBP/SGB) These are some of the main hardware differences between the Regular Game Boy and the Game Boy Color. @@ -253,10 +253,12 @@ These are some of the main hardware differences between the Regular Game Boy and - WRAM: 8 x 4K WRAM banks in the 0xD000 - 0xDFFF region - LCD VRAM DMA -## CGB features in GBDK +## Game Boy Color features in GBDK These are some of the main GBDK API features for the CGB. Many of the items listed below link to additional information. + - ROM header settings: + - See the FAQ entry @ref faq_gb_type_header_setting "How do I set SGB, Color only and Color compatibility in the ROM header?" - Tile and Pattern data: - Select VRAM Banks: @ref VBK_REG (used with `set_bkg/win/sprite_*()`) - set_bkg_attributes(), set_bkg_submap_attributes() @@ -364,6 +366,10 @@ To provide an easier experience, gbdk-nes attempts to hide most of these quirks This entire section is written as a guide on porting GB projects to NES. If you are new to GBDK, you may wish to familiarize yourself with using GBDK for GB development first as the topics covered will make a lot more sense after gaining experience with GB development. +### Mapper + +Currently the NES support in GBDK uses UNROM-512 (Mapper30) with single-screen mirroring (the mapper2 subset of Mapper30). + ### Buffered mode vs direct mode On the GB, the vblank period serves as an optimal time to write data to PPU memory, and PPU memory can also be written efficiently with VRAM DMA.

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.