Jump to content

apersson850

Members
  • Content Count

    1,063
  • Joined

  • Last visited

Posts posted by apersson850


  1. The principal is that any value check inside parenthesis will equate to either 0 (if false) or -1 (if true). Don't ask my why it's not 1, some weirdness in the interpreter...

    Not at all. Zero is zero, regardless of the system. If we look at 16 bits only, then not(0000H) = FFFFH. But in two complement notation, FFFFH = -1. Thus inverting all bits in zero returns minus one. This is true regardless of the number of bits, as long as we look at integers. It would not be true in the radix 100 floating point format used in the 99/4A, though.


  2. No, you don't need another library. But you need to tell the system where your library is. It's by default aware of the *SYSTEM.LIBRARY file, but that's all.

    You need to create a text file, which lists all other libraries you are using, so that the operating system can find them during runtime. If you create a file called *USERLIB.TEXT, and the content of that file is chesslib.code, then the index file is ready. *USERLIB.TEXT is the system's default user library index file. When you've done this, the system will know where to find the file which contains the library which holds the units your program needs.

    The *USERLIB.TEXT file may contain several lines, each referencing a different user library.

     

    It's also possible to create a user library index file with a different name, like sweden.text. Inside the file sweden.text you enter the same as in *USERLIB.TEXT above. But now your data isn't in the default library index file, so you need to tell the system where to look. The easiest way to do this is to type X (for eXecute) at the system prompt, then key in L=sweden.text. Now you've defined which index file to use, instead of *USERLIB.TEXT.

     

    Note that you must specify both the drive and the file name. *USERLIB.TEXT means that this file is on the system drive, normally the first one (#4: in the p-system, or DSK1 in the normal operating system). If that diskette's name is PSYS, then the names *USERLIB.TEXT, PSYS:USERLIB.TEXT and #4:USERLIB.TEXT are equivalent.

    You also have a default prefix drive, indicated by a colon. If you set the second drive to be the prefixed one, by typing X and then P=#5, and the diskette in the second drive is named PROJECT, then the file names HELLO.TEXT, #5:HELLO.TEXT, PROJECT:HELLO.TEXT and :HELLO.TEXT are equivalent.

     

    Page 105 in the Pascal compiler manual gives details about this.

     

    Feel free to ask questions. by all means! It's nice that somebody else discovers the p-system.


  3. Well, then that's why. Since scoreval is referred to in the interface section of movegen, it will be seen when phoenix is compiled. But since phoenix doesn't contain any uses scoreval declaration, this comes as a surprise to the compiler when phoenix is compiled.

     

    If you let phoenix explicitly use scoreval before it uses movegen, it will work. But that's unnecessary, actually even a bad choice, since phoenix doesn't need any direct access to scoreval. In movegen, place the uses scoreval declaration in the implementation section instead, and you'll get rid of the unnecessary direct link between phoenix and scoreval. At the same time, the compiler will not see the uses scoreval declaration when compiling phoenix, and thus will not care about where it's defined.


  4. Yes, back in those days when we used the real hardware only, I was fortunate enough to have a couple of friends who also had the p-code card in their computers. We exchanged a lot of ideas and work. The p-system is rather easy to use, but since it has quite a lot of features, it takes a while to become comfortable with them all.

     

    Here's a corresponding poke procedure in assembly language.

    SP      .EQU  10       ;Stack pointer in Pascal workspace is R10. Workspace at 8380H
            .PROC POKE,2   ;A procedure with two parameters
            MOV  *SP+,R0
            MOV  *SP+,*R0
            B    *R11
            .END
    

    This then requires the following declaration in your Pascal program.

    procedure poke(addr,value:integer); external;
    

    Compile the Pascal program, assemble the assembly program, run the linker to unite the two into one object code file and you're ready to run.​

    • Like 1

  5. Yes, poke could of course be implemented in assembly language, but there's no need to. You can use a variant record to accomplish the same thing without leaving Pascal.

    program demo;
    
    uses screenops;
    
    const sysdate = 13840;
    
    (* A data type to allow poking *)
    type
      window = record
        case boolean of
          true: (int: integer);
          false: (ptr: ^integer);
      end;
    
    (* And one to allow assigning a date record to an integer.
      sc_date_rec occupies the same space as one integer in memory. *)
    
      convdate = record
        case boolean of
          true: (int: integer);
          false: (dat: sc_date_rec);
      end;
    
    var
      today: sc_date_rec;
      buffer: convdate;
    
    (* Now we can write poke *)
    procedure poke(addr,value:integer);
    
    var memaddr: window;
    
    begin
      memaddr.int := addr;
      memaddr.ptr^ := value;
    end; (* poke *)
    
    begin (* demo *)
      with today do
        year := 16;
        month := 5;
        date := 8;
      end; (* with *)
      buffer.dat := today;
      poke(sysdate,buffer.int);
    end.
    

    The trick with a variant record with only a type definition is famous for this kind of operations.

    You can access VDP RAM in a similar way, from Pascal, but since the p-system frequently executes code from VDP RAM, and in such cases assumes that the VDP address isn't changed between instructions, you have to set your program to M_9900 language type, to force it into CPU RAM.

    When you do want to go to assembly, you'll notice that the interface between the two languages is more straightforward than it is between BASIC and assembly. The p-system's assembler is better than the 99/4A version of TI's own assembler as well. You must link explicitly, though, as no linking with separate assembly language object code is taking place at runtime.

     

    By the way, in the file p-system program development linked to above, you can on page 3-8 find the interface text of the screenops unit. There you can see where I got these data types from.

    • Like 2

  6. Poke is not in any unit. I defined it myself, but thought that perhaps you knew how to write one.

    If not, I can give you an example.

     

    The code I showed comes from a startup program that reads the current date from a real-time clock and sets it in the system, if it's different from the current one. It's not a theoretical design, but actually works.

     

    And, as you can see, there is a way to set the date. It's just not documented in TI's manuals, but is a standard UCSD p-system way of reading and setting the date.


  7. Oh, you are asking about things done 30 years ago! I can hardly remember what I did yesterday...

     

    But probably from some Internal architecture gudie for the UCSD p-system. As far as I can remember, the interface text section is intact in the system's compiled screenops unit, so you can read it there using decode.

    The fact that you have to poke the date into the copy in RAM for everything to work I found out when I wrote startup programs that could read the current date from real time clocks and set it in the p-system automatically. Without poking into that RAM location, I had to re-initialize the system for the new date to be valid and used by all functions.


  8. Use the unit screenops. Normally it's available in SYSTEM.LIBRARY, but if not, access from wherever, or include it there.

    You can see the outline of how to set the system date below. In the small program below, I don't show how to write a poke procedure in Pascal. Neither do I show the details of how to get a date record into an integer, which usually is what you poke. If you don't know how to do this, neither with the variant record nor with the ord trick particular to UCSD Pascal, come back.

    program datefix;
    
    uses screenops;
    
    const sysdate = 13840;
    
    var info: sc_info_type;
    
    begin
      (* Store date in system *)
      sc_use_info(sc_get,info);
      with info.sc_date do
      begin
        year := 16;
        month := 5;
        day := 6;
      end;
      sc_use_info(sc_give,info);
    
      (* The system keeps a copy in RAM for immediate access. *)
      poke(sysdate,date_as_an_integer);
    end.
    
    

  9. That's of course doable, but notice that the p-code card, although it contains GROM and 12 Kbytes of ROM, just like Extended BASIC does, is completely different in how it's implemented.

    • The p-code card uses a different set of GROM access addresses. This is necessary since the p-code card has eight GROM, not just five. Thus it can't use the standard addresses, or it would come in conflict with the three GROM in the console.
    • The p-code card has the GROM access addresses mapped into DSR memory space. Since they overlap precious ROM space there, they are fully decoded. Console GROM access addresses aren't.
    • The p-code card has 12 Kbytes of ROM, just like Extended BASIC, but this ROM is all in DSR space, not command module space. Also, bank switching is done with a CRU bit, not by writing to a ROM address, like Extended BASIC does.

    All of this can of course be handled, but perhaps not by a device developed to allow normal command modules to run on the machine. A GRAM Kracker wouldn't do, for example.


  10. While it's true that it doesn't take any special hardware to run the Turbo Pasc'99 (no p-code card needed), it's incorrect to say that it's a much better product. From a software development point of view, there has never been any more complete platform than Pascal with the p-code card on the 99/4A. All other systems are lacking one or, usually, several of the well thought out mechanisms inherent in USCD p-system IV.0.


  11. I can add that I have thought of, but never implemented, a further feature of my memory expansion. Since I already have the logic to enable and disable parts of the memory expansion by setting individual CRU bits, now decoded with base address 400H, I could add a secondary decoding scheme. If I included a four bit DIP switch, to select a number between zero and fifteen, I could make the 4000H-5FFFH RAM segment also answer when a CRU bit at 1X00H is set. Thus the memory in my expansion could work as a DSR in RAM too. That would make it easier to implement virtual cards in the machine, like a RAM disk or whatever.

    As it is now, the RAM disk I have implemented, relies on having the DSR software on one of my other expansion cards in the box. That's a card I've built myself, which has RAM in the DSR space, to allow for all sorts of modifications at run time. But the internal expansion would of course be more convenient if that wasn't needed to implement a RAM disk or whatever. You could perhaps implement a printout spooler or something like that.

×
×
  • Create New...