CHP Format - DragonRatTiger/CHPEditor GitHub Wiki

CHP (CHara Pomyu?) files are used to display animated characters in PMS-supported applications.

Below is a list of all information related to the CHP format, intended for creators to understand how this file format works, and intended for developers as a reference for how to implement support for this file format.

Format

All commands begin with a # symbol + the name of the command, and then followed by the value(s) needed. All commands and their value(s) must be separated by tabs (\t) or whitespace ( ). Empty values are disposed of before the rest are processed in order.

In addition, comments can be added to a CHP file. All comments must begin with //, and any text written after until the next newline will not be parsed. / can also be used, but must be at the very beginning of the line.

Example :

// ------------------------
#CharName	Chara Name
#Artist	ナãƒĨã‚Ķã‚ģ
// ------------------------
#CharBMP	char-bmp-1p.bmp
#CharFace	char-face-1p.bmp
#SelectCG	char-select-1p.bmp
#CharTex	char-tex-1p.bmp
// ------------------------

All commands and their values are always case-insensitive. This also applies for rect entries & file names. For example, all of these are legal, and are treated as the same command :

#CharName	Chara Name
#charname	Chara Name
#CHARNAME	Chara Name

Textures

There are currently 8 possible textures that can be loaded. Every single texture is optional, and can be loaded through a local, case-insensitive file path. Image format support is dependent on the program, but any common image format should be safe.

Command Usage
#CharBMP The primary spritesheet used by a character. Utilized by #Patern and #Layer.
#CharTex The secondary spritesheet used by a character. Utilized by #Texture.
#CharFace The character's render, typically separated into two sprites on a single texture. In FeelingPomu2nd, the smaller sprite is used during character selection, and the larger sprite is used during song loading & the results screen, showing off the rival character's full render.
#SelectCG The character's miniature icon. In FeelingPomu2nd, this icon appears during character selection.
#CharBMP2P The 2P variant of #CharBMP. If unavailable, the texture loaded by #CharBMP is used instead.
#CharTex2P The 2P variant of #CharTex. If unavailable, the texture loaded by #CharTex is used instead.
#CharFace2P The 2P variant of #CharFace. If unavailable, the texture loaded by #CharFace is used instead.
#SelectCG2P The 2P variant of #SelectCG. While this command is not supported in FeelingPomu2nd, this command was later added to beatoraja. If unavailable, the texture loaded by #SelectCG is used instead.

Example :

// ------------------------
#CharName	Chara Name
#Artist	ナãƒĨã‚Ķã‚ģ
// ------------------------
#CharBMP	char-bmp-1p.bmp
#CharFace	char-face-1p.bmp
#SelectCG	char-select-1p.bmp
#CharTex	char-tex-1p.bmp
#CharBMP2P	char-bmp-2p.bmp
#CharFace2P	char-face-2p.bmp
#SelectCG2P	char-select-2p.bmp	// Not supported on FeelingPomu2nd, but is supported on beatoraja
#CharTex2P	char-tex-2p.bmp
// ------------------------

Since BMP files are commonplace for Pomyu Chara textures, they often lack an alpha channel. To utilize alphas, the bottom-right pixel of the image is used as the color key. For example, if the bottom-right pixel is RGBA255,0,255,255, any pixel that matches these values are not drawn on-screen.

Exceptions to this rule are CharFace/CharFace2P, where the color key is always pure black (255,255,255,255), and SelectCG/SelectCG2P, where they have no color key.

2P Textures

Each texture comes with a 2P (Player 2) variant. If 2P is selected, and a 2P texture is available, the character will be drawn with a 2P texture. If 2P is selected, but a 2P texture is missing, the character will instead be drawn with its 1P texture.

Behavior in FeelingPomu2nd

BMP files are standard in FeelingPomu2nd, but any common image format is typically supported. However, FeelingPomu2nd lacks support for an alpha channel. If an image contains an alpha channel, the game will attempt to ignore it. As a result, some images with alpha channels could become distorted when loaded.

Animation & Timeline

CHP supports a total of 18 Animations, each triggered based on specific conditions in-game. Each animation will play either once or loop until the animation changes. Required/optional/unsupported animations depends on the program.

Animations are created through the use of the #Patern, #Texture, or #Layer commands, which contains the Animation ID & its frames. The speed of the animation inherits the value of #Anime by default, but can be modified by #Flame (misspelling of "frame") per animation. Every animation command must have an equal number of frames, or safely fallback to the least number of frames to avoid unexpected behavior.

Example :

#Patern	1	0203040506070809
#Patern	1	0F0F0F0F0F0F0F0F	FEFEFEFEFEFEFEFE
#Layer	1	2425262728292A2B	
// There can be any number of #Patern, #Texture, and #Layer commands in a single animation.

#Flame	2	50
#Patern	2	101213141516
#Texture	2	AAABACADAEAF
// Using the #Flame command, we can change Animation 2's framerate to a value other than #Anime's value (which is currently 83ms per frame).

#Loop	3	5
#Patern	3	5051525354606162636465666768696A
// Animations which can loop support the #Loop command, which lets you specify where to begin looping your animation after it plays its entire animation once.
// This value is zero-indexed, however, meaning that "0" is considered the first frame.
// For example, if you write "5", the animation will continue its loop beginning from the 6th frame instead of the 1st frame.

#Patern	4	A0A1A2A3A4A5
#Texture	4	B0B1B2B3B4
#Layer	4	C0C1C2C3C4C5C6C7
// Do not create an unequal amount of frames! This may create unintended behavior for applications not designed to handle this.
// As a note for programmers, you should use the least number of frames as a fallback, to avoid unusual behavior.

Below is a list of animations and how they're typically triggered, according to FeelingPomu2nd :

ID Name Trigger Notes Looping
1 Neutral - Default idle animation. Continues playing if there are no notes to respond to before the end of the idle animation. If a note is responded to, Animations 6-12 can be triggered based on how the note is hit + the side the character is on, after the animation finishes. ✔
2 Second 50% or higher gauge Between 50% and 75% gauge, this animation replaces Neutral. At >75% gauge, Neutral & Second alternate. ✔
3 Ojama Rival sets off Ojama Rival side ✔
4 Miss Miss a note Player side ❌
5 Standing Plays once at the beginning of a song - ❌
6 Fever Hitting great while at 100% gauge Player side ❌
7 Great Hitting great Player side ❌
8 Good Hitting good Player side ❌
9 Player hits Bad Player hits bad Rival side ❌
10 Player hits Fever Player hits perfect Rival side ❌
11 Player hits Great Player hits great Rival side ❌
12 Player hits Good Player hits good Rival side ❌
13 Unknown - There is no knowledge over what this animation is for or how it's triggered. Documentation has not been found anywhere, live or archived. ❔
14 Dance "Dance" Ojama must be active Rival side; The character's animation will be overlayed on top of the gameplay area, disturbing the player's ability to see the notes. ✔
15 Win Clear the song with less than 100% gauge (Player Side) / Player fails the song (Rival side) - ✔
16 Lose Fail the song (Player Side) / Player clears the song (Rival side) - ✔
17 Fever Win Clear the song with 100% gauge Player side ✔
18 Attacked by Ojama Rival sets off Ojama Player side ✔

Legacy Chara Animations

Pomyu Charas determined to be Legacy characters have slightly different behavior when switching between animations. Rather than wait for the idle animation to finish to determine the next animation, the character will immediately play its next animation as soon as a note is hit/missed, assuming its previous non-idle animation is already finished.

Drawing Frames

After specifying sprite/offset coordinates, each index may be used as a frame through the use of #Patern, #Texture, and #Layer commands. Each of these commands are drawn in different layers, with #Patern being drawn first, #Texture being drawn second, and #Layer being drawn last. However, there can be any number of #Patern/#Texture/#Layer commands in a single animation. The same command written in different lines determines what order they're drawn in, with the first instance of the command being drawn first.

#Patern and #Layer are capable of drawing sprites, and can optionally offset them as well. However, they will not draw past the boundary set by the character's #Size, and will be trimmed if they cross that boundary.

#Texture is capable of drawing sprites and optionally offsetting, similarly to #Patern and #Layer. However, it's also able to cross its boundary, as well as support the ability to change their opacity and rotation. In order to utilize the ability to change opacity, frames for sprite & offset are required to be written, and can not be skipped in favor of jumping to the next adjustable property. Similarly, rotation can not be adjusted without having sprite/offset/alpha frames already written.

Unlike using indexes for sprite/offset, alpha/rotation always uses Base16 values (00~FF), even if #Data were to use a value other than 16.

Example :

#Patern	1	02030405060708	FFFFFFFFFFFFFF
// Uses indexes #02, #03, #04, #05, #06, #07, and #08 to draw sprites, with each index's given coordinates
// While optional, the second string of text is used to offset the sprite, and/or rescale the sprite by stretching/shrinking it to the offset's size. If excluded, the sprite will always begin drawing at coordinates 0,0 , and the sprite size will stay the same.
// Assuming #Anime's value is set to 83, this animation will last 83ms * 7 (581ms), or 0.581 seconds.
// This is drawn first, before #Texture and #Layer are drawn.

#Texture	1	50515253545556	FAFAFAFAFEFEFE	FFFF800080FFFF	00204060402000
// This is the only command of the three that allows for alpha & rotation to be adjusted. This is also the only command of the three that can cross the character's boundary.
// Offset must be specified before alpha can be adjusted, and alpha must be specified before rotation can be adjusted.
// This is drawn second, after #Patern and before #Layer are drawn.

#Layer	1	90919293949596
// Follows the same rules as #Patern.
// This is drawn last, after #Patern and #Texture are drawn.

Drawing Rules

When drawing sprites, there are some rules for developers to consider :

  • If a sprite has a size of 0x0, or a size of 1x1, do not draw the sprite, regardless of the offset's size.
  • Coordinates with negative width/height are acceptable, and the sprite should be drawn as if it was flipped in those respective directions.
  • Avoid drawing any pixels past a spritesheet's boundaries.
    • In FeelingPomu2nd, any pixels outside of a spritesheet's boundaries are drawn as pure black pixels. This behavior likely isn't intended.
  • If the current animation is set to 13 (Dance), expand the crop boundary for #Patern and #Layer to fit the playfield instead.

Handling Invalid Frames

Sometimes, an animation may have a frame that uses invalid chars, or goes beyond the scope of available hex values. In this case, the developer should fallback to the previous frame as a replacement for that current frame.

Tweening

Tweening is supported through the use of two dashes (--) for each frame tweened. When one or more are placed between two frames, it will linearly transition from point A to point B. Sprite, offset, alpha, and rotation can be tweened for a smoother animation.

Tweening behavior based on how the timeline is written is still being studied, but the general behavior is like so :

#Anime	83
...
#Patern	1	02030405060708	A2----------A3
// Gradually shift this pattern's offset from A2 to A3, starting from the millisecond the first frame begins,
// and ending from the millisecond the last frame ends.
// This happens in the span of 83 * 7 ms (581ms, or 0.581 seconds).

#Texture	1	151515151515161616161616	FFFFFFFFFFFFFFFFFFFFFFFF	FF--------0000--------FF
// In this, the alpha of this texture shifts from 255, to 0, and back to 255.
// The previous tweening behavior specified above applies here as well.
// This tween starts from the millisecond the 1st frame begins, to the millisecond the 6th frame ends.
// After this, the next tween starts from the millisecond the 7th frame begins, to the millisecond the final frame ends.

#Layer	1	B0------B1------B0
// Tweening between sprite coordinates is legal as well, though every character i've seen has never made use of this. (Maybe they didn't know it was possible?)
// However, the tweening behavior from the last two examples differs here.
// Because there is only one frame between these two tweens, continuing to use the same behavior from the last two examples will produce choppy animations instead.
// This behavior hasn't been fully explored, but the best way for programmers to handle this is to divide this frame's length by 2, and use that as your middle ground when jumping to the next tween.

Commands

Chara Info

Text-based information about a character.

#CharName

Specifies the name of the character. This text value rarely appears, and the character's Name Image is displayed instead.

Example :

#CharName	åĪŠéƒŽ

#Artist

Specifies the creator(s) of the character. This usually includes the name of the animator, as well as anyone who assisted in this character's creation/animation (if applicable).

Example :

#Artist	ナãƒĨã‚Ķã‚ģ

Bitmaps

Image files referenced for a character's animations.

All file paths given are case-insensitive.

#CharBMP

Color Key: Auto or R0,G0,B0,A255

The primary image file used for a character. This image is referenced by #Patern and #Layer when displaying animation.

Example :

#CharBMP	char-bmp-1p.bmp

#CharBMP2P

Color Key: Auto or R0,G0,B0,A255

Similar to #CharBMP, but is used for a character's 2P palette.

Example :

#CharBMP2P	char-bmp-2p.bmp

#CharTex

Color Key: Auto or R0,G0,B0,A255

The secondary image file used by a character. Unlike #CharBMP, this image file is used exclusively by #Texture.

Example :

#CharTex	char-tex-1p.bmp

#CharTex2P

Color Key: Auto or R0,G0,B0,A255

Similar to #CharTex, but is used for a character's 2P palette.

Example :

#CharTex2P	char-tex-2p.bmp

#CharFace

Color Key: R0,G0,B0,A255

A 640x480 texture which displays a character's upper-body portrait and full-body portrait. These portraits typically appear during character selection & song options in FeelingPomu2nd.

FeelingPomu2nd have hard-coded rects for these portraits: x0,y0,w256,h256 for upper-body portrait, and x320,y0,w320,h480 for full-body portraits.

Example :

#CharFace	char-face-1p.bmp

#CharFace2P

Color Key: R0,G0,B0,A255

Similar to #CharBMP, but is used for a character's 2P palette.

Example :

#CharFace2P	char-face-2p.bmp

#SelectCG

Color Key: None

The miniature player icon that displays during character selection in FeelingPomu2nd.

Unlike the other Bitmap commands, there is no #SelectCG2P command available in FeelingPomu2nd.

Example :

#SelectCG	char-select-1p.bmp

Chara Settings

Various settings for how character animations should be handled and displayed.

#AutoColorSet

Determines if a character's spritesheets should use a color key for transparency, via. selecting the bottom-right pixel of each spritesheet. If this command is excluded from the CHP file, the color key will default to R0,G0,B0 (black). This command does not affect the color key for CharFace & SelectCG.

Example :

#AutoColorSet

#Anime

Sets the default animation framerate in milliseconds.

Example :

#Anime	50	// 50ms is 0.05 seconds per frame, aka. 20fps

#Size

Sets the character's resolution in pixels. The values set the character's width and height, respectively. 167x271 is the standard resolution, but any value is possible.

Example :

#Size	167	271

#Wait

Set's the character's Idle animation loop count, before determining which animation to switch to based on the user's performance.

Example :

#Wait	1

#Data

Determines the hexadecimal base size, which controls how many rects can be created. The value most often used is 16 (16^2 -> 256 max rects).

If this command is missing, this marks the character as Legacy, and only supports up to 100 rects. Refer to Animation Data for details.

Example :

#Data	16

Animation Data

#00~#FF

Each entry contains a Rect (x, y, width, height), which determines which sprite to display when called, or where to position/scale that sprite when called. The maximum number of rects that can be created are determined by the value of #Data powered by 2. (i.e. If Data is set to 16, 256 (16^2) total Rects can be created)

Note that #00 and #01 are used for Name Image and Background respectively (but you can still use these values in your animations). Outside of this, #02~#FF can be used for anything.

These entries are case-insensitive.

Example :

#00	1	1633	131	29
// Assuming this file follows standard FeelingPomu2nd sizes, 131x29 is the standard resolution for name images
#01	1	1	167	271
// Assuming this file follows standard FeelingPomu2nd sizes, 167x271 is the standard resolution for background

#02	169	1	167	271
#03	337	1	167	271
#04	505	1	167	271
#05	673	1	167	271
#06	841	1	167	271
#07	1009	1	167	271
#08	1177	1	167	271

#09	1	273	167	271
#0A	169	273	167	271
#0B	337	273	167	271
#0C	505	273	167	271
#0D	673	273	167	271
#0E	841	273	167	271
#0F	1009	273	167	271
#10	1177	273	167	271

However, legacy Pomyu Charas only use integers to register Rect entries, despite their animations still calling for hexadecimal values. This means that legacy Pomyu Charas can only use up to 100 Rects (#0~#99) no matter what.

#Flame

Overrides #Anime for the specified animation. (This command name is a misspelling of "Frame".)

Example :

#Flame	14	75	// Set State 14 (Dance) animation speed to 75ms per frame

#Loop

Determines at which frame to begin looping the rest of the specified animation. This command only applies to animations that are intended to constantly play, such as clear animations (Lose/Win/Fever Win), Ojama/Disturb animations, and Dance animation.

Example :

#Loop	15	9	// Loop from frame #9 onwards

Timeline Data

These commands will display frames based on the entries listed. More information on how these work can be found here.

None of these commands are explicitly required, and an animation can have no keyframes at all.

#Patern

The first animation command, drawn below #Texture and #Layer. #CharBMP is used for this command.

(This command name is a misspelling of "Pattern".)

Example :

#Patern	1	0203040506070809	// Uses entries #02, #03, #04, #05, #06, #07, #08, and #09

#Texture

The second and most advanced animation command, drawn on top of #Patern and drawn below #Layer. #CharTex is used for this command.

Example :

#Texture	07	101010101010	C0C0C0C0C0C0	00--FFFF--00	00--------80

#Layer

The final animation command, drawn on top of #Patern and #Texture. #CharBMP is used for this command.

Example :

#Layer	06	B0B1B2B3B4B5B6B7	FFFFC4C5C6C7FFFF

Beatoraja Exclusive Commands

Pomyu Chara support was added to beatoraja on Feburary 2018, and with it came a few new commands.

These commands have not been researched, mainly due to a lack of beatoraja skins and characters that make researching these behaviors possible. Everything listed below is speculated behavior.

#SelectCG2P

Color Key: None

Similar to #SelectCG, but is used for a character's 2P palette.

Example :

#SelectCG2P	char-select-2p.bmp

#CharFaceUpperSize / #CharFaceAllSize

Overrides the default, hard-coded rects for #CharFace.

Example :

#CharFaceUpperSize	0	0	320	320
#CharFaceAllSize	320	0	480	640

#Frame

Alternate command name for #Flame.

#Pattern

Alternate command name for #Patern.


Sources

Documentation on the CHP file format, as well as the creation of CHPEditor itself, would not be possible without the previous documentation created several years ago, now preserved by The Internet Archive. There is still more research to be done.

Colorful Canvas Series Portal : https://web.archive.org/web/20231230150503/https://pmcc.nekokan.dyndns.info/

Story of Namidaame - Pomyu Chara Creation Course Part I : https://web.archive.org/web/20220812155722/http://storyof.namidaame.com/yy_pce.htm

Story of Namidaame - Pomyu Chara Creation Course Part II : https://web.archive.org/web/20220812151526/http://storyof.namidaame.com/yy_tec.htm

Yukiiro's Pomyu Chara Webpage : https://web.archive.org/web/20151004013142/http://yukiiro.info/pomu/

beatoraja's Pomyu Chara loader Java file : https://github.com/exch-bms2/beatoraja/blob/master/src/bms/player/beatoraja/skin/PomyuCharaLoader.java