split classes into files for better understanding
- also for excluding some things in the build, as I may not need to support PCBoard at revision. Actually, I don't. Later I can add that support, but for now, I need the Revision bits working.
This commit is contained in:
parent
10e8940807
commit
49d411a3d1
15 changed files with 2454 additions and 746 deletions
117
16col/xbin.coffee
Normal file
117
16col/xbin.coffee
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
|
||||
class @ImageTextModeXBin extends @ImageTextMode
|
||||
|
||||
# Header constants
|
||||
PALETTE = 1
|
||||
FONT = 2
|
||||
COMPRESSED = 4
|
||||
NON_BLINK = 8
|
||||
FIVETWELVE_CHARS = 16
|
||||
|
||||
# Compression type constants
|
||||
NO_COMPRESSION = 0
|
||||
CHARACTER_COMPRESSION = 64
|
||||
ATTRIBUTE_COMPRESSION = 128
|
||||
FULL_COMPRESSION = 192
|
||||
|
||||
# Compression byte constants
|
||||
COMPRESSION_TYPE = 192
|
||||
COMPRESSION_COUNTER = 63
|
||||
|
||||
constructor: ( options ) ->
|
||||
super
|
||||
@header = { width: 0, height: 0, fontisze: 0, flags: 0 }
|
||||
this[k] = v for own k, v of options
|
||||
|
||||
parse: ( content ) ->
|
||||
@screen = []
|
||||
headerData = content.substr( 0, 11 )
|
||||
if headerData.length isnt 11 || !headerData.match( '^XBIN\x1a' )
|
||||
throw new Error( 'File is not an XBin' )
|
||||
|
||||
@header.width = @unpackShort( headerData.substr( 5, 2 ) )
|
||||
@header.height = @unpackShort( headerData.substr( 7, 2 ) )
|
||||
@header.fontsize = @getByteAt( headerData.substr( 9, 1 ) )
|
||||
@header.flags = @getByteAt( headerData.substr( 10, 1 ) )
|
||||
offset = 11
|
||||
|
||||
if @header.flags & PALETTE
|
||||
@parsePaletteData( content.substr( offset, 48 ) );
|
||||
offset += 48
|
||||
|
||||
if @header.flags & FONT
|
||||
fontlength = @header.fontsize
|
||||
if @header.flags & FIVETWELVE_CHARS
|
||||
fontlength *= 512
|
||||
else
|
||||
fontlength *= 256
|
||||
@parseFontData( content.substr( offset, fontlength ), @header.fontsize );
|
||||
offset += fontlength
|
||||
|
||||
if @header.flags & COMPRESSED
|
||||
@_parse_compressed( content.substr( offset ) )
|
||||
else
|
||||
@_parse_uncompressed( content.substr( offset ) )
|
||||
|
||||
_parse_compressed: ( data ) ->
|
||||
x = 0
|
||||
y = 0
|
||||
@screen[ y ] = []
|
||||
|
||||
data = data.split( '' )
|
||||
while info = data.shift()
|
||||
info = @getByteAt( info, 0 )
|
||||
break if info == 26
|
||||
|
||||
type = info & COMPRESSION_TYPE
|
||||
counter = ( info & COMPRESSION_COUNTER ) + 1
|
||||
|
||||
ch = null
|
||||
attr = null
|
||||
|
||||
while counter-- > 0
|
||||
switch type
|
||||
when NO_COMPRESSION
|
||||
ch = data.shift()
|
||||
attr = data.shift()
|
||||
when CHARACTER_COMPRESSION
|
||||
ch = data.shift() if !ch?
|
||||
attr = data.shift()
|
||||
when ATTRIBUTE_COMPRESSION
|
||||
attr = data.shift() if !attr?
|
||||
ch = data.shift()
|
||||
else
|
||||
ch = data.shift() if !ch?
|
||||
attr = data.shift() if !attr?
|
||||
|
||||
@screen[ y ][ x ] = { ch: ch, attr: @getByteAt( attr, 0 ) }
|
||||
|
||||
x++
|
||||
if x == @header.width
|
||||
x = 0
|
||||
y++
|
||||
break if y == @header.height
|
||||
@screen[ y ] = [] if !@screen[ y ]?
|
||||
|
||||
_parse_uncompressed: ( data ) ->
|
||||
x = 0
|
||||
y = 0
|
||||
@screen[ y ] = []
|
||||
|
||||
for i in [ 0 .. data.length - 2 ] by 2
|
||||
ch = data.substr( i, 1 )
|
||||
break if ch == "\x1a"
|
||||
attr = @getByteAt( data, i + 1 )
|
||||
@screen[ y ][ x ] = { 'ch': ch, 'attr': attr }
|
||||
x++
|
||||
if x == @header.width
|
||||
x = 0
|
||||
y++
|
||||
break if y == @header.height
|
||||
@screen[ y ] = [] if !@screen[ y ]?
|
||||
|
||||
getWidth: ->
|
||||
return @header.width
|
||||
|
||||
getHeight: ->
|
||||
return @header.height
|
||||
Loading…
Add table
Add a link
Reference in a new issue