diff --git a/PlasmaNew/FIRMWARE.md b/PlasmaNew/FIRMWARE.md new file mode 100644 index 0000000..2b67fc5 --- /dev/null +++ b/PlasmaNew/FIRMWARE.md @@ -0,0 +1,148 @@ +# PD01D221 firmware analysis (`tms27pc512.BIN`) + +Reverse-engineering notes for the dumped controller firmware — the 64 KB +TI TMS27PC512 EPROM (U3) from the Babcock PD01D221. This is the authoritative +source for the display's command set, and it feeds both [vPLASMA](../src/VPlasma.App/) +and the planned [hardware replica](README.md). + +Dump: `tms27pc512.BIN`, 65,536 bytes, MD5 `b775427806857f60ca4a4cc501f4b5cc`. +Analysis tooling: [`hc11dis.py`](hc11dis.py) (a purpose-built 68HC11 +disassembler — the toolchain has no m68hc11 target). + +## Memory map + +- **CPU $8000–$FFFF = EPROM upper 32 KB, 1:1** (the HC11 vector table lands at + ROM offset `$FFC0–$FFFF` and is valid, which pins the mapping). The EPROM's + **lower 32 KB is unused** (all `$00`) — only A15-high is decoded to the ROM. +- **Code:** `$9000–$B8xx`. **Data/tables:** `$8000–$8FFF` (demo), `$98AC+` + (dispatch tables), `$BC03+` (font descriptors), `$C000–$DFFF` (glyph + bitmaps + graphics). +- **RAM (Mosel MS62256, 32 KB) at low addresses:** HC11 registers on page 0 + (`$00–$3F`; SCSR=`$2E`, SCDR=`$2F`), zero-page variables `$40–$FF`, RX ring + buffer at `$0228`, and **ten 128×32 screen buffers** from `$0F6D` up. + +## Vectors + +| Vector | Target | Notes | +|--------|--------|-------| +| RESET | `$9059` | Init: registers, stack `$0227`, then main loop | +| **SCI (serial rx)** | **`$B85C`** | Interrupt-driven receive → ring buffer | +| COP watchdog | `$905E` | (re-inits) | +| others | `$9059` | default → reset | + +## Architecture + +1. **SCI RX ISR (`$B85C`)** — on RDRF, reads `SCSR`/`SCDR`, stores the byte to + a ring buffer at `$0228` (write ptr `$0228`, count `$022C`). No parsing here. +2. **Main-loop parser (`$B7E0–$B859`)** — pulls buffered bytes and runs an + `ESC`-state machine (flag `$AF`: bit `$10` = ESC seen, bit `$20` = operand + pending). Dispatch is **table-driven** (below). Printable chars in the + current font's `[first,last]` range (`$62`/`$63`) go to the character + renderer (`$9648`), which **enqueues** a glyph to a deferred rasterizer. +3. **Ten double-buffered screens** — descriptor table at **`$A4E0`** (10 × 6 + bytes): each screen has a **draw** pointer (`$BE`) and a **display** pointer + (`$BC`) into SRAM, 1 KB apart. `ESC I` sets the draw target, `ESC i` sets + what's scanned to the glass → **page-flipping / double-buffering**. + +## Command dispatch + +Two jump tables, indexed by byte: + +- **`ESC` + letter → command table at `$98AC`.** Valid letters `0x30`–`0x7E`; + index = `letter − 0x30`; null entry = ignored. **58 commands populated.** +- **Control bytes `0x08`–`0x14` → table at `$994C`.** index = `byte − 0x08`. + +Most command handlers share a prologue: first sighting of the letter sets the +"operand pending" flag and returns; the **next byte is the 1-byte operand** +(in `$C6`). Multi-operand commands (`ESC P/X/Y`) collect into a parameter +block at `$0070`. + +### Control characters (`$994C`) + +| Byte | Handler | Meaning | +|------|---------|---------| +| `0x08` BS | `$99AF` | cursor left | +| `0x09` HT | `$9966` | tab | +| `0x0A` LF | `$99F3` | line feed | +| `0x0B` VT | `$9A30` | vertical tab | +| `0x0D` CR | `$9A55` | carriage return | +| `0x11`–`0x14` DC1–DC4 | `$9A5C`/`$9B34`/`$9C09`/`$9CFC` | device controls (TBD) | +| `0x0C` FF, `0x0E`–`0x10` | — | no handler | + +### ESC commands (`$98AC`) — confirmed semantics + +| Cmd | Handler | Meaning | +|-----|---------|---------| +| `ESC @` | `$9F26` | **Clear** the active draw buffer (512 bytes = 128×32÷8) | +| `ESC G n` | `$A42B` | **Cursor mode**, low nibble of `$B4` (n = 0–7) | +| `ESC H n` | `$A44C` | **Text attributes**, low 4 bits of `$B1` (intensity/underline/reverse/flash) | +| `ESC K n` | `$A3EA` | **Font select** (n = 0–9; 8 real fonts) | +| `ESC L` | `$A556` | **Home** cursor (X=0, Y=0) | +| `ESC Q n` | `$A51C` | **Set cursor row Y** (range-checked 0–31) | +| `ESC R n` | `$A539` | **Set cursor column X** (range-checked 0–127) | +| `ESC I n` | `$A473` | **Select DRAW page** 0–9 (sets `$BE` from `$A4E0` table) | +| `ESC i n` | `$A4A2` | **Select DISPLAY page** 0–9 (page-flip; sets `$BC`) | +| `ESC P …` | `$AAF1` | **Graphics bitmap write** (multi-operand: screen,y,x,w,h,data) | +| `ESC A`–`ESC F` | `$9FB6`–`$A13C` | **Vector/graphics primitives** (line/point/move; pen state `$B6`, coords `$58/$59`, line routine `$A16C`) | +| `ESC X n` | `$A748` | **Set graphics pen X** (multi-op, 0–127) | +| `ESC Y n` | `$A644` | **Set graphics pen Y** (multi-op) | +| `ESC J` | `$A4D4` | **Toggle** mode bit `$B7.7` (orientation/display — TBD) | + +### ESC commands — populated but not yet decoded + +`ESC 0`–`9` (`$9E27`+, set continuations — likely custom-char / numeric entry), +`ESC : ; =` , `ESC < > W w _` (cluster `$AEBA–$AF00`), `ESC B C D E F` variants, +`ESC M N O` (`$A5BD/$A5C5/$A5E0`), `ESC Z ^ z ~` (cluster `$AC73–$ACA1`), +`ESC a`–`f`, `ESC h l n p q r x`. ~30 handlers remain to label — full list with +addresses is dumped by the tooling below. + +## Fonts + +Font-pointer table at **`$BC03`** (10 slots) → 12-byte descriptors. **8 real +fonts** (slots 8–9 are junk pointers, matching the demo's "8 STORED CHARACTER +FONTS"): + +| Font | First–Last | W×H | Notes | +|------|-----------|-----|-------| +| 0 | `0x20`–`0xFF` | 6×8 | base font, full range | +| 1 | `0x40`–`0x7F` | 6×8 | uppercase-only | +| 2 | `0x20`–`0xFF` | 6×10 | | +| 3 | `0x40`–`0x7F` | 6×10 | | +| 4 | `0x20`–`0x7F` | 12×16 | large | +| 5 | `0x20`–`0x7F` | 12×20 | largest | +| 6 | `0x20`–`0xFF` | 7×10 | | +| 7 | `0x40`–`0x7F` | 7×10 | | + +Glyph bitmaps live in ROM (`~$C000–$DFFF`). **Exact glyph base + encoding +pending** — the renderer at `$9648` enqueues to a deferred rasterizer; tracing +that (or brute-forcing the 'A' pattern at the known stride) will extract the +real glyphs to replace vPLASMA's public-domain 5×7 stand-in. + +## Demo program + +Enabled by **jumper 6** (PD3) — confirms the [JP1 map](README.md). A 10-screen +scripted demo; the script at `$8028+` is literal command usage (pointer table +at `$8000`). It's how the new `ESC R/I/Q/i/K` commands were first spotted, e.g. +`1B 47 00` (ESC G 0) `1B 40` (ESC @) `1B 4C` (ESC L) `1B 52 04` (ESC R 4) … + +## What this means + +**For vPLASMA:** the recovered commands can replace guessed behavior. Notably +`ESC Q`/`ESC R` are the real cursor-positioning commands (row/col), and the +`ESC P` "screen" byte selects one of 10 double-buffered pages — vPLASMA +currently models a single buffer. + +**For the replica:** this *is* the spec. The firmware confirms a clean model — +a byte-stream command parser, a 512-byte-per-page frame buffer, 10 pages with +page-flip, 8 fonts, text attributes as 4 flags, plus vector graphics. All of +it ports directly onto a modern MCU. The one artifact still to extract is the +glyph bitmaps. + +## Reproduce + +```sh +python hc11dis.py # disassemble from a CPU address +# e.g. python hc11dis.py B7E0 70 # the command parser +``` +Command/control tables are at `$98AC` / `$994C`; font table `$BC03`; screen +table `$A4E0`. diff --git a/PlasmaNew/README.md b/PlasmaNew/README.md index 6693c3e..9b17d47 100644 --- a/PlasmaNew/README.md +++ b/PlasmaNew/README.md @@ -200,7 +200,10 @@ CDC port satisfies perfectly. Confirm the current drive path. ## Status -**Parked pending a firmware dump.** The software emulator (vPLASMA) is built -and released; this hardware/protocol thread is blocked on getting the U3 -EPROM image (or the Babcock programming manual). Resume at the dump plan -above once a dump is in hand. +**Firmware dump received — analysis underway.** The U3 EPROM was dumped +(`tms27pc512.BIN`); see [`FIRMWARE.md`](FIRMWARE.md) for the disassembly +findings: memory map, the full command dispatch tables (58 `ESC` commands + +control chars), the 10-page double-buffered architecture, 8 fonts, and +decoded command semantics. Remaining: extract the glyph bitmaps and label the +~30 not-yet-decoded commands. The Babcock programming manual is no longer on +the critical path — the firmware is the authoritative spec. diff --git a/PlasmaNew/hc11dis.py b/PlasmaNew/hc11dis.py new file mode 100644 index 0000000..42bce24 --- /dev/null +++ b/PlasmaNew/hc11dis.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python3 +"""Minimal-but-practical Motorola 68HC11 disassembler for the PD01D221 ROM. +CPU address == ROM offset for $8000-$FFFF (EPROM upper 32KB maps 1:1).""" +import sys + +# addressing modes and their extra operand length (beyond opcode) +INH='inh'; IMM8='imm8'; IMM16='imm16'; DIR='dir'; EXT='ext'; IDX='idx'; IDY='idy'; REL='rel' +BITDIR='bitdir'; BITIDX='bitidx'; BITIDY='bitidy' # BSET/BCLR (mask) +BRDIR='brdir'; BRIDX='bridx'; BRIDY='bridy' # BRSET/BRCLR (mask+rel) + +# page 0 +P0 = { +0x00:('TEST',INH),0x01:('NOP',INH),0x02:('IDIV',INH),0x03:('FDIV',INH), +0x04:('LSRD',INH),0x05:('ASLD',INH),0x06:('TAP',INH),0x07:('TPA',INH), +0x08:('INX',INH),0x09:('DEX',INH),0x0A:('CLV',INH),0x0B:('SEV',INH), +0x0C:('CLC',INH),0x0D:('SEC',INH),0x0E:('CLI',INH),0x0F:('SEI',INH), +0x10:('SBA',INH),0x11:('CBA',INH),0x12:('BRSET',BRDIR),0x13:('BRCLR',BRDIR), +0x14:('BSET',BITDIR),0x15:('BCLR',BITDIR),0x16:('TAB',INH),0x17:('TBA',INH), +0x19:('DAA',INH),0x1B:('ABA',INH), +0x1C:('BSET',BITIDX),0x1D:('BCLR',BITIDX),0x1E:('BRSET',BRIDX),0x1F:('BRCLR',BRIDX), +0x20:('BRA',REL),0x21:('BRN',REL),0x22:('BHI',REL),0x23:('BLS',REL), +0x24:('BCC',REL),0x25:('BCS',REL),0x26:('BNE',REL),0x27:('BEQ',REL), +0x28:('BVC',REL),0x29:('BVS',REL),0x2A:('BPL',REL),0x2B:('BMI',REL), +0x2C:('BGE',REL),0x2D:('BLT',REL),0x2E:('BGT',REL),0x2F:('BLE',REL), +0x30:('TSX',INH),0x31:('INS',INH),0x32:('PULA',INH),0x33:('PULB',INH), +0x34:('DES',INH),0x35:('TXS',INH),0x36:('PSHA',INH),0x37:('PSHB',INH), +0x38:('PULX',INH),0x39:('RTS',INH),0x3A:('ABX',INH),0x3B:('RTI',INH), +0x3C:('PSHX',INH),0x3D:('MUL',INH),0x3E:('WAI',INH),0x3F:('SWI',INH), +0x40:('NEGA',INH),0x43:('COMA',INH),0x44:('LSRA',INH),0x46:('RORA',INH), +0x47:('ASRA',INH),0x48:('ASLA',INH),0x49:('ROLA',INH),0x4A:('DECA',INH), +0x4C:('INCA',INH),0x4D:('TSTA',INH),0x4F:('CLRA',INH), +0x50:('NEGB',INH),0x53:('COMB',INH),0x54:('LSRB',INH),0x56:('RORB',INH), +0x57:('ASRB',INH),0x58:('ASLB',INH),0x59:('ROLB',INH),0x5A:('DECB',INH), +0x5C:('INCB',INH),0x5D:('TSTB',INH),0x5F:('CLRB',INH), +0x60:('NEG',IDX),0x63:('COM',IDX),0x64:('LSR',IDX),0x66:('ROR',IDX), +0x67:('ASR',IDX),0x68:('ASL',IDX),0x69:('ROL',IDX),0x6A:('DEC',IDX), +0x6C:('INC',IDX),0x6D:('TST',IDX),0x6E:('JMP',IDX),0x6F:('CLR',IDX), +0x70:('NEG',EXT),0x73:('COM',EXT),0x74:('LSR',EXT),0x76:('ROR',EXT), +0x77:('ASR',EXT),0x78:('ASL',EXT),0x79:('ROL',EXT),0x7A:('DEC',EXT), +0x7C:('INC',EXT),0x7D:('TST',EXT),0x7E:('JMP',EXT),0x7F:('CLR',EXT), +0x80:('SUBA',IMM8),0x81:('CMPA',IMM8),0x82:('SBCA',IMM8),0x83:('SUBD',IMM16), +0x84:('ANDA',IMM8),0x85:('BITA',IMM8),0x86:('LDAA',IMM8),0x88:('EORA',IMM8), +0x89:('ADCA',IMM8),0x8A:('ORAA',IMM8),0x8B:('ADDA',IMM8),0x8C:('CPX',IMM16), +0x8D:('BSR',REL),0x8E:('LDS',IMM16),0x8F:('XGDX',INH), +0x90:('SUBA',DIR),0x91:('CMPA',DIR),0x92:('SBCA',DIR),0x93:('SUBD',DIR), +0x94:('ANDA',DIR),0x95:('BITA',DIR),0x96:('LDAA',DIR),0x97:('STAA',DIR), +0x98:('EORA',DIR),0x99:('ADCA',DIR),0x9A:('ORAA',DIR),0x9B:('ADDA',DIR), +0x9C:('CPX',DIR),0x9D:('JSR',DIR),0x9E:('LDS',DIR),0x9F:('STS',DIR), +0xA0:('SUBA',IDX),0xA1:('CMPA',IDX),0xA2:('SBCA',IDX),0xA3:('SUBD',IDX), +0xA4:('ANDA',IDX),0xA5:('BITA',IDX),0xA6:('LDAA',IDX),0xA7:('STAA',IDX), +0xA8:('EORA',IDX),0xA9:('ADCA',IDX),0xAA:('ORAA',IDX),0xAB:('ADDA',IDX), +0xAC:('CPX',IDX),0xAD:('JSR',IDX),0xAE:('LDS',IDX),0xAF:('STS',IDX), +0xB0:('SUBA',EXT),0xB1:('CMPA',EXT),0xB2:('SBCA',EXT),0xB3:('SUBD',EXT), +0xB4:('ANDA',EXT),0xB5:('BITA',EXT),0xB6:('LDAA',EXT),0xB7:('STAA',EXT), +0xB8:('EORA',EXT),0xB9:('ADCA',EXT),0xBA:('ORAA',EXT),0xBB:('ADDA',EXT), +0xBC:('CPX',EXT),0xBD:('JSR',EXT),0xBE:('LDS',EXT),0xBF:('STS',EXT), +0xC0:('SUBB',IMM8),0xC1:('CMPB',IMM8),0xC2:('SBCB',IMM8),0xC3:('ADDD',IMM16), +0xC4:('ANDB',IMM8),0xC5:('BITB',IMM8),0xC6:('LDAB',IMM8),0xC8:('EORB',IMM8), +0xC9:('ADCB',IMM8),0xCA:('ORAB',IMM8),0xCB:('ADDB',IMM8),0xCC:('LDD',IMM16), +0xCE:('LDX',IMM16),0xCF:('STOP',INH), +0xD0:('SUBB',DIR),0xD1:('CMPB',DIR),0xD2:('SBCB',DIR),0xD3:('ADDD',DIR), +0xD4:('ANDB',DIR),0xD5:('BITB',DIR),0xD6:('LDAB',DIR),0xD7:('STAB',DIR), +0xD8:('EORB',DIR),0xD9:('ADCB',DIR),0xDA:('ORAB',DIR),0xDB:('ADDB',DIR), +0xDC:('LDD',DIR),0xDD:('STD',DIR),0xDE:('LDX',DIR),0xDF:('STX',DIR), +0xE0:('SUBB',IDX),0xE1:('CMPB',IDX),0xE2:('SBCB',IDX),0xE3:('ADDD',IDX), +0xE4:('ANDB',IDX),0xE5:('BITB',IDX),0xE6:('LDAB',IDX),0xE7:('STAB',IDX), +0xE8:('EORB',IDX),0xE9:('ADCB',IDX),0xEA:('ORAB',IDX),0xEB:('ADDB',IDX), +0xEC:('LDD',IDX),0xED:('STD',IDX),0xEE:('LDX',IDX),0xEF:('STX',IDX), +0xF0:('SUBB',EXT),0xF1:('CMPB',EXT),0xF2:('SBCB',EXT),0xF3:('ADDD',EXT), +0xF4:('ANDB',EXT),0xF5:('BITB',EXT),0xF6:('LDAB',EXT),0xF7:('STAB',EXT), +0xF8:('EORB',EXT),0xF9:('ADCB',EXT),0xFA:('ORAB',EXT),0xFB:('ADDB',EXT), +0xFC:('LDD',EXT),0xFD:('STD',EXT),0xFE:('LDX',EXT),0xFF:('STX',EXT), +} +# page 1 ($18): Y versions +P1 = { +0x08:('INY',INH),0x09:('DEY',INH),0x1C:('BSET',BITIDY),0x1D:('BCLR',BITIDY), +0x1E:('BRSET',BRIDY),0x1F:('BRCLR',BRIDY),0x30:('TSY',INH),0x35:('TYS',INH), +0x38:('PULY',INH),0x3A:('ABY',INH),0x3C:('PSHY',INH), +0x60:('NEG',IDY),0x63:('COM',IDY),0x64:('LSR',IDY),0x66:('ROR',IDY), +0x67:('ASR',IDY),0x68:('ASL',IDY),0x69:('ROL',IDY),0x6A:('DEC',IDY), +0x6C:('INC',IDY),0x6D:('TST',IDY),0x6E:('JMP',IDY),0x6F:('CLR',IDY), +0x8C:('CPY',IMM16),0x8F:('XGDY',INH),0x9C:('CPY',DIR), +0xA0:('SUBA',IDY),0xA1:('CMPA',IDY),0xA2:('SBCA',IDY),0xA3:('SUBD',IDY), +0xA4:('ANDA',IDY),0xA5:('BITA',IDY),0xA6:('LDAA',IDY),0xA7:('STAA',IDY), +0xA8:('EORA',IDY),0xA9:('ADCA',IDY),0xAA:('ORAA',IDY),0xAB:('ADDA',IDY), +0xAC:('CPY',IDY),0xAD:('JSR',IDY),0xAE:('LDS',IDY),0xAF:('STS',IDY), +0xBC:('CPY',EXT),0xCE:('LDY',IMM16),0xDE:('LDY',DIR),0xDF:('STY',DIR), +0xE0:('SUBB',IDY),0xE1:('CMPB',IDY),0xE2:('SBCB',IDY),0xE3:('ADDD',IDY), +0xE4:('ANDB',IDY),0xE5:('BITB',IDY),0xE6:('LDAB',IDY),0xE7:('STAB',IDY), +0xE8:('EORB',IDY),0xE9:('ADCB',IDY),0xEA:('ORAB',IDY),0xEB:('ADDB',IDY), +0xEC:('LDD',IDY),0xED:('STD',IDY),0xEE:('LDY',IDY),0xEF:('STY',IDY), +0xFE:('LDY',EXT),0xFF:('STY',EXT), +} +# page 2 ($1A): CPD, and X/Y cross indexed +P2 = {0x83:('CPD',IMM16),0x93:('CPD',DIR),0xA3:('CPD',IDX),0xB3:('CPD',EXT), +0xAC:('CPY',IDX),0xEE:('LDY',IDX),0xEF:('STY',IDX)} +# page 4 ($CD): X/Y cross indexed +P4 = {0xA3:('CPD',IDY),0xAC:('CPX',IDY),0xEE:('LDX',IDY),0xEF:('STX',IDY)} + +def disasm(rom, addr, count): + out=[] + for _ in range(count): + start=addr + op=rom[addr]; addr+=1 + tab=P0; pfx='' + if op==0x18: pfx='18 '; op=rom[addr]; addr+=1; tab=P1 + elif op==0x1A: pfx='1A '; op=rom[addr]; addr+=1; tab=P2 + elif op==0xCD: pfx='CD '; op=rom[addr]; addr+=1; tab=P4 + ent=tab.get(op) + if ent is None: + out.append((start,f".byte ${op:02X}",'?')); continue + mn,mode=ent; operand=''; tgt=None + if mode==INH: pass + elif mode==IMM8: operand=f"#${rom[addr]:02X}"; addr+=1 + elif mode==IMM16: operand=f"#${(rom[addr]<<8)|rom[addr+1]:04X}"; addr+=2 + elif mode==DIR: operand=f"${rom[addr]:02X}"; addr+=1 + elif mode==EXT: + v=(rom[addr]<<8)|rom[addr+1]; addr+=2; operand=f"${v:04X}"; tgt=v + elif mode==IDX: operand=f"${rom[addr]:02X},X"; addr+=1 + elif mode==IDY: operand=f"${rom[addr]:02X},Y"; addr+=1 + elif mode==REL: + rel=rom[addr]; addr+=1; d=rel-256 if rel>127 else rel + tgt=(addr+d)&0xFFFF; operand=f"${tgt:04X}" + elif mode==BITDIR: operand=f"${rom[addr]:02X} #${rom[addr+1]:02X}"; addr+=2 + elif mode==BITIDX: operand=f"${rom[addr]:02X},X #${rom[addr+1]:02X}"; addr+=2 + elif mode==BITIDY: operand=f"${rom[addr]:02X},Y #${rom[addr+1]:02X}"; addr+=2 + elif mode==BRDIR: + dd=rom[addr]; mk=rom[addr+1]; rel=rom[addr+2]; addr+=3 + s=rel-256 if rel>127 else rel; tgt=(addr+s)&0xFFFF + operand=f"${dd:02X} #${mk:02X} ${tgt:04X}" + elif mode==BRIDX: + dd=rom[addr]; mk=rom[addr+1]; rel=rom[addr+2]; addr+=3 + s=rel-256 if rel>127 else rel; tgt=(addr+s)&0xFFFF + operand=f"${dd:02X},X #${mk:02X} ${tgt:04X}" + elif mode==BRIDY: + dd=rom[addr]; mk=rom[addr+1]; rel=rom[addr+2]; addr+=3 + s=rel-256 if rel>127 else rel; tgt=(addr+s)&0xFFFF + operand=f"${dd:02X},Y #${mk:02X} ${tgt:04X}" + raw=' '.join(f'{rom[b]:02X}' for b in range(start,addr)) + out.append((start,f"{pfx}{mn} {operand}".strip(), raw, mn, tgt)) + return out + +if __name__=='__main__': + rom=open(__import__('os').path.join(__import__('os').path.dirname(__file__),'tms27pc512.BIN'),'rb').read() + start=int(sys.argv[1],16); count=int(sys.argv[2]) if len(sys.argv)>2 else 40 + for row in disasm(rom,start,count): + a=row[0]; txt=row[1]; raw=row[2] + print(f"{a:04X}: {raw:<12} {txt}") diff --git a/PlasmaNew/tms27pc512.BIN b/PlasmaNew/tms27pc512.BIN new file mode 100644 index 0000000..5816ade Binary files /dev/null and b/PlasmaNew/tms27pc512.BIN differ