пятница, 5 февраля 2010 г.

Mass effect 2

Today I've finished the game. It was amazing. The best game in the last 2 years. For me, "Mass effect" is "Fallout" of the beginning of 21st century.
As it has been described in various reviews the ME2 has outperformed ME1 in everything. Bioware fixed all annoying things and made the game just brilliant: it's fast, good-looking, interesting and it can teach you if you are careful enough.
The dialogs can teach. The paragon-renegade decisions let you see how people react. Some of the dialogs are deep thoughts about our real world.

The deep thought that transfered from ME1 to ME2, the thought that made "Mass effect" a unique game in my eyes. In ME1 it has been said by Sovereign, now by Legion.

Shepard: Some of the geth followed Sovereign. The "heretics".
Legion: The heretics accepted their technology.
The Old Machines [Reapers] offered to give us our future. The geth will achieve their own future.
Shepard: What difference does it make how you acquire a certain technology?
Legion: Technology is not a straight line. There are many paths to the same end.
Accepting another's path blinds you to alternatives. Nazara -- Sovereign -- said this itself:
"Your civilization is based upon the technology of the mass relays. Our technology. By using it, your society develops along the paths we desire."


Accepting another's path blinds you to alternatives.
That's why a man should learn how things work if he wants to be able not just to follow and believe, but to lead and understand.

Your civilization is based upon the technology of the mass relays. Our technology. By using it, your society develops along the paths we desire.
We live in the world of rules created by others and thus develop along the paths the 'others' desire. That's a more elaborate stage of slavery, a hidden one. You live, you work, and you think this is life. But a small amount of people own large companies and can afford almost anything in life, they are modern kings. We develop the paths they desire...

--- RU ---
Mass effect 2

Сегодня я прошёл игру. Это было замечательно. Лучшая игра за последние два года. Для меня "Mass effect" - это "Fallout" начала 21-го века. Как было описано в разнообразных обзорах, ME2 превзошёл ME1 во всём. Bioware исправили все нудные вещи и создали блестящую игру: она быстрая, хорошо выглядящая, интересная, а также она может научить уму-разуму, если Вы будете достаточно внимательны.
Диалоги могут научить. Хорошие-плохие решения позволяют увидеть, как реагируют на них люди. Некоторые диалоги являются глубокими мыслями о нашем реальном мире.

Глубокая мысль, перекочевавшая из ME1 в ME2, мысль, которая сделала "Mass effect" уникальной игрой в моих глазах. В ME1 она была произнесена Властелином (Sovereign), теперь Легионом (Legion).

Шепард: Некоторые из гетов (Geth) последовали за Властелином. "Еретики".
Легион: Еретики приняли их технологии. Старые Машины [Пожинатели (Reapers)] предложили нам наше будущее.
Геты достигнут сами своего будущего.
Шепард: Есть ли разница, каким путём достаются технологии?
Легион: Технологии не прямая линия. Существует много путей для достижения одной и той же цели. Принятие чужого пути скрывает от тебя другие пути достижения.
Назара -- Властелин -- сам сказал это:
"Ваша цивилизация основана на технологии ретрансляторов массы (Mass relays). Нашей технологии. Используя её, ваше общество развивается путём, выбранным нами".

Принятие чужого пути скрывает от тебя другие пути достижения.
Вот почему человеку следует познавать суть вещей, если он хочет не только следовать и верить, а руководить и понимать.

Ваша цивилизация основана на технологии ретрансляторов массы (Mass relays). Нашей технологии. Используя её, ваше общество развивается путём, выбранным нами.
Мы живём в мире правил, созданных другими. Таким образом, мы развиваемся по пути, выбранному ими. Это более продвинутое состояние рабства - скрытое. Вы живёте, вы работаете и думаете, что это жизнь. Но небольшая группа людей владеет огромными компаниями, они могут позволить себе почти всё в этой жизни, они современные короли. Мы развиваемся по пути, выбранному ими...

понедельник, 1 февраля 2010 г.

Does an incorrect environment force you to an incorrect behaviour?

Today I understood my grudge against Delphi IDE and Object Pascal in general (I'm forced to use Delphi 7 at work).
One of my Delphi applications is Switch management GUI which looks like this:

The IP list is rendered within cxGrid component from DevExpress. It consists of two columns - row number and IP. I wanted to implement copying (WM_COPY) of the second column value only, but cxGrid does not allow this, because it copies the whole line, all the columns.
I did not implement handling of Ctrl+C, because there exist another standard shortcut for copying things in Windows - Ctrl+Insert. So handling concrete key bindings is wrong.
There's WM_COPY Windows message. Unfortunately, the cxGrid intercepts these messages, so I have no opportunity to handle it myself.
So I has to do one of the two bad things:
1) handle concrete key binding;
2) obey cxGrid limitation.
I chose the latter of two evils: I hid the first column. Now copying of the whole cxGrid line only copies one column value. At the same time I screwed the functionality up.

I saw the same bad pattern in Object Pascal, of which many people talked about already: interface and implementation within a single (!) file, call back functions on events, etc.. I wish I could use Qt4.

Thus I came to a question: "Does an incorrect environment force you to an incorrect behaviour?"
I'm forced to follow bad coding style, how does that affect me? Does it make my coding bad too? Does it corrupt my judgement?
I think yes. That makes me want to quit this job.

--- RU ---

Влияет ли неверное окружение к принятию неверных решений?

Сегодня я понял своё неприятие Delphi IDE и Object Pascal в принципе (я вынужден использовать Delphi 7 на работе).
Одно из моих приложений - ГУИ управления свитчами - выглядит следующим образом:

Список IP выводится в компоненте cxGrid от DevExpress. Он состоит из двух колонок - номер строки и IP. Я хотел реализовать копирование (WM_COPY) значения лишь во втором столбце, но cxGrid не позволяет это сделать, т.к. копирует всю строку, т.е. значения в обоих колонках.
Я не реализовал отлов Ctrl+C, т.к. существует ещё одно стандартное сочетание клавиш для копирования в Windows - это Ctrl+Insert. Поэтому ловить конкретные сочетания плохо.
Существует сообщение Windows WM_COPY. К сожалению, cxGrid перехватывает эти сообщения, поэтому я не могу переопределить его.
Приходится выбирать из двух неверных вещей:
1) ловить конкретные сочетания клавиш;
2) смириться с ограничениями cxGrid.
Я выбрал второе из зол: скрыл первый столбец. Теперь копирование всей строки cxGrid лишь копирует значение одной колонки. В то же время, я ухудшил функциональность.

Ту же неверную схему я наблюдаю и в Object Pascal, о которой уже говорили многие: интерфейс и реализация в пределах одного (!) файла, обратный вызов (callback) на события и т.п.. Жаль, что я не могу использовать Qt4.

Таким образом я пришёл к вопросу: "Влияет ли неверное окружение к принятию неверных решений?" Я вынужден следовать неверному стилю написания кода, как это влияет на меня? Делает ли это мой стиль написания кода неверным тоже? Искажает ли это мои суждения?
Думаю, да. Это вызывает у меня желание покинуть работу.

понедельник, 25 января 2010 г.

Avatar

On the 24th of January I've watched James Cameron's "Avatar" in 3D at "ДК Москва", a local movie theater.
Unfortunately, due to my bad eyesight I could not appreciate 3D effects, but I did appreciate some of the movie ideas.
The movie distinctly displayed the world of unity where every creature takes its part in the planet's life. I've met similar concept in Isaac Azimov's "Foundation" series.
I liked the idea of those flying creatures that you have to tame to fly on. It makes clear that the world is pretty complete, you don't need to fight it to live in, instead, you should learn how to live with it. As you learn the world you become more skilled and can tame higher level creatures like that big read flying one.
I think this is a hint for ourselves: don't fight the nature, but instead, learn it and live with it, and you may gain much higher level abilities than you would otherwise.
The other thing from the same topic sounded from the avatar that said: "Look at those people from the sky, they haven't left any green on their own planet and gonna do the same to us". That's painfully true. We traded something more precious for comfort, but I don't know what yet.
Finally, the last thought I had after watching the movie was that of the main character. When you understand something others don't understand, you're left all alone and isolated. They may even become your enemies.
So I can say "Avatar" is a great movie with great thoughts. Other people will surely find other ideas as well, because everyone sees what he wants to see :)

вторник, 25 августа 2009 г.

DPI independent Delphi application (problem with large fonts)

When run-time DPI varies from design-time DPI you usually get a messed up GUI with Delphi.
For example, I develop at 150 DPI:
If user has the same DPI everything looks fine:
When user uses a smaller DPI, e.g., 96 DPI, everything is messed up:
When user has a larger DPI, e.g., 200 DPI, everything is messed up again:
Articles on the web suggest to use ScaleBy procedure, Scale property, or PixelsPerInch property in various combinations.
If you set TForm.Scale to true, Delphi does scale some controls for you, but not all of them. For example, it scales TButton, TEdit, TPanel, but does not scale TForm, TPageControl. There's one simple trick to fix that.
Suppose you want to put TEdit on TForm and have it look good with any DPI.
1. Set TForm.Scale property to true.
2. Put TPanel on top of TForm and make it occupy the whole form, DO NOT alter the Align property, you MUST have it set to alNone.
3. Put TEdit on top of TPanel and place it as you would place it on TForm.
4. In TForm's constructor (or OnCreate procedure) do the following:
// DPI fix begin
ClientWidth := TPanel.ClientWidth;
ClientHeight := TPanel.ClientHeight;
TPanel.Align := alClient;
// DPI fix end

Delphi scales TPanel correctly, and TForm keeps the design time size. That's why we make TForm have TPanel's size.
Then we expand TPanel to occupy the whole TForm as it was intended at design time.
That's all. Just 3 lines of code.

Now when user has 96 DPI:
When user has 200 DPI:
Source code of the example for Delphi7:

Unit1.pas:
unit Unit1;

interface

uses
Classes,
ComCtrls,
Controls,
ExtCtrls,
Forms,
StdCtrls;

type
TForm1 = class(TForm)
Panel1: TPanel;
Edit1: TEdit;
PageControl2: TPageControl;
TabSheet1: TTabSheet;
TabSheet2: TTabSheet;
Panel2: TPanel;
Edit2: TEdit;
PageControl1: TPageControl;
TabSheet3: TTabSheet;
Panel3: TPanel;
TabSheet4: TTabSheet;
Edit3: TEdit;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
// DPI fix begin
ClientWidth := Panel1.ClientWidth;
ClientHeight := Panel1.ClientHeight;
Panel1.Align := alClient;
Panel2.Align := alClient;
Panel3.Align := alClient;
// DPI fix end
end;

end.


Unit1.dfm:
object Form1: TForm1
Left = 317
Top = 190
Width = 588
Height = 339
Anchors = [akLeft, akTop, akRight, akBottom]
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -17
Font.Name = 'Arial'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
PixelsPerInch = 150
TextHeight = 19
object Panel1: TPanel
Left = 0
Top = 0
Width = 580
Height = 305
BevelOuter = bvNone
TabOrder = 0
DesignSize = (
580
305)
object Edit1: TEdit
Left = 8
Top = 8
Width = 564
Height = 27
Anchors = [akLeft, akTop, akRight]
TabOrder = 0
Text = 'Edit1'
end
object PageControl2: TPageControl
Left = 8
Top = 40
Width = 561
Height = 257
ActivePage = TabSheet1
Anchors = [akLeft, akTop, akRight, akBottom]
TabOrder = 1
object TabSheet1: TTabSheet
Caption = 'TabSheet1'
object Panel2: TPanel
Left = 4
Top = 4
Width = 541
Height = 205
BevelOuter = bvNone
TabOrder = 0
DesignSize = (
541
205)
object Edit2: TEdit
Left = 8
Top = 8
Width = 525
Height = 27
Anchors = [akLeft, akTop, akRight]
TabOrder = 0
Text = 'Edit2'
end
object PageControl1: TPageControl
Left = 8
Top = 48
Width = 525
Height = 148
ActivePage = TabSheet3
Anchors = [akLeft, akTop, akRight, akBottom]
TabOrder = 1
object TabSheet3: TTabSheet
Caption = 'TabSheet1'
object Panel3: TPanel
Left = 0
Top = 0
Width = 513
Height = 113
BevelOuter = bvNone
TabOrder = 0
DesignSize = (
513
113)
object Edit3: TEdit
Left = 8
Top = 8
Width = 497
Height = 27
Anchors = [akLeft, akTop, akRight]
TabOrder = 0
Text = 'Edit3'
end
end
end
object TabSheet4: TTabSheet
Caption = 'TabSheet2'
ImageIndex = 1
end
end
end
end
object TabSheet2: TTabSheet
Caption = 'TabSheet2'
ImageIndex = 1
end
end
end
end

Note that my form is designed at 150 DPI so it will open distorted in your IDE if you use other DPI value. This article talks about run time DPI fix only :)

пятница, 14 ноября 2008 г.

Cisco Raw Data Record format

PRELUDE:

Recently the company I work at bought SCE which reports data throught Netflow v9. Though, in the other docs the SCE is said not to support Netflow v9. So we decided to catch RDRs and convert it to Netflow v5.
I was disappointed that the Raw Data Records: Formats and Field Contents document didn't contain full format description of RDR. It misses the main point: it doesn't tell you how the fields are layed out after you meet certain TAG.
Hopefully, we found a man who have already done RDR to Netflow v5 converter and asked him to help us out with RDR format. He sent us his RDR to Netflow v5 converter which I was observing. When I found out the RDR layout I was once again disappointed, because the first time I tried to catch and read RDRs, I used plain C structures.
For example, Transaction usage RDR contains almost all we need for a Netflow v5 packet. So I used
struct TUR {
char *subscriberID;
unsigned short packageID;
int serviceID;
- - - -
};

When thinking how they could send strings I assumed they simply send zero terminated strings like C does. That was false.

TOPIC:

GCC typedefs I use:
//! Typedef for signed 8-bit integer
typedef signed char s8;
//! Typedef for signed 16-bit integer
typedef signed short s16;
//! Typedef for signed 32-bit integer
typedef signed int s32;
//! Typedef for unsigned 8-bit integer
typedef unsigned char u8;
//! Typedef for unsigned 16-bit integer
typedef unsigned short u16;
//! Typedef for unsigned 32-bit integer
typedef unsigned int u32;


Every RDR field has the following format:
struct RDRField {
u8 type; // Field type
u32 size; // Field size
void *data;
};


Every RDR packet has the following format (RDRHeader format is unknown to me):
struct RDRPacket {
RDRHeader header; // sizeof(RDRHeader) == 20?
u32 tag; // Transaction usage, Subscriber, etc.
u8 fieldsNb; // Number of fields following (25 for TUR, 12 for SUR, etc.)
RDRField *fields;
};


For example, STRING field format is this:
struct STRING {
u8 type; // 0x29
u32 length;
char *str;
};

PACKAGE_ID:
struct PACKAGE_ID {
u8 type;
u32 size;
u16 value;
};

SERVICE_ID:
struct SERVICE_ID {
u8 type;
u32 size;
s32 value;
};

And so on.
Type and size are useful probably only for STRING fields to determine their lengths. Other fields don't need them really.
Note that most signed and unsigned 32-bit integers are in big endian (for example, a field's u32 size).

пятница, 26 сентября 2008 г.

Filesystem's system space size: ReiserFS > NTFS > Ext3





PRELUDE:

Recently I bought the second 750G hard drive Seagate with 32M cache. The first one was 750G Western digital with 16M cache. I bought it because I was out of space because I kept all I have on hard drive, rather than kept it on DVDs, because I share data with other users (local P2P atm).
So I decided to use the old Western digital as data one to keep music, movies, install files and all that is mostly read-only accessed thus giving my old hard drive a break after running for over half a year mostly 24h a day. So I went on copying data from old hard drive to the new one. First I found out that the disk with 32M cache is about 2-4 times faster on writing! So that's only sane it is used for system read-write. When I backed up everything I decided I will have single partition on the old hard drive for data. I was wondering which filesystem to choose. As a Linux user, I like ReiserFS as it is faster than Ext3 (while Ext4 is not yet out atm). But as a sane person I know I need to access the data from Windows too (playing games). First, I thought to use tools like Ext2FS for Windows and ReiserFS tool to access either volume from Windows. Both sucked too much. Ext2 one couldn't deal with Russian language, though I tried cp866, cp1251, utf-8, nothing helped. And ReiserFS one only works in cmd.exe. So back to old good NTFS, thanks ntfs-3g driver is now shipped by default with Slackware (distro I use since 10.0).

TOPIC:

Choosing among the three filesystems gave me some interesting results on the amount of system data they require to work. At the top you can see images with the results. It was really disgusting to know Ext3 eats about 1.5% of your space (which results in 11G of literally wasted space here) just to keep files. While NTFS and ReiserFS both eat under 100M of space, about 0.12% and 0.08% respectively. Notice, that ReiserFS eats about 1.6 times less than NTFS. I didn't know ReiserFS also rules in the space too :)

Though, the ReiserFS4 was sabotaged: http://linuxhelp.150m.com/jews/saboteurs.htm (in flavor of Ext4?)

вторник, 22 июля 2008 г.

Theading, Multitheaded game engine

Multithreaded Game Engine Architectures:

http://www.gamasutra.com/features/20060906/monkkonen_01.shtml

Threading 3D Game Engine Basics:

http://www.gamasutra.com/features/20051117/gabb_01.shtml

POSIX Threads Programming (good article to get understanding what thread is):

https://computing.llnl.gov/tutorials/pthreads/