from mrcrowbar import models as mrc, ansi, utils
from mrcrowbar.lib.hardware import ibm_pc
# map of DOS code page 437 to Unicode
CP437 = """ ☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼ !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~⌂ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ """
[docs]
def decode_nfo( buffer ):
"""Decodes a byte string in NFO format (beloved by PC scener groups) from DOS Code Page 437
to Unicode."""
assert utils.is_bytes( buffer )
return '\n'.join( [''.join( [CP437[y] for y in x] ) for x in buffer.split( b'\r\n' )] )
[docs]
class B800Char( mrc.Block ):
_palette = ibm_pc.EGA_DEFAULT_PALETTE
code_point = mrc.UInt8( 0x00 )
fg_blink = mrc.Bits( 0x01, 0b10000000 )
bg_colour = mrc.Bits( 0x01, 0b01110000 )
fg_colour = mrc.Bits( 0x01, 0b00001111 )
@property
def char( self ):
return CP437[self.code_point]
def __str__( self ):
return self.ansi_format()
def __repr__( self ):
return '<{}: char {}, bg {}, fg {}>'.format( self.__class__.__name__, self.char, self.bg_colour, self.fg_colour )
[docs]
class B800Screen( mrc.Block ):
B800_SCREEN_WIDTH = 80
chars = mrc.BlockField( B800Char, 0x00, count=2000 )
@property
def text( self ):
return '\n'.join(
[''.join(
[c.char for c in self.chars[i*self.B800_SCREEN_WIDTH:][:self.B800_SCREEN_WIDTH]]
) for i in range( (len( self.chars )+1)//self.B800_SCREEN_WIDTH )]
)
[docs]
def print( self ):
print( self.ansi_format() )
def __str__( self ):
return self.ansi_format()
def __repr__( self ):
return '<{}: {} chars, {}x{}>'.format( self.__class__.__name__, len( self.chars ), self.B800_SCREEN_WIDTH, 1+(len( self.chars )-1)//self.B800_SCREEN_WIDTH )
# source: https://www.fileformat.info/format/exe/corion-mz.htm
[docs]
class Relocation( mrc.Block ):
offset = mrc.UInt16_LE( 0x00 )
segment = mrc.UInt16_LE( 0x02 )
[docs]
class EXE( mrc.Block ):
mz_header = mrc.BlockField( MZHeader, 0x00 )