Some text stuff

Some text stuff
This commit is contained in:
AmazingAmpharos 2018-03-14 11:26:50 -05:00 committed by GitHub
commit ee7ad585f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 161 additions and 21 deletions

182
Text.py
View File

@ -1,3 +1,4 @@
# -*- coding: UTF-8 -*-
text_addresses = {'Pedestal': (0x180300, 256),
'Triforce': (0x180400, 256),
'Uncle': (0x180500, 256),
@ -137,10 +138,13 @@ Ganon1_texts = [
"Did you know?\nThe biggest\nand heaviest\ncheese ever\nproduced\nweighed\n57,518 pounds\nand was 32\nfeet long.",
"Now there was\na time, When\nyou loved me\nso. I couldn't\ndo wrong,\nAnd now you\nneed to know.\nSo How you\nlike me now?",
"Did you know?\nNutrition\nexperts\nrecommend that\nat least half\nof our daily\ngrains come\nfrom whole\ngrain products",
"The Hemiptera\nor true bugs\nare an order\nof insects\ncovering 50k\nto 80k species\nlike aphids,\ncicadas, and\nshield bugs.",
"Thanks for\ndropping in,\nthe first\npassengers\nin a hot\nair balloon.\nwere a duck,\na sheep,\nand a rooster.",
"You think you\nare so smart?\n\nI bet you\ndidn't know\nYou can't hum\nwhile holding\nyour nose\nclosed.",
"grumble,\n\ngrumble…\ngrumble,\n\ngrumble…\nSeriously you\nwere supposed\nto bring food",
"Join me hero,\nand I shall\nmake your face\nthe greatest\nin the dark\nworld!\n\nOr else you\nwill die!",
]
TavernMan_texts = [
'Did you know that talking to random NPCs wastes time in a race? I hope this information may be of use to you in the future.'
] + [
"What do you\ncall a blind\ndinosaur?\nadoyouthink-\nhesaurus\n",
"A blind man\nwalks into\na bar.\nAnd a table.\nAnd a chair.\n",
"What do ducks\nlike to eat?\n\nQuackers!\n",
@ -435,32 +439,78 @@ class SceneLargeCreditLine(SceneCreditLine):
def string_to_alttp_text(s, maxbytes=256):
lines = s.upper().split('\n')
outbuf = string_to_alttp_core(s)
# check for max length
if len(outbuf) > maxbytes - 2:
outbuf = outbuf[:maxbytes - 2]
# Note: this could crash if the last byte is part of a two byte command
# depedning on how well the command handles a value of 0x7F.
# Should probably do something about this.
outbuf.append(0x7F)
outbuf.append(0x7F)
return outbuf
special_commands = {
"{SPEED0}": [0x7A, 0x00],
"{SPEED2}": [0x7A, 0x02],
"{SPEED6}": [0x7A, 0x06],
"{PAUSE1}": [0x78, 0x01],
"{PAUSE3}": [0x78, 0x03],
"{PAUSE5}": [0x78, 0x05],
"{PAUSE7}": [0x78, 0x07],
"{PAUSE9}": [0x78, 0x09],
"{INPUT}": [0x7E],
"{CHOICE}": [0x68],
"{ITEMSELECT}": [0x69],
"{CHOICE2}": [0x71],
"{CHOICE3}": [0x72],
"{HARP}": [0x79, 0x2D],
"{MENU}": [0x6D, 0x00],
"{BOTTOM}": [0x6D, 0x00],
"{NOBORDER}": [0x6B, 0x02],
"{CHANGEPIC}": [0x67, 0x67],
"{CHANGEMUSIC}": [0x67],
"{INTRO}": [0x6E, 0x00, 0x77, 0x07, 0x7A, 0x03, 0x6B, 0x02, 0x67],
"{NOTEXT}": [0x6E, 0x00, 0x6B, 0x04],
"{IBOX}": [0x6B, 0x02, 0x77, 0x07, 0x7A, 0x03],
}
def string_to_alttp_core(s, pause=True, wrap=14):
s = s.upper()
lines = s.split('\n')
outbuf = bytearray()
lineindex = 0
is_intro = '{INTRO}' in s
while lines:
linespace = 14
linespace = wrap
line = lines.pop(0)
if line.startswith('{'):
outbuf.extend(special_commands[line])
continue
words = line.split(' ')
outbuf.append(0x74 if lineindex == 0 else 0x75 if lineindex == 1 else 0x76) # line starter
while words:
word = words.pop(0)
# sanity check: if the word we have is more than 14 characters, we take as much as we can still fit and push the rest back for later
if len(word) > 14:
if linespace < 14:
if wordlen(word) > wrap:
if linespace < wrap:
word = ' ' + word
word_first = word[:linespace]
words.insert(0, word[linespace:])
(word_first, word_rest) = splitword(word, linespace)
words.insert(0, word_rest)
lines.insert(0, ' '.join(words))
write_word(outbuf, word_first)
break
if len(word) <= (linespace if linespace == 14 else linespace - 1):
if linespace < 14:
if wordlen(word) <= (linespace if linespace == wrap else linespace - 1):
if linespace < wrap:
word = ' ' + word
linespace -= len(word)
linespace -= wordlen(word)
write_word(outbuf, word)
else:
# ran out of space, push word and lines back and continue with next line
@ -468,26 +518,102 @@ def string_to_alttp_text(s, maxbytes=256):
lines.insert(0, ' '.join(words))
break
if is_intro and lineindex < 3:
outbuf.extend([0xFF]*linespace)
has_more_lines = len(lines) > 1 or (lines and not lines[0].startswith('{'))
lineindex += 1
if lineindex % 3 == 0 and lines:
if pause and lineindex % 3 == 0 and has_more_lines:
outbuf.append(0x7E)
if lineindex >= 3 and lines:
if lineindex >= 3 and has_more_lines:
outbuf.append(0x73)
return outbuf
# check for max length
if len(outbuf) > maxbytes - 1:
outbuf = outbuf[:maxbytes - 1]
# make sure we interpret the end of box character
if outbuf[-1] == 0x00:
outbuf[-1] = 0x73
two_byte_commands = [
0x6B, 0x6C, 0x6D, 0x6E,
0x77, 0x78, 0x79, 0x7A
]
specially_coded_commands = {
0x73: 0xF6,
0x74: 0xF7,
0x75: 0xF8,
0x76: 0xF9,
0x7E: 0xFA,
0x7A: 0xFC,
}
outbuf.append(0x7F)
def string_to_alttp_text_compressed(s, pause=True, max_bytes_expanded=0x800, wrap=14):
inbuf = string_to_alttp_core(s, pause, wrap)
# Links name will need 8 bytes in the target buffer
# and two will be used by the terminator
# (Variables will use 2 bytes, but they start as 2 bytes)
bufsize = len(inbuf) + 7 * inbuf.count(0x6A) + 2
if bufsize > max_bytes_expanded:
raise ValueError("Uncompressed string too long for buffer")
inbuf.reverse()
outbuf = bytearray()
outbuf.append(0xfb) # terminator for previous record
while inbuf:
val = inbuf.pop()
if val == 0xFF:
outbuf.append(val)
elif val == 0x00:
outbuf.append(inbuf.pop())
elif val == 0x01: #kanji
outbuf.append(0xFD)
outbuf.append(inbuf.pop())
elif val >= 0x67:
if val in specially_coded_commands:
outbuf.append(specially_coded_commands[val])
else:
outbuf.append(0xFE)
outbuf.append(val)
if val in two_byte_commands:
outbuf.append(inbuf.pop())
else:
raise ValueError("Unexpected byte found in uncompressed string")
return outbuf
def wordlen(word):
l = 0
offset = 0
while offset < len(word):
c_len, offset = charlen(word, offset)
l += c_len
return l
def splitword(word, length):
l = 0
offset = 0
while True:
c_len, new_offset = charlen(word, offset)
if l+c_len > length:
break
l += c_len
offset = new_offset
return (word[0:offset], word[offset:])
def charlen(word, offset):
c = word[offset]
if c in ['>', '¼', '½', '']:
return (2, offset+1)
if c in ['@']:
return (4, offset+1)
if c in ['', '', '', '']:
return (2, offset+1)
return (1, offset+1)
def write_word(buf, word):
for char in word:
buf.extend([0x00, char_to_alttp_char(char)])
res = char_to_alttp_char(char)
if isinstance(res, int):
buf.extend([0x00, res])
else:
buf.extend(res)
char_map = {' ': 0xFF,
@ -499,12 +625,26 @@ char_map = {' ': 0xFF,
'.': 0xCD,
'~': 0xCE,
'': 0xCE,
'@': [0x6A], # Links name (only works if compressed)
'>': [0x00, 0xD2, 0x00, 0xD3], # Link's face
"'": 0xD8,
'': 0xD8,
'%': 0xDD, # Hylian Bird
'^': 0xDE, # Hylian Ankh
'=': 0xDF, # Hylian Wavy Lines
'': 0xE0,
'': 0xE1,
'': 0xE2,
'': 0xE3,
'': 0xE4, # Cursor
'¼': [0x00, 0xE5, 0x00, 0xE7], # ¼ heart
'½': [0x00, 0xE6, 0x00, 0xE7], # ½ heart
'¾': [0x00, 0xE8, 0x00, 0xE9], # ¾ heart
'': [0x00, 0xEA, 0x00, 0xEB], # full heart
'': [0x6C, 0x00], # var 0
'': [0x6C, 0x01], # var 1
'': [0x6C, 0x02], # var 2
'': [0x6C, 0x03], # var 3
'': 0x00,
'': 0x01,
'': 0x02,