Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
c3dcb09
Experimental sixel support, LLM-assisted, under review
jquast May 23, 2026
7886e6e
Merge remote-tracking branch 'upstream/main' into jq/sixel-experiments
jquast Jun 29, 2026
e06653e
still WIP, sixel vs. kitty, detection etc. progress
jquast Jul 3, 2026
4055acb
bump blessed for sixel detection fix
jquast Jul 4, 2026
a146199
finally some bugfixes
jquast Jul 5, 2026
52f75df
checkpoint: kitty and sixel working well!
jquast Jul 6, 2026
b859c98
blitting for kitty, harder than it looks but great benefits
jquast Jul 6, 2026
3c80eaf
set scale max for sixel, document, rewrite keystroke code a bit
jquast Jul 6, 2026
0c4e840
very improved sixel blitting using transparency, kitty next!
jquast Jul 6, 2026
ca95571
this is worse, maybe revert?
jquast Jul 6, 2026
3a94331
a bit of "autoscaling" dependong on FPS dropping too low
jquast Jul 7, 2026
a86ac97
progress, special exceptions
jquast Jul 7, 2026
47f6eeb
ruff
jquast Jul 7, 2026
1c00b32
cleanup GAMBATERM_PROFILE_DIR
jquast Jul 7, 2026
1401130
move two variables to 1 place
jquast Jul 7, 2026
0143157
not using libsixel anymore
jquast Jul 7, 2026
ed819be
remove libsixel submodule
jquast Jul 7, 2026
a89a180
document iTerm2 is meh
jquast Jul 7, 2026
2f8b741
small refactor but also possible some breaking, to test..
jquast Jul 7, 2026
b305d8f
refactor code, _privates -> publics
jquast Jul 7, 2026
b7bef49
ruff
jquast Jul 7, 2026
465ecd2
mypy fixes
jquast Jul 7, 2026
0035a88
reorg vars
jquast Jul 7, 2026
dfc5e71
more blitter_vis and extract out GraphicsRenderer and StatusBar
jquast Jul 8, 2026
50cfacd
more refactoring, better blit visualization
jquast Jul 8, 2026
e8f763e
upgrade to blessed 1.47, syncterm sixel fix
jquast Jul 9, 2026
659e7df
remove graphics cycling and other nits
jquast Jul 9, 2026
583d7fa
more refactoring
jquast Jul 9, 2026
5d52d82
small nit before refactor of blit
jquast Jul 9, 2026
daee3ba
additional refactoring
jquast Jul 9, 2026
c333145
smaller refactor, add "flash" on key frames for F12 debug
jquast Jul 9, 2026
09a66a3
performance improvements
jquast Jul 9, 2026
cd5fea9
bugfix status bar is idle when player is
jquast Jul 9, 2026
e6c3e9f
checkpint: almost done -- check xterm sixel blit next? not working?
jquast Jul 10, 2026
a636dc8
remove "autoscaler", implement "--limit-bandwidth"
jquast Jul 14, 2026
15b8c56
rm graphics_autoscaler.py, undo audio env val
jquast Jul 14, 2026
2f0b65b
small doc cleanup
jquast Jul 14, 2026
0cbe8e3
checkpoint: cleanup/refactor and remove bandwidth limit
jquast Jul 14, 2026
30cd6e4
test for banding WIP not verified
jquast Jul 15, 2026
81e4036
banding, WIP, some bugs
jquast Jul 15, 2026
2385e1e
--frame-banding temporarily a CLI argument
jquast Jul 15, 2026
0bfa491
audio buffer level estimation
jquast Jul 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 109 additions & 45 deletions README.md

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions gambaterm/audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ def adapt_sample_rate(self) -> None:
# Return the adjusted sample rate
self.sampling_ratio = self.nominal_sampling_ratio * correction

@property
def fill_fraction(self) -> float:
"""Instantaneous ring buffer fill ratio (0.0–1.0)."""
if self.ring_size == 0:
return 0.0
return max(0.0, (self.write_counter - self.read_counter) / self.ring_size)

def send(self, console: Console, audio: npt.NDArray[np.int16]) -> None:
# Resample input audio to output rate with speed adjustment
resampled = self.resampler.process(
Expand Down Expand Up @@ -250,6 +257,12 @@ def send(self, console: Console, audio: npt.NDArray[np.int16]) -> None:
if self.audio_out is not None:
self.audio_out.send(console, audio)

@property
def fill_fraction(self) -> float:
if self.audio_out is not None:
return self.audio_out.fill_fraction
return 0.0


@contextmanager
def audio_player(
Expand Down
2 changes: 1 addition & 1 deletion gambaterm/blessed_keyboard_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def blessed_key_pressed_context(

def _update() -> None:
while True:
key = term.inkey(timeout=0)
key = term.inkey(timeout=0, capture_cpr=True)
if not key:
break
if not key.released:
Expand Down
7 changes: 7 additions & 0 deletions gambaterm/colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ def cycle(self) -> ColorMode:
value += 1
return ColorMode(value)

def cycle_back(self) -> ColorMode:
"""Cycle to the previous color mode."""
value = int(self) - 1
if value <= int(ColorMode.COULD_NOT_DETECT):
value = int(ColorMode.HAS_24_BIT_COLOR)
return ColorMode(value)

def report(self) -> str:
"""Return a human-readable report of the color mode."""
if self == ColorMode.COULD_NOT_DETECT:
Expand Down
1 change: 1 addition & 0 deletions gambaterm/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ def __init__(

self.gb = GB()
self.force_gameboy = force_gameboy
self.last_video = np.zeros((self.HEIGHT, self.WIDTH), dtype=np.uint32)

# Set save_directory
if save_directory is not None:
Expand Down
6 changes: 2 additions & 4 deletions gambaterm/controller_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,11 @@ def pygame_button_pressed_context(
try:
import pygame
except ImportError:
raise SystemExit(
"""\
raise SystemExit("""\
The pygame library is not available, which is required to get controller support.
Please use the following command to install gambaterm with controller support:
pip3 install gambaterm[controller-support]
"""
)
""")

pygame.init()
pygame.joystick.init()
Expand Down
Loading
Loading