+Vorticon Posted July 18 Share Posted July 18 I find the am/pm scheme cumbersome personally and much prefer 24hr time. 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted July 18 Share Posted July 18 Inspired by @TheBF, I went ahead and created a clock unit which can display various formats of date and time anywhere on the text screen. I can't demo it right now as I am on my laptop and not on real hardware but it should work just fine. Spoiler unit clockutil; {displays various formats of date/time} interface procedure stamp(x, y : integer); procedure long_date(x, y : integer); procedure date(x, y : integer); procedure dmy(x, y : integer); procedure mdy(x, y : integer); procedure long_time(x, y : integer); procedure time(x, y : integer); implementation procedure getdow(dow : integer; var downame : string); {converts numeric dow to named dow} {sunday = 1} var dowstr : array[1..7] of string; begin dowstr[1] := 'sunday'; dowstr[2] := 'monday'; dowstr[3] := 'tuesday'; dowstr[4] := 'wednesday'; dowstr[5] := 'thursday'; dowstr[6] := 'friday'; dowstr[7] := 'saturday'; downame := dowstr[dow]; end; (* getdow *) procedure getmonth(month : integer; var monthname : string); {convert numeric month to named month} var monthstr : array[1..12] of string; begin monthstr[1] := 'january'; monthstr[2] := 'february'; monthstr[3] := 'march'; monthstr[4] := 'april'; monthstr[5] := 'may'; monthstr[6] := 'june'; monthstr[7] := 'july'; monthstr[8] := 'august'; monthstr[9] := 'september'; monthstr[10] := 'october'; monthstr[11] := 'november'; monthstr[12] := 'december'; monthname := monthstr[month]; end; (* getmonth *) procedure cdate(var day, dow, month, year : integer); external; procedure ctime(var sec, min, hr : integer); external; procedure stamp; {format: short-dow, short-month day, year, hr:min:sec} var dow, month, day, year, sec, min, hr : integer; dowstr, monthstr : string; begin ctime(sec, min, hr); cdate(day, dow, month, year); getdow(dow, dowstr); dowstr := copy(dowstr, 0, 3); getmonth(month, monthstr); monthstr :=copy(monthstr, 0, 3); gotoxy(x, y); writeln(dowstr,', ',monthstr,' ',day,', ',year,' ', hr,':',min,':',sec); end; (* stamp *) procedure long_date; {format: long-dow, long-month day, year} var dow, day, month, year : integer; dowstr, monthstr : string; begin cdate(day, dow, month, year); getdow(dow, dowstr); getmonth(month, monthstr); gotoxy(x, y); writeln(dowstr,', ',monthstr,' ',day,', ',year); end; (* long_date *) procedure date; {format: short-month day, year} var dow, day, month, year : integer; monthstr : string; begin cdate(day, dow, month, year); getmonth(month, monthstr); monthstr := copy(monthstr, 0, 3); gotoxy(x, y); writeln(monthstr,' ',day,', ',year); end; (* date *) procedure dmy; {format: day/num-month/short-year} var dow, day, month, year : integer; begin cdate(day, dow, month, year); year := year - 2000; gotoxy(x, y); writeln(day,'/',month,'/',year); end; (* dmy *) procedure mdy; {format: mum-month/day/short-year} var dow, day, month, year : integer; begin cdate(day, dow, month, year); year := year - 2000; gotoxy(x, y); writeln(month,'/',day,'/',year); end; (* mdy *) procedure long_time; {format: hr:hr min:min sec:sec} var sec, min, hr : integer; begin ctime(sec, min, hr); gotoxy(x, y); writeln('hr:',hr,' min:',min,' sec:',sec); end; (* long_time *) procedure time; {format: hr:min:sec} var sec, min, hr : integer; begin ctime(sec, min, hr); gotoxy(x, y); writeln(hr,':',min,':',sec); end; (* time *) end. (* clockutil *) 2 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted July 18 Share Posted July 18 Many years ago I had centre-fold from a magazine on my locker door, that was a red velvet cloth with a Pascal listing spread out on the cloth. I am thinking of that centre-fold when I see your code. 🤣 I noticed the confused icon. The implication from the computer magazine (April 1st issue) centre-fold was that Pascal was "beautiful". 1 1 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted July 18 Author Share Posted July 18 I have a program for my real TI 99/4A where it sets the hardware clock chip to generate interrupts and when that happens, it prints the current time in the upper right corner of the screen. Overwriting what may be there, but that doesn't matter with the p-system, since it writes on the physical screen, not the 80 column screen block. So the data that used to be on the screen in that corner is still there, just not visible. 3 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted July 18 Share Posted July 18 1 hour ago, apersson850 said: I have a program for my real TI 99/4A where it sets the hardware clock chip to generate interrupts and when that happens, it prints the current time in the upper right corner of the screen. Overwriting what may be there, but that doesn't matter with the p-system, since it writes on the physical screen, not the 80 column screen block. So the data that used to be on the screen in that corner is still there, just not visible. The IDE RTC can actually generate interrupts. How would you detect them in UCSD Pascal? Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted July 19 Share Posted July 19 20240718_214339.mp4 CLOCK.DSK 2 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted July 19 Share Posted July 19 13 hours ago, TheBF said: The implication from the computer magazine (April 1st issue) centre-fold was that Pascal was "beautiful". "Erotic" is probably more in line with a centerfold 😂 1 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted July 20 Author Share Posted July 20 On 7/19/2024 at 1:44 AM, Vorticon said: The IDE RTC can actually generate interrupts. How would you detect them in UCSD Pascal? The system does that. I just wrote a DSR, which rather was an ISR (Interrupt Service Routine). That ISR read the time from the clock and put it in VDP RAM at a position which ends up in the upper right corner. There's a VDP R1 copy in RAM, so I could check if the screen was 32 or 40 characters wide automatically. As soon as the clock is set to generate interrupts the P-system will service them. 2 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted July 20 Share Posted July 20 I had some time on my hands and was reading about probabilities, so I created this quick and dirty program to calculate the probability of having a certain number of heads for n consecutive coin tosses. It forced me to deal with the vagaries of precision limitations, real variables formatting, as well as write power and factorial functions. Time well spent Spoiler program cointoss; {calculates probability of head or tail outcomes (h) in n tosses} var i, n : integer; prob, factn, pwrneg2 : real; function fact(n : integer) : real; {calculate the factorial of an integer} var f : real; begin f := n; if n in [0, 1] then fact := 1 else begin repeat n := n - 1; f := f * n; until n = 1; fact := f; end; end; (* fact *) function pwr(n : real; m : integer) : real; {calculate n to the power of integer m} var p : real; begin if m = 0 then pwr := 1.0 else if m = 1 then pwr := n else begin if m < 0 then begin p := 1.0; repeat p := p / n; m := m + 1; until m = 0; pwr := p; end else begin p := n; repeat p := p * n; m := m - 1; until m = 0; pwr := p; end end; end; (* pwr *) begin page(output); gotoxy(0, 2); write('number of tosses: '); readln(n); factn := fact(n); pwrneg2 := pwr(2, -n); gotoxy(0, 5); for i := 0 to n do begin prob := (factn / (fact(i) * fact(n - i))) * pwrneg2; write('h: ', i); gotoxy(6, i + 5); writeln('prob: ', prob:12:8); end; end. (* cointoss *) COINTOSS.mp4 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted July 20 Share Posted July 20 4 hours ago, apersson850 said: The system does that. I just wrote a DSR, which rather was an ISR (Interrupt Service Routine). That ISR read the time from the clock and put it in VDP RAM at a position which ends up in the upper right corner. There's a VDP R1 copy in RAM, so I could check if the screen was 32 or 40 characters wide automatically. As soon as the clock is set to generate interrupts the P-system will service them. I thoughts interrupts were disabled with the pcode system. I guess I'm wrong then. Quote Link to comment Share on other sites More sharing options...
apersson850 Posted July 21 Author Share Posted July 21 8 hours ago, Vorticon said: I thoughts interrupts were disabled with the pcode system. I guess I'm wrong then. Well, yes and no. Hardware interrupts into the CPU are disabled. But the PME implements a virtual processor where the TMS 9900 executes the "microcode" (which is standard assembly instructions) to implement the "assembly language" (which is p-code). The "microcode" (assembly, really) running the PME also senses the interrupt pin to check if there is an interrupt pending. If there is, it's serviced. So yes, the p-system does respond to interrupts, but it does it on a higher logical level than normal. This does of course mean that interrupt latency is larger, since there will be several assembly instructions between each interrtupt serviced. For hardware interrupts is only one assembly instruction. Here it's at least one p-code, and frequently more. So the p-system is clearly not built to react precisely on microsecond things, not even milliseconds, but handle interrupts every 1/10 s it can very well do. On the other hand this approach also means that you can do other things than standard when you get an interrupt request from the VDP, for example. The p-system also handles the full keyboard and thus implements the type-ahead queue, so you can use the keyboard to type in a response to a question even before the question is shown on the screen. 1 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted July 21 Share Posted July 21 8 hours ago, apersson850 said: Well, yes and no. Hardware interrupts into the CPU are disabled. But the PME implements a virtual processor where the TMS 9900 executes the "microcode" (which is standard assembly instructions) to implement the "assembly language" (which is p-code). The "microcode" (assembly, really) running the PME also senses the interrupt pin to check if there is an interrupt pending. If there is, it's serviced. So yes, the p-system does respond to interrupts, but it does it on a higher logical level than normal. This does of course mean that interrupt latency is larger, since there will be several assembly instructions between each interrtupt serviced. For hardware interrupts is only one assembly instruction. Here it's at least one p-code, and frequently more. So the p-system is clearly not built to react precisely on microsecond things, not even milliseconds, but handle interrupts every 1/10 s it can very well do. On the other hand this approach also means that you can do other things than standard when you get an interrupt request from the VDP, for example. The p-system also handles the full keyboard and thus implements the type-ahead queue, so you can use the keyboard to type in a response to a question even before the question is shown on the screen. You got my attention. Do you happen to have example code about this? I can see using this for timing functions and such. 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted July 21 Share Posted July 21 When a disk pcode disk image is transferred to the TIPI, the latter automatically converts it into a folder containing 2 files: .sector and PASCAL. If anyone in using TIPI disks with the pcode card (I may be the only one but you never know...), the .sector file is the actual disk image which can be opened by pcode tool, NOT the PASCAL file in the same folder. Thanks to @Rhodanaj for figuring this out. This is important if you plan on sharing these images or using them under emulation. 4 1 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted July 22 Author Share Posted July 22 (edited) That's probably the "pseudo-file" called PASCAL in the standard OS that you see too. It's there just to make the whole disk occupied and make it possible to copy it with the Disk Manager module. I had bad luck with some source code for my clock card. I can check, but it could be that I only have the executable files left... But to use this interrupt function I have requires a DSR with an interrupt service on the clock card. Since I made my own, I designed it to have the clock chip, some CRU config bits and some RAM. I use that memory to load the DSR into. At boot time, the p-system scans all external cards to see if they have valid interrupt service code. So in my computer, it will store a list of CRU addresses 1300H and 1400H, for the RS232 and clock cards. The it will examine the pre-listed cards on interrupt to see who's calling for attention. Edited July 22 by apersson850 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted July 24 Share Posted July 24 So in theory the system should be able to recognize the IDE card as an interrupt generating card at boot? If that's the case, then what I need to understand is how to service the clock interrupt. I've never worked with interrupts before and I would have loved to see some example assembly code. I'll post that question on the assembly thread. Quote Link to comment Share on other sites More sharing options...
+TheBF Posted July 24 Share Posted July 24 7 hours ago, Vorticon said: So in theory the system should be able to recognize the IDE card as an interrupt generating card at boot? If that's the case, then what I need to understand is how to service the clock interrupt. I've never worked with interrupts before and I would have loved to see some example assembly code. I'll post that question on the assembly thread. The P code cards use of the word "interrupt" is different than the hardware's concept of the word "interrupt" in that in the P code system it's really the P Code system polling to see if it needs to take over and do something. With hardware on the 9900 the CPU actually stops running the code it's doing and does the equivalent of BLWP to a vector in a table of vectors starting at >0000. (TI-99 design locks that table in ROM which kind of sucks. @apersson850 rigged his memory so he can replace the ROM with RAM so he can write the table anyway he wants. I am jealous) 2 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted July 25 Author Share Posted July 25 I'll see if I can dig up the source to my clock card's DSR. Yes, if you want to look at the p-system in the traditional way, then you have to do as I explained. View the assembly code in the PME as equivalent to the microcode in a real CPU and the p-code as the assembly code. Then suddenly you are back on track, since what a real CPU does is that during a suitable microcode cycle (CPU state), it will poll the interrupt input to the chip and see if there's any request. If there is, then the microcode will do what's needed to start running the interrupt service and to make it possible to return to the previous task without losing track of what was going on before the interrupt. The PME instead uses the assembly code to poll the interrupt and stop executing p-code when there is a request. In the 99/4A, the whole interrupt service sequence is written in assembly. Part of it runs in the 8 K RAM part of memory, since servicing interrupts may imply turning the p-code card off, in case the interrupt comes from another card in the box. I've used my console's ability to change the interrupt vectors to implement a multitasking system in assembly. I used the TMS 9901's as a task switch timer. You can't do that unless you can change what's executed on an interrupt. 3 Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted July 25 Share Posted July 25 8 hours ago, apersson850 said: View the assembly code in the PME as equivalent to the microcode in a real CPU and the p-code as the assembly code. Then suddenly you are back on track, since what a real CPU does is that during a suitable microcode cycle (CPU state), it will poll the interrupt input to the chip and see if there's any request. If there is, then the microcode will do what's needed to start running the interrupt service and to make it possible to return to the previous task wi I'm sure you know this but I found it fascinating that: 9900 Interrupts are granted only after an instruction completes, though they can be sampled (latched) earlier. Documented in CPU flowcharts and timing diagrams in the data books. Interrupts are NOT granted immediately after a context switch. At least one instruction executes, so an interrupt handler may do LIMI 0 first to protect a critical section. And the 9900 instructions are not interruptible while in progress. In the two 9900 implementations I've studied this year, there is indeed a bit in the micro-instruction word to sample interrupts. I like your choice of "cycle" for this--much more relatable. (Two implementations are documented: 990/12 and TM990/1481. The 9995 and 99105 are partially revealed in patent disclosures.) 3 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted July 29 Share Posted July 29 Finally got around to modifying my SYSTEM.STARTUP file to automatically fetch the date and time and store it on the boot disk (#4). This is based on @apersson850's startup file, with several modifications made obviously to account for my own system. I store the time in sector 3 as 3 separate integers (HR, MIN, SEC) instead of a string since my clock procedures return integers. The attached boot disk includes the Editor, Filer and Compiler as well as the SYSTEM.STARTUP file which assumes that an IDE card with RTC is present at CRU >1900. Spoiler (*$R- *) (* Turn off range checking *) PROGRAM INITSTATE; USES MISC, {$U COMMANDIO.CODE} COMMANDIO; (* This program is a modified version of the MODRS232 * * utility program and sets the PRINTER: to PIO and REMIN/REMOUT: to * * 2400 8-N-1. Also reads the ide rtc and sets the time. * * Assumes IDE with RTC at cru >1900. *) const rddata = -30720; rdstat = -30718; wrtdata = -29696; wrtaddr = -29694; wrtenab = 16384; pabtbl = 10716; (* hex 29dc *) maxlen = 43; DATELOC = 13840; {RAM LOCATION OF SYSTEM DATE} DIGIT = '0123456789'; type byte = 0..255; DUAL = record case boolean of true: (int: integer); false:(ptr:^integer); end; BYTEWORD = RECORD CASE BOOLEAN OF TRUE : (VALUE : INTEGER); FALSE : (BYTES : PACKED ARRAY[1..2] OF BYTE); END; DIRTYPE = RECORD TFILL1 : PACKED ARRAY[0..11] OF CHAR; {SECTOR 3} HR : INTEGER; MIN : INTEGER; SEC : INTEGER; TFILL2 : PACKED ARRAY[0..237] OF CHAR; FILL1 : PACKED ARRAY[0..19] OF CHAR; (* SECTOR 4, PASCAL DIRECTORY *) DLASTBOOT : INTEGER; FILL2 : PACKED ARRAY[0..489] OF CHAR; (* SECTORS 4 AND 5 *) END; var cpuaddr: DUAL; curlen,period,vdpaddr: integer; savevdpaddr: integer; ch: char; unitno: integer; i,j: integer; pabname:string[43]; action, date : string; err : boolean; WORD : BYTEWORD; YEAR, MONTH, DAY, DOW, SEC, MIN, HR : INTEGER; MONTHNAME, MSTRING : STRING; DIRECTORY : DIRTYPE; MONTHSTR : ARRAY[1..12] OF STRING; PROCEDURE CDATE(VAR DAY, DOW, MONTH, YEAR : INTEGER); EXTERNAL; PROCEDURE CTIME(VAR SEC, MIN, HR : INTEGER); EXTERNAL; PROCEDURE POKE(ADDR, VALUE : INTEGER); VAR LOC : DUAL; BEGIN {POKE} LOC.INT := ADDR; LOC.PTR^ := VALUE; END; {POKE} FUNCTION PEEK(ADDR : INTEGER) : INTEGER; VAR LOC : DUAL; BEGIN {PEEK} LOC.INT := ADDR; PEEK := LOC.PTR^; END; {PEEK} procedure swapbyte(var x:integer); (* This procedure takes a word and reverses the order of the bytes *) type byteword = record case boolean of true: (addr:integer); false:(bytes: packed array[1..2] of byte); end; var word: byteword; tbyte: byte; begin with word do begin addr := x; tbyte := bytes[1]; bytes[1] := bytes[2]; bytes[2] := tbyte; x := addr; end; (* with statement *) end; (* procedure *) procedure wrtvdpaddr (vdpaddr : integer); (* This procedure initializes the VDP ram chip to read/write from the * * address passed in the parameter vdpaddr. *) begin cpuaddr.int := wrtaddr; swapbyte( vdpaddr ); cpuaddr.ptr^ := vdpaddr; swapbyte( vdpaddr ); cpuaddr.ptr^ := vdpaddr; end; (* procedure *) function rdvdp (var vdpaddr : integer) : integer; (* This function reads a byte of data from the VDP ram address specified * * in the parameter vdpaddr. *) begin wrtvdpaddr( vdpaddr ); cpuaddr.int := rddata; rdvdp := cpuaddr.ptr^ div 256; (* Right justify byte in word *) vdpaddr := vdpaddr + 1; end; (* procedure *) procedure wrtvdp( var vdpaddr : integer; data : integer); (* This procedure writes the byte of data passed in the parameter * * data to the VDP ram address specified in vdpaddr. *) var temp : integer; begin temp := vdpaddr + wrtenab; (* Write enable the address *) wrtvdpaddr(temp); cpuaddr.int := wrtdata; cpuaddr.ptr^ := data * 256; (* Left justify byte in word and write *) vdpaddr := vdpaddr + 1; end; (* procedure *) begin (* main program *) MONTHSTR[1] := 'JAN'; MONTHSTR[2] := 'FEB'; MONTHSTR[3] := 'MAR'; MONTHSTR[4] := 'APR'; MONTHSTR[5] := 'MAY'; MONTHSTR[6] := 'JUN'; MONTHSTR[7] := 'JUL'; MONTHSTR[8] := 'AUG'; MONTHSTR[9] := 'SEP'; MONTHSTR[10] := 'OCT'; MONTHSTR[11] := 'NOV'; MONTHSTR[12] := 'DEC'; unitno := 6; (* select PRINTER: *) pabname := 'PIO'; for j := 1 to 2 do begin cpuaddr.int := pabtbl + unitno * 2; vdpaddr := cpuaddr.ptr^ + 17; savevdpaddr := vdpaddr; period := 0; for i := 1 to length(pabname) do begin if (period = 0) and (pabname[i] = '.') then period := i - 1; if pabname[i] in ['a'..'z'] then pabname[i] := chr(ord(pabname[i])-32); end; (* for loop *) if period = 0 then period := length(pabname); vdpaddr := savevdpaddr-17; for i := 1 to 2 do wrtvdp(vdpaddr,0); wrtvdp(vdpaddr, period); for i := 1 to 3 do wrtvdp(vdpaddr, 0); vdpaddr := savevdpaddr; for i := 0 to length(pabname) do wrtvdp(vdpaddr, ord(pabname[i])); unitclear(unitno); unitno := 7; (* select REMIN/REMOUT: *) pabname := 'RS232/1.BA=2400.DA=8.PA=N.EC'; end; GOTOXY(1,2); WRITELN; writeln('PRINTER: PIO'); writeln('REMIN/REMOUT: RS232/1.BA=2400.DA=8.PA=N.EC'); writeln; (* prompt for the date and set it *) MONTHNAME := 'JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'; {GET SYSTEM DATE} WORD.VALUE := PEEK(DATELOC); YEAR := WORD.BYTES[1] DIV 2; WORD.VALUE := WORD.VALUE * 16; DAY := ORD((ODD(WORD.BYTES[1])) AND (ODD(31))); MONTH := WORD.BYTES[2] DIV 16; MSTRING := COPY(MONTHNAME,MONTH * 3 - 2, 3); {GET SYSTEM TIME} UNITREAD(4, DIRECTORY, SIZEOF(DIRECTORY), 1); HR := DIRECTORY.HR; MIN := DIRECTORY.MIN; SEC := DIRECTORY.SEC; WRITELN('LAST BOOT: ',DAY,'-',MSTRING,'-',YEAR,' ',HR,':',MIN,':',SEC); {GET CURRENT DATE} WRITELN('CURRENT DATE:',CHR(7)); CDATE(DAY, DOW, MONTH, YEAR); CTIME(SEC, MIN, HR); GOTOXY(14, 7); WRITELN(DAY,'-',MONTHSTR[MONTH],'-',YEAR,' ',HR,':',MIN,':',SEC); {UPDATE SYSTEM DATE IN RAM} I := (YEAR * 512) + (DAY * 16) + MONTH; POKE(DATELOC, I); {UPDATE ROOT DISK WITH DATE} DIRECTORY.HR := HR; DIRECTORY.MIN := MIN; DIRECTORY.SEC := SEC; DIRECTORY.DLASTBOOT := I; UNITWRITE(4,DIRECTORY,SIZEOF(DIRECTORY),1); END. UCSD Pascal Startup.mp4 EDT-COMP.dsk 4 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted August 2 Share Posted August 2 So I was reviewing the SYSTEM.STARTUP code and realized that I was not reserving space for sectors 0 to 2 in the DIRTYPE record, and so UNITREAD and UNITWRITE were retrieving that record starting at sector 0 and thus fetching or writing from/to the wrong location, and yet everything still works normally but really shouldn't. @apersson850's startup file does include fillers in the DIRTYPE record for sectors 0-2. What gives? DIRTYPE = RECORD *** HERE I SHOULD HAVE HAD 3 FILL ARRAYS EACH 256 BYTES LONG TO ACCOUNT FOR SECTORS 0-2 *** TFILL1 : PACKED ARRAY[0..11] OF CHAR; {SECTOR 3} HR : INTEGER; MIN : INTEGER; SEC : INTEGER; TFILL2 : PACKED ARRAY[0..237] OF CHAR; FILL1 : PACKED ARRAY[0..19] OF CHAR; (* SECTOR 4, PASCAL DIRECTORY *) DLASTBOOT : INTEGER; FILL2 : PACKED ARRAY[0..489] OF CHAR; (* SECTORS 4 AND 5 *) END; 1 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted August 2 Author Share Posted August 2 There is a special mode bit for physical disk access, i.e. block 0 is sectors 0 and 1. Otherwise block 0 is sectors 4 and 5, since 0-3 are reserved for the standard disk directory headers. Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted August 4 Share Posted August 4 On 8/2/2024 at 9:01 AM, apersson850 said: There is a special mode bit for physical disk access, i.e. block 0 is sectors 0 and 1. Otherwise block 0 is sectors 4 and 5, since 0-3 are reserved for the standard disk directory headers. I still don't understand why this worked Quote Link to comment Share on other sites More sharing options...
apersson850 Posted August 8 Author Share Posted August 8 (edited) You used unitread/write to start accessing logical disk block 0, which is in sectors 4-5. Looking at your code, you access block 1, which is in sectors 6-7. The p-system's directory is in sectors 4-7, so you're accessing the latter part of that. It's usually not used on a system disk, as it tend to have rather larger files and thus not very many. Your program will probably cause issues on disks with more files. In my program I used unitread/unitwrite in physical access mode, which implies that block 0 is in sectors 0-1. The optional control flag at the end of the parameter list determines the mode. The second least significant bit (value 2) is the logical/physical access bit. This is from the Texas Instruments Professional computer UCSD p-system Internal Architecture software library manual. Note that there's an error in bit numbers in the last two rows. Should be Bits 4-12 and then Bits 13-15. The 99/4A uses one of the user-defined bits (bit 14) to control the buffer location as being CPU or VDP RAM. This makes it possible to read VDP data directly from disk into the VDP RAM where you want it to be. Like character definitions or screen content. Edited August 8 by apersson850 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted August 8 Share Posted August 8 There is no mention of a "control" parameter in the compiler manual for UNITREAD/UNITWRITE. In your startup file, you have the following: (* Write information back to directory *) unitwrite(4,directory,sizeof(directory),0); Where exactly is that control parameter? Is it that last integer value? If it is then its not the correct value per your explanation and besides the manual only mentions that it's meant for VDP access if set to 16384... I must be missing something obvious here... Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted August 10 Share Posted August 10 Not precisely on topic, but, here is a 1979 paper on creating the TI PASCAL compiler. This is the source-code-portable Pascal, designed for use anywhere in TI. They were really going all-in on Pascal--big color advertisements in 1980 in Mini-Micro Systems. TI Pascal adopted several language extensions, including new forms of CASE, WITH, FOR, and forbidding GOTO (ESCAPE is used to break out of a loop). The compiler produces Common Intermediate Language (CIL), which is accepted by a Machine-Independent OPTimizer. Finally, code generators were made for TI-990 , TI-980, and IBM 370. The whole process was kept within 64K of memory. 4 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.