이번 시간에는 콘솔 텍스트 화면을 제어하기 위한 공부를 하겠다.


//------------------------------+---------------------------------------------------------------


#include <cstddef>              //  std::size_t


#define CRE                     //  constructor ( place holder )


using   u8                      = unsigned  char;   // 길게 치기 싫으니 난 요렇게

using   u16                     = unsigned  short;

using   u32                     = unsigned  int;

using   uu                      = std::size_t;


//------------------------------+---------------------------------------------------------------

//  TEX color space


//  콘솔창을 저수준 제어하기 위해서 ( 고수준은 억수로 느림 )

//  과거 호랑이 담배피던 DOS 시절, B800 : 0000 물리적인 주소에 구현되어 있던 텍스트 화면이

//  한 문자당 2바이트로 표현하던 것을 알아두면 좋다. 왜냐하면 지금도 한 문자당 2바이트를 필요로 하기 때문이다.

//  화면에 찍히는 한 문자는 아스키 코드 1 바이트, 그리고 색상 1 바이트로 이루어지는데,

//  색상은 배경색이 상위 nibble, 전경색이 ( 글씨색 ) 하위 nibble 이다.

//  각 색상은 +( 밝게 / 혹은 깜박이게 ), r, g, b 각각 1 비트씩 총 4비트로 이루어져 있다.


//  lighten, red, green, blue 를 인자로 1 nibble color 를 만들어주는 코드

constexpr   auto                make_color16( u8  l, u8  r, u8  g, u8  b )

{

    return  u8( l << 3 | r << 2 | g << 1 | b );

}


//  그리하야 표준 16색의 열거형 상수를 표현했다. ( 사실 단순 증가기 땜에 rvalue 는 필요 없지만 이해를 돕고자 )

//  색상 이름 찾아보는거 귀찮았었다. ( 작년에 만든것임 )

enum    class                   C4 : u8

{   //                      +  R  G  B

    black   = make_color16( 0, 0, 0, 0 ),

    navy    = make_color16( 0, 0, 0, 1 ),

    green   = make_color16( 0, 0, 1, 0 ),

    teal    = make_color16( 0, 0, 1, 1 ),

    maroon  = make_color16( 0, 1, 0, 0 ),

    purple  = make_color16( 0, 1, 0, 1 ),

    olive   = make_color16( 0, 1, 1, 0 ),

    silver  = make_color16( 0, 1, 1, 1 ),

    gray    = make_color16( 1, 0, 0, 0 ),

    blue    = make_color16( 1, 0, 0, 1 ),

    lime    = make_color16( 1, 0, 1, 0 ),

    aqua    = make_color16( 1, 0, 1, 1 ),

    red     = make_color16( 1, 1, 0, 0 ),

    fuchsia = make_color16( 1, 1, 0, 1 ),

    yellow  = make_color16( 1, 1, 1, 0 ),

    white   = make_color16( 1, 1, 1, 1 ),

};


//  전경색 / 배경색 으로 코드를 작성하면 알아서 1바이트가 조합이 되게

constexpr   auto                operator/( C4 fore, C4 back )

{

    return  u8( static_cast< u8 >( back ) << 4 | static_cast< u8 >( fore ) );

};


//  전경색만 뽑아 오기

constexpr   auto                get_fore( u8 color )

{

    return  static_cast< C4 >( color & 0xF );

}


//  배경색만 뽑아오기

constexpr   auto                get_back( u8 color )

{

    return  static_cast< C4 >( color >> 4 );

}


//  뭐야? 죄다 비트연산이잖아?

//  그렇다 비트 연산 못하는 프로그래머는 솔까말 쓸모가 없다.



//  아래는 꼭 필요하진 않지만 칼라를 그레이로 바꾸기 위해 만들어봤다. ( fade in / fade out 되는것 처럼 구현 할려고 )

constexpr   C4                  c4_to_gray[]

{

    C4::black, C4::gray,  C4::gray,  C4::gray,  C4::gray,  C4::gray,  C4::gray,  C4::silver,

    C4::gray,  C4::silver,C4::silver,C4::silver,C4::silver,C4::silver,C4::silver,C4::white,

};


constexpr   u32                 to_gray_level[]

{

    0, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 2, 2, 2, 2, 3,

};


//  그레이로 쓸만한게 아쉽게도 4색 뿐

constexpr   C4                  gray_level_to_c4[]

{

    C4::black, C4::gray, C4::silver, C4::white,

};


//  증가 감소 연산만 사용해도 알아서 검은색에서 더 아래로 내려가지 않고 흰색에서 더 위로 올라가지 않게

//  32비트 리터럴 문자열을 이용한 테크닉 ( 좀전에 고안함 )

constexpr   C4                  level_to_c4_clamp( u32 level )

{

    return  gray_level_to_c4[ U"001233"[ level + 1 ] ]; // 문자열 안의 숫자 앞에 백슬래시를 붙이시라

}


//  증가 / 감소 연산만 하면 알아서 그레이 스케일 안에서 움직인다.

auto&                           operator++( C4& c )

{

    return  c = level_to_c4_clamp( to_gray_level[ static_cast< u8 >( c ) ] + 1 );

};


auto&                           operator--( C4& c )

{

    return  c = level_to_c4_clamp( to_gray_level[ static_cast< u8 >( c ) ] - 1 );

};

//------------------------------+---------------------------------------------------------------


//  위에서 말했듯, 색상을 갖고 있는 한 문자를 위한 자료형이다.

struct                          TEX

{

    u8                          color;

    char                        letter;


    CRE                         TEX() = default;


    CRE                         TEX( const u8 color, const char c )

    :   color( color ), letter( c ) {}


    CRE                         TEX( const int value )

    :   color( value & 0xFF ), letter( ( value & 0xFF00 ) >> 8 ) {}

};

//------------------------------+---------------------------------------------------------------


별거 없지? 바로 다음 레슨으로 들어가자.