├── scxly ├── scxly.gb ├── screenshots │ ├── bgp_init.png │ ├── expected.png │ └── noint_noscx.png ├── make.bat ├── README.md ├── src │ └── scxly.sm83 └── inc │ └── gbhw.inc ├── lycscx ├── lycscx.gb ├── screenshots │ ├── expected.png │ └── noint_noscx.png ├── make.bat ├── README.md ├── src │ └── lycscx.sm83 └── inc │ └── gbhw.inc ├── lycscy ├── lycscy.gb ├── screenshots │ ├── expected.png │ └── noint_noscy.png ├── make.bat ├── README.md ├── src │ └── lycscy.sm83 └── inc │ └── gbhw.inc ├── winpos ├── winpos.gb ├── inc │ ├── font.chr │ ├── tileset.bin │ ├── background.bin │ └── window.bin ├── res │ ├── tiles.gbr │ ├── window.gbm │ └── background.gbm ├── screenshots │ └── expected.gif ├── make.bat ├── README.md └── src │ └── winpos.sm83 ├── fairylake ├── fairylake.gb ├── Tiles │ ├── BGM.gbm │ └── Tileset.gbr ├── inc │ ├── bgtiles.bin │ ├── initoam.bin │ ├── initoam.bin.bak │ ├── wdmap.bin │ ├── bgmap.bin │ ├── bgmap.bin.bak │ └── gbhw.inc ├── plans │ ├── Sketch.pdn │ ├── Sketch.png │ └── Tilesketch.pdn ├── screenshots │ └── expected.gif ├── make.bat ├── README.md └── src │ └── fairylake.sm83 ├── palettely ├── palettely.gb ├── screenshots │ ├── expected.png │ └── noint_nobgp.png ├── make.bat ├── README.md ├── src │ └── palettely.sm83 └── inc │ └── gbhw.inc ├── statcount ├── inc │ ├── font.chr │ └── hardware.inc ├── statcount.gb ├── statcount-auto.gb ├── screenshots │ ├── fail.png │ ├── pass.png │ ├── auto-fail.png │ └── auto-pass.png ├── make.bat ├── README.md └── src │ ├── statcount-auto.sm83 │ └── statcount.sm83 ├── README.md └── LICENSE /scxly/scxly.gb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/scxly/scxly.gb -------------------------------------------------------------------------------- /lycscx/lycscx.gb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/lycscx/lycscx.gb -------------------------------------------------------------------------------- /lycscy/lycscy.gb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/lycscy/lycscy.gb -------------------------------------------------------------------------------- /winpos/winpos.gb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/winpos/winpos.gb -------------------------------------------------------------------------------- /winpos/inc/font.chr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/winpos/inc/font.chr -------------------------------------------------------------------------------- /winpos/res/tiles.gbr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/winpos/res/tiles.gbr -------------------------------------------------------------------------------- /fairylake/fairylake.gb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/fairylake/fairylake.gb -------------------------------------------------------------------------------- /palettely/palettely.gb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/palettely/palettely.gb -------------------------------------------------------------------------------- /statcount/inc/font.chr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/statcount/inc/font.chr -------------------------------------------------------------------------------- /statcount/statcount.gb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/statcount/statcount.gb -------------------------------------------------------------------------------- /winpos/inc/tileset.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/winpos/inc/tileset.bin -------------------------------------------------------------------------------- /winpos/res/window.gbm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/winpos/res/window.gbm -------------------------------------------------------------------------------- /fairylake/Tiles/BGM.gbm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/fairylake/Tiles/BGM.gbm -------------------------------------------------------------------------------- /fairylake/inc/bgtiles.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/fairylake/inc/bgtiles.bin -------------------------------------------------------------------------------- /fairylake/inc/initoam.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/fairylake/inc/initoam.bin -------------------------------------------------------------------------------- /winpos/res/background.gbm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/winpos/res/background.gbm -------------------------------------------------------------------------------- /fairylake/Tiles/Tileset.gbr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/fairylake/Tiles/Tileset.gbr -------------------------------------------------------------------------------- /fairylake/plans/Sketch.pdn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/fairylake/plans/Sketch.pdn -------------------------------------------------------------------------------- /fairylake/plans/Sketch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/fairylake/plans/Sketch.png -------------------------------------------------------------------------------- /statcount/statcount-auto.gb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/statcount/statcount-auto.gb -------------------------------------------------------------------------------- /fairylake/inc/initoam.bin.bak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/fairylake/inc/initoam.bin.bak -------------------------------------------------------------------------------- /fairylake/plans/Tilesketch.pdn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/fairylake/plans/Tilesketch.pdn -------------------------------------------------------------------------------- /scxly/screenshots/bgp_init.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/scxly/screenshots/bgp_init.png -------------------------------------------------------------------------------- /scxly/screenshots/expected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/scxly/screenshots/expected.png -------------------------------------------------------------------------------- /statcount/screenshots/fail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/statcount/screenshots/fail.png -------------------------------------------------------------------------------- /statcount/screenshots/pass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/statcount/screenshots/pass.png -------------------------------------------------------------------------------- /lycscx/screenshots/expected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/lycscx/screenshots/expected.png -------------------------------------------------------------------------------- /lycscy/screenshots/expected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/lycscy/screenshots/expected.png -------------------------------------------------------------------------------- /winpos/screenshots/expected.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/winpos/screenshots/expected.gif -------------------------------------------------------------------------------- /fairylake/screenshots/expected.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/fairylake/screenshots/expected.gif -------------------------------------------------------------------------------- /lycscx/screenshots/noint_noscx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/lycscx/screenshots/noint_noscx.png -------------------------------------------------------------------------------- /lycscy/screenshots/noint_noscy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/lycscy/screenshots/noint_noscy.png -------------------------------------------------------------------------------- /palettely/screenshots/expected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/palettely/screenshots/expected.png -------------------------------------------------------------------------------- /scxly/screenshots/noint_noscx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/scxly/screenshots/noint_noscx.png -------------------------------------------------------------------------------- /statcount/screenshots/auto-fail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/statcount/screenshots/auto-fail.png -------------------------------------------------------------------------------- /statcount/screenshots/auto-pass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/statcount/screenshots/auto-pass.png -------------------------------------------------------------------------------- /palettely/screenshots/noint_nobgp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashiepaws/scribbltests/HEAD/palettely/screenshots/noint_nobgp.png -------------------------------------------------------------------------------- /scxly/make.bat: -------------------------------------------------------------------------------- 1 | rgbasm -o scxly.o src/scxly.sm83 2 | rgblink -o scxly.gb scxly.o 3 | rgbfix -v -p 0 scxly.gb 4 | del scxly.o 5 | pause -------------------------------------------------------------------------------- /lycscx/make.bat: -------------------------------------------------------------------------------- 1 | rgbasm -o lycscx.o src/lycscx.sm83 2 | rgblink -o lycscx.gb lycscx.o 3 | rgbfix -v -p 0 lycscx.gb 4 | del lycscx.o 5 | pause -------------------------------------------------------------------------------- /lycscy/make.bat: -------------------------------------------------------------------------------- 1 | rgbasm -o lycscy.o src/lycscy.sm83 2 | rgblink -o lycscy.gb lycscy.o 3 | rgbfix -v -p 0 lycscy.gb 4 | del lycscy.o 5 | pause -------------------------------------------------------------------------------- /winpos/make.bat: -------------------------------------------------------------------------------- 1 | rgbasm -o winpos.o src/winpos.sm83 2 | rgblink -o winpos.gb winpos.o 3 | rgbfix -v -p 0 winpos.gb 4 | del winpos.o 5 | pause -------------------------------------------------------------------------------- /fairylake/make.bat: -------------------------------------------------------------------------------- 1 | rgbasm -o fairylake.o src/fairylake.sm83 2 | rgblink -o fairylake.gb fairylake.o 3 | rgbfix -v -p 0 fairylake.gb 4 | del fairylake.o 5 | pause -------------------------------------------------------------------------------- /palettely/make.bat: -------------------------------------------------------------------------------- 1 | rgbasm -o palettely.o src/palettely.sm83 2 | rgblink -o palettely.gb palettely.o 3 | rgbfix -v -p 0 palettely.gb 4 | del palettely.o 5 | pause -------------------------------------------------------------------------------- /statcount/make.bat: -------------------------------------------------------------------------------- 1 | rgbasm -o statcount.o src/statcount.sm83 2 | rgblink -o statcount.gb statcount.o 3 | rgbfix -v -p 0 statcount.gb 4 | del statcount.o 5 | rgbasm -o statcount-auto.o src/statcount-auto.sm83 6 | rgblink -o statcount-auto.gb statcount-auto.o 7 | rgbfix -v -p 0 statcount-auto.gb 8 | del statcount-auto.o 9 | pause -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gameboy Scribbltests 2 | 3 | The Scribbltests are a (currently very limited) collection of self-written test ROMs for testing all sorts of things. For details, do check the individual test folders. 4 | 5 | **Note:** The ROMs in this repository are tested on hardware. The exact models they were tested on as well as the test results are provided in the individual README files. 6 | 7 | ### Credits, Copyright or whatever 8 | 9 | The ROMs in this repository are all written by [me](https://github.com/Hacktix) with the addition of "soft breakpoints" added by [Amjad50](https://github.com/Amjad50). Thanks to the [Emulation Development Discord](https://discord.gg/7nuaqZ2) as well as the [gbdev Discord](https://discord.gg/gpBxq85) for helping with debugging and verifying the tests, as well as motivating me to write these in the first place. 10 | 11 | If you have any questions or just want to talk about Gameboy stuff, feel free to hit me up on Discord (Optix™#1337). 12 | -------------------------------------------------------------------------------- /fairylake/inc/wdmap.bin: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /winpos/inc/background.bin: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /fairylake/inc/bgmap.bin: -------------------------------------------------------------------------------- 1 |  2 |  3 |  4 |  5 |        -------------------------------------------------------------------------------- /fairylake/inc/bgmap.bin.bak: -------------------------------------------------------------------------------- 1 |  2 |  3 |  4 |  5 |        -------------------------------------------------------------------------------- /lycscx/README.md: -------------------------------------------------------------------------------- 1 | # LYCSCX 2 | 3 | The LYCSXC test is intended to test basic functionality of SCX and LY=LYC STAT interrupts. It draws vertical lines onto the screen and changes SCX every 8 scanlines using LY=LYC interrupts. 4 | 5 | ## Verified on: 6 | 7 | * ✔ Gameboy Pocket (MGB 9638 D) 8 | * ✔ Gameboy Color (CPU CGB D) 9 | 10 | ## Minimum Requirements 11 | 12 | * **CPU:** 13 | * Functional Instructions 14 | * Basic Instruction Timing 15 | * Memory Access Timing **not** required 16 | * **Interrupts:** 17 | * VBlank Interrupt 18 | * LYC=LY STAT Interrupt 19 | * **PPU:** 20 | * LCDC Bits 0, 4 and 7 21 | * Functional LY Register 22 | * Functional Background Display 23 | * Horizontal Scrolling (SCX Register) 24 | 25 | ## Expected Output 26 | 27 | ![expected](./screenshots/expected.png) 28 | 29 | ## Common Error Outputs 30 | 31 | ### Broken LY=LYC Interrupts / SCX 32 | 33 | ![noint_noscx](./screenshots/noint_noscx.png) 34 | 35 | This screen may occur if background scrolling doesn't work correctly or LY=LYC interrupts aren't fired (thereby not incrementing the SCX register). -------------------------------------------------------------------------------- /lycscy/README.md: -------------------------------------------------------------------------------- 1 | # LYCSCY 2 | 3 | The LYCSCY is intended to test basic functionality of SCY and LY=LYC STAT interrupts. It fills each row of tiles of the background with a different tile and changes SCY every 8 scanlines using LY=LYC interrupts. 4 | 5 | # Verified on: 6 | 7 | * ✔ Gameboy Pocket (MGB 9638 D) 8 | * ✔ Gameboy Color (CPU CGB D) 9 | 10 | ## Minimum Requirements 11 | 12 | * **CPU:** 13 | * Functional Instructions 14 | * Basic Instruction Timing 15 | * Memory Access Timing **not** required 16 | * **Interrupts:** 17 | * VBlank Interrupt 18 | * LYC=LY STAT Interrupt 19 | * **PPU:** 20 | * LCDC Bits 0, 4 and 7 21 | * Functional LY Register 22 | * Functional Background Display 23 | * Vertical Scrolling (SCY Register) 24 | 25 | ## Expected Output 26 | 27 | ![expected](./screenshots/expected.png) 28 | 29 | ## Common Error Outputs 30 | 31 | ### Broken LY=LYC Interrupts / SCY 32 | 33 | ![noint_noscy](./screenshots/noint_noscy.png) 34 | 35 | This screen may occur if vertical background scrolling doesn't work correctly or LY=LYC interrupts aren't fired (thereby not modifying the SCY register). -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Optix 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /palettely/README.md: -------------------------------------------------------------------------------- 1 | # PaletteLY 2 | 3 | The PaletteLY test is intended to test basic functionality of the BGP register and STAT/VBlank interrupts. It draws solid colored tiles to the background and changes the value of the BGP register every 8 scanlines using LY=LYC interrupts. 4 | 5 | ## Verified on: 6 | 7 | * ✔ Gameboy Pocket (MGB 9638 D) 8 | * ✔ Gameboy Color (CPU CGB D) 9 | 10 | ## Minimum Requirements 11 | 12 | * **CPU:** 13 | * Functional Instructions 14 | * Basic Instruction Timing 15 | * Memory Access Timing **not** required 16 | * **Interrupts:** 17 | * VBlank Interrupt 18 | * LYC=LY STAT Interrupt 19 | * **PPU:** 20 | * LCDC Bits 0, 4 and 7 21 | * Functional LY Register 22 | * Functional Background Display 23 | * Functional Background Palette (BGP) 24 | 25 | ## Expected Output 26 | 27 | ![expected](./screenshots/expected.png) 28 | 29 | ## Common Error Outputs 30 | 31 | ### Broken LY=LYC Interrupts / BGP 32 | 33 | ![noint_nobgp](./screenshots/noint_nobgp.png) 34 | 35 | This screen may occur if LY=LYC interrupts aren't fired (thereby not modifying the BGP register) or the BGP register is ignored when rendering frames. -------------------------------------------------------------------------------- /winpos/inc/window.bin: -------------------------------------------------------------------------------- 1 |  2 |  3 |  4 |  5 |      6 |  7 |  8 |  9 |      10 |  11 |  12 |  13 |      14 |  15 |  16 |  17 |      18 |  19 |  20 |  21 |      22 |  23 |  24 |  25 |      26 |  27 |  28 |  29 |      30 |  31 |  32 |  33 |      -------------------------------------------------------------------------------- /fairylake/README.md: -------------------------------------------------------------------------------- 1 | # Fairylake 2 | 3 | The Fairylake Test comes closer to a demo than a proper test ROM. It utilizes a majority of features the Gameboy Graphics System has to offer. 4 | 5 | **Note:** This test is currently WIP. Expect major changes. 6 | 7 | ## Verified on: 8 | 9 | * ✔ Gameboy Pocket (MGB 9638 D) 10 | * ✔ Gameboy Color (CPU CGB D) 11 | 12 | ## Expected Output 13 | 14 | ![expected](./screenshots/expected.gif) 15 | 16 | ## ROM Behavior 17 | 18 | * **Scanlines 0 - 7:** Static background. No scrolling, no sprites. 19 | 20 | * **Scanlines 8 - 31:** "Cloud-layer", background tiles with SCX incremented every 7 VBlanks. 21 | * **Scanlines 32 - 47:** *(not yet implemented)* "Heatlines", mid-scanline modification of SCY causing a "wiggle" effect going up and down 22 | * **Scanlines 48 - 63:** Static background, no scrolling. Sun made up of 2 sprites, both with the same tile number, utilizing X-flip. 23 | * **Scanlines 64 - 71:** *(not yet implemented)* "Slow water", slow increments of SCX 24 | * **Scanlines 72 - 87:** *(not yet implemented)* "Mid water", slightly faster increments of SCX 25 | * **Scanlines 88 - 95:** *(not yet implemented)* "Fast water", even faster increments of SCX 26 | * **Scanlines 96 - 103:** "Grass", utilizing Window display 27 | * **Scanlines 104 and following:** Static background. No scrolling, no sprites, no windows. -------------------------------------------------------------------------------- /winpos/README.md: -------------------------------------------------------------------------------- 1 | # WinPos 2 | 3 | The WinPos test is a sort of emulator debugging tool which should assist with development of window-related PPU features. It allows for modification of the WX and WY registers at runtime and provides visible results directly. 4 | 5 | ## Verified on: 6 | 7 | * ✔ Gameboy Pocket (MGB 9638 D) 8 | * ✔ Gameboy Color (CPU CGB D) 9 | 10 | ## Minimum Requirements 11 | 12 | * **CPU:** 13 | * Functional Instructions 14 | * Basic Instruction Timing 15 | * Memory Access Timing **not** required 16 | * **Interrupts:** 17 | * VBlank Interrupts 18 | * **PPU:** 19 | * LCDC Bits 0, 1, 5, 6 and 7 20 | * Functional LY Register 21 | * Functional Background Display 22 | * Functional Window Display 23 | * Functional Sprites (For WX/WY Labels, not required) 24 | * **Other:** 25 | * Functional Joypad 26 | 27 | ## Usage 28 | 29 | When starting up, the WX register will be loaded with the value $07 whereas the WY register will be loaded with $00. These values can be manipulated using the joypad. Pressing the right/left buttons increment/decrement the WX register respectively, whereas the down/up buttons do the same for WY. 30 | 31 | The numbers in the top left of the screen represent the current state of the window position registers, displayed as `WX/WY` as 2-digit hex numbers. 32 | 33 | ## Screenshots 34 | 35 | ![expected](./screenshots/expected.gif) -------------------------------------------------------------------------------- /scxly/README.md: -------------------------------------------------------------------------------- 1 | # SCXLY 2 | 3 | The SCXLY test is intended to test basic functionality of SCX and STAT/VBlank interrupts. It draws straight, vertical lines onto the screen and sets SCX to the same value as LY for each scanline, creating a "diagonal line" sort of effect. 4 | 5 | ## Verified on: 6 | 7 | * ✔ Gameboy Pocket (MGB 9638 D) 8 | * ✔ Gameboy Color (CPU CGB D) 9 | 10 | ## Requirements 11 | 12 | * **CPU:** 13 | * Functional Instructions 14 | * Basic Instruction Timing 15 | * Memory Access Timing **not** required 16 | * **Interrupts:** 17 | * VBlank Interrupt 18 | * HBlank STAT Interrupt 19 | * **PPU:** 20 | * LCDC Bits 0, 4 and 7 21 | * Functional LY Register 22 | * Functional Background Display 23 | * Functional Background Palette (BGP) 24 | * Horizontal Scrolling (SCX Register) 25 | 26 | ## Expected Output 27 | 28 | ![expected](./screenshots/expected.png) 29 | 30 | ## Common Error Outputs 31 | 32 | ### Broken HBlank Interrupts / SCX 33 | 34 | ![noint_noscx](./screenshots/noint_noscx.png) 35 | 36 | This screen may occur if background scrolling doesn't work correctly or HBlank interrupts aren't fired (thereby not incrementing the SCX register). 37 | 38 | ### Incorrect initial BGP state 39 | 40 | ![bgp_init](./screenshots/bgp_init.png) 41 | 42 | A screen like this may occur if the BGP register isn't initialized with correct values after startup. The BGP register is changed to what it *should* be after startup on scanline 72. -------------------------------------------------------------------------------- /statcount/README.md: -------------------------------------------------------------------------------- 1 | # STATcount 2 | 3 | The STATcount ROM is intended as an emulator debugging tool to assist with PPU timings. It allows for running a variable amount of machine cycles (referred to as NOPs) before storing the status of the STAT register. 4 | 5 | ## Verified on: 6 | 7 | * ✔ Gameboy Pocket (MGB 9638 D) 8 | * ✔ Gameboy Color (CPU CGB D) 9 | 10 | ## Minimum Requirements 11 | 12 | * **CPU:** 13 | * Functional Instructions 14 | * Accurate Instruction Timing (especially `nop`, `jp hl` and `ld a,[$ff00+c]`) 15 | * Memory Access Timing **required** (at least for `ld a,[$ff00+c]`) 16 | * **Interrupts:** 17 | * VBlank Interrupts 18 | * **PPU:** 19 | * LCDC Bit 7 20 | * Functional LY Register 21 | * Functional STAT Register (including bit 7 reading as constant `1`) 22 | * Accurately timed Mode-loop (including scanline 0 after enabling LCD) 23 | * **Other:** 24 | * Functional Joypad (not required for `statcount-auto.gb`) 25 | * Functional WRAM ($C000 - $CFFF) 26 | 27 | ## Usage 28 | 29 | After starting up the ROM the amount of machine cycles to wait can be modified using the Up / Down buttons. The minimum amount of NOPs is 1 (as memory read instructions *should* have a latency before actually reading the value from memory). 30 | 31 | Once the desired amount of NOPs has been selected, press START to run the test. LCD will be disabled for a short bit, re-enabled to run the test, disabled again to load VRAM with test results and finally re-enabled to display the results. 32 | 33 | The "Test" label will read either `OK` or `!XXh`. If it is not `OK`, the value shown instead of `XX` is what was expected based on the selected amount of NOPs. 34 | 35 | ### statcount-auto.gb 36 | 37 | The STATcount-auto ROM is an automated version of the STATcount test. It iterates over NOP options $01 to $FF and validates the results. If all results match up with the expected values, a "Test OK!" label will show up. If there are errors, a "Test failed:" label will show up, followed by a list of NOP-count options that the tests failed for, formatted as 2-digit hex numbers. 38 | 39 | ## Screenshots 40 | 41 | ### statcount.gb 42 | 43 | #### Test Failed 44 | 45 | ![testfailed](./screenshots/fail.png) 46 | 47 | #### Test Passed 48 | 49 | ![testpassed](./screenshots/pass.png) 50 | 51 | ### statcount-auto.gb 52 | 53 | #### Test Failed 54 | 55 | ![auto-fail](./screenshots/auto-fail.png) 56 | 57 | #### Test Passed 58 | 59 | ![auto-pass](./screenshots/auto-pass.png) -------------------------------------------------------------------------------- /palettely/src/palettely.sm83: -------------------------------------------------------------------------------- 1 | include "inc/gbhw.inc" 2 | 3 | ;-------------------------------------------------------------------- 4 | ; 5 | ; Interrupt Handlers 6 | ; 7 | ;-------------------------------------------------------------------- 8 | section "VBlank", rom0[$0040] 9 | call endFrame 10 | reti 11 | section "LCDC", rom0[$0048] 12 | call startScanline 13 | reti 14 | section "TimerOverflow", rom0[$0050] 15 | reti 16 | section "Serial", rom0[$0058] 17 | reti 18 | section "Joypad", rom0[$0060] 19 | reti 20 | 21 | ;-------------------------------------------------------------------- 22 | ; 23 | ; Entry point of the program, disables interrupts and 24 | ; continues to the main code section. 25 | ; 26 | ;-------------------------------------------------------------------- 27 | section "EntryPoint", rom0[$100] 28 | di 29 | jp main 30 | 31 | ;-------------------------------------------------------------------- 32 | ; 33 | ; Main portion of the ROM containing the actual code 34 | ; 35 | ;-------------------------------------------------------------------- 36 | section "GameCode", rom0[$150] 37 | 38 | ;-------------------------------------------------------------------- 39 | ; 40 | ; Main function of the program called in the entry point 41 | ; 42 | ;-------------------------------------------------------------------- 43 | main:: 44 | call StopLCD ; Stop LCD 45 | call LoadTilesBG ; Load background tiles 46 | 47 | ld a, %11100100 ; Initialize BGP 48 | ld [rBGP], a 49 | 50 | ld a, $03 ; Allow only VBlank & LCD STAT interrupts 51 | ld [rIE], a 52 | ld a, $47 ; Enable LYC=LY STAT interrupts 53 | ld [rSTAT], a 54 | ld a, $00 ; Set initial LYC to $08 55 | ld [rLYC], a 56 | 57 | ld a, %10010001 ; Enable LCD & background tilemap $8000 58 | ld [rLCDC], a 59 | 60 | ld hl, rBGP 61 | 62 | ei ; Enable Interrupts 63 | 64 | ld b, 10 65 | 66 | .lockup ; Prevent PC from going to crazy places 67 | halt 68 | jr .lockup 69 | 70 | ;-------------------------------------------------------------------- 71 | ; 72 | ; Handler for LCD STAT interrupt. 73 | ; Called every scanline, rotates BGP << 2 and increments LYC by 8. 74 | ; 75 | ;-------------------------------------------------------------------- 76 | startScanline:: 77 | rlc [hl] ; Rotate background palette 78 | rlc [hl] 79 | 80 | ld a, [rLYC] ; Set next LYC 81 | add a, $08 82 | ld [rLYC], a 83 | ret 84 | 85 | ;-------------------------------------------------------------------- 86 | ; 87 | ; Handler for VBlank interrupt. 88 | ; Called every frame, resets LYC to zero and BGP to default. 89 | ; 90 | ;-------------------------------------------------------------------- 91 | endFrame:: 92 | ld a, $00 ; Reload LYC 93 | ld [rLYC], a 94 | ld a, %11100100 ; Reload BGP 95 | ld [rBGP], a 96 | 97 | dec b 98 | jr nz, .skip 99 | 100 | ld b, b 101 | 102 | .skip: 103 | ret 104 | 105 | ;-------------------------------------------------------------------- 106 | ; 107 | ; Loads Tile 0 with a test pattern and clears 108 | ; the entire background with Tile 0. 109 | ; 110 | ; Destroys: AF, HL, C, DE 111 | ; 112 | ;-------------------------------------------------------------------- 113 | LoadTilesBG:: 114 | ld c, $FF ; Load C with tile pattern 115 | ld hl, $8000 ; Load HL with base pointer for tileset 116 | ld de, $0010 ; Load DE with $10 (byte count for one tile) 117 | call memfill16 ; Fill tile 0 memory with pattern 118 | 119 | ld c, $00 ; Load C with zero 120 | ld hl, $9800 ; Load HL with base for background tilemap 121 | ld de, $0800 ; Load DE with byte count for background 122 | call memfill16 ; Fill background map with tile 0 123 | ret 124 | 125 | ;-------------------------------------------------------------------- 126 | ; 127 | ; Fills all bytes in a memory region with a certain value. 128 | ; - HL > Destination base pointer 129 | ; - DE > Amount of bytes to write 130 | ; - C > Byte to write 131 | ; 132 | ; Destroys: AF, HL, DE 133 | ; 134 | ;-------------------------------------------------------------------- 135 | memfill16:: 136 | .memfill16Loop 137 | ld a,c ; Load C into accumulator for memory writes 138 | ld [hli], a ; Load memory at HL and increment pointer 139 | dec de ; Decrement byte counter 140 | ld a,e ; Load A with lower nibble of byte counter 141 | and e ; Set zero flag if lower nibble of byte counter is 0 142 | jr nz, .memfill16Loop ; Restart memory load process if lower nibble != 0 143 | ld a,d ; Load A with higher nibble of byte counter 144 | and d ; Set zero flag if higher nibble of byte counter is 0 145 | jr nz, .memfill16Loop ; Restart memory load process if higher nibble != 0 146 | ret 147 | 148 | ;-------------------------------------------------------------------- 149 | ; 150 | ; Waits for the next VBlank period and stops LCD. 151 | ; 152 | ; Destroys: AF 153 | ; 154 | ;-------------------------------------------------------------------- 155 | StopLCD:: 156 | call WaitVBlank ; Wait for VBlank 157 | xor a ; Set A to 0 158 | ld [rLCDC], a ; Load 0 to LCDC 159 | ret 160 | 161 | ;-------------------------------------------------------------------- 162 | ; 163 | ; Pauses operation until the next VBlank period. 164 | ; 165 | ; Destroys: AF 166 | ; 167 | ;-------------------------------------------------------------------- 168 | WaitVBlank:: 169 | .vblLoop 170 | ld a, [rLY] ; Load current LY into A 171 | cp 144 ; Check if scanline is 144 (VBlank) 172 | jr nz, .vblLoop ; If not, repeat 173 | ret 174 | -------------------------------------------------------------------------------- /lycscx/src/lycscx.sm83: -------------------------------------------------------------------------------- 1 | include "inc/gbhw.inc" 2 | 3 | ;-------------------------------------------------------------------- 4 | ; 5 | ; Interrupt Handlers 6 | ; 7 | ;-------------------------------------------------------------------- 8 | section "VBlank", rom0[$0040] 9 | call endFrame 10 | reti 11 | section "LCDC", rom0[$0048] 12 | call startScanline 13 | reti 14 | section "TimerOverflow", rom0[$0050] 15 | reti 16 | section "Serial", rom0[$0058] 17 | reti 18 | section "Joypad", rom0[$0060] 19 | reti 20 | 21 | ;-------------------------------------------------------------------- 22 | ; 23 | ; Entry point of the program, disables interrupts and 24 | ; continues to the main code section. 25 | ; 26 | ;-------------------------------------------------------------------- 27 | section "EntryPoint", rom0[$100] 28 | di 29 | jp main 30 | 31 | ;-------------------------------------------------------------------- 32 | ; 33 | ; Main portion of the ROM containing the actual code 34 | ; 35 | ;-------------------------------------------------------------------- 36 | section "GameCode", rom0[$150] 37 | 38 | ;-------------------------------------------------------------------- 39 | ; 40 | ; Main function of the program called in the entry point 41 | ; 42 | ;-------------------------------------------------------------------- 43 | main:: 44 | call StopLCD ; Stop LCD 45 | call LoadTilesBG ; Load background tiles 46 | 47 | ld a, %11100100 ; Initialize BGP 48 | ld [rBGP], a 49 | 50 | ld a, $03 ; Allow only VBlank & LCD STAT interrupts 51 | ld [rIE], a 52 | ld a, $47 ; Enable LYC=LY STAT interrupts 53 | ld [rSTAT], a 54 | ld a, $00 ; Set initial LYC to $08 55 | ld [rLYC], a 56 | 57 | ld hl, rSCX ; Use HL as pointer for SCX 58 | 59 | ld a, %10010001 ; Enable LCD & background tilemap $8000 60 | ld [rLCDC], a 61 | 62 | ei ; Enable Interrupts 63 | 64 | ld b, 10 ; Fire software interrupt after 10 frames 65 | 66 | .lockup ; Prevent PC from going to crazy places 67 | halt 68 | jr .lockup 69 | 70 | ;-------------------------------------------------------------------- 71 | ; 72 | ; Handler for LCD STAT interrupt. 73 | ; Called every scanline, increments SCX by one and LYC by 8. 74 | ; 75 | ;-------------------------------------------------------------------- 76 | startScanline:: 77 | inc [hl] ; Increment SCX 78 | 79 | ld a, [rLYC] ; Set next LYC 80 | add a, $08 81 | ld [rLYC], a 82 | ret 83 | 84 | ;-------------------------------------------------------------------- 85 | ; 86 | ; Handler for VBlank interrupt. 87 | ; Called every frame, resets SCX to zero. 88 | ; 89 | ;-------------------------------------------------------------------- 90 | endFrame:: 91 | xor a ; Clear A register 92 | ld [rLYC], a ; Reload LYC 93 | ld [rSCX], a ; Reload SCX 94 | 95 | dec b 96 | jr nz, .skip 97 | 98 | ld b, b 99 | 100 | .skip: 101 | ret 102 | 103 | ;-------------------------------------------------------------------- 104 | ; 105 | ; Loads Tile 0 with a test pattern and clears 106 | ; the entire background with Tile 0. 107 | ; 108 | ; Destroys: AF, HL, C, DE 109 | ; 110 | ;-------------------------------------------------------------------- 111 | LoadTilesBG:: 112 | ld c, $BB ; Load C with tile pattern 113 | ld hl, $8000 ; Load HL with base pointer for tileset 114 | ld de, $0010 ; Load DE with $10 (byte count for one tile) 115 | call memfill16 ; Fill tile 0 memory with pattern 116 | 117 | ld c, $00 ; Load C with zero 118 | ld hl, $9800 ; Load HL with base for background tilemap 119 | ld de, $0800 ; Load DE with byte count for background 120 | call memfill16 ; Fill background map with tile 0 121 | ret 122 | 123 | ;-------------------------------------------------------------------- 124 | ; 125 | ; Fills all bytes in a memory region with a certain value. 126 | ; - HL > Destination base pointer 127 | ; - DE > Amount of bytes to write 128 | ; - C > Byte to write 129 | ; 130 | ; Destroys: AF, HL, DE 131 | ; 132 | ;-------------------------------------------------------------------- 133 | memfill16:: 134 | .memfill16Loop 135 | ld a,c ; Load C into accumulator for memory writes 136 | ld [hli], a ; Load memory at HL and increment pointer 137 | dec de ; Decrement byte counter 138 | ld a,e ; Load A with lower nibble of byte counter 139 | and e ; Set zero flag if lower nibble of byte counter is 0 140 | jr nz, .memfill16Loop ; Restart memory load process if lower nibble != 0 141 | ld a,d ; Load A with higher nibble of byte counter 142 | and d ; Set zero flag if higher nibble of byte counter is 0 143 | jr nz, .memfill16Loop ; Restart memory load process if higher nibble != 0 144 | ret 145 | 146 | ;-------------------------------------------------------------------- 147 | ; 148 | ; Waits for the next VBlank period and stops LCD. 149 | ; 150 | ; Destroys: AF 151 | ; 152 | ;-------------------------------------------------------------------- 153 | StopLCD:: 154 | call WaitVBlank ; Wait for VBlank 155 | xor a ; Set A to 0 156 | ld [rLCDC], a ; Load 0 to LCDC 157 | ret 158 | 159 | ;-------------------------------------------------------------------- 160 | ; 161 | ; Pauses operation until the next VBlank period. 162 | ; 163 | ; Destroys: AF 164 | ; 165 | ;-------------------------------------------------------------------- 166 | WaitVBlank:: 167 | .vblLoop 168 | ld a, [rLY] ; Load current LY into A 169 | cp 144 ; Check if scanline is 144 (VBlank) 170 | jr nz, .vblLoop ; If not, repeat 171 | ret 172 | -------------------------------------------------------------------------------- /scxly/src/scxly.sm83: -------------------------------------------------------------------------------- 1 | include "inc/gbhw.inc" 2 | 3 | ;-------------------------------------------------------------------- 4 | ; 5 | ; Interrupt Handlers 6 | ; 7 | ;-------------------------------------------------------------------- 8 | section "VBlank", rom0[$0040] 9 | call endFrame 10 | reti 11 | section "LCDC", rom0[$0048] 12 | call startScanline 13 | reti 14 | section "TimerOverflow", rom0[$0050] 15 | reti 16 | section "Serial", rom0[$0058] 17 | reti 18 | section "Joypad", rom0[$0060] 19 | reti 20 | 21 | ;-------------------------------------------------------------------- 22 | ; 23 | ; Entry point of the program, disables interrupts and 24 | ; continues to the main code section. 25 | ; 26 | ;-------------------------------------------------------------------- 27 | section "EntryPoint", rom0[$100] 28 | di 29 | jp main 30 | 31 | ;-------------------------------------------------------------------- 32 | ; 33 | ; Main portion of the ROM containing the actual code 34 | ; 35 | ;-------------------------------------------------------------------- 36 | section "GameCode", rom0[$150] 37 | 38 | ;-------------------------------------------------------------------- 39 | ; 40 | ; Main function of the program called in the entry point 41 | ; 42 | ;-------------------------------------------------------------------- 43 | main:: 44 | call StopLCD ; Stop LCD 45 | call LoadTilesBG ; Load background tiles 46 | 47 | ld a, [rBGP] ; Store initial BGP in $C000 48 | ld hl, $C000 49 | ld [hl], a 50 | 51 | ld a, $03 ; Allow only VBlank & LCD STAT interrupts 52 | ld [rIE], a 53 | ld a, $0F ; Enable HBlank STAT interrupts 54 | ld [rSTAT], a 55 | 56 | ld a, %10010001 ; Enable LCD & background tilemap $8000 57 | ld [rLCDC], a 58 | 59 | ei ; Enable Interrupts 60 | 61 | ld b, 10 62 | 63 | .lockup ; Prevent PC from going to crazy places 64 | halt 65 | jr .lockup 66 | 67 | ;-------------------------------------------------------------------- 68 | ; 69 | ; Handler for LCD STAT interrupt. 70 | ; Called every scanline, increments SCX by one. 71 | ; 72 | ;-------------------------------------------------------------------- 73 | startScanline:: 74 | ld a, [rSCX] ; Load A with current SCX value 75 | inc a ; Increment A 76 | ld [rSCX], a ; Write A back to memory 77 | cp a, 72 ; Check if next scanline is 72 78 | ret nz ; Return if not 79 | ld a, %11100100 ; Otherwise, set A to BGP should-value 80 | ld [rBGP], a ; And load into memory 81 | ret 82 | 83 | ;-------------------------------------------------------------------- 84 | ; 85 | ; Handler for VBlank interrupt. 86 | ; Called every frame, resets SCX to zero. 87 | ; 88 | ;-------------------------------------------------------------------- 89 | endFrame:: 90 | xor a ; Set A to zero 91 | ld [rSCX], a ; And load it into SCX 92 | ld a, [hl] ; Load initial BGP from RAM 93 | ld [rBGP], a ; And into the BGP register 94 | 95 | dec b 96 | jr nz, .skip 97 | 98 | ld b, b 99 | 100 | .skip: 101 | ret 102 | 103 | ;-------------------------------------------------------------------- 104 | ; 105 | ; Loads Tile 0 with a test pattern and clears 106 | ; the entire background with Tile 0. 107 | ; 108 | ; Destroys: AF, HL, C, DE 109 | ; 110 | ;-------------------------------------------------------------------- 111 | LoadTilesBG:: 112 | ld c, $BB ; Load C with tile pattern 113 | ld hl, $8000 ; Load HL with base pointer for tileset 114 | ld de, $0010 ; Load DE with $10 (byte count for one tile) 115 | call memfill16 ; Fill tile 0 memory with pattern 116 | 117 | ld c, $00 ; Load C with zero 118 | ld hl, $9800 ; Load HL with base for background tilemap 119 | ld de, $0800 ; Load DE with byte count for background 120 | call memfill16 ; Fill background map with tile 0 121 | ret 122 | 123 | ;-------------------------------------------------------------------- 124 | ; 125 | ; Fills all bytes in a memory region with a certain value. 126 | ; - HL > Destination base pointer 127 | ; - DE > Amount of bytes to write 128 | ; - C > Byte to write 129 | ; 130 | ; Destroys: AF, HL, DE 131 | ; 132 | ;-------------------------------------------------------------------- 133 | memfill16:: 134 | .memfill16Loop 135 | ld a,c ; Load C into accumulator for memory writes 136 | ld [hli], a ; Load memory at HL and increment pointer 137 | dec de ; Decrement byte counter 138 | ld a,e ; Load A with lower nibble of byte counter 139 | and e ; Set zero flag if lower nibble of byte counter is 0 140 | jr nz, .memfill16Loop ; Restart memory load process if lower nibble != 0 141 | ld a,d ; Load A with higher nibble of byte counter 142 | and d ; Set zero flag if higher nibble of byte counter is 0 143 | jr nz, .memfill16Loop ; Restart memory load process if higher nibble != 0 144 | ret 145 | 146 | ;-------------------------------------------------------------------- 147 | ; 148 | ; Waits for the next VBlank period and stops LCD. 149 | ; 150 | ; Destroys: AF 151 | ; 152 | ;-------------------------------------------------------------------- 153 | StopLCD:: 154 | call WaitVBlank ; Wait for VBlank 155 | xor a ; Set A to 0 156 | ld [rLCDC], a ; Load 0 to LCDC 157 | ret 158 | 159 | ;-------------------------------------------------------------------- 160 | ; 161 | ; Pauses operation until the next VBlank period. 162 | ; 163 | ; Destroys: AF 164 | ; 165 | ;-------------------------------------------------------------------- 166 | WaitVBlank:: 167 | .vblLoop 168 | ld a, [rLY] ; Load current LY into A 169 | cp 144 ; Check if scanline is 144 (VBlank) 170 | jr nz, .vblLoop ; If not, repeat 171 | ret 172 | -------------------------------------------------------------------------------- /lycscy/src/lycscy.sm83: -------------------------------------------------------------------------------- 1 | include "inc/gbhw.inc" 2 | 3 | ;-------------------------------------------------------------------- 4 | ; 5 | ; Interrupt Handlers 6 | ; 7 | ;-------------------------------------------------------------------- 8 | section "VBlank", rom0[$0040] 9 | call endFrame 10 | reti 11 | section "LCDC", rom0[$0048] 12 | call startScanline 13 | reti 14 | section "TimerOverflow", rom0[$0050] 15 | reti 16 | section "Serial", rom0[$0058] 17 | reti 18 | section "Joypad", rom0[$0060] 19 | reti 20 | 21 | ;-------------------------------------------------------------------- 22 | ; 23 | ; Entry point of the program, disables interrupts and 24 | ; continues to the main code section. 25 | ; 26 | ;-------------------------------------------------------------------- 27 | section "EntryPoint", rom0[$100] 28 | di 29 | jp main 30 | 31 | ;-------------------------------------------------------------------- 32 | ; 33 | ; Main portion of the ROM containing the actual code 34 | ; 35 | ;-------------------------------------------------------------------- 36 | section "GameCode", rom0[$150] 37 | 38 | ;-------------------------------------------------------------------- 39 | ; 40 | ; Main function of the program called in the entry point 41 | ; 42 | ;-------------------------------------------------------------------- 43 | main:: 44 | call StopLCD ; Stop LCD 45 | call LoadTilesBG ; Load background tiles 46 | 47 | ld a, %11100100 ; Initialize BGP 48 | ld [rBGP], a 49 | 50 | ld a, $03 ; Allow only VBlank & LCD STAT interrupts 51 | ld [rIE], a 52 | ld a, $47 ; Enable LYC=LY STAT interrupts 53 | ld [rSTAT], a 54 | ld a, $00 ; Set initial LYC to $00 55 | ld [rLYC], a 56 | 57 | ld a, %10010001 ; Enable LCD & background tilemap $8000 58 | ld [rLCDC], a 59 | 60 | ei ; Enable Interrupts 61 | 62 | ld b, 10 63 | 64 | .lockup ; Prevent PC from going to crazy places 65 | halt 66 | jr .lockup 67 | 68 | ;-------------------------------------------------------------------- 69 | ; 70 | ; Handler for LCD STAT interrupt. 71 | ; Called every scanline, increments SCY and LYC by 8. 72 | ; 73 | ;-------------------------------------------------------------------- 74 | startScanline:: 75 | ld a, [rSCY] ; Subtract 8 from SCY 76 | sub a, $08 77 | ld [rSCY], a 78 | 79 | ld a, [rLYC] ; Set next LYC 80 | add a, $08 81 | ld [rLYC], a 82 | ret 83 | 84 | ;-------------------------------------------------------------------- 85 | ; 86 | ; Handler for VBlank interrupt. 87 | ; Called every frame, resets SCY and LYC to zero. 88 | ; 89 | ;-------------------------------------------------------------------- 90 | endFrame:: 91 | ld a, $00 ; Reload LYC 92 | ld [rLYC], a 93 | xor a ; Reload SCY 94 | ld [rSCY], a 95 | 96 | dec b 97 | jr nz, .skip 98 | 99 | ld b, b 100 | 101 | .skip: 102 | ret 103 | 104 | ;-------------------------------------------------------------------- 105 | ; 106 | ; Loads Tiles 00 - 0F with fancy line pattern tiles and sets 107 | ; the background to those tiles, switching the tile every row 108 | ; of tiles. 109 | ; 110 | ; Destroys: AF, HL, C, DE 111 | ; 112 | ;-------------------------------------------------------------------- 113 | LoadTilesBG:: 114 | ld c, $FF ; Load C with tile pattern 115 | ld hl, $8000 ; Load HL with base pointer for tileset 116 | 117 | .tileLoadLoop 118 | ld de, $0010 ; Load DE with $10 (byte count for one tile) 119 | call memfill16 ; Fill tile 0 memory with pattern 120 | ld a, c ; Subtract $11 from tile pattern 121 | and c ; Check if tile data is 0 122 | jr z, .breakTileLoad ; If so, break loop 123 | sub $11 ; Otherwise subtract $11 124 | ld c, a ; Load value from A into C 125 | jr .tileLoadLoop ; And repeat 126 | 127 | .breakTileLoad 128 | ld c, $00 ; Load C with zero 129 | ld hl, $9800 ; Load HL with base for background tilemap 130 | 131 | .bgLoadLoop 132 | ld de, $0040 ; Load DE with byte count for background row 133 | call memfill16 ; Fill background map with tile 0 134 | ld a, c ; A with value from C 135 | inc a ; Increment A by one 136 | and $0F ; And limit result to lower 4 bits 137 | ld c, a ; Load value from A into C 138 | ld a, h ; Load upper byte of last written address into A 139 | cp $9C ; And compare to $9C (end of tilemap) 140 | ret z ; If end has been reached, return 141 | jr .bgLoadLoop ; Otherwise repeat 142 | ret 143 | 144 | ;-------------------------------------------------------------------- 145 | ; 146 | ; Fills all bytes in a memory region with a certain value. 147 | ; - HL > Destination base pointer 148 | ; - DE > Amount of bytes to write 149 | ; - C > Byte to write 150 | ; 151 | ; Destroys: AF, HL, DE 152 | ; 153 | ;-------------------------------------------------------------------- 154 | memfill16:: 155 | .memfill16Loop 156 | ld a,c ; Load C into accumulator for memory writes 157 | ld [hli], a ; Load memory at HL and increment pointer 158 | dec de ; Decrement byte counter 159 | ld a,e ; Load A with lower nibble of byte counter 160 | and e ; Set zero flag if lower nibble of byte counter is 0 161 | jr nz, .memfill16Loop ; Restart memory load process if lower nibble != 0 162 | ld a,d ; Load A with higher nibble of byte counter 163 | and d ; Set zero flag if higher nibble of byte counter is 0 164 | jr nz, .memfill16Loop ; Restart memory load process if higher nibble != 0 165 | ret 166 | 167 | ;-------------------------------------------------------------------- 168 | ; 169 | ; Waits for the next VBlank period and stops LCD. 170 | ; 171 | ; Destroys: AF 172 | ; 173 | ;-------------------------------------------------------------------- 174 | StopLCD:: 175 | call WaitVBlank ; Wait for VBlank 176 | xor a ; Set A to 0 177 | ld [rLCDC], a ; Load 0 to LCDC 178 | ret 179 | 180 | ;-------------------------------------------------------------------- 181 | ; 182 | ; Pauses operation until the next VBlank period. 183 | ; 184 | ; Destroys: AF 185 | ; 186 | ;-------------------------------------------------------------------- 187 | WaitVBlank:: 188 | .vblLoop 189 | ld a, [rLY] ; Load current LY into A 190 | cp 144 ; Check if scanline is 144 (VBlank) 191 | jr nz, .vblLoop ; If not, repeat 192 | ret 193 | -------------------------------------------------------------------------------- /fairylake/src/fairylake.sm83: -------------------------------------------------------------------------------- 1 | include "inc/gbhw.inc" 2 | 3 | ;-------------------------------------------------------------------- 4 | ; 5 | ; Interrupt Handlers 6 | ; 7 | ;-------------------------------------------------------------------- 8 | section "VBlank", rom0[$0040] 9 | jp HandleVBlank 10 | section "LCDC", rom0[$0048] 11 | jp HandleStat 12 | section "TimerOverflow", rom0[$0050] 13 | reti 14 | section "Serial", rom0[$0058] 15 | reti 16 | section "Joypad", rom0[$0060] 17 | reti 18 | 19 | ;-------------------------------------------------------------------- 20 | ; 21 | ; Entry point of the program, disables interrupts and 22 | ; continues to the main code section. 23 | ; 24 | ;-------------------------------------------------------------------- 25 | section "EntryPoint", rom0[$100] 26 | di 27 | jp Main 28 | 29 | ;-------------------------------------------------------------------- 30 | ; 31 | ; Main portion of the ROM containing the actual code 32 | ; 33 | ;-------------------------------------------------------------------- 34 | section "GameCode", rom0[$150] 35 | 36 | ;-------------------------------------------------------------------- 37 | ; 38 | ; Main function of the program called in the entry point 39 | ; 40 | ;-------------------------------------------------------------------- 41 | Main:: 42 | call StopLCD ; Stop LCD 43 | call LoadBackground ; Load BG data into VRAM 44 | 45 | ld hl, $C000 ; Initialize RAM 46 | ld a, 8 ; Load A with size of used RAM + 1 47 | ld b, a 48 | xor a 49 | .ramInitLoop 50 | ld [hli], a 51 | dec b 52 | jr nz, .ramInitLoop 53 | 54 | ld a, %11100100 ; Initialize BGP 55 | ld [rBGP], a 56 | ld a, %00100100 ; Initialize OBP0 57 | ld [rOBP0], a 58 | ld a, %01000111 ; Initialize STAT 59 | ld [rSTAT], a 60 | ld a, 96 ; Initialize WY 61 | ld [rWY], a 62 | ld a, 7 ; Initialize WX 63 | ld [rWX], a 64 | xor a ; Initialize LYC 65 | ld [rLYC], a 66 | ld [rIF], a ; Clear IF 67 | ld a, %00000011 ; Initialize IE 68 | ld [rIE], a 69 | ei 70 | ld a, %11010011 ; Restart LCD 71 | ld [rLCDC], a 72 | 73 | .lockup ; Prevent PC from going to crazy places 74 | halt 75 | jr .lockup 76 | 77 | ;-------------------------------------------------------------------- 78 | ; 79 | ; VBlank interrupt handler 80 | ; 81 | ;-------------------------------------------------------------------- 82 | HandleVBlank:: 83 | ld hl, $C005 ; Update Cloud Scroll value 84 | inc [hl] 85 | ld a, 3 86 | cp a, [hl] 87 | jr z, .doCloudScroll 88 | jr .postCloudScroll 89 | .doCloudScroll 90 | xor a 91 | ld [hl], a 92 | ld hl, $C000 93 | inc [hl] 94 | .postCloudScroll 95 | 96 | ld hl, $C006 97 | inc [hl] 98 | ld a, [hl] 99 | cp 7 100 | jr nz, .skipReload 101 | ld a, [$C007] 102 | and a 103 | jr nz, .loadDecrRipple 104 | inc a 105 | ld [$C007], a 106 | jr .endModeSwap 107 | .loadDecrRipple 108 | xor a 109 | ld [$C007], a 110 | jr .endModeSwap 111 | .endModeSwap 112 | xor a 113 | ld [hl], a 114 | .skipReload 115 | sla a 116 | sla a 117 | ld h, $FE 118 | ld l, a 119 | ld a, [$C007] 120 | and a 121 | jr nz, .incrRipple 122 | dec [hl] 123 | jr .endRipple 124 | .incrRipple 125 | inc [hl] 126 | jr .endRipple 127 | .endRipple 128 | 129 | reti 130 | 131 | ;-------------------------------------------------------------------- 132 | ; 133 | ; STAT interrupt handler 134 | ; 135 | ;-------------------------------------------------------------------- 136 | HandleStat:: 137 | ld a, [rLYC] 138 | cp 0 139 | jr z, .scxNullTop 140 | cp 8 141 | jr z, .cloudScroll 142 | cp 32 143 | jp z, .heatlineWave 144 | cp 48 145 | jr z, .scxNullMid 146 | cp 63 147 | jr z, .waterBgpChange 148 | cp 64 149 | jr z, .slowWater 150 | cp 72 151 | jr z, .midWater 152 | cp 88 153 | jr z, .fastWater 154 | cp 96 155 | jr z, .enableWindow 156 | cp 103 157 | jr z, .disableWindow 158 | .scxNullTop 159 | xor a 160 | ld [rSCX], a 161 | ld a, 8 162 | ld [rLYC], a 163 | reti 164 | .cloudScroll 165 | ld a, [$C000] 166 | ld [rSCX], a 167 | ld a, 32 168 | ld [rLYC], a 169 | reti 170 | .heatlineWave 171 | xor a 172 | ld [rSCX], a 173 | ld a, 48 174 | ld [rLYC], a 175 | reti 176 | .scxNullMid 177 | xor a 178 | ld [rSCX], a 179 | ld a, 63 180 | ld [rLYC], a 181 | reti 182 | .waterBgpChange 183 | ld a, [rSTAT] 184 | and 2 185 | jr z, .actualWaterBgpChange 186 | ld a, %01001111 187 | ld [rSTAT], a 188 | .actualWaterBgpChange 189 | ld a, %11100101 190 | ld [rBGP], a 191 | ld a, %01000111 192 | ld [rSTAT], a 193 | ld a, 64 194 | ld [rLYC], a 195 | reti 196 | .slowWater 197 | ld a, 72 198 | ld [rLYC], a 199 | reti 200 | .midWater 201 | ld a, 88 202 | ld [rLYC], a 203 | reti 204 | .fastWater 205 | ld a, 96 206 | ld [rLYC], a 207 | reti 208 | .enableWindow 209 | ld a, %11110011 210 | ld [rLCDC], a 211 | ld a, 103 212 | ld [rLYC], a 213 | reti 214 | .disableWindow 215 | ld a, [rSTAT] 216 | and %00001000 217 | jr nz, .actualWindowDisable 218 | ld a, %01001111 219 | ld [rSTAT], a 220 | reti 221 | .actualWindowDisable 222 | ld a, %11010011 223 | ld [rLCDC], a 224 | ld a, %01000111 225 | ld [rSTAT], a 226 | ld a, %11100100 227 | ld [rBGP], a 228 | xor a 229 | ld [rSCX], a 230 | ld [rLYC], a 231 | reti 232 | 233 | ;-------------------------------------------------------------------- 234 | ; 235 | ; Copies the BGMap sections into VRAM 236 | ; 237 | ;-------------------------------------------------------------------- 238 | LoadBackground:: 239 | ld hl, $8000 240 | ld de, BGTiles 241 | ld bc, BGTilesEnd - BGTiles 242 | call memcpy 243 | 244 | ld hl, $9800 245 | ld de, BGMap 246 | ld bc, BGMapEnd - BGMap 247 | call memcpy 248 | 249 | ld hl, $9C00 250 | ld de, WindowMap 251 | ld bc, WindowMapEnd - WindowMap 252 | call memcpy 253 | 254 | ld hl, $FE00 255 | ld de, InitOAM 256 | ld bc, InitOAMEnd - InitOAM 257 | call memcpy 258 | 259 | ret 260 | 261 | ;-------------------------------------------------------------------- 262 | ; 263 | ; Copies BC amount of bytes from DE and following to HL and following 264 | ; 265 | ;-------------------------------------------------------------------- 266 | memcpy:: 267 | .memcpyLoop 268 | ld a, [de] 269 | ld [hli], a 270 | inc de 271 | dec bc 272 | ld a, b 273 | or c 274 | jr nz, .memcpyLoop 275 | ret 276 | 277 | ;-------------------------------------------------------------------- 278 | ; 279 | ; Waits for the next VBlank period and stops LCD. 280 | ; 281 | ; Destroys: AF 282 | ; 283 | ;-------------------------------------------------------------------- 284 | StopLCD:: 285 | call WaitVBlank ; Wait for VBlank 286 | xor a ; Set A to 0 287 | ld [rLCDC], a ; Load 0 to LCDC 288 | ret 289 | 290 | ;-------------------------------------------------------------------- 291 | ; 292 | ; Pauses operation until the next VBlank period. 293 | ; 294 | ; Destroys: AF 295 | ; 296 | ;-------------------------------------------------------------------- 297 | WaitVBlank:: 298 | .vblLoop 299 | ld a, [rLY] ; Load current LY into A 300 | cp 144 ; Check if scanline is 144 (VBlank) 301 | jr nz, .vblLoop ; If not, repeat 302 | ret 303 | 304 | ;-------------------------------------------------------------------- 305 | ; 306 | ; Background Memory 307 | ; 308 | ;-------------------------------------------------------------------- 309 | section "BGTiles", rom0 310 | BGTiles: 311 | incbin "inc/bgtiles.bin" 312 | BGTilesEnd: 313 | 314 | section "BGMap", rom0 315 | BGMap: 316 | incbin "inc/bgmap.bin" 317 | BGMapEnd: 318 | 319 | section "WindowMap", rom0 320 | WindowMap: 321 | incbin "inc/wdmap.bin" 322 | WindowMapEnd: 323 | 324 | ;-------------------------------------------------------------------- 325 | ; 326 | ; OAM Memory 327 | ; 328 | ;-------------------------------------------------------------------- 329 | section "InitOAM", rom0 330 | InitOAM: 331 | incbin "inc/initoam.bin" 332 | InitOAMEnd: -------------------------------------------------------------------------------- /winpos/src/winpos.sm83: -------------------------------------------------------------------------------- 1 | include "inc/hardware.inc" 2 | 3 | ;-------------------------------------------------------------------- 4 | ; # RAM MAP # 5 | ; $C000 - WX Value 6 | ; $C001 - WY Value 7 | ; $C002 - Joypad Cooldown 8 | ;-------------------------------------------------------------------- 9 | 10 | section "VBlank", rom0[$0040] 11 | jp HandleVBlank 12 | section "LCDC", rom0[$0048] 13 | reti 14 | section "TimerOverflow", rom0[$0050] 15 | reti 16 | section "Serial", rom0[$0058] 17 | reti 18 | section "Joypad", rom0[$0060] 19 | reti 20 | 21 | 22 | 23 | section "EntryPoint", rom0[$100] 24 | di 25 | jp Main 26 | 27 | 28 | 29 | section "GameCode", rom0[$150] 30 | ;-------------------------------------------------------------------- 31 | ; Main Function of the Test 32 | ;-------------------------------------------------------------------- 33 | Main:: 34 | call StopLCD ; Stop LCD to load VRAM 35 | call Initialize ; Load VRAM, initialize regs 36 | 37 | MainLoop: 38 | halt 39 | jr MainLoop 40 | 41 | ;-------------------------------------------------------------------- 42 | ; VBlank Handler 43 | ;-------------------------------------------------------------------- 44 | HandleVBlank:: 45 | call PrintRegs ; Update register display 46 | 47 | ld a, [$C000] 48 | ld [rWX], a 49 | ld a, [$C001] 50 | ld [rWY], a 51 | 52 | ld a, [$C002] ; Load Joypad Lock counter 53 | and a ; Set zero flag if 0 54 | jp z, .skipCooldown ; If zero, skip cooldown 55 | dec a ; Decrement A by one 56 | ld [$C002], a ; Load A into Joypad Lock RAM 57 | reti ; And wait for next VBlank 58 | .skipCooldown 59 | 60 | ld a, %11101111 ; Check direction keys 61 | ld [rP1], a ; Load multiplexer value 62 | ld a, [rP1] ; Load button states 63 | 64 | ; Joypad RIGHT 65 | bit 0, a ; Check if Right pressed 66 | jr nz, .rightNotPressed ; If not, skip 67 | ld a, [$C000] ; Load WX into A 68 | inc a ; Increment A 69 | ld [$C000], a ; Load A into WX RAM 70 | ld a, $05 ; Load A with Joypad Lock 71 | ld [$C002], a ; And load into RAM 72 | reti ; And wait for next VBlank 73 | .rightNotPressed 74 | 75 | ; Joypad LEFT 76 | bit 1, a ; Check if Left pressed 77 | jr nz, .leftNotPressed ; If not, skip 78 | ld a, [$C000] ; Load WX into A 79 | dec a ; Decrement A 80 | ld [$C000], a ; Load A into WX RAM 81 | ld a, $05 ; Load A with Joypad Lock 82 | ld [$C002], a ; And load into RAM 83 | reti ; And wait for next VBlank 84 | .leftNotPressed 85 | 86 | ; Joypad UP 87 | bit 2, a ; Check if Up pressed 88 | jr nz, .upNotPressed ; If not, skip 89 | ld a, [$C001] ; Load WY into A 90 | dec a ; Decrement A 91 | ld [$C001], a ; Load A into WY RAM 92 | ld a, $05 ; Load A with Joypad Lock 93 | ld [$C002], a ; And load into RAM 94 | reti ; And wait for next VBlank 95 | .upNotPressed 96 | 97 | bit 3, a ; Check if Down pressed 98 | jr nz, .downNotPressed ; If not, skip 99 | 100 | ; Joypad DOWN 101 | ld a, [$C001] ; Load WY into A 102 | inc a ; Increment A 103 | ld [$C001], a ; Load A into WY RAM 104 | ld a, $05 ; Load A with Joypad Lock 105 | ld [$C002], a ; And load into RAM 106 | reti ; And wait for next VBlank 107 | .downNotPressed 108 | 109 | reti 110 | 111 | ;-------------------------------------------------------------------- 112 | ; Initializes Registers for Test 113 | ;-------------------------------------------------------------------- 114 | Initialize:: 115 | call InitRAM ; Initialize RAM with $00 116 | call LoadFont ; Load font tiles into VRAM 117 | call LoadGraphics ; Load graphic tiles into VRAM 118 | call InitOAM ; Initialize OAM 119 | 120 | xor a ; Load A with base WY 121 | ld [$C001], a ; Load into WY RAM 122 | ld [rWY], a ; And into WY register 123 | 124 | ld a, $07 ; Load A with base WX 125 | ld [$C000], a ; Load into WX RAM 126 | ld [rWX], a ; And into WX register 127 | call PrintRegs ; and print to screen 128 | 129 | ld a, %11100100 ; Initialize BGP 130 | ld [rBGP], a 131 | 132 | ld a, $01 ; Allow only VBlank IRQs 133 | ld [rIE], a 134 | xor a ; Clear any remaining IRQs 135 | ld [rIF], a 136 | ei ; Enable interrupts 137 | 138 | ld [rSCY], a ; Initialize SCY 139 | ld [rSCX], a ; Initialize SCX 140 | ld [rNR52], a ; Turn off sound 141 | ld [rSTAT], a ; Disable all STAT triggers 142 | 143 | ld a, %11100011 ; Enable LCD, Background, Sprites and Window 144 | ld [rLCDC], a 145 | 146 | ret 147 | 148 | ;-------------------------------------------------------------------- 149 | ; Initializes OAM with all values for displaying stuff 150 | ;-------------------------------------------------------------------- 151 | InitOAM:: 152 | call ClearOAM ; Clear OAM of residue sprites 153 | ld hl, $FE00 ; Set OAM base pointer 154 | 155 | ld a, $FF ; Load all-black 156 | ld [rOBP0], a ; Into OBP0 157 | 158 | ; Load chars as sprites into OAM 159 | ld bc, $1109 160 | ld d, "0" 161 | call LoadCharSprite 162 | ld bc, $1111 163 | ld d, "7" 164 | call LoadCharSprite 165 | ld bc, $1119 166 | ld d, "/" 167 | call LoadCharSprite 168 | ld bc, $1121 169 | ld d, "0" 170 | call LoadCharSprite 171 | ld bc, $1129 172 | ld d, "0" 173 | call LoadCharSprite 174 | 175 | ret 176 | 177 | ;-------------------------------------------------------------------- 178 | ; Loads a new OAM char sprite based on the given input 179 | ; 180 | ; Inputs: 181 | ; - B : Y-Position 182 | ; - C : X-Position 183 | ; - D : Character to draw 184 | ;-------------------------------------------------------------------- 185 | LoadCharSprite:: 186 | ld a, b ; Load Y Value 187 | ld [hli], a ; Into OAM 188 | ld a, c ; Load X Value 189 | ld [hli], a ; Into OAM 190 | ld a, d ; Load tile number 191 | ld [hli], a ; Into OAM 192 | xor a ; Set A to 0 193 | ld [hli], a ; Load as sprite flags 194 | ret 195 | 196 | ;-------------------------------------------------------------------- 197 | ; Initializes OAM with zero 198 | ;-------------------------------------------------------------------- 199 | ClearOAM:: 200 | ld hl, $FE00 ; Load OAM base pointer 201 | .clearOAM 202 | xor a ; Set A to 0 203 | ld [hli], a ; Load into HL++ 204 | ld a, l ; Check lower address byte 205 | cp $A0 ; For $A0 (end of OAM) 206 | jr nz, .clearOAM ; If not, repeat 207 | ret 208 | 209 | ;-------------------------------------------------------------------- 210 | ; Prints the values at $C000 and $C001 to the screen. 211 | ; 212 | ; Inputs: 213 | ; - [$C000] : WX 214 | ; - [$C001] : WY 215 | ;-------------------------------------------------------------------- 216 | PrintRegs:: 217 | ld a, [$C000] 218 | call AtoASCII 219 | ld a, d 220 | ld [$FE02], a 221 | ld a, e 222 | ld [$FE06], a 223 | 224 | ld a, [$C001] 225 | call AtoASCII 226 | ld a, d 227 | ld [$FE0E], a 228 | ld a, e 229 | ld [$FE12], a 230 | ret 231 | 232 | ;-------------------------------------------------------------------- 233 | ; Converts the value in A reg to two hex ASCII bytes 234 | ; 235 | ; Inputs: 236 | ; - A : Value to convert 237 | ; 238 | ; Outputs: 239 | ; - DE : ASCII bytes 240 | ; 241 | ; Source: 242 | ; https://stackoverflow.com/questions/22838444/convert-an-8bit-number-to-hex-in-z80-assembler 243 | ;-------------------------------------------------------------------- 244 | AtoASCII:: 245 | ld c, a 246 | call .num1 247 | ld d, a 248 | ld a, c 249 | call .num2 250 | ld e, a 251 | ret 252 | .num1 253 | rra 254 | rra 255 | rra 256 | rra 257 | .num2 258 | or $F0 259 | daa 260 | add a, $A0 261 | adc a, $40 262 | ret 263 | 264 | ;-------------------------------------------------------------------- 265 | ; Initializes RAM $C000-$CFFF with zero 266 | ;-------------------------------------------------------------------- 267 | InitRAM:: 268 | ld hl, $C000 269 | .initByteRAM 270 | xor a 271 | ld [hli], a 272 | ld a, h 273 | cp $D0 274 | jr nz, .initByteRAM 275 | ret 276 | 277 | ;-------------------------------------------------------------------- 278 | ; Loads font tiles into VRAM 279 | ;-------------------------------------------------------------------- 280 | LoadFont:: 281 | ld hl, $8000 ; Tile Data starting address 282 | ld de, FontTiles ; ROM Tile Pointer 283 | ld bc, FontTilesEnd - FontTiles ; Tile Data byte count 284 | .copyFont 285 | ld a, [de] ; Load A with tile data byte 286 | ld [hli], a ; And load into VRAM 287 | inc de ; Go to next byte in ROM 288 | dec bc ; And decrement count 289 | ld a, b ; Load high byte of count 290 | or c ; And OR with high byte 291 | jr nz, .copyFont ; Repeat if count is not 0 292 | ret 293 | 294 | ;-------------------------------------------------------------------- 295 | ; Loads graphics tiles into VRAM 296 | ;-------------------------------------------------------------------- 297 | LoadGraphics:: 298 | 299 | ld hl, $9000 300 | ld de, Tileset 301 | ld bc, TilesetEnd - Tileset 302 | .copyTileset 303 | ld a, [de] ; Load A with tile data byte 304 | ld [hli], a ; And load into VRAM 305 | inc de ; Go to next byte in ROM 306 | dec bc ; And decrement count 307 | ld a, b ; Load high byte of count 308 | or c ; And OR with high byte 309 | jr nz, .copyTileset ; Repeat if count is not 0 310 | 311 | ld hl, $9800 312 | ld de, BackgroundTilemap 313 | ld bc, BackgroundTilemapEnd - BackgroundTilemap 314 | .copyBackgroundTilemap 315 | ld a, [de] ; Load A with tile data byte 316 | ld [hli], a ; And load into VRAM 317 | inc de ; Go to next byte in ROM 318 | dec bc ; And decrement count 319 | ld a, b ; Load high byte of count 320 | or c ; And OR with high byte 321 | jr nz, .copyBackgroundTilemap ; Repeat if count is not 0 322 | 323 | ld hl, $9C00 324 | ld de, WindowTilemap 325 | ld bc, WindowTilemapEnd - WindowTilemap 326 | .copyWindowTilemap 327 | ld a, [de] ; Load A with tile data byte 328 | ld [hli], a ; And load into VRAM 329 | inc de ; Go to next byte in ROM 330 | dec bc ; And decrement count 331 | ld a, b ; Load high byte of count 332 | or c ; And OR with high byte 333 | jr nz, .copyWindowTilemap ; Repeat if count is not 0 334 | 335 | ret 336 | 337 | ;-------------------------------------------------------------------- 338 | ; Waits for VBlank then stops LCD 339 | ;-------------------------------------------------------------------- 340 | StopLCD:: 341 | call WaitVBlank ; Wait for VBlank 342 | xor a ; Set A to 0 343 | ld [rLCDC], a ; Load 0 to LCDC 344 | ret 345 | 346 | ;-------------------------------------------------------------------- 347 | ; Waits for VBlank then returns 348 | ;-------------------------------------------------------------------- 349 | WaitVBlank:: 350 | .vblLoop 351 | ld a, [rLY] ; Load current LY into A 352 | cp 144 ; Check if scanline is 144 (VBlank) 353 | jr nz, .vblLoop ; If not, repeat 354 | ret 355 | 356 | ;-------------------------------------------------------------------- 357 | ; 358 | ; # DATA SECTION 359 | ; 360 | ;-------------------------------------------------------------------- 361 | 362 | ;-------------------------------------------------------------------- 363 | ; Tile Data 364 | ;-------------------------------------------------------------------- 365 | section "Tiles", rom0 366 | 367 | FontTiles: 368 | incbin "inc/font.chr" 369 | FontTilesEnd: 370 | 371 | Tileset: 372 | incbin "inc/tileset.bin" 373 | TilesetEnd: 374 | 375 | WindowTilemap: 376 | incbin "inc/window.bin" 377 | WindowTilemapEnd: 378 | 379 | BackgroundTilemap: 380 | incbin "inc/background.bin" 381 | BackgroundTilemapEnd: -------------------------------------------------------------------------------- /statcount/src/statcount-auto.sm83: -------------------------------------------------------------------------------- 1 | include "inc/hardware.inc" 2 | 3 | ;-------------------------------------------------------------------- 4 | ; # RAM MAP # 5 | ; $C000 - Last stored STAT value 6 | ; $C001 - NOP counter 7 | ; $C002 - Joypad Cooldown 8 | ;-------------------------------------------------------------------- 9 | 10 | section "VBlank", rom0[$0040] 11 | call endFrame 12 | reti 13 | section "LCDC", rom0[$0048] 14 | reti 15 | section "TimerOverflow", rom0[$0050] 16 | reti 17 | section "Serial", rom0[$0058] 18 | reti 19 | section "Joypad", rom0[$0060] 20 | reti 21 | 22 | 23 | 24 | section "EntryPoint", rom0[$100] 25 | di 26 | jp Main 27 | 28 | 29 | 30 | section "GameCode", rom0[$150] 31 | ;-------------------------------------------------------------------- 32 | ; Main Function of the Test 33 | ;-------------------------------------------------------------------- 34 | Main:: 35 | call StopLCD ; Stop LCD to load VRAM 36 | call InitTest ; Load VRAM, initialize regs 37 | call AutoTest ; Run all tests 38 | call CompareResults ; Process results 39 | 40 | ld a, b 41 | push af ; Store the result for later 42 | and a 43 | call z, TestPassed 44 | call nz, TestFailed 45 | 46 | ld a, %10000001 ; Enable LCD and Background 47 | ld [rLCDC], a 48 | 49 | ld a, 1 50 | ld [rIE], a ; Enable Vblank so we can know when 51 | ; the frame ends drawing this frame 52 | 53 | ei ; Enable interrupts 54 | 55 | pop af ; Get the results back 56 | ld b, 10 ; Loop for 10 frames before breakpoint 57 | 58 | MainLoop: 59 | halt 60 | jr MainLoop 61 | 62 | 63 | ;-------------------------------------------------------------------- 64 | ; 65 | ; Handler for VBlank interrupt. 66 | ; Called every frame, fire breakpoint to mark the end of the test 67 | ; 68 | ;-------------------------------------------------------------------- 69 | endFrame:: 70 | dec b 71 | jr nz, .skip 72 | 73 | ld b, b ; Fire a software breakpoint 74 | ; register `a` should have the number 75 | ; of wrong stats 76 | 77 | .skip: 78 | ret 79 | 80 | ;-------------------------------------------------------------------- 81 | ; Loads VRAM to display test fail message 82 | ;-------------------------------------------------------------------- 83 | TestFailed:: 84 | ld hl, $9821 85 | ld de, strFail 86 | call PrintStr 87 | 88 | ld bc, $9861 89 | ld hl, $C101 90 | 91 | .checkBytePrint 92 | ld a, [hli] ; Load next value from RAM 93 | and a ; And check if zero 94 | jr z, .skipPrint ; If it is, skip error print 95 | ld a, l ; Otherwise, load lower byte 96 | dec a ; Minus 1 97 | push bc 98 | call AtoASCII ; And convert to ASCII 99 | pop bc 100 | ld a, d ; Load first char 101 | ld [bc], a ; Write to VRAM 102 | inc bc ; And increment VRAM pointer 103 | ld a, e ; Load second char 104 | ld [bc], a ; Write to VRAM 105 | inc bc ; And increment VRAM pointer 106 | ld a, "," ; Load comma char 107 | ld [bc], a ; Write to VRAM 108 | inc bc ; And increment VRAM pointer 109 | ld a, c ; Load lower VRAM pointer byte 110 | and $13 ; Check if at end of line 111 | cp $13 ; Set zero-flag if so 112 | jr nz, .skipLinebreak ; Otherwise, skip linebreak 113 | ld a, c ; Load lower VRAM pointer byte 114 | add $0e ; And add $0E 115 | ld c, a ; Load back into pointer 116 | jr nc, .skipLinebreakOverflow ; Skip overflow if add caused no carry 117 | inc b ; Otherwise increment upper byte 118 | .skipLinebreakOverflow 119 | .skipLinebreak 120 | .skipPrint 121 | dec l ; Decrement lower RAM pointer byte 122 | inc l ; Set zero flag if value was zero 123 | jr nz, .checkBytePrint ; If not, check next byte 124 | 125 | dec c 126 | xor a 127 | ld [bc], a 128 | 129 | ret 130 | 131 | ;-------------------------------------------------------------------- 132 | ; Loads VRAM to display test pass message 133 | ;-------------------------------------------------------------------- 134 | TestPassed:: 135 | ld hl, $9821 136 | ld de, strPass 137 | call PrintStr 138 | ret 139 | 140 | ;-------------------------------------------------------------------- 141 | ; Compares the results stored in RAM at $C101 - $C1FF and overwrites 142 | ; them with $00 if they match. Non-matching results are overwritten 143 | ; with non-zero values. 144 | ;-------------------------------------------------------------------- 145 | CompareResults:: 146 | ld hl, $C101 ; Load RAM pointer 147 | ld de, StatTestData ; Load compare data pointer 148 | ld b, $00 ; Initialize error counter 149 | .compareByte 150 | ld a, [de] ; Load compare data into A 151 | xor [hl] ; XOR with value from RAM 152 | ld [hli], a ; Load result into RAM 153 | jr z, .skipFailInc ; If equal, skip B increment 154 | inc b ; Otherwise increment error counter 155 | .skipFailInc 156 | inc de ; Increment data pointer 157 | dec l ; Decrement L 158 | inc l ; And increment, setting Z if L==0 159 | jr nz, .compareByte ; If L != 0, compare another byte 160 | 161 | ret 162 | 163 | ;-------------------------------------------------------------------- 164 | ; Automatically tests with NOP values $01 - $FF and stores the 165 | ; results in RAM from $C101 - $C1FF 166 | ;-------------------------------------------------------------------- 167 | AutoTest:: 168 | ld hl, $C101 169 | ld a, $01 170 | 171 | .testIteration 172 | ld [$C001], a 173 | push hl 174 | call RunTest 175 | ld a, [$C000] 176 | pop hl 177 | ld [hli], a 178 | ld a, [$C001] 179 | inc a 180 | jp nz, .testIteration 181 | 182 | call StopLCD 183 | 184 | ret 185 | 186 | ;-------------------------------------------------------------------- 187 | ; Runs the test and updates values in RAM 188 | ;-------------------------------------------------------------------- 189 | RunTest:: 190 | call StopLCD ; Stop LCD while preparing test 191 | 192 | ld hl, nopBase ; Load clockslide base 193 | xor a ; Set A to 0 194 | ld d, a ; And load upper add byte 195 | ld a, [$C001] ; Load NOP count into A 196 | ld e, a ; Buffer NOP count in E 197 | ld a, $FF ; Set A to $FF 198 | sub e ; Subtract NOP count 199 | ld e, a ; Load lower add byte 200 | add hl, de ; Add clockslide offset to pointer 201 | 202 | ld c, $41 ; Load $41 for STAT read 203 | 204 | ld a, [$C001] ; Load NOP count into A 205 | cp 1 ; Check if running 1 NOP 206 | jr z, .singleNopTest ; If so, run different test routine 207 | 208 | ld a, %10000001 ; Enable LCD and Background 209 | ld [rLCDC], a 210 | 211 | jp hl ; Start clockslide NOPs 212 | 213 | .singleNopTest ; Skips JP HL, saving 1 NOP 214 | ld a, %10000001 ; Enable LCD and Background 215 | ld [rLCDC], a 216 | 217 | ld a, [$FF00+c] ; Acts as NOP before read 218 | ld [$C000], a ; Load STAT into memory 219 | ret 220 | 221 | ;-------------------------------------------------------------------- 222 | ; 253 NOPs followed by code to store STAT in RAM 223 | ; - 1 Cycle timeout by JP HL 224 | ; - 1 Cycle timeout by LD A, [$FF00+C] 225 | ; => 253 NOP instructions for 255 NOPs 226 | ; 227 | ; Prerequisite: 228 | ; - C must be loaded with $41 229 | ;-------------------------------------------------------------------- 230 | nopBase: 231 | REPT $FD 232 | nop 233 | ENDR 234 | ld a, [$FF00+c] ; Acts as NOP before read 235 | ld [$C000], a ; Load STAT into memory 236 | ret 237 | 238 | ;-------------------------------------------------------------------- 239 | ; Initializes Registers for Test 240 | ;-------------------------------------------------------------------- 241 | InitTest:: 242 | call InitRAM ; Initialize RAM with $00 243 | call LoadFont ; Load font tiles into VRAM 244 | 245 | ld a, $01 ; Load A with minimum NOPs, 246 | ld [$C001], a ; and load into NOP reg 247 | 248 | ld a, %11100100 ; Initialize BGP 249 | ld [rBGP], a 250 | ld [rLYC], a ; Disable LYC 251 | 252 | xor a ; Load A with 0 253 | ld [rSCY], a ; Initialize SCY 254 | ld [rSCX], a ; Initialize SCX 255 | ld [rNR52], a ; Turn off sound 256 | ld [rSTAT], a ; Disable all STAT triggers 257 | 258 | ld a, %10000001 ; Enable LCD and Background 259 | ld [rLCDC], a 260 | 261 | ret 262 | 263 | ;-------------------------------------------------------------------- 264 | ; Converts the value in A reg to two hex ASCII bytes 265 | ; 266 | ; Inputs: 267 | ; - A : Value to convert 268 | ; 269 | ; Outputs: 270 | ; - DE : ASCII bytes 271 | ; 272 | ; Source: 273 | ; https://stackoverflow.com/questions/22838444/convert-an-8bit-number-to-hex-in-z80-assembler 274 | ;-------------------------------------------------------------------- 275 | AtoASCII:: 276 | ld c, a 277 | call .num1 278 | ld d, a 279 | ld a, c 280 | call .num2 281 | ld e, a 282 | ret 283 | .num1 284 | rra 285 | rra 286 | rra 287 | rra 288 | .num2 289 | or $F0 290 | daa 291 | add a, $A0 292 | adc a, $40 293 | ret 294 | 295 | ;-------------------------------------------------------------------- 296 | ; Initializes RAM $C000-$CFFF with zero 297 | ;-------------------------------------------------------------------- 298 | InitRAM:: 299 | ld hl, $C000 300 | .initByteRAM 301 | xor a 302 | ld [hli], a 303 | ld a, h 304 | cp $D0 305 | jr nz, .initByteRAM 306 | ret 307 | 308 | ;-------------------------------------------------------------------- 309 | ; Loads font tiles into VRAM 310 | ;-------------------------------------------------------------------- 311 | LoadFont:: 312 | ld hl, $9000 ; Tile Data starting address 313 | ld de, FontTiles ; ROM Tile Pointer 314 | ld bc, FontTilesEnd - FontTiles ; Tile Data byte count 315 | .copyFont 316 | ld a, [de] ; Load A with tile data byte 317 | ld [hli], a ; And load into VRAM 318 | inc de ; Go to next byte in ROM 319 | dec bc ; And decrement count 320 | ld a, b ; Load high byte of count 321 | or c ; And OR with high byte 322 | jr nz, .copyFont ; Repeat if count is not 0 323 | ret 324 | 325 | ;-------------------------------------------------------------------- 326 | ; Copies tiles to display a given string to VRAM 327 | ; 328 | ; Inputs: 329 | ; - HL : Copy Destination 330 | ; - DE : String Pointer 331 | ;-------------------------------------------------------------------- 332 | PrintStr:: 333 | .copyString 334 | ld a, [de] ; Load string byte into A 335 | ld [hli], a ; And into VRAM 336 | inc de ; Increment string pointer 337 | and a ; And check if null byte 338 | jr nz, .copyString ; Repeat if not 339 | ret 340 | 341 | ;-------------------------------------------------------------------- 342 | ; Waits for VBlank then stops LCD 343 | ;-------------------------------------------------------------------- 344 | StopLCD:: 345 | call WaitVBlank ; Wait for VBlank 346 | xor a ; Set A to 0 347 | ld [rLCDC], a ; Load 0 to LCDC 348 | ret 349 | 350 | ;-------------------------------------------------------------------- 351 | ; Waits for VBlank then returns 352 | ;-------------------------------------------------------------------- 353 | WaitVBlank:: 354 | .vblLoop 355 | ld a, [rLY] ; Load current LY into A 356 | cp 144 ; Check if scanline is 144 (VBlank) 357 | jr nz, .vblLoop ; If not, repeat 358 | ret 359 | 360 | ;-------------------------------------------------------------------- 361 | ; 362 | ; # DATA SECTION 363 | ; 364 | ;-------------------------------------------------------------------- 365 | 366 | ;-------------------------------------------------------------------- 367 | ; Strings 368 | ;-------------------------------------------------------------------- 369 | section "Strings", rom0 370 | strPass: 371 | db "Test OK!", 0 372 | strFail: 373 | db "Test failed:", 0 374 | 375 | ;-------------------------------------------------------------------- 376 | ; STAT Tests 377 | ;-------------------------------------------------------------------- 378 | section "TestDataSTAT", rom0[$1000] 379 | StatTestData: 380 | 381 | ; Scanline 0 382 | REPT 18 383 | db $80 384 | ENDR 385 | REPT 43 386 | db $83 387 | ENDR 388 | REPT 51 389 | db $80 390 | ENDR 391 | 392 | ; Scanline 1 393 | REPT 20 394 | db $82 395 | ENDR 396 | REPT 43 397 | db $83 398 | ENDR 399 | REPT 51 400 | db $80 401 | ENDR 402 | 403 | ; Scanline 2 404 | REPT 20 405 | db $82 406 | ENDR 407 | REPT 9 ; Only 9 more to add up to 256 bytes of test data 408 | db $83 409 | ENDR 410 | 411 | ;-------------------------------------------------------------------- 412 | ; Font Tile Data 413 | ;-------------------------------------------------------------------- 414 | section "Font", rom0 415 | FontTiles: 416 | incbin "inc/font.chr" 417 | FontTilesEnd: 418 | -------------------------------------------------------------------------------- /lycscx/inc/gbhw.inc: -------------------------------------------------------------------------------- 1 | ;* 2 | ;* GBHW.INC - Gameboy Hardware definitions for GALP 3 | ;* 4 | ;* by GABY. Inspired from work done by Carsten Sorensen & others. 5 | ;* 6 | ;* V1.0 - The original version 7 | ;* 8 | 9 | ; If all of these are already defined, don't do it again. 10 | 11 | IF !DEF(HARDWARE_INC) 12 | HARDWARE_INC SET 1 13 | 14 | rev_Check_hardware_inc: MACRO 15 | ;NOTE: REVISION NUMBER CHANGES MUST BE ADDED 16 | ;TO SECOND PARAMETER IN FOLLOWING LINE. 17 | IF \1 > 1.0 ;PUT REVISION NUMBER HERE 18 | WARN "Version \1 or later of 'gbhw.inc' is required." 19 | ENDC 20 | ENDM 21 | 22 | _HW EQU $FF00 23 | 24 | _VRAM EQU $8000 ; $8000->$A000 25 | _SCRN0 EQU $9800 ; $9800->$9BFF 26 | _SCRN1 EQU $9C00 ; $9C00->$9FFF 27 | _RAM EQU $C000 ; $C000->$E000 28 | _HRAM EQU $F800 ; $F800->$FFFE 29 | _OAMRAM EQU $FE00 ; $FE00->$FE9F 30 | _AUD3WAVERAM EQU $FF30 ; $FF30->$FF3F 31 | 32 | 33 | ; -- 34 | ; -- OAM flags 35 | ; -- 36 | 37 | OAMF_PRI EQU %10000000 ; Priority 38 | OAMF_YFLIP EQU %01000000 ; Y flip 39 | OAMF_XFLIP EQU %00100000 ; X flip 40 | OAMF_PAL0 EQU %00000000 ; Palette number; 0,1 41 | OAMF_PAL1 EQU %00010000 ; Palette number; 0,1 42 | 43 | 44 | ;*************************************************************************** 45 | ;* 46 | ;* Custom registers 47 | ;* 48 | ;*************************************************************************** 49 | 50 | ; -- 51 | ; -- P1 ($FF00) 52 | ; -- Register for reading joy pad info. (R/W) 53 | ; -- 54 | rP1 EQU $FF00 55 | 56 | P1F_5 EQU %00100000 ; P15 out port 57 | P1F_4 EQU %00010000 ; P14 out port 58 | P1F_3 EQU %00001000 ; P13 in port 59 | P1F_2 EQU %00000100 ; P12 in port 60 | P1F_1 EQU %00000010 ; P11 in port 61 | P1F_0 EQU %00000001 ; P10 in port 62 | 63 | 64 | ; -- 65 | ; -- LCDC ($FF40) 66 | ; -- LCD Control (R/W) 67 | ; -- 68 | rLCDC EQU $FF40 69 | 70 | LCDCF_OFF EQU %00000000 ; LCD Control Operation 71 | LCDCF_ON EQU %10000000 ; LCD Control Operation 72 | LCDCF_WIN9800 EQU %00000000 ; Window Tile Map Display Select 73 | LCDCF_WIN9C00 EQU %01000000 ; Window Tile Map Display Select 74 | LCDCF_WINOFF EQU %00000000 ; Window Display 75 | LCDCF_WINON EQU %00100000 ; Window Display 76 | LCDCF_BG8800 EQU %00000000 ; BG & Window Tile Data Select 77 | LCDCF_BG8000 EQU %00010000 ; BG & Window Tile Data Select 78 | LCDCF_BG9800 EQU %00000000 ; BG Tile Map Display Select 79 | LCDCF_BG9C00 EQU %00001000 ; BG Tile Map Display Select 80 | LCDCF_OBJ8 EQU %00000000 ; OBJ Construction 81 | LCDCF_OBJ16 EQU %00000100 ; OBJ Construction 82 | LCDCF_OBJOFF EQU %00000000 ; OBJ Display 83 | LCDCF_OBJON EQU %00000010 ; OBJ Display 84 | LCDCF_BGOFF EQU %00000000 ; BG Display 85 | LCDCF_BGON EQU %00000001 ; BG Display 86 | ; "Window Character Data Select" follows BG 87 | 88 | 89 | ; -- 90 | ; -- STAT ($FF41) 91 | ; -- LCDC Status (R/W) 92 | ; -- 93 | rSTAT EQU $FF41 94 | 95 | STATF_LYC EQU %01000000 ; LYCEQULY Coincidence (Selectable) 96 | STATF_MODE10 EQU %00100000 ; Mode 10 97 | STATF_MODE01 EQU %00010000 ; Mode 01 (V-Blank) 98 | STATF_MODE00 EQU %00001000 ; Mode 00 (H-Blank) 99 | STATF_LYCF EQU %00000100 ; Coincidence Flag 100 | STATF_HB EQU %00000000 ; H-Blank 101 | STATF_VB EQU %00000001 ; V-Blank 102 | STATF_OAM EQU %00000010 ; OAM-RAM is used by system 103 | STATF_LCD EQU %00000011 ; Both OAM and VRAM used by system 104 | STATF_BUSY EQU %00000010 ; When set, VRAM access is unsafe 105 | 106 | 107 | ; -- 108 | ; -- SCY ($FF42) 109 | ; -- Scroll Y (R/W) 110 | ; -- 111 | rSCY EQU $FF42 112 | 113 | 114 | ; -- 115 | ; -- SCY ($FF43) 116 | ; -- Scroll X (R/W) 117 | ; -- 118 | rSCX EQU $FF43 119 | 120 | 121 | ; -- 122 | ; -- LY ($FF44) 123 | ; -- LCDC Y-Coordinate (R) 124 | ; -- 125 | ; -- Values range from 0->153. 144->153 is the VBlank period. 126 | ; -- 127 | rLY EQU $FF44 128 | 129 | 130 | ; -- 131 | ; -- LYC ($FF45) 132 | ; -- LY Compare (R/W) 133 | ; -- 134 | ; -- When LYEQUEQULYC, STATF_LYCF will be set in STAT 135 | ; -- 136 | rLYC EQU $FF45 137 | 138 | 139 | ; -- 140 | ; -- DMA ($FF46) 141 | ; -- DMA Transfer and Start Address (W) 142 | ; -- 143 | rDMA EQU $FF46 144 | 145 | 146 | ; -- 147 | ; -- BGP ($FF47) 148 | ; -- BG Palette Data (W) 149 | ; -- 150 | ; -- Bit 7-6 - Intensity for %11 151 | ; -- Bit 5-4 - Intensity for %10 152 | ; -- Bit 3-2 - Intensity for %01 153 | ; -- Bit 1-0 - Intensity for %00 154 | ; -- 155 | rBGP EQU $FF47 156 | 157 | 158 | ; -- 159 | ; -- OBP0 ($FF48) 160 | ; -- Object Palette 0 Data (W) 161 | ; -- 162 | ; -- See BGP for info 163 | ; -- 164 | rOBP0 EQU $FF48 165 | 166 | 167 | ; -- 168 | ; -- OBP1 ($FF49) 169 | ; -- Object Palette 1 Data (W) 170 | ; -- 171 | ; -- See BGP for info 172 | ; -- 173 | rOBP1 EQU $FF49 174 | 175 | 176 | ; -- 177 | ; -- SB ($FF01) 178 | ; -- Serial Transfer Data (R/W) 179 | ; -- 180 | rSB EQU $FF01 181 | 182 | ; -- 183 | ; -- SC ($FF02) 184 | ; -- Serial I/O Control (R/W) 185 | ; -- 186 | rSC EQU $FF02 187 | 188 | ; -- 189 | ; -- DIV ($FF04) 190 | ; -- Divider register (R/W) 191 | ; -- 192 | rDIV EQU $FF04 193 | 194 | 195 | ; -- 196 | ; -- TIMA ($FF05) 197 | ; -- Timer counter (R/W) 198 | ; -- 199 | rTIMA EQU $FF05 200 | 201 | 202 | ; -- 203 | ; -- TMA ($FF06) 204 | ; -- Timer modulo (R/W) 205 | ; -- 206 | rTMA EQU $FF06 207 | 208 | 209 | ; -- 210 | ; -- TAC ($FF07) 211 | ; -- Timer control (R/W) 212 | ; -- 213 | rTAC EQU $FF07 214 | 215 | TACF_START EQU %00000100 216 | TACF_STOP EQU %00000000 217 | TACF_4KHZ EQU %00000000 218 | TACF_16KHZ EQU %00000011 219 | TACF_65KHZ EQU %00000010 220 | TACF_262KHZ EQU %00000001 221 | 222 | 223 | ; -- 224 | ; -- IF ($FF0F) 225 | ; -- Interrupt Flag (R/W) 226 | ; -- 227 | ; -- IE ($FFFF) 228 | ; -- Interrupt Enable (R/W) 229 | ; -- 230 | rIF EQU $FF0F 231 | rIE EQU $FFFF 232 | 233 | IEF_HILO EQU %00010000 ; Transition from High to Low of Pin number P10-P13 234 | IEF_SERIAL EQU %00001000 ; Serial I/O transfer end 235 | IEF_TIMER EQU %00000100 ; Timer Overflow 236 | IEF_LCDC EQU %00000010 ; LCDC (see STAT) 237 | IEF_VBLANK EQU %00000001 ; V-Blank 238 | 239 | 240 | ; -- 241 | ; -- WY ($FF4A) 242 | ; -- Window Y Position (R/W) 243 | ; -- 244 | ; -- 0 SO2 ON/OFF (Vin??) 269 | ; -- Bit 6-4 - SO2 output level (volume) (# 0-7) 270 | ; -- Bit 3 - Vin->SO1 ON/OFF (Vin??) 271 | ; -- Bit 2-0 - SO1 output level (volume) (# 0-7) 272 | ; -- 273 | rNR50 EQU $FF24 274 | rAUDVOL EQU rNR50 275 | 276 | 277 | ; -- 278 | ; -- AUDTERM/NR51 ($FF25) 279 | ; -- Selection of Sound output terminal (R/W) 280 | ; -- 281 | ; -- Bit 7 - Output sound 4 to SO2 terminal 282 | ; -- Bit 6 - Output sound 3 to SO2 terminal 283 | ; -- Bit 5 - Output sound 2 to SO2 terminal 284 | ; -- Bit 4 - Output sound 1 to SO2 terminal 285 | ; -- Bit 3 - Output sound 4 to SO1 terminal 286 | ; -- Bit 2 - Output sound 3 to SO1 terminal 287 | ; -- Bit 1 - Output sound 2 to SO1 terminal 288 | ; -- Bit 0 - Output sound 0 to SO1 terminal 289 | ; -- 290 | rNR51 EQU $FF25 291 | rAUDTERM EQU rNR51 292 | 293 | 294 | ; -- 295 | ; -- AUDENA/NR52 ($FF26) 296 | ; -- Sound on/off (R/W) 297 | ; -- 298 | ; -- Bit 7 - All sound on/off (sets all audio regs to 0!) 299 | ; -- Bit 3 - Sound 4 ON flag (doesn't work!) 300 | ; -- Bit 2 - Sound 3 ON flag (doesn't work!) 301 | ; -- Bit 1 - Sound 2 ON flag (doesn't work!) 302 | ; -- Bit 0 - Sound 1 ON flag (doesn't work!) 303 | ; -- 304 | rNR52 EQU $FF26 305 | rAUDENA EQU rNR52 306 | 307 | 308 | ;*************************************************************************** 309 | ;* 310 | ;* SoundChannel #1 registers 311 | ;* 312 | ;*************************************************************************** 313 | 314 | ; -- 315 | ; -- AUD1SWEEP/NR10 ($FF10) 316 | ; -- Sweep register (R/W) 317 | ; -- 318 | ; -- Bit 6-4 - Sweep Time 319 | ; -- Bit 3 - Sweep Increase/Decrease 320 | ; -- 0: Addition (frequency increases???) 321 | ; -- 1: Subtraction (frequency increases???) 322 | ; -- Bit 2-0 - Number of sweep shift (# 0-7) 323 | ; -- Sweep Time: (n*7.8ms) 324 | ; -- 325 | rNR10 EQU $FF10 326 | rAUD1SWEEP EQU rNR10 327 | 328 | 329 | ; -- 330 | ; -- AUD1LEN/NR11 ($FF11) 331 | ; -- Sound length/Wave pattern duty (R/W) 332 | ; -- 333 | ; -- Bit 7-6 - Wave Pattern Duty (00:12.5% 01:25% 10:50% 11:75%) 334 | ; -- Bit 5-0 - Sound length data (# 0-63) 335 | ; -- 336 | rNR11 EQU $FF11 337 | rAUD1LEN EQU rNR11 338 | 339 | 340 | ; -- 341 | ; -- AUD1ENV/NR12 ($FF12) 342 | ; -- Envelope (R/W) 343 | ; -- 344 | ; -- Bit 7-4 - Initial value of envelope 345 | ; -- Bit 3 - Envelope UP/DOWN 346 | ; -- 0: Decrease 347 | ; -- 1: Range of increase 348 | ; -- Bit 2-0 - Number of envelope sweep (# 0-7) 349 | ; -- 350 | rNR12 EQU $FF12 351 | rAUD1ENV EQU rNR12 352 | 353 | 354 | ; -- 355 | ; -- AUD1LOW/NR13 ($FF13) 356 | ; -- Frequency lo (W) 357 | ; -- 358 | rNR13 EQU $FF13 359 | rAUD1LOW EQU rNR13 360 | 361 | 362 | ; -- 363 | ; -- AUD1HIGH/NR14 ($FF14) 364 | ; -- Frequency hi (W) 365 | ; -- 366 | ; -- Bit 7 - Initial (when set, sound restarts) 367 | ; -- Bit 6 - Counter/consecutive selection 368 | ; -- Bit 2-0 - Frequency's higher 3 bits 369 | ; -- 370 | rNR14 EQU $FF14 371 | rAUD1HIGH EQU rNR14 372 | 373 | 374 | ;*************************************************************************** 375 | ;* 376 | ;* SoundChannel #2 registers 377 | ;* 378 | ;*************************************************************************** 379 | 380 | ; -- 381 | ; -- AUD2LEN/NR21 ($FF16) 382 | ; -- Sound Length; Wave Pattern Duty (R/W) 383 | ; -- 384 | ; -- see AUD1LEN for info 385 | ; -- 386 | rNR21 EQU $FF16 387 | rAUD2LEN EQU rNR21 388 | 389 | 390 | ; -- 391 | ; -- AUD2ENV/NR22 ($FF17) 392 | ; -- Envelope (R/W) 393 | ; -- 394 | ; -- see AUD1ENV for info 395 | ; -- 396 | rNR22 EQU $FF17 397 | rAUD2ENV EQU rNR22 398 | 399 | 400 | ; -- 401 | ; -- AUD2LOW/NR23 ($FF18) 402 | ; -- Frequency lo (W) 403 | ; -- 404 | rNR23 EQU $FF18 405 | rAUD2LOW EQU rNR23 406 | 407 | 408 | ; -- 409 | ; -- AUD2HIGH/NR24 ($FF19) 410 | ; -- Frequency hi (W) 411 | ; -- 412 | ; -- see AUD1HIGH for info 413 | ; -- 414 | rNR24 EQU $FF19 415 | rAUD2HIGH EQU rNR24 416 | 417 | 418 | ;*************************************************************************** 419 | ;* 420 | ;* SoundChannel #3 registers 421 | ;* 422 | ;*************************************************************************** 423 | 424 | ; -- 425 | ; -- AUD3ENA/NR30 ($FF1A) 426 | ; -- Sound on/off (R/W) 427 | ; -- 428 | ; -- Bit 7 - Sound ON/OFF (1EQUON,0EQUOFF) 429 | ; -- 430 | rNR30 EQU $FF1A 431 | rAUD3ENA EQU rNR30 432 | 433 | 434 | ; -- 435 | ; -- AUD3LEN/NR31 ($FF1B) 436 | ; -- Sound length (R/W) 437 | ; -- 438 | ; -- Bit 7-0 - Sound length 439 | ; -- 440 | rNR31 EQU $FF1B 441 | rAUD3LEN EQU rNR31 442 | 443 | 444 | ; -- 445 | ; -- AUD3LEVEL/NR32 ($FF1C) 446 | ; -- Select output level 447 | ; -- 448 | ; -- Bit 6-5 - Select output level 449 | ; -- 00: 0/1 (mute) 450 | ; -- 01: 1/1 451 | ; -- 10: 1/2 452 | ; -- 11: 1/4 453 | ; -- 454 | rNR32 EQU $FF1C 455 | rAUD3LEVEL EQU rNR32 456 | 457 | 458 | ; -- 459 | ; -- AUD3LOW/NR33 ($FF1D) 460 | ; -- Frequency lo (W) 461 | ; -- 462 | ; -- see AUD1LOW for info 463 | ; -- 464 | rNR33 EQU $FF1D 465 | rAUD3LOW EQU rNR33 466 | 467 | 468 | ; -- 469 | ; -- AUD3HIGH/NR34 ($FF1E) 470 | ; -- Frequency hi (W) 471 | ; -- 472 | ; -- see AUD1HIGH for info 473 | ; -- 474 | rNR34 EQU $FF1E 475 | rAUD3HIGH EQU rNR34 476 | 477 | 478 | ; -- 479 | ; -- AUD4LEN/NR41 ($FF20) 480 | ; -- Sound length (R/W) 481 | ; -- 482 | ; -- Bit 5-0 - Sound length data (# 0-63) 483 | ; -- 484 | rNR41 EQU $FF20 485 | rAUD4LEN EQU rNR41 486 | 487 | 488 | ; -- 489 | ; -- AUD4ENV/NR42 ($FF21) 490 | ; -- Envelope (R/W) 491 | ; -- 492 | ; -- see AUD1ENV for info 493 | ; -- 494 | rNR42 EQU $FF21 495 | rAUD4ENV EQU rNR42 496 | 497 | 498 | ; -- 499 | ; -- AUD4POLY/NR42 ($FF22) 500 | ; -- Polynomial counter (R/W) 501 | ; -- 502 | ; -- Bit 7-4 - Selection of the shift clock frequency of the (scf) 503 | ; -- polynomial counter (0000-1101) 504 | ; -- freqEQUdrf*1/2^scf (not sure) 505 | ; -- Bit 3 - Selection of the polynomial counter's step 506 | ; -- 0: 15 steps 507 | ; -- 1: 7 steps 508 | ; -- Bit 2-0 - Selection of the dividing ratio of frequencies (drf) 509 | ; -- 000: f/4 001: f/8 010: f/16 011: f/24 510 | ; -- 100: f/32 101: f/40 110: f/48 111: f/56 (fEQU4.194304 Mhz) 511 | ; -- 512 | rNR42_2 EQU $FF22 513 | rAUD4POLY EQU rNR42_2 514 | 515 | 516 | ; -- 517 | ; -- AUD4GO/NR43 ($FF23) 518 | ; -- (has wrong name and value (ff30) in Dr.Pan's doc!) 519 | ; -- 520 | ; -- Bit 7 - Inital 521 | ; -- Bit 6 - Counter/consecutive selection 522 | ; -- 523 | rNR43 EQU $FF23 524 | rAUD4GO EQU rNR43 ; silly name! 525 | 526 | ;*************************************************************************** 527 | ;* 528 | ;* Cart related 529 | ;* 530 | ;*************************************************************************** 531 | 532 | ROM_NOMBC EQU 0 533 | ROM_MBC1 EQU 1 534 | ROM_MBC1_RAM EQU 2 535 | ROM_MBC1_RAM_BAT EQU 3 536 | ROM_MBC2 EQU 5 537 | ROM_MBC2_BAT EQU 6 538 | ROM_NOMBC_RAM EQU 8 539 | ROM_NOMBC_RAM_BAT EQU 9 540 | 541 | ROM_SIZE_256KBIT EQU 0 542 | ROM_SIZE_512KBIT EQU 1 543 | ROM_SIZE_1M EQU 2 544 | ROM_SIZE_2M EQU 3 545 | ROM_SIZE_4M EQU 4 546 | ROM_SIZE_8M EQU 5 547 | ROM_SIZE_16M EQU 6 548 | 549 | ROM_SIZE_32KBYTE EQU 0 550 | ROM_SIZE_64KBYTE EQU 1 551 | ROM_SIZE_128KBYTE EQU 2 552 | ROM_SIZE_256KBYTE EQU 3 553 | ROM_SIZE_512KBYTE EQU 4 554 | ROM_SIZE_1MBYTE EQU 5 555 | ROM_SIZE_2MBYTE EQU 6 556 | 557 | RAM_SIZE_0KBIT EQU 0 558 | RAM_SIZE_16KBIT EQU 1 559 | RAM_SIZE_64KBIT EQU 2 560 | RAM_SIZE_256KBIT EQU 3 561 | RAM_SIZE_1MBIT EQU 4 562 | 563 | RAM_SIZE_0KBYTE EQU 0 564 | RAM_SIZE_2KBYTE EQU 1 565 | RAM_SIZE_8KBYTE EQU 2 566 | RAM_SIZE_32KBYTE EQU 3 567 | RAM_SIZE_128KBYTE EQU 4 568 | 569 | ;*************************************************************************** 570 | ;* 571 | ;* Keypad related 572 | ;* 573 | ;*************************************************************************** 574 | 575 | PADF_DOWN EQU $80 576 | PADF_UP EQU $40 577 | PADF_LEFT EQU $20 578 | PADF_RIGHT EQU $10 579 | PADF_START EQU $08 580 | PADF_SELECT EQU $04 581 | PADF_B EQU $02 582 | PADF_A EQU $01 583 | 584 | PADB_DOWN EQU $7 585 | PADB_UP EQU $6 586 | PADB_LEFT EQU $5 587 | PADB_RIGHT EQU $4 588 | PADB_START EQU $3 589 | PADB_SELECT EQU $2 590 | PADB_B EQU $1 591 | PADB_A EQU $0 592 | 593 | ;*************************************************************************** 594 | ;* 595 | ;* Screen related 596 | ;* 597 | ;*************************************************************************** 598 | 599 | SCRN_X EQU 160 ; Width of screen in pixels 600 | SCRN_Y EQU 144 ; Height of screen in pixels 601 | SCRN_X_B EQU 20 ; Width of screen in bytes 602 | SCRN_Y_B EQU 18 ; Height of screen in bytes 603 | 604 | SCRN_VX EQU 256 ; Virtual width of screen in pixels 605 | SCRN_VY EQU 256 ; Virtual height of screen in pixels 606 | SCRN_VX_B EQU 32 ; Virtual width of screen in bytes 607 | SCRN_VY_B EQU 32 ; Virtual height of screen in bytes 608 | 609 | NINTENDO_LOGO: MACRO 610 | ;* 611 | ;* Nintendo scrolling logo 612 | ;* (Code won't work on a real GameBoy) 613 | ;* (if next six lines are altered.) 614 | DB $CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83,$00,$0C,$00,$0D 615 | DB $00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6,$DD,$DD,$D9,$99 616 | DB $BB,$BB,$67,$63,$6E,$0E,$EC,$CC,$DD,$DC,$99,$9F,$BB,$B9,$33,$3E 617 | ENDM 618 | 619 | ROM_HEADER: MACRO 620 | ;* 621 | ;* Nintendo scrolling logo 622 | ;* (Code won't work on a real GameBoy) 623 | ;* (if next six lines are altered.) 624 | 625 | ; 0123456789ABCDEF 626 | DB $CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83,$00,$0C,$00,$0D 627 | DB $00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6,$DD,$DD,$D9,$99 628 | DB $BB,$BB,$67,$63,$6E,$0E,$EC,$CC,$DD,$DC,$99,$9F,$BB,$B9,$33,$3E 629 | 630 | DB "EXAMPLE",0,0,0,0,0,0,0,0 ; Cart name - 15bytes 631 | DB 0 ; $143 632 | DB 0,0 ; $144 - Licensee code (not important) 633 | DB 0 ; $146 - SGB Support indicator 634 | DB \1 ; $147 - Cart type 635 | DB \2 ; $148 - ROM Size 636 | DB \3 ; $149 - RAM Size 637 | DB 1 ; $14a - Destination code 638 | DB $33 ; $14b - Old licensee code 639 | DB 0 ; $14c - Mask ROM version 640 | DB 0 ; $14d - Complement check (important) 641 | DW 0 ; $14e - Checksum (not important) 642 | 643 | ENDM 644 | 645 | ENDC ;HARDWARE_INC 646 | -------------------------------------------------------------------------------- /lycscy/inc/gbhw.inc: -------------------------------------------------------------------------------- 1 | ;* 2 | ;* GBHW.INC - Gameboy Hardware definitions for GALP 3 | ;* 4 | ;* by GABY. Inspired from work done by Carsten Sorensen & others. 5 | ;* 6 | ;* V1.0 - The original version 7 | ;* 8 | 9 | ; If all of these are already defined, don't do it again. 10 | 11 | IF !DEF(HARDWARE_INC) 12 | HARDWARE_INC SET 1 13 | 14 | rev_Check_hardware_inc: MACRO 15 | ;NOTE: REVISION NUMBER CHANGES MUST BE ADDED 16 | ;TO SECOND PARAMETER IN FOLLOWING LINE. 17 | IF \1 > 1.0 ;PUT REVISION NUMBER HERE 18 | WARN "Version \1 or later of 'gbhw.inc' is required." 19 | ENDC 20 | ENDM 21 | 22 | _HW EQU $FF00 23 | 24 | _VRAM EQU $8000 ; $8000->$A000 25 | _SCRN0 EQU $9800 ; $9800->$9BFF 26 | _SCRN1 EQU $9C00 ; $9C00->$9FFF 27 | _RAM EQU $C000 ; $C000->$E000 28 | _HRAM EQU $F800 ; $F800->$FFFE 29 | _OAMRAM EQU $FE00 ; $FE00->$FE9F 30 | _AUD3WAVERAM EQU $FF30 ; $FF30->$FF3F 31 | 32 | 33 | ; -- 34 | ; -- OAM flags 35 | ; -- 36 | 37 | OAMF_PRI EQU %10000000 ; Priority 38 | OAMF_YFLIP EQU %01000000 ; Y flip 39 | OAMF_XFLIP EQU %00100000 ; X flip 40 | OAMF_PAL0 EQU %00000000 ; Palette number; 0,1 41 | OAMF_PAL1 EQU %00010000 ; Palette number; 0,1 42 | 43 | 44 | ;*************************************************************************** 45 | ;* 46 | ;* Custom registers 47 | ;* 48 | ;*************************************************************************** 49 | 50 | ; -- 51 | ; -- P1 ($FF00) 52 | ; -- Register for reading joy pad info. (R/W) 53 | ; -- 54 | rP1 EQU $FF00 55 | 56 | P1F_5 EQU %00100000 ; P15 out port 57 | P1F_4 EQU %00010000 ; P14 out port 58 | P1F_3 EQU %00001000 ; P13 in port 59 | P1F_2 EQU %00000100 ; P12 in port 60 | P1F_1 EQU %00000010 ; P11 in port 61 | P1F_0 EQU %00000001 ; P10 in port 62 | 63 | 64 | ; -- 65 | ; -- LCDC ($FF40) 66 | ; -- LCD Control (R/W) 67 | ; -- 68 | rLCDC EQU $FF40 69 | 70 | LCDCF_OFF EQU %00000000 ; LCD Control Operation 71 | LCDCF_ON EQU %10000000 ; LCD Control Operation 72 | LCDCF_WIN9800 EQU %00000000 ; Window Tile Map Display Select 73 | LCDCF_WIN9C00 EQU %01000000 ; Window Tile Map Display Select 74 | LCDCF_WINOFF EQU %00000000 ; Window Display 75 | LCDCF_WINON EQU %00100000 ; Window Display 76 | LCDCF_BG8800 EQU %00000000 ; BG & Window Tile Data Select 77 | LCDCF_BG8000 EQU %00010000 ; BG & Window Tile Data Select 78 | LCDCF_BG9800 EQU %00000000 ; BG Tile Map Display Select 79 | LCDCF_BG9C00 EQU %00001000 ; BG Tile Map Display Select 80 | LCDCF_OBJ8 EQU %00000000 ; OBJ Construction 81 | LCDCF_OBJ16 EQU %00000100 ; OBJ Construction 82 | LCDCF_OBJOFF EQU %00000000 ; OBJ Display 83 | LCDCF_OBJON EQU %00000010 ; OBJ Display 84 | LCDCF_BGOFF EQU %00000000 ; BG Display 85 | LCDCF_BGON EQU %00000001 ; BG Display 86 | ; "Window Character Data Select" follows BG 87 | 88 | 89 | ; -- 90 | ; -- STAT ($FF41) 91 | ; -- LCDC Status (R/W) 92 | ; -- 93 | rSTAT EQU $FF41 94 | 95 | STATF_LYC EQU %01000000 ; LYCEQULY Coincidence (Selectable) 96 | STATF_MODE10 EQU %00100000 ; Mode 10 97 | STATF_MODE01 EQU %00010000 ; Mode 01 (V-Blank) 98 | STATF_MODE00 EQU %00001000 ; Mode 00 (H-Blank) 99 | STATF_LYCF EQU %00000100 ; Coincidence Flag 100 | STATF_HB EQU %00000000 ; H-Blank 101 | STATF_VB EQU %00000001 ; V-Blank 102 | STATF_OAM EQU %00000010 ; OAM-RAM is used by system 103 | STATF_LCD EQU %00000011 ; Both OAM and VRAM used by system 104 | STATF_BUSY EQU %00000010 ; When set, VRAM access is unsafe 105 | 106 | 107 | ; -- 108 | ; -- SCY ($FF42) 109 | ; -- Scroll Y (R/W) 110 | ; -- 111 | rSCY EQU $FF42 112 | 113 | 114 | ; -- 115 | ; -- SCY ($FF43) 116 | ; -- Scroll X (R/W) 117 | ; -- 118 | rSCX EQU $FF43 119 | 120 | 121 | ; -- 122 | ; -- LY ($FF44) 123 | ; -- LCDC Y-Coordinate (R) 124 | ; -- 125 | ; -- Values range from 0->153. 144->153 is the VBlank period. 126 | ; -- 127 | rLY EQU $FF44 128 | 129 | 130 | ; -- 131 | ; -- LYC ($FF45) 132 | ; -- LY Compare (R/W) 133 | ; -- 134 | ; -- When LYEQUEQULYC, STATF_LYCF will be set in STAT 135 | ; -- 136 | rLYC EQU $FF45 137 | 138 | 139 | ; -- 140 | ; -- DMA ($FF46) 141 | ; -- DMA Transfer and Start Address (W) 142 | ; -- 143 | rDMA EQU $FF46 144 | 145 | 146 | ; -- 147 | ; -- BGP ($FF47) 148 | ; -- BG Palette Data (W) 149 | ; -- 150 | ; -- Bit 7-6 - Intensity for %11 151 | ; -- Bit 5-4 - Intensity for %10 152 | ; -- Bit 3-2 - Intensity for %01 153 | ; -- Bit 1-0 - Intensity for %00 154 | ; -- 155 | rBGP EQU $FF47 156 | 157 | 158 | ; -- 159 | ; -- OBP0 ($FF48) 160 | ; -- Object Palette 0 Data (W) 161 | ; -- 162 | ; -- See BGP for info 163 | ; -- 164 | rOBP0 EQU $FF48 165 | 166 | 167 | ; -- 168 | ; -- OBP1 ($FF49) 169 | ; -- Object Palette 1 Data (W) 170 | ; -- 171 | ; -- See BGP for info 172 | ; -- 173 | rOBP1 EQU $FF49 174 | 175 | 176 | ; -- 177 | ; -- SB ($FF01) 178 | ; -- Serial Transfer Data (R/W) 179 | ; -- 180 | rSB EQU $FF01 181 | 182 | ; -- 183 | ; -- SC ($FF02) 184 | ; -- Serial I/O Control (R/W) 185 | ; -- 186 | rSC EQU $FF02 187 | 188 | ; -- 189 | ; -- DIV ($FF04) 190 | ; -- Divider register (R/W) 191 | ; -- 192 | rDIV EQU $FF04 193 | 194 | 195 | ; -- 196 | ; -- TIMA ($FF05) 197 | ; -- Timer counter (R/W) 198 | ; -- 199 | rTIMA EQU $FF05 200 | 201 | 202 | ; -- 203 | ; -- TMA ($FF06) 204 | ; -- Timer modulo (R/W) 205 | ; -- 206 | rTMA EQU $FF06 207 | 208 | 209 | ; -- 210 | ; -- TAC ($FF07) 211 | ; -- Timer control (R/W) 212 | ; -- 213 | rTAC EQU $FF07 214 | 215 | TACF_START EQU %00000100 216 | TACF_STOP EQU %00000000 217 | TACF_4KHZ EQU %00000000 218 | TACF_16KHZ EQU %00000011 219 | TACF_65KHZ EQU %00000010 220 | TACF_262KHZ EQU %00000001 221 | 222 | 223 | ; -- 224 | ; -- IF ($FF0F) 225 | ; -- Interrupt Flag (R/W) 226 | ; -- 227 | ; -- IE ($FFFF) 228 | ; -- Interrupt Enable (R/W) 229 | ; -- 230 | rIF EQU $FF0F 231 | rIE EQU $FFFF 232 | 233 | IEF_HILO EQU %00010000 ; Transition from High to Low of Pin number P10-P13 234 | IEF_SERIAL EQU %00001000 ; Serial I/O transfer end 235 | IEF_TIMER EQU %00000100 ; Timer Overflow 236 | IEF_LCDC EQU %00000010 ; LCDC (see STAT) 237 | IEF_VBLANK EQU %00000001 ; V-Blank 238 | 239 | 240 | ; -- 241 | ; -- WY ($FF4A) 242 | ; -- Window Y Position (R/W) 243 | ; -- 244 | ; -- 0 SO2 ON/OFF (Vin??) 269 | ; -- Bit 6-4 - SO2 output level (volume) (# 0-7) 270 | ; -- Bit 3 - Vin->SO1 ON/OFF (Vin??) 271 | ; -- Bit 2-0 - SO1 output level (volume) (# 0-7) 272 | ; -- 273 | rNR50 EQU $FF24 274 | rAUDVOL EQU rNR50 275 | 276 | 277 | ; -- 278 | ; -- AUDTERM/NR51 ($FF25) 279 | ; -- Selection of Sound output terminal (R/W) 280 | ; -- 281 | ; -- Bit 7 - Output sound 4 to SO2 terminal 282 | ; -- Bit 6 - Output sound 3 to SO2 terminal 283 | ; -- Bit 5 - Output sound 2 to SO2 terminal 284 | ; -- Bit 4 - Output sound 1 to SO2 terminal 285 | ; -- Bit 3 - Output sound 4 to SO1 terminal 286 | ; -- Bit 2 - Output sound 3 to SO1 terminal 287 | ; -- Bit 1 - Output sound 2 to SO1 terminal 288 | ; -- Bit 0 - Output sound 0 to SO1 terminal 289 | ; -- 290 | rNR51 EQU $FF25 291 | rAUDTERM EQU rNR51 292 | 293 | 294 | ; -- 295 | ; -- AUDENA/NR52 ($FF26) 296 | ; -- Sound on/off (R/W) 297 | ; -- 298 | ; -- Bit 7 - All sound on/off (sets all audio regs to 0!) 299 | ; -- Bit 3 - Sound 4 ON flag (doesn't work!) 300 | ; -- Bit 2 - Sound 3 ON flag (doesn't work!) 301 | ; -- Bit 1 - Sound 2 ON flag (doesn't work!) 302 | ; -- Bit 0 - Sound 1 ON flag (doesn't work!) 303 | ; -- 304 | rNR52 EQU $FF26 305 | rAUDENA EQU rNR52 306 | 307 | 308 | ;*************************************************************************** 309 | ;* 310 | ;* SoundChannel #1 registers 311 | ;* 312 | ;*************************************************************************** 313 | 314 | ; -- 315 | ; -- AUD1SWEEP/NR10 ($FF10) 316 | ; -- Sweep register (R/W) 317 | ; -- 318 | ; -- Bit 6-4 - Sweep Time 319 | ; -- Bit 3 - Sweep Increase/Decrease 320 | ; -- 0: Addition (frequency increases???) 321 | ; -- 1: Subtraction (frequency increases???) 322 | ; -- Bit 2-0 - Number of sweep shift (# 0-7) 323 | ; -- Sweep Time: (n*7.8ms) 324 | ; -- 325 | rNR10 EQU $FF10 326 | rAUD1SWEEP EQU rNR10 327 | 328 | 329 | ; -- 330 | ; -- AUD1LEN/NR11 ($FF11) 331 | ; -- Sound length/Wave pattern duty (R/W) 332 | ; -- 333 | ; -- Bit 7-6 - Wave Pattern Duty (00:12.5% 01:25% 10:50% 11:75%) 334 | ; -- Bit 5-0 - Sound length data (# 0-63) 335 | ; -- 336 | rNR11 EQU $FF11 337 | rAUD1LEN EQU rNR11 338 | 339 | 340 | ; -- 341 | ; -- AUD1ENV/NR12 ($FF12) 342 | ; -- Envelope (R/W) 343 | ; -- 344 | ; -- Bit 7-4 - Initial value of envelope 345 | ; -- Bit 3 - Envelope UP/DOWN 346 | ; -- 0: Decrease 347 | ; -- 1: Range of increase 348 | ; -- Bit 2-0 - Number of envelope sweep (# 0-7) 349 | ; -- 350 | rNR12 EQU $FF12 351 | rAUD1ENV EQU rNR12 352 | 353 | 354 | ; -- 355 | ; -- AUD1LOW/NR13 ($FF13) 356 | ; -- Frequency lo (W) 357 | ; -- 358 | rNR13 EQU $FF13 359 | rAUD1LOW EQU rNR13 360 | 361 | 362 | ; -- 363 | ; -- AUD1HIGH/NR14 ($FF14) 364 | ; -- Frequency hi (W) 365 | ; -- 366 | ; -- Bit 7 - Initial (when set, sound restarts) 367 | ; -- Bit 6 - Counter/consecutive selection 368 | ; -- Bit 2-0 - Frequency's higher 3 bits 369 | ; -- 370 | rNR14 EQU $FF14 371 | rAUD1HIGH EQU rNR14 372 | 373 | 374 | ;*************************************************************************** 375 | ;* 376 | ;* SoundChannel #2 registers 377 | ;* 378 | ;*************************************************************************** 379 | 380 | ; -- 381 | ; -- AUD2LEN/NR21 ($FF16) 382 | ; -- Sound Length; Wave Pattern Duty (R/W) 383 | ; -- 384 | ; -- see AUD1LEN for info 385 | ; -- 386 | rNR21 EQU $FF16 387 | rAUD2LEN EQU rNR21 388 | 389 | 390 | ; -- 391 | ; -- AUD2ENV/NR22 ($FF17) 392 | ; -- Envelope (R/W) 393 | ; -- 394 | ; -- see AUD1ENV for info 395 | ; -- 396 | rNR22 EQU $FF17 397 | rAUD2ENV EQU rNR22 398 | 399 | 400 | ; -- 401 | ; -- AUD2LOW/NR23 ($FF18) 402 | ; -- Frequency lo (W) 403 | ; -- 404 | rNR23 EQU $FF18 405 | rAUD2LOW EQU rNR23 406 | 407 | 408 | ; -- 409 | ; -- AUD2HIGH/NR24 ($FF19) 410 | ; -- Frequency hi (W) 411 | ; -- 412 | ; -- see AUD1HIGH for info 413 | ; -- 414 | rNR24 EQU $FF19 415 | rAUD2HIGH EQU rNR24 416 | 417 | 418 | ;*************************************************************************** 419 | ;* 420 | ;* SoundChannel #3 registers 421 | ;* 422 | ;*************************************************************************** 423 | 424 | ; -- 425 | ; -- AUD3ENA/NR30 ($FF1A) 426 | ; -- Sound on/off (R/W) 427 | ; -- 428 | ; -- Bit 7 - Sound ON/OFF (1EQUON,0EQUOFF) 429 | ; -- 430 | rNR30 EQU $FF1A 431 | rAUD3ENA EQU rNR30 432 | 433 | 434 | ; -- 435 | ; -- AUD3LEN/NR31 ($FF1B) 436 | ; -- Sound length (R/W) 437 | ; -- 438 | ; -- Bit 7-0 - Sound length 439 | ; -- 440 | rNR31 EQU $FF1B 441 | rAUD3LEN EQU rNR31 442 | 443 | 444 | ; -- 445 | ; -- AUD3LEVEL/NR32 ($FF1C) 446 | ; -- Select output level 447 | ; -- 448 | ; -- Bit 6-5 - Select output level 449 | ; -- 00: 0/1 (mute) 450 | ; -- 01: 1/1 451 | ; -- 10: 1/2 452 | ; -- 11: 1/4 453 | ; -- 454 | rNR32 EQU $FF1C 455 | rAUD3LEVEL EQU rNR32 456 | 457 | 458 | ; -- 459 | ; -- AUD3LOW/NR33 ($FF1D) 460 | ; -- Frequency lo (W) 461 | ; -- 462 | ; -- see AUD1LOW for info 463 | ; -- 464 | rNR33 EQU $FF1D 465 | rAUD3LOW EQU rNR33 466 | 467 | 468 | ; -- 469 | ; -- AUD3HIGH/NR34 ($FF1E) 470 | ; -- Frequency hi (W) 471 | ; -- 472 | ; -- see AUD1HIGH for info 473 | ; -- 474 | rNR34 EQU $FF1E 475 | rAUD3HIGH EQU rNR34 476 | 477 | 478 | ; -- 479 | ; -- AUD4LEN/NR41 ($FF20) 480 | ; -- Sound length (R/W) 481 | ; -- 482 | ; -- Bit 5-0 - Sound length data (# 0-63) 483 | ; -- 484 | rNR41 EQU $FF20 485 | rAUD4LEN EQU rNR41 486 | 487 | 488 | ; -- 489 | ; -- AUD4ENV/NR42 ($FF21) 490 | ; -- Envelope (R/W) 491 | ; -- 492 | ; -- see AUD1ENV for info 493 | ; -- 494 | rNR42 EQU $FF21 495 | rAUD4ENV EQU rNR42 496 | 497 | 498 | ; -- 499 | ; -- AUD4POLY/NR42 ($FF22) 500 | ; -- Polynomial counter (R/W) 501 | ; -- 502 | ; -- Bit 7-4 - Selection of the shift clock frequency of the (scf) 503 | ; -- polynomial counter (0000-1101) 504 | ; -- freqEQUdrf*1/2^scf (not sure) 505 | ; -- Bit 3 - Selection of the polynomial counter's step 506 | ; -- 0: 15 steps 507 | ; -- 1: 7 steps 508 | ; -- Bit 2-0 - Selection of the dividing ratio of frequencies (drf) 509 | ; -- 000: f/4 001: f/8 010: f/16 011: f/24 510 | ; -- 100: f/32 101: f/40 110: f/48 111: f/56 (fEQU4.194304 Mhz) 511 | ; -- 512 | rNR42_2 EQU $FF22 513 | rAUD4POLY EQU rNR42_2 514 | 515 | 516 | ; -- 517 | ; -- AUD4GO/NR43 ($FF23) 518 | ; -- (has wrong name and value (ff30) in Dr.Pan's doc!) 519 | ; -- 520 | ; -- Bit 7 - Inital 521 | ; -- Bit 6 - Counter/consecutive selection 522 | ; -- 523 | rNR43 EQU $FF23 524 | rAUD4GO EQU rNR43 ; silly name! 525 | 526 | ;*************************************************************************** 527 | ;* 528 | ;* Cart related 529 | ;* 530 | ;*************************************************************************** 531 | 532 | ROM_NOMBC EQU 0 533 | ROM_MBC1 EQU 1 534 | ROM_MBC1_RAM EQU 2 535 | ROM_MBC1_RAM_BAT EQU 3 536 | ROM_MBC2 EQU 5 537 | ROM_MBC2_BAT EQU 6 538 | ROM_NOMBC_RAM EQU 8 539 | ROM_NOMBC_RAM_BAT EQU 9 540 | 541 | ROM_SIZE_256KBIT EQU 0 542 | ROM_SIZE_512KBIT EQU 1 543 | ROM_SIZE_1M EQU 2 544 | ROM_SIZE_2M EQU 3 545 | ROM_SIZE_4M EQU 4 546 | ROM_SIZE_8M EQU 5 547 | ROM_SIZE_16M EQU 6 548 | 549 | ROM_SIZE_32KBYTE EQU 0 550 | ROM_SIZE_64KBYTE EQU 1 551 | ROM_SIZE_128KBYTE EQU 2 552 | ROM_SIZE_256KBYTE EQU 3 553 | ROM_SIZE_512KBYTE EQU 4 554 | ROM_SIZE_1MBYTE EQU 5 555 | ROM_SIZE_2MBYTE EQU 6 556 | 557 | RAM_SIZE_0KBIT EQU 0 558 | RAM_SIZE_16KBIT EQU 1 559 | RAM_SIZE_64KBIT EQU 2 560 | RAM_SIZE_256KBIT EQU 3 561 | RAM_SIZE_1MBIT EQU 4 562 | 563 | RAM_SIZE_0KBYTE EQU 0 564 | RAM_SIZE_2KBYTE EQU 1 565 | RAM_SIZE_8KBYTE EQU 2 566 | RAM_SIZE_32KBYTE EQU 3 567 | RAM_SIZE_128KBYTE EQU 4 568 | 569 | ;*************************************************************************** 570 | ;* 571 | ;* Keypad related 572 | ;* 573 | ;*************************************************************************** 574 | 575 | PADF_DOWN EQU $80 576 | PADF_UP EQU $40 577 | PADF_LEFT EQU $20 578 | PADF_RIGHT EQU $10 579 | PADF_START EQU $08 580 | PADF_SELECT EQU $04 581 | PADF_B EQU $02 582 | PADF_A EQU $01 583 | 584 | PADB_DOWN EQU $7 585 | PADB_UP EQU $6 586 | PADB_LEFT EQU $5 587 | PADB_RIGHT EQU $4 588 | PADB_START EQU $3 589 | PADB_SELECT EQU $2 590 | PADB_B EQU $1 591 | PADB_A EQU $0 592 | 593 | ;*************************************************************************** 594 | ;* 595 | ;* Screen related 596 | ;* 597 | ;*************************************************************************** 598 | 599 | SCRN_X EQU 160 ; Width of screen in pixels 600 | SCRN_Y EQU 144 ; Height of screen in pixels 601 | SCRN_X_B EQU 20 ; Width of screen in bytes 602 | SCRN_Y_B EQU 18 ; Height of screen in bytes 603 | 604 | SCRN_VX EQU 256 ; Virtual width of screen in pixels 605 | SCRN_VY EQU 256 ; Virtual height of screen in pixels 606 | SCRN_VX_B EQU 32 ; Virtual width of screen in bytes 607 | SCRN_VY_B EQU 32 ; Virtual height of screen in bytes 608 | 609 | NINTENDO_LOGO: MACRO 610 | ;* 611 | ;* Nintendo scrolling logo 612 | ;* (Code won't work on a real GameBoy) 613 | ;* (if next six lines are altered.) 614 | DB $CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83,$00,$0C,$00,$0D 615 | DB $00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6,$DD,$DD,$D9,$99 616 | DB $BB,$BB,$67,$63,$6E,$0E,$EC,$CC,$DD,$DC,$99,$9F,$BB,$B9,$33,$3E 617 | ENDM 618 | 619 | ROM_HEADER: MACRO 620 | ;* 621 | ;* Nintendo scrolling logo 622 | ;* (Code won't work on a real GameBoy) 623 | ;* (if next six lines are altered.) 624 | 625 | ; 0123456789ABCDEF 626 | DB $CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83,$00,$0C,$00,$0D 627 | DB $00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6,$DD,$DD,$D9,$99 628 | DB $BB,$BB,$67,$63,$6E,$0E,$EC,$CC,$DD,$DC,$99,$9F,$BB,$B9,$33,$3E 629 | 630 | DB "EXAMPLE",0,0,0,0,0,0,0,0 ; Cart name - 15bytes 631 | DB 0 ; $143 632 | DB 0,0 ; $144 - Licensee code (not important) 633 | DB 0 ; $146 - SGB Support indicator 634 | DB \1 ; $147 - Cart type 635 | DB \2 ; $148 - ROM Size 636 | DB \3 ; $149 - RAM Size 637 | DB 1 ; $14a - Destination code 638 | DB $33 ; $14b - Old licensee code 639 | DB 0 ; $14c - Mask ROM version 640 | DB 0 ; $14d - Complement check (important) 641 | DW 0 ; $14e - Checksum (not important) 642 | 643 | ENDM 644 | 645 | ENDC ;HARDWARE_INC 646 | -------------------------------------------------------------------------------- /scxly/inc/gbhw.inc: -------------------------------------------------------------------------------- 1 | ;* 2 | ;* GBHW.INC - Gameboy Hardware definitions for GALP 3 | ;* 4 | ;* by GABY. Inspired from work done by Carsten Sorensen & others. 5 | ;* 6 | ;* V1.0 - The original version 7 | ;* 8 | 9 | ; If all of these are already defined, don't do it again. 10 | 11 | IF !DEF(HARDWARE_INC) 12 | HARDWARE_INC SET 1 13 | 14 | rev_Check_hardware_inc: MACRO 15 | ;NOTE: REVISION NUMBER CHANGES MUST BE ADDED 16 | ;TO SECOND PARAMETER IN FOLLOWING LINE. 17 | IF \1 > 1.0 ;PUT REVISION NUMBER HERE 18 | WARN "Version \1 or later of 'gbhw.inc' is required." 19 | ENDC 20 | ENDM 21 | 22 | _HW EQU $FF00 23 | 24 | _VRAM EQU $8000 ; $8000->$A000 25 | _SCRN0 EQU $9800 ; $9800->$9BFF 26 | _SCRN1 EQU $9C00 ; $9C00->$9FFF 27 | _RAM EQU $C000 ; $C000->$E000 28 | _HRAM EQU $F800 ; $F800->$FFFE 29 | _OAMRAM EQU $FE00 ; $FE00->$FE9F 30 | _AUD3WAVERAM EQU $FF30 ; $FF30->$FF3F 31 | 32 | 33 | ; -- 34 | ; -- OAM flags 35 | ; -- 36 | 37 | OAMF_PRI EQU %10000000 ; Priority 38 | OAMF_YFLIP EQU %01000000 ; Y flip 39 | OAMF_XFLIP EQU %00100000 ; X flip 40 | OAMF_PAL0 EQU %00000000 ; Palette number; 0,1 41 | OAMF_PAL1 EQU %00010000 ; Palette number; 0,1 42 | 43 | 44 | ;*************************************************************************** 45 | ;* 46 | ;* Custom registers 47 | ;* 48 | ;*************************************************************************** 49 | 50 | ; -- 51 | ; -- P1 ($FF00) 52 | ; -- Register for reading joy pad info. (R/W) 53 | ; -- 54 | rP1 EQU $FF00 55 | 56 | P1F_5 EQU %00100000 ; P15 out port 57 | P1F_4 EQU %00010000 ; P14 out port 58 | P1F_3 EQU %00001000 ; P13 in port 59 | P1F_2 EQU %00000100 ; P12 in port 60 | P1F_1 EQU %00000010 ; P11 in port 61 | P1F_0 EQU %00000001 ; P10 in port 62 | 63 | 64 | ; -- 65 | ; -- LCDC ($FF40) 66 | ; -- LCD Control (R/W) 67 | ; -- 68 | rLCDC EQU $FF40 69 | 70 | LCDCF_OFF EQU %00000000 ; LCD Control Operation 71 | LCDCF_ON EQU %10000000 ; LCD Control Operation 72 | LCDCF_WIN9800 EQU %00000000 ; Window Tile Map Display Select 73 | LCDCF_WIN9C00 EQU %01000000 ; Window Tile Map Display Select 74 | LCDCF_WINOFF EQU %00000000 ; Window Display 75 | LCDCF_WINON EQU %00100000 ; Window Display 76 | LCDCF_BG8800 EQU %00000000 ; BG & Window Tile Data Select 77 | LCDCF_BG8000 EQU %00010000 ; BG & Window Tile Data Select 78 | LCDCF_BG9800 EQU %00000000 ; BG Tile Map Display Select 79 | LCDCF_BG9C00 EQU %00001000 ; BG Tile Map Display Select 80 | LCDCF_OBJ8 EQU %00000000 ; OBJ Construction 81 | LCDCF_OBJ16 EQU %00000100 ; OBJ Construction 82 | LCDCF_OBJOFF EQU %00000000 ; OBJ Display 83 | LCDCF_OBJON EQU %00000010 ; OBJ Display 84 | LCDCF_BGOFF EQU %00000000 ; BG Display 85 | LCDCF_BGON EQU %00000001 ; BG Display 86 | ; "Window Character Data Select" follows BG 87 | 88 | 89 | ; -- 90 | ; -- STAT ($FF41) 91 | ; -- LCDC Status (R/W) 92 | ; -- 93 | rSTAT EQU $FF41 94 | 95 | STATF_LYC EQU %01000000 ; LYCEQULY Coincidence (Selectable) 96 | STATF_MODE10 EQU %00100000 ; Mode 10 97 | STATF_MODE01 EQU %00010000 ; Mode 01 (V-Blank) 98 | STATF_MODE00 EQU %00001000 ; Mode 00 (H-Blank) 99 | STATF_LYCF EQU %00000100 ; Coincidence Flag 100 | STATF_HB EQU %00000000 ; H-Blank 101 | STATF_VB EQU %00000001 ; V-Blank 102 | STATF_OAM EQU %00000010 ; OAM-RAM is used by system 103 | STATF_LCD EQU %00000011 ; Both OAM and VRAM used by system 104 | STATF_BUSY EQU %00000010 ; When set, VRAM access is unsafe 105 | 106 | 107 | ; -- 108 | ; -- SCY ($FF42) 109 | ; -- Scroll Y (R/W) 110 | ; -- 111 | rSCY EQU $FF42 112 | 113 | 114 | ; -- 115 | ; -- SCY ($FF43) 116 | ; -- Scroll X (R/W) 117 | ; -- 118 | rSCX EQU $FF43 119 | 120 | 121 | ; -- 122 | ; -- LY ($FF44) 123 | ; -- LCDC Y-Coordinate (R) 124 | ; -- 125 | ; -- Values range from 0->153. 144->153 is the VBlank period. 126 | ; -- 127 | rLY EQU $FF44 128 | 129 | 130 | ; -- 131 | ; -- LYC ($FF45) 132 | ; -- LY Compare (R/W) 133 | ; -- 134 | ; -- When LYEQUEQULYC, STATF_LYCF will be set in STAT 135 | ; -- 136 | rLYC EQU $FF45 137 | 138 | 139 | ; -- 140 | ; -- DMA ($FF46) 141 | ; -- DMA Transfer and Start Address (W) 142 | ; -- 143 | rDMA EQU $FF46 144 | 145 | 146 | ; -- 147 | ; -- BGP ($FF47) 148 | ; -- BG Palette Data (W) 149 | ; -- 150 | ; -- Bit 7-6 - Intensity for %11 151 | ; -- Bit 5-4 - Intensity for %10 152 | ; -- Bit 3-2 - Intensity for %01 153 | ; -- Bit 1-0 - Intensity for %00 154 | ; -- 155 | rBGP EQU $FF47 156 | 157 | 158 | ; -- 159 | ; -- OBP0 ($FF48) 160 | ; -- Object Palette 0 Data (W) 161 | ; -- 162 | ; -- See BGP for info 163 | ; -- 164 | rOBP0 EQU $FF48 165 | 166 | 167 | ; -- 168 | ; -- OBP1 ($FF49) 169 | ; -- Object Palette 1 Data (W) 170 | ; -- 171 | ; -- See BGP for info 172 | ; -- 173 | rOBP1 EQU $FF49 174 | 175 | 176 | ; -- 177 | ; -- SB ($FF01) 178 | ; -- Serial Transfer Data (R/W) 179 | ; -- 180 | rSB EQU $FF01 181 | 182 | ; -- 183 | ; -- SC ($FF02) 184 | ; -- Serial I/O Control (R/W) 185 | ; -- 186 | rSC EQU $FF02 187 | 188 | ; -- 189 | ; -- DIV ($FF04) 190 | ; -- Divider register (R/W) 191 | ; -- 192 | rDIV EQU $FF04 193 | 194 | 195 | ; -- 196 | ; -- TIMA ($FF05) 197 | ; -- Timer counter (R/W) 198 | ; -- 199 | rTIMA EQU $FF05 200 | 201 | 202 | ; -- 203 | ; -- TMA ($FF06) 204 | ; -- Timer modulo (R/W) 205 | ; -- 206 | rTMA EQU $FF06 207 | 208 | 209 | ; -- 210 | ; -- TAC ($FF07) 211 | ; -- Timer control (R/W) 212 | ; -- 213 | rTAC EQU $FF07 214 | 215 | TACF_START EQU %00000100 216 | TACF_STOP EQU %00000000 217 | TACF_4KHZ EQU %00000000 218 | TACF_16KHZ EQU %00000011 219 | TACF_65KHZ EQU %00000010 220 | TACF_262KHZ EQU %00000001 221 | 222 | 223 | ; -- 224 | ; -- IF ($FF0F) 225 | ; -- Interrupt Flag (R/W) 226 | ; -- 227 | ; -- IE ($FFFF) 228 | ; -- Interrupt Enable (R/W) 229 | ; -- 230 | rIF EQU $FF0F 231 | rIE EQU $FFFF 232 | 233 | IEF_HILO EQU %00010000 ; Transition from High to Low of Pin number P10-P13 234 | IEF_SERIAL EQU %00001000 ; Serial I/O transfer end 235 | IEF_TIMER EQU %00000100 ; Timer Overflow 236 | IEF_LCDC EQU %00000010 ; LCDC (see STAT) 237 | IEF_VBLANK EQU %00000001 ; V-Blank 238 | 239 | 240 | ; -- 241 | ; -- WY ($FF4A) 242 | ; -- Window Y Position (R/W) 243 | ; -- 244 | ; -- 0 SO2 ON/OFF (Vin??) 269 | ; -- Bit 6-4 - SO2 output level (volume) (# 0-7) 270 | ; -- Bit 3 - Vin->SO1 ON/OFF (Vin??) 271 | ; -- Bit 2-0 - SO1 output level (volume) (# 0-7) 272 | ; -- 273 | rNR50 EQU $FF24 274 | rAUDVOL EQU rNR50 275 | 276 | 277 | ; -- 278 | ; -- AUDTERM/NR51 ($FF25) 279 | ; -- Selection of Sound output terminal (R/W) 280 | ; -- 281 | ; -- Bit 7 - Output sound 4 to SO2 terminal 282 | ; -- Bit 6 - Output sound 3 to SO2 terminal 283 | ; -- Bit 5 - Output sound 2 to SO2 terminal 284 | ; -- Bit 4 - Output sound 1 to SO2 terminal 285 | ; -- Bit 3 - Output sound 4 to SO1 terminal 286 | ; -- Bit 2 - Output sound 3 to SO1 terminal 287 | ; -- Bit 1 - Output sound 2 to SO1 terminal 288 | ; -- Bit 0 - Output sound 0 to SO1 terminal 289 | ; -- 290 | rNR51 EQU $FF25 291 | rAUDTERM EQU rNR51 292 | 293 | 294 | ; -- 295 | ; -- AUDENA/NR52 ($FF26) 296 | ; -- Sound on/off (R/W) 297 | ; -- 298 | ; -- Bit 7 - All sound on/off (sets all audio regs to 0!) 299 | ; -- Bit 3 - Sound 4 ON flag (doesn't work!) 300 | ; -- Bit 2 - Sound 3 ON flag (doesn't work!) 301 | ; -- Bit 1 - Sound 2 ON flag (doesn't work!) 302 | ; -- Bit 0 - Sound 1 ON flag (doesn't work!) 303 | ; -- 304 | rNR52 EQU $FF26 305 | rAUDENA EQU rNR52 306 | 307 | 308 | ;*************************************************************************** 309 | ;* 310 | ;* SoundChannel #1 registers 311 | ;* 312 | ;*************************************************************************** 313 | 314 | ; -- 315 | ; -- AUD1SWEEP/NR10 ($FF10) 316 | ; -- Sweep register (R/W) 317 | ; -- 318 | ; -- Bit 6-4 - Sweep Time 319 | ; -- Bit 3 - Sweep Increase/Decrease 320 | ; -- 0: Addition (frequency increases???) 321 | ; -- 1: Subtraction (frequency increases???) 322 | ; -- Bit 2-0 - Number of sweep shift (# 0-7) 323 | ; -- Sweep Time: (n*7.8ms) 324 | ; -- 325 | rNR10 EQU $FF10 326 | rAUD1SWEEP EQU rNR10 327 | 328 | 329 | ; -- 330 | ; -- AUD1LEN/NR11 ($FF11) 331 | ; -- Sound length/Wave pattern duty (R/W) 332 | ; -- 333 | ; -- Bit 7-6 - Wave Pattern Duty (00:12.5% 01:25% 10:50% 11:75%) 334 | ; -- Bit 5-0 - Sound length data (# 0-63) 335 | ; -- 336 | rNR11 EQU $FF11 337 | rAUD1LEN EQU rNR11 338 | 339 | 340 | ; -- 341 | ; -- AUD1ENV/NR12 ($FF12) 342 | ; -- Envelope (R/W) 343 | ; -- 344 | ; -- Bit 7-4 - Initial value of envelope 345 | ; -- Bit 3 - Envelope UP/DOWN 346 | ; -- 0: Decrease 347 | ; -- 1: Range of increase 348 | ; -- Bit 2-0 - Number of envelope sweep (# 0-7) 349 | ; -- 350 | rNR12 EQU $FF12 351 | rAUD1ENV EQU rNR12 352 | 353 | 354 | ; -- 355 | ; -- AUD1LOW/NR13 ($FF13) 356 | ; -- Frequency lo (W) 357 | ; -- 358 | rNR13 EQU $FF13 359 | rAUD1LOW EQU rNR13 360 | 361 | 362 | ; -- 363 | ; -- AUD1HIGH/NR14 ($FF14) 364 | ; -- Frequency hi (W) 365 | ; -- 366 | ; -- Bit 7 - Initial (when set, sound restarts) 367 | ; -- Bit 6 - Counter/consecutive selection 368 | ; -- Bit 2-0 - Frequency's higher 3 bits 369 | ; -- 370 | rNR14 EQU $FF14 371 | rAUD1HIGH EQU rNR14 372 | 373 | 374 | ;*************************************************************************** 375 | ;* 376 | ;* SoundChannel #2 registers 377 | ;* 378 | ;*************************************************************************** 379 | 380 | ; -- 381 | ; -- AUD2LEN/NR21 ($FF16) 382 | ; -- Sound Length; Wave Pattern Duty (R/W) 383 | ; -- 384 | ; -- see AUD1LEN for info 385 | ; -- 386 | rNR21 EQU $FF16 387 | rAUD2LEN EQU rNR21 388 | 389 | 390 | ; -- 391 | ; -- AUD2ENV/NR22 ($FF17) 392 | ; -- Envelope (R/W) 393 | ; -- 394 | ; -- see AUD1ENV for info 395 | ; -- 396 | rNR22 EQU $FF17 397 | rAUD2ENV EQU rNR22 398 | 399 | 400 | ; -- 401 | ; -- AUD2LOW/NR23 ($FF18) 402 | ; -- Frequency lo (W) 403 | ; -- 404 | rNR23 EQU $FF18 405 | rAUD2LOW EQU rNR23 406 | 407 | 408 | ; -- 409 | ; -- AUD2HIGH/NR24 ($FF19) 410 | ; -- Frequency hi (W) 411 | ; -- 412 | ; -- see AUD1HIGH for info 413 | ; -- 414 | rNR24 EQU $FF19 415 | rAUD2HIGH EQU rNR24 416 | 417 | 418 | ;*************************************************************************** 419 | ;* 420 | ;* SoundChannel #3 registers 421 | ;* 422 | ;*************************************************************************** 423 | 424 | ; -- 425 | ; -- AUD3ENA/NR30 ($FF1A) 426 | ; -- Sound on/off (R/W) 427 | ; -- 428 | ; -- Bit 7 - Sound ON/OFF (1EQUON,0EQUOFF) 429 | ; -- 430 | rNR30 EQU $FF1A 431 | rAUD3ENA EQU rNR30 432 | 433 | 434 | ; -- 435 | ; -- AUD3LEN/NR31 ($FF1B) 436 | ; -- Sound length (R/W) 437 | ; -- 438 | ; -- Bit 7-0 - Sound length 439 | ; -- 440 | rNR31 EQU $FF1B 441 | rAUD3LEN EQU rNR31 442 | 443 | 444 | ; -- 445 | ; -- AUD3LEVEL/NR32 ($FF1C) 446 | ; -- Select output level 447 | ; -- 448 | ; -- Bit 6-5 - Select output level 449 | ; -- 00: 0/1 (mute) 450 | ; -- 01: 1/1 451 | ; -- 10: 1/2 452 | ; -- 11: 1/4 453 | ; -- 454 | rNR32 EQU $FF1C 455 | rAUD3LEVEL EQU rNR32 456 | 457 | 458 | ; -- 459 | ; -- AUD3LOW/NR33 ($FF1D) 460 | ; -- Frequency lo (W) 461 | ; -- 462 | ; -- see AUD1LOW for info 463 | ; -- 464 | rNR33 EQU $FF1D 465 | rAUD3LOW EQU rNR33 466 | 467 | 468 | ; -- 469 | ; -- AUD3HIGH/NR34 ($FF1E) 470 | ; -- Frequency hi (W) 471 | ; -- 472 | ; -- see AUD1HIGH for info 473 | ; -- 474 | rNR34 EQU $FF1E 475 | rAUD3HIGH EQU rNR34 476 | 477 | 478 | ; -- 479 | ; -- AUD4LEN/NR41 ($FF20) 480 | ; -- Sound length (R/W) 481 | ; -- 482 | ; -- Bit 5-0 - Sound length data (# 0-63) 483 | ; -- 484 | rNR41 EQU $FF20 485 | rAUD4LEN EQU rNR41 486 | 487 | 488 | ; -- 489 | ; -- AUD4ENV/NR42 ($FF21) 490 | ; -- Envelope (R/W) 491 | ; -- 492 | ; -- see AUD1ENV for info 493 | ; -- 494 | rNR42 EQU $FF21 495 | rAUD4ENV EQU rNR42 496 | 497 | 498 | ; -- 499 | ; -- AUD4POLY/NR42 ($FF22) 500 | ; -- Polynomial counter (R/W) 501 | ; -- 502 | ; -- Bit 7-4 - Selection of the shift clock frequency of the (scf) 503 | ; -- polynomial counter (0000-1101) 504 | ; -- freqEQUdrf*1/2^scf (not sure) 505 | ; -- Bit 3 - Selection of the polynomial counter's step 506 | ; -- 0: 15 steps 507 | ; -- 1: 7 steps 508 | ; -- Bit 2-0 - Selection of the dividing ratio of frequencies (drf) 509 | ; -- 000: f/4 001: f/8 010: f/16 011: f/24 510 | ; -- 100: f/32 101: f/40 110: f/48 111: f/56 (fEQU4.194304 Mhz) 511 | ; -- 512 | rNR42_2 EQU $FF22 513 | rAUD4POLY EQU rNR42_2 514 | 515 | 516 | ; -- 517 | ; -- AUD4GO/NR43 ($FF23) 518 | ; -- (has wrong name and value (ff30) in Dr.Pan's doc!) 519 | ; -- 520 | ; -- Bit 7 - Inital 521 | ; -- Bit 6 - Counter/consecutive selection 522 | ; -- 523 | rNR43 EQU $FF23 524 | rAUD4GO EQU rNR43 ; silly name! 525 | 526 | ;*************************************************************************** 527 | ;* 528 | ;* Cart related 529 | ;* 530 | ;*************************************************************************** 531 | 532 | ROM_NOMBC EQU 0 533 | ROM_MBC1 EQU 1 534 | ROM_MBC1_RAM EQU 2 535 | ROM_MBC1_RAM_BAT EQU 3 536 | ROM_MBC2 EQU 5 537 | ROM_MBC2_BAT EQU 6 538 | ROM_NOMBC_RAM EQU 8 539 | ROM_NOMBC_RAM_BAT EQU 9 540 | 541 | ROM_SIZE_256KBIT EQU 0 542 | ROM_SIZE_512KBIT EQU 1 543 | ROM_SIZE_1M EQU 2 544 | ROM_SIZE_2M EQU 3 545 | ROM_SIZE_4M EQU 4 546 | ROM_SIZE_8M EQU 5 547 | ROM_SIZE_16M EQU 6 548 | 549 | ROM_SIZE_32KBYTE EQU 0 550 | ROM_SIZE_64KBYTE EQU 1 551 | ROM_SIZE_128KBYTE EQU 2 552 | ROM_SIZE_256KBYTE EQU 3 553 | ROM_SIZE_512KBYTE EQU 4 554 | ROM_SIZE_1MBYTE EQU 5 555 | ROM_SIZE_2MBYTE EQU 6 556 | 557 | RAM_SIZE_0KBIT EQU 0 558 | RAM_SIZE_16KBIT EQU 1 559 | RAM_SIZE_64KBIT EQU 2 560 | RAM_SIZE_256KBIT EQU 3 561 | RAM_SIZE_1MBIT EQU 4 562 | 563 | RAM_SIZE_0KBYTE EQU 0 564 | RAM_SIZE_2KBYTE EQU 1 565 | RAM_SIZE_8KBYTE EQU 2 566 | RAM_SIZE_32KBYTE EQU 3 567 | RAM_SIZE_128KBYTE EQU 4 568 | 569 | ;*************************************************************************** 570 | ;* 571 | ;* Keypad related 572 | ;* 573 | ;*************************************************************************** 574 | 575 | PADF_DOWN EQU $80 576 | PADF_UP EQU $40 577 | PADF_LEFT EQU $20 578 | PADF_RIGHT EQU $10 579 | PADF_START EQU $08 580 | PADF_SELECT EQU $04 581 | PADF_B EQU $02 582 | PADF_A EQU $01 583 | 584 | PADB_DOWN EQU $7 585 | PADB_UP EQU $6 586 | PADB_LEFT EQU $5 587 | PADB_RIGHT EQU $4 588 | PADB_START EQU $3 589 | PADB_SELECT EQU $2 590 | PADB_B EQU $1 591 | PADB_A EQU $0 592 | 593 | ;*************************************************************************** 594 | ;* 595 | ;* Screen related 596 | ;* 597 | ;*************************************************************************** 598 | 599 | SCRN_X EQU 160 ; Width of screen in pixels 600 | SCRN_Y EQU 144 ; Height of screen in pixels 601 | SCRN_X_B EQU 20 ; Width of screen in bytes 602 | SCRN_Y_B EQU 18 ; Height of screen in bytes 603 | 604 | SCRN_VX EQU 256 ; Virtual width of screen in pixels 605 | SCRN_VY EQU 256 ; Virtual height of screen in pixels 606 | SCRN_VX_B EQU 32 ; Virtual width of screen in bytes 607 | SCRN_VY_B EQU 32 ; Virtual height of screen in bytes 608 | 609 | NINTENDO_LOGO: MACRO 610 | ;* 611 | ;* Nintendo scrolling logo 612 | ;* (Code won't work on a real GameBoy) 613 | ;* (if next six lines are altered.) 614 | DB $CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83,$00,$0C,$00,$0D 615 | DB $00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6,$DD,$DD,$D9,$99 616 | DB $BB,$BB,$67,$63,$6E,$0E,$EC,$CC,$DD,$DC,$99,$9F,$BB,$B9,$33,$3E 617 | ENDM 618 | 619 | ROM_HEADER: MACRO 620 | ;* 621 | ;* Nintendo scrolling logo 622 | ;* (Code won't work on a real GameBoy) 623 | ;* (if next six lines are altered.) 624 | 625 | ; 0123456789ABCDEF 626 | DB $CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83,$00,$0C,$00,$0D 627 | DB $00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6,$DD,$DD,$D9,$99 628 | DB $BB,$BB,$67,$63,$6E,$0E,$EC,$CC,$DD,$DC,$99,$9F,$BB,$B9,$33,$3E 629 | 630 | DB "EXAMPLE",0,0,0,0,0,0,0,0 ; Cart name - 15bytes 631 | DB 0 ; $143 632 | DB 0,0 ; $144 - Licensee code (not important) 633 | DB 0 ; $146 - SGB Support indicator 634 | DB \1 ; $147 - Cart type 635 | DB \2 ; $148 - ROM Size 636 | DB \3 ; $149 - RAM Size 637 | DB 1 ; $14a - Destination code 638 | DB $33 ; $14b - Old licensee code 639 | DB 0 ; $14c - Mask ROM version 640 | DB 0 ; $14d - Complement check (important) 641 | DW 0 ; $14e - Checksum (not important) 642 | 643 | ENDM 644 | 645 | ENDC ;HARDWARE_INC 646 | -------------------------------------------------------------------------------- /fairylake/inc/gbhw.inc: -------------------------------------------------------------------------------- 1 | ;* 2 | ;* GBHW.INC - Gameboy Hardware definitions for GALP 3 | ;* 4 | ;* by GABY. Inspired from work done by Carsten Sorensen & others. 5 | ;* 6 | ;* V1.0 - The original version 7 | ;* 8 | 9 | ; If all of these are already defined, don't do it again. 10 | 11 | IF !DEF(HARDWARE_INC) 12 | HARDWARE_INC SET 1 13 | 14 | rev_Check_hardware_inc: MACRO 15 | ;NOTE: REVISION NUMBER CHANGES MUST BE ADDED 16 | ;TO SECOND PARAMETER IN FOLLOWING LINE. 17 | IF \1 > 1.0 ;PUT REVISION NUMBER HERE 18 | WARN "Version \1 or later of 'gbhw.inc' is required." 19 | ENDC 20 | ENDM 21 | 22 | _HW EQU $FF00 23 | 24 | _VRAM EQU $8000 ; $8000->$A000 25 | _SCRN0 EQU $9800 ; $9800->$9BFF 26 | _SCRN1 EQU $9C00 ; $9C00->$9FFF 27 | _RAM EQU $C000 ; $C000->$E000 28 | _HRAM EQU $F800 ; $F800->$FFFE 29 | _OAMRAM EQU $FE00 ; $FE00->$FE9F 30 | _AUD3WAVERAM EQU $FF30 ; $FF30->$FF3F 31 | 32 | 33 | ; -- 34 | ; -- OAM flags 35 | ; -- 36 | 37 | OAMF_PRI EQU %10000000 ; Priority 38 | OAMF_YFLIP EQU %01000000 ; Y flip 39 | OAMF_XFLIP EQU %00100000 ; X flip 40 | OAMF_PAL0 EQU %00000000 ; Palette number; 0,1 41 | OAMF_PAL1 EQU %00010000 ; Palette number; 0,1 42 | 43 | 44 | ;*************************************************************************** 45 | ;* 46 | ;* Custom registers 47 | ;* 48 | ;*************************************************************************** 49 | 50 | ; -- 51 | ; -- P1 ($FF00) 52 | ; -- Register for reading joy pad info. (R/W) 53 | ; -- 54 | rP1 EQU $FF00 55 | 56 | P1F_5 EQU %00100000 ; P15 out port 57 | P1F_4 EQU %00010000 ; P14 out port 58 | P1F_3 EQU %00001000 ; P13 in port 59 | P1F_2 EQU %00000100 ; P12 in port 60 | P1F_1 EQU %00000010 ; P11 in port 61 | P1F_0 EQU %00000001 ; P10 in port 62 | 63 | 64 | ; -- 65 | ; -- LCDC ($FF40) 66 | ; -- LCD Control (R/W) 67 | ; -- 68 | rLCDC EQU $FF40 69 | 70 | LCDCF_OFF EQU %00000000 ; LCD Control Operation 71 | LCDCF_ON EQU %10000000 ; LCD Control Operation 72 | LCDCF_WIN9800 EQU %00000000 ; Window Tile Map Display Select 73 | LCDCF_WIN9C00 EQU %01000000 ; Window Tile Map Display Select 74 | LCDCF_WINOFF EQU %00000000 ; Window Display 75 | LCDCF_WINON EQU %00100000 ; Window Display 76 | LCDCF_BG8800 EQU %00000000 ; BG & Window Tile Data Select 77 | LCDCF_BG8000 EQU %00010000 ; BG & Window Tile Data Select 78 | LCDCF_BG9800 EQU %00000000 ; BG Tile Map Display Select 79 | LCDCF_BG9C00 EQU %00001000 ; BG Tile Map Display Select 80 | LCDCF_OBJ8 EQU %00000000 ; OBJ Construction 81 | LCDCF_OBJ16 EQU %00000100 ; OBJ Construction 82 | LCDCF_OBJOFF EQU %00000000 ; OBJ Display 83 | LCDCF_OBJON EQU %00000010 ; OBJ Display 84 | LCDCF_BGOFF EQU %00000000 ; BG Display 85 | LCDCF_BGON EQU %00000001 ; BG Display 86 | ; "Window Character Data Select" follows BG 87 | 88 | 89 | ; -- 90 | ; -- STAT ($FF41) 91 | ; -- LCDC Status (R/W) 92 | ; -- 93 | rSTAT EQU $FF41 94 | 95 | STATF_LYC EQU %01000000 ; LYCEQULY Coincidence (Selectable) 96 | STATF_MODE10 EQU %00100000 ; Mode 10 97 | STATF_MODE01 EQU %00010000 ; Mode 01 (V-Blank) 98 | STATF_MODE00 EQU %00001000 ; Mode 00 (H-Blank) 99 | STATF_LYCF EQU %00000100 ; Coincidence Flag 100 | STATF_HB EQU %00000000 ; H-Blank 101 | STATF_VB EQU %00000001 ; V-Blank 102 | STATF_OAM EQU %00000010 ; OAM-RAM is used by system 103 | STATF_LCD EQU %00000011 ; Both OAM and VRAM used by system 104 | STATF_BUSY EQU %00000010 ; When set, VRAM access is unsafe 105 | 106 | 107 | ; -- 108 | ; -- SCY ($FF42) 109 | ; -- Scroll Y (R/W) 110 | ; -- 111 | rSCY EQU $FF42 112 | 113 | 114 | ; -- 115 | ; -- SCY ($FF43) 116 | ; -- Scroll X (R/W) 117 | ; -- 118 | rSCX EQU $FF43 119 | 120 | 121 | ; -- 122 | ; -- LY ($FF44) 123 | ; -- LCDC Y-Coordinate (R) 124 | ; -- 125 | ; -- Values range from 0->153. 144->153 is the VBlank period. 126 | ; -- 127 | rLY EQU $FF44 128 | 129 | 130 | ; -- 131 | ; -- LYC ($FF45) 132 | ; -- LY Compare (R/W) 133 | ; -- 134 | ; -- When LYEQUEQULYC, STATF_LYCF will be set in STAT 135 | ; -- 136 | rLYC EQU $FF45 137 | 138 | 139 | ; -- 140 | ; -- DMA ($FF46) 141 | ; -- DMA Transfer and Start Address (W) 142 | ; -- 143 | rDMA EQU $FF46 144 | 145 | 146 | ; -- 147 | ; -- BGP ($FF47) 148 | ; -- BG Palette Data (W) 149 | ; -- 150 | ; -- Bit 7-6 - Intensity for %11 151 | ; -- Bit 5-4 - Intensity for %10 152 | ; -- Bit 3-2 - Intensity for %01 153 | ; -- Bit 1-0 - Intensity for %00 154 | ; -- 155 | rBGP EQU $FF47 156 | 157 | 158 | ; -- 159 | ; -- OBP0 ($FF48) 160 | ; -- Object Palette 0 Data (W) 161 | ; -- 162 | ; -- See BGP for info 163 | ; -- 164 | rOBP0 EQU $FF48 165 | 166 | 167 | ; -- 168 | ; -- OBP1 ($FF49) 169 | ; -- Object Palette 1 Data (W) 170 | ; -- 171 | ; -- See BGP for info 172 | ; -- 173 | rOBP1 EQU $FF49 174 | 175 | 176 | ; -- 177 | ; -- SB ($FF01) 178 | ; -- Serial Transfer Data (R/W) 179 | ; -- 180 | rSB EQU $FF01 181 | 182 | ; -- 183 | ; -- SC ($FF02) 184 | ; -- Serial I/O Control (R/W) 185 | ; -- 186 | rSC EQU $FF02 187 | 188 | ; -- 189 | ; -- DIV ($FF04) 190 | ; -- Divider register (R/W) 191 | ; -- 192 | rDIV EQU $FF04 193 | 194 | 195 | ; -- 196 | ; -- TIMA ($FF05) 197 | ; -- Timer counter (R/W) 198 | ; -- 199 | rTIMA EQU $FF05 200 | 201 | 202 | ; -- 203 | ; -- TMA ($FF06) 204 | ; -- Timer modulo (R/W) 205 | ; -- 206 | rTMA EQU $FF06 207 | 208 | 209 | ; -- 210 | ; -- TAC ($FF07) 211 | ; -- Timer control (R/W) 212 | ; -- 213 | rTAC EQU $FF07 214 | 215 | TACF_START EQU %00000100 216 | TACF_STOP EQU %00000000 217 | TACF_4KHZ EQU %00000000 218 | TACF_16KHZ EQU %00000011 219 | TACF_65KHZ EQU %00000010 220 | TACF_262KHZ EQU %00000001 221 | 222 | 223 | ; -- 224 | ; -- IF ($FF0F) 225 | ; -- Interrupt Flag (R/W) 226 | ; -- 227 | ; -- IE ($FFFF) 228 | ; -- Interrupt Enable (R/W) 229 | ; -- 230 | rIF EQU $FF0F 231 | rIE EQU $FFFF 232 | 233 | IEF_HILO EQU %00010000 ; Transition from High to Low of Pin number P10-P13 234 | IEF_SERIAL EQU %00001000 ; Serial I/O transfer end 235 | IEF_TIMER EQU %00000100 ; Timer Overflow 236 | IEF_LCDC EQU %00000010 ; LCDC (see STAT) 237 | IEF_VBLANK EQU %00000001 ; V-Blank 238 | 239 | 240 | ; -- 241 | ; -- WY ($FF4A) 242 | ; -- Window Y Position (R/W) 243 | ; -- 244 | ; -- 0 SO2 ON/OFF (Vin??) 269 | ; -- Bit 6-4 - SO2 output level (volume) (# 0-7) 270 | ; -- Bit 3 - Vin->SO1 ON/OFF (Vin??) 271 | ; -- Bit 2-0 - SO1 output level (volume) (# 0-7) 272 | ; -- 273 | rNR50 EQU $FF24 274 | rAUDVOL EQU rNR50 275 | 276 | 277 | ; -- 278 | ; -- AUDTERM/NR51 ($FF25) 279 | ; -- Selection of Sound output terminal (R/W) 280 | ; -- 281 | ; -- Bit 7 - Output sound 4 to SO2 terminal 282 | ; -- Bit 6 - Output sound 3 to SO2 terminal 283 | ; -- Bit 5 - Output sound 2 to SO2 terminal 284 | ; -- Bit 4 - Output sound 1 to SO2 terminal 285 | ; -- Bit 3 - Output sound 4 to SO1 terminal 286 | ; -- Bit 2 - Output sound 3 to SO1 terminal 287 | ; -- Bit 1 - Output sound 2 to SO1 terminal 288 | ; -- Bit 0 - Output sound 0 to SO1 terminal 289 | ; -- 290 | rNR51 EQU $FF25 291 | rAUDTERM EQU rNR51 292 | 293 | 294 | ; -- 295 | ; -- AUDENA/NR52 ($FF26) 296 | ; -- Sound on/off (R/W) 297 | ; -- 298 | ; -- Bit 7 - All sound on/off (sets all audio regs to 0!) 299 | ; -- Bit 3 - Sound 4 ON flag (doesn't work!) 300 | ; -- Bit 2 - Sound 3 ON flag (doesn't work!) 301 | ; -- Bit 1 - Sound 2 ON flag (doesn't work!) 302 | ; -- Bit 0 - Sound 1 ON flag (doesn't work!) 303 | ; -- 304 | rNR52 EQU $FF26 305 | rAUDENA EQU rNR52 306 | 307 | 308 | ;*************************************************************************** 309 | ;* 310 | ;* SoundChannel #1 registers 311 | ;* 312 | ;*************************************************************************** 313 | 314 | ; -- 315 | ; -- AUD1SWEEP/NR10 ($FF10) 316 | ; -- Sweep register (R/W) 317 | ; -- 318 | ; -- Bit 6-4 - Sweep Time 319 | ; -- Bit 3 - Sweep Increase/Decrease 320 | ; -- 0: Addition (frequency increases???) 321 | ; -- 1: Subtraction (frequency increases???) 322 | ; -- Bit 2-0 - Number of sweep shift (# 0-7) 323 | ; -- Sweep Time: (n*7.8ms) 324 | ; -- 325 | rNR10 EQU $FF10 326 | rAUD1SWEEP EQU rNR10 327 | 328 | 329 | ; -- 330 | ; -- AUD1LEN/NR11 ($FF11) 331 | ; -- Sound length/Wave pattern duty (R/W) 332 | ; -- 333 | ; -- Bit 7-6 - Wave Pattern Duty (00:12.5% 01:25% 10:50% 11:75%) 334 | ; -- Bit 5-0 - Sound length data (# 0-63) 335 | ; -- 336 | rNR11 EQU $FF11 337 | rAUD1LEN EQU rNR11 338 | 339 | 340 | ; -- 341 | ; -- AUD1ENV/NR12 ($FF12) 342 | ; -- Envelope (R/W) 343 | ; -- 344 | ; -- Bit 7-4 - Initial value of envelope 345 | ; -- Bit 3 - Envelope UP/DOWN 346 | ; -- 0: Decrease 347 | ; -- 1: Range of increase 348 | ; -- Bit 2-0 - Number of envelope sweep (# 0-7) 349 | ; -- 350 | rNR12 EQU $FF12 351 | rAUD1ENV EQU rNR12 352 | 353 | 354 | ; -- 355 | ; -- AUD1LOW/NR13 ($FF13) 356 | ; -- Frequency lo (W) 357 | ; -- 358 | rNR13 EQU $FF13 359 | rAUD1LOW EQU rNR13 360 | 361 | 362 | ; -- 363 | ; -- AUD1HIGH/NR14 ($FF14) 364 | ; -- Frequency hi (W) 365 | ; -- 366 | ; -- Bit 7 - Initial (when set, sound restarts) 367 | ; -- Bit 6 - Counter/consecutive selection 368 | ; -- Bit 2-0 - Frequency's higher 3 bits 369 | ; -- 370 | rNR14 EQU $FF14 371 | rAUD1HIGH EQU rNR14 372 | 373 | 374 | ;*************************************************************************** 375 | ;* 376 | ;* SoundChannel #2 registers 377 | ;* 378 | ;*************************************************************************** 379 | 380 | ; -- 381 | ; -- AUD2LEN/NR21 ($FF16) 382 | ; -- Sound Length; Wave Pattern Duty (R/W) 383 | ; -- 384 | ; -- see AUD1LEN for info 385 | ; -- 386 | rNR21 EQU $FF16 387 | rAUD2LEN EQU rNR21 388 | 389 | 390 | ; -- 391 | ; -- AUD2ENV/NR22 ($FF17) 392 | ; -- Envelope (R/W) 393 | ; -- 394 | ; -- see AUD1ENV for info 395 | ; -- 396 | rNR22 EQU $FF17 397 | rAUD2ENV EQU rNR22 398 | 399 | 400 | ; -- 401 | ; -- AUD2LOW/NR23 ($FF18) 402 | ; -- Frequency lo (W) 403 | ; -- 404 | rNR23 EQU $FF18 405 | rAUD2LOW EQU rNR23 406 | 407 | 408 | ; -- 409 | ; -- AUD2HIGH/NR24 ($FF19) 410 | ; -- Frequency hi (W) 411 | ; -- 412 | ; -- see AUD1HIGH for info 413 | ; -- 414 | rNR24 EQU $FF19 415 | rAUD2HIGH EQU rNR24 416 | 417 | 418 | ;*************************************************************************** 419 | ;* 420 | ;* SoundChannel #3 registers 421 | ;* 422 | ;*************************************************************************** 423 | 424 | ; -- 425 | ; -- AUD3ENA/NR30 ($FF1A) 426 | ; -- Sound on/off (R/W) 427 | ; -- 428 | ; -- Bit 7 - Sound ON/OFF (1EQUON,0EQUOFF) 429 | ; -- 430 | rNR30 EQU $FF1A 431 | rAUD3ENA EQU rNR30 432 | 433 | 434 | ; -- 435 | ; -- AUD3LEN/NR31 ($FF1B) 436 | ; -- Sound length (R/W) 437 | ; -- 438 | ; -- Bit 7-0 - Sound length 439 | ; -- 440 | rNR31 EQU $FF1B 441 | rAUD3LEN EQU rNR31 442 | 443 | 444 | ; -- 445 | ; -- AUD3LEVEL/NR32 ($FF1C) 446 | ; -- Select output level 447 | ; -- 448 | ; -- Bit 6-5 - Select output level 449 | ; -- 00: 0/1 (mute) 450 | ; -- 01: 1/1 451 | ; -- 10: 1/2 452 | ; -- 11: 1/4 453 | ; -- 454 | rNR32 EQU $FF1C 455 | rAUD3LEVEL EQU rNR32 456 | 457 | 458 | ; -- 459 | ; -- AUD3LOW/NR33 ($FF1D) 460 | ; -- Frequency lo (W) 461 | ; -- 462 | ; -- see AUD1LOW for info 463 | ; -- 464 | rNR33 EQU $FF1D 465 | rAUD3LOW EQU rNR33 466 | 467 | 468 | ; -- 469 | ; -- AUD3HIGH/NR34 ($FF1E) 470 | ; -- Frequency hi (W) 471 | ; -- 472 | ; -- see AUD1HIGH for info 473 | ; -- 474 | rNR34 EQU $FF1E 475 | rAUD3HIGH EQU rNR34 476 | 477 | 478 | ; -- 479 | ; -- AUD4LEN/NR41 ($FF20) 480 | ; -- Sound length (R/W) 481 | ; -- 482 | ; -- Bit 5-0 - Sound length data (# 0-63) 483 | ; -- 484 | rNR41 EQU $FF20 485 | rAUD4LEN EQU rNR41 486 | 487 | 488 | ; -- 489 | ; -- AUD4ENV/NR42 ($FF21) 490 | ; -- Envelope (R/W) 491 | ; -- 492 | ; -- see AUD1ENV for info 493 | ; -- 494 | rNR42 EQU $FF21 495 | rAUD4ENV EQU rNR42 496 | 497 | 498 | ; -- 499 | ; -- AUD4POLY/NR42 ($FF22) 500 | ; -- Polynomial counter (R/W) 501 | ; -- 502 | ; -- Bit 7-4 - Selection of the shift clock frequency of the (scf) 503 | ; -- polynomial counter (0000-1101) 504 | ; -- freqEQUdrf*1/2^scf (not sure) 505 | ; -- Bit 3 - Selection of the polynomial counter's step 506 | ; -- 0: 15 steps 507 | ; -- 1: 7 steps 508 | ; -- Bit 2-0 - Selection of the dividing ratio of frequencies (drf) 509 | ; -- 000: f/4 001: f/8 010: f/16 011: f/24 510 | ; -- 100: f/32 101: f/40 110: f/48 111: f/56 (fEQU4.194304 Mhz) 511 | ; -- 512 | rNR42_2 EQU $FF22 513 | rAUD4POLY EQU rNR42_2 514 | 515 | 516 | ; -- 517 | ; -- AUD4GO/NR43 ($FF23) 518 | ; -- (has wrong name and value (ff30) in Dr.Pan's doc!) 519 | ; -- 520 | ; -- Bit 7 - Inital 521 | ; -- Bit 6 - Counter/consecutive selection 522 | ; -- 523 | rNR43 EQU $FF23 524 | rAUD4GO EQU rNR43 ; silly name! 525 | 526 | ;*************************************************************************** 527 | ;* 528 | ;* Cart related 529 | ;* 530 | ;*************************************************************************** 531 | 532 | ROM_NOMBC EQU 0 533 | ROM_MBC1 EQU 1 534 | ROM_MBC1_RAM EQU 2 535 | ROM_MBC1_RAM_BAT EQU 3 536 | ROM_MBC2 EQU 5 537 | ROM_MBC2_BAT EQU 6 538 | ROM_NOMBC_RAM EQU 8 539 | ROM_NOMBC_RAM_BAT EQU 9 540 | 541 | ROM_SIZE_256KBIT EQU 0 542 | ROM_SIZE_512KBIT EQU 1 543 | ROM_SIZE_1M EQU 2 544 | ROM_SIZE_2M EQU 3 545 | ROM_SIZE_4M EQU 4 546 | ROM_SIZE_8M EQU 5 547 | ROM_SIZE_16M EQU 6 548 | 549 | ROM_SIZE_32KBYTE EQU 0 550 | ROM_SIZE_64KBYTE EQU 1 551 | ROM_SIZE_128KBYTE EQU 2 552 | ROM_SIZE_256KBYTE EQU 3 553 | ROM_SIZE_512KBYTE EQU 4 554 | ROM_SIZE_1MBYTE EQU 5 555 | ROM_SIZE_2MBYTE EQU 6 556 | 557 | RAM_SIZE_0KBIT EQU 0 558 | RAM_SIZE_16KBIT EQU 1 559 | RAM_SIZE_64KBIT EQU 2 560 | RAM_SIZE_256KBIT EQU 3 561 | RAM_SIZE_1MBIT EQU 4 562 | 563 | RAM_SIZE_0KBYTE EQU 0 564 | RAM_SIZE_2KBYTE EQU 1 565 | RAM_SIZE_8KBYTE EQU 2 566 | RAM_SIZE_32KBYTE EQU 3 567 | RAM_SIZE_128KBYTE EQU 4 568 | 569 | ;*************************************************************************** 570 | ;* 571 | ;* Keypad related 572 | ;* 573 | ;*************************************************************************** 574 | 575 | PADF_DOWN EQU $80 576 | PADF_UP EQU $40 577 | PADF_LEFT EQU $20 578 | PADF_RIGHT EQU $10 579 | PADF_START EQU $08 580 | PADF_SELECT EQU $04 581 | PADF_B EQU $02 582 | PADF_A EQU $01 583 | 584 | PADB_DOWN EQU $7 585 | PADB_UP EQU $6 586 | PADB_LEFT EQU $5 587 | PADB_RIGHT EQU $4 588 | PADB_START EQU $3 589 | PADB_SELECT EQU $2 590 | PADB_B EQU $1 591 | PADB_A EQU $0 592 | 593 | ;*************************************************************************** 594 | ;* 595 | ;* Screen related 596 | ;* 597 | ;*************************************************************************** 598 | 599 | SCRN_X EQU 160 ; Width of screen in pixels 600 | SCRN_Y EQU 144 ; Height of screen in pixels 601 | SCRN_X_B EQU 20 ; Width of screen in bytes 602 | SCRN_Y_B EQU 18 ; Height of screen in bytes 603 | 604 | SCRN_VX EQU 256 ; Virtual width of screen in pixels 605 | SCRN_VY EQU 256 ; Virtual height of screen in pixels 606 | SCRN_VX_B EQU 32 ; Virtual width of screen in bytes 607 | SCRN_VY_B EQU 32 ; Virtual height of screen in bytes 608 | 609 | NINTENDO_LOGO: MACRO 610 | ;* 611 | ;* Nintendo scrolling logo 612 | ;* (Code won't work on a real GameBoy) 613 | ;* (if next six lines are altered.) 614 | DB $CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83,$00,$0C,$00,$0D 615 | DB $00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6,$DD,$DD,$D9,$99 616 | DB $BB,$BB,$67,$63,$6E,$0E,$EC,$CC,$DD,$DC,$99,$9F,$BB,$B9,$33,$3E 617 | ENDM 618 | 619 | ROM_HEADER: MACRO 620 | ;* 621 | ;* Nintendo scrolling logo 622 | ;* (Code won't work on a real GameBoy) 623 | ;* (if next six lines are altered.) 624 | 625 | ; 0123456789ABCDEF 626 | DB $CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83,$00,$0C,$00,$0D 627 | DB $00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6,$DD,$DD,$D9,$99 628 | DB $BB,$BB,$67,$63,$6E,$0E,$EC,$CC,$DD,$DC,$99,$9F,$BB,$B9,$33,$3E 629 | 630 | DB "EXAMPLE",0,0,0,0,0,0,0,0 ; Cart name - 15bytes 631 | DB 0 ; $143 632 | DB 0,0 ; $144 - Licensee code (not important) 633 | DB 0 ; $146 - SGB Support indicator 634 | DB \1 ; $147 - Cart type 635 | DB \2 ; $148 - ROM Size 636 | DB \3 ; $149 - RAM Size 637 | DB 1 ; $14a - Destination code 638 | DB $33 ; $14b - Old licensee code 639 | DB 0 ; $14c - Mask ROM version 640 | DB 0 ; $14d - Complement check (important) 641 | DW 0 ; $14e - Checksum (not important) 642 | 643 | ENDM 644 | 645 | ENDC ;HARDWARE_INC 646 | -------------------------------------------------------------------------------- /palettely/inc/gbhw.inc: -------------------------------------------------------------------------------- 1 | ;* 2 | ;* GBHW.INC - Gameboy Hardware definitions for GALP 3 | ;* 4 | ;* by GABY. Inspired from work done by Carsten Sorensen & others. 5 | ;* 6 | ;* V1.0 - The original version 7 | ;* 8 | 9 | ; If all of these are already defined, don't do it again. 10 | 11 | IF !DEF(HARDWARE_INC) 12 | HARDWARE_INC SET 1 13 | 14 | rev_Check_hardware_inc: MACRO 15 | ;NOTE: REVISION NUMBER CHANGES MUST BE ADDED 16 | ;TO SECOND PARAMETER IN FOLLOWING LINE. 17 | IF \1 > 1.0 ;PUT REVISION NUMBER HERE 18 | WARN "Version \1 or later of 'gbhw.inc' is required." 19 | ENDC 20 | ENDM 21 | 22 | _HW EQU $FF00 23 | 24 | _VRAM EQU $8000 ; $8000->$A000 25 | _SCRN0 EQU $9800 ; $9800->$9BFF 26 | _SCRN1 EQU $9C00 ; $9C00->$9FFF 27 | _RAM EQU $C000 ; $C000->$E000 28 | _HRAM EQU $F800 ; $F800->$FFFE 29 | _OAMRAM EQU $FE00 ; $FE00->$FE9F 30 | _AUD3WAVERAM EQU $FF30 ; $FF30->$FF3F 31 | 32 | 33 | ; -- 34 | ; -- OAM flags 35 | ; -- 36 | 37 | OAMF_PRI EQU %10000000 ; Priority 38 | OAMF_YFLIP EQU %01000000 ; Y flip 39 | OAMF_XFLIP EQU %00100000 ; X flip 40 | OAMF_PAL0 EQU %00000000 ; Palette number; 0,1 41 | OAMF_PAL1 EQU %00010000 ; Palette number; 0,1 42 | 43 | 44 | ;*************************************************************************** 45 | ;* 46 | ;* Custom registers 47 | ;* 48 | ;*************************************************************************** 49 | 50 | ; -- 51 | ; -- P1 ($FF00) 52 | ; -- Register for reading joy pad info. (R/W) 53 | ; -- 54 | rP1 EQU $FF00 55 | 56 | P1F_5 EQU %00100000 ; P15 out port 57 | P1F_4 EQU %00010000 ; P14 out port 58 | P1F_3 EQU %00001000 ; P13 in port 59 | P1F_2 EQU %00000100 ; P12 in port 60 | P1F_1 EQU %00000010 ; P11 in port 61 | P1F_0 EQU %00000001 ; P10 in port 62 | 63 | 64 | ; -- 65 | ; -- LCDC ($FF40) 66 | ; -- LCD Control (R/W) 67 | ; -- 68 | rLCDC EQU $FF40 69 | 70 | LCDCF_OFF EQU %00000000 ; LCD Control Operation 71 | LCDCF_ON EQU %10000000 ; LCD Control Operation 72 | LCDCF_WIN9800 EQU %00000000 ; Window Tile Map Display Select 73 | LCDCF_WIN9C00 EQU %01000000 ; Window Tile Map Display Select 74 | LCDCF_WINOFF EQU %00000000 ; Window Display 75 | LCDCF_WINON EQU %00100000 ; Window Display 76 | LCDCF_BG8800 EQU %00000000 ; BG & Window Tile Data Select 77 | LCDCF_BG8000 EQU %00010000 ; BG & Window Tile Data Select 78 | LCDCF_BG9800 EQU %00000000 ; BG Tile Map Display Select 79 | LCDCF_BG9C00 EQU %00001000 ; BG Tile Map Display Select 80 | LCDCF_OBJ8 EQU %00000000 ; OBJ Construction 81 | LCDCF_OBJ16 EQU %00000100 ; OBJ Construction 82 | LCDCF_OBJOFF EQU %00000000 ; OBJ Display 83 | LCDCF_OBJON EQU %00000010 ; OBJ Display 84 | LCDCF_BGOFF EQU %00000000 ; BG Display 85 | LCDCF_BGON EQU %00000001 ; BG Display 86 | ; "Window Character Data Select" follows BG 87 | 88 | 89 | ; -- 90 | ; -- STAT ($FF41) 91 | ; -- LCDC Status (R/W) 92 | ; -- 93 | rSTAT EQU $FF41 94 | 95 | STATF_LYC EQU %01000000 ; LYCEQULY Coincidence (Selectable) 96 | STATF_MODE10 EQU %00100000 ; Mode 10 97 | STATF_MODE01 EQU %00010000 ; Mode 01 (V-Blank) 98 | STATF_MODE00 EQU %00001000 ; Mode 00 (H-Blank) 99 | STATF_LYCF EQU %00000100 ; Coincidence Flag 100 | STATF_HB EQU %00000000 ; H-Blank 101 | STATF_VB EQU %00000001 ; V-Blank 102 | STATF_OAM EQU %00000010 ; OAM-RAM is used by system 103 | STATF_LCD EQU %00000011 ; Both OAM and VRAM used by system 104 | STATF_BUSY EQU %00000010 ; When set, VRAM access is unsafe 105 | 106 | 107 | ; -- 108 | ; -- SCY ($FF42) 109 | ; -- Scroll Y (R/W) 110 | ; -- 111 | rSCY EQU $FF42 112 | 113 | 114 | ; -- 115 | ; -- SCY ($FF43) 116 | ; -- Scroll X (R/W) 117 | ; -- 118 | rSCX EQU $FF43 119 | 120 | 121 | ; -- 122 | ; -- LY ($FF44) 123 | ; -- LCDC Y-Coordinate (R) 124 | ; -- 125 | ; -- Values range from 0->153. 144->153 is the VBlank period. 126 | ; -- 127 | rLY EQU $FF44 128 | 129 | 130 | ; -- 131 | ; -- LYC ($FF45) 132 | ; -- LY Compare (R/W) 133 | ; -- 134 | ; -- When LYEQUEQULYC, STATF_LYCF will be set in STAT 135 | ; -- 136 | rLYC EQU $FF45 137 | 138 | 139 | ; -- 140 | ; -- DMA ($FF46) 141 | ; -- DMA Transfer and Start Address (W) 142 | ; -- 143 | rDMA EQU $FF46 144 | 145 | 146 | ; -- 147 | ; -- BGP ($FF47) 148 | ; -- BG Palette Data (W) 149 | ; -- 150 | ; -- Bit 7-6 - Intensity for %11 151 | ; -- Bit 5-4 - Intensity for %10 152 | ; -- Bit 3-2 - Intensity for %01 153 | ; -- Bit 1-0 - Intensity for %00 154 | ; -- 155 | rBGP EQU $FF47 156 | 157 | 158 | ; -- 159 | ; -- OBP0 ($FF48) 160 | ; -- Object Palette 0 Data (W) 161 | ; -- 162 | ; -- See BGP for info 163 | ; -- 164 | rOBP0 EQU $FF48 165 | 166 | 167 | ; -- 168 | ; -- OBP1 ($FF49) 169 | ; -- Object Palette 1 Data (W) 170 | ; -- 171 | ; -- See BGP for info 172 | ; -- 173 | rOBP1 EQU $FF49 174 | 175 | 176 | ; -- 177 | ; -- SB ($FF01) 178 | ; -- Serial Transfer Data (R/W) 179 | ; -- 180 | rSB EQU $FF01 181 | 182 | ; -- 183 | ; -- SC ($FF02) 184 | ; -- Serial I/O Control (R/W) 185 | ; -- 186 | rSC EQU $FF02 187 | 188 | ; -- 189 | ; -- DIV ($FF04) 190 | ; -- Divider register (R/W) 191 | ; -- 192 | rDIV EQU $FF04 193 | 194 | 195 | ; -- 196 | ; -- TIMA ($FF05) 197 | ; -- Timer counter (R/W) 198 | ; -- 199 | rTIMA EQU $FF05 200 | 201 | 202 | ; -- 203 | ; -- TMA ($FF06) 204 | ; -- Timer modulo (R/W) 205 | ; -- 206 | rTMA EQU $FF06 207 | 208 | 209 | ; -- 210 | ; -- TAC ($FF07) 211 | ; -- Timer control (R/W) 212 | ; -- 213 | rTAC EQU $FF07 214 | 215 | TACF_START EQU %00000100 216 | TACF_STOP EQU %00000000 217 | TACF_4KHZ EQU %00000000 218 | TACF_16KHZ EQU %00000011 219 | TACF_65KHZ EQU %00000010 220 | TACF_262KHZ EQU %00000001 221 | 222 | 223 | ; -- 224 | ; -- IF ($FF0F) 225 | ; -- Interrupt Flag (R/W) 226 | ; -- 227 | ; -- IE ($FFFF) 228 | ; -- Interrupt Enable (R/W) 229 | ; -- 230 | rIF EQU $FF0F 231 | rIE EQU $FFFF 232 | 233 | IEF_HILO EQU %00010000 ; Transition from High to Low of Pin number P10-P13 234 | IEF_SERIAL EQU %00001000 ; Serial I/O transfer end 235 | IEF_TIMER EQU %00000100 ; Timer Overflow 236 | IEF_LCDC EQU %00000010 ; LCDC (see STAT) 237 | IEF_VBLANK EQU %00000001 ; V-Blank 238 | 239 | 240 | ; -- 241 | ; -- WY ($FF4A) 242 | ; -- Window Y Position (R/W) 243 | ; -- 244 | ; -- 0 SO2 ON/OFF (Vin??) 269 | ; -- Bit 6-4 - SO2 output level (volume) (# 0-7) 270 | ; -- Bit 3 - Vin->SO1 ON/OFF (Vin??) 271 | ; -- Bit 2-0 - SO1 output level (volume) (# 0-7) 272 | ; -- 273 | rNR50 EQU $FF24 274 | rAUDVOL EQU rNR50 275 | 276 | 277 | ; -- 278 | ; -- AUDTERM/NR51 ($FF25) 279 | ; -- Selection of Sound output terminal (R/W) 280 | ; -- 281 | ; -- Bit 7 - Output sound 4 to SO2 terminal 282 | ; -- Bit 6 - Output sound 3 to SO2 terminal 283 | ; -- Bit 5 - Output sound 2 to SO2 terminal 284 | ; -- Bit 4 - Output sound 1 to SO2 terminal 285 | ; -- Bit 3 - Output sound 4 to SO1 terminal 286 | ; -- Bit 2 - Output sound 3 to SO1 terminal 287 | ; -- Bit 1 - Output sound 2 to SO1 terminal 288 | ; -- Bit 0 - Output sound 0 to SO1 terminal 289 | ; -- 290 | rNR51 EQU $FF25 291 | rAUDTERM EQU rNR51 292 | 293 | 294 | ; -- 295 | ; -- AUDENA/NR52 ($FF26) 296 | ; -- Sound on/off (R/W) 297 | ; -- 298 | ; -- Bit 7 - All sound on/off (sets all audio regs to 0!) 299 | ; -- Bit 3 - Sound 4 ON flag (doesn't work!) 300 | ; -- Bit 2 - Sound 3 ON flag (doesn't work!) 301 | ; -- Bit 1 - Sound 2 ON flag (doesn't work!) 302 | ; -- Bit 0 - Sound 1 ON flag (doesn't work!) 303 | ; -- 304 | rNR52 EQU $FF26 305 | rAUDENA EQU rNR52 306 | 307 | 308 | ;*************************************************************************** 309 | ;* 310 | ;* SoundChannel #1 registers 311 | ;* 312 | ;*************************************************************************** 313 | 314 | ; -- 315 | ; -- AUD1SWEEP/NR10 ($FF10) 316 | ; -- Sweep register (R/W) 317 | ; -- 318 | ; -- Bit 6-4 - Sweep Time 319 | ; -- Bit 3 - Sweep Increase/Decrease 320 | ; -- 0: Addition (frequency increases???) 321 | ; -- 1: Subtraction (frequency increases???) 322 | ; -- Bit 2-0 - Number of sweep shift (# 0-7) 323 | ; -- Sweep Time: (n*7.8ms) 324 | ; -- 325 | rNR10 EQU $FF10 326 | rAUD1SWEEP EQU rNR10 327 | 328 | 329 | ; -- 330 | ; -- AUD1LEN/NR11 ($FF11) 331 | ; -- Sound length/Wave pattern duty (R/W) 332 | ; -- 333 | ; -- Bit 7-6 - Wave Pattern Duty (00:12.5% 01:25% 10:50% 11:75%) 334 | ; -- Bit 5-0 - Sound length data (# 0-63) 335 | ; -- 336 | rNR11 EQU $FF11 337 | rAUD1LEN EQU rNR11 338 | 339 | 340 | ; -- 341 | ; -- AUD1ENV/NR12 ($FF12) 342 | ; -- Envelope (R/W) 343 | ; -- 344 | ; -- Bit 7-4 - Initial value of envelope 345 | ; -- Bit 3 - Envelope UP/DOWN 346 | ; -- 0: Decrease 347 | ; -- 1: Range of increase 348 | ; -- Bit 2-0 - Number of envelope sweep (# 0-7) 349 | ; -- 350 | rNR12 EQU $FF12 351 | rAUD1ENV EQU rNR12 352 | 353 | 354 | ; -- 355 | ; -- AUD1LOW/NR13 ($FF13) 356 | ; -- Frequency lo (W) 357 | ; -- 358 | rNR13 EQU $FF13 359 | rAUD1LOW EQU rNR13 360 | 361 | 362 | ; -- 363 | ; -- AUD1HIGH/NR14 ($FF14) 364 | ; -- Frequency hi (W) 365 | ; -- 366 | ; -- Bit 7 - Initial (when set, sound restarts) 367 | ; -- Bit 6 - Counter/consecutive selection 368 | ; -- Bit 2-0 - Frequency's higher 3 bits 369 | ; -- 370 | rNR14 EQU $FF14 371 | rAUD1HIGH EQU rNR14 372 | 373 | 374 | ;*************************************************************************** 375 | ;* 376 | ;* SoundChannel #2 registers 377 | ;* 378 | ;*************************************************************************** 379 | 380 | ; -- 381 | ; -- AUD2LEN/NR21 ($FF16) 382 | ; -- Sound Length; Wave Pattern Duty (R/W) 383 | ; -- 384 | ; -- see AUD1LEN for info 385 | ; -- 386 | rNR21 EQU $FF16 387 | rAUD2LEN EQU rNR21 388 | 389 | 390 | ; -- 391 | ; -- AUD2ENV/NR22 ($FF17) 392 | ; -- Envelope (R/W) 393 | ; -- 394 | ; -- see AUD1ENV for info 395 | ; -- 396 | rNR22 EQU $FF17 397 | rAUD2ENV EQU rNR22 398 | 399 | 400 | ; -- 401 | ; -- AUD2LOW/NR23 ($FF18) 402 | ; -- Frequency lo (W) 403 | ; -- 404 | rNR23 EQU $FF18 405 | rAUD2LOW EQU rNR23 406 | 407 | 408 | ; -- 409 | ; -- AUD2HIGH/NR24 ($FF19) 410 | ; -- Frequency hi (W) 411 | ; -- 412 | ; -- see AUD1HIGH for info 413 | ; -- 414 | rNR24 EQU $FF19 415 | rAUD2HIGH EQU rNR24 416 | 417 | 418 | ;*************************************************************************** 419 | ;* 420 | ;* SoundChannel #3 registers 421 | ;* 422 | ;*************************************************************************** 423 | 424 | ; -- 425 | ; -- AUD3ENA/NR30 ($FF1A) 426 | ; -- Sound on/off (R/W) 427 | ; -- 428 | ; -- Bit 7 - Sound ON/OFF (1EQUON,0EQUOFF) 429 | ; -- 430 | rNR30 EQU $FF1A 431 | rAUD3ENA EQU rNR30 432 | 433 | 434 | ; -- 435 | ; -- AUD3LEN/NR31 ($FF1B) 436 | ; -- Sound length (R/W) 437 | ; -- 438 | ; -- Bit 7-0 - Sound length 439 | ; -- 440 | rNR31 EQU $FF1B 441 | rAUD3LEN EQU rNR31 442 | 443 | 444 | ; -- 445 | ; -- AUD3LEVEL/NR32 ($FF1C) 446 | ; -- Select output level 447 | ; -- 448 | ; -- Bit 6-5 - Select output level 449 | ; -- 00: 0/1 (mute) 450 | ; -- 01: 1/1 451 | ; -- 10: 1/2 452 | ; -- 11: 1/4 453 | ; -- 454 | rNR32 EQU $FF1C 455 | rAUD3LEVEL EQU rNR32 456 | 457 | 458 | ; -- 459 | ; -- AUD3LOW/NR33 ($FF1D) 460 | ; -- Frequency lo (W) 461 | ; -- 462 | ; -- see AUD1LOW for info 463 | ; -- 464 | rNR33 EQU $FF1D 465 | rAUD3LOW EQU rNR33 466 | 467 | 468 | ; -- 469 | ; -- AUD3HIGH/NR34 ($FF1E) 470 | ; -- Frequency hi (W) 471 | ; -- 472 | ; -- see AUD1HIGH for info 473 | ; -- 474 | rNR34 EQU $FF1E 475 | rAUD3HIGH EQU rNR34 476 | 477 | 478 | ; -- 479 | ; -- AUD4LEN/NR41 ($FF20) 480 | ; -- Sound length (R/W) 481 | ; -- 482 | ; -- Bit 5-0 - Sound length data (# 0-63) 483 | ; -- 484 | rNR41 EQU $FF20 485 | rAUD4LEN EQU rNR41 486 | 487 | 488 | ; -- 489 | ; -- AUD4ENV/NR42 ($FF21) 490 | ; -- Envelope (R/W) 491 | ; -- 492 | ; -- see AUD1ENV for info 493 | ; -- 494 | rNR42 EQU $FF21 495 | rAUD4ENV EQU rNR42 496 | 497 | 498 | ; -- 499 | ; -- AUD4POLY/NR42 ($FF22) 500 | ; -- Polynomial counter (R/W) 501 | ; -- 502 | ; -- Bit 7-4 - Selection of the shift clock frequency of the (scf) 503 | ; -- polynomial counter (0000-1101) 504 | ; -- freqEQUdrf*1/2^scf (not sure) 505 | ; -- Bit 3 - Selection of the polynomial counter's step 506 | ; -- 0: 15 steps 507 | ; -- 1: 7 steps 508 | ; -- Bit 2-0 - Selection of the dividing ratio of frequencies (drf) 509 | ; -- 000: f/4 001: f/8 010: f/16 011: f/24 510 | ; -- 100: f/32 101: f/40 110: f/48 111: f/56 (fEQU4.194304 Mhz) 511 | ; -- 512 | rNR42_2 EQU $FF22 513 | rAUD4POLY EQU rNR42_2 514 | 515 | 516 | ; -- 517 | ; -- AUD4GO/NR43 ($FF23) 518 | ; -- (has wrong name and value (ff30) in Dr.Pan's doc!) 519 | ; -- 520 | ; -- Bit 7 - Inital 521 | ; -- Bit 6 - Counter/consecutive selection 522 | ; -- 523 | rNR43 EQU $FF23 524 | rAUD4GO EQU rNR43 ; silly name! 525 | 526 | ;*************************************************************************** 527 | ;* 528 | ;* Cart related 529 | ;* 530 | ;*************************************************************************** 531 | 532 | ROM_NOMBC EQU 0 533 | ROM_MBC1 EQU 1 534 | ROM_MBC1_RAM EQU 2 535 | ROM_MBC1_RAM_BAT EQU 3 536 | ROM_MBC2 EQU 5 537 | ROM_MBC2_BAT EQU 6 538 | ROM_NOMBC_RAM EQU 8 539 | ROM_NOMBC_RAM_BAT EQU 9 540 | 541 | ROM_SIZE_256KBIT EQU 0 542 | ROM_SIZE_512KBIT EQU 1 543 | ROM_SIZE_1M EQU 2 544 | ROM_SIZE_2M EQU 3 545 | ROM_SIZE_4M EQU 4 546 | ROM_SIZE_8M EQU 5 547 | ROM_SIZE_16M EQU 6 548 | 549 | ROM_SIZE_32KBYTE EQU 0 550 | ROM_SIZE_64KBYTE EQU 1 551 | ROM_SIZE_128KBYTE EQU 2 552 | ROM_SIZE_256KBYTE EQU 3 553 | ROM_SIZE_512KBYTE EQU 4 554 | ROM_SIZE_1MBYTE EQU 5 555 | ROM_SIZE_2MBYTE EQU 6 556 | 557 | RAM_SIZE_0KBIT EQU 0 558 | RAM_SIZE_16KBIT EQU 1 559 | RAM_SIZE_64KBIT EQU 2 560 | RAM_SIZE_256KBIT EQU 3 561 | RAM_SIZE_1MBIT EQU 4 562 | 563 | RAM_SIZE_0KBYTE EQU 0 564 | RAM_SIZE_2KBYTE EQU 1 565 | RAM_SIZE_8KBYTE EQU 2 566 | RAM_SIZE_32KBYTE EQU 3 567 | RAM_SIZE_128KBYTE EQU 4 568 | 569 | ;*************************************************************************** 570 | ;* 571 | ;* Keypad related 572 | ;* 573 | ;*************************************************************************** 574 | 575 | PADF_DOWN EQU $80 576 | PADF_UP EQU $40 577 | PADF_LEFT EQU $20 578 | PADF_RIGHT EQU $10 579 | PADF_START EQU $08 580 | PADF_SELECT EQU $04 581 | PADF_B EQU $02 582 | PADF_A EQU $01 583 | 584 | PADB_DOWN EQU $7 585 | PADB_UP EQU $6 586 | PADB_LEFT EQU $5 587 | PADB_RIGHT EQU $4 588 | PADB_START EQU $3 589 | PADB_SELECT EQU $2 590 | PADB_B EQU $1 591 | PADB_A EQU $0 592 | 593 | ;*************************************************************************** 594 | ;* 595 | ;* Screen related 596 | ;* 597 | ;*************************************************************************** 598 | 599 | SCRN_X EQU 160 ; Width of screen in pixels 600 | SCRN_Y EQU 144 ; Height of screen in pixels 601 | SCRN_X_B EQU 20 ; Width of screen in bytes 602 | SCRN_Y_B EQU 18 ; Height of screen in bytes 603 | 604 | SCRN_VX EQU 256 ; Virtual width of screen in pixels 605 | SCRN_VY EQU 256 ; Virtual height of screen in pixels 606 | SCRN_VX_B EQU 32 ; Virtual width of screen in bytes 607 | SCRN_VY_B EQU 32 ; Virtual height of screen in bytes 608 | 609 | NINTENDO_LOGO: MACRO 610 | ;* 611 | ;* Nintendo scrolling logo 612 | ;* (Code won't work on a real GameBoy) 613 | ;* (if next six lines are altered.) 614 | DB $CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83,$00,$0C,$00,$0D 615 | DB $00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6,$DD,$DD,$D9,$99 616 | DB $BB,$BB,$67,$63,$6E,$0E,$EC,$CC,$DD,$DC,$99,$9F,$BB,$B9,$33,$3E 617 | ENDM 618 | 619 | ROM_HEADER: MACRO 620 | ;* 621 | ;* Nintendo scrolling logo 622 | ;* (Code won't work on a real GameBoy) 623 | ;* (if next six lines are altered.) 624 | 625 | ; 0123456789ABCDEF 626 | DB $CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83,$00,$0C,$00,$0D 627 | DB $00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6,$DD,$DD,$D9,$99 628 | DB $BB,$BB,$67,$63,$6E,$0E,$EC,$CC,$DD,$DC,$99,$9F,$BB,$B9,$33,$3E 629 | 630 | DB "EXAMPLE",0,0,0,0,0,0,0,0 ; Cart name - 15bytes 631 | DB 0 ; $143 632 | DB 0,0 ; $144 - Licensee code (not important) 633 | DB 0 ; $146 - SGB Support indicator 634 | DB \1 ; $147 - Cart type 635 | DB \2 ; $148 - ROM Size 636 | DB \3 ; $149 - RAM Size 637 | DB 1 ; $14a - Destination code 638 | DB $33 ; $14b - Old licensee code 639 | DB 0 ; $14c - Mask ROM version 640 | DB 0 ; $14d - Complement check (important) 641 | DW 0 ; $14e - Checksum (not important) 642 | 643 | ENDM 644 | 645 | ENDC ;HARDWARE_INC 646 | -------------------------------------------------------------------------------- /statcount/src/statcount.sm83: -------------------------------------------------------------------------------- 1 | include "inc/hardware.inc" 2 | 3 | ;-------------------------------------------------------------------- 4 | ; # RAM MAP # 5 | ; $C000 - Last stored STAT value 6 | ; $C001 - NOP counter 7 | ; $C002 - Joypad Cooldown 8 | ;-------------------------------------------------------------------- 9 | 10 | section "VBlank", rom0[$0040] 11 | jp HandleVBlank 12 | section "LCDC", rom0[$0048] 13 | reti 14 | section "TimerOverflow", rom0[$0050] 15 | reti 16 | section "Serial", rom0[$0058] 17 | reti 18 | section "Joypad", rom0[$0060] 19 | reti 20 | 21 | 22 | 23 | section "EntryPoint", rom0[$100] 24 | di 25 | jp Main 26 | 27 | 28 | 29 | section "GameCode", rom0[$150] 30 | ;-------------------------------------------------------------------- 31 | ; Main Function of the Test 32 | ;-------------------------------------------------------------------- 33 | Main:: 34 | call StopLCD ; Stop LCD to load VRAM 35 | call InitTest ; Load VRAM, initialize regs 36 | 37 | MainLoop: 38 | halt 39 | jr MainLoop 40 | 41 | ;-------------------------------------------------------------------- 42 | ; VBlank Handler 43 | ;-------------------------------------------------------------------- 44 | HandleVBlank:: 45 | call PrintRegs ; Update register display 46 | 47 | ld a, [$C002] ; Load Joypad Lock counter 48 | and a ; Set zero flag if 0 49 | jp z, .skipCooldown ; If zero, skip cooldown 50 | dec a ; Decrement A by one 51 | ld [$C002], a ; Load A into Joypad Lock RAM 52 | reti ; And wait for next VBlank 53 | .skipCooldown 54 | 55 | ld a, %11101111 ; Check direction keys 56 | ld [rP1], a ; Load multiplexer value 57 | ld a, [rP1] ; Load button states 58 | 59 | bit 2, a ; Check if Up pressed 60 | jr nz, .upNotPressed ; If not, skip 61 | 62 | ; Joypad UP 63 | ld a, [$C001] ; Load NOP count into A 64 | inc a ; Increment A 65 | jr nz, .noUpOverflow ; Check if overflow 66 | ld a, $01 ; If so, load minimum 67 | .noUpOverflow 68 | ld [$C001], a ; Load A into NOP RAM 69 | ld a, $05 ; Load A with Joypad Lock 70 | ld [$C002], a ; And load into RAM 71 | reti ; And wait for next VBlank 72 | .upNotPressed 73 | 74 | bit 3, a ; Check if Down pressed 75 | jr nz, .downNotPressed ; If not, skip 76 | 77 | ; Joypad DOWN 78 | ld a, [$C001] ; Load NOP count into A 79 | dec a ; Decrement A 80 | jr nz, .noDownOverflow ; If not zero, skip reload 81 | ld a, $FF ; Otherwise load maximum 82 | .noDownOverflow 83 | ld [$C001], a ; Load A into NOP RAM 84 | ld a, $05 ; Load A with Joypad Lock 85 | ld [$C002], a ; And load into RAM 86 | reti ; And wait for next VBlank 87 | .downNotPressed 88 | 89 | ld a, %11011111 ; Check button keys 90 | ld [rP1], a ; Load multiplexer value 91 | ld a, [rP1] ; Load button states 92 | 93 | bit 3, a ; Check if Start pressed 94 | jr nz, .startNotPressed ; If not, skip 95 | 96 | ; Joypad START 97 | ld a, $05 ; Load A with Joypad Lock 98 | ld [$C002], a ; And load into RAM 99 | pop hl ; Pop return vector from stack 100 | jp RunTest ; Otherwise start test 101 | .startNotPressed 102 | reti 103 | 104 | ;-------------------------------------------------------------------- 105 | ; VBlank Handler 106 | ;-------------------------------------------------------------------- 107 | 108 | ;-------------------------------------------------------------------- 109 | ; Runs the test and updates values in RAM 110 | ;-------------------------------------------------------------------- 111 | RunTest:: 112 | di ; Disable interrupts for test 113 | call StopLCD ; Stop LCD while preparing test 114 | 115 | ld hl, nopBase ; Load clockslide base 116 | xor a ; Set A to 0 117 | ld d, a ; And load upper add byte 118 | ld a, [$C001] ; Load NOP count into A 119 | ld e, a ; Buffer NOP count in E 120 | ld a, $FF ; Set A to $FF 121 | sub e ; Subtract NOP count 122 | ld e, a ; Load lower add byte 123 | add hl, de ; Add clockslide offset to pointer 124 | 125 | ld c, $41 ; Load $41 for STAT read 126 | 127 | ld a, [$C001] ; Load NOP count into A 128 | cp 1 ; Check if running 1 NOP 129 | jr z, .singleNopTest ; If so, run different test routine 130 | 131 | ld a, %10000001 ; Enable LCD and Background 132 | ld [rLCDC], a 133 | 134 | jp hl ; Start clockslide NOPs 135 | 136 | .singleNopTest ; Skips JP HL, saving 1 NOP 137 | ld a, %10000001 ; Enable LCD and Background 138 | ld [rLCDC], a 139 | 140 | ld a, [$FF00+c] ; Acts as NOP before read 141 | ld [$C000], a ; Load STAT into memory 142 | jp PostTestCleanup 143 | 144 | ;-------------------------------------------------------------------- 145 | ; Disables LCD, prints test results, enables LCD, returns to Main 146 | ;-------------------------------------------------------------------- 147 | PostTestCleanup:: 148 | call StopLCD ; Stop LCD for cleanup 149 | call PrintRegs ; Print results 150 | 151 | ld hl, $98A1 ; X = 1, Y = 5 152 | ld de, strTest ; Load Test string 153 | call PrintStr ; And print 154 | 155 | ld a, [$C001] ; Get NOP value 156 | ld hl, StatTestData ; Load test data base pointer 157 | ld c, a ; Load NOP to lower addr byte 158 | xor a ; Clear A 159 | ld b, a ; Load $00 to higher addr byte 160 | add hl, bc ; Add test range offset to HL 161 | ld a, [$C000] ; Load logged STAT value 162 | cp a, [hl] ; Compare to test value 163 | jr nz, .testErr ; If match, do the following 164 | ld hl, $98A7 ; Otherwise load VRAM pointer 165 | ld de, strOK ; Load pointer to "OK" string 166 | call PrintStr ; Print string 167 | jr .endPostTest ; And skip to end of routine 168 | .testErr ; Otherwise, if STAT doesn't match 169 | push hl ; Preserve HL 170 | ld hl, $98A7 ; Load VRAM pointer 171 | ld de, strErr ; Load Error string 172 | call PrintStr ; And print string 173 | pop hl ; Restore HL 174 | ld a, [hl] ; Load expected value to A 175 | call AtoASCII ; And convert to ASCII 176 | ld hl, $98A8 ; Load VRAM pointer 177 | ld a, d ; Set first char 178 | ld [hli], a ; And load to VRAM 179 | ld a, e ; Set second char 180 | ld [hli], a ; And load to VRAM 181 | 182 | .endPostTest 183 | xor a ; Clear any remaining IRQs 184 | ld [rIF], a 185 | ei ; Re-Enable interrupts 186 | ld a, %10000001 ; Enable LCD and Background 187 | ld [rLCDC], a 188 | 189 | jp MainLoop ; Return to main loop 190 | 191 | ;-------------------------------------------------------------------- 192 | ; 253 NOPs followed by code to store STAT in RAM 193 | ; - 1 Cycle timeout by JP HL 194 | ; - 1 Cycle timeout by LD A, [$FF00+C] 195 | ; => 253 NOP instructions for 255 NOPs 196 | ; 197 | ; Prerequisite: 198 | ; - C must be loaded with $41 199 | ;-------------------------------------------------------------------- 200 | nopBase: 201 | REPT $FD 202 | nop 203 | ENDR 204 | ld a, [$FF00+c] ; Acts as NOP before read 205 | ld [$C000], a ; Load STAT into memory 206 | jp PostTestCleanup 207 | 208 | ;-------------------------------------------------------------------- 209 | ; Initializes Registers for Test 210 | ;-------------------------------------------------------------------- 211 | InitTest:: 212 | call InitRAM ; Initialize RAM with $00 213 | call LoadFont ; Load font tiles into VRAM 214 | 215 | ld hl, $9821 ; X = 1, Y = 1 216 | ld de, strSTAT ; Load STAT string 217 | call PrintStr ; And print 218 | 219 | ld hl, $9861 ; X = 1, Y = 3 220 | ld de, strNOP ; Load NOP string 221 | call PrintStr ; And print 222 | 223 | ld hl, $98A1 ; X = 1, Y = 5 224 | ld de, strTest ; Load Test string 225 | call PrintStr ; And print 226 | 227 | ld hl, $9901 ; X = 1, Y = 8 228 | ld de, strInstr ; Load 'Press START' string 229 | call PrintStr ; And print 230 | 231 | ld a, $01 ; Load A with minimum NOPs, 232 | ld [$C001], a ; load into NOP reg 233 | call PrintRegs ; and print to screen 234 | 235 | ld a, %11100100 ; Initialize BGP 236 | ld [rBGP], a 237 | 238 | ld a, $FF ; Effectively disable LYC 239 | ld [rLYC], a 240 | 241 | ld a, $01 ; Allow only VBlank IRQs 242 | ld [rIE], a 243 | xor a ; Clear any remaining IRQs 244 | ld [rIF], a 245 | ei ; Enable interrupts 246 | 247 | xor a ; Load A with 0 248 | ld [rSCY], a ; Initialize SCY 249 | ld [rSCX], a ; Initialize SCX 250 | ld [rNR52], a ; Turn off sound 251 | ld [rSTAT], a ; Disable all STAT triggers 252 | 253 | ld a, %10000001 ; Enable LCD and Background 254 | ld [rLCDC], a 255 | 256 | ret 257 | 258 | ;-------------------------------------------------------------------- 259 | ; Prints the values at $C000 and $C001 to the screen. 260 | ; 261 | ; Inputs: 262 | ; - [$C000] : STAT Value 263 | ; - [$C001] : NOP Value 264 | ;-------------------------------------------------------------------- 265 | PrintRegs:: 266 | ld a, [$C000] ; Get STAT value 267 | call AtoASCII ; Convert to ASCII 268 | ld hl, $9827 ; Load location on screen 269 | ld a, d ; Load upper byte 270 | ld [hli], a ; And print 271 | ld a, e ; Load lower byte 272 | ld [hli], a ; And print 273 | 274 | ld a, [$C001] ; Same as above 275 | call AtoASCII ; but for NOP value 276 | ld hl, $9867 277 | ld a, d 278 | ld [hli], a 279 | ld a, e 280 | ld [hli], a 281 | 282 | ret 283 | 284 | ;-------------------------------------------------------------------- 285 | ; Converts the value in A reg to two hex ASCII bytes 286 | ; 287 | ; Inputs: 288 | ; - A : Value to convert 289 | ; 290 | ; Outputs: 291 | ; - DE : ASCII bytes 292 | ; 293 | ; Source: 294 | ; https://stackoverflow.com/questions/22838444/convert-an-8bit-number-to-hex-in-z80-assembler 295 | ;-------------------------------------------------------------------- 296 | AtoASCII:: 297 | ld c, a 298 | call .num1 299 | ld d, a 300 | ld a, c 301 | call .num2 302 | ld e, a 303 | ret 304 | .num1 305 | rra 306 | rra 307 | rra 308 | rra 309 | .num2 310 | or $F0 311 | daa 312 | add a, $A0 313 | adc a, $40 314 | ret 315 | 316 | ;-------------------------------------------------------------------- 317 | ; Initializes RAM $C000-$CFFF with zero 318 | ;-------------------------------------------------------------------- 319 | InitRAM:: 320 | ld hl, $C000 321 | .initByteRAM 322 | xor a 323 | ld [hli], a 324 | ld a, h 325 | cp $D0 326 | jr nz, .initByteRAM 327 | ret 328 | 329 | ;-------------------------------------------------------------------- 330 | ; Loads font tiles into VRAM 331 | ;-------------------------------------------------------------------- 332 | LoadFont:: 333 | ld hl, $9000 ; Tile Data starting address 334 | ld de, FontTiles ; ROM Tile Pointer 335 | ld bc, FontTilesEnd - FontTiles ; Tile Data byte count 336 | .copyFont 337 | ld a, [de] ; Load A with tile data byte 338 | ld [hli], a ; And load into VRAM 339 | inc de ; Go to next byte in ROM 340 | dec bc ; And decrement count 341 | ld a, b ; Load high byte of count 342 | or c ; And OR with high byte 343 | jr nz, .copyFont ; Repeat if count is not 0 344 | ret 345 | 346 | ;-------------------------------------------------------------------- 347 | ; Copies tiles to display a given string to VRAM 348 | ; 349 | ; Inputs: 350 | ; - HL : Copy Destination 351 | ; - DE : String Pointer 352 | ;-------------------------------------------------------------------- 353 | PrintStr:: 354 | .copyString 355 | ld a, [de] ; Load string byte into A 356 | ld [hli], a ; And into VRAM 357 | inc de ; Increment string pointer 358 | and a ; And check if null byte 359 | jr nz, .copyString ; Repeat if not 360 | ret 361 | 362 | ;-------------------------------------------------------------------- 363 | ; Waits for VBlank then stops LCD 364 | ;-------------------------------------------------------------------- 365 | StopLCD:: 366 | call WaitVBlank ; Wait for VBlank 367 | xor a ; Set A to 0 368 | ld [rLCDC], a ; Load 0 to LCDC 369 | ret 370 | 371 | ;-------------------------------------------------------------------- 372 | ; Waits for VBlank then returns 373 | ;-------------------------------------------------------------------- 374 | WaitVBlank:: 375 | .vblLoop 376 | ld a, [rLY] ; Load current LY into A 377 | cp 144 ; Check if scanline is 144 (VBlank) 378 | jr nz, .vblLoop ; If not, repeat 379 | ret 380 | 381 | ;-------------------------------------------------------------------- 382 | ; 383 | ; # DATA SECTION 384 | ; 385 | ;-------------------------------------------------------------------- 386 | 387 | ;-------------------------------------------------------------------- 388 | ; Strings 389 | ;-------------------------------------------------------------------- 390 | section "Strings", rom0 391 | strSTAT: 392 | db "STAT: 00h", 0 393 | strNOP: 394 | db "NOPs: 00h", 0 395 | strInstr: 396 | db "Press START to run test", 0 397 | strTest: 398 | db "Test: ??", 0 399 | strOK: 400 | db "OK ", 0 401 | strErr: 402 | db "!00h", 0 403 | 404 | ;-------------------------------------------------------------------- 405 | ; STAT Tests 406 | ;-------------------------------------------------------------------- 407 | section "TestDataSTAT", rom0[$1000] 408 | StatTestData: 409 | 410 | ; Scanline 0 411 | ; NOP 0 cannot be read => unknown 412 | db $FF 413 | REPT 18 414 | db $80 415 | ENDR 416 | REPT 43 417 | db $83 418 | ENDR 419 | REPT 51 420 | db $80 421 | ENDR 422 | 423 | ; Scanline 1 424 | REPT 20 425 | db $82 426 | ENDR 427 | REPT 43 428 | db $83 429 | ENDR 430 | REPT 51 431 | db $80 432 | ENDR 433 | 434 | ; Scanline 2 435 | REPT 20 436 | db $82 437 | ENDR 438 | REPT 9 ; Only 9 more to add up to 256 bytes of test data 439 | db $83 440 | ENDR 441 | 442 | ;-------------------------------------------------------------------- 443 | ; Font Tile Data 444 | ;-------------------------------------------------------------------- 445 | section "Font", rom0 446 | FontTiles: 447 | incbin "inc/font.chr" 448 | FontTilesEnd: -------------------------------------------------------------------------------- /statcount/inc/hardware.inc: -------------------------------------------------------------------------------- 1 | ;* 2 | ;* Gameboy Hardware definitions 3 | ;* 4 | ;* Based on Jones' hardware.inc 5 | ;* And based on Carsten Sorensen's ideas. 6 | ;* 7 | ;* Rev 1.1 - 15-Jul-97 : Added define check 8 | ;* Rev 1.2 - 18-Jul-97 : Added revision check macro 9 | ;* Rev 1.3 - 19-Jul-97 : Modified for RGBASM V1.05 10 | ;* Rev 1.4 - 27-Jul-97 : Modified for new subroutine prefixes 11 | ;* Rev 1.5 - 15-Aug-97 : Added _HRAM, PAD, CART defines 12 | ;* : and Nintendo Logo 13 | ;* Rev 1.6 - 30-Nov-97 : Added rDIV, rTIMA, rTMA, & rTAC 14 | ;* Rev 1.7 - 31-Jan-98 : Added _SCRN0, _SCRN1 15 | ;* Rev 1.8 - 15-Feb-98 : Added rSB, rSC 16 | ;* Rev 1.9 - 16-Feb-98 : Converted I/O registers to $FFXX format 17 | ;* Rev 2.0 - : Added GBC registers 18 | ;* Rev 2.1 - : Added MBC5 & cart RAM enable/disable defines 19 | ;* Rev 2.2 - : Fixed NR42,NR43, & NR44 equates 20 | ;* Rev 2.3 - : Fixed incorrect _HRAM equate 21 | ;* Rev 2.4 - 27-Apr-13 : Added some cart defines (AntonioND) 22 | ;* Rev 2.5 - 03-May-15 : Fixed format (AntonioND) 23 | ;* Rev 2.6 - 09-Apr-16 : Added GBC OAM and cart defines (AntonioND) 24 | ;* Rev 2.7 - 19-Jan-19 : Added rPCMXX (ISSOtm) 25 | ;* Rev 2.8 - 03-Feb-19 : Added audio registers flags (Álvaro Cuesta) 26 | ;* Rev 2.9 - 28-Feb-20 : Added utility rP1 constants 27 | 28 | ; If all of these are already defined, don't do it again. 29 | 30 | IF !DEF(HARDWARE_INC) 31 | HARDWARE_INC SET 1 32 | 33 | rev_Check_hardware_inc : MACRO 34 | ;NOTE: REVISION NUMBER CHANGES MUST BE ADDED 35 | ;TO SECOND PARAMETER IN FOLLOWING LINE. 36 | IF \1 > 2.9 ;PUT REVISION NUMBER HERE 37 | WARN "Version \1 or later of 'hardware.inc' is required." 38 | ENDC 39 | ENDM 40 | 41 | _HW EQU $FF00 42 | 43 | _VRAM EQU $8000 ; $8000->$9FFF 44 | _SCRN0 EQU $9800 ; $9800->$9BFF 45 | _SCRN1 EQU $9C00 ; $9C00->$9FFF 46 | _SRAM EQU $A000 ; $A000->$BFFF 47 | _RAM EQU $C000 ; $C000->$DFFF 48 | _OAMRAM EQU $FE00 ; $FE00->$FE9F 49 | _AUD3WAVERAM EQU $FF30 ; $FF30->$FF3F 50 | _HRAM EQU $FF80 ; $FF80->$FFFE 51 | 52 | ; *** MBC5 Equates *** 53 | 54 | rRAMG EQU $0000 ; $0000->$1fff 55 | rROMB0 EQU $2000 ; $2000->$2fff 56 | rROMB1 EQU $3000 ; $3000->$3fff - If more than 256 ROM banks are present. 57 | rRAMB EQU $4000 ; $4000->$5fff - Bit 3 enables rumble (if present) 58 | 59 | 60 | ; -- 61 | ; -- OAM flags 62 | ; -- 63 | 64 | OAMF_PRI EQU %10000000 ; Priority 65 | OAMF_YFLIP EQU %01000000 ; Y flip 66 | OAMF_XFLIP EQU %00100000 ; X flip 67 | OAMF_PAL0 EQU %00000000 ; Palette number; 0,1 (DMG) 68 | OAMF_PAL1 EQU %00010000 ; Palette number; 0,1 (DMG) 69 | OAMF_BANK0 EQU %00000000 ; Bank number; 0,1 (GBC) 70 | OAMF_BANK1 EQU %00001000 ; Bank number; 0,1 (GBC) 71 | 72 | OAMF_PALMASK EQU %00000111 ; Palette (GBC) 73 | 74 | OAMB_PRI EQU 7 ; Priority 75 | OAMB_YFLIP EQU 6 ; Y flip 76 | OAMB_XFLIP EQU 5 ; X flip 77 | OAMB_PAL1 EQU 4 ; Palette number; 0,1 (DMG) 78 | OAMB_BANK1 EQU 3 ; Bank number; 0,1 (GBC) 79 | 80 | 81 | ;*************************************************************************** 82 | ;* 83 | ;* Custom registers 84 | ;* 85 | ;*************************************************************************** 86 | 87 | ; -- 88 | ; -- P1 ($FF00) 89 | ; -- Register for reading joy pad info. (R/W) 90 | ; -- 91 | rP1 EQU $FF00 92 | 93 | P1F_5 EQU %00100000 ; P15 out port, set to 0 to get buttons 94 | P1F_4 EQU %00010000 ; P14 out port, set to 0 to get dpad 95 | P1F_3 EQU %00001000 ; P13 in port 96 | P1F_2 EQU %00000100 ; P12 in port 97 | P1F_1 EQU %00000010 ; P11 in port 98 | P1F_0 EQU %00000001 ; P10 in port 99 | 100 | P1F_GET_DPAD EQU P1F_5 101 | P1F_GET_BTN EQU P1F_4 102 | P1F_GET_NONE EQU P1F_4 | P1F_5 103 | 104 | ; -- 105 | ; -- SB ($FF01) 106 | ; -- Serial Transfer Data (R/W) 107 | ; -- 108 | rSB EQU $FF01 109 | 110 | ; -- 111 | ; -- SC ($FF02) 112 | ; -- Serial I/O Control (R/W) 113 | ; -- 114 | rSC EQU $FF02 115 | 116 | ; -- 117 | ; -- DIV ($FF04) 118 | ; -- Divider register (R/W) 119 | ; -- 120 | rDIV EQU $FF04 121 | 122 | 123 | ; -- 124 | ; -- TIMA ($FF05) 125 | ; -- Timer counter (R/W) 126 | ; -- 127 | rTIMA EQU $FF05 128 | 129 | 130 | ; -- 131 | ; -- TMA ($FF06) 132 | ; -- Timer modulo (R/W) 133 | ; -- 134 | rTMA EQU $FF06 135 | 136 | 137 | ; -- 138 | ; -- TAC ($FF07) 139 | ; -- Timer control (R/W) 140 | ; -- 141 | rTAC EQU $FF07 142 | 143 | TACF_START EQU %00000100 144 | TACF_STOP EQU %00000000 145 | TACF_4KHZ EQU %00000000 146 | TACF_16KHZ EQU %00000011 147 | TACF_65KHZ EQU %00000010 148 | TACF_262KHZ EQU %00000001 149 | 150 | ; -- 151 | ; -- IF ($FF0F) 152 | ; -- Interrupt Flag (R/W) 153 | ; -- 154 | rIF EQU $FF0F 155 | 156 | ; -- 157 | ; -- LCDC ($FF40) 158 | ; -- LCD Control (R/W) 159 | ; -- 160 | rLCDC EQU $FF40 161 | 162 | LCDCF_OFF EQU %00000000 ; LCD Control Operation 163 | LCDCF_ON EQU %10000000 ; LCD Control Operation 164 | LCDCF_WIN9800 EQU %00000000 ; Window Tile Map Display Select 165 | LCDCF_WIN9C00 EQU %01000000 ; Window Tile Map Display Select 166 | LCDCF_WINOFF EQU %00000000 ; Window Display 167 | LCDCF_WINON EQU %00100000 ; Window Display 168 | LCDCF_BG8800 EQU %00000000 ; BG & Window Tile Data Select 169 | LCDCF_BG8000 EQU %00010000 ; BG & Window Tile Data Select 170 | LCDCF_BG9800 EQU %00000000 ; BG Tile Map Display Select 171 | LCDCF_BG9C00 EQU %00001000 ; BG Tile Map Display Select 172 | LCDCF_OBJ8 EQU %00000000 ; OBJ Construction 173 | LCDCF_OBJ16 EQU %00000100 ; OBJ Construction 174 | LCDCF_OBJOFF EQU %00000000 ; OBJ Display 175 | LCDCF_OBJON EQU %00000010 ; OBJ Display 176 | LCDCF_BGOFF EQU %00000000 ; BG Display 177 | LCDCF_BGON EQU %00000001 ; BG Display 178 | ; "Window Character Data Select" follows BG 179 | 180 | 181 | ; -- 182 | ; -- STAT ($FF41) 183 | ; -- LCDC Status (R/W) 184 | ; -- 185 | rSTAT EQU $FF41 186 | 187 | STATF_LYC EQU %01000000 ; LYCEQULY Coincidence (Selectable) 188 | STATF_MODE10 EQU %00100000 ; Mode 10 189 | STATF_MODE01 EQU %00010000 ; Mode 01 (V-Blank) 190 | STATF_MODE00 EQU %00001000 ; Mode 00 (H-Blank) 191 | STATF_LYCF EQU %00000100 ; Coincidence Flag 192 | STATF_HB EQU %00000000 ; H-Blank 193 | STATF_VB EQU %00000001 ; V-Blank 194 | STATF_OAM EQU %00000010 ; OAM-RAM is used by system 195 | STATF_LCD EQU %00000011 ; Both OAM and VRAM used by system 196 | STATF_BUSY EQU %00000010 ; When set, VRAM access is unsafe 197 | 198 | 199 | ; -- 200 | ; -- SCY ($FF42) 201 | ; -- Scroll Y (R/W) 202 | ; -- 203 | rSCY EQU $FF42 204 | 205 | 206 | ; -- 207 | ; -- SCY ($FF43) 208 | ; -- Scroll X (R/W) 209 | ; -- 210 | rSCX EQU $FF43 211 | 212 | 213 | ; -- 214 | ; -- LY ($FF44) 215 | ; -- LCDC Y-Coordinate (R) 216 | ; -- 217 | ; -- Values range from 0->153. 144->153 is the VBlank period. 218 | ; -- 219 | rLY EQU $FF44 220 | 221 | 222 | ; -- 223 | ; -- LYC ($FF45) 224 | ; -- LY Compare (R/W) 225 | ; -- 226 | ; -- When LYEQUEQULYC, STATF_LYCF will be set in STAT 227 | ; -- 228 | rLYC EQU $FF45 229 | 230 | 231 | ; -- 232 | ; -- DMA ($FF46) 233 | ; -- DMA Transfer and Start Address (W) 234 | ; -- 235 | rDMA EQU $FF46 236 | 237 | 238 | ; -- 239 | ; -- BGP ($FF47) 240 | ; -- BG Palette Data (W) 241 | ; -- 242 | ; -- Bit 7-6 - Intensity for %11 243 | ; -- Bit 5-4 - Intensity for %10 244 | ; -- Bit 3-2 - Intensity for %01 245 | ; -- Bit 1-0 - Intensity for %00 246 | ; -- 247 | rBGP EQU $FF47 248 | 249 | 250 | ; -- 251 | ; -- OBP0 ($FF48) 252 | ; -- Object Palette 0 Data (W) 253 | ; -- 254 | ; -- See BGP for info 255 | ; -- 256 | rOBP0 EQU $FF48 257 | 258 | 259 | ; -- 260 | ; -- OBP1 ($FF49) 261 | ; -- Object Palette 1 Data (W) 262 | ; -- 263 | ; -- See BGP for info 264 | ; -- 265 | rOBP1 EQU $FF49 266 | 267 | 268 | ; -- 269 | ; -- WY ($FF4A) 270 | ; -- Window Y Position (R/W) 271 | ; -- 272 | ; -- 0 SO2 ON/OFF (Vin??) 404 | ; -- Bit 6-4 - SO2 output level (volume) (# 0-7) 405 | ; -- Bit 3 - Vin->SO1 ON/OFF (Vin??) 406 | ; -- Bit 2-0 - SO1 output level (volume) (# 0-7) 407 | ; -- 408 | rNR50 EQU $FF24 409 | rAUDVOL EQU rNR50 410 | 411 | AUDVOL_VIN_LEFT EQU %10000000 ; SO2 412 | AUDVOL_VIN_RIGHT EQU %00001000 ; SO1 413 | 414 | 415 | ; -- 416 | ; -- AUDTERM/NR51 ($FF25) 417 | ; -- Selection of Sound output terminal (R/W) 418 | ; -- 419 | ; -- Bit 7 - Output sound 4 to SO2 terminal 420 | ; -- Bit 6 - Output sound 3 to SO2 terminal 421 | ; -- Bit 5 - Output sound 2 to SO2 terminal 422 | ; -- Bit 4 - Output sound 1 to SO2 terminal 423 | ; -- Bit 3 - Output sound 4 to SO1 terminal 424 | ; -- Bit 2 - Output sound 3 to SO1 terminal 425 | ; -- Bit 1 - Output sound 2 to SO1 terminal 426 | ; -- Bit 0 - Output sound 0 to SO1 terminal 427 | ; -- 428 | rNR51 EQU $FF25 429 | rAUDTERM EQU rNR51 430 | 431 | ; SO2 432 | AUDTERM_4_LEFT EQU %10000000 433 | AUDTERM_3_LEFT EQU %01000000 434 | AUDTERM_2_LEFT EQU %00100000 435 | AUDTERM_1_LEFT EQU %00010000 436 | ; SO1 437 | AUDTERM_4_RIGHT EQU %00001000 438 | AUDTERM_3_RIGHT EQU %00000100 439 | AUDTERM_2_RIGHT EQU %00000010 440 | AUDTERM_1_RIGHT EQU %00000001 441 | 442 | 443 | ; -- 444 | ; -- AUDENA/NR52 ($FF26) 445 | ; -- Sound on/off (R/W) 446 | ; -- 447 | ; -- Bit 7 - All sound on/off (sets all audio regs to 0!) 448 | ; -- Bit 3 - Sound 4 ON flag (doesn't work!) 449 | ; -- Bit 2 - Sound 3 ON flag (doesn't work!) 450 | ; -- Bit 1 - Sound 2 ON flag (doesn't work!) 451 | ; -- Bit 0 - Sound 1 ON flag (doesn't work!) 452 | ; -- 453 | rNR52 EQU $FF26 454 | rAUDENA EQU rNR52 455 | 456 | AUDENA_ON EQU %10000000 457 | AUDENA_OFF EQU %00000000 ; sets all audio regs to 0! 458 | 459 | 460 | ;*************************************************************************** 461 | ;* 462 | ;* SoundChannel #1 registers 463 | ;* 464 | ;*************************************************************************** 465 | 466 | ; -- 467 | ; -- AUD1SWEEP/NR10 ($FF10) 468 | ; -- Sweep register (R/W) 469 | ; -- 470 | ; -- Bit 6-4 - Sweep Time 471 | ; -- Bit 3 - Sweep Increase/Decrease 472 | ; -- 0: Addition (frequency increases???) 473 | ; -- 1: Subtraction (frequency increases???) 474 | ; -- Bit 2-0 - Number of sweep shift (# 0-7) 475 | ; -- Sweep Time: (n*7.8ms) 476 | ; -- 477 | rNR10 EQU $FF10 478 | rAUD1SWEEP EQU rNR10 479 | 480 | AUD1SWEEP_UP EQU %00000000 481 | AUD1SWEEP_DOWN EQU %00001000 482 | 483 | 484 | ; -- 485 | ; -- AUD1LEN/NR11 ($FF11) 486 | ; -- Sound length/Wave pattern duty (R/W) 487 | ; -- 488 | ; -- Bit 7-6 - Wave Pattern Duty (00:12.5% 01:25% 10:50% 11:75%) 489 | ; -- Bit 5-0 - Sound length data (# 0-63) 490 | ; -- 491 | rNR11 EQU $FF11 492 | rAUD1LEN EQU rNR11 493 | 494 | 495 | ; -- 496 | ; -- AUD1ENV/NR12 ($FF12) 497 | ; -- Envelope (R/W) 498 | ; -- 499 | ; -- Bit 7-4 - Initial value of envelope 500 | ; -- Bit 3 - Envelope UP/DOWN 501 | ; -- 0: Decrease 502 | ; -- 1: Range of increase 503 | ; -- Bit 2-0 - Number of envelope sweep (# 0-7) 504 | ; -- 505 | rNR12 EQU $FF12 506 | rAUD1ENV EQU rNR12 507 | 508 | 509 | ; -- 510 | ; -- AUD1LOW/NR13 ($FF13) 511 | ; -- Frequency lo (W) 512 | ; -- 513 | rNR13 EQU $FF13 514 | rAUD1LOW EQU rNR13 515 | 516 | 517 | ; -- 518 | ; -- AUD1HIGH/NR14 ($FF14) 519 | ; -- Frequency hi (W) 520 | ; -- 521 | ; -- Bit 7 - Initial (when set, sound restarts) 522 | ; -- Bit 6 - Counter/consecutive selection 523 | ; -- Bit 2-0 - Frequency's higher 3 bits 524 | ; -- 525 | rNR14 EQU $FF14 526 | rAUD1HIGH EQU rNR14 527 | 528 | 529 | ;*************************************************************************** 530 | ;* 531 | ;* SoundChannel #2 registers 532 | ;* 533 | ;*************************************************************************** 534 | 535 | ; -- 536 | ; -- AUD2LEN/NR21 ($FF16) 537 | ; -- Sound Length; Wave Pattern Duty (R/W) 538 | ; -- 539 | ; -- see AUD1LEN for info 540 | ; -- 541 | rNR21 EQU $FF16 542 | rAUD2LEN EQU rNR21 543 | 544 | 545 | ; -- 546 | ; -- AUD2ENV/NR22 ($FF17) 547 | ; -- Envelope (R/W) 548 | ; -- 549 | ; -- see AUD1ENV for info 550 | ; -- 551 | rNR22 EQU $FF17 552 | rAUD2ENV EQU rNR22 553 | 554 | 555 | ; -- 556 | ; -- AUD2LOW/NR23 ($FF18) 557 | ; -- Frequency lo (W) 558 | ; -- 559 | rNR23 EQU $FF18 560 | rAUD2LOW EQU rNR23 561 | 562 | 563 | ; -- 564 | ; -- AUD2HIGH/NR24 ($FF19) 565 | ; -- Frequency hi (W) 566 | ; -- 567 | ; -- see AUD1HIGH for info 568 | ; -- 569 | rNR24 EQU $FF19 570 | rAUD2HIGH EQU rNR24 571 | 572 | 573 | ;*************************************************************************** 574 | ;* 575 | ;* SoundChannel #3 registers 576 | ;* 577 | ;*************************************************************************** 578 | 579 | ; -- 580 | ; -- AUD3ENA/NR30 ($FF1A) 581 | ; -- Sound on/off (R/W) 582 | ; -- 583 | ; -- Bit 7 - Sound ON/OFF (1EQUON,0EQUOFF) 584 | ; -- 585 | rNR30 EQU $FF1A 586 | rAUD3ENA EQU rNR30 587 | 588 | 589 | ; -- 590 | ; -- AUD3LEN/NR31 ($FF1B) 591 | ; -- Sound length (R/W) 592 | ; -- 593 | ; -- Bit 7-0 - Sound length 594 | ; -- 595 | rNR31 EQU $FF1B 596 | rAUD3LEN EQU rNR31 597 | 598 | 599 | ; -- 600 | ; -- AUD3LEVEL/NR32 ($FF1C) 601 | ; -- Select output level 602 | ; -- 603 | ; -- Bit 6-5 - Select output level 604 | ; -- 00: 0/1 (mute) 605 | ; -- 01: 1/1 606 | ; -- 10: 1/2 607 | ; -- 11: 1/4 608 | ; -- 609 | rNR32 EQU $FF1C 610 | rAUD3LEVEL EQU rNR32 611 | 612 | 613 | ; -- 614 | ; -- AUD3LOW/NR33 ($FF1D) 615 | ; -- Frequency lo (W) 616 | ; -- 617 | ; -- see AUD1LOW for info 618 | ; -- 619 | rNR33 EQU $FF1D 620 | rAUD3LOW EQU rNR33 621 | 622 | 623 | ; -- 624 | ; -- AUD3HIGH/NR34 ($FF1E) 625 | ; -- Frequency hi (W) 626 | ; -- 627 | ; -- see AUD1HIGH for info 628 | ; -- 629 | rNR34 EQU $FF1E 630 | rAUD3HIGH EQU rNR34 631 | 632 | 633 | ; -- 634 | ; -- AUD4LEN/NR41 ($FF20) 635 | ; -- Sound length (R/W) 636 | ; -- 637 | ; -- Bit 5-0 - Sound length data (# 0-63) 638 | ; -- 639 | rNR41 EQU $FF20 640 | rAUD4LEN EQU rNR41 641 | 642 | 643 | ; -- 644 | ; -- AUD4ENV/NR42 ($FF21) 645 | ; -- Envelope (R/W) 646 | ; -- 647 | ; -- see AUD1ENV for info 648 | ; -- 649 | rNR42 EQU $FF21 650 | rAUD4ENV EQU rNR42 651 | 652 | 653 | ; -- 654 | ; -- AUD4POLY/NR43 ($FF22) 655 | ; -- Polynomial counter (R/W) 656 | ; -- 657 | ; -- Bit 7-4 - Selection of the shift clock frequency of the (scf) 658 | ; -- polynomial counter (0000-1101) 659 | ; -- freqEQUdrf*1/2^scf (not sure) 660 | ; -- Bit 3 - Selection of the polynomial counter's step 661 | ; -- 0: 15 steps 662 | ; -- 1: 7 steps 663 | ; -- Bit 2-0 - Selection of the dividing ratio of frequencies (drf) 664 | ; -- 000: f/4 001: f/8 010: f/16 011: f/24 665 | ; -- 100: f/32 101: f/40 110: f/48 111: f/56 (fEQU4.194304 Mhz) 666 | ; -- 667 | rNR43 EQU $FF22 668 | rAUD4POLY EQU rNR43 669 | 670 | 671 | ; -- 672 | ; -- AUD4GO/NR44 ($FF23) 673 | ; -- (has wrong name and value (ff30) in Dr.Pan's doc!) 674 | ; -- 675 | ; -- Bit 7 - Inital 676 | ; -- Bit 6 - Counter/consecutive selection 677 | ; -- 678 | rNR44 EQU $FF23 679 | rAUD4GO EQU rNR44 ; silly name! 680 | 681 | 682 | ; -- 683 | ; -- PCM12 ($FF76) 684 | ; -- Sound channel 1&2 PCM amplitude (R) 685 | ; -- 686 | ; -- Bit 7-4 - Copy of sound channel 2's PCM amplitude 687 | ; -- Bit 3-0 - Copy of sound channel 1's PCM amplitude 688 | ; -- 689 | rPCM12 EQU $FF76 690 | 691 | 692 | ; -- 693 | ; -- PCM34 ($FF77) 694 | ; -- Sound channel 3&4 PCM amplitude (R) 695 | ; -- 696 | ; -- Bit 7-4 - Copy of sound channel 4's PCM amplitude 697 | ; -- Bit 3-0 - Copy of sound channel 3's PCM amplitude 698 | ; -- 699 | rPCM34 EQU $FF77 700 | 701 | 702 | ;*************************************************************************** 703 | ;* 704 | ;* Flags common to multiple sound channels 705 | ;* 706 | ;*************************************************************************** 707 | 708 | ; -- 709 | ; -- Square wave duty cycle 710 | ; -- 711 | ; -- Can be used with AUD1LEN and AUD2LEN 712 | ; -- See AUD1LEN for more info 713 | ; -- 714 | AUDLEN_DUTY_12_5 EQU %00000000 ; 12.5% 715 | AUDLEN_DUTY_25 EQU %01000000 ; 25% 716 | AUDLEN_DUTY_50 EQU %10000000 ; 50% 717 | AUDLEN_DUTY_75 EQU %11000000 ; 75% 718 | 719 | 720 | ; -- 721 | ; -- Audio envelope flags 722 | ; -- 723 | ; -- Can be used with AUD1ENV, AUD2ENV, AUD4ENV 724 | ; -- See AUD1ENV for more info 725 | ; -- 726 | AUDENV_UP EQU %00001000 727 | AUDENV_DOWN EQU %00000000 728 | 729 | 730 | ; -- 731 | ; -- Audio trigger flags 732 | ; -- 733 | ; -- Can be used with AUD1HIGH, AUD2HIGH, AUD3HIGH 734 | ; -- See AUD1HIGH for more info 735 | ; -- 736 | 737 | AUDHIGH_RESTART EQU %10000000 738 | AUDHIGH_LENGTH_ON EQU %01000000 739 | AUDHIGH_LENGTH_OFF EQU %00000000 740 | 741 | 742 | ;*************************************************************************** 743 | ;* 744 | ;* Cart related 745 | ;* 746 | ;*************************************************************************** 747 | 748 | CART_COMPATIBLE_DMG EQU $00 749 | CART_COMPATIBLE_DMG_GBC EQU $80 750 | CART_COMPATIBLE_GBC EQU $C0 751 | 752 | CART_ROM EQU $00 753 | CART_ROM_MBC1 EQU $01 754 | CART_ROM_MBC1_RAM EQU $02 755 | CART_ROM_MBC1_RAM_BAT EQU $03 756 | CART_ROM_MBC2 EQU $05 757 | CART_ROM_MBC2_BAT EQU $06 758 | CART_ROM_RAM EQU $08 759 | CART_ROM_RAM_BAT EQU $09 760 | CART_ROM_MBC3_BAT_RTC EQU $0F 761 | CART_ROM_MBC3_RAM_BAT_RTC EQU $10 762 | CART_ROM_MBC3 EQU $11 763 | CART_ROM_MBC3_RAM EQU $12 764 | CART_ROM_MBC3_RAM_BAT EQU $13 765 | CART_ROM_MBC5 EQU $19 766 | CART_ROM_MBC5_BAT EQU $1A 767 | CART_ROM_MBC5_RAM_BAT EQU $1B 768 | CART_ROM_MBC5_RUMBLE EQU $1C 769 | CART_ROM_MBC5_RAM_RUMBLE EQU $1D 770 | CART_ROM_MBC5_RAM_BAT_RUMBLE EQU $1E 771 | CART_ROM_MBC7_RAM_BAT_GYRO EQU $22 772 | CART_ROM_POCKET_CAMERA EQU $FC 773 | 774 | CART_ROM_256K EQU 0 ; 2 banks 775 | CART_ROM_512K EQU 1 ; 4 banks 776 | CART_ROM_1M EQU 2 ; 8 banks 777 | CART_ROM_2M EQU 3 ; 16 banks 778 | CART_ROM_4M EQU 4 ; 32 banks 779 | CART_ROM_8M EQU 5 ; 64 banks 780 | CART_ROM_16M EQU 6 ; 128 banks 781 | CART_ROM_32M EQU 7 ; 256 banks 782 | CART_ROM_64M EQU 8 ; 512 banks 783 | 784 | CART_RAM_NONE EQU 0 785 | CART_RAM_16K EQU 1 ; 1 incomplete bank 786 | CART_RAM_64K EQU 2 ; 1 bank 787 | CART_RAM_256K EQU 3 ; 4 banks 788 | CART_RAM_1M EQU 4 ; 16 banks 789 | 790 | CART_RAM_ENABLE EQU $0A 791 | CART_RAM_DISABLE EQU $00 792 | 793 | ;*************************************************************************** 794 | ;* 795 | ;* Keypad related 796 | ;* 797 | ;*************************************************************************** 798 | 799 | PADF_DOWN EQU $80 800 | PADF_UP EQU $40 801 | PADF_LEFT EQU $20 802 | PADF_RIGHT EQU $10 803 | PADF_START EQU $08 804 | PADF_SELECT EQU $04 805 | PADF_B EQU $02 806 | PADF_A EQU $01 807 | 808 | PADB_DOWN EQU $7 809 | PADB_UP EQU $6 810 | PADB_LEFT EQU $5 811 | PADB_RIGHT EQU $4 812 | PADB_START EQU $3 813 | PADB_SELECT EQU $2 814 | PADB_B EQU $1 815 | PADB_A EQU $0 816 | 817 | ;*************************************************************************** 818 | ;* 819 | ;* Screen related 820 | ;* 821 | ;*************************************************************************** 822 | 823 | SCRN_X EQU 160 ; Width of screen in pixels 824 | SCRN_Y EQU 144 ; Height of screen in pixels 825 | SCRN_X_B EQU 20 ; Width of screen in bytes 826 | SCRN_Y_B EQU 18 ; Height of screen in bytes 827 | 828 | SCRN_VX EQU 256 ; Virtual width of screen in pixels 829 | SCRN_VY EQU 256 ; Virtual height of screen in pixels 830 | SCRN_VX_B EQU 32 ; Virtual width of screen in bytes 831 | SCRN_VY_B EQU 32 ; Virtual height of screen in bytes 832 | 833 | ;* 834 | ;* Nintendo scrolling logo 835 | ;* (Code won't work on a real GameBoy) 836 | ;* (if next lines are altered.) 837 | NINTENDO_LOGO : MACRO 838 | DB $CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83,$00,$0C,$00,$0D 839 | DB $00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6,$DD,$DD,$D9,$99 840 | DB $BB,$BB,$67,$63,$6E,$0E,$EC,$CC,$DD,$DC,$99,$9F,$BB,$B9,$33,$3E 841 | ENDM 842 | 843 | ENDC ;HARDWARE_INC 844 | --------------------------------------------------------------------------------