+Vorticon Posted May 14 Share Posted May 14 Where is all the TI-centric p-system software? I checked out the Whtech site and all there is are the system disks. I'm looking for examples of what was achieved using that system aside from @apersson850's own work. Were there any games made for it using the TI libraries included with the system? The documentation for these can be spotty in places or missing important information (such as the sound volume detail discussed above), or advanced usage of sprites. For example, I am a bit unclear on the usage of the SPRITE_CHANGE_LIST. When I create a sprite using the SET_SPR_ATTRIBUTE function which is supposed to automatically create a SPRITE_CHANGE_LIST, how do I subsequently access specific fields for that sprite such as color or position since I don't know the name assigned to that list? So far the only way to do this that I know of is to use the SET_SPR_ATTRIBUTE function each time I want to make a change to the sprite, and that's a slow function. There has to be a better way. 1 Quote Link to comment https://forums.atariage.com/topic/193355-pascal-on-the-994a/page/40/#findComment-5466184 Share on other sites More sharing options...
Tursi Posted May 14 Share Posted May 14 I don't have a lot to contribute to Pascal discussion, but I do remember that 99er published a Pascal game called Cannibal. I never saw it run 1 1 Quote Link to comment https://forums.atariage.com/topic/193355-pascal-on-the-994a/page/40/#findComment-5466460 Share on other sites More sharing options...
+Vorticon Posted May 15 Share Posted May 15 4 hours ago, Tursi said: I don't have a lot to contribute to Pascal discussion, but I do remember that 99er published a Pascal game called Cannibal. I never saw it run I'll see if I can find it. Thanks! Quote Link to comment https://forums.atariage.com/topic/193355-pascal-on-the-994a/page/40/#findComment-5466637 Share on other sites More sharing options...
apersson850 Posted May 15 Author Share Posted May 15 22 hours ago, Vorticon said: ...and that's a slow function. There has to be a better way. The advantages of separately compiled units are many, but speed isn't one of them. An inter-segment external global call is about the slowest thing you can execute as a p-code. If you want to do a graphical game in Pascal for some reason, then you need to do something special with the graphics, I would presume. Quote Link to comment https://forums.atariage.com/topic/193355-pascal-on-the-994a/page/40/#findComment-5466805 Share on other sites More sharing options...
+Vorticon Posted May 15 Share Posted May 15 I do have a project in mind. We'll see if it comes together. Quote Link to comment https://forums.atariage.com/topic/193355-pascal-on-the-994a/page/40/#findComment-5466997 Share on other sites More sharing options...
+Vorticon Posted May 16 Share Posted May 16 To answer my own questions about sprite usage, you can either set up a SPRITE_CHANGE_LIST manually or use SET_SPR_ATTRIBUTE, but not both because they will overwrite each other. The former is cumbersome because it's very verbose, but it's much faster than the latter once it is set up and provides you with additional features such as a sprite "lifespan countdown" and automatic linking to other lists, so it's a trade off. Below is an example. Link is already pre-defined by the SPRITE unit. var car0 : link; begin (* define new sprite *) new(car0); car0^.packet := [spr_pattern..spr_x_vel]; with car0^ do begin pattern_number := 136; color := 4; clock := 0; y_pos := 175; x_pos := 0; y_vel := -10; x_vel := 5; countdown := 0; link := nil; end; (* start up the sprite *) set_sprite(0, car0); (* change the sprite's position and velocity *) with car0^ do begin y_pos := 99; x_pos := 127; y_vel := 0; x_vel := 0; end; (* with any change the sprite has to be reassigned to the SPRITE_CHANGE_LIST *) set_sprite(0, car0); (* Now compare this to using just the SET_SPR_ATTRIBUTE function *) (* Define sprite and set it in motion *) SET_SPR_ATTRIBUTE(136, 4, 0, 175, 0, -10, 5); (* change sprite position and velocity *) SET_SPR_ATTRIBUTE(136, 4, 0, 99, 127, 0, 0); 3 Quote Link to comment https://forums.atariage.com/topic/193355-pascal-on-the-994a/page/40/#findComment-5467484 Share on other sites More sharing options...
+Vorticon Posted May 19 Share Posted May 19 There is actually a way to get a pointer to a sprite's change list after using the SET_SPR_ATTRIBUTE function: simply use the GET_SPRITE function! Not sure how I missed that. In other words, set up a sprite with SET_SPR_ATTRIBUTE, then execute a GET_SPRITE to get a pointer to it. From there on one can access any of the sprite elements in the change list directly. Unfortunately, it turns out that sprite functionality in the p-system is not as flexible as one might think at first glance. For example, you cannot check sprite coincidence between 2 specified sprites. The SPRITE_COINC is a boolean function that returns true when any sprite coincides with any other sprite, plus there is no way to check for coincidence between a sprite and a specific coordinate point, unlike XB. And to make matters worse, the x_pos and y_pos values are not updated automatically as the sprite moves. Not sure if this is a bug or intentional, but it's a major limitation (I think it's a bug). There are workarounds of course, but it makes sprite usage clumsy at best. Feels half baked in some sense. 3 Quote Link to comment https://forums.atariage.com/topic/193355-pascal-on-the-994a/page/40/#findComment-5469149 Share on other sites More sharing options...
+TheBF Posted May 19 Share Posted May 19 14 minutes ago, Vorticon said: There is actually a way to get a pointer to a sprite's change list after using the SET_SPR_ATTRIBUTE function: simply use the GET_SPRITE function! Not sure how I missed that. In other words, set up a sprite with SET_SPR_ATTRIBUTE, then execute a GET_SPRITE to get a pointer to it. From there on one can access any of the sprite elements in the change list directly. Unfortunately, it turns out that sprite functionality in the p-system is not as flexible as one might think at first glance. For example, you cannot check sprite coincidence between 2 specified sprites. The SPRITE_COINC is a boolean function that returns true when any sprite coincides with any other sprite, plus there is no way to check for coincidence between a sprite and a specific coordinate point, unlike XB. And to make matters worse, the x_pos and y_pos values are not updated automatically as the sprite moves. Not sure if this is a bug or intentional, but it's a major limitation (I think it's a bug). There are workarounds of course, but it makes sprite usage clumsy at best. Feels half baked in some sense. Pure conjecture here, but this sounds like the sprite table has a replica somewhere in RAM which is what you change in your program. That table would be copied out to VDP RAM(maybe on the video interrupt?) to make things happen, but it seems they don't ever copy it back. I played with that idea when I tried to make sprites work. It was simpler to use the VDP memory functions to fetch and store bytes to/from VDP and just manipulate VDP RAM like it was normal memory. It's slower but just as with P-code, you are not running at processor speed anyway so writing to RAM and doing a block copy to VDP didn't seem to by me much. Does Pascal give you functions to peek/poke VDP RAM? @apersson850 can help us understand what is actually happening behind the curtain. 3 Quote Link to comment https://forums.atariage.com/topic/193355-pascal-on-the-994a/page/40/#findComment-5469161 Share on other sites More sharing options...
apersson850 Posted May 19 Author Share Posted May 19 I've never dechipered the sprite movement code in the p-system, since I've never used it for anything serious. You can write peek and poke yourself in Pascal, thus also access VDP RAM directly. But if you do you have to make sure your program doesn't run from VDP RAM, since then you change the address to the running code. 1 Quote Link to comment https://forums.atariage.com/topic/193355-pascal-on-the-994a/page/40/#findComment-5469294 Share on other sites More sharing options...
+Vorticon Posted May 19 Share Posted May 19 I dug a little further into this and it turns out the Sprite Attribute List starts at >C00. This is interesting because according to the EA manual sprite auto-motion requires the SAL to be at >300, which tells me that the p-system seems to actively move sprites directly. Second, the table only contains sprites that are on screen, with those defined off-screen not represented. The table appears to be initialized to >C000 >0000 for each sprite otherwise. >C000 is 192,0 which is just off screen. And I can see that the x and y positions for the visible sprites are updated in real time. So @TheBF's hunch is correct in that there must be a master copy of the SAL in RAM somewhere which is likely not a fixed location but depends on available memory for any particular program and the x and y positions in the VDP are not updating the RAM copy. This has got to be a bug. The good news is that I can easily write a small assembly procedure to check a sprite's position now that I know where to look for it. Homework for today 😁 4 Quote Link to comment https://forums.atariage.com/topic/193355-pascal-on-the-994a/page/40/#findComment-5469337 Share on other sites More sharing options...
Asmusr Posted May 19 Share Posted May 19 35 minutes ago, Vorticon said: I dug a little further into this and it turns out the Sprite Attribute List starts at >C00. This is interesting because according to the EA manual sprite auto-motion requires the SAL to be at >300, which tells me that the p-system seems to actively move sprites directly. Second, the table only contains sprites that are on screen, with those defined off-screen not represented. The table appears to be initialized to >C000 >0000 for each sprite otherwise. >C000 is 192,0 which is just off screen. And I can see that the x and y positions for the visible sprites are updated in real time. So @TheBF's hunch is correct in that there must be a master copy of the SAL in RAM somewhere which is likely not a fixed location but depends on available memory for any particular program and the x and y positions in the VDP are not updating the RAM copy. This has got to be a bug. The good news is that I can easily write a small assembly procedure to check a sprite's position now that I know where to look for it. Homework for today 😁 It sounds like it works the same way as in all my games. Why do you think that's a bug? Quote Link to comment https://forums.atariage.com/topic/193355-pascal-on-the-994a/page/40/#findComment-5469354 Share on other sites More sharing options...
+Vorticon Posted May 19 Share Posted May 19 46 minutes ago, Asmusr said: It sounds like it works the same way as in all my games. Why do you think that's a bug? The only way to obtain the current sprite position is by looking up the x_pos and y_pos elements of the sprite's change list as there is no function to do that for you in the p-system. These elements are not getting updated as the sprite moves, and retain their original value when the sprite was created. This makes little sense and severely limits the usability of sprites. Yes, you can get around that by using assembly routines, but I'm talking here about what's available to the user within the p-system proper. Quote Link to comment https://forums.atariage.com/topic/193355-pascal-on-the-994a/page/40/#findComment-5469392 Share on other sites More sharing options...
Asmusr Posted May 19 Share Posted May 19 56 minutes ago, Vorticon said: The only way to obtain the current sprite position is by looking up the x_pos and y_pos elements of the sprite's change list as there is no function to do that for you in the p-system. These elements are not getting updated as the sprite moves, and retain their original value when the sprite was created. This makes little sense and severely limits the usability of sprites. Yes, you can get around that by using assembly routines, but I'm talking here about what's available to the user within the p-system proper. I don't know much about the p-system, but it makes sense to me to keep your master list of sprites in CPU RAM and rebuild the sprite attribute list in VDP RAM on the fly. But if you can't read back the content of the master list, then yes, that's a problem. 3 Quote Link to comment https://forums.atariage.com/topic/193355-pascal-on-the-994a/page/40/#findComment-5469430 Share on other sites More sharing options...
+Vorticon Posted May 19 Share Posted May 19 Exactly... Quote Link to comment https://forums.atariage.com/topic/193355-pascal-on-the-994a/page/40/#findComment-5469486 Share on other sites More sharing options...
+TheBF Posted May 19 Share Posted May 19 This may be of some interest @Vorticon I build a thingy I call a table creators. It allows me to point to a base address of any kind of memory and when given a parameter it computes the offset into that "table" using Assembly Language. For the Sprite table I have TABLE4: which assumes records are four bytes. The offset into each sprite record takes only 2 instructions. SLA Rx,2 and A Rx,Ry I create a separate TABLE4 for each field in a SPRITE record by making each TABLE4 start one byte higher. Using this kind of thing means that reading and writing single bytes with a fetch and store operator into VDP RAM is still pretty quick. It ends up looking like this in Forth, using SAT (sprite attribute table) base address in VDP RAM. SAT TABLE4: SP.Y SAT 1+ TABLE4: SP.X SAT 2+ TABLE4: SP.PAT SAT 3 + TABLE4: SP.COLR The usage is like this #1 SP.Y VC@ #1 SP.X VC@ \ "fetch sprite 1 x and y from VDP RAM RED #3 SP.COLR VC! \ set #3 sprite's colour Not sure how that would translate to Pascal but the concept could have the same advantages as in Forth where there is an underlying interpreter slowing things down. 2 Quote Link to comment https://forums.atariage.com/topic/193355-pascal-on-the-994a/page/40/#findComment-5469585 Share on other sites More sharing options...
apersson850 Posted May 20 Author Share Posted May 20 (edited) Yes, Pascal runs a sprite movement system all by its own. I've never studied it in detail, as I've not used it. The only two things I remember is that it has two bitmaps at 280AH for sprites 0-15 and 16-31 where it indicates which are moving automatically. So when using Pascal, make sure your moving sprites are in one of these groups if you have no more than 16, since it will skip messing with the whole group if no sprite is moving there. The other thing I remember is that the printout of the assembly routine handling the sprites is about two pages (A4). About 140 bytes of memory fit on one page. As you understand I know where it is in memory, so I can easily find it and analyze it. Time permitting... At 2808H there's a sprite coincidence counter, so some sprite related data is in that area. Edited May 20 by apersson850 3 Quote Link to comment https://forums.atariage.com/topic/193355-pascal-on-the-994a/page/40/#findComment-5469835 Share on other sites More sharing options...
+Vorticon Posted May 20 Share Posted May 20 Here's a real life code snippet on how to check the position of a moving sprite. It uses VSBR (VDP Single Byte Read) from my VDPUTIL library. In testing I had this a repeat/until loop checking for a destination position and it worked really well and was reasonably fast. set_sprite(sprnum, car[sprnum]); (* start sprite moving *) salloc := 3072 + (sprnum * 4); (* find location of sprite entry in the Sprite Attribute List *) vsbr(salloc, y); (* get y position *) vsbr(salloc + 1, x); (* get x position *) Below is the listing of VDPUTIL ready to assemble. Spoiler ;vdp access routines ;by walid maalouli ;march 2024 vdpwa .equ 8c02h ;vdp write address vdprd .equ 8800h ;vdp read data vdpwd .equ 8c00h ;vdp write data vrtab .equ 2810h ;location of vdp registers copies for PME .proc vwtr,2 ;vdp write to register ;usage: vwtr(regnum, byteval) .def vsavtab mov *r10+,r0 ;get the register value li r1,8000h ;bit mask for msb swpb *r10 ;r10 has pointer to register number socb r1,*r10 ;set the most significant bit swpb r0 movb r0,@vdpwa ;write byte value nop movb *r10,@vdpwa ;write the register number nop b *r11 vsavtab .block 8 .proc vsbr,2 ;vdp single byte read ;usage: vsbr(vdpadr, intvar) mov *r10+,r0 ;get the pointer to the variable swpb *r10 ;r10 now has the vdp address movb *r10,@vdpwa ;write the vdp address lsb swpb *r10 movb *r10,@vdpwa ;write the vdp address msb nop clr *r0 movb @vdprd,*r0 ;store vdp byte into variable swpb *r0 b *r11 .proc vmbr,3 ;vdp multiple byte read ;usage: vmbr(vdpadr, bytearray, bytenum) mov *r10+,r0 ;get the number of bytes to read mov *r10+,r1 ;get the pointer to the byte array swpb *r10 ;r10 now has the vdp address movb *r10,@vdpwa ;write the vdp address lsb swpb *r10 movb *r10,@vdpwa ;write the vdp address msb nop readnxt movb @vdprd,*r1+ ;read byte dec r0 jne readnxt ;done reading all bytes? b *r11 .proc vsbw,2 ;vdp single byte write ;usage: vsbw(vdpadr, intval) mov *r10+,r0 ;get the pointer to the variable swpb *r10 ;r10 now has the vdp address movb *r10,@vdpwa ;write the vdp address lsb swpb *r10 li r1,4000h ;bit mask for vdp address msb socb r1,*r10 ;set the 2 most significant bits movb *r10,@vdpwa ;write the vdp address msb swpb r0 movb r0,@vdpwd ;write byte to vdp address b *r11 .proc vmbw,3 ;vdp multiple byte write ;usage: vmbw(vdpadr, bytearray, bytenum) mov *r10+,r0 ;get the number of bytes to write mov *r10+,r1 ;get the pointer to the byte array swpb *r10 ;r10 now has the vdp address movb *r10,@vdpwa ;write the vdp address lsb swpb *r10 li r2,4000h ;bit mask for vdp address msb socb r2,*r10 ;set the 2 most significant bits movb *r10,@vdpwa ;write the vdp address msb wrinxt movb *r1+,@vdpwd ;write byte to vdp dec r0 jne wrinxt ;done writing all the bytes? b *r11 .proc regcopy,2 ;save copy of vdp register in pme table at >2810 ;usage: regcopy(regnum, byteval) mov *r10+,r0 ;get register value mov *r10,r1 ;get register number dec r1 ;calculate vr address in table sla r1,1 ai r1,vrtab movb r0,*r1 ;save vr value in table b *r11 .proc savevr ;save default pme vdp registers ;usage: savevr .ref vsavtab li r1,vrtab ;point to pme vr table li r2,7 ;number of registers to save li r3,vsavtab ;point to register save table savnxt movb *r1+,*r3+ ;save register dec r2 jne savnxt ;are all registers saved? (vr1-vr7) b *r11 .proc restorevr ;restore default pme vdp registers ;usage: restorevr .ref vsavtab li r1,vsavtab ;point to register save table li r2,7 ;number of registers to restore li r3,vrtab ;point to pme vr table resnxt movb *r1+,*r3+ ;restore register dec r2 jne resnxt ;are all registers restored? (vr1-vr7) b *r11 .end 3 Quote Link to comment https://forums.atariage.com/topic/193355-pascal-on-the-994a/page/40/#findComment-5470154 Share on other sites More sharing options...
+Vorticon Posted May 21 Share Posted May 21 Best I could make it. Still not bad 3 Quote Link to comment https://forums.atariage.com/topic/193355-pascal-on-the-994a/page/40/#findComment-5470940 Share on other sites More sharing options...
apersson850 Posted May 22 Author Share Posted May 22 The utility modrs232 shows how you can access VDP RAM directly from Pascal, if you want to. Quote Link to comment https://forums.atariage.com/topic/193355-pascal-on-the-994a/page/40/#findComment-5471226 Share on other sites More sharing options...
+Vorticon Posted May 22 Share Posted May 22 1 hour ago, apersson850 said: The utility modrs232 shows how you can access VDP RAM directly from Pascal, if you want to. Indeed, but it's not complete. I preferred to roll my own to suit my needs better. Quote Link to comment https://forums.atariage.com/topic/193355-pascal-on-the-994a/page/40/#findComment-5471273 Share on other sites More sharing options...
apersson850 Posted May 23 Author Share Posted May 23 I rather meant that the principle is demonstrated in that program. Of course you can run your own. 2 Quote Link to comment https://forums.atariage.com/topic/193355-pascal-on-the-994a/page/40/#findComment-5471865 Share on other sites More sharing options...
+Vorticon Posted May 27 Share Posted May 27 How does one override the system font again? Quote Link to comment https://forums.atariage.com/topic/193355-pascal-on-the-994a/page/40/#findComment-5474827 Share on other sites More sharing options...
apersson850 Posted May 27 Author Share Posted May 27 (edited) By having a file called SYSTEM.CHARAC on the system disk (#4) at boot time. That is *SYSTEM.CHARAC in p-system lingo. You can use the file OS:SYSTEM.CHARAC as a template, if you like. It's a simple memory image of the character definitions. Edited May 27 by apersson850 2 1 Quote Link to comment https://forums.atariage.com/topic/193355-pascal-on-the-994a/page/40/#findComment-5474958 Share on other sites More sharing options...
+Vorticon Posted June 4 Share Posted June 4 So I'm very motivated to get the TIPI disks working fully with the pcode card without having to remove the TI disk controller. With my current set up, TIPI is at >1000 and the disk controller is at >1100. Everything works fine and the system sees the 3 TIPI drives except the Editor which throws a Stack Overflow error when attempting to edit anything. From what I understand from @apersson850, the p-system is detecting both the TIPI and the real disk controller and creating an additional PCB in VDP RAM, which reduces the Editor's available RAM just enough to make it crash. The TOPMEM pointer at >2782 points to the highest VDP RAM location available and the PCB's are normally placed starting at that location and TOPMEM is adjusted down accordingly based on the length of the PCB. Now, since I don't need the physical drives when using the TIPI, in theory I should be able to remove the PCB for the TI controller and restore TOPMEM to its original content and *theoretically* the Editor will have enough RAM to work. So I need some additional info: How are the PCB's structured under the p-system? If each drive as its own PCB, why does the system not natively recognize more than 3 drives? Essentially, with both the TIPI and the TI controller coexisting, shouldn't we see 6 drives when we run the Volume command from the Filer? Or does the system only access the first controller it sees? Quote Link to comment https://forums.atariage.com/topic/193355-pascal-on-the-994a/page/40/#findComment-5480277 Share on other sites More sharing options...
apersson850 Posted June 5 Author Share Posted June 5 I've not managed to get the p-system to automatically find more than one disk controller in the system. I can use it with the physical drives and two RAMdisks, but then I inject the PCB for the RAMdisks manually. To avoid changing TOPMEM I put them in the sprite attribute table, since I normally don't use that anyway. A PCB is a PAB with some added information. The p-system stores the CRU base address and the address to call to make access quicker. Every PCB for a physical disk drive is the same. The system just changes the drive number in the associated PAB when doing the call. The p-system has tables with unit characteristics. They in turn point to tables with addresses for INIT, READ, WRITE and STATUS, as applicable. All disk units point to the same place, since they use the same controller. But the p-system knows that there will not be more than three disks, so it doesn't populate the entries for units #10, #11 and #12. So for a CorComp controller which has four drives you simply copy the same value as is stored for #4 to the place where you have #10. Had the controller been able to also handle DSK5 and DSK6 you could have continued a bit further. But the RAMdisks have a different DSR, so they need a different PCB and different pointers in the unit table. I can show the structure of the PCB but it will have to wait until next week, when I'm back at home again. Quote Link to comment https://forums.atariage.com/topic/193355-pascal-on-the-994a/page/40/#findComment-5480767 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.