Jump to content
IGNORED

Pascal on the 99/4A


apersson850

Recommended Posts

4 hours ago, TheBF said:

In your substantial computer experience Is there any other machine besides TI-99 where the term "polls the interrupts" is used. It's like an oxymoron to me. :)  

In my little world interrupts are about removing the need to poll.

It's a question about the level of abstraction, really.

 

The TMS 9900 executes machine instructions according to its definition. Inside the CPU, there's a microprogram running. This microprogram controls fetching the instructions, decoding them, fetching parameters and data and execute whatever the instruction is supposed to do. In between each instruction, the CPU uses a microprogram instruction to poll its interrupt interface to see if there's a hardware line with an incoming interrupt signal.

 

The p-system executes p-code instructions. Inside the p-system, there is the p-machine which executes p-code instructions according to their definition. In our case the p-machine is actually a PME, p-machine emulator, which consists of a TMS 9900 processor executing machine instructions. These machine instructions control fetching the p-code instructions, decoding them, fetching parameters and data and execute whatever the instruction is supposed to do. In between each instruction, the CPU uses a machine instruction to poll its interrupt interface to see if there's a hardware line with an incoming interrupt signal.

 

The similarities should be obvious.

The UCSD p-system version III actually ran on a hardware processor, made by Western Digital, which executed p-code as its native language.

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

So I'm trying to get my system to prompt me for the date at system startup, and I found this little program in issue 4 of 99 Magazine:

PROGRAM SETDATE;
{$U COMMANDIO.CODE}
USES COMMANDIO;

VAR
 ACTION, DATE : STRING;

BEGIN
 WRITE(CHR(12), 'DATE :', CHR(7));
 READLN(DATE);
 IF DATE = '' THEN
  EXIT(PROGRAM)
 ELSE
  BEGIN
   ACTION := CONCAT('I=FD', DATE, ',*');
   REDIRECT(ACTION)
  END
END.

 

Pretty straightforward stuff, but the compiler is giving me a "IDENTIFIER NOT OF THE APPROPRIATE CLASS" error with the REDIRECT keyword. Huh? Never heard of that one before (well maybe in Java). Any thoughts?

Link to comment
Share on other sites

It's in my memory map document.

Think it's on whtech. Or I can post, but not right now.

 

You call redirect as a procedure, but it's a boolean function. It returns the result of your attempt, so you can check that it was OK or call exception to clear what you did, in case you asked for something stupid.

Edited by apersson850
Link to comment
Share on other sites

1 hour ago, apersson850 said:

It's in my memory map document.

Think it's on whtech. Or I can post, but not right now.

 

You call redirect as a procedure, but it's a boolean function. It returns the result of your attempt, so you can check that it was OK or call exception to clear what you did, in case you asked for something stupid.

Of course! Did not remember that. The listing is obviously wrong then. I 'll modify it.

I do have your memory map. I'll look up the DATE location. 

Thanks.

Link to comment
Share on other sites

To avoid confusion for those who have Peter Miller's description of the UCSD directory: The date word used in the directory and in the System date at &H3610 is not as Peter Miller describes as 7 bits for the year, then 4 bits for the month and the last 5 bits for the day. However, it is as described in the Memory Map of @apersson850: The first 7 bits for the year, then 5 bits for the day and the last 4 bits for the month. So '0011000' for year 24 (= 0001 1000), '10111' for day 23 (= 0001 0111) and '0001' for January. This gives 0011 0001 0111 0001 is &H3171.

  • Thanks 1
Link to comment
Share on other sites

Here's the corrected version. Obviously calling the Filer and setting the date that way is much slower than poking it directly into memory. That's coming next :)

 

PROGRAM SETDATE;
{$U COMMANDIO.CODE}
USES COMMANDIO;

VAR
 ACTION, DATE : STRING;

BEGIN
 WRITE(CHR(12), 'DATE :', CHR(7));
 READLN(DATE);
 IF DATE = '' THEN
  EXIT(PROGRAM)
 ELSE
  BEGIN
   ACTION := CONCAT('I="FD', DATE, ',Q"');
   IF NOT(REDIRECT(ACTION)) THEN
    EXCEPTION(TRUE)
  END
END.

 

  • Like 3
Link to comment
Share on other sites

I know you are well beyond the Intel hex thing now @VORTICON but I am trying to confirm/deny that code I got from MaxForth is generating a compliant checksum.

 

Based on a post by @apersson850 I think one line of your code would need to change to give the same result that my version generates. 

On 1/19/2024 at 10:00 AM, apersson850 said:

That was supposed to be the 1's complement. For 2's complement i used the odd(-n) instruction. A minus sign in Pascal is like NEG in assembly and that's the same as 2's complement.

 

Could someone confirm that the 2nd line below would be the correction from 1s' complement to 2's complement.

(Lee is watching I hope I spelled that right or I will only get part marks) ;)

 

( ORIGINAL LINE } 
 DATACHECK := ORD(NOT(ODD(DATACHECK)) AND ODD(255)) + 1;

{ Should be ? }
  DATACHECK := ORD((ODD(-DATACHECK)) AND ODD(255));

 

  • Like 1
Link to comment
Share on other sites

12 hours ago, TheBF said:
( ORIGINAL LINE } 
 DATACHECK := ORD(NOT(ODD(DATACHECK)) AND ODD(255)) + 1;

{ Should be ? }
  DATACHECK := ORD((ODD(-DATACHECK)) AND ODD(255));

 

These two are equivalent. The first one calculates the 1's complement then add 1, which makes it the 2's complement.

The second line calculates the 2's complement directly.

 

Going back to the date thing, my system works like this:

  • At startup, it reads date and time for last login with the present system disk (in drive #4:) and prints that on the screen.
  • Reads the current date and time from my hardware real-time clock and displays that on the screen.
  • Stores the current date in the login tracking area on the system disk.
  • Updates the p-system's date on the system disk.
  • Updates the p-system's current date in memory.

The first three items are my own idea. I store the login time in an area on the disk that's not used by the p-system. It also uses my hardware clock. Today there are several possibilities for that, even on the real TI 99/4A, but back when I built it there was nothing to buy with a clock inside. It was before CorComp's Triple Tech card and similar things.

 

Extra info: The unused parts of the disk comes from the fact that the p-system creates a dummy disk and file structure for the standard operating system on each diskette, combined with that the p-system always accesses blocked volumes (disk) one block at a time. A block is 512 bytes in size. So a diskette used with the p-system has the following structure, listed by sector:

  • Machine's disk directory.
  • Machine's map of used sectors.
  • Machine's entry for the dummy file PASCAL, which occupies the whole disk.
  • Unused sector.

Then comes the p-system's disk directory, four blocks long (2 Kbyte) and possibly the duplicate directory, another four blocks.

After that there's space for the maximum of 77 files the p-system can handle on a disk.

 

This means that the p-system's file handling is less flexible than the standard file system on the TI 99/4A, but the implementation is faster to handle. Files are always contiguous and the whole directory is temporarily read into RAM when dealing with a disk. This is why it's a good idea to have a duplicate directory on real disks. Should the writing of an updated directory (in RAM) to the disk be interrupted, you can retreive the duplicate directory and at least return to that state, so you don't lose more than the last change.

 

The limitation to 77 files comes from the desire to be able to temporarily handle the whole directory in RAM and the fact that the disk sizes at the beginning of the p-system frequently made it impossible to fit even 77 files, unless they all were very small.

 

All this I described above can be done at Pascal level.

Peek and poke are easy to implement, to handle the date stored in memory, by using a datatype with a variant record.

The Pascal intrinsics unitread and unitwrite will directly access a logical disk block. I write logical because the standard mode is to access block zero as the first block with the p-system's disk directory, although that starts in physical disk sector 4 (block 2). But there's a physical mode bit for unitread/unitwrite which changes the offset to zero, so with that bit set unitread/unitwrite will access the disk with block zero being the sectors zero and one on the disk. Thus you can effectively access an arbitrary sector on a disk directly from Pascal.

Edited by apersson850
  • Like 2
  • Thanks 1
Link to comment
Share on other sites

10 hours ago, Geoff Oltmans said:

Apologies if this was covered earlier... but what are the differences between IV.0 and IV.2.2 (which according to Wikipedia is the latest)?

Well, that's the kind of question which can have an infinite answer.

In short, versions with different leading roman numbers have different versions of the p-machine. Thus the p-code executed in these systems are different, so they are completely incompatible with each other.

Code generated by a compiler for p-system II.3 will execute on II.5, but not on IV.0, for example.

Version IV is the latest (and most probably last) version of the PME. Then the higher the second number is, the more developed the system's functions are. As an example, IV.0 doesn't support subsidiary volumes, but later versions do.

The ability to use extended memory is another feature that appeared after IV.0. In IV.0 machines, the code pool is between the heap and stack in memory, thus competing with these areas for space. Machines with more memory than 64 Kbytes can have an external code pool, so that the heap and stack are in one 64 Kbyte memory segment and the code pool in another segment. If such a machine has (at least) 128 Kbytes of RAM, you can have 64 Kbytes for data and 64 Kbytes for code available at the same time.

The TI 99/4A is a special case here, since it has both an internal code pool in 24 K RAM, an external code pool in VDP RAM and a ROMdisk with code on the p-code card.

 

Here is a description of some features added to a system after IV.0. It seems to be for p-systems on IBM PC machines.

Edited by apersson850
  • Like 3
Link to comment
Share on other sites

6 hours ago, apersson850 said:

Going back to the date thing, my system works like this:

  • At startup, it reads date and time for last login with the present system disk (in drive #4:) and prints that on the screen.
  • Reads the current date and time from my hardware real-time clock and displays that on the screen.
  • Stores the current date in the login tracking area on the system disk.
  • Updates the p-system's date on the system disk.
  • Updates the p-system's current date in memory.

The first three items are my own idea. I store the login time in an area on the disk that's not used by the p-system. It also uses my hardware clock. Today there are several possibilities for that, even on the real TI 99/4A, but back when I built it there was nothing to buy with a clock inside. It was before CorComp's Triple Tech card and similar things.

 

Extra info: The unused parts of the disk comes from the fact that the p-system creates a dummy disk and file structure for the standard operating system on each diskette, combined with that the p-system always accesses blocked volumes (disk) one block at a time. A block is 512 bytes in size. So a diskette used with the p-system has the following structure, listed by sector:

  • Machine's disk directory.
  • Machines map of used sectors.
  • Machines entry for the dummy file PASCAL, which occupies the whole disk.
  • Unused sector.

Then comes the p-system's disk directory, four blocks long (2 Kbyte) and possibly the duplicate directory, another four blocks.

After that there's space for the maximum of 77 files the p-system can handle on a disk.

 

This means that the p-system's file handling is less flexible than the standard file system on the TI 99/4A, but the implementation is faster to handle. Files are always contigous and the whole directory is temporarily read into RAM when dealing with a disk. This is why it's a good idea to have a duplicate directory on real disks. Should the writing of an updated directory (in RAM) to the disk be interrupted, you can retreive the duplicate directory and at least return to that state, so you don't lose more than the last change.

 

The limitation to 77 files comes from the desire to be able to temporarily handle the whole directory in RAM and the fact that the disk sizes at the beginning of the p-system frequently made it impossible to fit even 77 files, unless they all were very small.

 

All this I described above can be done at Pascal level.

Peek and poke are easy to implement, to handle the date stored in memory, by using a datatype with a variant record.

The Pascal intrinsics unitread and unitwrite will directly access a logical disk block. I write logical because the standard mode is to access block zero as the first block with the p-system's disk directory, although that starts in physical disk sector 4 (block 2). But there's a physical mode bit for unitread/unitwrite which changes the offset to zero, so with that bit set unitread/unitwrite will access the disk with block zero being the sectors zero and one on the disk. Thus you can effectively access an arbitrary sector on a disk directly from Pascal.

Great info. Thanks.

I'm actually building an IDE card from @Shift838 which has an RTC and I do plan on accessing that clock at system startup to update the system. One question: where on the system disk is the date stored? Updating the date in memory obviously will not automatically update the disk as well. I suppose this could be done with the Filer as I've shown in the previous program, but I have the distinct feeling you have a much better way of doing this :)

  • Like 2
Link to comment
Share on other sites

1 minute ago, Vorticon said:

One question: where on the system disk is the date stored?

Later today I'll get the code that does it and show you here.

But basically, the disk directory has 78 entries. The first one describes the disk itself, the other 77 the files that can be on the disk. At the end of each entry, there is a date. For the disk, it's the date of last boot and for the files of last change.

The date of last boot on the system disk (in #4:) is the date the system starts up with, until you use the Filer to tell it another date. When you do that with the Filer, it will update both the copy of the date in RAM and the last boot date on the system disk. So I made my program do the same thing.

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

I had a little free time to work on the new version of SETDATE, and I am now able to retrieve the system date from memory. I'll try working on the setting of a new date hopefully in the next day or 2 as time allows. I did use @apersson850's PEEK and POKE routines from the TURTLEGRAPHICS unit.

 

PROGRAM SETDATE;
CONST
 DATELOC = 13840; {RAM LOCATION OF SYSTEM DATE}

TYPE
 BYTE = 0..255;

 DUAL = RECORD
  CASE BOOLEAN OF
   TRUE : (INT: INTEGER);
   FALSE : (PTR : ^INTEGER);
  END; {DUAL}
  
 BYTEWORD = RECORD
  CASE BOOLEAN OF
   TRUE : (VALUE : INTEGER);
   FALSE : (BYTES : PACKED ARRAY[1..2] OF BYTE);
  END;
  
VAR
 WORD : BYTEWORD;
 YEAR, MONTH, DAY : INTEGER;
 MONTHNAME, MSTRING : STRING;

PROCEDURE POKE(ADDR, VALUE : INTEGER);
VAR
 LOC : DUAL;

BEGIN
 LOC.INT := ADDR;
 LOC.PTR^ := VALUE;
END; {POKE}

FUNCTION PEEK(ADDR : INTEGER) : INTEGER;
VAR
 LOC : DUAL;
 
BEGIN
 LOC.INT := ADDR;
 PEEK := LOC.PTR^;
END; {PEEK}

BEGIN
 MONTHNAME := 'JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC';
 WORD.VALUE := PEEK(DATELOC);
 YEAR := WORD.BYTES[1] DIV 2;
 WORD.VALUE := WORD.VALUE * 128;
 DAY := WORD.BYTES[1] DIV 8;
 MONTH := WORD.BYTES[2] DIV 128;
 MSTRING := COPY(MONTHNAME,MONTH * 3 - 2, 3);
 WRITELN('SYSTEM DATE: ',DAY,'-',MSTRING,'-',YEAR);
END.

 

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

7 hours ago, apersson850 said:

Good progress.

 

Here is my program that normally runs as SYSTEM.STARTUP.

It does a bit more than just setting the time, but you can just swim by the things you don't need.

 

 

autostart.pdf 119.68 kB · 4 downloads

I can see that you define a record for the directory and it looks like each sector is 256 bytes. However, it appears we're missing 2 bytes from sector 3 and 1 byte from sectors 4-5 (?). Is the location of the record element dlastboot the normal location where the system date is written in the standard system or is it your own custom location? If it is custom, then where in the directory is the date written?

In the end though, we still have to access the disk system to write the date, so I'm wondering if it's worth going through all that trouble versus just going with the REDIRECT option above.

I've already modified the MODRS232 source to set the PRINTER: to PIO and the REMIN/OUT to 2400 8-N-1 which is what I need for my purposes and added the date setting program to it as SYSTEM.STARTUP.

One last thing: any thoughts on how to convert a string of digits to an integer efficiently? We have STR to do the reverse but there is no String-to-integer function built in. I can create such a function but it will require parsing the string character by character and going through decimal order conversions, clunky at best and likely slow...

Link to comment
Share on other sites

Now you got me worried, so I checked. There are no bytes missing in the dirtype data structure. Perhaps you got fooled by the fact that there is a string? A string's default length is string[80]. That's 81 bytes including the length byte. But since dirtype is a record, not a packed record, all items that aren't a full word are padded to be a full word. In an earlier post I pointed out that the smallest storage unit in Pascal is a word. That goes even for a boolean, which occupies 16 bits but only use one of them. So a string will occupy 82 bytes in the record, where one byte isn't used for anything.

That's why they made disk names 7 characters and file names 15 characters. With the length byte that's 8 and 16, so fits nicely as four or eight words.

 

dlastboot is the system's definition (and name, actually) of the date on the disk, and if it's the system disk at boot time, then that's what is used to set the system's date. There is a date at the end of each file too, which represents the last date that file was changed.

My program accesses the disk both to change that date but also to handle my own, more detailed information about last boot time and date. Which can't be done by invoking the Filer.

But the thing is of course that when you get the solution for free, then all the trouble somebody else did (me in this case), so you can just include it. That's why I share it to begin with.

 

If you look in my extrascreen package, then inside there are parsers doing both text-to-integer and text-to-real inside that unit. They are of course designed with the task to convert a user input in mind, and then the speed of the conversion is still fast compared to how long it takes the user to input the value. If you are going to convert text to numbers on a large scale, then they may not cater. As long as they are used once per user input, nobody will notice the delay.

If it's only for this application, then if you can consider the extra time needed to call in the Filer to do the work, then parsing takes no time at all in comparison.

Edited by apersson850
  • Like 1
Link to comment
Share on other sites

@Vorticon 

 DUAL = RECORD
  CASE BOOLEAN OF
   TRUE : (INT: INTEGER);
   FALSE : (PTR : ^INTEGER);
  END; {DUAL}

@apersson850

 

14 hours ago, apersson850 said:

Here is my program that normally runs as SYSTEM.STARTUP.

When I see such programs I get depressed...: I still have so much to learn about Pascal... I can't figure out what makes a boolean = True of a record that record an integer and False a pointer...

With missing @ or 'addr' I had no idea how to peek or poke something in this UCSD Pascal. How this record does it now, goes over my head.

 

After I bought the Pcode system in 1983 (200 dollar for each disk and about 300 dollar for the card) I just made some simple programs with it. 

I got married in 1984, got 3 kids and when i finaly got some time again for my TI, many connections were oxidized and the computer was not working in a nice way anymore.

In 1998 I discoverd 'Might and Magic 6' and all my free time went into this game. 🙂 I think I have played it now about 7 or 8 times. I still prefer this game to the sequels, Might and Magic 7 to 10. To walk for the first time in a 3D world (in 1998) was something so overwhelming, that I never will forget that feeling! It made me completely forget the feeling I had when I first saw a rotating wire model of a chalice (with hidden lines!) on TV around 1962.

So when i needed to make programs, I first used Excel and later Visual Basic. Visual Basic is just what the name tells you, it is just Basic: tell your program what you want it to do in English and it works. When you do not know the right syntax, you can google it.

With my retirement in sight and now that I actually have my pension, I had more time for my TI (as an emulator). However, before I could start doing anything with Pcode again (because I did spend so much money on it), I first wanted a program that would make it easier for me to create the program text. Visual Basic .net has been developed so much now, that it has become quite easy to create a program. Now, after some years, the Pcode program is that far that I can work with it. But I understand that I first have to know much more about Pascal, before I can make some programs with it .....

 

in the attachment the subroutine for converting the word with the disk date to text in Visual Basic. No magic about it. 🙂

 

pcode.jpg

  • Like 1
Link to comment
Share on other sites

6 hours ago, apersson850 said:

Now you got me worried, so I checked. There are no bytes missing in the dirtype data structure. Perhaps you got fooled by the fact that there is a string? A string's default length is string[80]. That's 81 bytes including the length byte. But since dirtype is a record, not a packed record, all items that aren't a full word are padded to be a full word. In an earlier post I pointed out that the smallest storage unit in Pascal is a word. That goes even for a boolean, which occupies 16 bits but only use one of them. So a string will occupy 82 bytes in the record, where one byte isn't used for anything.

That's why they made disk names 7 characters and file names 15 characters. With the length byte that's 8 and 16, so fits nicely as four or eight words.

 

dlastboot is the system's definition (and name, actually) of the date on the disk, and if it's the system disk at boot time, then that's what is used to set the system's date. There is a date at the end of each file too, which represents the last date that file was changed.

My program accesses the disk both to change that date but also to handle my own, more detailed information about last boot time and date. Which can't be done by invoking the Filer.

But the thing is of course that when you get the solution for free, then all the trouble somebody else did (me in this case), so you can just include it. That's why I share it to begin with.

 

If you look in my extrascreen package, then inside there are parsers doing both text-to-integer and text-to-real inside that unit. They are of course designed with the task to convert a user input in mind, and then the speed of the conversion is still fast compared to how long it takes the user to input the value. If you are going to convert text to numberc on a large scale, then they may not cater. As long as they are used once per user input, nobody will notice the delay.

If it's only for this application, then if you can consider the extra time needed to call in the Filer to do the work, then parsing takes no time at all in comparison.

OK makes sense. I'll look at the extrascreen unit. I have absolutely no problem using other people's code as long as I fully understand how it works so I can learn from it. But I also like to challenge myself and try to come up with my own solutions and compare them to what's already been done. Remember, this whole thing is just a hobby and, at least for me, the programming challenge is where the fun is!

To be honest, there are probably only a handful of people at most around here who actually use Pascal on the TI, so it's all about personal edification above all else despite the availability of full emulation nowadays. It's really a shame because it's such a powerful language and yet eminently readable and well structured...

Link to comment
Share on other sites

1 hour ago, Rhodanaj said:

@Vorticon 

 DUAL = RECORD
  CASE BOOLEAN OF
   TRUE : (INT: INTEGER);
   FALSE : (PTR : ^INTEGER);
  END; {DUAL}

@apersson850

 

When I see such programs I get depressed...: I still have so much to learn about Pascal... I can't figure out what makes a boolean = True of a record that record an integer and False a pointer...

With missing @ or 'addr' I had no idea how to peek or poke something in this UCSD Pascal. How this record does it now, goes over my head.

 

After I bought the Pcode system in 1983 (200 dollar for each disk and about 300 dollar for the card) I just made some simple programs with it. 

I got married in 1984, got 3 kids and when i finaly got some time again for my TI, many connections were oxidized and the computer was not working in a nice way anymore.

In 1998 I discoverd 'Might and Magic 6' and all my free time went into this game. 🙂 I think I have played it now about 7 or 8 times. I still prefer this game to the sequels, Might and Magic 7 to 10. To walk for the first time in a 3D world (in 1998) was something so overwhelming, that I never will forget that feeling! It made me completely forget the feeling I had when I first saw a rotating wire model of a chalice (with hidden lines!) on TV around 1962.

So when i needed to make programs, I first used Excel and later Visual Basic. Visual Basic is just what the name tells you, it is just Basic: tell your program what you want it to do in English and it works. When you do not know the right syntax, you can google it.

With my retirement in sight and now that I actually have my pension, I had more time for my TI (as an emulator). However, before I could start doing anything with Pcode again (because I did spend so much money on it), I first wanted a program that would make it easier for me to create the program text. Visual Basic .net has been developed so much now, that it has become quite easy to create a program. Now, after some years, the Pcode program is that far that I can work with it. But I understand that I first have to know much more about Pascal, before I can make some programs with it .....

 

in the attachment the subroutine for converting the word with the disk date to text in Visual Basic. No magic about it. 🙂

 

pcode.jpg

A variant record is a simple mechanism to allow access to the common memory location of that record with different type of variables for example. In this case we can access either the contents of the memory location pointed to by the pointer (PEEK) by reading the integer element, or assign a memory location to the pointer and write a desired value to that location by changing the integer element (POKE). Pretty simple really. The boolean values are just a binary choice and don't actually get used.

I love Visual Basic and I don't get why it's falling out of favor... For what it's worth, the Pcode Tool has been a lifesaver!

  • Thanks 1
Link to comment
Share on other sites

I understand you want to learn. Nothing wrong with that. My comment was more along the line that if you use things I've already spent effort in creating, then you can build on that and create something on a higher level, more astonishing, which I could also benefit from. Instead of you spending time figuring out the same thing I once did. So my comment was mainly in my own interest. I confess... 🙂

 

@Rhodanaj You got an explanation of the variant record. The use of a boolean variant is just because only two versions are needed. You can do it in different ways. These two are equivalent:

 DUAL = RECORD
  CASE BOOLEAN OF
   TRUE : (INT: INTEGER);
   FALSE : (PTR : ^INTEGER);
  END; {DUAL}

dual = record
  case integer of
    1: (int: integer);
    2: (ptr: ^integer);
end; (* dual *)

Here it's important to know that UCSD Pascal does not enforce that you use all possible variants, so it's OK to have an integer type but only use two of the 65536 possible alternatives.

However, the second alternative can give you more options. You can have four versions, so you can access data at a location either as an integer, as an array of two bytes or an array of two characters.

byte = 0.255;
bytearray = packed array[0..1] of byte;
chararray = packed array[0..1] of char;
quad = record
  case integer of
    1: (int: integer);
    2: (ptr: ^integer);
    3: (byteptr: ^bytearray);
    4: (charptr: ^chararray);
end; (* quad *)

With this declaration you can use the same data type to point somewhere in memory and then read out/store an integer, two bytes or two characters by just using the appropriate variant. This is also a way to typecast a variable, since you can assign an integer to this variable and then assign that to another variable, which is of the type bytearray.

 

Another way you can transfer data between different types in UCSD Pascal is by using the move intrinsics. You can do a moveleft(source, destination, 82) where the source is a string and the destination is an array[0..40] of integer.

Normally Pascal doesn't allow mixing types like that, but moveleft doesn't care.

 

This is of course a list of things that could be considered "dirty tricks". From the original Pascal, by Wirth, intended for educational use, Knowles team at UCSD created a very versatile language, which could be used also for system programming. Most of the things you can do with a TI 99/4A, including direct access to VDP and sound chip as well as disk sector IO, can be done without having to go to assembly level. One thing you can't do is CRU access.

 

For the size of the computer you can also accomplish quite a lot. P-code is compact and the compilation means the source code doesn't have to be in memory at the same time. BASIC can tokenize keywords, but variable names have to remain. With Pascal they are only in the source and replaced by a p-code in the object code.

Forth is compact too, but doesn't provide the intelligent code pool management and can't run code neither from VDP RAM nor from GROM.

  • Thanks 2
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...