Jump to content


  • Content Count

  • Joined

  • Last visited

Community Reputation

684 Excellent

1 Follower

About apersson850

  • Rank

Recent Profile Visitors

7,265 profile views
  1. 24 lines with 40 characters each is 960 characters, not 1000. So it's something else.
  2. Just some hints. When you comment like this, it gives you very little information about the size of the different data items. * BYTE 1 /0=OPEN 1 = CLOSED * BYTE 2 FILE TYPE >12 =OUTPUT,VARIABLE DISPLAY * NEXT POSITION=BUFFER ADDRESS * NEXT RECORD LENGTH >50 = 80 BYTES * NEXT CHARACTER COUNT * NEXT RECORD NUMBER * NEXT CASSETTE OFFSET * LAST IS FILELENGTH DESCRIPTOR LENGTH * NOTE: FILE DESCRIPTOR LENGTH * FOR FILE: 'DSK1.FILE1' = 10 >0A TLOAD TEXT 'LOAD DSK ' Do it like this instead. * BYTE Opcode 0=OPEN 1 = CLOSED * BYTE FILE TYPE >12 =OUTPUT,VARIABLE DISPLAY * DATA BUFFER ADDRESS * BYTE RECORD LENGTH >50 = 80 BYTES * BYTE CHARACTER COUNT * DATA RECORD NUMBER * BYTE CASSETTE OFFSET * BYTE FILELENGTH DESCRIPTOR LENGTH * NOTE: FILE DESCRIPTOR LENGTH * FOR FILE: 'DSK1.FILE1' = 10 >0A TLOAD TEXT 'LOAD DSK ' Now you can see the structure of the PAB. Here is a code snippet. CLR @PAGE INC @PAGE * SET PAGE TO 1 LI R0,929 CLR R2 INC R2 * R2=1 LI R3,>3000 * "0 This is a better version LI R0,929 LI R2,1 MOV R2,@PAGE LI R3,'0 ' It's more compact and obvious enough to make the comments you had there redundant. Here too, use the character load for clarity BLWP @VSBR * 1ST WE NEED TO GET THE LENGTH OF THE FILENAME IN R2 CB R1,R3 * ERROR! CANT BE "0 OR LESS" JLE GFERR1 * DISPLAY A MESSAGE LI R3,>3900 * IT HAS TO BE A NUMBER CB R1,R3 JGT GFERR1 * ERROR, NOT 1-9 LI R3,>2E00 * NOW ITS LEGAL, CONTINUE LOOKIN SG FOR "." PERIOD MARK INC R0 INC R2 * R2=2 BLWP @VSBR CB R1,R3 JNE GFERR1 * NOT VALID! ERROR GOTTA HAVE "." INC R0 INC R2 * R2=3 LI R3,>4100 * LOOKING FOR A CHAR VALUE UPPER A-Z BLWP @VSBR CB R1,R3 JLT GFERR1 * NOPE NOT A-Z, ERROR- WAS LESS THAN "A" LI R3,>5A00 * CHECK FOR GREATER THAN "Z" CB R1,R3 JGT GFERR1 * NOPE, NOT A-Z, WAS GREATER THAN "Z" LI R3,>2000 * CHECK FOR SPACE TO GET TOTAL COUNT KLNMH INC R0 INC R2 BLWP @VSBR CB R1,R3 * FOUND END OF NAME YET?, NO, KEEP LOOKING JNE KLNMH * KEEP LOOKING FOR NAME HERE AI R2,2 * WE ADD IN THE "DSK" 3 BYTES TO GET OUR FULL DESCRIP # MOV R2,@COUNT * SAVE THE LENGTH OF FILENAME LI R0,926 LI R1,FLNM * FILENAME BUFFER BLWP @VMBR When you read incremental data from the VDP, there's no need to use the VSBR procedure. The VDPRD address is autoincrementing, so it will give you the next byte each time you access it. SWPB R0 * 1ST WE NEED TO GET THE LENGTH OF THE FILENAME INTO R1 MOVB R0,@VDPWA * Set up the VDP address for reading SWPB R0 MOVB R0,@BDPWA NOP MOVB @VDPRD,R1 * Now you fetch consecutive characters by just reading the data, which is much faster than calling VSBR CB R1,R3 * ERROR! CANT BE "0 OR LESS" JLE GFERR1 * DISPLAY A MESSAGE LI R3,'9 ' * IT HAS TO BE A NUMBER CB R1,R3 JGT GFERR1 * ERROR, NOT 1-9 LI R3,'. ' * NOW ITS LEGAL, CONTINUE LOOKING FOR "." PERIOD MARK INC R2 * R2=2 CB @VDPRD,R3 * Here you only compare once, so you don't need to save the value in R1 JNE GFERR1 * NOT VALID! ERROR GOTTA HAVE "." INC R2 * R2=3 LI R3,'A ' * LOOKING FOR A CHAR VALUE UPPER A-Z MOVB @VDPRD,R1 * Here you must save it in R1, since you want to compare it against two values CB R1,R3 JLT GFERR1 * NOPE NOT A-Z, ERROR- WAS LESS THAN "A" LI R3,'Z ' * CHECK FOR GREATER THAN "Z" CB R1,R3 JGT GFERR1 * NOPE, NOT A-Z, WAS GREATER THAN "Z" LI R3,' ' * CHECK FOR SPACE TO GET TOTAL COUNT KLNMH CB @VDPRD,R3 * Since you are using the value only once here, you can compare what you get from the VDP directly to your match value. No need to store it in R1 JNE KLNMH * KEEP LOOKING FOR NAME HERE AI R2,3 * WE ADD IN THE "DSK" 3 BYTES TO GET OUR FULL DESCRIP # So you better add three, not two MOV R2,@COUNT * SAVE THE LENGTH OF FILENAME Where is COUNT? The file name counter you have defined is called COUNTP. Since it's a byte, you can't move it like this either LI R0,926 LI R1,FLNM * FILENAME BUFFER BLWP @VMBR This part is still wrong. First you define 10 bytes with PAB data. Then you have COUNTP (or should it be COUNT?) as the first byte after the PAB data fields. But it shouldn't be there, it should be the last byte in the PAB data field. The file name shall start at where COUNTP is now. The count should be at FSPAB+9, but now it's at FSPAB+10. FSPAB DATA >0012,SBUFF,>8000,>0000,>0000 * OP DV 128 COUNTP BYTE 0 FLNM BSS 48 You can take advantage of the fact that you don't intend to offer cassette storage when you move the file name length to the PAB. That means that instead of doing something like SWPB R2 MOVB R2,@FSPAB+9 You can do this MOV R2,@FSPAB+8 This means that the byte before the count will get the value zero, but since it's used by the tape DSR only, that doesn't matter here. You still don't have to save R11 in routines where you don't destroy R11 inside the routine. Besides, when you don't use all workspace registers, it's more efficient to save R11 into a register, like R10. At the end, you can then just B *R10. RT is not an instruction. It's a macro, which translates to B *R11. You can use RT, but then it's only RT, not RT *R11.
  3. That's good. Make a map of what you use, so you don't use one thing for multiple purposes at the same time.
  4. Yes, when you save data you have to put it in the buffer, then call the DSR. If you read data, you have to call the DSR then handle the data it placed in the buffer for you. And each time, you only move one record at a time (128 bytes in this case). So you need to do it many times if you have a lot of data on a SAMS card. You're right in that a filename is often max 10 characters. Like ASMFILETXT or BASICGAME1. But to the system, that's just a partial file name. To actually locate the file BASICGAME1, you need the full file name, which could be DSK2.BASICGAME1. Or even DSK.GAMEDISK.BASICGAME1.
  5. OK, that makes sense to allocate 50 bytes for PAB data plus the name. But the FLNM block is only 16, so that doesn't match, then. It's not futureproof in the same way.
  6. Since you load a READ command, you are going to read data from a file and place it in SAMS memory, not the other way around. Or you used the wrong command. If you want to store your SAMS pages in a file, you want to write. Whichever, to store the data on disk, you have to read one record (128 bytes) from memory to VDP RAM buffer, do a write operation (call the DSR), increment the record counter in the PAB in VDP memory and do it again, until you've stored everything you want to store. Since you, for some reason I don't know, have decided to have 1000 characters in a page, not 1024, but have chosen to use a record length of 128, which isn't an integer fraction of 1000, you have to deal with the mess that you have to move seven records 128 bytes long and one 104. Or in each record store 125 valid bytes and three garbage, then just don't care about the garbage. It's inefficient programming, whichever you do.
  7. Having space for 16 characters in a file name makes no sense, since a valid file name on a disk is up to 25 bytes long. Like DSK.DISKNAMEIS.FILENAMEIS Placing the new PAB 50 bytes before the previous one doesn't make sense either, if it's only 27 bytes long. What are you going to do with the 23 bytes in between? They aren't enough for a buffer anyway. I would recommend allocating the PAB with mixed BYTE and DATA directives, matching the actual use of the data. That makes the program easier to understand.
  8. Where you can position you PAB in VDP RAM does of course depend on your runtime environment. If you make support routines running under Extended BASIC you have one scenario. If you are using Pascal, Forth or whatever, you have different scenarios. When you run a pure assembly program, you define the scenario. There are assumptions when your program starts, depending on if it's loaded by Editor/Assembler module or something else, but you can change them as you like. The BYTE and DATA directives generate code with specific data. BYTE 27 BYTE 32 DATA 15364 will generate four bytes of code. BSS 4 as well as BES 4 will reserve space for four bytes of data, but no specific value will be loaded. Normally, the loader program will just skip these bytes, and start loading values four bytes further ahead. Thus COUNT BSS 16 will reserve the same amount of space as COUNT BYTE 0 BSS 15 but in the second case, you are certain that COUNT is set to zero when the program starts.
  9. Is this some midnight math too, or what do you mean here? If we are talking real disk sectors, then they are 256 bytes. Each can hold exactly two records that are 128 bytes long. A 1 K page will fill exactly four sectors. Now assuming you are talking kilobyte, not 1000 characters. But since a kilobyte is 1024 bytes, the difference isn't 28 there either.
  10. A touch of chaos theory in that.
  11. I have 64 K RAM, 16 bit wide, in my console. It can cover the whole address range. Mapped in and out in 8K blocks by CRU bits at >400. One advantage of this is that if I map out the 32 K RAM part, then anything "below" becomes visible. So my design allows for simply paging out the 16 bit wide RAM, and revert to the standard memory expansion in the PEB, if necessary. It also allows for copying the resident monitor program to RAM, then modify it, if desired.
  12. In a way your calculator is correct. Hex 1F40 is really 8000 decimal, but 8 kilobytes amounts to 8192 bytes. Which is hex 2000. The p-system was designed to provide portable source code (a big issue before things like Windows inhabitate a lot of machines out there) and run in small memory (a big issue when hardly any reasonably priced computer had more than 64 K RAM). Portability we don't have much use for today, but running in small memories is still needed to run the p-system on the TI 99/4A.
  13. Note that this post is a sidetrack from the main subject. But I just thought about how many different ways there are to manage memory. Here in Forth we have the data stack in high 24 K memory and code storage in low 24 K memory. Then we have the return stack in high 8 K memory. If you look at the p-system (Pascal), it uses only one stack, for both data and return addresses. It's in the same place as for Forth, high 24 K RAM. At the low end of the 24 K memory is the heap, which is an area used for dynamically created variables and memory locked code. In between is the secondary code pool, where code that can be relocated, even after loading it, is placed. Normal p-code is relocatable any number of times. When requesting memory from the heap, or trying to push data to the stack, the system will create a fault if the request can't be granted. Then a memory manager is called, which investigates if moving the code in one direction can create enough available memory in the other direction. If the code is segmented, then any segments that aren't called at the moment can be removed from memory, to release more memory for other purposes. If the removed code is later needed again, it will be reloaded from disk. Since p-code is a byte-code, it can also run from VDP RAM. That's where the primary code pool is located, to avoid code competing with the heap and stack for memory. It's only if the primary code pool is full, or if code that has to be memory locked (like code containing assembly instructions), that code is loaded to the secondary code pool in expansion RAM. The heap allows for un-synchronized allocations and releases of data. This means that free holes can be created inside the heap. They are also managed and can be re-used, also automatically. All this is automatic within the p-system, which is yet another reason for why it's not as fast as Forth. But it's very memory efficient. The fact that the p-system can combine the data and return stacks is to a large extent due to that the main language, Pascal, works with local data associated with each procedure/function. When a procedure is called, an activation record, with space for all local variables, is allocated on the stack. This record lives as long as the procedure is called, which means that also pushing the return address (and some other data, in something called a Mark stack control word, MSCW) at the same time, to the same stack, makes sense.
  14. And then there's a return stack somewhere too, right?
  • Create New...