Skip to content

Incorrect ANSI Cursor Positioning in libctru Console (args[0], args[1] Reversed) #582

Description

@AugensteinT

Bug Report

What's the issue you encountered?

When using ANSI escape sequences to position the cursor in wide console mode on the New 2DS XL (e.g. \x1b[5;20H), the row and col values appear to be interpreted in the wrong order. That is, text intended for row 5, column 20 appears at row 20, column 5 instead.

This breaks expected ANSI behavior, which uses the format ESC [ <row> ; <col> H.

After investigating the console.c implementation, it seems that the call to consolePosition() uses consolePosition(args[0], args[1]), which incorrectly assigns:

cursorX = row;
cursorY = col;

However, cursorX should be the column, and cursorY should be the row — this causes all cursor placement via ANSI codes to be reversed. Swapping the arguments to consolePosition(args[1], args[0]) fixes the issue and restores expected ANSI behavior.

This issue became visible after updating to libctru v2.6.1, which includes a fix for 1-based coordinates. It’s possible this update introduced the inversion accidentally by fixing the origin without verifying argument order.

No changes were made to devkitPro tooling manually; all packages were installed through the official pacman method.


How can the issue be reproduced?

  1. Start a basic libctru 3DS homebrew project (with wide mode enabled).
  2. Use printf("\x1b[5;20HHello world\n");
  3. Observe where the text is printed — it appears at row 20, column 5, not the expected row 5, column 20.
  4. Swap the arguments in the escape sequence (\x1b[20;5H) — now it renders correctly.

This indicates an argument reversal in the library code.


Environment?

  • Host OS: Windows 10
  • Shell used: msys2.exe
  • Toolchain: Official devkitARM (installed via pacman)
  • libctru version: v2.6.1
  • Console mode: gfxSetWide(true) enabled
  • Target device: New 2DS XL running homebrew

Additional context?

  • The function consolePosition(x, y) in console.c expects x = column and y = row.
  • ANSI escape sequences define cursor positions as ESC [ <row> ; <col> H.
  • Therefore, consolePosition(args[0], args[1]) is incorrect — it swaps the intended cursor placement.
  • Fix: change to consolePosition(args[1], args[0]).

This would restore ANSI compatibility and expected console behavior.

Let me know if you'd like a pull request or patch demonstrating the change.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions