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.
- Used 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.
- Could generate video thumbnails and parse some ID3 tags.
- Videos used ASF or MP4 containers with G.726 or AAC as audio codecs, respectively.
- Maximum of 30 frames-per-second for video.
- The original version came with 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 IO 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. For the original Play-Yan, the software looks for the file "playan.fup". Nintendo did release at least one firmware update as well, allowing the original Play-Yan to run MP4 files, something the later Play-Yan Micro version could do out-of-the-box.

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
0x904 - Resume Music/Video Playback	| N/A								| N/A
0x905 - Seek Forwards/Backwards		| Seek Speed (1x, 2x, 3x, 4x?), Min = 1, Shift Left 1 Per Step	| N/A
0x906 - Unknown				| N/A								| 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 - Get Cartridge Status		| 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 unknown data via Parameter 3. 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 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 return data is simply 0x80000100 or 0x80001000 to signify the end of certain internal operations within the Play-Yan. 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 - 2 IRQs
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40000200
Bytes 0x04 - 0x07	| 0x01 or 0x02
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x80001000
-----------------------------------------------------------------------

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 the current directory 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 some other encoding for kana)
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 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.

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. This parameter does not affect how folders are returned in the list, however.





-----------------------------------------------------------------------
Command 0x201 - Change Current Directory - 2 IRQs
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40000201
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x80001000
-----------------------------------------------------------------------

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
-----------------------------------------------------------------------

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.





-----------------------------------------------------------------------
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 or some other encoding for kana.





-----------------------------------------------------------------------
Command 0x700 - Play Video/Grab Video Frame - 2 IRQs*
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40000700
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x80001000
Bytes 0x04 - 0x07	| Video Length Counter
Bytes 0x08 - 0x0B	| Frame Size in Bytes
Bytes 0x14 - 0x18	| Current Video Position
-----------------------------------------------------------------------

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

Each time the second IRQ is fired, the Current Video Position is updated. The Play-Yan software uses this to determine the minutes/seconds timestamp. It appears that the value 0x3C0 roughly equates 1 second. This IRQ fires every time a video frame needs to be displayed, therefore it should match the video's framerate. Each increment of the Current Video Position should thus reflect that. E.g. for a video playing at 30 frames-per-second, the Current Video Position updates at roughly 0x20 intervals.

The frame itself is read similarly to video thumbnails. Refers to the appropiate section below for more details. The size of the frame is the video's resolution (typically 240x160) in 15-bit color pixels. Therefore, this value is usually 0x12C00.

*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 - 2 IRQs
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40000701
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x80001000
-----------------------------------------------------------------------

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	| Unknown
Bytes 0x14 - 0x17	| Track Bar 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.

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





-----------------------------------------------------------------------
Command 0x801 - Stop Music Playback - 2 IRQs
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40000801
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x80001000
-----------------------------------------------------------------------

Stops the current music file that is playing.





-----------------------------------------------------------------------
Command 0x2000 - Play Sound Effect - 1 IRQ
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x80001000
-----------------------------------------------------------------------

Only 1 IRQ is fired for this command. It appears to force the Play-Yan to generate a brief sound effect, typically used for menus or when playing Garage Games. The sound effect (something like a chirp) is the same in all instances. It is necessary for the Play-Yan itself to generate the 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 decides whether or not to use the headphone jack or the GBA's speakers as output. 





-----------------------------------------------------------------------
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 - Get Cartridge Status - 1 IRQ
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x40008000
Bytes 0x04 - 0x07	| SD Card Status
-----------------------------------------------------------------------

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. As the SD card is essential for the Play-Yan, this is the first command executed when booting. Setting the following bits indicates specific errors, and the Play-Yan will halt booting up and display an appropiate message:

-----------------------------------------------------------------------
Bit 0	| The cartridge is in bad condition
Bit 1	| No SD card detected or incompatible card inserted
Bit 2	| Filesystem error
-----------------------------------------------------------------------

Setting Bits 0 and 1 together produces the same "cartridge is in bad condition error". Setting Bits 0 and 2 together produces a general error. If no bits are set, this indicates there were no problems.





-----------------------------------------------------------------------
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
Bytes 0x04 - 0x07	| SD Card Status
-----------------------------------------------------------------------
Bytes 0x00 - 0x03	| 0x80001000
-----------------------------------------------------------------------

This command is issued shortly after Get SD Card Status. It's purpose is currently unknown. It generates 1 IRQ, which also returns the card's status.





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.

During boot, however, after the software has uploaded a copy of firmware from ROM to the Play-Yan, the Play-Yan will generate an initial Game Pak IRQ, unprompted by any command. This alerts software that the Play-Yan hardware is finally ready and can now accept commands. The response data for this IRQ is 0x80000100. The software will pause indefinitely until it receives this IRQ.


***************************************************
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. It seems a 0x2000 command is always issued before the first 0x500 command; this may be the mechanism that tells the Play-Yan which videos need thumbnails generated.

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).