You are not logged in.

Read the FAQ and Knowledge Base before posting.
We won't make a 3DS/2DS emulator.



#1 2024-08-05 13:59:59

windwakr
Member
Registered: 2010-06-10
Posts: 33

Details on various slot2 accessories

I have no desire to properly implement these so I'll just leave this info here, where it is unlikely to be seen by anyone. tongue


The Motion Pack was used by one game, Tony Hawk's Motion. The bare minimum for detection to succeed is to return 0xFCXX on word sized reads. The game will enter a loop polling bytes from 0x0A000000. I don't fully understand this part but you can get it to continue by letting it read [0x00, 0x03, 0x03, 0x03, 0x03]. It will then read bytes from the same address for the X, Y, and Z acceleration values. These are served two bits at a time(starting from the top of the byte) in the least significant bits of the return value. for a total of 12 reads. A value of 0x80 seems to be the neutral point for each acceleration value? It will then go back to polling the address for those 5 values from earlier. This is enough to fully play Tony Hawk and its included "Hue Pixel Painter" minigame. In my example video I had hooked up Lua bindings and sent in my controller analog stick as the X/Y acceleration values through a Lua script.

One additional note is that depending on the values received, the game can change how it accesses the device. If you only send 0x03 on byte reads initially then the Tony Hawk portion of the game will actually switch over to reading it as if it were an NDSmotion Motion Pak. See libnds for how that works: https://github.com/devkitPro/libnds/blo … dsmotion.c
This mode is not necessary to emulate for playing the game as you can just send the sequence I mentioned earlier instead to have it read the values sequentially from 0x0A000000.

Video: https://files.catbox.moe/wkpnb6.webm


The Bayer Didget was used by one game, Knock 'Em Downs: World's Fair. The bare minimum for detection to succeed is to return 0xF3XX on word sized reads. The game then performs two reads from 0x0A000000 and expects them to be 0xBD and 0xDA. It then works like a glucoboy, which shonumi has reverse engineered and written a blog post about. After it writes to 0x0A000000 to pick a register to read, you trigger a gba slot interrupt( setIF(PROCNUM, 0x2000); ) to tell it that a byte is ready for it to read from 0x0A000000. I'm not sure if the registers it reads from are exactly the same as the glucoboy, so it would take a bit of exploration. Overall though, it's a simple add-on to emulate.

Pic: https://files.catbox.moe/qw5n9c.png

Last edited by windwakr (2024-09-06 22:07:46)

Offline

#2 2024-08-07 14:13:51

AsPoke3172
Member
Registered: 2010-04-21
Posts: 209

Re: Details on various slot2 accessories

Oh yeah! That game "Knock 'Em Down World's Fair" requires gba / slot 2 items called Bayer Didget! I hope someone emulate it soon! smile

Offline

#3 2024-08-12 01:38:38

windwakr
Member
Registered: 2010-06-10
Posts: 33

Re: Details on various slot2 accessories

Probably the most uselss add-on.

The Bey Point Reader(BPR) is an accessory used by some Japanese-only Beyblade games to read the data off of a device called a Beypointer. It can also send your name to the Beypointer. What is a Beypointer? I have no clue.

Minimal code for detection is returning 0x96 on byte-sized reads and 0xF500 on word-sized reads from 0x080000BE.

The BPR uses these addresses for communication, all word-sized.

0x0815FE00, 0x0815FE02..0x0815FE0E : Buffer for communication packets
0x0815FE10 : Status/Config?
0x0815FE12 : Size of packet in buffer, written from DS
0x0815FE14 : Size of packet in buffer, written from BPR
0x0815FE16 : ???
0x0815FEFE : Read from before every read/write, discarded. Clocks the Beypointer?

pic: https://files.catbox.moe/uxx5lv.png
save file for Metal Fight Beyblade (J): https://files.catbox.moe/f1qhju.zip
To access the BPR feature, バトル -> たいせんメニュー -> BPコラしん

Here is minimal code for working read/write, though there's no persistent storage after closing the emulator.
This test code was written in place of the guitar grip code out of laziness.

/*
	Copyright (C) 2009 CrazyMax
	Copyright (C) 2009-2013 DeSmuME team

	This file is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 2 of the License, or
	(at your option) any later version.

	This file is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with the this software.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "../slot2.h"
//#include "../armcpu.h"

#define ARR_SIZE 0x30 //IDK. Game never reads higher than around 0x2D
//0-2 = some points, 3-5 = some other points, 6-7 = wins, 8-9 = losses, 0xA-0xB = "game overs", 0xC = battle something(can't read it)
// 0x18-0x27 = 8 character name in Shift-JIS, only supports some characters
//little endian
static u8 arr[ARR_SIZE] = { 0xA8, 0x16, 0x03, 0xF0, 0x06, 0x00, 0x55, 0xA4, 0x5C, 0x11, 0x00, 0x08, 0x37, 0x0D, 0x0E, 0x0F,
						    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x82, 0x60, 0x82, 0x61, 0x82, 0x62, 0x82, 0x63,
						    0x82, 0x64, 0x82, 0x65, 0x00, 0x00, 0x00, 0x00, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,};

class Slot2_GuitarGrip : public ISlot2Interface
{
private: 
	int processCommand;
	u16 status; //idk
	u8 buf[8] = { 0 };
	u8 bufSize = 0;

	u8 reverseNibble(u8 val) { return (val & 0xF0) >> 4 | (val & 0x0F) << 4; }

	u16 processBpr(u32 addr)
	{
		u16 outWord = 0;
		u8 pos;
		u8 size;
		if (processCommand) {
			processCommand = 0;
			u8 cmd = buf[0];

			switch (cmd) {
			case 0x40: //?
				break;
			case 0x44: //Read
				pos = reverseNibble(buf[1]);
				size = reverseNibble(buf[2]);
				for (int i = 0; i < size; i++) { //Copy data into buf
					if ((pos+i < ARR_SIZE) && (i+1 < 8))
						buf[i + 1] = reverseNibble(arr[pos + i]);
				}
				buf[0] = 0x46;
				bufSize = size + 1;
				status = 0x02;
				printf("BPR READ, POS: %02X, SIZE: %02X\n", pos, size);
				break;
			case 0x45: //Write
				pos = reverseNibble(buf[1]);
				size = reverseNibble(buf[2]);
				for (int i = 0; i < size; i++) { //Copy data from buf
					if ((pos+i < ARR_SIZE) && (i+3 < 8))
						arr[pos+i] = reverseNibble(buf[i + 3]);
				}
				buf[0] = 0x46; //Only need to change the first byte of the buffer, the rest is fine
				bufSize = size + 3;
				status = 0x02;
				printf("BPR WRITE, POS: %02X, SIZE: %02X\n", pos, size);
				break;
			case 0x46: //Data
				buf[0] = 0x4C;
				bufSize = 1;
				status = 0x02;
				break;
			case 0x4C: //?
				status = 0x04;
				break;
			default:
				outWord = 0;
				break;
			}
		}

		if ((addr >= 0x0815FE00) && (addr <= 0x815FE0E)) {
			u32 tmp = (addr & 0xF) / 2;
			outWord = buf[tmp];
		} else if (addr == 0x0815FE10) {
			outWord = status;
		}else if (addr == 0x0815FE14) {
			outWord = bufSize;
		}
		return outWord;
	}
	
public:
	virtual Slot2Info const* info()
	{
		//static Slot2InfoSimple info("Guitar Grip", "Guitar Grip for Guitar Hero games", 0x04);
		static Slot2InfoSimple info("Bey Point Reader", "BPR", 0x04);
		return &info;
	}

	virtual void connect()
	{
		processCommand = 0;
		bufSize = 0;
		status = 0;
	}

	virtual void writeWord(u8 PROCNUM, u32 addr, u16 val)
	{
		//printf("writeWord: %08X = %04X\n", addr, val);

		if ((addr >= 0x0815FE00) && (addr <= 0x0815FE0E)) {
			u32 tmp = (addr & 0xF) / 2;
			buf[tmp] = val & 0xFF;
		}

		if ((addr == 0x0815FE12)) {
			bufSize = val & 0xFF;
			processCommand = 1;
		} else if (addr == 0x0815FE16) {
			status = 0x0; //?
		}
	}

	virtual u8	readByte(u8 PROCNUM, u32 addr) 
	{
		//if (addr != 0x080000B2)
		//	printf("readByte: %08X\n", addr);

		return 0x96; //Detection
	}
	
	virtual u16	readWord(u8 PROCNUM, u32 addr)
	{
		u16 outWord = 0x0000;

		if (addr == 0x080000BE) { //Detection
			outWord = 0xF500;
		}

		if ((addr >= 0x815FE00) && (addr < 0x815FEFE))
			outWord = processBpr(addr);

		//if ((addr > 0x080000BE) && (addr != 0x0815FEFE))
		//	printf("readWord: %08X = %04X\n", addr, outWord);// from %08X(ARM%c)\n", addr, outWord, ARMPROC.instruct_adr, PROCNUM ? '7' : '9');

		return outWord;
	}
	virtual u32	readLong(u8 PROCNUM, u32 addr) { if (addr != 0x080000AC) printf("readLong: %08X\n", addr);  return 0x0; }
};

ISlot2Interface* construct_Slot2_GuitarGrip() { return new Slot2_GuitarGrip(); }

void guitarGrip_setKey(bool green, bool red, bool yellow, bool blue)
{
	//const u8 g = (green)	? (1 << 6) : 0;
	//const u8 r = (red)		? (1 << 5) : 0;
	//const u8 y = (yellow)	? (1 << 4) : 0;
	//const u8 b = (blue)		? (1 << 3) : 0;
	//
	//guitarKeyStatus = ~(g | r | y | b);
}

void guitarGrip_setKey(u8 theKeys)
{
	//guitarKeyStatus = theKeys;
}

Offline

#4 2024-08-12 01:54:03

zeromus
Radical Ninja
Registered: 2009-01-05
Posts: 6,210

Re: Details on various slot2 accessories

Thanks for your continued hard work! I hope I have time to look into this one day...... in the meantime... it's a good tutorial task for a new contributor....

Offline

#5 2024-08-14 02:14:17

AsPoke3172
Member
Registered: 2010-04-21
Posts: 209

Re: Details on various slot2 accessories

Oh yeah! Someone make Powar, the PokeWalker emulator for Pokemon Heart Gold and Soul Silver.

https://www.reddit.com/r/EmuDev/comment … _emulator/

I hope Demume and MelonDS emulator can support this one very soon.

Offline

#6 2024-09-06 22:28:54

windwakr
Member
Registered: 2010-06-10
Posts: 33

Re: Details on various slot2 accessories

The Wave Scanner is an accessory that connects to the DS through the microphone connector used by one game(technically 3), Ryuusei no Rockman. It has minigames that can be played on it to level it up. That level can be transferred to the DS to power up your character. It can also scan "battle cards", which have barcodes on them, and send them to the DS. Its operation is simple and requires no emulation changes as long as the wav samples are encoded at the exact right bitrate(that's a discussion for another topic).
I've written a Python script that will generate wav samples for every card and a variety of Wave Scanner devices.
https://gist.github.com/windwakr/058a78 … a0b950771c
The wavs are directly usable in DeSmuME as-is. Enjoy.

Demonstration video. I power up with a level 50 Pegasus Wave Scanner then enter battle and scan an Air Spreader card.
https://webmshare.com/play/ZJB6w


-----

This one is just partially understood.

The Direction Sensing Card is the(official? unofficial?) name for a special oversized slot-1 game card used by the game Hoshizora Navi. The game communicates with the built-in AK8973 compass chip over game card SPI commands. I haven't seen the internals of one of these game cards so I'm not sure how it's wired up.

The games uses these SPI commands

0x10 - ??
0x11 - ??
0x2X - Write, the lower nibble indicates the amount of bytes
0x4X - ??
0x60 - Read byte
0x80 - ?? Game halts until it's 0 when reading
0x82 - ?? Game halts until it's 0 when reading
0x85 - ?? Game writes 0x98 here
0x88 - Seems to be used to set the reset pin on the compass chip?

Using just the 0x2X, 0x60, and 0x8X commands you can emulate enough of the chip to get the game to successfully read/write values.

The game also has an accelerometer chip. Again, as I haven't seen inside the game card I'm unsure of what the exact chip is. It writes to registers 0x20-0x22, checks the status of register 0x27, then reads registers 0x28-0x2D for the accelerometer outputs. Turns out there's dozens of chips with this exact configuration. I've been referring to the datasheet for LIS3DH, although it's highly unlikely that's the exact chip inside. The game reads from the accelerometer through spi 02 commands. It writes the (register number | 0xC0) then reads the result. On successive reads the next register is read. I haven't traced how register writes are performed. I'm also unsure how these commands are differentiated from BM_CMD_WRITELOW commands.

What's the point of emulating this functionality when the game already has a freelook mode using the dpad? It would be useful for Android emulation, I suppose.

For future reference this may be a good base for generating realistic-looking magnetometer output
https://github.com/NavPy/SensorSim/blob … sim_mag.py
It would still need to be shaped into whatever the AK8973 outputs(with its offset/gain stuff).
I'd imagine a stationary rotating accelerometer wouldn't be too difficult to simulate the output of.

Here's a video demonstration with very poorly coded inputs. The first half is spent "calibrating" the device, which just consists of rotating it around a bit until the compass icon turns green.
https://webmshare.com/play/oOvY6

Last edited by windwakr (2024-09-07 01:34:16)

Offline

#7 2024-09-07 03:35:47

zeromus
Radical Ninja
Registered: 2009-01-05
Posts: 6,210

Re: Details on various slot2 accessories

Offline

#8 2024-09-08 22:40:43

windwakr
Member
Registered: 2010-06-10
Posts: 33

Re: Details on various slot2 accessories

Here are other known unemulated accessories. I have no intention of researching these but it would be useful to have them listed in one place.

slot-1 game card with bluetooth capabilities

  • Learn with Pokémon: Typing Adventure

  • Kuruma de DS

Some people have done some reverse engineering of the functionality of the bluetooth chip including how to access the save data.
https://github.com/kynex7510/PTSM

The DS game Lunar Knights can read the solar sensor from any of the three GBA Boktai games. The solar sensor is well known and implemented in many GBA emulators. Should be trivial to implement.

Faceningscan slot-2 accessory. I don't know anything about this. It has a camera and maybe a microcontroller that does some processing? This is used by two games

  • Facening de Hyoujou Yutaka ni Inshou Up: Otona no DS Kao Training

  • Shiseido Beauty Solution Kaihatsu Center Kanshuu: Project Beauty

slot-1 game card with infrared capabilities

  • Personal Trainer: Walking

  • Active Health with Carol Vorderman

  • Pokemon HGSS

  • Pokemon BW and BW2

Offline

#9 2024-09-12 15:58:29

windwakr
Member
Registered: 2010-06-10
Posts: 33

Re: Details on various slot2 accessories

Just some minor info on the bluetooth slot-1 game cards.

Kuruma de DS uses different commands than Pokemon Typing to access its flash. Refer to the useful PTSM project linked previously for information on how Pokemon Typing reads its flash.

0xFCEC Write flash
0xFCED Read flash
0xFCEE Sector erase

Also, the game seems to expect to find the string "NTRUZCJ" at 0xF000 in its flash. It does not write this value during save initialization.

Kuruma de DS booting on an emulator for the first time:
https://files.catbox.moe/ee9lz1.webm
Not sure if the invisible button on the title screen is a DeSmuME bug or caused by something I did. None of the 3D settings affect it.

Of course, access to the flash memory is the easy part. Then comes the difficulty of simulating a bluetooth device connection, which I will not be attempting.

Last edited by windwakr (2024-09-12 16:03:51)

Offline

#10 2024-10-03 23:46:14

windwakr
Member
Registered: 2010-06-10
Posts: 33

Re: Details on various slot2 accessories

OK, I lied about not researching the bluetooth chip. tongue

Here is some info on Pokemon Typing. Responses from the bluetooth chip, responses from the keyboard, info on the HID input reports, etc.
https://gist.github.com/windwakr/812809 … 228f5b8696

Video of the game running with an emulated bluetooth keyboard:
https://files.catbox.moe/3ue3uy.webm
Unfortunately, I'm not very happy with my code and don't have time to rewrite it so I don't think I'll be releasing this build.
I think if someone were to work on bluetooth emulation then Dolphin's bluetooth emulation code would probably make a good base.

Offline

Board footer

Powered by FluxBB