+Vorticon Posted December 10, 2022 Share Posted December 10, 2022 Anyone here know why this simple program is not working? It's supposed to read a text file character by character, echo the text to the screen and write it back to another text file. Everything is working except that the target file remains empty. No errors are issued. Puzzling... { character copy primitive } program copyprog; const ENDFILE = -1; NEWLINE = 10; { ASCII value } type character = -1..127; { ASCII plus ENDFILE } var f,o : interactive; { getc -- get one character from standard input } function getc (var c : character) : character; var ch : char; begin if (eof(f)) then c := ENDFILE else if (eoln(f)) then begin readln(f); c := NEWLINE end else begin read(f, ch); c := ord(ch) end; getc := c end; { putc -- put one character on standard output } procedure putc (c : character); begin if (c = NEWLINE) then begin writeln; writeln(o) end else write(chr(c)); write(o, chr(c)) end; { copy -- copy input to output } procedure copy; var c : character; begin while ( getc(c) <> ENDFILE ) do putc(c) end; begin { main program } reset(f, '#5:test.text'); rewrite(o, '#5:testout.text'); copy; close(f); close(o) end. Quote Link to comment Share on other sites More sharing options...
SteveB Posted December 10, 2022 Share Posted December 10, 2022 (edited) Puh ... I'm a little bit spoiled by Delphi and Lazarus and never did Pascal on the TI. Though pascal had become my native digital tongue somehow in the early 90's and I never went beyond. It looks good at first sight. My thoughts in random order: Is the file testout.text created but empty? close() should call flush() .. or should this be done manually in TI Pascal? try a writeln(o,'this is a test') instead of the copy command ... is it written to disk? I have never seen "interactive" as a type. Is it comparable with standard Pascal "TEXT" ? Or "FILE of BYTE" or what? I did not find a good explanation in the UCSD Pascal Docs. Why do you need the extra handling of NEWLINE? Isn't >0A a character like all others and could be handled as a normal, displayable char? PS: Found a good definition of 'interactive' in the Apple manual. It looks good for screen and keyboard, but not for files on disks ... is there a special reason to use it instead of TEXT? Edited December 10, 2022 by SteveB PS added 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted December 10, 2022 Share Posted December 10, 2022 20 minutes ago, SteveB said: My thoughts in random order: Is the file testout.text created but empty? close() should call flush() .. or should this be done manually in TI Pascal? try a writeln(o,'this is a test') instead of the copy command ... is it written to disk? I have never seen "interactive" as a type. Is it comparable with standard Pascal "TEXT" ? Or "FILE of BYTE" or what? I did not find a good explanation in the UCSD Pascal Docs. Why do you need the extra handling of NEWLINE? Isn't >0A a character like all others and could be handled as a normal, displayable char? PS: Found a good definition of 'interactive' in the Apple manual. It looks good for screen and keyboard, but not for files on disks ... is there a special reason to use it instead of TEXT? testout.text is a pre-existing empty text file There is no flush() with UCSD Pascal. Should be automatically handled by the close command writeln(o, 'this is a test') does not write anything to disk either The reason I use interactive instead of text is because it is the default for UCSD Pascal. If I was to use text, then I would have to replace read with the pair ch := f^ and get(f), and replace write with o^ := c and put(o). There is a good explanation of why that is on pages 22-24 of the compiler manual. I tried it both ways and the result is the same. Using NEWLINE is simply for clarity rather than use decimal 10. A bit of a background about all this: I am currently reading an excellent book from 1981 called "Software Tools in Pascal" by Kernighan and Plauger, pointed out by FarmerPotato. It teaches us proper Pascal program structure and design, as well as fleshes out a series of tools for source text manipulation. Great read, if a bit geeky 😁 Still puzzled... 4 Quote Link to comment Share on other sites More sharing options...
SteveB Posted December 10, 2022 Share Posted December 10, 2022 From the manual: Shoud you change your close(o) to close(o,LOCK) to explicitly make it persistent? 6 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted December 11, 2022 Share Posted December 11, 2022 Yes that's it! I did not realize that the close statement took options under UCSD Pascal. It's all detailed on page 52 of the compiler manual. That said it seems to me that the default behavior should have been to flush the write buffer to the file instead of requiring a special option for that... Thanks! 2 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted December 12, 2022 Share Posted December 12, 2022 12 hours ago, Vorticon said: Yes that's it! I did not realize that the close statement took options under UCSD Pascal. It's all detailed on page 52 of the compiler manual. That said it seems to me that the default behavior should have been to flush the write buffer to the file instead of requiring a special option for that... Thanks! I agree. That seems strange to not **flush on close(). Maybe @apersson850 has an explanation or some deeper insights why it is this way. **Not to be confused with the rule of the water closet: always close before flushing. 4 1 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted December 12, 2022 Author Share Posted December 12, 2022 The requirement to use LOCK to make the file stick on the disk is that if you don't use LOCK, you are creating a temporary file, one you intend to live just as long as the program is executing. Like it or not... It's correct that interactive is a text file with a different buffer handling. 1 1 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted July 24, 2023 Author Share Posted July 24, 2023 There have been several posts over the last years about making it possible to run the p-system without the p-code card. Or rather with a replacement. Some insight in the memory use of the p-system could be handy, should anyone ever attempt it again. The p-system has quite a lot of features you don't get in the BASIC environment, for example. Due to this, it's also more memory hungry. A p-system IV.0 can't really run on a machine with as little as 32 K of RAM (the rest is video RAM). To make it possible, the p-system on the 99/4A uses some tricks. One of the most important is allowing p-code to run from three different types of memory: CPU RAM (the normal one), VDP RAM (video) and GROM (TI's special memory mapped ROM circuits). Usage of memory: CPU RAM 8 kbyte part Screen buffer for the 80 column screen. Jump table for the PME. Code for things that can't run from the p-code card, like interrupt and IO-handling. CPU RAM PAD (256 bytes) PME inner interpreter. System related things, like FAC and similar. Workspaces. CPU RAM 24 kbyte part Heap. Secondary code pool. Stack. VDP RAM. 16 kbytes accessed via the VDP. Screen content. Primary code pool. Disk buffers. P-code card ROM 12 kbyte in the DSR space. PME. BIOS. P-code card GROM 48 kbyte read only on the card, mapped in the DSR space. Assembly code repository for things loaded during startup and then to the RAM in the lower expansion area. The operating system's disk unit OS: (a GROM-disk). 6 1 Quote Link to comment Share on other sites More sharing options...
Rossman Posted July 26, 2023 Share Posted July 26, 2023 Hi, @apersson850. It has been a long time. I am so glad to see your post. I have naïve questions, as you have come to expect from me. "Or rather with a replacement." p-code is interpreted, so there must be an interpreter in ROM for compiled Pascal code, as well as to act as the system OS (? maybe not, maybe executing p-code is just a switchable mode of a flexible OS?). Do you mean p-code embedded in ROM on a cartridge? Or some other form of ROM injection? Is there a clear path forward from the 99/8 architecture that incorporated p-system IV in the form of motherboard ROMs? I suppose a cartridge is an advantage over having a PEB, but availability of ROMs is one of several problems to solve. Pascal was resource intensive for its day. On the TI it required a PEB and memory expansion, as you point out. (Sidebar: I'd argue that resource intensity of Pascal carried forward in the successor language Java. The JVM footprint, the #includes with the standard compile... by 2012 a simple service written in Java had a gig-plus footprint. Admittedly most of these were language defaults of convenience, which can be overridden. Still, it can be argued that Java resource bloat was no small contributor to the success of Python, but ... ok, sidebar, I'll stop, you haven't missed this dribble.) "uses some tricks" Not uncommonly on the TI and similar systems of yore, we ran out of core and we had to write memory swap routines. We swapped to disk because that was where the storage was. It was a humbling moment in the early 80s when I told my dad of all of these memory expansion techniques I'd figured out for the TI (reality check: they were just crude disk I/O) when he told me of the stuff he did on an IBM 1401 and later a first generation System/360 to accomplish the same, and more. That's great, kid. Let me tell you how the world works. In your opinion, is the Pascal memory management sufficiently optimized or is there a memory management optimization worth embedding in Pascal code on the 99/4 and /4A? I believe your post describes what makes a p-system ROM a good citizen, but is there a "what makes a Pascal program a model citizen"? Again, my questions are just naïve and interpretations of what you posted, Anders. They may not be worth answering. But your post got me thinking just the same. Best regards, R. Quote Link to comment Share on other sites More sharing options...
apersson850 Posted July 26, 2023 Author Share Posted July 26, 2023 The p-system is a system in layers. At the bottom, there are hardware specific services, like for the keyboard, screen, disk IO, interrupt services and similar. These are written in 9900 assembly language. At the next level, there is the PME, which interprets p-code. This is written in 9900 assembly language and runs mainly from the p-code card's ROM chips. Some of it is in 8 K RAM and the innner part in RAM PAD at 8300H (for speed reasons). The PME can execute p-code from all sorts of memory, CPU RAM, VDP RAM or GROM. Then there is the main operating system, which is mainly written in Pascal and compiled to p-code. The operating system is stored in GROM chips on the p-code card. Some parts stored there are 9900 assembly code. It can't be executed from GROM, but is moved to 8 K RAM for execution. So the GROM is in that case just a repository. Then there are various external parts of the operating system, like the Filer, which is stored on disk and read into RAM to execute. Code is running from one of the code pools. The main code pool is in VDP RAM, to avoid occupuing the secondary code pool more than necessary. The second code pool is in 24 K RAM, where it competes with the heap and stack for space. So more code there implies less space for variables. The only advantage of not having the p-code card is that you don't need a PEB then, providing you have other ways of handling expansion RAM and disk storage. And that the p-code cards are in somewhat short supply. When TI implemented it, the resources required wouldn't fit in a cartridge and you needed the PEB anyway, so it wasn't too big a deal. The memory management allows for writing software that can be segmented, so that not all segments need to be in memory at the same time for the program to work. Typically you have one segment that's loaded all the time (the main program), but you can write an input routine in one segment, a printout routine in another segment, a data manipulation and storage handler in a third. Since you neither input, store or print at the same time, the system can load what's needed when it's needed, and also discard a non-used segment if the space it occupies is needed for something else. This applies to code. You can allocate and dispose data areas as you need, but they have to fit in the 24 K RAM, together with the stack, other data and any code that needs to run there. From this, it's obvious that if you can keep segments small enough so that the calling segment and called segment both fits in the primary code pool (VDP RAM), you have more space available for data. In my opinion, this is good enough for a small machine like the 99/4A. Adding more features requires more support code, which will use more of that memory we try to save for our own use. 3 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted July 26, 2023 Share Posted July 26, 2023 How would one go about accessing the bitmap screen if the UCSD system uses the VDP as the primary code pool? Quote Link to comment Share on other sites More sharing options...
apersson850 Posted July 26, 2023 Author Share Posted July 26, 2023 (edited) The p-system has pointers to where the main code pool starts and ends. When I implemented bit-mapped graphis with Pascal I changed the pointer. This means that many more programs have to run from the secondary code pool, as the remaining part of the primary one is pretty small. But as long as they fit in there, the system works the same as always. Well, not for screen output, of course, but the rest. There's a way to force a program to load in the secondary pool, no matter what, but it's better to just let the system check the remaining space in the small pool there is left and determine if it's enough or not. Edited July 26, 2023 by apersson850 1 Quote Link to comment Share on other sites More sharing options...
+9640News Posted July 26, 2023 Share Posted July 26, 2023 I'm not saying it would be easy, but the Geneve does have the source code for the PSYSTEM. I am not sure how easy it would be to port over to the TI-99/4A, but with a F18a and a SAMS, there may be a possibility. I don't know if anyone has ever explored that option/opportunity. Just throwing it out there. 2 Quote Link to comment Share on other sites More sharing options...
+mizapf Posted July 26, 2023 Share Posted July 26, 2023 We have a P-system on the Geneve? 1 Quote Link to comment Share on other sites More sharing options...
+9640News Posted July 26, 2023 Share Posted July 26, 2023 39 minutes ago, mizapf said: We have a P-system on the Geneve? Yes. There are some issues with the runtime system, but all source code is available and has been since the early 90's. Check out GitHub - BeeryMiller/PSYSTEM 2 3 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted July 27, 2023 Share Posted July 27, 2023 7 hours ago, apersson850 said: The p-system has pointers to where the main code pool starts and ends. When I implemented bit-mapped graphis with Pascal I changed the pointer. This means that many more programs have to run from the secondary code pool, as the remaining part of the primary one is pretty small. But as long as they fit in there, the system works the same as always. Well, not for screen output, of course, but the rest. There's a way to force a program to load in the secondary pool, no matter what, but it's better to just let the system check the remaining space in the small pool there is left and determine if it's enough or not. Is there documentation somewhere on these pointers? Quote Link to comment Share on other sites More sharing options...
apersson850 Posted July 27, 2023 Author Share Posted July 27, 2023 (edited) For the primary code pool they are at 2780H and 2782H. You can find them here. Looking at the document, it seems I've not figured out where they are for the secondary code pool. I probably didn't need them. Edited July 27, 2023 by apersson850 1 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted July 27, 2023 Author Share Posted July 27, 2023 14 hours ago, 9640News said: I'm not saying it would be easy, but the Geneve does have the source code for the PSYSTEM. I am not sure how easy it would be to port over to the TI-99/4A, but with a F18a and a SAMS, there may be a possibility. I don't know if anyone has ever explored that option/opportunity. I took a quick look. It doesn't seem to be the same version of the p-system that's running on the Geneve as on the 99/4A. There are also differences like that ATTACH is implemented, so the interrupt structure is different and that's exploited in the Geneve. Some day when I have more time than I know what to do with it all, I'll make a deep dive into the source code for the Geneve... 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted July 28, 2023 Share Posted July 28, 2023 15 hours ago, apersson850 said: For the primary code pool they are at 2780H and 2782H. You can find them here. Looking at the document, it seems I've not figured out where they are for the secondary code pool. I probably didn't need them. Thanks! So basically I can just point 2780H to the first free VDP address after setting up the bitmap space and 2782H to last free address and the OS should handle it from there as far as the code pools are concerned? Quote Link to comment Share on other sites More sharing options...
apersson850 Posted July 28, 2023 Author Share Posted July 28, 2023 When I reserve space for bitmap, I just check that the top memory pointer isn't smaller than what the bottom pointer needs to be. If not, there's space available for bitmap. Here is the code to do it. program bit_map_reserve; (* Utility used for pre-reserving space for bit-map mode programs *) (* A-DATA 860604 *) uses screenops; var prline :sc_long_string; ret_set :sc_chset; ch :char; procedure interpreter(ch :char); (* Command line interpreter *) const intmem = 10112; (* Interpreters VDP memory pointer *) topmem = 10114; (* Top VDP memory pointer *) newint = 14360; (* New intmem value *) stdint = 3576; (* Standard intmem value *) type dual = record case boolean of true :(int :integer); false:(ptr :^integer); end; (* dual *) procedure poke(addr,value :integer); var window :dual; begin window.int := addr; window.ptr^ := value; end; (* poke *) function peek(addr :integer):integer; var window :dual; begin window.int := addr; peek := window.ptr^; end; (* peek *) procedure clearline; (* Clears common prompt line *) begin sc_gotoxy(0,1); sc_clrcurline; end; (* clearline *) procedure allocate; (* Reserves space for bit-map mode *) begin clearline; if peek(topmem)<newint then writeln('Reservation impossible') else begin poke(intmem,newint); writeln('Space reserved for bit-map'); end; end; (* Allocate *) procedure deallocate; (* Releases space reserved for bit-map *) begin clearline; poke(intmem,stdint); writeln('Bit-map space released'); end; (* deallocate *) procedure show; (* Displays current VDP RAM space *) begin clearline; writeln('Current VDP space is ',peek(topmem)-peek(intmem),' bytes'); end; (* show *) begin (* interpreter *) case ch of 'A' :allocate; 'D' :deallocate; 'S' :show; end; (* case *) end; (* interpreter *) begin (* main *) prline := 'Bitreserve: A(lloc,D(ealloc,S(how,Q(uit'; ret_set := ['A','D','S','Q']; repeat ch := sc_prompt(prline,-1,0,0,0,ret_set,false,','); interpreter(ch); until ch='Q'; end. By reserving space for bitmap prior to loading your program that uses bitmap, you don't fall into the trap that the program you have loaded to use bitmap already have occupied the space you need for bitmap. I think I did set the language type for the program bitreserve to M_9900 instead of pseudo, to make sure it's not itself in VDP RAM. 2 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted July 28, 2023 Share Posted July 28, 2023 Thank you! Do you happen to have the source of the sc_prompt procedure? So when you reassign the pointers, are the code pools immediately relocated? I assume that the change is persistent until the next system reset? Apologies for all the questions, but I have a project in mind that I'd like to implement on the TI. I recently wrote a Boids flocking simulation in Pascal on the TRS-80 Model 4P and it will require bitmap access for a proper display on the TI. The source itself is pretty much standard Pascal and should port quite easily. 1 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted July 28, 2023 Author Share Posted July 28, 2023 (edited) No, I don't have the source for sc_prompt. But that procedure is hosted in unit screenops, which is delivered with the system. Yes, when the pointers are updated, the next request to the code loader to load code into the code pool will take the new values into account. So the probability that the code ends up in the secondary code pool increases dramatically. I think it stays until the next reset, or if you use the program bitreserve to give it back to the system. Well, feel free to use the whole turtlegraphics unit if you like. It's not optimized all the way, and some things aren't fully implemented, but it's useful and works (as far as I know). Look at whtech/programming/pascal/turtle.*. There are a few files, including the one I posted above. OK, looking at it I realize that many of the programs that demonstrate the use of turtlegraphics require my own unit extrascreen too. It's used for keyboard input. Normally you don't want to show an entered key on the screen when bitmap graphics is displayed. My unit extrascreen allows for reading keys without any screen echo. It also allows for doing this even if they keyboard buffer isn't where it normally is, and that's the case when bitmap mode is used. The p-system supports buffered keyboard input, and normally that buffer is in VDP RAM that's needed for bitmap mode. So I have to move it, but that I can handle and so can the system. Edited July 28, 2023 by apersson850 2 1 Quote Link to comment Share on other sites More sharing options...
+Atari2600PAL Posted August 3, 2023 Share Posted August 3, 2023 On 8/22/2020 at 1:43 PM, ralphb said: Here is a DS/DD disk image with all individual P system disks combined. If your controller can handle DS/DD, the disk makes it a lot easier to work with the P system. Thanks to Anders for helping me create this disk! pcode.dsk 360 kB · 106 downloads I'm new to disks/PEB on a 99 (back in the day only had a tape drive & synth) Is it too much to hope that if I upload this dsk file to my TIPI I can just copy the PASCAL file it extracts to a normally formatted disk and it will work with the p-code card please? Many thanks Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted August 3, 2023 Share Posted August 3, 2023 (edited) We were discussing floating point in the CORTEX BASIC thread. I thought of the math library that I had seen. It's math.src from Microprocessor Pascal for TM990/101 microcomputer. I thought it may be of interest here. The formulas are attributed to: Computer Approximations, John F. Hart, et.al., John Wiley & Sons, 1968. ARCTAN(X) SIN(X) COS(X) EXP(X) LN(X) SQRT(X) Pascal source (also see attached). I apologize for any garbage characters - the fpyfile util for sim990 left 2-byte record#s in the text. Spoiler math.src Edited August 3, 2023 by FarmerPotato typos 1 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted August 3, 2023 Author Share Posted August 3, 2023 3 hours ago, Atari2600PAL said: Is it too much to hope that if I upload this dsk file to my TIPI I can just copy the PASCAL file it extracts to a normally formatted disk and it will work with the p-code card please? No, it's not too much. What's imperative is that the PASCAL file is not only transferred, but that it ends up in exactly the same sectors as it originally occupied on the disk it was copied from. Which it normally does, if you copy it to an empty disk. This is due to the fact that the PASCAL file is never used by the p-system. It's there just as a dummy file, to mark the diskette as fully used. The p-system instead accesses certain sectors on the disk, where it has its own file system with directory and files. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.