Calculator Tools Calculator Tools

Otter Python - Calc Runner Game

Sep 4, 2026

About this app

A fun, calculator-themed Flappy Otter game inspired by Python programming on handheld calculators. Help the otter navigate through code pipes!

ULTRA-SYNC TI-84 CE | Program Forge 🔌 READY TO TRANSFER Waiting for Handshake... ULTRA-SYNC 84+CE 00:00:00 🛰️ COM PORT 3: ACTIVE PROGRAM LOGIC PROGM EDITOR Define variables & functions using standard syntax CONVERT TO TI-BASIC VIRTUAL DISPLAY 84-CE COLOR Calculator Runtime Simulation PROGRAM:MYPROG :Disp "READY" TI-CONNECT READY CODE (PASTE THIS) PROGRAM:MYPROG COPY SNIPPET EXPORT GUIDE Step 1: Open Software 💻 Open TI-Connect™ CE on your PC/Mac. Connect your calculator via Mini-USB. Step 2: Create Program 📄 Click the Program Editor icon. Select File > New Program. Step 3: Transfer ⚡ Paste the snippet from the middle column. Press Ctrl+S to save and Ctrl+G to Send to Calc! SAVE AS .8XP-TXT Note: Direct .8xp binary export requires desktop signing. Use the .txt import for best results. Memory Usage 128 B Complexity LOW Firmware Target v5.6.1 OS Compatible

Put this on your site

Source

                    <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">

<title>ULTRA-SYNC TI-84 CE | Program Forge</title>
<meta name="description" content="Generate TI-84 Plus CE compatible TI-BASIC code and export it directly for use with TI-Connect CE software.">
<meta name="keywords" content="TI-Connect CE, TI-84 Plus CE, TI-Basic Editor, Calculator App, Program Transfer">

<!-- Libraries -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.min.js" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css2?family=Share+Tech+Mono&family=Orbitron:wght@400;900&family=Bungee&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">

<style>
:root {
--ti-blue: #0047bb;
--ti-yellow: #ffcc00;
--neon-cyan: #00f2ff;
--calc-body: #2c2c2c;
--calc-screen: #9dae94;
--bg-deep: #050508;
}

body {
background: var(--bg-deep);
background-image:
linear-gradient(rgba(0, 242, 255, 0.03) 1px, transparent 1px),
linear-gradient(90deg, rgba(0, 242, 255, 0.03) 1px, transparent 1px);
background-size: 30px 30px;
color: #ffffff;
font-family: 'Share Tech Mono', monospace;
min-height: 100vh;
margin: 0;
}

.main-shell {
max-width: 1300px;
margin: 0 auto;
padding: 20px;
}

.header-bar {
background: rgba(0, 71, 187, 0.2);
border-bottom: 2px solid var(--ti-blue);
padding: 15px 30px;
display: flex;
justify-content: space-between;
align-items: center;
backdrop-filter: blur(10px);
margin-bottom: 30px;
border-radius: 0 0 20px 20px;
}

.brand {
font-family: 'Bungee', cursive;
font-size: 1.5rem;
color: var(--neon-cyan);
text-shadow: 0 0 10px var(--neon-cyan);
}

.status-tag {
background: #111;
padding: 5px 15px;
border-radius: 20px;
font-size: 0.8rem;
border: 1px solid var(--ti-blue);
color: var(--ti-yellow);
}

.grid-container {
display: grid;
grid-template-columns: 1fr 1fr 350px;
gap: 20px;
}

@media (max-width: 1200px) {
.grid-container { grid-template-columns: 1fr 1fr; }
.side-panel { grid-column: span 2; }
}

@media (max-width: 768px) {
.grid-container { grid-template-columns: 1fr; }
.side-panel { grid-column: span 1; }
}

.card-panel {
background: rgba(20, 20, 30, 0.8);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 15px;
padding: 20px;
box-shadow: 0 10px 30px rgba(0,0,0,0.5);
position: relative;
overflow: hidden;
}

.card-panel::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 4px;
background: var(--ti-blue);
}

.editor-area {
background: #000;
border-radius: 10px;
padding: 10px;
height: 400px;
border: 1px solid #333;
}

textarea {
width: 100%;
height: 100%;
background: transparent;
border: none;
color: #00ff41;
font-family: 'JetBrains Mono', monospace;
resize: none;
outline: none;
line-height: 1.5;
}

.ti-preview {
background: var(--calc-screen);
height: 300px;
border-radius: 5px;
padding: 10px;
color: #222;
font-weight: bold;
font-size: 1.2rem;
box-shadow: inset 0 0 15px rgba(0,0,0,0.3);
overflow-y: auto;
border: 5px solid #111;
}

.action-btn {
background: var(--ti-blue);
color: white;
border: none;
padding: 12px 20px;
border-radius: 8px;
font-weight: bold;
text-transform: uppercase;
letter-spacing: 1px;
transition: all 0.3s;
width: 100%;
margin-top: 15px;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
}

.action-btn:hover {
background: var(--neon-cyan);
color: #000;
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(0, 242, 255, 0.4);
}

.action-btn.secondary {
background: #333;
}

.instruction-card {
background: rgba(255, 255, 255, 0.05);
border-radius: 10px;
padding: 15px;
margin-top: 15px;
border-left: 4px solid var(--ti-yellow);
}

.mini-label {
font-size: 0.7rem;
text-transform: uppercase;
color: #888;
margin-bottom: 5px;
display: block;
}

.badge-ti {
background: #000;
color: var(--ti-yellow);
padding: 2px 8px;
border: 1px solid var(--ti-yellow);
border-radius: 4px;
font-size: 0.65rem;
vertical-align: middle;
}

/* Animations */
@keyframes blink {
0%, 100% { opacity: 1; }
50% { opacity: 0; }
}

.cursor-blink {
display: inline-block;
width: 10px;
height: 18px;
background: #000;
animation: blink 1s infinite;
vertical-align: middle;
}

#sync-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.95);
z-index: 9999;
display: none;
flex-direction: column;
align-items: center;
justify-content: center;
backdrop-filter: blur(10px);
}

.usb-cable {
font-size: 5rem;
margin-bottom: 20px;
color: var(--neon-cyan);
animation: flow 2s infinite linear;
}

@keyframes flow {
0% { transform: scale(1); filter: drop-shadow(0 0 5px var(--neon-cyan)); }
50% { transform: scale(1.1); filter: drop-shadow(0 0 20px var(--neon-cyan)); }
100% { transform: scale(1); filter: drop-shadow(0 0 5px var(--neon-cyan)); }
}

.progress-bar-ti {
width: 300px;
height: 20px;
background: #222;
border: 2px solid #444;
border-radius: 10px;
overflow: hidden;
margin: 20px 0;
}

.progress-fill {
width: 0%;
height: 100%;
background: repeating-linear-gradient(45deg, var(--ti-blue), var(--ti-blue) 10px, #0055ff 10px, #0055ff 20px);
transition: width 0.1s;
}

.ti-shortcut {
background: #222;
border: 1px solid #444;
padding: 2px 6px;
border-radius: 4px;
color: var(--ti-yellow);
font-family: 'Courier New', Courier, monospace;
}

</style>
</head>
<body>

<div id="sync-overlay">
<div class="usb-cable">🔌</div>
<h3 id="sync-msg">READY TO TRANSFER</h3>
<div class="progress-bar-ti">
<div class="progress-fill" id="sync-progress"></div>
</div>
<p class="text-muted" id="sync-subtext">Waiting for Handshake...</p>
</div>

<nav class="header-bar">
<div class="brand">ULTRA-SYNC <span style="font-weight: 300; opacity: 0.7;">84+CE</span></div>
<div class="d-flex align-items-center gap-3">
<div id="clock" class="status-tag">00:00:00</div>
<div class="status-tag" style="border-color: #28a745; color: #28a745;">🛰️ COM PORT 3: ACTIVE</div>
</div>
</nav>

<div class="main-shell">
<div class="grid-container">

<!-- Logic Editor -->
<div class="card-panel">
<div class="d-flex justify-content-between align-items-center mb-3">
<h5 class="m-0"><i class="fas fa-code me-2"></i>PROGRAM LOGIC</h5>
<span class="badge-ti">PROGM EDITOR</span>
</div>
<span class="mini-label">Define variables & functions using standard syntax</span>
<div class="editor-area">
<textarea id="ti-input" placeholder="Disp &quot;HELLO WORLD&quot;&#10;Prompt A,B&#10;C = sqrt(A^2 + B^2)&#10;Disp &quot;RESULT:&quot;,C"></textarea>
</div>
<button class="action-btn" onclick="syncData()">
<i class="fas fa-bolt"></i> CONVERT TO TI-BASIC
</button>
</div>

<!-- Live Preview -->
<div class="card-panel">
<div class="d-flex justify-content-between align-items-center mb-3">
<h5 class="m-0"><i class="fas fa-calculator me-2"></i>VIRTUAL DISPLAY</h5>
<span class="badge-ti">84-CE COLOR</span>
</div>
<span class="mini-label">Calculator Runtime Simulation</span>
<div class="ti-preview" id="sim-view">
<div>PROGRAM:MYPROG</div>
<div id="sim-content">:Disp "READY" <span class="cursor-blink"></span></div>
</div>

<div class="mt-3">
<span class="mini-label">TI-CONNECT READY CODE (PASTE THIS)</span>
<div id="raw-code" style="background: #111; color: #00f2ff; padding: 15px; border-radius: 8px; font-size: 0.9rem; border: 1px dashed #444; height: 100px; overflow-y: auto;">
PROGRAM:MYPROG
</div>
<button class="action-btn secondary mt-2" onclick="copyCode()">
<i class="fas fa-copy"></i> COPY SNIPPET
</button>
</div>
</div>

<!-- Export Instructions -->
<div class="card-panel side-panel">
<h5 class="mb-3"><i class="fas fa-share-square me-2"></i>EXPORT GUIDE</h5>

<div class="instruction-card">
<h6>Step 1: Open Software 💻</h6>
<p class="small text-muted">Open <strong>TI-Connect™ CE</strong> on your PC/Mac. Connect your calculator via Mini-USB.</p>
</div>

<div class="instruction-card">
<h6>Step 2: Create Program 📄</h6>
<p class="small text-muted">Click the <strong>Program Editor</strong> icon. Select <strong>File > New Program</strong>.</p>
</div>

<div class="instruction-card" style="border-color: var(--ti-blue);">
<h6>Step 3: Transfer ⚡</h6>
<p class="small text-muted">Paste the snippet from the middle column. Press <span class="ti-shortcut">Ctrl+S</span> to save and <span class="ti-shortcut">Ctrl+G</span> to Send to Calc!</p>
</div>

<div class="mt-4">
<button class="action-btn" style="background: #e91e63;" onclick="downloadTextFile()">
<i class="fas fa-download"></i> SAVE AS .8XP-TXT
</button>
<p class="text-center x-small mt-2" style="font-size: 0.7rem; color: #666;">
Note: Direct .8xp binary export requires desktop signing. Use the .txt import for best results.
</p>
</div>
</div>

</div>

<!-- Dashboard Stats -->
<div class="row mt-4">
<div class="col-md-3">
<div class="card-panel text-center p-3">
<div class="mini-label">Memory Usage</div>
<div class="h4 m-0" id="mem-val">128 B</div>
</div>
</div>
<div class="col-md-3">
<div class="card-panel text-center p-3">
<div class="mini-label">Complexity</div>
<div class="h4 m-0 text-success">LOW</div>
</div>
</div>
<div class="col-md-6">
<div class="card-panel p-3 d-flex align-items-center justify-content-between">
<div>
<div class="mini-label">Firmware Target</div>
<div class="h5 m-0">v5.6.1 OS Compatible</div>
</div>
<i class="fas fa-microchip fa-2x text-muted"></i>
</div>
</div>
</div>
</div>

<script>
// Persistence Logic
function saveLocal(key, value) {
localStorage.setItem('tisync_' + key, JSON.stringify(value));
}

function loadLocal(key) {
const val = localStorage.getItem('tisync_' + key);
return val ? JSON.parse(val) : null;
}

// TI-BASIC Translation Engine
const TRANSLATIONS = [
{ regex: /sqrt\(/gi, replace: "√(" },
{ regex: /\^2/gi, replace: "²" },
{ regex: /\*/gi, replace: "*" },
{ regex: /sin\(/gi, replace: "sin(" },
{ regex: /cos\(/gi, replace: "cos(" },
{ regex: /tan\(/gi, replace: "tan(" },
{ regex: /!=/gi, replace: "≠" },
{ regex: /<=/gi, replace: "≤" },
{ regex: />=/gi, replace: "≥" },
{ regex: /->/gi, replace: "→" },
{ regex: /input /gi, replace: "Input " },
{ regex: /disp /gi, replace: "Disp " },
{ regex: /prompt /gi, replace: "Prompt " }
];

function syncData() {
const input = $('#ti-input').val();
if(!input) return;

// Process Code
let lines = input.split('\n');
let outputLines = ["PROGRAM:ULTRA"];
let simHtml = "";

lines.forEach(line => {
if(line.trim() === "") return;

let processed = line;
TRANSLATIONS.forEach(t => {
processed = processed.replace(t.regex, t.replace);
});

// TI-BASIC lines always start with colon in file view
outputLines.push(":" + processed.toUpperCase());

// Sim view
simHtml += `<div>:${processed.toUpperCase()}</div>`;
});

const finalCode = outputLines.join('\n');
$('#raw-code').text(finalCode);
$('#sim-content').html(simHtml + ' <span class="cursor-blink"></span>');

// Update Mem
$('#mem-val').text(finalCode.length + " B");

saveLocal('lastProg', input);

// Simulation FX
$('#sim-view').css('background', '#fff');
setTimeout(() => $('#sim-view').css('background', 'var(--calc-screen)'), 100);
}

function copyCode() {
const text = $('#raw-code').text();
navigator.clipboard.writeText(text).then(() => {
const btn = $('.secondary');
const oldHtml = btn.html();
btn.html('<i class="fas fa-check"></i> COPIED!');
setTimeout(() => btn.html(oldHtml), 2000);
});
}

function downloadTextFile() {
const text = $('#raw-code').text();
const blob = new Blob([text], { type: 'text/plain' });
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = 'ULTRA_SYNC.txt';
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
}

function syncAnimation() {
const overlay = $('#sync-overlay');
const bar = $('#sync-progress');
const msg = $('#sync-msg');
const sub = $('#sync-subtext');

overlay.css('display', 'flex').hide().fadeIn();
bar.css('width', '0%');

let progress = 0;
const messages = ["Initializing USB...", "Syncing Handshake...", "Parsing Tokens...", "Sending RAM Page 0...", "Checksum Validated!", "Success!"];

const timer = setInterval(() => {
progress += 2;
bar.css('width', progress + '%');

const msgIdx = Math.floor((progress / 100) * (messages.length - 1));
msg.text(messages[msgIdx]);
sub.text(`TRANSMITTING BYTE ${Math.floor(progress * 1.28)} OF DATA...`);

if(progress >= 100) {
clearInterval(timer);
setTimeout(() => {
overlay.fadeOut();
}, 800);
}
}, 40);
}

// Realtime Clock
function updateClock() {
const now = new Date();
$('#clock').text(now.toLocaleTimeString());
}

$(document).ready(() => {
setInterval(updateClock, 1000);
updateClock();

// Initial Sync Simulation trigger
setTimeout(syncAnimation, 1000);

// Hotkey Ctrl+S
$(window).bind('keydown', function(event) {
if (event.ctrlKey || event.metaKey) {
if (String.fromCharCode(event.which).toLowerCase() === 's') {
event.preventDefault();
syncData();
}
}
});

// Load existing
const saved = loadLocal('lastProg');
if(saved) {
$('#ti-input').val(saved);
syncData();
}
});
</script>
</body>
</html>