Цитата Сообщение от Oleg N. Cher Посмотреть сообщение
Как работать из OMSI Pascal с бинарными файлами?
Насколько мне помнится, должно проходить что то типа
Код:
  TYPE BYTE  =0..255; /* не помню все встроенные типы, если вдруг такого нет */

  BINARY = FILE OF BYTE;
Дальше пример не из RT, а из RSX, но насколько мне помнится, в OMSI всё было очень похоже
С ходу программы, которая работала бы без буфера - не нашел. А с двоичными файлами и буфером:
Код:
PROGRAM SYSTEM_GENERATION;

  CONST
    BUFF_LAST = 377B;

        (* NEXT CONSTANT - FROM FILE RTS.MAC,
           ( ALSO, MODULE PDP11 CONTAIN IT )   *)

    INITIAL_START_ENTRY        = 452B;
    INITIAL_START_STACK_BOTTOM = 454B;
    INITIAL_START_STACK_LIMIT  = 456B;
    LOADER_INFO                = 460B;

  TYPE
    CARDINAL  =0..65535;

    FLAG_TYPE =(ENTRY_POINT_FLAG,
                CODE_FLAG,
                LINKER_TABLE_FLAG,
                DEBUGGER_TABLE_FLAG,
                OLD_LOAD_KEY_FLAG,
                NEW_LOAD_KEY_FLAG,
                FIRST_FREE_LOC_FLAG,
                OLD_FIRST_FREE_LOC_FLAG,
                MAX_FLAG);

    FLAG_SET  =SET OF FLAG_TYPE;

    FILE_NAME =PACKED ARRAY [1..35] OF CHAR;

    BLOCK     =0..BUFF_LAST;

    BIG_BUFFER=ARRAY [BLOCK] OF CARDINAL;

    WORK      =FILE OF BIG_BUFFER;

    DOUBLE    =ARRAY [0..1] OF CARDINAL;

  VAR
    FOUND                   : FLAG_SET;
    FLAG                    : FLAG_TYPE;

    WHERE,
    WORD,
    NBYTES,
    I,
    X                       : CARDINAL;

    LOD_NAME,
    RTS_NAME,
    TSK_NAME                : FILE_NAME;

    LOD_FILE,
    RTS_FILE,
    TSK_FILE                : WORK;

    EOF_LOD_FILE            : BOOLEAN;

    CH                      : CHAR;

    CHECK_SUM               : CARDINAL;
    BUFFER_R                : BIG_BUFFER;
    INDEX_R,
    LIMIT_R                 : BLOCK;

    SYSTEM_ENTRY_POINT_VALUE: CARDINAL;
    SYSTEM_LOAD_KEY_VALUE   : CARDINAL;
    OLD_FREE_LOC            : CARDINAL;
    FIRST_FREE_LOC          : CARDINAL;

    BUFFER_W                : BIG_BUFFER;
    INDEX_W,
    CURRENT_BLOCK,
    LIMIT_W                 : CARDINAL;

    LIMIT_RTS               : CARDINAL;
    RTS_BLOCK               : CARDINAL;
    EOF_RTS_FILE            : BOOLEAN;

  PROCEDURE EXITST(I: INTEGER ); EXTERNAL;

  FUNCTION FLGTYP(WORD: CARDINAL): FLAG_TYPE; EXTERNAL;

  PROCEDURE INIT_TTIO;
  BEGIN
    IF INPUT^ <> ' ' THEN
      REPEAT
        READ(CH)
      UNTIL CH = ' ';
  END (* INIT_TTIO *);

  PROCEDURE HALT(I: CARDINAL);
  BEGIN
    CASE I OF
      1:  WRITELN('LOD INPUT FILE HAS WRONG FORMAT');
      2:  WRITELN('NO ENTRY POINT BLOCK FOUND ON LOD INPUT FILE');
      3:  WRITELN('NO NEW KEY BLOCK FOUND ON LOD INPUT FILE');
      4:  WRITELN('NO FIRST FREE LOC BLOCK FOUND ON LOD INPUT FILE');
      5:  WRITELN('SINTAX ERROR IN FILE NAME');
      6:  WRITELN('EOF REACHED ON LOD INPUT FILE');
      7:  WRITELN('CHECK. SUMM ERROR ON LOD INPUT FILE');
      8:  WRITELN('BOTH PARTS OF SYSTEM TRY TO OCCUPY SAME LOCATION');
      9:  WRITELN('EOF REACHED ON RTS INPUT FILE');
     10:  WRITELN('NO OLD FIRST FREE LOC BLOCK FOUND ON LOD INPUT FILE');
     ELSE WRITELN('UNKNOWN ERROR')
    END;
    EXITST(4)
  END (* HALT *);

  PROCEDURE READ_FILE_NAME(VAR F_N: FILE_NAME;
                           VAR S  : BOOLEAN;
                           VAR D  : BOOLEAN   );

    VAR
      I: INTEGER;

  BEGIN
    FOR I:=1 TO 35 DO F_N[I]:=CHR(0);
    I:=0;
    S:=FALSE;
    D:=FALSE;

    REPEAT
      I:=I+1;
      READ(F_N[I]);
      IF F_N[I] = ' ' THEN BEGIN
        IF EOLN AND (I=1) THEN D:=TRUE;
        I:=I-1
      END;
    UNTIL EOLN OR EOF OR D OR (I>=34);
    IF EOF THEN EXITST(0);
    IF EOLN AND (I<=34) THEN S:=TRUE;
    IF EOLN OR (I>=34)  THEN READLN;
  END (* READ_FILE_NAME *);

(*-------------------rabota s LOD-fajlom--------------------*)

  PROCEDURE READ_SECTOR;
  BEGIN
    BUFFER_R:=LOD_FILE^;
    GET(LOD_FILE);
    INDEX_R:=0;
    LIMIT_R:=BUFFER_R[BUFF_LAST];
    IF LIMIT_R=0 THEN EOF_LOD_FILE:=TRUE;
  END;

  PROCEDURE READ_AND_CHECK;

    VAR
      X : CARDINAL;

  BEGIN
    IF EOF_LOD_FILE THEN
      HALT(6)
    ELSE BEGIN
      X:=BUFFER_R[INDEX_R];
      INDEX_R:=INDEX_R+1;
      IF INDEX_R = LIMIT_R THEN
        IF LIMIT_R = BUFF_LAST THEN
          READ_SECTOR
        ELSE
           EOF_LOD_FILE := TRUE;
      IF CHECK_SUM <> X THEN HALT(7)
    END;
  END (* READ_AND_CHECK *);

  PROCEDURE READ_WORD(VAR X:CARDINAL);

    BEGIN
      IF EOF_LOD_FILE
      THEN HALT(6)
      ELSE
        BEGIN
          X := BUFFER_R[INDEX_R];
          INDEX_R := INDEX_R + 1;
          IF INDEX_R = LIMIT_R
          THEN
            IF LIMIT_R = BUFF_LAST
            THEN READ_SECTOR
            ELSE EOF_LOD_FILE :=TRUE;
          CHECK_SUM := CHECK_SUM + X
        END;
    END;

  PROCEDURE SKIP_RECORD( COUNT : CARDINAL );

    VAR
      X : CARDINAL;

    BEGIN
      WHILE COUNT > 0 DO BEGIN
        READ_WORD(X);
        COUNT := COUNT - 1
      END
    END;

  PROCEDURE START_READ;

    BEGIN
      CHECK_SUM := 0;
      EOF_LOD_FILE := FALSE;
      READ_SECTOR
    END;

  PROCEDURE OPEN_READ;

    VAR
      SUCCESS,
      DEFAULT  : BOOLEAN;

    BEGIN
      WRITE('MODULA-2 PROGRAM LOAD FILE >');
      READ_FILE_NAME(LOD_NAME,SUCCESS,DEFAULT);
      IF SUCCESS
      THEN
        IF DEFAULT
        THEN RESET(LOD_FILE,'SY:MOD.LOD/SE/RO')
        ELSE RESET(LOD_FILE,LOD_NAME,'SY:MOD.LOD/SE/RO')
      ELSE
        HALT(5);
      START_READ
    END;

  PROCEDURE RE_OPEN_READ;

    BEGIN
      RESET(LOD_FILE);
      START_READ
    END;

  PROCEDURE CLOSE_READ;

    BEGIN
      CLOSE(LOD_FILE)
    END;

(*---------------------rabota s TSK-fajlom---------------*)

  PROCEDURE WRITE_SECTOR;

    VAR
      I : BLOCK;

    BEGIN
      SEEK(TSK_FILE,CURRENT_BLOCK);
      TSK_FILE^ := BUFFER_W;
      PUT(TSK_FILE);
      INDEX_W := 0;
      CURRENT_BLOCK := CURRENT_BLOCK + 1
    END;

  PROCEDURE WRITE_WORD( W : CARDINAL );

    VAR
      I : BLOCK;

    BEGIN
      IF W <> 0
      THEN
        IF BUFFER_W [INDEX_W] <> 0
        THEN
          HALT(8)
        ELSE
          BUFFER_W[INDEX_W] := W;
      IF INDEX_W < BUFF_LAST
      THEN
        INDEX_W := INDEX_W + 1
      ELSE
        BEGIN
          WRITE_SECTOR;
          IF LIMIT_W < CURRENT_BLOCK
          THEN
            BEGIN
              FOR I := 0 TO BUFF_LAST DO BUFFER_W [I] := 0;
              LIMIT_W := CURRENT_BLOCK
            END
          ELSE
            BEGIN
              BUFFER_W := TSK_FILE^;
              GET(TSK_FILE)
            END
        END
    END;

  PROCEDURE WRITE_ZERO_LABEL_BLOCK;

    VAR
      I : BLOCK;

    BEGIN
      FOR I := 0 TO BUFF_LAST DO BUFFER_W[I] := 0;
      WRITE_SECTOR;
      WRITE_SECTOR
    END;

  PROCEDURE START_WRITE( WHERE : CARDINAL );

    VAR
      I : CARDINAL;

    BEGIN
      CURRENT_BLOCK := ( WHERE DIV (( BUFF_LAST+1)*2)) + 3;
      INDEX_W       := ( WHERE DIV 2 ) MOD ( BUFF_LAST+1 );
      IF LIMIT_W < CURRENT_BLOCK
      THEN
        BEGIN
          FOR I := 0 TO BUFF_LAST DO BUFFER_W [I] := 0;
          REPEAT
            LIMIT_W := LIMIT_W + 1;
            IF LIMIT_W < CURRENT_BLOCK
            THEN
              BEGIN
                SEEK(TSK_FILE,LIMIT_W);
                TSK_FILE^ := BUFFER_W;
                PUT(TSK_FILE)
              END;
          UNTIL LIMIT_W = CURRENT_BLOCK
        END
      ELSE
        BEGIN
          SEEK(TSK_FILE,CURRENT_BLOCK);
          BUFFER_W := TSK_FILE^
        END
    END;

  PROCEDURE END_WRITE;

    BEGIN
      WRITE_SECTOR
    END;

  PROCEDURE OPEN_WRITE;

    VAR
      I     : INTEGER;
      POINT : BOOLEAN;

    BEGIN
      FOR I := 1 TO 35 DO TSK_NAME[I] := CHR(0);
      I := 1;
      WHILE ( LOD_NAME[I] <> CHR(0) ) AND
            ( LOD_NAME[I] <> '.'    ) AND
            ( LOD_NAME[I] <> ';'    ) AND
            (       I <=  34        )     DO BEGIN
        TSK_NAME[I] := LOD_NAME[I];
        I := I + 1
      END;
      IF I = 1
      THEN
        REWRITE(TSK_FILE,'SY:MOD.TSK/SE/NOBL/RW')
      ELSE
        BEGIN
          LOD_NAME[I] := '.';
          LOD_NAME[I+1] := 'T';
          LOD_NAME[I+2] := 'S';
          LOD_NAME[I+3] := 'K';
          REWRITE(TSK_FILE,TSK_NAME,'SY:MOD.TSK/SE/NOBL/RW')
        END;
      INDEX_W       := 0;
      LIMIT_W       := 1;
      CURRENT_BLOCK := 1
    END;

  PROCEDURE CLOSE_WRITE;

    BEGIN
      CLOSE(TSK_FILE)
    END;

  PROCEDURE TRANSFER_RECORD( C,A : CARDINAL );

    VAR
      X : CARDINAL;

    BEGIN
      START_WRITE(A);
      WHILE C > 0 DO BEGIN
        READ_WORD (X);
        WRITE_WORD(X);
        C := C - 1
      END;
      END_WRITE
    END;

(*--------------------rabota s RTS--------------------*)

  PROCEDURE READ_RTS_SECTOR;

    BEGIN
      RTS_BLOCK := RTS_BLOCK + 1;
      SEEK(RTS_FILE,RTS_BLOCK);
      BUFFER_R := RTS_FILE^;
      GET(RTS_FILE);
      INDEX_R := 0
    END;

  PROCEDURE READ_RTS_WORD( VAR X : CARDINAL);

    BEGIN
      IF EOF_RTS_FILE
      THEN
        HALT(9)
      ELSE
        BEGIN
          X := BUFFER_R[INDEX_R];
          IF RTS_BLOCK < LIMIT_RTS DIV ((BUFF_LAST+1)*2) + 3
          THEN
            IF INDEX_R < BUFF_LAST
            THEN
              INDEX_R := INDEX_R + 1
            ELSE
              READ_RTS_SECTOR
          ELSE
            IF INDEX_R < ( LIMIT_RTS DIV 2 ) MOD ( BUFF_LAST+1 )
            THEN
              INDEX_R := INDEX_R + 1
            ELSE
               EOF_RTS_FILE :=TRUE
        END
    END;


  PROCEDURE MERGE_RTS;

    VAR
      I  : BLOCK;
      X  : CARDINAL;
      F1 : CARDINAL;
      F2 : CARDINAL;

    BEGIN
      FOR I := 0 TO BUFF_LAST DO BUFFER_W[I] := BUFFER_R[I];
      LIMIT_RTS := BUFFER_R [5];
      CURRENT_BLOCK := 1;
      WRITE_SECTOR;
      START_WRITE(0);
      READ_RTS_SECTOR;  (* 2 BLOCK *)
      READ_RTS_SECTOR;  (* 3 BLOCK *)
      REPEAT
        READ_RTS_WORD(X);
        WRITE_WORD(X);
      UNTIL EOF_RTS_FILE;
      END_WRITE;

      CURRENT_BLOCK := 1;
      SEEK(TSK_FILE,CURRENT_BLOCK);
      BUFFER_W := TSK_FILE^;
      IF (FIRST_FREE_LOC MOD 100B) = 0 THEN FIRST_FREE_LOC := FIRST_FREE_LOC+1;
      F1 := ( FIRST_FREE_LOC DIV 100B )*100B + 77B;
      F2 := ( FIRST_FREE_LOC + 77B ) DIV 100B;

      (* HIGHEST VIRT. ADR., MAPPED BY ADR. WINDOW 0    *)

      BUFFER_W [5] := F1;

      (* HIGHEST TASK VIRTUAL ADDRESS (=BUFFER_W[5])    *)

      BUFFER_W [6] := F1;

      (* TASK LOAD SIZE IN 64(10)-WORDS BLOCKS (SIZE OF THE ROOT SEGMENT) *)

      BUFFER_W [7] := F2;

      (* TASK MAXIMUM SIZE IN 64(10)-WORDS BLOCKS. = THE SIZE OF THE
          ROOT SEGMENT + ANY ADDITIONAL PHYSICAL MEMORY, NEEDED TO CONTAIN
          TASK OVERLAYS                                                     *)

      BUFFER_W [8] := F2;

      (* TASK EXTENSION - UP TO 64 KB                   *)

      BUFFER_W [352B DIV 2] := 2000B-F2;

      (* RELATIVE BLOCK NUMBER OF R/O IMAGE             *)

      BUFFER_W [364B DIV 2] := FIRST_FREE_LOC DIV (( BUFF_LAST+1)*2) + 4;

      TSK_FILE^ := BUFFER_W;
      PUT(TSK_FILE);

      CURRENT_BLOCK := 3;
      SEEK(TSK_FILE,CURRENT_BLOCK);
      BUFFER_W := TSK_FILE^;

      (* INITIAL STACK POINTER *)

      BUFFER_W [8] := 0;        (* WE ARE USED ALL 64 KB MEMORY *)

      TSK_FILE^ := BUFFER_W;
      PUT(TSK_FILE)
    END;

  PROCEDURE OPEN_RTS_READ;

    VAR
      S,
      D : BOOLEAN;

    BEGIN
      WRITE(CHR(15B));
      WRITELN('   FILE OF RUN TIME SYSTEM OR');
      WRITE  ('<CR> FOR DEFAULT MS:[1,54]RTS.TSK:');
      READ_FILE_NAME(RTS_NAME,S,D);
      IF S
      THEN
        IF D
        THEN
          RESET(RTS_FILE,'MS:[1,54]RTS.TSK/RO/SE')
        ELSE
          RESET(RTS_FILE,RTS_NAME,'SY:[1,54]RTS.TSK/RO/SE')
      ELSE
        HALT(5);
      RTS_BLOCK := 0;
      READ_RTS_SECTOR;
      LIMIT_RTS := 177777B
    END;

  PROCEDURE CLOSE_RTS_READ;

    BEGIN
      CLOSE(RTS_FILE)
    END;

  PROCEDURE WRITE_LUN_BLOCK;

    VAR
      I : CARDINAL;

    BEGIN
      CURRENT_BLOCK := 2;
      SEEK(TSK_FILE,CURRENT_BLOCK);
      FOR I := 1  TO BUFF_LAST DO BUFFER_W [I] := 0;
      FOR I := 1  TO 16 DO BUFFER_W [2*I-2] := 54523B;
      FOR I := 19 TO 20 DO BUFFER_W [2*I-2] := 54523B;
      BUFFER_W [2*17-2] := 44524B;
      BUFFER_W [2*18-2] := 44524B;
      WRITE_SECTOR
    END;

  PROCEDURE WRITE_COMMUNICATION_AREA;

    BEGIN
     START_WRITE(INITIAL_START_ENTRY);
     WRITE_WORD(SYSTEM_ENTRY_POINT_VALUE);
     END_WRITE;
     START_WRITE(INITIAL_START_STACK_BOTTOM);
     WRITE_WORD(0);     (* USE ALL MEMORY *)
     END_WRITE;
     START_WRITE(INITIAL_START_STACK_LIMIT);
     WRITE_WORD (FIRST_FREE_LOC);
     END_WRITE;
     START_WRITE(LOADER_INFO);
     WRITE_WORD (SYSTEM_LOAD_KEY_VALUE);
     END_WRITE;
    END;

(*---------------------M A I N---------------------*)
BEGIN
  INIT_TTIO;
  OPEN_READ;
  OPEN_WRITE;
  WRITE_ZERO_LABEL_BLOCK;

  FOUND := [];
  WHILE NOT EOF_LOD_FILE DO BEGIN
    READ_WORD(X);
    FLAG := FLGTYP(X);
    READ_WORD(NBYTES);
    READ_WORD(WHERE);
    IF FLAG >= MAX_FLAG THEN HALT(1);
    FOUND := FOUND+[FLAG];
    CASE FLAG OF
      ENTRY_POINT_FLAG        : SYSTEM_ENTRY_POINT_VALUE := WHERE;
      NEW_LOAD_KEY_FLAG       : SYSTEM_LOAD_KEY_VALUE    := WHERE;
      OLD_FIRST_FREE_LOC_FLAG : OLD_FREE_LOC             := WHERE;
      FIRST_FREE_LOC_FLAG     : FIRST_FREE_LOC           := WHERE;
    ELSE
    END;
    IF FLAG = CODE_FLAG
    THEN TRANSFER_RECORD((NBYTES-6) DIV 2, WHERE)
    ELSE SKIP_RECORD    ((NBYTES-6) DIV 2       );
    READ_AND_CHECK
  END;
  IF NOT (ENTRY_POINT_FLAG IN FOUND)        THEN HALT(2);
  IF NOT (NEW_LOAD_KEY_FLAG IN FOUND)       THEN HALT(3);
  IF NOT (OLD_FIRST_FREE_LOC_FLAG IN FOUND) THEN HALT(10);
  IF NOT (FIRST_FREE_LOC_FLAG IN FOUND)     THEN HALT(4);
  TRANSFER_RECORD(0,FIRST_FREE_LOC-1);
  CLOSE_READ;
  OPEN_RTS_READ;
  MERGE_RTS;
  CLOSE_RTS_READ;
  WRITE_COMMUNICATION_AREA;
  WRITE_LUN_BLOCK;
  CLOSE_WRITE;
  WRITELN('END SYSTEM GENERATION ');
END.