Play-Yan Technical Documentation 0.1
September 24th, 2022
Shonumi aka D.S. Baxter


***************************************************
1. Introduction
***************************************************

On February 21, 2005, Nintendo released their very own video/music player for the Game Boy Advance in the form of a unique cartridge. It was branded the Play-Yan and was designated the product code AGS-006. Sold exclusively in Japan, it handled MP3 audio files as well and MPEG-4 video files. The hardware had a dedicated SD card slot so users could access their own media.

On September 13, 2005, Nintendo released an updated version called the Play-Yan Micro. It was largely the same as the original Play-Yan, however, it was updated with native support for the MP4 video container, a different interface, and it removed support for the 13 minigames. The Play-Yan Micro was otherwise unchanged.


***************************************************
2. General Hardware Information
***************************************************

- Features a normal-sized SD card reader.
- Can handle card capacities up to 2GB, depending on the manufacturer.
- Not compatible with SDHC, SDXC, or SDUC cards.
- Uses hardware decoding for media files via an Alpha Mosiac VC01.
- Uploads firmware on boot, and can optionally update with the correct files on an SD card.
- Features a slightly larger than normal cartridge shell.
- Has a 3.5mm audio jack to output sound and bypass the GBA's speakers.
- Generates video thumbnails and parses some ID3 tags (ID3v1 through ID3v2.4).
- Videos use ASF or MP4 containers with G.726 or AAC as audio codecs, respectively.
- Both ASF and MP4 files use MPEG-4 (MP4S) as the video codec.
- Maximum of 30 frames-per-second for video.
- The original version has 13 "Garage Games" built into the ROM, unlockable with special video files.


***************************************************
3. Hardware Registers and I/O
***************************************************

The Play-Yan has a large number of addresses mapped to cartridge ROM that control firmware access, issue playback commands, and retrieve information such as filenames, thumbnails, and other metadata.

----------------------------------------------------------------------------------------------------------------------
Hardware Registers	| R/W	| Address	| Size		| Description
----------------------------------------------------------------------------------------------------------------------
PY_INIT_DATA		| (R)	| 0x9000000	| 8-bit		| Appears to be some kind of data stream.
PY_STAT			| (R)	| 0x9000006	| 8-bit		| Play-Yan Status Register.
UNKNOWN REGISTER 00	| (w)	| 0xB000000 	| 16-bit	| Unknown. Play-Yan mostly writes zero to this register.
UNKNOWN REGISTER 02	| (R/W)	| 0xB000002	| 16-bit	| Unknown. Play-Yan mostly writes zero to this register.
PY_DATA_ADDR		| (R/W)	| 0xB000004	| 16-bit	| Address used to access Play-Yan data.
PY_DATA_MODE		| (R/W)	| 0xB000006	| 16-bit	| Determines data access mode (e.g. firmware read or firmware write).
PY_DATA_PARAM		| (R/W)	| 0xB000010	| 16-bit	| Appears to be some kind of parameter for data access.
PY_FIRM_STAT		| (R/W)	| 0xB000012	| 16-bit	| Play-Yan Firmware Status Register.
----------------------------------------------------------------------------------------------------------------------

PY_INIT_DATA is read a number of times during the initial boot sequence. It appears to be a data stream of unknown purpose.

PY_STAT acts as the overall status register for the Play-Yan. Its primary purpose appears to be checking whether or not firmware is available accessible. Before uploading any portion of firmware during the initial boot sequence, the Play-Yan checks Bit 7 of PY_STAT, which acts as a busy flag for firmware operations. If Bit 7 is set LOW, the firmware is busy, otherwise if Bit 7 is set HIGH, firmware is ready for more data.

PY_DATA_ADDR determines the address used for data operations for Play-Yan related data. It is used in conjunction with the I/O regions listed below as well as PY_DATA_MODE. Depending on the value of PY_DATA_ADDR, different contexts are used to retrieve data from these regions, e.g. it distinguishes between writing commands for the Play-Yan to execute or writing firmware data. The address is actually 32-bits. The Play-Yan must write to PY_DATA_ADDR twice, with the lower 16-bit first, and the upper 16-bit second.

PY_DATA_MODE determines what kind of data read or write the Play-Yan will perform. Used in conjection with the I/O regions listed below as well as PY_DATA_ADDR.

PY_DATA_PARAM appears to be a parameter passed along to the Play-Yan that affects data access. Currently unknown exactly how it functions.

PY_FIRM_STAT appears to be another type of firmware status register. Before reading any portion of firmware, the Play-Yan checks this to make sure Bit 4 is set.

Several regions of memory on the Play-Yan are dedicated to unique purposes. Some of them overlap, and their function often depends on whether data is being written or read. The Play-Yan typically uses these for accessing large amounts of information, such as pixels representing video data, firmware, or commands. 

----------------------------------------------------------------------------------------------------------------------
I/O Regions		| I/O Direction	| Description
----------------------------------------------------------------------------------------------------------------------
0xB000100 - 0xB0002FF	| Input		| Play-Yan Command
0xB000100 - 0xB0002FF	| Input		| Firmware In
0xB000300 - 0xB00031F	| Output	| Game Pak IRQ Data
0xB000300 - 0xB0004FF	| Output	| Play-Yan SD Card and Internal Data
0xB000500 - 0xB0006FF	| Output	| Play-Yan Thumbnail and Video Data
----------------------------------------------------------------------------------------------------------------------


***************************************************
4. Reading and Writing Firmware
***************************************************

To write to the Play-Yan's firmware, the following steps are performed:

-----------------------------------------------------------------------
PY_DATA_PARAM = 0x0A
PY_DATA_MODE = 0x68
PY_DATA_ADDR = LOW 16 BITS OF ADDRESS
PY_DATA_ADDR = HIGH 16 BITS OF ADDRESS
UNKNOWN REGISTER 02 = 0x00

WAIT FOR BIT 7 OF PY_STAT TO READ HIGH
WRITE DATA INTO 0xB000300 THROUGH 0xB0004FF
-----------------------------------------------------------------------

The address to write the firmware is internal to the Play-Yan. This is evidently any address from 0x00000 - 0xEFFFF. Only 512 bytes can be written at a time, so writing the entire firmware to the Play-Yan requires multiple iterations of the above steps.

The Play-Yan provides its own default firmware in its ROM and uploads this accordingly on every boot. This method ensures that the firmware is never corrupted by a bad update. A similar method is used for the WiiSpeak accessory on the Wii. The Play-Yan can update to a newer firmware if such a file is included on the SD card.

To read from the Play-Yan's firmware, the following steps are performed:

-----------------------------------------------------------------------
PY_DATA_PARAM = 0x08
PY_DATA_MODE = 0x78
PY_DATA_ADDR = LOW 16 BITS OF ADDRESS
PY_DATA_ADDR = HIGH 16 BITS OF ADDRESS
UNKNOWN REGISTER 02 = 0x00
PY_DATA_PARAM = 0x09

WAIT FOR BIT 4 OF PY_FIRM_STAT TO READ HIGH
READ DATA FROM 0xB000300 THROUGH 0xB0004FF
-----------------------------------------------------------------------

It's possible to read sequential blocks of firmware without repeating all of the above steps. The Play-Yan's ROM, for example, reads a total of 0xA00 bytes at a time. After each 0x200 bytes, only PY_FIRM_STAT needs to be checked before reading the next block. Once a total of 0xA00 bytes have been read, however, all the steps mentioned above are repeated before reading sequentially yet again.


***************************************************
5. Reading SD Card Data
***************************************************

The Play-Yan is capable of reading select data from the SD Card. After the software issues a command, the Play-Yan will respond with different kinds of data, for example, a list of all files in a given directory. This means that while the Play-Yan's software does not have direct access to the card, it has a vastly simpler interface to retrieve information. The memory region used overlaps with where firmware is read from, however, the process for accessing is somewhat different. The following steps are performed:

-----------------------------------------------------------------------
PY_DATA_PARAM = 0x08
PY_DATA_MODE = 0x78
PY_DATA_ADDR = 0x00
PY_DATA_ADDR = 0x00
UNKNOWN REGISTER 02 = 0x00
PY_DATA_PARAM = 0x09

WAIT FOR BIT 4 OF PY_FIRM_STAT TO READ HIGH
PY_DATA_PARAM = 0x08
READ DATA FROM 0xB000300 THROUGH 0xB0004FF
-----------------------------------------------------------------------

As with reading firmware, sequential 512-byte blocks can be read at a time. This is once again achieved by checking PY_FIRM_STAT. An additional step, setting PY_DATA_PARAM to 0x08, however, is necessary. The Play-Yan's software does not update the address when sequentially reading SD card data. Typically, the Play-Yan reads around 0x6800 bytes worth of data at a time and later copying that to RAM. Such a large amount of data allows it to process long lists of filenames, video frames, or vast amounts of metadata, depending on the expected response to a command.


***************************************************
6. Play-Yan Commands
***************************************************

A number of commands may be issued to the Play-Yan. These allow the software to access many of the cartridge's advanced functions surrounding multimedia playback and file handling. Rather than manually processing things, the Play-Yan hands things over to its hardware and firmware through an interface. There are two methods of sending commands on the Play-Yan: serial and non-serial. These determine whether the data is written to a single, fixed 16-bit address or across a range of I/O addresses, respectively.

Each command typically consists of 12 bytes written to the 0xB000000 - 0xB00001F address range for serial commands and the 0xB000100 - 0xB00011F address range for non-serial commands. Some commands may contain additional parameter data beyond this, and not every command follows the same pattern of using 32-bit parameters. In general, however, the structure of a command is as follows:

-----------------------------------------------------------------------
Address			| Data
-----------------------------------------------------------------------
0xB000x00 - 0xB000x03	| Command 
0xB000x04 - 0xB000x07	| Parameter 1
0xB000x08 - 0xB000x0B	| Parameter 2
0xB000x0C ...		| Parameter 3
-----------------------------------------------------------------------

Data for most commands is usually broken into 32-bit chunks, sent LSB first. Essentially, the Play-Yan just sends a command along with 2 parameters, both of which are optional. Below is a list of known or observed commands along with their parameters:

----------------------------------------------------------------------------------------------------------------------------------------------
Command					| Parameter 1							| Parameter 2
----------------------------------------------------------------------------------------------------------------------------------------------
0x200 - Get Filesystem Information	| File Type							| N/A
0x201 - Change Current Directory	| Directory Name						| N/A
0x300 - Adjust Video Brightness		| Brightness level, Min = 0x101, Max = 0x2C0, 0x40 increments	| N/A
0x400 - Unknown				| N/A								| N/A
0x500 - Grab Video Thumbnail Data*	| Width of thumbnail (60 pixels)				| Height of thumbnail (40 pixels)
0x600 - Grab ID3 Data*			| Music Filename						| N/A
0x700 - Play Video/Grab Video Frame*	| Width of video (240 pixels)					| Height of video (160 pixels)
0x701 - Stop Video Playback		| N/A								| N/A
0x800 - Play Music File*		| Music Filename						| N/A
0x801 - Stop Music Playback		| N/A								| N/A
0x902 - Pause Music/Video Playback	| N/A								| N/A
0x903 - Advance Frame			| Advance Frame Speed						| N/A
0x904 - Resume Music/Video Playback	| N/A								| N/A
0x905 - Seek Forwards/Backwards		| Seek Speed							| Seek Position
0x906 - Sleep During Playback		| Sleep Status, 0 = Enter Sleep Mode, 1 = Exit Sleep Mode	| N/A
0xB00 - Adjust Volume			| Volume level, Min = 0x00, Max = 0x38				| N/A
0xD00 - Adjust Bass Boost		| Bass boost level, Min = 0x00, Max = 0x0F			| N/A
0xD01 - Enable/Disable Bass Boost	| ON = 0x800F, OFF = 0x8F0F					| N/A
0x2000 - Play Sound Effect		| N/A								| N/A
0x3000 - Check For Key File*		| Key File Name							| N/A
0x3001 - Read Key File Data		| N/A								| N/A
0x3003 - Close Key File			| N/A								| N/A
0x8000 - Check For Firmware		| N/A								| N/A
0x8001 - Load Firmware			| N/A								| N/A
0x10000 - Enter Sleep Mode		| N/A								| N/A
0x800000 - Unknown			| N/A								| N/A
----------------------------------------------------------------------------------------------------------------------------------------------

*These commands send non-standard amounts of data for their parameters. See the end of this section for further details on each. additional data beyond a second parameter. Overall, it sends a total of 0x218 bytes, the latter portion of which has an unknown purpose.

The Play-Yan Micro exclusively uses serial commands and uses the following proceedure to issue them:

-----------------------------------------------------------------------
PY_DATA_MODE = 0x28
PY_DATA_ADDR = 0xF020
PY_DATA_ADDR = 0x000F
UNKNOWN REGISTER 02 = 0x00

WAIT FOR BIT 7 OF PY_STAT TO READ HIGH
WRITE 16-BIT DATA INTO 0xB000000
REPEAT 16-BIT WRITES INTO 0xB000000 AS NEEDED FOR COMMAND LENGTH
PY_DATA_PARAM = 0x0C
PY_DATA_PARAM = 0x08
-----------------------------------------------------------------------

The original Play-Yan exclusively uses non-serial commands and uses the following proceedure to issue them:

-----------------------------------------------------------------------
PY_DATA_MODE = 0x68
PY_DATA_ADDR = 0xF020
PY_DATA_ADDR = 0x000F
UNKNOWN REGISTER 02 = 0x00

WAIT FOR BIT 7 OF PY_STAT TO READ HIGH
WRITE DATA INTO 0xB000100 THROUGH 0xB00010B
PY_DATA_PARAM = 0x0C
PY_DATA_PARAM = 0x08
-----------------------------------------------------------------------

Note that the data address specified by PY_DATA_ADDR is 0xFF020. Some commands will trigger a Game Pak IRQ when the Play-Yan responds. See the section below for more details.

* The 0x201 Change Current Directory command uses Parameter 1 as a null-terminated string representing the target folder the Play-Yan will move into. The string has no fixed length, thus making this an irregular command. The Play-Yan appears to send additional unknown data after the string.

* The 0x500 Grab Video Thumbnail Data command sends additional data via Parameter 3. Some of these bytes are a null-terminated string representing the filename of a specific video to generate thumbnail data. This string begins at 0xB000114. Altogether, 0x218 bytes are sent. Since this amount exceeds the 0xB0002FF boundary for parameter input, the last 0x18 bytes are written at the beginning of the section, starting over at 0xB000100.

* The 0x600 Grab ID3 Data command uses Parameter 1 as a null-terminated string representing the target file to lookup metadata. The string has no fixed length, thus making this an irregular command. The Play-Yan appears to send additional unknown data after the string.

* The 0x700 Play Video command uses Parameter 3 as a null-terminated string representing the filename of a specific video file to play. Like music, the Play-Yan software internally monitors which video the user has highlighted and passes the filename's string to the hardware. This string likewise has no fixed length. The Play-Yan appears to send additional unknown data after the string.

* The 0x800 Play Music File command uses Parameter 1 as a null-terminated string representing the filename of specific music file to play. The Play-Yan software internally keeps track of which song the user has currently highlighted, and it passes the filename's string to the hardware. The string has no fixed length, thus making this an irregular command. The Play-Yan appears to send additional unknown data after the string.

* The 0x903 Advance Frame Command moves the current video playback position forward by the number of frames specified in Parameter 1. The Play-Yan software only ever uses a value of 0x01 for this command, thus in practice it always advances by a single frame. This command is used when video playback is paused. Note that there does not appear to be a corresponding command to step backwards by a given amount of frames while paused. The Play-Yan software somewhat gets around this by temporarily unpausing playback, calling the Seek Backwards command, and quickly pausing the video again.

* The 0x905 Seek Forwards/Backwards command uses Parameter 1 to indicate the direction to fast forward or rewind audio/video. It operates differently depending on which media is being played. For audio, it represents a new value for the Track Bar Position used for the 0x800 command. To go forward, the Play-Yan's software takes the current value and increments it, then passes it along to the 0x905 command. For video, values 0x01 - 0x03 moves forward; higher values skip ahead further. Values 0xFFFFFFFF through 0xFFFFFFFD move backwards; lower values rewind more. For the Play-Yan Micro, the parameters are 16-bit, therefore rewinding uses values 0xFFFF through 0xFFFD instead.

Additionally for videos, when setting Parameter 1 to 0x00, Parameter 2 acts as a specific seek position. This allows video playback to jump to a fixed timestamp. The Play-Yan's software uses this feature to continue videos if the user exits before it finishes. The value of Parameter 2 appears to be a frame number. Note that while the Play-Yan software automatically records the frames count when exiting a video, it always restarts the playback several seconds (~5 to 6) prior to the exit. If a video is cancelled too early, the software won't even bother offering the user the option to continue playback and will simply restart from the beginning.

* The 0x906 Sleep During Playback command uses Parameter 1 to indicate whether the Play-Yan hardware should enter or exit Sleep Mode while playing music. Note that this Sleep Mode is different from the GBA's. Here, the cartridge will continously generate audio through its built-in headphone jack. After issuing the 0x906 command to enter Sleep Mode, the Play-Yan's software will separately put the GBA into a low-power mode Halt state. This command is also different from the 0x10000 Enter Sleep Mode command. Most importantly, 0x906 command does not generate Game Pak IRQs when exiting Sleep Mode. Additionally, this command is only available to the user when headphones are plugged in.

The GBA and Play-Yan will briefly exit Sleep Mode when a song ends. The Play-Yan will generate a Game Pak IRQ for the 0x801 Stop Music Playback command at that time. The Play-Yan's software will then re-enter Sleep Mode on its own after a few seconds unless the user intervenes.

* The 0x3000 Check For Key File command uses Parameter 1 as a null-terminated string representing the filename of the "key file", which is a .ini text file containing various settings such as what theme to use, video brightness, and audio volume. This command, as well as all other 0x300x commands, is exclusive to the Play-Yan Micro. The string should have a fixed length, as the software is hardcoded to use "play_yanmicro.ini", however, it can technically be any length.


***************************************************
7. Game Pak IRQs
***************************************************

The Play-Yan's hardware produces a variety of Game Pak IRQs when the software sends certain commands. Not every command will generate an IRQ, however, the ones that do are pivotal to operating the Play-Yan. For example, during the initial boot process, the Play-Yan's software waits indefinitely until several commands to respond with IRQs, without which the software essentially locks up. Each Game Pak IRQ returns data that can be read at 0xB000300 - 0xB00031F. Some commands may cause multiple IRQs to be generated as well, where the first 4 bytes of return data is simply 0x80000100 or 0x80001000. This signifies the end of certain internal operations within the Play-Yan, generally related to firmware loading, or audio/video playback. Use the following process to read the Game Pak IRQ data:

-----------------------------------------------------------------------
PY_DATA_PARAM = 0x08
PY_DATA_MODE = 0x78
PY_DATA_ADDR = 0xF000
PY_DATA_ADDR = 0x000F
UNKNOWN REGISTER 02 = 0x00
PY_DATA_PARAM = 0x09

WAIT FOR BIT 4 OF PY_FIRM_STAT TO READ HIGH
PY_DATA_PARAM = 0x08
READ DATA FROM 0xB000300 THROUGH 0xB00031F
-----------------------------------------------------------------------

A list of commands and their known IRQs and the IRQ data is shown below:

-----------------------------------------------------------------------
Command 0x200 - Get Filesystem Information - 1 IRQ
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40000200
Bytes 0x04 - 0x07	| 0x01 or 0x02
-----------------------------------------------------------------------

This command prompts the Play-Yan to start reading the filesystem on the SD card. It allows the software to grab a list of available files or folders for music, or video files. The Play-Yan will scan for any files and folders it can find. Afterwards, the software can read the data through the SD Card Data interface described in the section above. The data contains the total number of files and folders within the directory along with 268-byte entries of metadata for each item found. The format of the list returned via SD Card Data is as follows:

-----------------------------------------------------------------------
Bytes 0x0000 - 0x0003	| Unused (zeroes)
Bytes 0x0004 - 0x0007	| Number of files and folders
Bytes 0x0008 - 0x67FF	| File/Folder metadata
-----------------------------------------------------------------------

The format for each 268-byte metadata entry for files/folders is as follows:

-----------------------------------------------------------------------
Bytes 0x0000 - 0x00FF	| Name (ASCII or UTF-8 for kana and kanji)
Bytes 0x0100 - 0x0107	| Some kinda hash or checksum
Bytes 0x0108 - 0x010B	| Entry Type
-----------------------------------------------------------------------

The name of the file/folder should be null-terminated, otherwise the Play-Yan will consider the entry invalid. The string encoding can be plain ASCII for Latin script, or UTF-8 when using Japanese characters.

The Entry Type describes what kind of item was found within the filesystem. If Bit 0 is set, the Play-Yan will register the item as a Video File. If Bit 1 is set, the Play-Yan will register the item as a Music File. If neither Bit 0 nor Bit 1 is set, the Play-Yan will register the item as a Folder. This behavior is only applicable when reading Music Files, however. When reading Video Files, all videos present on the SD card are returned and folders are ignored. That is to say, the Get Filesystem Information automatically acts recursively for Video Files. When used for Music Files, it acts exclusively on the current directory.

The second parameter determines what types of files will be returned. If this parameter is set to 0x01, the Play-Yan will only return Video Files when reading entries from SD Card Data. If this parameter is set to 0x02, the Play-Yan will only return Music Files when reading entries from SD Card Data.





-----------------------------------------------------------------------
Command 0x201 - Change Current Directory - 1 IRQ
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40000201
-----------------------------------------------------------------------

Changes the current directory the Play-Yan will look for new files and folders. The folder to change into must be passed as a null-terminated string for Parameter 1. The Play-Yan is capable of traversing up and down directories through this mechanism. The Play-Yan software is programmed to automatically search through various folders and sub-folders in order to map out existing music or video files. If the string in Parameter 1 is just "..", the Play-Yan will move upwards by one folder, allowing it to backtrack through previous directories.





-----------------------------------------------------------------------
Command 0x500 - Grab Video Thumbnail Data - 1 IRQ
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40000500
Bytes 0x04 - 0x07	| Unknown
Bytes 0x08 - 0x0B	| Unknown
Bytes 0x0C - 0x0F	| Video Length in Milliseconds
-----------------------------------------------------------------------

After the 0x500 command is issued, a corresponding Game Pak IRQ signals that the Play-Yan is ready to provide a 60x40 thumbnail image for a video file. For the specifics regarding reading these thumbnails, refer to the appropiate section below.

The Video Length in Milliseconds is the overall total playtime for a specific video. This data is passed from the Play-Yan to its software when accessing a video's thumbnail. Unlike music, videos do not constantly update the position of the trackbar via Game Pak IRQs while playing. Instead, the Play-Yan's software handles that when the timestamp is updated. It will use the value specified here in conjunction with the Current Video Position (see the 0x700 command) to calculate how far along the video has progressed.







-----------------------------------------------------------------------
Command 0x600 - Grab ID3 Data - 1 IRQ
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40000600
Bytes 0x04 - 0x07	| Unknown (must be non-zero to grab data)
-----------------------------------------------------------------------

This command instructs the Play-Yan to grab ID3 data for a given song. It always precedes the 0x800 command when playing music since the Play-Yan displays the ID3 information onscreen during this time. The exact purpose of Bytes 0x04 - 0x07 are unknown, however, this value must be non-zero to indicate that the ID3 data exists at all. After this command has executed, the necessary ID3 data can be read via the SD Card Data interface. The format of ID3 data is as follows:

-----------------------------------------------------------------------
Bytes 0x0000 - 0x0003	| Unused (zeroes)
Bytes 0x0004 - 0x0044	| Song Title
Bytes 0x0045 - 0x008B	| Artist Name
-----------------------------------------------------------------------

Each entry (for title and artist name) is a null-terminated string encoded as ASCII for Latin script or Shift-JIS for kana and kanji. While the Play-Yan supports parsing ID3v2 tags, it does not support several text encodings. Unicode strings are not recognized for this command. As such, the text encoding flag for a tag inside the actual MP3 should be 0x00 (for ISO-8859-1). Additionally, while this implies it should technically support extended ASCII characters, the Play-Yan does not have the font to render them.





-----------------------------------------------------------------------
Command 0x700 - Play Video/Grab Video Frame - 2 IRQs*
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40000700
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x80001000
Bytes 0x04 - 0x07	| Unknown
Bytes 0x08 - 0x0B	| Frame Size in Bytes
Bytes 0x10 - 0x13	| Audio Buffer Size
Bytes 0x18 - 0x1B	| Current Video Position
-----------------------------------------------------------------------

These interrupts are responsible for alerting the Play-Yan's software when a new video frame is ready for display, updating the current playback position within a video, and updating the video's audio. The first IRQ initializes the process, while the second IRQ repeats indefinitely until the end of the video.

There are 2 distinct types of Game Pak IRQs generated continuously when playing a video file. The first updates video data and the current timestamp, while the second updates the audio data. If Audio Buffer Size is non-zero, only the audio is updated, otherwise video is updated. Do note that when headphones are plugged in, the Play-Yan only generates Game Pak IRQs that update video data.

The Current Video Position's value is expressed in milliseconds. As this IRQ fires every time a video frame needs to be displayed, the value incremented should match the video's framerate. E.g. for a video playing at 30 frames-per-second, the Current Video Position value increases by approximately 0x21 or 0x22. The video frame itself is read similarly to video thumbnails. Refer to the appropiate section below for more details. The size of the frame is the video's resolution on the GBA (typically 240x160) in 15-bit color pixels. Therefore, this value is usually 0x12C00.

Sample data is read from the SD Card Data interface. The data is equally split into left and right audio buffers. Typically, the buffer will always be 0x480 samples total unless the very end of a video has fewer than that remaining. Videos always use a sample rate of 8192Hz.

*The second IRQ constantly fires for the duration of the video for as many frames need to be updated each second.





-----------------------------------------------------------------------
Command 0x701 - Stop Video Playback - 1 IRQ
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40000701
-----------------------------------------------------------------------

Stops the current video file that is playing.





-----------------------------------------------------------------------
Command 0x800 - Play Music File - 2 IRQs*
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40000800
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x80001000
Bytes 0x0C - 0x0F	| Unknown
Bytes 0x10 - 0x13	| Audio Buffer Size
Bytes 0x14 - 0x17	| Trackbar Position
Bytes 0x18 - 0x1B	| Play Time in Seconds 
-----------------------------------------------------------------------

After the 0x800 command is issued, a Game Pak IRQ is generated when the Play-Yan hardware begins processing an audio file. This command always follows the 0x600 command.

The Track Bar Position indicates how far along the visual slider has moved across the screen for the duration of the song. It seems to work on a scale of 0x0000 to 0x6400. To move the track bar accurately, this value should increment by (0x6400 / Song Length in Seconds) on average every second. When fast-forwarding or rewinding, this value changes accordingly.

The Play Time in Seconds represents the amount of time elapsed while playing the current song. Unlike the Current Video Position for the Play Video command, here the number of seconds passed is directly returned. That is to say, a value of 0x1E represents a time of 00:00:30 (30 seconds), value of 0x3C represents a time of 00:01:00 (1 minute, e.g. 60 seconds), and a value of 0xFF represents a time of 00:04:16 (4 minutes, 16 seconds, e.g. 256 seconds). Again, fast-forwarding or rewinding will change the result returned by the Play-Yan.

There are 2 distinct types of Game Pak IRQs generated continuously when playing an audio file. The first updates audio samples that the GBA can read from a buffer and push out to its own speakers. The second updates the trackbar exclusively. The Play-Yan's audio processing hardware will alert the CPU when it has converted samples from an MP3 file into samples compatible with the GBA's DMA channels. The maximum amount of samples the Play-Yan can buffer is 0x480 bytes.

For updating audio samples, only the bytes 0x10 through 0x13 need be non-zero. If those bytes are zero, then the Play-Yan software will interpret the IRQ data as representing an update to the trackbar, in which case bytes 0x14 through 0x1B should hold values appropiate for the current playback time. Do note that when headphones are plugged in, the Play-Yan only generates Game Pak IRQs that update the trackbar position. In this case, the Play-Yan's hardware handles pushing out audio samples, therefore an audio buffer is not needed.

Sample data is read from the SD Card Data interface. The data is equally split into left and right audio buffers. Typically, the buffer will always be 0x480 samples total unless the very end of a song has fewer than that remaining. Music always uses a sample rate of 16384Hz.

*The second IRQ constantly fires for the duration of the music.





-----------------------------------------------------------------------
Command 0x801 - Stop Music Playback - 1 IRQ
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40000801
-----------------------------------------------------------------------

Stops the current music file that is playing.





-----------------------------------------------------------------------
Command 0x2000 - Play Sound Effect - 1 IRQ*
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x80001000
Bytes 0x10 - 0x13	| Audio Buffer Size
-----------------------------------------------------------------------

This command generates a brief sound effect from the Play-Yan. It is typically used for menus or when playing Garage Games. The default sound effect (something like a chirp) is the same in all instances. It is necessary for the Play-Yan itself to generate these sound effects rather than the GBA because the Play-Yan may need to push samples through the built-in headphone. The Play-Yan is responsible for generating all sound (music, video, and sound effects), and it also determines whether or not the headphone jack or the GBA's speakers will be used as output. Samples for the sound effect are embedded within firmware, so the sound itself can be changed in theory.

Sound effects use an audio buffer much like music and videos do, with the same format. The audio buffer size of sound effects, however, is generally extremely short, measuring in at only 0x2BA samples. While the original Play-Yan uses a set sample rate of 8192Hz for sound effects, the Play-Yan Micro switches from 16384Hz during the intro animation to 8192Hz for all subsequent operations. Do note that these IRQs are not generated when headphones are plugged into the Play-Yan.

*This IRQ constantly fires for the duration of the sound effect.





-----------------------------------------------------------------------
Command 0x3000 - Check For Key File - 1 IRQ
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40003000
Bytes 0x04 - 0x07	| Key File Exists Flag
-----------------------------------------------------------------------

This command prompts the Play-Yan Micro to check the root directory of the SD card for the presence of a key file. The file should be named "play_yanmicro.ini". If this file exists, it proceeds to open it and try and parse the contents of the text file. If it can't find the file, it will boot up anyway and resort to using default settings. The second 32-bit value returned by this IRQ indicates whether the file was found. A value of zero indicates the file is available, while any non-zero value indicates a problem.





-----------------------------------------------------------------------
Command 0x3001 - Read Key File Data - 1 IRQ
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40003001
Bytes 0x04 - 0x07	| Key File Is Open Flag
Bytes 0x08 - 0x0B	| Key File Size
-----------------------------------------------------------------------

This command opens and reads the contents of the key file on the Play-Yan Micro. After executing this command, the key file can be read back as SD Card data. The second return value for this IRQ is a flag detailing the file's status. A value of zero indicates it was successfully opened, while any non-zero values indicates a problem. The third return value is the size of the key file in bytes. If the key file cannot be opened during this stage, the Play-Yan Micro will use default settings. After reading the key file, the Play-Yan Micro will parse and validate the results. If there is an issue here, the software will still boot up with default settings, however, it will display an icon representing a bad key file.





-----------------------------------------------------------------------
Command 0x3003 - Close Key File - 1 IRQ
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40003003
-----------------------------------------------------------------------

This command presumably closes the key file. The Play Yan Micro only executes this command if the key file was previously opened.





-----------------------------------------------------------------------
Command 0x8000 - Check For Firmware - 1 IRQ
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40008000
Bytes 0x08 - 0x0B	| Firmware File Status
-----------------------------------------------------------------------

This command is used to determine if a firmware update file is present on the root of the SD card. If both Bit 0 and Bit 1 are set for the Firmware File Status, the Play-Yan software will take steps to load in the new firmware file. In this case, the Play-Yan's code also calls the 0x8001 command immediately after writing to firmware. 





-----------------------------------------------------------------------
Command 0x8001 - Load Firmware - 1 IRQ
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x80000100
Bytes 0x04 - 0x07	| SD Card Status
-----------------------------------------------------------------------

This command seems to load a firmware update file if it's present. A single value is returned for the overall status of the Play-Yan cartridge. This can be used to determine if an appropiate SD card has been inserted or if there are any problems in general. Non-zero values for the SD Card Status represent specific errors. The Play-Yan will halt and display the following messages:

-----------------------------------------------------------------------
0x01	| カートリッジが調子悪いみたい...
	| The cartridge seems to be in bad shape...
-----------------------------------------------------------------------
0x02	| SDカードが調子悪いみたい... 電源を切ってSDカードをチェックしてネ。
	| The SD card seems to be in bad shape... Turn off the power and check the SD card.
-----------------------------------------------------------------------
0x03	| SDカードが入ってないヨ! 電源を切って SDカードを入れてネ。
	| There's no SD card! Turn off the power and insert an SD card.
-----------------------------------------------------------------------
0x04	| ファイルがおかしいみたい。
	| The file seems to be wrong.
-----------------------------------------------------------------------
0x05+	| エラーが出ちゃいました... 
	| An error occurred...
-----------------------------------------------------------------------

This command is called at various points when the new firmware is apparently executing, such as during boot and when the user switches between Music and Video menus.




-----------------------------------------------------------------------
Command 0x10000 - Sleep - 1 IRQ
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x80010001
-----------------------------------------------------------------------

This command is called right before the Play-Yan forces the GBA hardware into low-power STOP mode via a software interrupt. After the 0x10000 command, the Play-Yan itself will evidently enter into some kind of low-power state as well. It seems to wake up automatically when the GBA exits STOP mode. At that time, the Play-Yan will generate a Game Pak IRQ to indicate that the hardware is awake and ready to use.





-----------------------------------------------------------------------
Command 0x800000 - Unknown - 2 IRQs
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40800000
-----------------------------------------------------------------------

This command is issued only if no firmware update file was found. It seems to take the place of the 0x8001 command in that case. Its purpose is currently unknown, but appears related to firmware.





For each Game Pak IRQ, the first 4 bytes acts as a sort of 32-bit "ID" for the command used. This helps the Play-Yan software figure out what exactly triggered the IRQ in the first place. Typically, this ID is simply the command itself OR'ed with 0x40000000 or 0x80000000, although some exceptions such as the Sleep command do exist. When the ID has been OR'ed with 0x40000000, this means the Play-Yan is directly responding to a command issued by the software and generating an appropiate Game Pak IRQ. IDs OR'ed with 0x80000000, on the other hand, represent Game Pak IRQs generated by the Play-Yan on its own. Again, this is generally used to signal the end of certain internal operations. In such cases, the software explicitly waits and treats the Play-Yan hardware as busy with a given task.

Writing the value 0xA5A50032 to the firmware address 0x10000400 appears to generate a Game Pak IRQ. This is first done during boot, after the software has uploaded a copy of firmware from ROM to the Play-Yan. This special firmware write also occurs at various times when a firmware update file has been detected (notably before entering the Music or Videos menus). The response data for this IRQ is always 0x80000100, and the Play-Yan software will pause indefinitely until this IRQ is handled. However, this IRQ is not generated when the Play-Yan exits Sleep Mode. This special write seems to cause the Play-Yan to execute any data currently written to firmware.


***************************************************
8. Reading Video Frames and Video Thumbnails
***************************************************

Use the following process to read video frame or video thumbnail data after issuing the 0x500 or the 0x700 command:

-----------------------------------------------------------------------
PY_DATA_PARAM = 0x08
PY_DATA_MODE = 0x78
PY_DATA_ADDR = 0x0000
PY_DATA_ADDR = 0x0000
UNKNOWN REGISTER 02 = 0x00
PY_DATA_PARAM = 0x09

WAIT FOR BIT 4 OF PY_FIRM_STAT TO READ HIGH
READ DATA FROM 0xB000500 THROUGH 0xB0006FF
-----------------------------------------------------------------------

Data can be read sequentially in 512-byte blocks without the need for writing to other registers. Simply waiting for Bit 4 of PY_FIRM_STAT is sufficient. Each frame or thumbnail will be the size as specified by the 0x500 or the 0x700 command, which ordinarily is 60x40 and 240x160, respectively. Both use 15-bit pixels, and their format is an exact match for the Game Boy Advance's bitmap mode (BG Mode 3). In total, the Play-Yan will typically provide 0x12C0 bytes of data for each thumbnail and 0x12C00 for each video frame.

A 0x500 command must be issued for each thumbnail the Play-Yan needs to process. Each page in the Play-Yan's file browser can only contain 6 videos, therefore, the Play-Yan's software only issues 6 of these commands at a time. If a page has less than 6 entries, only that many 0x500 commands need to be sent. The Play-Yan will only use the first frame of a given video to generate a thumbnail.

For video frames, the 0x700 command is only issued once. Subsequent Game Pak IRQs are automatically generated by the video processing hardware for each frame, at which point the Play-Yan can read back this data and display them using BG Mode 3 for fullscreen bitmap display.


***************************************************
9. Garage Games
***************************************************

The original Play-Yan allowed users to access 13 minigames called "Garage Games". After the Play-Yan launched, Nintendo released them on their website in a weekly fashion. Users downloaded a special .ASF file, and when stored on an SD card, the Play-Yan would start the game. The entire game took place in the 60x40 window dedicated to video thumbnails. Contrary to most available information, these Garage Games are technically not "DLC". Each Garage Game already exists in the Play-Yan ROM and the .ASF files contain no executable code. However, the Garage Games are normally inaccessible without the .ASF files present. The files Nintendo provided act as a sort of key that unlocks the content.

Each .ASF file is a valid video and will generate a thumbnail preview on the Play-Yan. This thumbnail acts as a fingerprint that the Play-Yan can use to identify an individual file. The 0x12C0 bytes of thumbnail data is quickly hashed into a 32-bit number and compared against a list of expected values. Should the thumbnail's hash match that internal list, the Play-Yan recognizes it as a Garage Game.

It should also be noted that the video file's name has to match as well. If the file name is incorrect, the Play-Yan won't bother creating a hash and will simply treat it as a regular video file. This behavior can be reproduced by renaming any of the .ASF files from Nintendo. The names of each Garage Game is case-sensitive as well; they all need to be uppercase in order to work. A list of all the Garage Games and their 32-bit hashes is provided below:

AVOID		0xF8CB9008
BAT		0xD911FE57
CREDIT		0x02F86041
FIRE		0x0D78A9FE
FISH		0x5741DE47
INSECT		0x4D5E5AEB
JUMP		0x748C5BAF
KEEPER		0x3FEBEFE5
MEMORY		0x90119AE6
NEKOROID	0xD839D809
NOSE		0x86D3BA78
TRIPLE		0xD5C0A40B
WAVE		0xE7DCD82B

The hash can be calculated using the following psuedo-code:

-----------------------------------------------------------------------
HASH = 0
INDEX = 0

WHILE INDEX NOT EQUAL TO 0x960
	HASH = HASH + 16-BIT THUMBNAIL PIXEL DATA
	HASH = HASH ROTATE RIGHT 31
	INCREMENT INDEX BY 1
-----------------------------------------------------------------------

Although this hashing prevents most ordinary videos from randomly generating a thumbnail that triggers the Garage Game to play, the hashing method is prone to collisions. It is possible, therefore, to specifically create a thumbnail that matches any of the above listed hashes, in effect creating "bootleg" Garage Games.


***************************************************
10. Key File
***************************************************

The key file is a simple text file the Play-Yan Micro reads on when starting up. The file name must be "play_yanmicro.ini" and must be stored in the SD card's root directory. The Play-Yan Micro uses this to change various settings automatically for the user. Note that the key file is exclusive to the Play-Yan Micro and is not used at all for the original Play-Yan. Below is the default key file provided by Nintendo, along with an explanation of the entries and their values:

-----------------------------------------------------------------------
PLAY_YAN_Design=1
PLAY_YAN_StartMode=1
PLAY_YAN_VolumeAdd=0
PLAY_YAN_AudioPlayMode=0
PLAY_YAN_AudioBass=0
PLAY_YAN_AudioWide=0
PLAY_YAN_VideoPlayMode=0
PLAY_YAN_VideoBright=0
-----------------------------------------------------------------------

PLAY_YAN_Design: Changes the user-interface theme between Pictogram and Mario (values 0 and 1 respectively).

PLAY_YAN_StartMode: Determines whether Videos or Music will be the default selected option on the main menu after booting (values 0 and 1 respectively).

PLAY_YAN_VolumeAdd: Determines the initial level of volume for all media. Uses values -18 to 9 for mute volume to just below the max (does not use the 10 highest levels of volume).

PLAY_YAN_AudioPlayMode: Determines how songs are played, such as loop through all songs, loop over a single song continuously, loop over songs randomly, or play all songs in order once (values 0 through 3 respectively).

PLAY_YAN_AudioBass: Determines whether the bass is left at default levels or amplified (values 0 and 1 respectively).

PLAY_YAN_AudioWide: Determines the level of stereo sound amplification (values 0 through 6).

PLAY_YAN_VideoPlayMode: Determines how videos are played, such as play a single video once, loop over a single video continously, play all videos once, or loop over all videos (values 0 through 3 respectively).

PLAY_YAN_VideoBright: Determines the level of brightness adjustment for video playback (values 0 through 5).


***************************************************
11. Firmware Update
***************************************************

Both the original Play-Yan and the Play-Yan Micro have the ability to update their internal firmware when the appropiate file is provided in the root directory of the SD card. This update is applied after the default firmware is loaded from ROM. Apparently the default firmware contains a hard-coded string that will be used for the update. The original Play-Yan looks for a file called "playan.fup", while the Micro version looks for a file called "play_yanmicro.fup".

Nintendo only ever released a firmware update file for the original Play-Yan, in July of 2005. The update added MP4 support (MPEG-4 as the video codec and stereo AAC as the audio codec), bringing the original model inline with the later Micro version. This firmware update file measures in at around 554KB and is still available to download from Nintendo's Japanese website. No firmware update file for the Play-Yan Micro is known to exist, however.

The following is the current working theory of how firmware update is processed:

1) Default firmware from ROM is loaded into firmware and executed at boot.

2) Later during boot, the 0x8000 command is issued to determine if a firmware update file is present.

3) If a firmware update file is present, a small portion of default firmware from ROM is rewritten and executed.

4) Immediately afterwards, the 0x8001 command is issued. This seems to automatically load and execute the firmware update file.

5) The Play-Yan's software checks the SD card status as reported by 0x8001 to make sure no errors occurred.

Steps 3 through 5 appear to repeat every time the user enters the Music or Videos menu. It is important to note that this happens only after boot, or when switching from Music to Videos or switching from Videos to Music. Exiting the Music menu and re-entering the Music menu, for example, does not trigger the above process. As the firmware file is quite massive for the GBA, it appears the firmware file is not read manually byte-by-byte (in contrast to the Nintendo MP3 Player). The 0x8001 command likely handles loading and validating the firmware update file.