Turbo Pascal PopolonY2k's Framework

Page 3/5
1 | 2 | | 4 | 5

Par popolony2k

Hero (544)

Portrait de popolony2k

24-06-2016, 21:33

@rolandve my solution is very close to the prototype written by you in your last message. I have created a simple format to store the Turbo Pascal function/procedure and its initial address, so if you omit the starting address you want to execute the function, the address stored in the dll file will be used, is something closer to the BLOAD MSX BASIC command.

I need to fix some issues before releasing this feature.

[]'s
PopolonY2k

Par rolandve

Champion (372)

Portrait de rolandve

24-06-2016, 21:47

@Popolony2k,

Using fixed addresses in DLL's has the risk of overwriting existing code, but that risk always exist because the programmer doesn't know up-front what his last used byte will be. So if you want to play it safe, you better abuse the last 28KB of a 128 KB machine for example.

Do you also include version numbers in de library? That turned out to be a critical feature in debugging Smile

Did you btw make an equivalent routine for inkey$? I wrote some code that crashes after compilation

function inkey : char;
var
    ch : char;
begin;
      if KeyPressed then
         Begin
           Read(Kbd,ch);
           inkey:=ch;
        end
     else
        inkey:=''';
end;

Result : Runtime Error 10 at Adress XXXX. TP Manual says that this error is character conversion related.
It doesn't make sense: read(kbd, ch); reads a character so using that return value should be possible.

Regards

Par Manuel

Ascended (19677)

Portrait de Manuel

24-06-2016, 22:33

Stuff like that should work. This is what is in a main menu I once wrote:

       IF KeyPressed THEN
       BEGIN
         Read(KBD,Key);
         CASE Key OF
              Sel: BEGIN VDP10:=(VDP10 XOR 2); WrtVDP(9,VDP10) END;
              Esc: Select:=3;
         END;
       END;

So, very similar...

Full code here: https://www.msx.org/downloads/games/dexterity/kink

Par rolandve

Champion (372)

Portrait de rolandve

24-06-2016, 23:38

Looks like the error is caused by assigning an empty character '' to a char.

Par Manuel

Ascended (19677)

Portrait de Manuel

24-06-2016, 23:58

I just assigned Null to it, aliased as follows:
CONST Esc=#27; Null=#00; Sel=#24; Ret=#13; Home=#11; Ins=#18; Del=#127; {Keys}

Par rolandve

Champion (372)

Portrait de rolandve

25-06-2016, 10:53

Thats what I did, if I can't assign emptiness, assign it to Null.

Par popolony2k

Hero (544)

Portrait de popolony2k

25-06-2016, 18:51

rolandve wrote:

@Popolony2k,

Using fixed addresses in DLL's has the risk of overwriting existing code, but that risk always exist because the programmer doesn't know up-front what his last used byte will be. So if you want to play it safe, you better abuse the last 28KB of a 128 KB machine for example.

Do you also include version numbers in de library? That turned out to be a critical feature in debugging Smile

@rolanve, in fact this solution is not an open solution for all existing languages in the MSX scenario. I'm just focusing in the Turbo Pascal "world" because when you export a function or procedure written in Turbo Pascal you will need take care about the runtime too, because the Turbo Pascal runtime should be loaded before if you're using functions/procedures from the turbo pascal runtime library.

But the loadable file library specification I have created is open and is something like described below:

Const      ctLibMaxSignature = 6;  { Signature size (ctLibMaxSignature + 1) }

Type TLibraryHdr = Record  { Loadable module file header specification (128 bytes record)}
  aSignature    : Array[0..ctLibMaxSignature] Of Char;   { Signature 7 bytes }
  nMinorVrs     : Byte;  { Module file minor version 1 byte }
  nMajorVrs     : Byte;  { Module file major version 1 byte }
  nNumEntries : Byte;  { Routines entries on file 1 byte }
  aFiller          : Array[0..117] Of Byte;  { Filler  118 bytes }
End;
 
Type TLibraryEntryName = String[50];     {Entry name definition }

Type TLibraryEntry = Record    { Loadable module file entry specification (128 bytes record) }
  strEntryName   : TLibraryEntryName;    { Entry name - routine name 51 bytes }
  nEntryAddress  : Integer;   { Entry default address 2 bytes }
  nEntrySize       : Integer;   { Routine size - 2 bytes }
  aFiller             : Array[0..72] Of Byte;  { Filler 73 bytes }
End; 

Questions about the risk of overwriting existing code, this must be considered by the programmer because we are talking about MSXDOS applications and this operating system don't have strong control about which memory has been used by its applications, except if you're using the memory mapper standard functions where you can reserve some pages for system applications, to be used for resident device drivers and so on.

Considering the MSXDOS operating system the programmer must to integrate the memory use with the loadable modules, because these technologies are independent (at least considering in my framework Smile ).

Loadable module in MSXDOS is a very complicated question because this operating system, different from FUZIX for example, has no architecture to support this feature, so my solution is very well integrated with the active process only, but the loadable module file specification is open and could be used with and in any existing languages for MSX.

rolandve wrote:

Did you btw make an equivalent routine for inkey$? I wrote some code that crashes after compilation

function inkey : char;
var
    ch : char;
begin;
      if KeyPressed then
         Begin
           Read(Kbd,ch);
           inkey:=ch;
        end
     else
        inkey:=''';
end;

Result : Runtime Error 10 at Adress XXXX. TP Manual says that this error is character conversion related.
It doesn't make sense: read(kbd, ch); reads a character so using that return value should be possible.

Regards

My inkey function is written below:

Function InKey : char;
var
    ch : char;
Begin;
      If( KeyPressed ) Then
         Begin
           Read( Kbd,ch );
           InKey:=ch;
        End
     Else
        InKey:=#0;
End;

Check the line where I'm setting :

InKey:=#0;

This is one of several ways to resolve the NULL question, if there's no keyboard response. In C and in the ASCII table this character (0 - zero) represents NULL and could be used here normally because we don't have keyboard input for the non-printable character #0 (NULL in the ASCII table), so using this return code doesn't affects the function results.

In your code you should to test the result of this function is is NULL, like :

  Var
       ch : Char;

Begin
  ch := Inkey;

  If( ch = #0 )  Then
    WriteLn( 'Is NULL')
  Else
    WriteLn( ch );

[]'s
PopolonY2k

Par rolandve

Champion (372)

Portrait de rolandve

25-06-2016, 20:20

Yup, memory allocation is the issue the programmer must worry about. Since there is no hardware memory protection the programmer has power to do everything wrong. Actually the mapper structure forces the programmer to consider memory as an issue. Just a malloc(20000*sizeof(int)) doesn't really work.

Whats the purpose of the aSignature field? The magic number that allows other program's to recognise the code? or do you intent to integrate a 7 byte MD5?

Have a nice weekend!

Par popolony2k

Hero (544)

Portrait de popolony2k

25-06-2016, 20:43

The aSignature filed is just a simple signature for a loadable module to be recognized.

Today this signature is POPLIB, so if this 7 bytes size field contains this content (POPLIB), it will be recognized as a valid loadable module for my framework implementation.

Today this specification is quite simple.

Have a nice weekend too. Smile

[]'s
PopolonY2k

Par raymond

Hero (653)

Portrait de raymond

09-06-2019, 08:17

Hello Popolon,

Do you have an update about the new version of your framework?

Page 3/5
1 | 2 | | 4 | 5