Initial commit

This commit is contained in:
Jeff Jetton 2022-05-14 10:48:07 -05:00
parent af3626d034
commit 8f4e597db5
8 changed files with 2210 additions and 0 deletions

102
packer.py Normal file
View File

@ -0,0 +1,102 @@
# Read in file of five-letter words and encode them into two groups
# of three-byte packed binary.
#
# Each letter is converted to a five-bit value, 0-25.
# The bits are put together into a 25 bits, which would normally take
# up four bytes of storage. Since bit 0 of the MSB (the right-most bit
# of our 25 bits) can only be 0 or 1, we'll just split the data
# into two groups and only store the least-significant 24 bits.
#
# In other words, if the first letter is A-P (0-15), we can store that
# first letter in only four bits. Remaining letters are five bits each
# regardless, for a total of 24 bits (three bytes).
# If the first letter is P-Z (15-25), we'll still store it in four bits,
# but in separate list that we'll keep in a specific section of
# memory. We'll just need to be aware that words from that part of the
# list will need to have that bit put back on (i.e., have that first
# letter shifted up the alphabet by 16 letters)
import random
INFILE = 'words.txt'
OUTFILE_0 = 'words_0.bin'
OUTFILE_1 = 'words_1.bin'
def pack(word):
# Pack a five-letter word into three bytes.
# Return binary bytes along with an overflow flag (1 or 0)
word = word.strip().upper()
if len(word) != 5:
raise ValueError(f'"{word}" is not five letters long')
b = 0
for i in range(5):
# Convert letter to 0-25 integer
c = ord(word[i]) - 65
if (c < 0) or (c > 25):
raise ValueError('Character out of range A-Z in word ' + word)
# Scoot current contents of b over by five bits,
# then add new character
b = b * 32
b += c
# Did we "overflow" into bit 24?
if b & 0x1000000:
# Mask off just the leftmost three bytes
b &= 0xFFFFFF
overflow = 1
else:
overflow = 0
# Return as a three-byte bytes object
return [b.to_bytes(3, 'big'), overflow]
def head_and_tail(list, size=6):
print('Head: ' + str(list[0:size]))
print('Tail: ' + str(list[-size:]))
return
##############################################################################
# Read in list
print('\nReading ' + INFILE)
with open(INFILE, 'r') as infile:
words = infile.readlines()
print('Words read: ' + str(len(words)))
head_and_tail(words)
print()
# Shuffle them up
print('Shuffling...')
random.seed(24601)
random.shuffle(words)
head_and_tail(words)
print()
# Pack into bytes (this also uppercases and strips whitespace/returns)
print('Packing words...')
packed_list = [[],[]]
for word in words:
packed = pack(word)
packed_list[packed[1]].append(packed[0])
print('Words with first bit = 0: ' + str(len(packed_list[0])))
print('Words with first bit = 1: ' + str(len(packed_list[1])))
print()
# Save as two separate list files
print('Saving word lists...')
with open(OUTFILE_0, 'wb') as outfile:
for data in packed_list[0]:
outfile.write(data)
with open(OUTFILE_1, 'wb') as outfile:
for data in packed_list[1]:
outfile.write(data)
print('Done\n')

866
words.txt Normal file
View File

@ -0,0 +1,866 @@
ABBOT
ABEAM
ABOUT
ABOVE
ABUSE
ABUZZ
ABYSS
ACHOO
ACRID
ADDED
ADDER
AFOOT
AFTER
AGAIN
AGAPE
AGLOW
AGREE
AIDED
ALGOL
ALIEN
ALLEY
ALLOW
ALLOY
ALOFT
ALTAR
AMBER
AMBLE
AMONG
ANGER
ANGLE
ANISE
ANKLE
ANNEX
ANODE
ANVIL
AORTA
APPLE
ARISE
ARMOR
AROMA
ARRAY
ARTSY
ASHEN
ASIDE
ASSAY
ATTIC
AUDIT
AWARE
AWFUL
AWOKE
BADGE
BADLY
BAKER
BALER
BANJO
BARGE
BARON
BASIC
BASIN
BATHE
BAYOU
BEADY
BEFIT
BEGAN
BEGIN
BELIE
BENCH
BERTH
BEVEL
BINGO
BIRTH
BLACK
BLANK
BLAST
BLESS
BLITZ
BLOCK
BLOWN
BLUER
BLUFF
BLUNT
BLUSH
BOARD
BODGE
BOOST
BOOZE
BRACE
BRAID
BRAIN
BRAWN
BREAD
BREAK
BRIBE
BRIDE
BRING
BRISK
BROAD
BROIL
BROKE
BROTH
BROWN
BUDGE
BUGGY
BUILD
BUILT
BULGE
BULKY
BURNT
BURST
BUSHY
BUTTE
BUYER
BYTES
CABBY
CABIN
CACHE
CAGED
CAMEL
CANDY
CARAT
CAROL
CARRY
CATCH
CAUSE
CEASE
CEDAR
CHAFE
CHAIR
CHAMP
CHARD
CHART
CHASE
CHEAP
CHECK
CHESS
CHICK
CHIEF
CHILD
CHIRP
CHOCK
CHORD
CHUNK
CLACK
CLAIM
CLASP
CLASS
CLEAN
CLEAR
CLICK
CLIMB
CLOCK
CLOSE
CLOUD
CLUNG
COAST
COBOL
COCOA
CODEC
CODED
CODER
COLOR
COMBO
COMET
CONCH
COULD
COUNT
COUPE
COVEN
COVER
CRAFT
CREAK
CREEP
CREPE
CRIED
CROSS
CROWD
CRUEL
CRUFT
CRUMB
CRUST
CRYPT
CYCLE
DAFFY
DANCE
DANDY
DATED
DAZED
DEATH
DEBAR
DEBUG
DELTA
DEPOT
DEUCE
DEVIL
DIARY
DICEY
DIMLY
DINGO
DIODE
DISCO
DITCH
DOING
DOLLY
DOUGH
DOWEL
DOWNY
DRAWL
DRAWN
DREAD
DREAM
DRESS
DRIFT
DRINK
DRIVE
DROID
DROVE
DROWN
DRUID
DUVET
DWELL
DWELT
EARLY
EARTH
EIGHT
EJECT
ELECT
ELEGY
ELFIN
ELUDE
EMAIL
EMOJI
EMOTE
ENEMY
ENJOY
ENTER
ENVOY
EPOXY
EQUAL
EQUIP
ERASE
ERECT
ESSAY
ETHIC
ETHOS
ETUDE
EVENT
EVERY
EXACT
EXILE
EXPEL
EXTOL
FAINT
FALSE
FARAD
FAVOR
FEAST
FETAL
FIBER
FIELD
FIERY
FIGHT
FILTH
FINAL
FIRST
FISHY
FLACK
FLAIL
FLAKE
FLANK
FLARE
FLIER
FLING
FLOCK
FLOOR
FLOSS
FLUID
FLUME
FLUNG
FLUTE
FOCAL
FOGGY
FOIST
FOLLY
FORCE
FORTH
FOUND
FREED
FRESH
FRIAR
FRILL
FRISK
FROND
FRONT
FROST
FROTH
FRUIT
FUROR
GAILY
GASSY
GAUZE
GAYLY
GEESE
GENIE
GHOST
GIRTH
GIVEN
GLADE
GLASS
GLIDE
GLINT
GLOAM
GLOSS
GLUON
GLYPH
GOOFY
GOOSE
GOURD
GRACE
GRADE
GRAFT
GRAND
GRAPE
GRASP
GRASS
GRAVE
GRAZE
GREAT
GREED
GREEN
GRILL
GRIPE
GROOM
GROUP
GROWL
GRUMP
GRUNT
GUARD
GUESS
GUEST
GUIDE
GUILE
GULCH
GUSTO
HACKS
HAIRY
HANDY
HAPPY
HARPY
HARRY
HASTE
HASTY
HATCH
HEADY
HEARD
HEART
HEAVY
HELIX
HENRY
HERON
HERTZ
HINGE
HOBBY
HONEY
HORSE
HOTEL
HOTLY
HOUSE
HUMAN
HUMID
HURRY
HYDRO
HYENA
IDEAL
IDYLL
INEPT
INERT
INFER
INFIX
INNER
INTRO
IRATE
IVORY
JELLY
JERKY
JETON
JEWEL
JOKER
JOULE
JOUST
JUMBO
JUMPY
KABOB
KAPUT
KARMA
KAYAK
KNEEL
KNOCK
KNOLL
KNOWN
KOALA
KUDZU
LABEL
LABOR
LANAI
LARGE
LARVA
LATER
LATHE
LAUGH
LEACH
LEARN
LEASH
LEAST
LEAVE
LEECH
LEMMA
LEVEL
LEVER
LIEGE
LIGHT
LIKEN
LILAC
LINGO
LLAMA
LOCAL
LOCUS
LOGIC
LOOPY
LUCID
LURCH
LYRIC
MACRO
MAJOR
MANNA
MASON
MATCH
MEANT
MEATY
MEDIA
MELON
MERGE
METAL
METER
MICRO
MIGHT
MIMIC
MINCE
MIRTH
MISTY
MODEL
MODEM
MOMMY
MONEY
MONTH
MORAL
MOUND
MOUNT
MOUTH
MUMMY
MUMPS
MUSIC
MUSTY
NAIVE
NASAL
NAVEL
NEEDY
NERDY
NEVER
NIGHT
NINNY
NOISE
NORTH
NOSEY
NUDGE
NURSE
NYLON
NYMPH
OCCUR
OCEAN
OCTAL
OCTET
ODDLY
OFFER
OFTEN
OLDEN
OLDER
ONION
OPERA
OPIUM
ORBIT
ORDER
ORGAN
OTHER
OVERT
OXIDE
OZONE
PAINT
PANDA
PANEL
PANKO
PAPER
PARER
PARTY
PEACE
PEARL
PECAN
PENNY
PERCH
PESKY
PETAL
PETTY
PHASE
PIANO
PIECE
PIETY
PILAF
PIPER
PIQUE
PITCH
PIXEL
PLACE
PLAIN
PLAIT
PLANE
PLANT
PLIED
PLIER
PLUMB
POACH
POINT
POISE
POKER
POLKA
POSER
POSSE
POUCH
POUND
POWER
PRESS
PRIDE
PRINT
PROBE
PROSE
PROVE
PROWL
PSALM
PULSE
PUNCH
PUPIL
PUREE
PURGE
PURSE
QUACK
QUAIL
QUAKE
QUALM
QUARK
QUART
QUEEN
QUEER
QUELL
QUERY
QUEST
QUEUE
QUICK
QUIET
QUILL
QUILT
QUIRK
QUITE
QUOTA
RABID
RACER
RADAR
RADIO
RAISE
RANGE
RAZOR
REACH
REACT
READY
REALM
RECAP
REIGN
RELAX
RELAY
REMIX
REPEL
REPLY
RESET
RETRO
RETRY
REVEL
RHYME
RIGHT
RIGID
RIPER
RISER
RIVER
RONDO
ROUND
ROWDY
ROYAL
RUDER
SABLE
SALLY
SATIN
SAUCE
SAUCY
SAUNA
SAVOR
SCALA
SCALE
SCANT
SCARE
SCOOT
SCORE
SCORN
SCOUR
SENSE
SERVE
SERVO
SETUP
SEVEN
SEVER
SEWER
SHALL
SHAPE
SHARE
SHARK
SHARP
SHAVE
SHEAR
SHEEP
SHEET
SHELL
SHIED
SHIFT
SHINE
SHINY
SHIRT
SHOAL
SHOOK
SHORE
SHORT
SHOUT
SHOWN
SHREW
SHUSH
SHYLY
SIEGE
SIGHT
SILKY
SINCE
SIXTH
SKILL
SKIMP
SKUNK
SLACK
SLAIN
SLASH
SLEEK
SLEEP
SLEPT
SLIME
SLIMY
SLURP
SMACK
SMALL
SMELL
SMILE
SMIRK
SMITE
SMOKE
SMOOT
SNARE
SNARL
SNEAK
SNEER
SNOOP
SNOUT
SNOWY
SOLID
SOLVE
SONAR
SONIC
SOUND
SOUTH
SPACE
SPARE
SPARK
SPEAK
SPECK
SPEED
SPELL
SPEND
SPICY
SPOKE
SPREE
SQUAD
STAGE
STAKE
STAND
START
STASH
STATE
STEAM
STEEL
STEIN
STENT
STICK
STILL
STILT
STINT
STONE
STONY
STOOD
STOOL
STORE
STORK
STORY
STOUT
STOVE
STRIP
STRUT
STUCK
STUDY
SUAVE
SUGAR
SWAMP
SWARM
SWELL
SWIFT
SWORE
SWUNG
SYRUP
SYSOP
TABLE
TABOO
TACKY
TEACH
TEETH
TENOR
TENTH
TERSE
TESLA
TESTY
THANK
THEIR
THERE
THESE
THICK
THIEF
THIGH
THING
THINK
THIRD
THOSE
THREE
THROW
TIBIA
TIGER
TITAN
TITHE
TODAY
TONIC
TOOTH
TOPAZ
TOPIC
TORCH
TORSO
TOTAL
TOUCH
TOWER
TOXIC
TRACK
TRACT
TRADE
TRAIL
TRAIN
TRAIT
TREAD
TREND
TRIAC
TROLL
TROOP
TRUCK
TRUNK
TRUST
TUBER
TUNIC
TWANG
TWICE
TWIST
TYING
UNDER
UNITY
UNSET
UNTIL
USUAL
VALID
VALUE
VAPOR
VENAL
VERSO
VIDEO
VIGOR
VIOLA
VIRUS
VISIT
VISTA
VITAL
VIVID
VOCAL
VOICE
VOILA
VOLTS
VOUCH
VOWEL
VYING
WACKY
WAIVE
WASTE
WATCH
WATER
WATTS
WAXEN
WELCH
WHEAT
WHEEL
WHERE
WHICH
WHIFF
WHILE
WHITE
WHOLE
WHOSE
WIDEN
WIDTH
WIELD
WINCE
WISPY
WITCH
WITTY
WOKEN
WOMAN
WONKY
WOOZY
WORLD
WORSE
WOULD
WREAK
WRIST
WRITE
WRONG
WROTE
XENON
YACHT
YEARN
YEAST
YIELD
YOUNG
YOUTH
ZEBRA
ZESTY
ZONED

BIN
words_0.bin Normal file

Binary file not shown.

BIN
words_1.bin Normal file

Binary file not shown.

404
worple.asm Normal file
View File

@ -0,0 +1,404 @@
;-----------------------------------------------------------------------------
;
; "Worple" -- A Wordle-Style Game for the Apple I
;
; Jeff Jetton (inspired by a Javascript game by Josh Wardle)
; Feb/Mar 2022
;
; Written for the dasm assembler, but should work with tweaks for others
;
;-----------------------------------------------------------------------------
processor 6502
; Constants -----------------------------------------------------------------
KBD equ $D010 ; Location of input character from keyboard
KBDCR equ $D011 ; Keyboard control: Indicator that a new input
; character is ready
ECHO equ $FFEF ; WozMon routine to display register A char
WOZMON equ $FF1F ; Entry point back to WozMonitor
NULL equ $00 ; String terminator
CR equ $0D ; Carriage return ASCII value
ESC equ $1B ; Escape key ASCII value
BACKSP equ '_ ; Yup. This is what the backspace key generates.
MAXGUES equ '6 ; Guesses are tracked as ASCII numbers, not ints!
BUFFER equ $0200 ; Text buffer for user input
; Zero-page variables -------------------------------------------------------
seg.u VARS
org $0000
APACK ds 4 ; Workspace for packed version of answer
HINTWK ds 5 ; Workspace for building hint string--starts as copy of ANSWER
RAND ds 2 ; Pointer to a word in the list, constantly cycled in the
; key-polling routine to "randomly" pick one each game
COUNTER ds 1 ; Zero-page counter to use when X & Y are occupied in EVALUATE
TXTPTR ds 2 ; Two-byte pointer to char in a text string. Used by PRINT
; Main program --------------------------------------------------------------
seg CODE
org $0300
; Init the program
cli ; No interrupts (just to be safe)
cld ; BCD mode off
jsr INITRND ; Set RAND pointer to beginning of word list
; Show welcome message and ask if user wants instructions
jsr PRINT
dc CR
dc "WORPLE!"
dc CR
dc CR
dc "INSTRUCTIONS (Y/N)? "
dc NULL
jsr GETLINE ; Ask user for a string in input text
lda BUFFER ; Put first character of that string in A
cmp #'Y ; Is it Y?
beq INSTR ; Yes, show instructions
jmp NEWGAME ; Too far for a branch :-(
INSTR jsr PRINT
dc "YOU HAVE SIX TURNS TO GUESS MY 5-LETTER"
dc CR
dc "WORD. I'LL GIVE YOU HINTS AFTER EACH:"
dc CR
dc CR
dc " * = LETTER IN CORRECT PLACE"
dc CR
dc " ? = RIGHT LETTER, WRONG PLACE"
dc CR
dc " - = NOT IN WORD"
dc CR
dc NULL
NEWGAME jsr PRINT
dc CR
dc NULL
lda #'0 ; Init GNUM (guess number) to ASCII "0"
sta GNUM ; We store this directly in the prompt text
; jsr INITRND ; Uncomment to debug (always pick 1st word)
jsr UNPACK ; Unpack into ANSWER whatever RAND now points to
NXTTURN inc GNUM ; Next guess number
PROMPT jsr PRINT ; Display prompt...
dc "GUESS #"
GNUM dc 'N ; Current guess # is embedded here
dc ": "
dc NULL
jsr GETLINE ; Get player guess
cpx #5 ; User typed exactly five chars + CR?
beq EVALUAT ; Yes
cpx #0 ; No chars?
beq PROMPT ; Yes, just redo prompt without err msg
jsr PRINT ; Display error message amd try again
dc " ENTER 5 LETTERS"
dc CR
dc NULL
jmp PROMPT
EVALUAT SUBROUTINE ; Build hint string. The workspace keeps track
; of which letters in the ANSWER we've matched
; to already, in some way or another.
lda #0
sta COUNTER ; Track number of matches in COUNTER
ldx #4
.exalp lda ANSWER,X
cmp BUFFER,X ; Exact match to guess at this position?
beq .match ; Yes
sta HINTWK,X ; Store the answer letter in HINTWK workspace
lda #'- ; for possible inexact matching later
sta HINT,X ; Store "-" in HINT for now
bne .nxtltr ; Always taken
.match lda #'* ; Put "*" in both HINT (for display) and HINTWK
sta HINT,X ; (so the letter is out of the running for
sta HINTWK,X ; the inexact match check below)
inc COUNTER
.nxtltr dex ; Loop backwards for exact matches
bpl .exalp
ldx #0 ; Now check (looping forward) for inexact matches
.inxlp lda HINTWK,X
cmp #'* ; Have we exact-matched this letter already?
beq .nextx ; Yes, move on to next guessed letter
lda BUFFER,X ; A holds guessed letter
ldy #0
.chkltr cmp HINTWK,Y ; Does guessed letter match answer letter at Y?
beq .inxmch ; Yes, it's an inexact match
iny
cpy #5
bne .chkltr
beq .nextx
.inxmch lda #'?
sta HINT,X ; Put "?" at the guessed letter's position in HINT
sta HINTWK,Y ; and at the tested letter's position in HINTWK, so
; it won't get re-matched by a later guessed letter
.nextx inx
cpx #5
bne .inxlp
; Display the hint string
jsr PRINT
dc " "
HINT dc "-----" ; This gets overwritten by hint string at runtime
dc CR
dc NULL
; Was that a winning guess? (i.e., did we get five matches?)
lda #5
cmp COUNTER
beq WINNER
; Are we done yet?
lda GNUM ; Check current guess number
cmp #MAXGUES ; Was that the last turn?
beq LOSE ; Yup
jmp NXTTURN
LOSE jsr PRINT
dc "SORRY, THE WORD WAS "
dc '"
ANSWER dc "XXXXX" ; Overwritten by answer text at runtime
dc '"
dc NULL
jmp REPLAY
WINNER lda GNUM ; We won! Set up a response string to print...
and #%111 ; Convert ASCII GNUM "1" to "6" to values 1 to 6
asl ; Mult. by two to yield an offset from 2 to 12
tax ; Move offset to X
lda [PTRTBL-2],X ; Copy over LSB of response string
sta TXTPTR
lda [PTRTBL-1],X ; ...and the MSB
sta TXTPTR+1
jsr PRPTR ; Call print subroutine that assumes TXTPTR is set
lda #'! ; Saves one byte vs. putting the ! in each string
jsr ECHO
REPLAY jsr PRINT
dc CR
dc CR
dc "PLAY AGAIN (Y/N)? "
dc NULL
jsr GETLINE
lda BUFFER ; First character of response
cmp #'Y ; Is it Y?
bne QUIT ; No
jmp NEWGAME
QUIT jmp WOZMON ; Exit to monitor
; Subroutines ---------------------------------------------------------------
UNPACK SUBROUTINE ; Unpack the word currently pointed to by RAND
ldy #2 ; First copy the three bytes of the packed answer into
; the last three bytes of four-byte workspace APACK
.cpylp lda (RAND),Y
sta [APACK+1],Y
dey
bpl .cpylp ; Loop if not done copying
lda RAND ; Which part of the word list is RAND on (0 or 1)?
cmp #<WORDS_1 ; Subtract LSB of "1" list address from MSB of RAND
; We use cmp since we don't care about the result,
; just the carry flag (cmp sets carry automatically)
lda RAND+1 ; Subtract the MSB of "1" list from MSG of RAND
sbc #>WORDS_1 ; taking into account the carry flag from the cmp step
lda #0 ; Carry flag winds up equal to what bit 25 should be
adc #0 ; Put carry flag in A
sta APACK ; 1 if we're into "1" list, 0 if not
ldy #6 ; Shift the 25 bits of the packed word to the leftmost
.shftlp jsr ROTWKSP ; end of the four-byte (32-bit) workspace
dey
bpl .shftlp
iny ; Bump Y to zero to track ANSWER byte offset
.nxtltr lda #5 ; Each letter is encoded into five bits
sta COUNTER ; which we'll count using COUNTER
.nxtbit jsr ROTWKSP ; Rotate leftmost workspace bit into carry
rol ; Rotate that carry into A
dec COUNTER
bne .nxtbit
clc ; Letter is ready. Convert to ASCII char.
adc #$A1 ; The 5 we put in A at .nxtltr was never cleared.
; So we can't just add 65 to convert 0-25 to ASCII
; 65-90. The shifted 101 means the letters are now
; encoded as 10100000-10111001 ($A0-$B9), so we
; add $A1. Not clearing A saves two bytes :-)
sta ANSWER,Y ; Store freshly-unpacked letter in the ANSWER string
iny
cpy #5 ; Have we done all five letters?
bmi .nxtltr ; No, do next letter...
rts
ROTWKSP SUBROUTINE ; Rotates all 32 bits of APACK to the left, into carry
; Used by UNPACK above. Destroys X.
ldx #3 ; Loop uses 4 fewer bytes than unrolled version
.shflp ROL APACK,X
dex
bpl .shflp
rts
INITRND lda #<WORDS_0 ; Start RAND address at beginning of word list
sta RAND
lda #>WORDS_0
sta RAND + 1
rts
; Input handling. Similar to WozMon's GETLINE, but doesn't do a CR first
; and also cycles through RAND offsets while polling for a key press.
; Ignores non-alpha keys except for backspace, escape, and return.
; Treats backspace like an escape (cancels current input line), so the hint
; string will still line up with the guess correctly.
GETLINE SUBROUTINE ; Get user input and cycle word pointer while polling
ldx #0 ; Register X is our current buffer offset
.getkey clc ; Move RAND pointer up by three bytes
lda RAND
adc #3
sta RAND
lda RAND+1
adc #0
sta RAND+1
lda RAND ; Did we move past the end of the word list?
cmp #<WRDEND ; (See UNPACK for notes on how this weird check works)
lda RAND+1
sbc #>WRDEND
bcc .chkpia ; Carry clear = had to borrow, so not past end yet
jsr INITRND ; Otherwise, set back at beginning of list
.chkpia lda KBDCR ; Check PIA for keyboard input
bpl .getkey ; Loop if A is "positive" (bit 7 low... no key ready)
lda KBD ; Get the keyboard character
and #%01111111 ; Clear bit 7, which is always set for some reason
cmp #'[ ; Did they type something greater than Z?
bcs .notaz ; Yes -- so not A-Z, check for other commands
cmp #'A ; Less than A?
bcc .notaz ; Yes
sta BUFFER,X ; Store letter in buffer
jsr ECHO ; display it
inx ; bump up buffer pointer
bmi .reprmt ; If we overflowed the buffer, reprompt
; (Otherwise this will fall through to the bne .getkey)
.notaz cmp #CR ; Return/Enter?
beq .enter ; Yes, echo it and return without zeroing X
cmp #BACKSP ; Did they hit a backspace?
beq .reprmt ; Yes, reprompt
cmp #ESC ; What about Escape?
bne .getkey ; Nope. Ignore this key and get next one
.reprmt ldx #0 ; Set X back to zero and return (causing a re-prompt)
.enter lda #CR
jmp ECHO
; End of input line handler
; Print routines: Use PRINT to print text immediately after JSR PRINT call
; (Immediate mode). PRPTR is, in turn, called by PRINT.
; PRPTR assumes TXTPTR is already correctly set up. Call it
; directly when setting up TXTPTR in some other way. Note
; that PRPTR starts with an INC, so set TXTPTR to one less
; than the address of the string you want to print.
PRINT SUBROUTINE ; Prints any null-terminated text following its call
pla ; JSR stores the return address minus one on the stack
sta TXTPTR ; Pop it back off and put it in our text pointer
pla ; (Little end was last in!)
sta TXTPTR+1
jsr PRPTR ; Call print routine now that TXTPTR is set up
lda TXTPTR+1 ; Push current pointer onto the stack (big end first)
pha ; This will be on the NULL, i.e. address-1 of the
lda TXTPTR ; next operation after the end of the string,
pha ; which is what RTS expects to see
rts
PRPTR SUBROUTINE ; Prints null-terminated string starting from TXTPTR+1
ldx #0 ; No non-indexed indirect mode, so just keep X at zero
.nextch inc TXTPTR ; Bump up the pointer one byte
bne .readch ; If we didn't wrap, read next character
inc TXTPTR+1 ; We did wrap, so bump up the most-sig byte too
.readch lda (TXTPTR,X)
beq .done ; If we're on a NULL, stop printing
jsr ECHO ; Otherwise, display the character
jmp .nextch
.done rts
; Stored data --------------------------------------------------------------
PTRTBL ; Pointer table for the "winner" responses below
.word TXT_W1-1 ; PRPTR routine assumes we start
.word TXT_W2-1 ; by pointing to the address
.word TXT_W3-1 ; just before the string
.word TXT_W4-1 ; we really want
.word TXT_W5-1
.word TXT_W6-1
; The responses themselves, depending on guess #
TXT_W1 dc "LUCKY"
dc NULL
TXT_W2 dc "AMAZING"
dc NULL
TXT_W3 dc "WOO-HOO"
dc NULL
TXT_W4 dc "WELL DONE"
dc NULL
TXT_W5 dc "NOT BAD"
dc NULL
TXT_W6 dc "PHEW"
dc NULL
; **** Word lists **********************************************************
; Letters are coded into five-bit chunks, so 25 bits for a five-letter word.
; Ex: A = 0 (00000), P = 15 (01111), Q = 16 (10000), and Z = 25 (11001)
; To fit into three bytes (24 bits), we don't store the leftmost bit of the
; first letter. Instead it's inferred and reconstructed based on which section
; of the alphabetical list of words we're in:
; Words starting with A-P, where the unstored leftmost bit should be zero:
WORDS_0 INCBIN "words_0.bin"
; Words starting with Q-Z, where unstored leftmost bit should be one:
WORDS_1 INCBIN "words_1.bin"
WRDEND ; Symbol to let us know we've reached the end of the list

BIN
worple.bin Normal file

Binary file not shown.

421
worple.js Normal file
View File

@ -0,0 +1,421 @@
tapes['Worple'] = {
script: 'C100R\n0300.0FFER\n0300R\n',
tracks: [[
0x58, 0xD8, 0x20, 0x2A, 0x05, 0x20, 0x7D, 0x05,
0x0D, 0x57, 0x4F, 0x52, 0x50, 0x4C, 0x45, 0x21,
0x0D, 0x0D, 0x49, 0x4E, 0x53, 0x54, 0x52, 0x55,
0x43, 0x54, 0x49, 0x4F, 0x4E, 0x53, 0x20, 0x28,
0x59, 0x2F, 0x4E, 0x29, 0x3F, 0x20, 0x00, 0x20,
0x33, 0x05, 0xAD, 0x00, 0x02, 0xC9, 0x59, 0xF0,
0x03, 0x4C, 0xD8, 0x03, 0x20, 0x7D, 0x05, 0x59,
0x4F, 0x55, 0x20, 0x48, 0x41, 0x56, 0x45, 0x20,
0x53, 0x49, 0x58, 0x20, 0x54, 0x55, 0x52, 0x4E,
0x53, 0x20, 0x54, 0x4F, 0x20, 0x47, 0x55, 0x45,
0x53, 0x53, 0x20, 0x4D, 0x59, 0x20, 0x35, 0x2D,
0x4C, 0x45, 0x54, 0x54, 0x45, 0x52, 0x0D, 0x57,
0x4F, 0x52, 0x44, 0x2E, 0x20, 0x20, 0x49, 0x27,
0x4C, 0x4C, 0x20, 0x47, 0x49, 0x56, 0x45, 0x20,
0x59, 0x4F, 0x55, 0x20, 0x48, 0x49, 0x4E, 0x54,
0x53, 0x20, 0x41, 0x46, 0x54, 0x45, 0x52, 0x20,
0x45, 0x41, 0x43, 0x48, 0x3A, 0x0D, 0x0D, 0x20,
0x20, 0x2A, 0x20, 0x3D, 0x20, 0x4C, 0x45, 0x54,
0x54, 0x45, 0x52, 0x20, 0x49, 0x4E, 0x20, 0x43,
0x4F, 0x52, 0x52, 0x45, 0x43, 0x54, 0x20, 0x50,
0x4C, 0x41, 0x43, 0x45, 0x0D, 0x20, 0x20, 0x3F,
0x20, 0x3D, 0x20, 0x52, 0x49, 0x47, 0x48, 0x54,
0x20, 0x4C, 0x45, 0x54, 0x54, 0x45, 0x52, 0x2C,
0x20, 0x57, 0x52, 0x4F, 0x4E, 0x47, 0x20, 0x50,
0x4C, 0x41, 0x43, 0x45, 0x0D, 0x20, 0x20, 0x2D,
0x20, 0x3D, 0x20, 0x4E, 0x4F, 0x54, 0x20, 0x49,
0x4E, 0x20, 0x57, 0x4F, 0x52, 0x44, 0x0D, 0x00,
0x20, 0x7D, 0x05, 0x0D, 0x00, 0xA9, 0x30, 0x8D,
0xF2, 0x03, 0x20, 0xE9, 0x04, 0xEE, 0xF2, 0x03,
0x20, 0x7D, 0x05, 0x47, 0x55, 0x45, 0x53, 0x53,
0x20, 0x23, 0x4E, 0x3A, 0x20, 0x00, 0x20, 0x33,
0x05, 0xE0, 0x05, 0xF0, 0x1C, 0xE0, 0x00, 0xF0,
0xE7, 0x20, 0x7D, 0x05, 0x20, 0x45, 0x4E, 0x54,
0x45, 0x52, 0x20, 0x35, 0x20, 0x4C, 0x45, 0x54,
0x54, 0x45, 0x52, 0x53, 0x0D, 0x00, 0x4C, 0xE8,
0x03, 0xA9, 0x00, 0x85, 0x0B, 0xA2, 0x04, 0xBD,
0x9E, 0x04, 0xDD, 0x00, 0x02, 0xF0, 0x09, 0x95,
0x04, 0xA9, 0x2D, 0x9D, 0x6F, 0x04, 0xD0, 0x09,
0xA9, 0x2A, 0x9D, 0x6F, 0x04, 0x95, 0x04, 0xE6,
0x0B, 0xCA, 0x10, 0xE3, 0xA2, 0x00, 0xB5, 0x04,
0xC9, 0x2A, 0xF0, 0x19, 0xBD, 0x00, 0x02, 0xA0,
0x00, 0xD9, 0x04, 0x00, 0xF0, 0x07, 0xC8, 0xC0,
0x05, 0xD0, 0xF6, 0xF0, 0x08, 0xA9, 0x3F, 0x9D,
0x6F, 0x04, 0x99, 0x04, 0x00, 0xE8, 0xE0, 0x05,
0xD0, 0xDC, 0x20, 0x7D, 0x05, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2D,
0x2D, 0x2D, 0x2D, 0x2D, 0x0D, 0x00, 0xA9, 0x05,
0xC5, 0x0B, 0xF0, 0x2C, 0xAD, 0xF2, 0x03, 0xC9,
0x36, 0xF0, 0x03, 0x4C, 0xE5, 0x03, 0x20, 0x7D,
0x05, 0x53, 0x4F, 0x52, 0x52, 0x59, 0x2C, 0x20,
0x54, 0x48, 0x45, 0x20, 0x57, 0x4F, 0x52, 0x44,
0x20, 0x57, 0x41, 0x53, 0x20, 0x22, 0x58, 0x58,
0x58, 0x58, 0x58, 0x22, 0x00, 0x4C, 0xC1, 0x04,
0xAD, 0xF2, 0x03, 0x29, 0x07, 0x0A, 0xAA, 0xBD,
0x9E, 0x05, 0x85, 0x0C, 0xBD, 0x9F, 0x05, 0x85,
0x0D, 0x20, 0x8D, 0x05, 0xA9, 0x21, 0x20, 0xEF,
0xFF, 0x20, 0x7D, 0x05, 0x0D, 0x0D, 0x50, 0x4C,
0x41, 0x59, 0x20, 0x41, 0x47, 0x41, 0x49, 0x4E,
0x20, 0x28, 0x59, 0x2F, 0x4E, 0x29, 0x3F, 0x20,
0x00, 0x20, 0x33, 0x05, 0xAD, 0x00, 0x02, 0xC9,
0x59, 0xD0, 0x03, 0x4C, 0xD8, 0x03, 0x4C, 0x1F,
0xFF, 0xA0, 0x02, 0xB1, 0x09, 0x99, 0x01, 0x00,
0x88, 0x10, 0xF8, 0xA5, 0x09, 0xC9, 0x51, 0xA5,
0x0A, 0xE9, 0x0C, 0xA9, 0x00, 0x69, 0x00, 0x85,
0x00, 0xA0, 0x06, 0x20, 0x22, 0x05, 0x88, 0x10,
0xFA, 0xC8, 0xA9, 0x05, 0x85, 0x0B, 0x20, 0x22,
0x05, 0x2A, 0xC6, 0x0B, 0xD0, 0xF8, 0x18, 0x69,
0xA1, 0x99, 0x9E, 0x04, 0xC8, 0xC0, 0x05, 0x30,
0xE9, 0x60, 0xA2, 0x03, 0x36, 0x00, 0xCA, 0x10,
0xFB, 0x60, 0xA9, 0xD9, 0x85, 0x09, 0xA9, 0x05,
0x85, 0x0A, 0x60, 0xA2, 0x00, 0x18, 0xA5, 0x09,
0x69, 0x03, 0x85, 0x09, 0xA5, 0x0A, 0x69, 0x00,
0x85, 0x0A, 0xA5, 0x09, 0xC9, 0xFF, 0xA5, 0x0A,
0xE9, 0x0F, 0x90, 0x03, 0x20, 0x2A, 0x05, 0xAD,
0x11, 0xD0, 0x10, 0xE1, 0xAD, 0x10, 0xD0, 0x29,
0x7F, 0xC9, 0x5B, 0xB0, 0x0D, 0xC9, 0x41, 0x90,
0x09, 0x9D, 0x00, 0x02, 0x20, 0xEF, 0xFF, 0xE8,
0x30, 0x0C, 0xC9, 0x0D, 0xF0, 0x0A, 0xC9, 0x5F,
0xF0, 0x04, 0xC9, 0x1B, 0xD0, 0xBF, 0xA2, 0x00,
0xA9, 0x0D, 0x4C, 0xEF, 0xFF, 0x68, 0x85, 0x0C,
0x68, 0x85, 0x0D, 0x20, 0x8D, 0x05, 0xA5, 0x0D,
0x48, 0xA5, 0x0C, 0x48, 0x60, 0xA2, 0x00, 0xE6,
0x0C, 0xD0, 0x02, 0xE6, 0x0D, 0xA1, 0x0C, 0xF0,
0x06, 0x20, 0xEF, 0xFF, 0x4C, 0x8F, 0x05, 0x60,
0xAB, 0x05, 0xB1, 0x05, 0xB9, 0x05, 0xC1, 0x05,
0xCB, 0x05, 0xD3, 0x05, 0x4C, 0x55, 0x43, 0x4B,
0x59, 0x00, 0x41, 0x4D, 0x41, 0x5A, 0x49, 0x4E,
0x47, 0x00, 0x57, 0x4F, 0x4F, 0x2D, 0x48, 0x4F,
0x4F, 0x00, 0x57, 0x45, 0x4C, 0x4C, 0x20, 0x44,
0x4F, 0x4E, 0x45, 0x00, 0x4E, 0x4F, 0x54, 0x20,
0x42, 0x41, 0x44, 0x00, 0x50, 0x48, 0x45, 0x57,
0x00, 0x7A, 0x31, 0x03, 0x23, 0xA0, 0x4A, 0x68,
0xB9, 0xCC, 0x7A, 0x30, 0x0D, 0x28, 0xE1, 0xF3,
0x45, 0x95, 0x0D, 0xF5, 0x81, 0xB3, 0x65, 0xA0,
0x64, 0xB0, 0x34, 0x08, 0xC2, 0x01, 0xB3, 0x86,
0xCE, 0x2E, 0x48, 0x82, 0x44, 0x54, 0x11, 0x63,
0x46, 0xCC, 0x91, 0x46, 0x01, 0x0B, 0x04, 0x0C,
0x83, 0xD4, 0x35, 0xB8, 0x14, 0x34, 0xCE, 0x68,
0xD1, 0x8F, 0x40, 0x45, 0x78, 0xF7, 0x21, 0xB3,
0xF5, 0xA0, 0x91, 0xB7, 0x0A, 0x92, 0x1A, 0x2D,
0x58, 0xF8, 0xA1, 0xB3, 0x60, 0x53, 0x24, 0x28,
0xA0, 0x83, 0xF7, 0x2D, 0x40, 0x20, 0x4C, 0x47,
0x15, 0x92, 0x52, 0x15, 0xD2, 0x47, 0x08, 0xB1,
0xD1, 0x27, 0x0C, 0x83, 0xF5, 0x81, 0x13, 0x20,
0x45, 0xCB, 0x0B, 0x02, 0x24, 0x60, 0x4A, 0x58,
0xDC, 0x2D, 0xCD, 0x72, 0x02, 0x23, 0x63, 0xBA,
0x53, 0x38, 0xBA, 0xCD, 0x1A, 0x21, 0x73, 0x54,
0x46, 0x53, 0x65, 0x80, 0x64, 0x18, 0xB8, 0x03,
0xF4, 0x12, 0x78, 0x00, 0xE2, 0x52, 0x3B, 0x11,
0x6B, 0xEA, 0x92, 0x33, 0x02, 0xB9, 0xD3, 0x09,
0x20, 0x64, 0x54, 0x2E, 0x67, 0x00, 0xD3, 0x39,
0xF5, 0xD1, 0x81, 0x1A, 0x48, 0xF8, 0x18, 0x90,
0x03, 0x17, 0x0C, 0xC4, 0xF0, 0x34, 0x60, 0x86,
0x92, 0x33, 0xF5, 0xA0, 0x83, 0x25, 0xBA, 0x44,
0x32, 0x2E, 0x60, 0x55, 0x81, 0xAA, 0x07, 0x46,
0x60, 0xF7, 0x22, 0x44, 0xF7, 0x50, 0x47, 0x65,
0xD1, 0xCD, 0x12, 0x46, 0x67, 0x68, 0x82, 0xA4,
0xC0, 0x35, 0xA0, 0x25, 0x82, 0x52, 0x77, 0x52,
0x44, 0x0B, 0x16, 0x8B, 0x72, 0x46, 0x79, 0xB4,
0x10, 0xC4, 0x05, 0xAD, 0xD8, 0x55, 0x81, 0x0B,
0x55, 0xB8, 0x4A, 0x32, 0x55, 0x0B, 0xB2, 0x02,
0x47, 0xE1, 0x4C, 0x93, 0xCA, 0x4A, 0x78, 0xE8,
0x98, 0x0D, 0x09, 0x48, 0x18, 0x30, 0x34, 0x44,
0x62, 0x12, 0x44, 0x50, 0x44, 0x03, 0x70, 0x34,
0x78, 0x23, 0x90, 0x0F, 0x1A, 0x18, 0xD8, 0x08,
0xC4, 0x18, 0xF0, 0x3C, 0x91, 0xB0, 0x46, 0xA0,
0xC0, 0x25, 0xD1, 0x01, 0x8C, 0x83, 0x27, 0x51,
0x63, 0x1A, 0x45, 0xB3, 0x28, 0x90, 0x8F, 0xF4,
0x01, 0xAE, 0xA0, 0x60, 0x0A, 0xDC, 0x31, 0xE7,
0x49, 0x48, 0x18, 0x08, 0xB9, 0x80, 0xE1, 0x10,
0x0D, 0x20, 0x30, 0x8B, 0x20, 0x34, 0x78, 0x58,
0x92, 0x47, 0x92, 0x2D, 0x78, 0x25, 0xA0, 0x4A,
0x38, 0x90, 0x0C, 0x12, 0x34, 0x47, 0x15, 0x82,
0x53, 0xE7, 0xA2, 0x8C, 0xD0, 0x22, 0xA4, 0xC7,
0x52, 0x67, 0x86, 0x94, 0x91, 0x05, 0xB8, 0xB3,
0x18, 0xB9, 0x44, 0x34, 0x02, 0x38, 0xFA, 0x34,
0x47, 0x28, 0xBA, 0x52, 0x15, 0x81, 0xAA, 0xF9,
0x01, 0x6C, 0xE2, 0xCC, 0x8D, 0x55, 0xD1, 0x84,
0x15, 0xA2, 0x79, 0x02, 0xCC, 0x91, 0x00, 0xD2,
0x44, 0x14, 0x46, 0x67, 0x23, 0xA1, 0x63, 0x72,
0x02, 0xB8, 0x70, 0x4C, 0x47, 0x7C, 0x0E, 0x2E,
0xF0, 0x34, 0x8B, 0x54, 0x34, 0x0B, 0x60, 0x61,
0x78, 0x23, 0xD1, 0xAA, 0x64, 0x46, 0x67, 0x68,
0x80, 0x44, 0xF7, 0x00, 0x47, 0x62, 0x35, 0x04,
0xA6, 0xB9, 0x6B, 0x50, 0x21, 0xB3, 0xF5, 0x81,
0x0D, 0xF7, 0x58, 0x91, 0x10, 0x44, 0xC4, 0x27,
0x0C, 0x91, 0x25, 0x82, 0x4F, 0x38, 0xBA, 0xA4,
0x54, 0x12, 0x38, 0x45, 0x90, 0xD8, 0xB2, 0x54,
0x91, 0x27, 0x0C, 0x82, 0x77, 0x46, 0x44, 0x57,
0x22, 0x53, 0x54, 0x04, 0x91, 0x20, 0x08, 0xE4,
0x18, 0xA1, 0xA6, 0x1A, 0x4E, 0x64, 0x50, 0x55,
0xD1, 0x20, 0x44, 0x13, 0x49, 0xD0, 0x64, 0xF2,
0x02, 0x2B, 0xB2, 0x00, 0x47, 0x23, 0x80, 0xA4,
0x0B, 0x39, 0x44, 0x27, 0x30, 0x93, 0x52, 0x02,
0x53, 0xB7, 0x39, 0xF8, 0x77, 0x4D, 0x78, 0xA0,
0x45, 0x80, 0xF8, 0xA0, 0x64, 0xA7, 0x01, 0x60,
0x4A, 0x92, 0x38, 0xE5, 0x8C, 0x91, 0xB4, 0x34,
0xCE, 0xE1, 0x4C, 0x0B, 0x40, 0x46, 0x67, 0x10,
0x0C, 0xC4, 0x30, 0x34, 0x78, 0xB4, 0x18, 0xF3,
0x92, 0x45, 0x58, 0xC7, 0x31, 0x98, 0xE9, 0x9C,
0x91, 0xA0, 0x05, 0xC1, 0x05, 0xAC, 0x98, 0x17,
0x02, 0x23, 0x34, 0x08, 0x98, 0x72, 0x00, 0x78,
0xA6, 0xB8, 0x4A, 0xF4, 0x10, 0x44, 0x6A, 0x02,
0x23, 0x8A, 0xBA, 0x38, 0x10, 0x35, 0x2E, 0x47,
0xBA, 0xF8, 0x55, 0xD1, 0x03, 0x1A, 0x21, 0x63,
0xD4, 0x18, 0xF3, 0x38, 0xB9, 0x03, 0xE1, 0x8D,
0x78, 0xB0, 0x44, 0xC4, 0xC7, 0x51, 0xA3, 0x27,
0x54, 0x8D, 0x22, 0x02, 0x44, 0xC7, 0x0C, 0x8C,
0x67, 0x3A, 0x44, 0xC4, 0x18, 0xF3, 0x49, 0x9D,
0xD2, 0x55, 0xD2, 0x64, 0xF2, 0x44, 0x47, 0x06,
0x98, 0x91, 0x23, 0x90, 0x4A, 0xE7, 0x92, 0x20,
0xFA, 0x46, 0x44, 0x3A, 0x54, 0x93, 0xE1, 0x0A,
0x91, 0x6A, 0x2C, 0x47, 0x0A, 0x0D, 0x13, 0x10,
0x49, 0x0D, 0xB0, 0x05, 0xD1, 0x92, 0x4D, 0xCD,
0xC2, 0x02, 0x78, 0xF2, 0x4C, 0x0B, 0x54, 0x48,
0xF8, 0x4B, 0xBC, 0x8B, 0x67, 0x52, 0x23, 0x7C,
0x11, 0xA0, 0x81, 0xE1, 0x6B, 0x05, 0x99, 0xCB,
0x46, 0xA5, 0xD8, 0x18, 0xA0, 0x64, 0x27, 0x51,
0xB3, 0xC2, 0x44, 0xC4, 0x65, 0xB8, 0x0C, 0x74,
0x34, 0xC4, 0x4A, 0x91, 0xB3, 0xF7, 0x4A, 0x44,
0xC7, 0x44, 0x0B, 0xB5, 0x81, 0x80, 0x1A, 0x60,
0x91, 0x06, 0x04, 0x91, 0x57, 0x2D, 0x78, 0x28,
0x90, 0x0A, 0x48, 0x50, 0x0B, 0x58, 0xBA, 0x67,
0x46, 0x91, 0x98, 0x6A, 0x12, 0x53, 0x28, 0x91,
0xE4, 0xF4, 0x3C, 0x91, 0x17, 0x3A, 0x53, 0xC2,
0x4C, 0x91, 0x57, 0x46, 0x67, 0x22, 0x0C, 0x11,
0x15, 0xBA, 0xCD, 0x6A, 0x20, 0x64, 0x4B, 0xCD,
0xCB, 0x44, 0x90, 0x53, 0x10, 0x4C, 0xE4, 0xF4,
0x5C, 0x8B, 0x06, 0xB4, 0x97, 0x70, 0x4A, 0x78,
0x06, 0x05, 0x64, 0xEC, 0xB9, 0xA4, 0x72, 0x02,
0x33, 0x27, 0x2D, 0xD1, 0x32, 0x04, 0x11, 0x01,
0x8C, 0x91, 0x81, 0x90, 0x0B, 0x27, 0x02, 0x53,
0x23, 0x82, 0x23, 0x08, 0xA2, 0x44, 0x23, 0x92,
0x52, 0x68, 0x80, 0x64, 0x37, 0x58, 0x8B, 0x37,
0x2D, 0x78, 0xD2, 0x44, 0x78, 0x25, 0x90, 0x0D,
0x38, 0xD1, 0x03, 0x70, 0x09, 0x52, 0xC7, 0x51,
0xB3, 0x72, 0x2D, 0x17, 0x15, 0x80, 0x4A, 0xB0,
0x50, 0xC7, 0x10, 0x28, 0x91, 0xB0, 0x4C, 0xE4,
0xF3, 0x82, 0x44, 0x03, 0x44, 0x84, 0x20, 0x05,
0x0D, 0x06, 0x99, 0x64, 0x15, 0xB8, 0x4A, 0x25,
0x90, 0x11, 0x67, 0x38, 0xB8, 0xD2, 0x54, 0x91,
0xB2, 0x31, 0x80, 0x88, 0x82, 0x64, 0xD7, 0x22,
0x44, 0x4B, 0x80, 0x53, 0x37, 0x59, 0xB8, 0x25,
0xA1, 0x81, 0x65, 0xE1, 0xE7, 0x60, 0x21, 0x78,
0x68, 0x81, 0xA3, 0x49, 0x9D, 0x02, 0x32, 0x06,
0x86, 0x38, 0xA1, 0xAA, 0xDA, 0x0C, 0xC4, 0xC7,
0x0C, 0x8B, 0x70, 0x4A, 0x64, 0xC7, 0x34, 0x98,
0x00, 0xBA, 0xA4, 0xC4, 0x46, 0x67, 0x68, 0x90,
0x83, 0x20, 0x04, 0x38, 0xBC, 0x45, 0x02, 0xF5,
0x81, 0xA4, 0xE8, 0x8C, 0x91, 0xB2, 0x54, 0x8B,
0xF4, 0x42, 0x84, 0x86, 0xB4, 0x91, 0xF0, 0x46,
0x78, 0x55, 0x82, 0x24, 0x48, 0x51, 0x0F, 0x12,
0x19, 0x0D, 0x64, 0x54, 0x8D, 0xFA, 0x44, 0xC4,
0x28, 0xBA, 0xC3, 0x27, 0x51, 0xE4, 0x68, 0x82,
0x52, 0x97, 0x51, 0x64, 0x68, 0xA1, 0xE4, 0x32,
0x3D, 0xD3, 0x06, 0xA9, 0x64, 0x70, 0x45, 0xF8,
0x68, 0x90, 0x8D, 0x92, 0x58, 0x8B, 0x77, 0x04,
0x38, 0xA0, 0x3E, 0x93, 0x58, 0xA2, 0x4A, 0xCA,
0x31, 0x98, 0x77, 0x4C, 0x8B, 0x25, 0xBA, 0x83,
0x28, 0xD0, 0x8B, 0xF0, 0x21, 0xB3, 0xC0, 0x0A,
0x2E, 0x86, 0x95, 0x17, 0x68, 0x90, 0x13, 0x68,
0xD1, 0xB3, 0x50, 0x2E, 0x44, 0xF8, 0x92, 0x52,
0xC4, 0x31, 0x02, 0x5A, 0x45, 0xD1, 0x45, 0xD0,
0x64, 0x58, 0xB9, 0xA3, 0x68, 0xBA, 0xCB, 0x15,
0xD0, 0xA5, 0x23, 0x81, 0x8F, 0xE5, 0x8C, 0x8D,
0xC0, 0x4C, 0x47, 0x68, 0x80, 0xB3, 0xC4, 0x34,
0x44, 0x30, 0x4C, 0x83, 0x72, 0x36, 0x38, 0x06,
0xA2, 0x44, 0x58, 0xBA, 0x53, 0xB2, 0x02, 0x53,
0xAA, 0x0F, 0x34, 0x23, 0x81, 0x11, 0xB2, 0x10,
0x47, 0x38, 0xA0, 0xB3, 0xF2, 0x4E, 0x78, 0x10,
0x2C, 0x91, 0x06, 0xB8, 0x64, 0xB7, 0x08, 0x0B,
0xF8, 0xBA, 0xA4, 0xE2, 0x94, 0x91, 0x15, 0xD1,
0xB3, 0x2C, 0x09, 0x64, 0x6A, 0x12, 0x52, 0x55,
0x80, 0x4A, 0x58, 0xA0, 0x11, 0xC2, 0x2D, 0xCD,
0xC2, 0x4C, 0x0B, 0x70, 0x46, 0x38, 0x58, 0xD1,
0x13, 0x00, 0x85, 0xD3, 0x6A, 0x4A, 0x6E, 0x1A,
0x46, 0x53, 0x28, 0xD1, 0x81, 0xB4, 0x28, 0x8D,
0xF4, 0x2C, 0x05, 0x55, 0xB9, 0xD1, 0x18, 0x82,
0xCD, 0x57, 0x18, 0xD8, 0x58, 0xA1, 0x6B, 0x25,
0xD1, 0xA6, 0x1A, 0x2C, 0xC4, 0xBA, 0x44, 0x47,
0xF2, 0x00, 0x44, 0x34, 0x38, 0x64, 0xC4, 0x4A,
0x78, 0xCA, 0x49, 0x02, 0x01, 0x1D, 0xCE, 0x9A,
0x31, 0xF8, 0x32, 0x50, 0x44, 0x23, 0xBA, 0x23,
0x65, 0xA1, 0xB3, 0x1A, 0x0C, 0xC4, 0x58, 0x90,
0x83, 0xF4, 0x4C, 0x47, 0x10, 0x49, 0x02, 0x32,
0x02, 0x67, 0x15, 0xD0, 0x91, 0xD7, 0x48, 0x98,
0xFA, 0x44, 0x84, 0xB4, 0x2C, 0x02, 0x28, 0xD2,
0x53, 0x12, 0x18, 0x0D, 0x10, 0x0D, 0x78, 0x38,
0x92, 0x52, 0x08, 0xCE, 0x58, 0x03, 0x01, 0xE4,
0x01, 0x45, 0x03, 0x4B, 0xA1, 0x64, 0x05, 0xCC,
0x11, 0xE6, 0xA1, 0xCD, 0x38, 0xA2, 0xA4, 0x20,
0x18, 0x83, 0x18, 0x81, 0x0D, 0xF0, 0x35, 0x4E,
0xF2, 0x49, 0x58, 0x6A, 0x21, 0x64, 0x12, 0x2D,
0x04, 0x00, 0xBA, 0x93, 0x06, 0xD5, 0x0B, 0x97,
0x28, 0x91, 0x03, 0x2D, 0xD6, 0xF8, 0xB8, 0x24,
0x17, 0x3B, 0x24, 0xD7, 0x46, 0x67, 0x23, 0x82,
0x33, 0xF0, 0x44, 0x91, 0x52, 0x4C, 0x0B, 0x18,