Page 1 of 1

WriteChar is ok, WriteLn not

Posted: Sun Nov 18, 2007 5:40 am
by Nils
Hi,

i want to program a Kernel in Pascal. There are two functions: WriteChar (print a char) and WriteLn (print strings):

Code: Select all

type 
  TScreen = Array[1..25, 1..80] of record
    c    : Char;
    attr : Byte;
  end;

Code: Select all

procedure WriteChar(c : Char);
begin
  Screen^[X, Y].c := c;
  inc(Y);
end;

procedure WriteLn(s : String);
var i : Integer;
begin
  for i := 1 to Length(s) do
    WriteChar(s[i]);
end;
If I would write a line like this one, there would be a "a" on the screen WriteChar('a');
If I would write WriteLn('a'); there would be nothing.

I found out, that there ist maybe a Problem with the string (s : String) or Length(s)/s.
If I would print s[1] on the screen, there would be also nothing. Length(s) is also wrong, because this code prints nothing:

Code: Select all

procedure WriteLn(s : String);
var i : Integer;
begin
  for i := 1 to Length(s) do
    WriteChar('a');
end;
But Length(s)+3 and there are 3 characters..

Have someone any idea, why WriteLn is not working ?

Maybe there is a mistake in following lines, but I found nothing:

Code: Select all

unit system;

interface

type
  ValSInt = LongInt;
  SizeInt = LongInt;

procedure FPC_INITIALIZEUNITS; compilerproc;
procedure FPC_DO_EXIT; compilerproc;
procedure fpc_shortstr_assign(len: longint; src, dst: pointer);
function fpc_shortstr_concat(const s1, s2 : ShortString) : ShortString; compilerproc;
function fpc_shortstr_to_shortstr(len : LongInt; const sstr : ShortString) : ShortString; compilerproc;

implementation

procedure FPC_INITIALIZEUNITS; alias: 'FPC_INITIALIZEUNITS'; compilerproc;
begin

end;

...

Posted: Sun Nov 18, 2007 6:16 am
by Laksen
Why don't you just use the generic fpc rtl? With a bit of fiddling you can use all the standard functions

Are your compilerproc's correct?

Posted: Sun Nov 18, 2007 6:19 am
by Dex
Try this:

Code: Select all

unit vgatxt;

interface

const
     C_Base=$000B8000;
     C_XSize=80;
     C_YSize=25;
     C_LENGTH=C_XSize*C_YSize;

     C_AT_BLACK=0;
     C_AT_BLUE=1;
     C_AT_GREEN=2;
     C_AT_CYAN=3;
     C_AT_RED=4;
     C_AT_MAGENTA=5;
     C_AT_YELLOW=6;
     C_AT_WHITE=7;
     C_crtc_adr =$3D4;


procedure C_Init;
procedure C_set_attribs(a:integer);
procedure C_set_colours(fg,bg:integer);
procedure C_scroll_up;
procedure C_scroll_down;
procedure C_clear;
procedure C_putchar(c:char);
function C_getchar:char;
procedure C_locate(x,y:longint);

function C_GetX:integer;
function C_GetY:integer;

implementation

uses includes, ports, interupts;

type
     vdu=packed array [1..C_LENGTH] of word;
     pvdu=^vdu;



var
     XPos,YPos:longint;
     Attribs:integer;
     screen:pvdu;

procedure setcursor;
var
        i:word;
begin
        i:=(xpos-1)+(ypos*C_XSize)-C_XSize;
        outb(14,C_crtc_adr);
        outb(i div 256, C_crtc_adr + 1);
        outb(15,C_crtc_adr + 0);
        outb(i and $ff,C_crtc_adr + 1);
end;

procedure C_clear;
var
     i:longint;
begin
     for i:=1 to C_LENGTH do
     begin
          screen^[i]:=$0720;
     end;
     XPos:=1;YPos:=1;
     setcursor;
end;

procedure C_Init;
var err:KRetCode;
        a:cardinal;
begin
     screen:=C_Base;
     C_clear;
     C_set_colours(C_AT_WHITE,C_AT_BLACK);
     setcursor;
     a:=inb_p($61);
     outb_p(a or $80,$61);
     outb(a,$61);
end;

procedure C_set_attribs(a:integer);
begin
     Attribs:=(a and 255)
end;

procedure C_set_colours(fg,bg:integer);
begin
     Attribs:=(bg and 15)*16 + (fg and 15)
end;

procedure C_scroll_up;
var
     i:longint;
begin
     for i:=C_XSize to C_LENGTH do screen^[i-C_XSize]:=screen^[i];
     for i:=(C_LENGTH-C_XSize)+1 to C_LENGTH do screen^[i]:=$20;
end;

procedure C_scroll_down;
var
     i:longint;
begin
     for i:=(C_LENGTH-C_XSize) downto 1 do screen^[i+C_XSize]:=screen^[i];
     for i:=1 to C_XSize do screen^[i]:=$20;
end;

procedure checkandscroll;
begin
     if XPos<1 then
     begin
          XPos:=C_XSize;
          YPos:=YPos-1
     end else if XPos>C_XSize then
     begin
          XPos:=1;
          YPos:=YPos+1
     end;
     if YPos<1 then
     begin
          YPos:=1;
          C_scroll_down
     end else if YPos>C_YSize then
     begin
          YPos:=C_YSize;
          C_scroll_up
     end;
     setcursor;
end;

procedure C_putchar(c:char);
var
     pos:longint;
     data:word;
begin
     if c=#13 then begin
             XPos:=1;
     end else if c=#10 then begin
             YPos:=Ypos+1;
     end else begin
             pos:=(YPos-1)*C_XSize+XPos;
             data:=ord(c)+256*attribs;
             screen^[pos]:=data;
             XPos:=XPos+1;
     end;

     checkandscroll;
end;

function C_getchar:char;
var
     pos:longint;
     data:word;
begin
     pos:=(YPos-1)*C_XSize+XPos;
     data:=screen^[pos];
     C_getchar:=char(data and $ff)
end;

function C_GetX:integer;
begin
     C_GetX:=XPos
end;

function C_GetY:integer;
begin
     C_GetY:=YPos
end;

procedure C_locate(x,y:longint);
begin
     if (x<1) then x:=1 else if (x>C_XSize) then x:=C_XSize;
     if (y<1) then y:=1 else if (y>C_YSize) then y:=C_YSize;
     XPos:=x;
     YPos:=y;
     setcursor;
end;


//initialization
//        C_init;

end.

Code: Select all

procedure readchar(params :PParameters);
begin
        params^[0]:=0;
        params^[1]:=cardinal(ord(inkey));
end;

procedure writechar(params :PParameters);
var
        c:char;
begin
        params^[0]:=0;
        c:=char(params^[1] and $ff);
        C_putchar(c);
end;
But inflater is the one to answer your ?.

Posted: Sun Nov 18, 2007 8:31 am
by Nils
I understood the code, but not the way to write a line. What is PParameters ?

Posted: Sun Nov 18, 2007 8:31 am
by inflater
Hi,
Dex wrote:But inflater is the one to answer your ?.
We-ell.. :oops: I try to do my best. :)

Try this code:

Code: Select all

type
  TScreen = Array[1..80, 1..25] of record
    c    : Char;
    attr : Byte;
  end; 

procedure WriteChar(c : Char);
begin
  Screen^[X, Y].c := c;
  inc(X);
end;
It seems that you've forgot to set the attribute; or (s: String) points to a invalid location in memory.
If even that doesn't work, try Dex's code.

Regards
inflater

Posted: Sun Nov 18, 2007 10:27 am
by LordMage
Well, I think the others tried to make things a little too complicated. If your writechar function works and you writeln function doesn't it is because arrays in programming begin with a 0 not a 1.

Code: Select all


procedure WriteLn(s : String); 
var i : Integer; 
begin 
  for i := 0 to (Length(s) -1) do 
    WriteChar(s[i]); 
end;


Posted: Sun Nov 18, 2007 11:48 am
by inflater
LordMage wrote:arrays in programming begin with a 0 not a 1
In Pascal, a standard String has on the 0th byte it's size (TString has max. 255 characters). The actual ASCII characters in the string are starting from 1st byte. So "Length(s)" can be replaced with "s[0]", but I don't think this will solve the problem... :(

Regards
inflater

Posted: Sun Nov 18, 2007 12:23 pm
by LordMage
okay, ignore my post then. I guess that shows how long it's been since I programmed with pascal. Haven't touched it since 1998.

Posted: Mon Nov 19, 2007 8:49 am
by Nils
I thought I would have implemented fpc_shortstr_assign, but it was not there.... I'm new with Pascal on Kernel-Dev (but I program with Pascal a long time). The functions of Dex are very helpful to find a good structure.

Thx to all :) !