Merge branch 'master' of https://github.com/pret/pokecrystal into pokecrystal-mobile-en-rebase

This commit is contained in:
vulcandth 2022-10-04 09:09:14 -05:00
commit aa82112708
91 changed files with 229 additions and 525 deletions

View File

@ -16,7 +16,7 @@ jobs:
uses: actions/checkout@master
with:
path: rgbds
ref: v0.5.2
ref: v0.6.0
repository: gbdev/rgbds
- name: Install rgbds

6
FAQ.md
View File

@ -41,15 +41,15 @@ You need to install `gcc`. If you're using Cygwin, re-run its setup, and at "Sel
### "ERROR: `UNION` already defined"
Download [**rgbds 0.5.2**][rgbds] or newer. Older versions will not work.
Download [**rgbds 0.6.0**][rgbds] or newer. Older versions will not work.
### "ERROR: Macro not defined"
Download [**rgbds 0.5.2**][rgbds] or newer. Older versions will not work.
Download [**rgbds 0.6.0**][rgbds] or newer. Older versions will not work.
### "Expression must be 8-bit"
Download [**rgbds 0.5.2**][rgbds] or newer. Older versions will not work.
Download [**rgbds 0.6.0**][rgbds] or newer. Older versions will not work.
### "Segmentation fault" from `rgbgfx`

View File

@ -42,9 +42,9 @@ Run setup and leave the default settings. At the "**Select Packages**" step, cho
Double click on the text that says "**Skip**" next to each package to select the most recent version to install.
Then follow the [**rgbds** instructions](https://rgbds.gbdev.io/install#pre-built) for Windows with Cygwin to install **rgbds 0.5.2**.
Then follow the [**rgbds** instructions](https://rgbds.gbdev.io/install#pre-built) for Windows with Cygwin to install **rgbds 0.6.0**.
**Note:** If you already have an older rgbds, you will need to update to 0.5.2. Ignore this if you have never installed rgbds before. If a version newer than 0.5.2 does not work, try downloading 0.5.2.
**Note:** If you already have an older rgbds, you will need to update to 0.6.0. Ignore this if you have never installed rgbds before. If a version newer than 0.6.0 does not work, try downloading 0.6.0.
Now open the **Cygwin terminal** and enter the following commands.
@ -67,7 +67,7 @@ Install [**Homebrew**](https://brew.sh/). Follow the official instructions.
Open **Terminal** and prepare to enter commands.
Then follow the [**rgbds** instructions](https://rgbds.gbdev.io/install#pre-built) for macOS to install **rgbds 0.5.2**.
Then follow the [**rgbds** instructions](https://rgbds.gbdev.io/install#pre-built) for macOS to install **rgbds 0.6.0**.
Now you're ready to [build **pokecrystal**](#build-pokecrystal).
@ -84,7 +84,7 @@ To install the software required for **pokecrystal**:
sudo apt-get install make gcc git
```
Then follow the [**rgbds** instructions](https://rgbds.gbdev.io/install#building-from-source) to build **rgbds 0.5.2** from source.
Then follow the [**rgbds** instructions](https://rgbds.gbdev.io/install#building-from-source) to build **rgbds 0.6.0** from source.
### OpenSUSE
@ -94,7 +94,7 @@ To install the software required for **pokecrystal**:
sudo zypper install make gcc git
```
Then follow the [**rgbds** instructions](https://rgbds.gbdev.io/install#building-from-source) to build **rgbds 0.5.2** from source.
Then follow the [**rgbds** instructions](https://rgbds.gbdev.io/install#building-from-source) to build **rgbds 0.6.0** from source.
### Arch Linux
@ -104,9 +104,9 @@ To install the software required for **pokecrystal**:
sudo pacman -S make gcc git rgbds
```
Then follow the [**rgbds** instructions](https://rgbds.gbdev.io/install#pre-built) for Arch Linux to install **rgbds 0.5.2**.
Then follow the [**rgbds** instructions](https://rgbds.gbdev.io/install#pre-built) for Arch Linux to install **rgbds 0.6.0**.
If you want to compile and install **rgbds** yourself instead, then follow the [**rgbds** instructions](https://rgbds.gbdev.io/install#building-from-source) to build **rgbds 0.5.2** from source.
If you want to compile and install **rgbds** yourself instead, then follow the [**rgbds** instructions](https://rgbds.gbdev.io/install#building-from-source) to build **rgbds 0.6.0** from source.
### Termux
@ -122,7 +122,7 @@ To install **rgbds**:
sudo apt install rgbds
```
If you want to compile and install **rgbds** yourself instead, then follow the [**rgbds** instructions](https://rgbds.gbdev.io/install#building-from-source) to build **rgbds 0.5.2** from source.
If you want to compile and install **rgbds** yourself instead, then follow the [**rgbds** instructions](https://rgbds.gbdev.io/install#building-from-source) to build **rgbds 0.6.0** from source.
### Other distros
@ -133,7 +133,7 @@ If your distro is not listed here, try to find the required software in its repo
- `git`
- `rgbds`
If `rgbds` is not available, you'll need to follow the [**rgbds** instructions](https://rgbds.gbdev.io/install#building-from-source) to build **rgbds 0.5.2** from source.
If `rgbds` is not available, you'll need to follow the [**rgbds** instructions](https://rgbds.gbdev.io/install#building-from-source) to build **rgbds 0.6.0** from source.
Now you're ready to [build **pokecrystal**](#build-pokecrystal).
@ -161,12 +161,12 @@ make crystal11
### Build with a local rgbds version
If you have different projects that require different versions of `rgbds`, it might not be convenient to install rgbds 0.5.2 globally. Instead, you can put its files in a directory within pokecrystal, such as `pokecrystal/rgbds-0.5.2/`. Then specify it when you run `make`:
If you have different projects that require different versions of `rgbds`, it might not be convenient to install rgbds 0.6.0 globally. Instead, you can put its files in a directory within pokecrystal, such as `pokecrystal/rgbds-0.6.0/`. Then specify it when you run `make`:
```bash
make RGBDS=rgbds-0.5.2/
make RGBDS=rgbds-0.6.0/
```
```bash
make RGBDS=rgbds-0.5.2/ crystal11
make RGBDS=rgbds-0.6.0/ crystal11
```

View File

@ -108,7 +108,7 @@ tools:
$(MAKE) -C tools/
RGBASMFLAGS = -L -Weverything -Wnumeric-string=2 -Wtruncation=1
RGBASMFLAGS = -hL -Q8 -P includes.asm -Weverything -Wnumeric-string=2 -Wtruncation=1
# Create a sym/map for debug purposes if `make` run with `DEBUG=1`
ifeq ($(DEBUG),1)
RGBASMFLAGS += -E
@ -126,13 +126,13 @@ $(pokecrystal11_vc_obj): RGBASMFLAGS += -D _CRYSTAL11 -D _CRYSTAL11_VC
tools/make_patch $*_vc.sym $^ $@
rgbdscheck.o: rgbdscheck.asm
$(RGBASM) -o $@ $<
$(RGBASM) $(RGBASMFLAGS) -o $@ $<
# The dep rules have to be explicit or else missing files won't be reported.
# As a side effect, they're evaluated immediately instead of when the rule is invoked.
# It doesn't look like $(shell) can be deferred so there might not be a better way.
define DEP
$1: $2 $$(shell tools/scan_includes $2) | rgbdscheck.o
$1: $2 $$(shell tools/scan_includes $2) | includes.asm rgbdscheck.o
$$(RGBASM) $$(RGBASMFLAGS) -o $$@ $$<
endef
@ -152,8 +152,8 @@ $(foreach obj, $(pokecrystal11_debug_obj), $(eval $(call DEP,$(obj),$(obj:11_deb
$(foreach obj, $(pokecrystal11_vc_obj), $(eval $(call DEP,$(obj),$(obj:11_vc.o=.asm))))
# Dependencies for VC files that need to run scan_includes
%.constants.sym: %.constants.asm $(shell tools/scan_includes %.constants.asm) | rgbdscheck.o
$(RGBASM) $< > $@
%.constants.sym: %.constants.asm $(shell tools/scan_includes %.constants.asm) | includes.asm rgbdscheck.o
$(RGBASM) $(RGBASMFLAGS) $< > $@
endif
@ -166,18 +166,10 @@ pokecrystal_debug_opt = -Cjv -t PM_CRYSTAL -i BXTE -n 0 -k 01 -l 0x33 -m 0x10
pokecrystal11_debug_opt = -Cjv -t PM_CRYSTAL -i BXTE -n 1 -k 01 -l 0x33 -m 0x10 -r 5 -p 0
pokecrystal11_vc_opt = -Cjv -t PM_CRYSTAL -i BXTE -n 1 -k 01 -l 0x33 -m 0x10 -r 5 -p 0
pokecrystal_base = us
pokecrystal11_base = us
pokecrystal_au_base = us
pokecrystal_eu_base = us
pokecrystal11_vc_base = us
pokecrystal_debug_base = dbg
pokecrystal11_debug_base = dbg
%.gbc: $$(%_obj) layout.link
$(RGBLINK) -n $*.sym -m $*.map -l layout.link -o $@ $(filter %.o,$^)
$(RGBFIX) $($*_opt) $@
#tools/stadium --base $($*_base) $@
#tools/stadium $@
### LZ compression rules
@ -223,14 +215,15 @@ gfx/pokemon/girafarig/front.animated.tilemap: gfx/pokemon/girafarig/front.2bpp g
### Misc file-specific graphics rules
gfx/pokemon/%/back.2bpp: rgbgfx += -h
gfx/pokemon/%/back.2bpp: rgbgfx += -Z -c embedded
gfx/pokemon/%/front.2bpp: rgbgfx += -c embedded
gfx/trainers/%.2bpp: rgbgfx += -h
gfx/trainers/%.2bpp: rgbgfx += -Z -c embedded
gfx/pokemon/egg/unused_front.2bpp: rgbgfx += -h
gfx/pokemon/egg/unused_front.2bpp: rgbgfx += -Z
gfx/new_game/shrink1.2bpp: rgbgfx += -h
gfx/new_game/shrink2.2bpp: rgbgfx += -h
gfx/new_game/shrink1.2bpp: rgbgfx += -Z
gfx/new_game/shrink2.2bpp: rgbgfx += -Z
gfx/mail/dragonite.1bpp: tools/gfx += --remove-whitespace
gfx/mail/large_note.1bpp: tools/gfx += --remove-whitespace
@ -240,7 +233,7 @@ gfx/mail/litebluemail_border.1bpp: tools/gfx += --remove-whitespace
gfx/pokedex/pokedex.2bpp: tools/gfx += --trim-whitespace
gfx/pokedex/pokedex_sgb.2bpp: tools/gfx += --trim-whitespace
gfx/pokedex/question_mark.2bpp: rgbgfx += -h
gfx/pokedex/question_mark.2bpp: rgbgfx += -Z
gfx/pokedex/slowpoke.2bpp: tools/gfx += --trim-whitespace
gfx/pokedex/slowpoke_mobile.2bpp: tools/gfx += --trim-whitespace
@ -282,13 +275,13 @@ gfx/battle_anims/rocks.2bpp: tools/gfx += --remove-whitespace
gfx/battle_anims/skyattack.2bpp: tools/gfx += --remove-whitespace
gfx/battle_anims/status.2bpp: tools/gfx += --remove-whitespace
gfx/player/chris.2bpp: rgbgfx += -h
gfx/player/chris_back.2bpp: rgbgfx += -h
gfx/player/kris.2bpp: rgbgfx += -h
gfx/player/kris_back.2bpp: rgbgfx += -h
gfx/player/chris.2bpp: rgbgfx += -Z
gfx/player/chris_back.2bpp: rgbgfx += -Z
gfx/player/kris.2bpp: rgbgfx += -Z
gfx/player/kris_back.2bpp: rgbgfx += -Z
gfx/trainer_card/chris_card.2bpp: rgbgfx += -h
gfx/trainer_card/kris_card.2bpp: rgbgfx += -h
gfx/trainer_card/chris_card.2bpp: rgbgfx += -Z
gfx/trainer_card/kris_card.2bpp: rgbgfx += -Z
gfx/trainer_card/leaders.2bpp: tools/gfx += --trim-whitespace
gfx/overworld/chris_fish.2bpp: tools/gfx += --trim-whitespace
@ -296,7 +289,7 @@ gfx/overworld/kris_fish.2bpp: tools/gfx += --trim-whitespace
gfx/sprites/big_onix.2bpp: tools/gfx += --remove-whitespace --remove-xflip
gfx/battle/dude.2bpp: rgbgfx += -h
gfx/battle/dude.2bpp: rgbgfx += -Z
gfx/font/unused_bold_font.1bpp: tools/gfx += --trim-whitespace

View File

@ -1,6 +1,3 @@
INCLUDE "constants.asm"
SECTION "Audio", ROMX
INCLUDE "audio/engine.asm"

View File

@ -420,5 +420,12 @@
; ASCII charmap, for mobile functions
pushc
newcharmap ascii
newcharmap ascii
DEF PRINTABLE_ASCII EQUS " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz\{|}~"
for i, STRLEN("{PRINTABLE_ASCII}")
charmap STRSUB("{PRINTABLE_ASCII}", i + 1, 1), i + $20
endr
charmap "\t", $09
charmap "\n", $0a
charmap "\r", $0d
popc

View File

@ -1,6 +1,3 @@
INCLUDE "constants.asm"
SECTION "Maps", ROMX
INCLUDE "data/maps/maps.asm"

View File

@ -1,6 +1,3 @@
INCLUDE "constants.asm"
SECTION "Pokedex Entries 001-064", ROMX
BulbasaurPokedexEntry:: INCLUDE "data/pokemon/dex_entries/bulbasaur.asm"

View File

@ -1,6 +1,3 @@
INCLUDE "constants.asm"
SECTION "Egg Moves", ROMX
; All instances of Charm, Steel Wing, Sweet Scent, and Lovely Kiss were

View File

@ -1,6 +1,3 @@
INCLUDE "constants.asm"
SECTION "Evolutions and Attacks", ROMX
; Evos+attacks data structure:

View File

@ -1,6 +1,3 @@
INCLUDE "constants.asm"
SECTION "Text 1", ROMX
INCLUDE "data/text/common_1.asm"

View File

@ -771,11 +771,9 @@ And on `sine_table` in [macros/data.asm](https://github.com/pret/pokecrystal/blo
```asm
MACRO sine_table
; \1 samples of sin(x) from x=0 to x<32768 (pi radians)
DEF x = 0
rept \1
dw (sin(x) + (sin(x) & $ff)) >> 8 ; round up
DEF x += DIV(32768, \1) ; a circle has 65536 "degrees"
; \1 samples of sin(x) from x=0 to x<0.5 turns (pi radians)
for x, \1
dw sin(x * 0.5 / (\1))
endr
ENDM
```

View File

@ -53,7 +53,7 @@ CheckOppositeGender:
ld [wTempMonDVs], a
ld a, [hl]
ld [wTempMonDVs + 1], a
ld a, 3
ld a, TEMPMON
ld [wMonType], a
farcall GetGender
pop bc

View File

@ -562,7 +562,7 @@ DayCare_InitBreeding:
ld [wTempMonDVs + 1], a
ld a, [wBreedMon1Species]
ld [wCurPartySpecies], a
ld a, $3
ld a, TEMPMON
ld [wMonType], a
ld a, [wBreedMon1Species]
cp DITTO

View File

@ -799,6 +799,7 @@ ReceiveInfraredLEDOn:
xor a
ldh [rIF], a
halt
nop
ldh a, [c]
bit rRP_RECEIVING, a
jr z, .recv_loop
@ -813,6 +814,7 @@ ReceiveInfraredLEDOff:
xor a
ldh [rIF], a
halt
nop
ldh a, [c]
bit rRP_RECEIVING, a
jr nz, .no_recv_loop
@ -829,6 +831,7 @@ SendInfraredLEDOn:
xor a
ldh [rIF], a
halt
nop
jr .wait
SendInfraredLEDOff:
@ -841,6 +844,7 @@ SendInfraredLEDOff:
xor a
ldh [rIF], a
halt
nop
jr .wait
InitializeIRCommunicationRoles:
@ -1037,6 +1041,7 @@ SendIRDataMessage:
xor a
ldh [rIF], a
halt
nop
ld a, rRP_ENABLE_READ_MASK | (1 << rRP_LED_ON)
ldh [rRP], a
; Turn the LED off for longer if the bit is 1
@ -1057,6 +1062,7 @@ SendIRDataMessage:
xor a
ldh [rIF], a
halt
nop
.no_halt
ldh a, [hMGNumBits]
dec a
@ -1070,6 +1076,7 @@ SendIRDataMessage:
xor a
ldh [rIF], a
halt
nop
ld d, 5
call SendInfraredLEDOn

View File

@ -1,6 +1,3 @@
INCLUDE "constants.asm"
SECTION "Credits", ROMX
Credits::

View File

@ -1,6 +1,3 @@
INCLUDE "constants.asm"
SECTION "Events", ROMX
OverworldLoop::

View File

@ -1079,7 +1079,7 @@ PCMonInfo:
hlcoord 1, 12
call PrintLevel
ld a, $3
ld a, TEMPMON
ld [wMonType], a
farcall GetGender
jr c, .skip_gender

View File

@ -1,6 +1,3 @@
INCLUDE "constants.asm"
; PokemonPicPointers and UnownPicPointers are assumed to start at the same
; address, but in different banks. This is enforced in layout.link.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 B

After

Width:  |  Height:  |  Size: 241 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 326 B

After

Width:  |  Height:  |  Size: 377 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 243 B

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 347 B

After

Width:  |  Height:  |  Size: 436 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 B

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 363 B

After

Width:  |  Height:  |  Size: 440 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 252 B

After

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 423 B

After

Width:  |  Height:  |  Size: 467 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 238 B

After

Width:  |  Height:  |  Size: 222 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 320 B

After

Width:  |  Height:  |  Size: 373 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 259 B

After

Width:  |  Height:  |  Size: 243 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 327 B

After

Width:  |  Height:  |  Size: 403 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 B

After

Width:  |  Height:  |  Size: 241 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 334 B

After

Width:  |  Height:  |  Size: 365 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 287 B

After

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 380 B

After

Width:  |  Height:  |  Size: 437 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 B

After

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 B

After

Width:  |  Height:  |  Size: 297 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 236 B

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 297 B

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 B

After

Width:  |  Height:  |  Size: 216 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 341 B

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 B

After

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 305 B

After

Width:  |  Height:  |  Size: 362 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 303 B

After

Width:  |  Height:  |  Size: 287 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 423 B

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 252 B

After

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 397 B

After

Width:  |  Height:  |  Size: 472 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 B

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 414 B

After

Width:  |  Height:  |  Size: 481 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 224 B

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 273 B

After

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 215 B

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 277 B

After

Width:  |  Height:  |  Size: 316 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 219 B

After

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 254 B

After

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 265 B

After

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 340 B

After

Width:  |  Height:  |  Size: 366 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 220 B

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 331 B

After

Width:  |  Height:  |  Size: 370 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 273 B

After

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 380 B

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 260 B

After

Width:  |  Height:  |  Size: 244 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 331 B

After

Width:  |  Height:  |  Size: 376 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 255 B

After

Width:  |  Height:  |  Size: 239 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 386 B

After

Width:  |  Height:  |  Size: 438 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 B

After

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 323 B

After

Width:  |  Height:  |  Size: 363 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 248 B

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 337 B

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 225 B

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 367 B

After

Width:  |  Height:  |  Size: 375 B

View File

@ -1,5 +1,3 @@
INCLUDE "constants.asm"
MACRO tilecoll
; used in data/tilesets/*_collision.asm
db COLL_\1, COLL_\2, COLL_\3, COLL_\4

View File

@ -1,5 +1,3 @@
INCLUDE "constants.asm"
SECTION "NULL", ROM0
NULL::

View File

@ -5,7 +5,8 @@ DelayFrame::
; Wait for the next VBlank, halting to conserve battery
.halt
halt ; rgbasm adds a nop after this instruction by default
halt
nop
ld a, [wVBlankOccurred]
and a
jr nz, .halt

View File

@ -198,7 +198,7 @@ MACRO dict
jr nz, .not\@
ld a, \2
.not\@:
elif STRSUB("\2", 1, 1) == "."
elif !STRCMP(STRSUB("\2", 1, 1), ".")
; Locals can use a short jump
jr z, \2
else

View File

@ -1,6 +1,26 @@
INCLUDE "charmap.asm"
INCLUDE "macros.asm"
INCLUDE "macros/asserts.asm"
INCLUDE "macros/const.asm"
INCLUDE "macros/predef.asm"
INCLUDE "macros/farcall.asm"
INCLUDE "macros/data.asm"
INCLUDE "macros/code.asm"
INCLUDE "macros/gfx.asm"
INCLUDE "macros/coords.asm"
INCLUDE "macros/vc.asm"
INCLUDE "macros/scripts/audio.asm"
INCLUDE "macros/scripts/maps.asm"
INCLUDE "macros/scripts/events.asm"
INCLUDE "macros/scripts/text.asm"
INCLUDE "macros/scripts/movement.asm"
INCLUDE "macros/scripts/battle_commands.asm"
INCLUDE "macros/scripts/battle_anims.asm"
INCLUDE "macros/scripts/oam_anims.asm"
INCLUDE "macros/scripts/pic_anims.asm"
INCLUDE "macros/legacy.asm"
INCLUDE "constants/hardware_constants.asm"
INCLUDE "constants/deco_constants.asm"

View File

@ -1,12 +1,7 @@
; A library included as part of the Mobile Adapter GB SDK.
INCLUDE "macros/code.asm"
INCLUDE "macros/const.asm"
INCLUDE "macros/gfx.asm"
INCLUDE "constants/gfx_constants.asm"
INCLUDE "constants/hardware_constants.asm"
INCLUDE "constants/mobile_constants.asm"
INCLUDE "constants/text_constants.asm"
setcharmap ascii
SECTION "Mobile Adapter SDK Mail", ROMX

View File

@ -1,8 +1,6 @@
; A library included as part of the Mobile Adapter GB SDK.
INCLUDE "macros/const.asm"
INCLUDE "constants/hardware_constants.asm"
INCLUDE "constants/mobile_constants.asm"
setcharmap ascii
; Mobile Adapter protocol commands
DEF MOBILE_COMMAND_BEGIN_SESSION EQU $10

View File

@ -1,21 +0,0 @@
INCLUDE "macros/asserts.asm"
INCLUDE "macros/const.asm"
INCLUDE "macros/predef.asm"
INCLUDE "macros/farcall.asm"
INCLUDE "macros/data.asm"
INCLUDE "macros/code.asm"
INCLUDE "macros/gfx.asm"
INCLUDE "macros/coords.asm"
INCLUDE "macros/vc.asm"
INCLUDE "macros/scripts/audio.asm"
INCLUDE "macros/scripts/maps.asm"
INCLUDE "macros/scripts/events.asm"
INCLUDE "macros/scripts/text.asm"
INCLUDE "macros/scripts/movement.asm"
INCLUDE "macros/scripts/battle_commands.asm"
INCLUDE "macros/scripts/battle_anims.asm"
INCLUDE "macros/scripts/oam_anims.asm"
INCLUDE "macros/scripts/pic_anims.asm"
INCLUDE "macros/legacy.asm"

View File

@ -94,10 +94,8 @@ MACRO bcd
ENDM
MACRO sine_table
; \1 samples of sin(x) from x=0 to x<32768 (pi radians)
DEF x = 0
rept \1
dw (sin(x) + (sin(x) & $ff)) >> 8 ; round up
DEF x += DIV(32768, \1) ; a circle has 65536 "degrees"
; \1 samples of sin(x) from x=0 to x<0.5 turns (pi radians)
for x, \1
dw sin(x * 0.5 / (\1))
endr
ENDM

View File

@ -1,6 +1,3 @@
INCLUDE "constants.asm"
SECTION "bank1", ROMX
INCLUDE "engine/link/place_waiting_text.asm"

View File

@ -4634,7 +4634,10 @@ Function119e4f:
.loop2
ld a, [de]
inc de
pushc
setcharmap ascii
cp "\n"
popc
jr z, .newline
cp [hl]
jr nz, .unequal
@ -4659,7 +4662,10 @@ Function119e4f:
ld a, [hli]
ld [de], a
inc de
cp $d
pushc
setcharmap ascii
cp "\r"
popc
jr z, .finish
dec c
jr nz, .loop3

View File

@ -1,5 +1,3 @@
INCLUDE "constants.asm"
INCLUDE "macros/ram.asm"

View File

@ -1,18 +1,16 @@
MAJOR EQU 0
MINOR EQU 5
PATCH EQU 2
MINOR EQU 6
PATCH EQU 0
MACRO wrong_rgbds
fail "pokecrystal requires rgbds v0.5.2 or newer."
ENDM
WRONG_RGBDS EQUS "fail \"pokecrystal requires rgbds v0.6.0 or newer.\""
IF !DEF(__RGBDS_MAJOR__) || !DEF(__RGBDS_MINOR__) || !DEF(__RGBDS_PATCH__)
wrong_rgbds
WRONG_RGBDS
ELSE
IF (__RGBDS_MAJOR__ < MAJOR) || \
(__RGBDS_MAJOR__ == MAJOR && __RGBDS_MINOR__ < MINOR) || \
(__RGBDS_MAJOR__ == MAJOR && __RGBDS_MINOR__ == MINOR && __RGBDS_PATCH__ < PATCH) || \
(__RGBDS_MAJOR__ == MAJOR && __RGBDS_MINOR__ == MINOR && __RGBDS_PATCH__ == PATCH && DEF(__RGBDS_RC__))
wrong_rgbds
WRONG_RGBDS
ENDC
ENDC

View File

@ -39,7 +39,7 @@ function register_bank(amount) {
}
}
rom_bank && toupper($0) ~ /^[ \t]*EMPTY/ {
rom_bank && toupper($0) ~ /^[ \t]*EMPTY$/ {
# Empty bank
register_bank(16384)
}

View File

@ -1,69 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Usage: python3 free_space.py [BANK=none] [pokecrystal.map]
Calculate the free space in the ROM or its individual banks.
The BANK argument allows printing free space in one, all, or none of the ROM's banks.
Valid arguments are numbers (in decimal "42" or hexadecimal "0x2A"), "all" or "none".
If not specified, defaults to "none".
"""
import sys
from mapreader import MapReader
def main():
print_bank = 'none'
filename = 'pokecrystal.map'
for arg in sys.argv[1:]:
if arg.startswith('BANK='):
print_bank = arg.split('=', 1)[-1]
else:
filename = arg
if print_bank not in {'all', 'none'}:
try:
print_bank = (int(print_bank[2:], 16)
if print_bank.startswith('0x') or print_bank.startswith('0X')
else int(print_bank))
except ValueError:
error = f'Error: invalid BANK: {print_bank}'
if print_bank.isalnum():
error += f' (did you mean: 0x{print_bank}?)'
print(error, file=sys.stderr)
sys.exit(1)
num_banks = 0x80
bank_size = 0x4000 # bytes
total_size = num_banks * bank_size
reader = MapReader()
with open(filename, 'r', encoding='utf-8') as file:
reader.read_map_data(file.readlines())
free_space = 0
per_bank = []
default_bank_data = {'sections': [], 'used': 0, 'slack': bank_size}
for bank in range(num_banks):
bank_data = reader.bank_data['ROM0 bank' if bank == 0 else 'ROMX bank']
data = bank_data.get(bank, default_bank_data)
used, slack = data['used'], data['slack']
per_bank.append((used, slack))
free_space += slack
free_percent = 100 * free_space / total_size
print(f'Free space: {free_space}/{total_size} ({free_percent:.2f}%)')
if print_bank != 'none':
print()
print('bank, used, free')
for bank in range(num_banks):
used, slack = per_bank[bank]
if print_bank in {'all', bank}:
print(f'${bank:02X}, {used}, {slack}')
if __name__ == '__main__':
main()

View File

@ -1,173 +0,0 @@
# -*- coding: utf-8 -*-
# A library for parsing the pokecrystal.map file output by rgbds.
import re
class MapReader:
# {'ROM Bank': { 0: { 'sections': [ { 'beg': 1234,
# 'end': 5678,
# 'name': 'Section001',
# 'symbols': [ { 'symbol': 'Function1234',
# 'address: 1234,
# },
# ]
# },
# ],
# 'used': 1234,
# 'slack': 4567,
# },
# },
# 'OAM': { 'sections': [ { 'beg': 1234,
# 'end': 5678,
# 'name': 'Section002',
# 'symbols': [ { 'symbol': 'Data1234',
# 'address: 1234,
# },
# ]
# },
# ],
# 'used': 1234,
# 'slack': 4567,
# },
# }
#
bank_data = {}
bank_types = {
'HRAM' : { 'size': 0x80, 'banked': False, },
'OAM' : { 'size': 0xA0, 'banked': False, },
'ROM0 bank': { 'size': 0x4000, 'banked': True, },
'ROMX bank': { 'size': 0x4000, 'banked': True, },
'SRAM bank': { 'size': 0x2000, 'banked': True, },
'VRAM bank': { 'size': 0x1000, 'banked': True, },
'WRAM bank': { 'size': 0x2000, 'banked': True, },
}
# FSM states
INIT, BANK, SECTION = range(3)
# $506D-$519A ($012E bytes) ["Type Matchups"]
section_header_regex = re.compile('\$([0-9A-Fa-f]{4})-\$([0-9A-Fa-f]{4}) \(.*\) \["(.*)"\]')
# $506D = TypeMatchups
section_data_regex = re.compile('\$([0-9A-Fa-f]{4}) = (.*)')
# $3ED2 bytes
slack_regex = re.compile('\$([0-9A-Fa-f]{4}) bytes?')
def __init__(self, *args, **kwargs):
self.__dict__.update(kwargs)
def _parse_init(self, line):
line = line.split(':', 1)[0]
parts = line.split(' #', 1)
if (parts[0] in self.bank_types):
self._cur_bank_name = parts[0]
self._cur_bank_type = self.bank_types[self._cur_bank_name]
if (self._cur_bank_type['banked'] and len(parts) > 1):
parts[1] = parts[1].split(':', 1)[0]
parts[1] = parts[1].split(' ', 1)[0]
self._cur_bank = int(parts[1], 10)
if self._cur_bank_name not in self.bank_data:
self.bank_data[self._cur_bank_name] = {}
if self._cur_bank_type['banked']:
if self._cur_bank not in self.bank_data[self._cur_bank_name]:
self.bank_data[self._cur_bank_name][self._cur_bank] = {}
self._cur_data = self.bank_data[self._cur_bank_name][self._cur_bank]
else:
self._cur_data = self.bank_data[self._cur_bank_name]
if ({} == self._cur_data):
self._cur_data['sections'] = []
self._cur_data['used'] = 0
self._cur_data['slack'] = self._cur_bank_type['size']
return True
return False
def _parse_section_header(self, header):
section_data = self.section_header_regex.match(header)
if section_data is not None:
beg = int(section_data.group(1), 16)
end = int(section_data.group(2), 16)
name = section_data.group(3)
self._cur_section = {'beg': beg, 'end': end, 'name': name, 'symbols': []}
self._cur_data['sections'].append(self._cur_section)
return True
return False
def _parse_slack(self, data):
slack_data = self.slack_regex.match(data)
slack_bytes = int(slack_data.group(1), 16)
self._cur_data['slack'] = slack_bytes
used_bytes = 0
for s in self._cur_data['sections']:
used_bytes += s['end'] - s['beg'] + 1
self._cur_data['used'] = used_bytes
def read_map_data(self, map):
if type(map) is str:
map = map.split('\n')
self._state = MapReader.INIT
self._cur_bank_name = ''
self._cur_bank_type = {}
self._cur_bank = 0
self._cur_data = {}
for line in map:
line = line.rstrip()
if (MapReader.INIT == self._state):
if (self._parse_init(line)):
self._state = MapReader.BANK
elif (MapReader.BANK == self._state or MapReader.SECTION == self._state):
if ('' == line):
self._state = MapReader.INIT
else:
line = line.lstrip()
parts = line.split(': ', 1)
if (MapReader.SECTION == self._state):
section_data = self.section_data_regex.match(parts[0])
if section_data is not None:
address = int(section_data.group(1), 16)
name = section_data.group(2)
self._cur_section['symbols'].append({'name': name, 'address': address})
continue
if ('SECTION' == parts[0]):
if (self._parse_section_header(parts[1])):
self._state = MapReader.SECTION
elif ('SLACK' == parts[0]):
self._parse_slack(parts[1])
self._state = MapReader.INIT
elif ('EMPTY' == parts[0]):
self._cur_data = {'sections': [], 'used': 0, 'slack': self._cur_bank_type['size']}
self._state = MapReader.INIT
else:
pass
for k, v in self.bank_data.items():
if (self.bank_types[k]['banked']):
for _, vv in v.items():
vv['sections'].sort(key=lambda x: x['beg'])
for vvv in vv['sections']:
vvv['symbols'].sort(key=lambda x: x['address'])
else:
v['sections'].sort(key=lambda x: x['beg'])
for vv in v['sections']:
vv['symbols'].sort(key=lambda x: x['address'])

View File

@ -1,23 +1,18 @@
#define PROGRAM_NAME "stadium"
#define USAGE_OPTS "[-h|--help] [-b|--base us|eu|dbg] pokecrystal.gbc"
#define USAGE_OPTS "[-h|--help] [-e|--european] pokecrystal.gbc"
#include "common.h"
enum Base { BASE_NONE, BASE_US, BASE_EU, BASE_DEBUG };
void parse_args(int argc, char *argv[], enum Base *base) {
void parse_args(int argc, char *argv[], bool *european) {
struct option long_options[] = {
{"base", required_argument, 0, 'b'},
{"european", no_argument, 0, 'e'},
{"help", no_argument, 0, 'h'},
{0}
};
for (int opt; (opt = getopt_long(argc, argv, "b:h", long_options)) != -1;) {
for (int opt; (opt = getopt_long(argc, argv, "eh", long_options)) != -1;) {
switch (opt) {
case 'b':
*base = !strcmp(optarg, "us") ? BASE_US :
!strcmp(optarg, "eu") ? BASE_EU :
!strcmp(optarg, "dbg") ? BASE_DEBUG :
BASE_NONE;
case 'e':
*european = true;
break;
case 'h':
usage_exit(0);
@ -28,58 +23,110 @@ void parse_args(int argc, char *argv[], enum Base *base) {
}
}
// A matching ROM has 128 banks
#define NUMBANKS 128
// ROM banks are 0x4000 bytes
#define BANKSIZE 0x4000
// A matching ROM is 2 MB
#define ROMSIZE (NUMBANKS * BANKSIZE)
// The Game Boy cartridge header stores a global checksum at 0x014E-0x014F
#define GLOBALOFF 0x014E
// "base" data; Crystal-only
#define BASESIZE 24
// ASCII "N64PS3" header
// ASCII "base" header (Crystal only)
#define BASE10SIZE 6
uint8_t base10[BASE10SIZE] = {'b', 'a', 's', 'e', 1, 0};
// "base" + 2-byte version + 2-byte CRC
#define BASEHEADERSIZE (BASE10SIZE + 2)
// "base" + 2-byte version + 2-byte CRC + per-bank bit flags
#define BASEDATASIZE (BASEHEADERSIZE + NUMBANKS / 8)
// The base data is stored before the Stadium data
#define BASEDATAOFF (N64PS3DATAOFF - BASEDATASIZE)
// ASCII "N64PS3" header (Stadium G/S was the third Japanese Stadium release for N64)
#define N64PS3SIZE 6
// N64PS3 + CRC
#define HEADERSIZE (N64PS3SIZE + 2)
// Checksum every half-bank
#define CHECKSIZE 0x2000
uint8_t n64ps3[N64PS3SIZE] = {'N', '6', '4', 'P', 'S', '3'};
// "N64PS3" + 2-byte CRC
#define N64PS3HEADERSIZE (N64PS3SIZE + 2)
// "N64PS3" + 2-byte CRC + per-half-bank 2-byte checksums
#define N64PS3DATASIZE (N64PS3HEADERSIZE + NUMBANKS * 2 * 2)
// The Stadium data is stored at the end of the ROM
#define N64PS3DATAOFF (ROMSIZE - N64PS3DATASIZE)
// The CRC polynomial value
#define CRC_POLY 0xC387
// The CRC initial value (also used for checksums)
#define CRC_INIT 0xFEFE
// The CRC initial value for Crystal base data
#define CRC_INIT_BASE 0xACDE
// Base data format: "base", 1, version byte, CRC (big-endian),
// 16 bytes = a 128-bit mask of which banks Stadium can skip comparing
uint8_t us_base[BASESIZE] = {'b', 'a', 's', 'e', 1, 0, 0, 0,
0x40, 0x11, 0x00, 0x22, 0x00, 0x3A, 0xF3, 0x38,
0x18, 0xFF, 0xFF, 0x0F, 0x07, 0x10, 0x68, 0x07};
uint8_t eu_base[BASESIZE] = {'b', 'a', 's', 'e', 1, 1, 0, 0,
0x00, 0x10, 0x00, 0x00, 0x00, 0x0C, 0xA3, 0x38,
0x00, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x14};
uint8_t dbg_base[BASESIZE] = {'b', 'a', 's', 'e', 1, 0, 0, 0,
0x40, 0x10, 0x00, 0x22, 0x00, 0x3A, 0xE3, 0x38,
0x00, 0xFF, 0xFF, 0x07, 0x07, 0x10, 0x68, 0x06};
uint8_t n64ps3[N64PS3SIZE] = {'N', '6', '4', 'P', 'S', '3'};
// The CRC lookup table
uint16_t crc_table[256];
#define SET_U16BE(file, off, v) do { \
file[(off) + 0] = (uint8_t)(((v) & 0xFF00) >> 8); \
file[(off) + 1] = (uint8_t)(((v) & 0x00FF) >> 0); \
} while (0)
void calculate_checksums(uint8_t *file, int filesize, enum Base base) {
int NUMCHECKS = filesize / CHECKSIZE;
int DATASIZE = HEADERSIZE + NUMCHECKS * 2; // 2 bytes per checksum
int ORIGIN = filesize - DATASIZE; // Stadium data goes at the end of the file
// CRCs of every bank in the base ROM, crystal_base0.bin
uint16_t base0_crcs[NUMBANKS] = {
0x9650, 0x8039, 0x2D8F, 0xD75A, 0xAC50, 0x5D55, 0xE94B, 0x9886,
0x2A46, 0xB5AC, 0xC3D3, 0x79C4, 0xCE55, 0xA95E, 0xEF78, 0x9B50,
0x82BA, 0x8716, 0x5895, 0xAD33, 0x4EF0, 0xE434, 0xC521, 0xBFB1,
0xB352, 0xA497, 0xCA84, 0xD3F5, 0x3C79, 0xB61A, 0xAE1B, 0xF314,
0x00B3, 0x7C0A, 0x1018, 0x7F6B, 0x1CFF, 0x15AF, 0x4078, 0xE473,
0x081C, 0x4B9D, 0x2FFC, 0xD9D0, 0x2CBA, 0xCD8C, 0x004C, 0x773C,
0xF040, 0x3585, 0xF924, 0x6FD5, 0xC5E4, 0xD918, 0x1228, 0x1C86,
0x21C0, 0x77F3, 0x6206, 0x0110, 0x152F, 0x0F74, 0xCEDF, 0xBBFE,
0xE382, 0x5C15, 0xFD4D, 0x954C, 0xD2D9, 0xCA2F, 0x14B1, 0x9D2F,
0x172C, 0xEA0C, 0x4EAD, 0x604B, 0x0659, 0xF4C5, 0x4168, 0xD151,
0x58C7, 0x99BF, 0x77D3, 0xCDEC, 0x61B5, 0x1A48, 0xD614, 0x7FB0,
0x91D5, 0x812A, 0x812A, 0x82B2, 0xDCE2, 0x9067, 0x6DB3, 0x3DC7,
0xDCB8, 0xA1CE, 0x9C21, 0x4A23, 0xB50F, 0x63E6, 0xE78A, 0x9238,
0x644D, 0x1BD6, 0xB5B6, 0x1AB9, 0x9D07, 0xC849, 0x6992, 0x10CA,
0x4453, 0xA3A1, 0x5A18, 0xAFE0, 0x7F2B, 0xFC38, 0xFC38, 0xBA98,
0x5AEB, 0xFC38, 0xFC38, 0xFC38, 0xFC38, 0xEFAD, 0x6D83, 0xFC38
};
// CRCs of every bank in the European base ROM, crystal_base1.bin
uint16_t base1_crcs[NUMBANKS] = {
0x5416, 0xFD37, 0xC4A4, 0xBC37, 0x9458, 0xB489, 0xE94B, 0x9906,
0x2A46, 0xDEA9, 0x17F4, 0xF447, 0xCE55, 0xD843, 0xC5B2, 0xAE13,
0x4E91, 0x3984, 0xD984, 0xD02F, 0x77B8, 0x4D8D, 0x1F8C, 0x7185,
0xBA34, 0xA497, 0xE813, 0xFF97, 0x245E, 0xB61A, 0xCEF0, 0x8BF4,
0xA786, 0x4CE5, 0xA9B8, 0x1988, 0xEF53, 0x2A24, 0x4588, 0x6084,
0x2609, 0x4B9D, 0x8C33, 0xD9D0, 0x2CBA, 0xCD8C, 0xDA4F, 0xE020,
0xF040, 0x3585, 0x2B21, 0xAEEA, 0xC5E4, 0xD918, 0x1228, 0x1C86,
0x78B3, 0xF4B1, 0x7577, 0x0110, 0x152F, 0x0F74, 0xCCDD, 0x3444,
0x58A8, 0x1FB0, 0xDACE, 0x954C, 0xD2D9, 0xF7CB, 0xEE99, 0xA5F0,
0x172C, 0xEA0C, 0x4EAD, 0x604B, 0x0659, 0xF4C5, 0x4168, 0xD151,
0x58C7, 0x99BF, 0x77D3, 0xCDEC, 0x61B5, 0x1A48, 0xD614, 0x7FB0,
0x91D5, 0x812A, 0x812A, 0x82B2, 0x5C2C, 0x91E6, 0x79C5, 0xF2BF,
0xDCB8, 0xA1CE, 0x9C21, 0x579B, 0x4B59, 0x21F5, 0xB2B6, 0x58AD,
0xC91D, 0xB96F, 0x4DCE, 0xBA03, 0x9D07, 0x7A7E, 0xC77E, 0xB8AA,
0xF7E4, 0xA7A4, 0x22E8, 0xAFE0, 0xE0C8, 0xFC38, 0xFC38, 0x2277,
0x5AEB, 0xFC38, 0xFC38, 0x4314, 0x25B0, 0xCE7B, 0x12FA, 0xDD05
};
uint16_t calculate_checksum(uint16_t checksum, uint8_t *file, size_t size) {
for (size_t i = 0; i < size; i++) {
checksum += file[i];
}
return checksum;
}
uint16_t calculate_crc(uint16_t crc, uint8_t *file, size_t size) {
for (size_t i = 0; i < size; i++) {
crc = (crc >> 8) ^ crc_table[(crc & 0xFF) ^ file[i]];
}
return crc;
}
void calculate_checksums(uint8_t *file, bool european) {
// Initialize the CRC table
uint16_t crc_table[256];
for (int i = 0; i < 256; i++) {
uint16_t c = i;
for (uint16_t i = 0; i < sizeof(crc_table) / sizeof(*crc_table); i++) {
uint16_t rem = 0;
for (int y = 0; y < 8; y++) {
for (uint16_t y = 0, c = i; y < 8; y++, c >>= 1) {
rem = (rem >> 1) ^ ((rem ^ c) & 1 ? CRC_POLY : 0);
c >>= 1;
}
crc_table[i] = rem;
}
@ -87,56 +134,55 @@ void calculate_checksums(uint8_t *file, int filesize, enum Base base) {
// Clear the global checksum
SET_U16BE(file, GLOBALOFF, 0);
// Write the appropriate base data, or none
int BASEOFF = ORIGIN - BASESIZE;
if (base == BASE_US) {
memcpy(file + BASEOFF, us_base, BASESIZE);
} else if (base == BASE_EU) {
memcpy(file + BASEOFF, eu_base, BASESIZE);
} else if (base == BASE_DEBUG) {
memcpy(file + BASEOFF, dbg_base, BASESIZE);
// Initialize the base data (this should be free space anyway)
memset(file + BASEDATAOFF, 0, BASEDATASIZE);
memcpy(file + BASEDATAOFF, base10, BASE10SIZE);
// Use the appropriate base CRCs
uint16_t *base_crcs = base0_crcs;
if (european) {
base_crcs = base1_crcs;
file[BASEDATAOFF + BASE10SIZE - 1] = 1;
}
// Calculate the CRC of the base data, or none
if (base) {
uint16_t crc = CRC_INIT_BASE;
for (int i = BASEOFF; i < BASEOFF + BASESIZE; i++) {
crc = (crc >> 8) ^ crc_table[(crc & 0xFF) ^ file[i]];
// Calculate the base data bits using bank CRCs
// Bits indicate if the bank CRC matches the base one
for (size_t i = 0; i < BASEDATASIZE - BASEHEADERSIZE; i++) {
uint8_t bits = 0;
for (size_t j = 0; j < 8; j++) {
size_t bank = i * 8 + j;
uint16_t crc = calculate_crc(CRC_INIT, file + bank * BANKSIZE, BANKSIZE);
bits |= (crc == base_crcs[bank]) << j;
}
SET_U16BE(file, BASEOFF + 6, crc);
file[BASEDATAOFF + BASEHEADERSIZE + i] = bits;
}
// Calculate the CRC of the base data
uint16_t crc = calculate_crc(CRC_INIT_BASE, file + BASEDATAOFF, BASEDATASIZE);
SET_U16BE(file, BASEDATAOFF + BASEHEADERSIZE - 2, crc);
// Initialize the Stadium data (this should be free space anyway)
memset(file + ORIGIN, 0, DATASIZE);
memcpy(file + ORIGIN, n64ps3, N64PS3SIZE);
memset(file + N64PS3DATAOFF, 0, N64PS3DATASIZE);
memcpy(file + N64PS3DATAOFF, n64ps3, N64PS3SIZE);
// Calculate the half-bank checksums
for (int i = 0; i < NUMCHECKS; i++) {
uint16_t checksum = CRC_INIT;
for (int j = 0; j < CHECKSIZE; j++) {
checksum += file[i * CHECKSIZE + j];
}
SET_U16BE(file, ORIGIN + HEADERSIZE + i * 2, checksum);
for (size_t i = 0; i < NUMBANKS * 2; i++) {
uint16_t checksum = calculate_checksum(CRC_INIT, file + i * BANKSIZE / 2, BANKSIZE / 2);
SET_U16BE(file, N64PS3DATAOFF + N64PS3HEADERSIZE + i * 2, checksum);
}
// Calculate the CRC of the half-bank checksums
uint16_t crc = CRC_INIT;
for (int i = ORIGIN + HEADERSIZE; i < ORIGIN + DATASIZE; i++) {
crc = (crc >> 8) ^ crc_table[(crc & 0xFF) ^ file[i]];
}
SET_U16BE(file, ORIGIN + HEADERSIZE - 2, crc);
crc = calculate_crc(CRC_INIT, file + N64PS3DATAOFF + N64PS3HEADERSIZE, N64PS3DATASIZE - N64PS3HEADERSIZE);
SET_U16BE(file, N64PS3DATAOFF + N64PS3HEADERSIZE - 2, crc);
// Calculate the global checksum
uint16_t globalsum = 0;
for (int i = 0; i < filesize; i++) {
globalsum += file[i];
}
uint16_t globalsum = calculate_checksum(0, file, ROMSIZE);
SET_U16BE(file, GLOBALOFF, globalsum);
}
int main(int argc, char *argv[]) {
enum Base base = BASE_NONE;
parse_args(argc, argv, &base);
bool european = false;
parse_args(argc, argv, &european);
argc -= optind;
argv += optind;
@ -147,7 +193,9 @@ int main(int argc, char *argv[]) {
char *filename = argv[0];
long filesize;
uint8_t *file = read_u8(filename, &filesize);
calculate_checksums(file, filesize, base);
if (filesize == ROMSIZE) {
calculate_checksums(file, european);
}
write_u8(filename, file, filesize);
return 0;
}

View File

@ -90,14 +90,14 @@ for objfile in objects:
elif magic == b'RGB9':
obj_ver = 10 + unpack_from('<I', file)[0]
if obj_ver not in [6, 10, 11, 12, 13, 15, 16, 17, 18]:
if obj_ver not in [6, 10, 11, 12, 13, 15, 16, 17, 18, 19]:
print(f"Error: File '{objfile}' is of an unknown format.", file=sys.stderr)
sys.exit(1)
num_symbols = unpack_from('<I', file)[0]
unpack_from('<I', file) # skip num sections
if obj_ver in [16, 17, 18]:
if obj_ver in [16, 17, 18, 19]:
node_filenames = []
num_nodes = unpack_from('<I', file)[0]
for x in range(num_nodes):
@ -117,7 +117,7 @@ for objfile in objects:
sym_type = symtype(unpack_from('<B', file)[0] & 0x7f)
if sym_type == symtype.IMPORT:
continue
if obj_ver in [16, 17, 18]:
if obj_ver in [16, 17, 18, 19]:
sym_fileno = unpack_from('<I', file)[0]
sym_filename = node_filenames[sym_fileno]
else:

View File

@ -1,64 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Usage: python used_space.py [pokecrystal.map] [used_space.png]
Generate a PNG visualizing the space used by each bank in the ROM.
"""
import sys
from colorsys import hls_to_rgb
import png
from mapreader import MapReader
def main():
mapfile = sys.argv[1] if len(sys.argv) >= 2 else 'pokecrystal.map'
outfile = sys.argv[2] if len(sys.argv) >= 3 else 'used_space.png'
num_banks = 0x80
bank_mask = 0x3FFF
bank_size = 0x4000 # bytes
bpp = 8 # bytes per pixel
height = 256 # pixels
assert bank_size % bpp == 0 and (bank_size // bpp) % height == 0
pixels_per_bank = bank_size // bpp # 2048 pixels
bank_width = pixels_per_bank // height # 8 pixels
width = bank_width * num_banks # 1024 pixels
reader = MapReader()
with open(mapfile, 'r', encoding='utf-8') as file:
reader.read_map_data(file.readlines())
hit_data = []
default_bank_data = {'sections': [], 'used': 0, 'slack': bank_size}
for bank in range(num_banks):
hits = [0] * pixels_per_bank
bank_data = reader.bank_data['ROM0 bank' if bank == 0 else 'ROMX bank']
data = bank_data.get(bank, default_bank_data)
for s in data['sections']:
beg = s['beg'] & bank_mask
end = s['end'] & bank_mask
for i in range(beg, end + 1):
hits[i // bpp] += 1
hit_data.append(hits)
pixels = [[(0xFF, 0xFF, 0xFF)] * width for _ in range(height)]
for bank, hits in enumerate(hit_data):
hue = 0 if bank == 0 else 210 if bank % 2 else 270
for i, hit in enumerate(hits):
x, y = i % bank_width + bank * bank_width, i // bank_width
hls = (hue / 360, 1 - (85 * hit / bpp) / 100, 1)
rgb = tuple(int(c * 0xFF) for c in hls_to_rgb(*hls))
pixels[y][x] = rgb
png_data = [tuple(c for pixel in row for c in pixel) for row in pixels]
with open(outfile, 'wb') as file:
writer = png.Writer(width, height, greyscale=False, bitdepth=8, compression=9)
writer.write(file, png_data)
if __name__ == '__main__':
main()

View File

@ -1,5 +1,3 @@
INCLUDE "constants.asm"
; These are all the asm constants needed to make the crystal11_vc patch.
MACRO vc_const