Skip to content
This repository has been archived by the owner on Jan 21, 2022. It is now read-only.

MaryHal/TapTracker

Repository files navigation

TapTracker

About

This project aims to log various game data (and inputs) during a game of Tetris: The Grandmaster 2 Plus (TGM2p/TGM2+/TAP) when run in an emulator (MAME). TapTracker runs alongside the emulator and performs its logging in real-time. Windows support is experimental.

BlockTracker was my first attempt at this. It was done by interacting with scanmem as a child process, but ultimately, this meant every time I started up the game, I had to probe for the memory address holding level data (not unlike someone using cheat-engine) then pass the proper memory addresses to BlockTracker. Along the way I wrote quite possibly the worst code I’ve ever written, so despite it being such a small program, it wasn’t too pleasant for me to look at and maintain. (There was one upside though: this method was game-agnostic, so I could probe any TGM-style game for level data).

In contrast, TapTracker takes a more direct route by modifying a TGM-specific version of MAME to output relevant data.

Building TapTracker

First things first, get the source code from this repository:

git clone https://github.com/sanford1/TapTracker.git

After cloning, enter the created directory and retrieve all the submodules:

git submodule update --init --recursive

Building this project requires premake5, make, and glfw3:

premake5 gmake
make

Download

If you don’t want to go through the trouble of building this by yourself (and you trust me enough): Latest Release

Running TapTracker

TapTracker no longer runs shmupmametgm as a child process, but TapTracker must be run after shmupmametgm has started. For now, TapTracker only logs stats for player 1. You must also enable TapTracker in modded shmupmametgm with the -taptracker switch or the correct option in your mame.ini.

Command line arguments:

Usage: ./TapTracker [options] [arguments]

Options:
  --js       Set to 1 to enable joystick support. This setting has priority over the config file. (-1)
  --config   Set json config file path (config.json)
  --pb       Set "Personal Bests" file path (GoldST.txt)
  --version  Output version
  --help     Output help

On first run, TapTracker will create a (commented) json configuration file (config.json is the default file if you don’t specify a different path). You can use this file to create windows / layouts.

TapTracker also tracks your personal best times for sections and completed games. TapTracker will import/export a file named “GoldST.txt” by default.

Check bin/default_config.json (or run TapTracker without a config file) to generate a commented config file.

Screenshots

UI is still a work-in-progress.

screenshot05.png screenshot03.pngscreenshot04.png

The top portion graphs the time vs level during the last three sections. Below that is a table listing section times (newer, more speedrun-timer-like layout on the left). If joystick support is enabled, a second window is opened that displays joystick inputs per level (no keyboard support yet).

Videos

TapTracker Demo

Old Video of TapTracker (without input viewer)

Old Video of BlockTracker

To-do list

[Partially complete] Document TAP states
I’ve reverse engineered most of the TGM2+ states (read: I’ve figured out what they mean), but there may be edge cases that still confuse TapTracker.
[Partially complete] Implement resizable layouts
TapTracker only supports a single window size and layout right now, and it’s difficult to modify.
[Partially complete] Rework OpenGL code
It’s rigid and messy right now. Not to mention it also uses a ton of immediate mode. There’s an old git branch (gltest) that updates the 15-year-old rendering code to 14-year-old rendering code.
Player 2 support
Log stats for Player 2 too.
Diagram Generation
Create a Fumen diagram during play. A prototype (written in Python) can be found in the autofumen directory. This functionality is now built into shmupmametgm.
MAME patch for Windows
No longer necessary, fork of shmupmametgm supports Windows (but not TapTracker!).
More error logging
Since in addition to the original TapTracker code, we have to reproduce some of tgm2p’s game logic, there may be unforeseen edge cases. We probably should catch those.
Config files
For configurable layouts and to possibly replace the command line arguments. YAML? JSON? Roll my own plain text data file? Maybe something like this (plain text):
Window MainWindow
Size 240x540
Layout 14.0 2.0
Ratio Graph 0.72
Fixed Table 130.0
Fixed CurrentState 14.0

Window ExtraWindow
Size 180x120
Layout 4.0, 2.0
Ratio GameHistory 1.0

Window ButtonWindow
Size 180x112
Layout 4.0 0.0
Ratio InputHistory 1.0
    

Or this (yaml):

joystick:
    enabled: yes
    axis-hori: 6
    axis-vert: 7
    button-a:  1
    button-b:  2
    button-c:  3

windows:
    - name:   MainWindow
      width:  240
      height: 540
      layout:
          - type:  graph
            ratio: 0.72
          - type:  table
            fixed: 130
          - type: state
            fixed 14
    - name:   Extra
      width:  180
      height: 120
      layout:
          - type:  history
            ratio: 1

    - name:   ButtonWindow
      width:  180
      height: 112
      layout:
          - type:  buttons
            ratio: 1
    
Adaptive draw functions
Some draw routines are very static and don’t change with size.

Appendix

TAP (tgm2p)

Useful RAM Addresses

All these addresses are for player 1. I still need to double check some of these.

AddressTypeDescriptionNotes
0x06064B99int8_tARE/Line Clear Delay Time Remaining
0x06064BA8uint32_tRandom Number Generator State
0x06064BC8int32_tScore
0x06064BE1uint8_tDAS CounterCan overflow(!)
0x06064BE4int32_tTotal Time
0x06064BE8int32_tGame Time
0x06064BF5int8_tBlock State
0x06064BF6int16_tCurrent Block
0x06064BF8int16_tNext Block
0x06064BFCint16_tCurrent Block X Position
0x06064C00int16_tCurrent Block Y Position
0x06064C02int8_tGravity Left
0x06064C04int8_t[4]Block History
0x06064C2Aint16_tRO Badge Score
0x06064C2Cint16_tNumber of Blocks Rotated
0x06064C2Eint16_tCurrent Block Rotation Count
0x06064C34int16_tCurrent Block Alive Time
  • Extra:
AddressTypeDescriptionNotes
0x06064BFAint8_tCurrent Block Rotation State
0x06064BBAint16_tPlayer 1 Level
0x06064BEAint16_tPlayer 1 Timer
0x06079378int8_tInternal Grade
0x06079379int8_tInternal Grade Points
0x06064BD0int8_tM-Roll Progress State
0x06066845int8_tM-Roll Flag
0x06064C25int8_tSection Index
0x06064BA4int16_tCurrent Game ModeSee below for corresponding values

Block Indices

IndexBlock
2I
3Z
4S
5J
6L
7O
8T

TGM2P States

M-Roll Flags
ValueDefinition
17Failure state in the first half of the game (100-499).
19Failure state in the second half of the game (500-999).
31Failure state at the end of the game, currently in fading credit roll.
34Garbage value when the game is still loading.
48Neutral state. Value during the first section (0-100) and non-play game states.
49Passing state during the first half of the game (100-499).
51Passing state during the second half of the game (500-999).
127Passing state at the end of the game, currently in the invisible credit roll.
Internal State
ValueDefinition
0
1
2Tetromino can be controlled by the player.
3Tetromino cannot be influenced anymore.
4Tetromino is being locked to the playfield.
5Block entry delay (ARE).
7“Game Over” is being shown on screen.
10No game has started, idle state.
11Blocks are fading away when topping out (losing).
13Blocks are fading away when completing a game.
71Garbage value when the game is still loading.
Game Mode
Base Modes
ModeValue
No Game Mode0
Normal1
Master2
Doubles4
Tgm+128
Death4096
Mode Masks
MaskValueBit-shift
Versus8(1 << 3)
Credits16(1 << 4)
20G32(1 << 5)
Big64(1 << 6)
Item512(1 << 9)
TLS1024(1 << 10)

TGM1 (tgmj)

Useful RAM Addresses

AddressTypeDescriptionNotes
0x0017695DPlayer 1 State
0x0017699APlayer 1 Level
0x0017698CPlayer 1 Timer
0x0017699CPlayer 1 Grade
0x00000000Player 1 Grade Points
0x00000000Player 1 GM Flags
0x00000000Player 1 In-Credit-Roll
0x0017699EPlayer 1 Section Num
0x001769D4Player 1 Tetromino
0x001769D2Player 1 Next Tetromino
0x001769DAPlayer 1 Current X
0x001769DEPlayer 1 Current Y
0x001769D7Player 1 Rotation State

TGM1 States

TGM1 State
enum tgmj_internal_state
{
    TGMJ_IDLE         = 0,  // No game has started, just waiting...
    TGMJ_ACTIVE       = 20,
    TGMJ_LOCKING      = 30, // Cannot be influenced anymore
    TGMJ_LINECLEAR    = 40,
    TGMJ_LINECLEAR2   = 50,
    TGMJ_LOCKED       = 60,

    TGMJ_ENTRY        = 10,
    TGMJ_ENTRY2       = 100,

    TGMJ_UNKNOWN      = 110, // Probably a death state
    TGMJ_FADING1      = 111, // Blocks greying out at when topping out
    TGMJ_FADING2      = 112, // Blocks greying out at when topping out
    TGMJ_NAME_ENTRY   = 114,
    TGMJ_DEAD         = 115,
    TGMJ_GAMEOVER     = 116,  // "Game Over" is being shown on screen.

    TGMJ_READY0       = 90, // READY!
    TGMJ_READY1       = 91, // READY!
    TGMJ_READY2       = 92, // READY!
    TGMJ_READY3       = 93, // READY!
    TGMJ_READY4       = 94, // READY!
    TGMJ_READY5       = 95, // GO!
    TGMJ_READY6       = 96, // GO!
};
TGM1 Mode Masks
#define MODE_20G_MASK  (1 << 0)
#define MODE_BIG_MASK  (1 << 2)
#define MODE_UKI_MASK  (1 << 3)
#define MODE_REV_MASK  (1 << 4)
#define MODE_MONO_MASK (1 << 5)
#define MODE_TLS_MASK  (1 << 7)