#!/usr/bin/python3
from __future__ import annotations
from mrcrowbar import ansi
from mrcrowbar import models as mrc
from mrcrowbar import 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 )