Jump to content
IGNORED

Pascal on the 99/4A


apersson850

Recommended Posts

2 hours ago, apersson850 said:

You will also gain the advantage of compiling at twice the speed on the real machine, with the compiler on the RAM-disk. Even faster if source and code are on the RAM-disk too.

Now that would definitely be a good incentive. That said, I recently purchased an IDE drive card for the TI with an RTC which I'm planning on building it this week, and my hope is that there might be a way to use that as an additional drive in my p-system. It may not be as fast as a RAM disk, but this will offset by the fact that contents will obviously be non-volatile.

But going back to the SAMS, since data can only be access through a 4K window at >2000 in the p-system, I have no clue how to get this scheme to work as an alternate code pool seamlessly, particularly since transparent 4K paging will be required for larger data or programs, not to mention that any screen I/O will corrupt the data while the card is active and will not be visible. I am intrigued enough to consider it, but it may be a little beyond my pay grade. If you want, perhaps you can give us an outline of how one could accomplish this for starters, keeping in mind that I am not engineer/developer anything and I only do this for the intellectual stimulation :lol:

  • Like 2
Link to comment
Share on other sites

No, no, no, not an alternate code pool. I'm talking about making it available as a drive (volume in p-system vocabulary), just a much faster such drive.

What you do need is a place to have a DSR to handle it, because it must take command like a disk drive, where the system assumes a CRU address to enable the DSR and an entry address to access it.

Since the system will assume it to be a normal DSR, the BIOS will already have disabled the p-code card and will re-enable it before returning, so you don't need to worry about that.

You'll implement the equivalent of sector read/write (subprogram 10H on your "disk controller"). That's all it takes. That's the only thing the p-system uses.

What will call you is the equivalent of the unitread/unitwrite procedure in the SBIOS, which will ask for a transfer to or from the drive.

 

In the SAMS, you'll have to map that 4 K window to one page which is available as normal memory and active when no access to the RAMdisk is active. When an access is active, you'll be asked for a particular 256 byte sector to map in. You have to calculate which page that is in and which offset it has, read/write that sector to the buffer address unitwrite/-read will ask for, return the standard page in SAMS and exit.

 

There are some tricks involved in convincing the p-system that there is one more drive controller in the system, but that you'll face already if you want to add an IDE controller in parallel to the standard disk controller.

 

Thinking about the feasibility about this - I'm not sure without checking in the code or other documentation how high a sector number you can send to the 10H subprogram. The p-system can handle 32768 blocks, but that's 65536 sectors, so it maxes out what an unsigned 16-bit value can hold. Splitting it in more than one file doesn't help, since they'll still have different sectors. Splitting the file over two virtual volumes on one SAMS card will help and doesn't make the driver much more complicated.

  • Like 1
Link to comment
Share on other sites

6 hours ago, apersson850 said:

If I understand you correctly, SAMS is accessed via a window, into which you map whichever physical memory page you like in the SAMS device. That window may be a memory expansion part, like 2000-3FFFH or it could be the DSR page, 4000-5FFFH. Now I may have misunderstood the details (I've not worked with SAMS at all), but hopefully I have the core idea correct here.

Unfortunately SAMS cannot map into in the DSR space, >4000 - >5FFF - only into the normal expansion RAM areas. And pages are switched not using CRU but by writing to registers mapped into >4000 - >401f.

Edited by Asmusr
Link to comment
Share on other sites

37 minutes ago, Asmusr said:

Unfortunately SAMS cannot map into in the DSR space, >4000 - >5FFF - only into the normal expansion RAM areas. And pages are switched not using CRU but by writing to registers mapped into >4000 - >401f.

Right. So I assume that rules out creating a DSR for it. Mind you I have zero understanding of how DSR's are set up and programmed outside of just a very superficial general concept. Is there a document somewhere that has a reasonable explanation of how one might create a DSR?

Link to comment
Share on other sites

2 hours ago, Vorticon said:

Right. So I assume that rules out creating a DSR for it. Mind you I have zero understanding of how DSR's are set up and programmed outside of just a very superficial general concept. Is there a document somewhere that has a reasonable explanation of how one might create a DSR?

Maybe this? https://www.unige.ch/medecine/nouspikel/ti99/headers.htm

 

I have been thinking about writing a RAM disk DSR for the SAMS for years, but I thought the only option would be to put it (or part of it) in a GROM, and that wouldn't work for some implementations of DSRLNK. But it could be different for the p-code card.

 

Anyway, when thinking about a memory manager for SAMS, splitting it into 4096 sectors of 256 bytes (which would be the smallest amount of memory you could allocate) might still be a good idea, even though you wouldn't access the sectors as files. You could use one page as a map of which sectors were allocated, and use other concepts from file systems like file descriptor records. 

  • Thanks 1
Link to comment
Share on other sites

Posted (edited)

Now I've read about how SAMS work, so I know what I'm talking about.

 

There are a couple of options, some unique to what you can do with the p-system.

 

One way is to do like I did with my own RAM-disk. Since it uses RAM everywhere, across the whole address space 0000-FFFFH, I stored the DSR in RAM on my IO-card. What kind of card it is doesn't matter (it's my own design - only one exists). The important thing is that it has the DSR in RAM. Since part of my RAM-disk is in the DSR space, I have to turn off the DSR and run the code to reach that elsewhere. I solved that by saving a part of some other memory in the RAM for the DSR, copy code from the DSR out to the saved area, jump there, turn off the DSR from the outside and map in the RAM-disk memory over the DSR space, access the desired sector, turn the DSR back on again, jump back into it, restore the saved memory and return.

A lot of maneuvers but much faster than a standard floppy. These tricks are needed only for that particular memory segment, so they aren't used for all other memory.

 

With the p-system there is also another way. Normally all DSR programs must be in the 4000-5FFFH range. But the p-system does a prescan of needed DSRs at boot time and stores a table with information about the CRU and entry address. Thus it's possible to add the RAM-disk DSR after boot (you need to do that anyway, since it will only search for one disk controller at start) by storing the CRU address of the SAMS (typically 1E00H, I've noticed) and then a fake entry address to the DSR elsewhere than in DSR space. If you have a cartridge with RAM you can store it there. Even the original Mini Memory would do, but there are other options too today.

Then you manage the SAMS from that program in Mini Memory and just return to where called from when you are ready. During the access, you can control the map registers as you like and have for example 2000-3FFFH as your window into the SAMS world. You don't even have to save anything, since that will be in the default SAMS page for that part of the memory.

What you implement is a sector read/write program, which acts the same as it would do if it was in a disk controller. You'll just store or read the sector you're asked to do, and that's it.

 

A third version of this is that you use the high end of 2000-3FFFH, which seems unused by the p-system. That's easier to verify today, when we can check with an emulator if it's touched. But then you can of course not use the 2000-3FFFH as a window into the SAMS repository, since then you'll switch out yourself. Software suicide. You have to use a window somewhere in the A000-FFFFH range instead.

 

For the p-system the whole thing is simplified significantly by the fact that you need to implement sector read/write and nothing more. That's the only thing the p-system uses. I've done that a couple of times now, both for my own RAM-disk and for a Horizon card, where certain versions of the DSR aren't compatible with the p-system.

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

2 minutes ago, apersson850 said:

A third version of this is that you use the high end of 2000-3FFFH, which seems unused by the p-system. That's easier to verify today, when we can check with an emulator if it's touched. But then you can of course not use the 2000-3FFFH as a window into the SAMS repository, since then you'll switch out yourself. Software suicide.

SAMS pages in 4K blocks, so can't you have your code at the high part of >3000 and switch pages at >2000 without causing issues like this?

Link to comment
Share on other sites

2 hours ago, apersson850 said:

With the p-system there is also another way. Normally all DSR programs must be in the 4000-5FFFH range. But the p-system does a prescan of needed DSRs at boot time and stores a table with information about the CRU and entry address. Thus it's possible to add the RAM-disk DSR after boot (you need to do that anyway, since it will only search for one disk controller at start) by storing the CRU address of the SAMS (typically 1E00H, I've noticed) and then a fake entry address to the DSR elsewhere than in DSR space. If you have a cartridge with RAM you can store it there. Even the original Mini Memory would do, but there are other options too today.

Then you manage the SAMS from that program in Mini Memory and just return to where called from when you are ready. During the access, you can control the map registers as you like and have for example 2000-3FFFH as your window into the SAMS world. You don't even have to save anything, since that will be in the default SAMS page for that part of the memory.

What you implement is a sector read/write program, which acts the same as it would do if it was in a disk controller. You'll just store or read the sector you're asked to do, and that's it.

That seems to be the best path to me. The Mini Memory requirement in my view is probably the most universal solution to store the DSR. I have some serious reading to do...

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

2 hours ago, apersson850 said:

A third version of this is that you use the high end of 2000-3FFFH, which seems unused by the p-system.

 

2 hours ago, JasonACT said:

SAMS pages in 4K blocks, so can't you have your code at the high part of >3000 and switch pages at >2000 without causing issues like this?

 

Indeed, if the entire 4 KiB block at >3000..>3FFF is unused by the p-system, using >3000 (SAMS register address = >4004) as your only 4 KiB paging address, you are good for a single 4 KiB SAMS page window.

 

...lee

  • Like 2
Link to comment
Share on other sites

1 minute ago, Lee Stewart said:

 

 

Indeed, if the entire 4 KiB block at >3000..>3FFF is unused by the p-system, using >3000 (SAMS register address = >4004) as your only 4 KiB paging address, you are good for a single 4 KiB SAMS page window.

 

...lee

Now that we know that >3000..>3FFF is free  that seems like the best solution to me. 

There are very few problems with just having one window for SAMS.

The only time you need to think about it is if you want to copy from SAMS page to SAMS page.

That will require reading some SAMS data into normal memory, change page and copy it back. 

I ran into this with the ED99 editor and ended up using two "windows" so I could copy records SAMS-to-SAMS with the most efficiency but it is a luxury in a tiny machine like 99. 

Not a necessity. 

  • Like 2
Link to comment
Share on other sites

3 hours ago, TheBF said:

Now that we know that >3000..>3FFF is free  that seems like the best solution to me. 

There are very few problems with just having one window for SAMS.

It's not free, just not needed while running an assembly program, at least based on @apersson850's memory map. It will need to be restored prior to returning to the host program.

Link to comment
Share on other sites

Posted (edited)

The very end of it is not used by the p-system, I believe. I have not verified that.

But as long as you return the original page prior to returning you can use other pages too.

 

To implement a DSR which can act as a disk controller you don't need to worry about copying from one page to another. That's done in the same way as for a physical disk, i.e. read the data from the disk/SAMS to a buffer in RAM, write that buffer to disk/SAMS at a different place.

Not as efficient as moving from one page to another directly, but the advantage is that it's all normal file handling.

 

Some details:

The p-system was from an early stage aimed at being easy to move to other computers. Hence it's a very layered system. Pretty far down in the layers is the RSP (Runtime Support Package).

The RSP contains the various unit-procedures, like unitread and so on. The functions ioresult and time are there too.

The RSP handles things like mapping device unit numbers, calculates the status of performed IO routines and similar.

For this purposes the RSP uses the units globals, kernel and BIOS (Basic Input Output System).

 

The next layer down, the unit BIOS also uses units globals and kernel, so they are on the same page about where other system data and services are located.

In the BIOS all the generic unitread, unitwrite and similar are split up in unitread for console, unitread for serial port, unitread for disks and so on. Calculations to map the p-system's logical 512 byte disk block size to the physical sector size of the host computer are done on this level too. Reading a character from the keyboard is in this layer represented by picking a character from the input queue, but there is no actual keyboard access.

All the way down here the system is written in Pascal. But from the BIOS calls are made to the SBIOS (Simplified Basic Input Output System).

 

Down at the SBIOS layer we hit assembly language specifically written for the CPU and computer architecture the p-system is actually running on. In the 99/4A, parts of the SBIOS is executing from the p-code card ROM. Then it branches to parts stored in expansion RAM (2000-3FFFH part), where the p-code card can be turned off and an (almost) standard DSRCALL is done. This in not a complete DSRLINK, since the p-system at boot time does DSRPROBE calls, to figure out where the DSR code it will later use is located. When it has found the disk controller att boot time, it will create a PCB (Peripheral Control Block) which is a record with the CRU base address, entry address of the sector read/write procedure and a standard PAB for that kind of call. Later, when the SBIOS is calling the disk read/write sector DSR, it will no longer scan for anything. It will populate the PAB with the required information, link to it just like you do with the normal DSRLNK, then just enable the already known CRU address and branch to the already known DSR address.

That last part of the sentence is the important thing here, because it means we can create a dummy PCB, plug in whatever CRU and branch address we like and then just populate the system's list of known devices with a link to this PCB and links to the system's already existing routines for the unit-procedures applicable to our faked device. In this particular case it should behave like a disk controller, so we copy the links for units that actually do access the disk controller, create a PAB in our PCB that's identical to the one used by the real disk controller and the only difference is the link to our dummy PCB, which will send the SBIOS into our DSR, which then doesn't even have to be on a card with memory in the normal DSR space.

 

So not even the SBIOS will have to know that it's calling a DSR that's very much out of the ordinary. It will just follow it's normal path without even realizing it has been tricked into some very special DSR.

In the particular case with the SAMS page we'll store that CRU address of the SAMS card, not because we need to (there's no DSR memory on the card), but because it saves us the work to enable/disable the card ourselves and then branch to a DSR doing the equivalent of sector read/write for our RAM-disk. This routine can most probably reside high up in the 2000-3FFFH block, since the very last part there isn't used by the p-system.

At least so it seems. Using Classic 99, it's easy enough to fill that memory with some specific data and then verify that it hasn't been changed.

 

To do this thing a few things have to be written.

  1. The DSR which simulates sector read/write from/to SAMS.
  2. The program which installs this code in memory, as it can't be loaded the normal way.
  3. A program which fills in the system's tables with the proper values.

When I've done these things before, I've selected to keep these things separate. The reason is that loading the DSR has been completely separate from starting the system with my solutions, so once item 2 has been executed once, then as long as the computer has been powered I've only needed to do item 3, even if I've done a complete reboot of the p-system.

Inside item 3 I've also included telling the system that the compiler, editor, filer, assembler and linker are on the RAM-disk. But that's not true the first time you execute it, since you need to create the RAM-disk before you can transfer these system programs to it. So you have to do item 3, then use the filer to zero the new RAM-disk device and then move the system files to it. After that, I do item 3 once again, and now it's true that the system files are on the RAM-disk, so after this the system will run them from there.

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

1 hour ago, apersson850 said:

But as long as you return the original page prior to returning you can use other pages too.

 

I tried >A000 and the system crashed every time. Since there is no way to tell where in upper memory an assembly program is residing, it seemed safe to avoid upper memory altogether. 

 

1 hour ago, apersson850 said:

To do this thing a few things have to be written.

  1. The DSR which simulates sector read/write from/to SAMS.
  2. The program which installs this code in memory, as it can't be loaded the normal way.
  3. A program which fills in the system's tables with the proper values.

When I've done these things before, I've selected to keep these things separate. The reason is that loading the DSR has been completely separate from starting the system with my solutions, so once item 2 has been executed once, then as long as the computer has been powered I've only needed to do item 3, even if I've done a complete reboot of the p-system.

Inside item 3 I've also included telling the system that the compiler, editor, filer, assembler and linker are on the RAM-disk. But that's not true the first time you execute it, since you need to create the RAM-disk before you can transfer these system programs to it. So you have to do item 3, then use the filer to zero the new RAM-disk device and then move the system files to it. After that, I do item 3 once again, and now it's true that the system files are on the RAM-disk, so after this the system will run them from there.

With all this needing to be done, particularly the invocation of the Filer and the copying of all the needed programs to the RAM disk, initial boot time must have been pretty lengthy (I'm estimating 2-3 minutes). A minor inconvenience I suppose in return for the benefits of a RAM disk.

Seems to me you are best suited to make this project a reality since you've essentially done all this before. The only bit that would be different would be the windowing of the RAM access, and that's pretty straightforward to do as I've shown previously. What say you? 😁

Link to comment
Share on other sites

Posted (edited)

Yes, the initial start takes a while. But since the system allows for input redirection, you can write a script that does all that automatically.

 

Regarding the project then yes, I think I know most of what needs to be done. Right now I'm involved in the arrangement of three sports events, so there will be no programming the nearest month.

Edited by apersson850
Link to comment
Share on other sites

I'm trying to get bitmap mode working under the p-system. I'm using @apersson850's bitreserve scheme to reserve the VDP memory for bitmap mode, then I'm setting up all the appropriate VDP registers and loading the pattern descriptor table and the color table with the appropriate data from an image on disk. Prior to reserving the VDP memory, I am copying the entire VDP RAM to the SAMS card for later restoration. 

I verified with the Classic99 debugger that all the VDP registers are properly set up and that the VDP data has been loaded correctly, but it seems that the system is refusing to switch to bitmap mode after setting VR0 appropriately (value of 2) and I'm getting garbage on the screen although the colors appear correct. I did save the modified registers to the PME table (not sure if that is necessary).  I have attached a disk image of the code. Execute BITRESERVE to run the demo. Note that it does not restore the system properly afterward. I haven't gotten to that yet. Incidentally, I am quite familiar with bitmap mode and I've done this many times outside of the p-system, so I think there is some special set up I am missing here under this environment.

 

 

 

Here is the modified bitreserve code:

Spoiler
 (* reserve vdp memory for bitmap *)
 (* backs up entire vdp to sams card 
    [pages 16 to 19] *)
    
program bitreserve;
{$U commandio.code} 
uses commandio;  

const
 intmem = 10112;       { Interpreters VDP memory pointer }
 newint = 14360;       { New intmem value }

type
 byte = 0..255;

 dual = record
   case boolean of
     true :(int :integer);
     false:(ptr :^integer);
 end; (* dual *)

var
 i, spage, size, offset, vdpadr : integer;
 vdparr : packed array[0..8191] of byte;
 
function samsinit : integer; external;
 
function samssize : integer; external;
 
procedure dataops(rwcode : integer;
                  var spage, size, offset : integer;
                  var bytearr); external;

procedure vmbr(address : integer; var bytearr; bytenum : integer); external;
 
procedure poke(addr, value :integer);
 var
   window :dual;

 begin
   window.int := addr;
   window.ptr^ := value;
 end; (* poke *)

begin
 i := samsinit; {initialize the sams card}
 writeln('sams card found and initialized');
 i := samssize; {verify number of pages available}
 writeln(i, ' pages available');

 spage := 16;
 offset := 0;
 size := sizeof(vdparr);
 vdpadr := 0;
 
 {back up vdp memory to sams card}
 for i := 1 to 2 do
  begin
   vmbr(vdpadr, vdparr, 8192);  {read 8k of vdp}
   dataops(1, spage, size, offset, vdparr); {save in sams card}
   vdpadr := 8192;
   spage := 18;
   size := sizeof(vdparr);
  end;
 writeln('vdp memory backed up');
 
 {reserve bitmap area in vdp}
 poke(intmem,newint);
 writeln('bitmap memory reserved');
 writeln(chr(10), 'loading imagedemo');
 chain('imagedemo');
end. (* bitreserve *)

 

 

and here is the imagedemo program which attempts to put a bitmap image on screen. The SAMS and VDP utilities associated with it are below as well.

Spoiler
(* bitmap image demonstration *)

program imagedemo;

type
 byte = 0..255;
 
 dual = record
  case boolean of
   true :(int :integer);
   false:(ptr :^integer);
 end; (* dual *)

var
 spage, bytenum, offset, vdpadr : integer;
 buffer : packed array[0..6143] of byte;

function getkey : integer; external;

procedure dataops(rwcode : integer;
                  var spage, bytenum, offset : integer;
                  var buffer); external;
                  
procedure vmbw(vdpadr : integer;
               var bytearray;
               bytenum : integer); external;
               
procedure vsbw(vdpadr, byteval : integer); external;

procedure vwtr(regnum, byteval : integer); external;

procedure regcopy(regnum, regval : integer); external;

procedure getimage(imagename : string);
(* load image pattern and color files from disk into sams card *)

var
 infile : file;
 pname, cname : string;
 blocks : integer;

begin
 pname := concat(imagename, '.pdat');
 cname := concat(imagename, '.cdat');
 reset(infile, pname);  {open pattern data file}
 blocks := blockread(infile, buffer, 12);  {load pattern data}
 offset := 0;
 bytenum := sizeof(buffer);
 dataops(1, spage, bytenum, offset, buffer);  {save pattern data to sams card}
 close(infile);
 reset(infile, cname);  {open color data file}
 blocks := blockread(infile, buffer, 12);  {load color data}
 offset := 2048;
 bytenum := sizeof(buffer);
 dataops(1, spage, bytenum, offset, buffer); {save color data to sams card}
 spage := succ(spage);
 close(infile);
end; (* getimage *)

procedure initbitmap;

begin
 vwtr(7, 241);  {set background color to black}
 regcopy(7, 241);  {save register to pme vr table}
 vwtr(1, 224);  {16k ram and vdp interrupts enabled}
 regcopy(1, 224);
 vwtr(2, 7);  {sit address at >1c00}
 regcopy(2, 7);
 vwtr(3, 127);  {ct address at >0000}
 regcopy(3, 127);
 vwtr(4, 7);  {pdt address at >2000}
 regcopy(4, 7);
 vwtr(5, 62); {sal address at >1f00}
 regcopy(5, 62);
 vwtr(6, 3);  {sdt address at >1800}
 regcopy(6, 3);
 vsbw(7936, 208);  {mark start of sal as invalid}
 vwtr(0, 2);  {initiate bitmap mode}
end; (* initbitmap *)

procedure showimage(spage : integer);

begin
 offset := 0;
 bytenum := sizeof(buffer);
 dataops(2, spage, bytenum, offset, buffer);  {load pattern data from sams}
 vmbw(8192, buffer, sizeof(buffer));  {transfer pattern data to vdp}
 offset := 2048;  {point to color data in sams}
 bytenum := sizeof(buffer);
 dataops(2, spage, bytenum, offset, buffer); {load color data from sams}
 vmbw(0, buffer, sizeof(buffer));  {transfer color data to vdp}
 spage := succ(spage);
end; (* showimage *)

begin
 spage := 20;  {start of image data in sams card}
 initbitmap;
 getimage('viger1');
 showimage(20);
 repeat
 until getkey <> 255;
end. (* imagedemo *)

 

 

 

SAMS utilities:

Spoiler
;routines for sams card access
;walid maalouli
;march 2024

        .func samsinit
;initialize the sams card and verify card is present
;returns 0 for absent and 1 for present
;usage: statusint := samsinit

        .def    procret,pmeret,pcodeon,pcodoff
        mov     r11,@procret
        bl      @pcodoff
        li      r12,1e00h       ;cru address of sams card
        sbo     0               ;turn card on
        li      r1,0ff00h
        li      r0,4000h        ;start address of sams registers
nxtpage ai      r1,0100h        ;increment page number starting at 0
        mov     r1,*r0+         ;load page number into sams register
        ci      r0,4020h        ;beyond last register (401eh)?
        jlt     nxtpage
        c       r1,@401eh       ;if match then card present
        jne     nocard
        li      r2,1
        jmp     endinit
nocard  clr     r2
endinit mov     r2,*r10         ;place card indicator on return stack
        sbz     0               ;turn sams card off
        bl      @pcodeon
        mov     @procret,r11
        b       *r11

pcodeon li      r12,1f00h       ;activate the pcode card
        sbo     0
        mov     @pmeret,r12     ;restore the pme pointer
        b       *r11

pcodoff mov     r12,@pmeret     ;save the pme pointer
        li      r12,1f00h       ;deactivate the pcode card
        sbz     0
        b       *r11

pmeret  .word
procret .word

        .func   samssize
;returns the number of pages available
;usage: sizeint := samssize

        .ref    pcodeon,pcodoff,procret
        mov     r11,@procret
        bl      @pcodoff
        li      r12,1e00h       ;cru address of sams card
        sbo     0               ;turn on card
        sbo     1               ;turn mapping on
        li      r4,16           ;page counter. skip over first 16 pages
        li      r1,15           ;starting bank/page
        mov     @2000h,r3       ;save contents of test memory location
        li      r2,0ffffh       ;test value
        mov     r2,@2000h       ;load test memory with value
incpage ai      r1,1            ;add page/bank starting at page >10 bank 0
        swpb    r1
        mov     r1,@4004h       ;map address >2000 to page/bank
        c       r2,@2000h       ;did it write correctly?
        jeq     endpage         ;new page should not equal initial value
        swpb    r1
        inc     r4              ;increment page counter
        jmp     incpage         ;try next page
endpage li      r1,0200h        ;restore original mapping
        mov     r1,@4004h
        mov     r3,@2000h       ;restore contents of test memory location
        sbz     1               ;turn mapping off
        sbz     0               ;turn off sams card
        mov     r4,*r10         ;return page counter
        bl      @pcodeon
        mov     @procret,r11
        b       *r11

        .proc   dataops,5
;read/save data to sams pages up to maximum card capacity
;usage: dataops(rwcode, startpage, datasize, offset, data)
;rwcode : 1=save, 2=read
;startpage is the starting page for the save operation. 
;subsequent pages will be automatically assigned if needed
;datasize can be obtained by sizeof(data)
;offset is the number of bytes from the start of the page
;data is a packed array of byte

        .ref    pcodeon,pcodoff,procret
        mov     r11,@procret
        bl      @pcodoff
        mov     *r10+,r4        ;get pointer to data array
        mov     *R10+,r3        ;get pointer to page offset
        mov     *r10+,r2        ;get pointer to number of bytes to transfer
        mov     *r10+,r1        ;get pointer to starting page
        li      r6,4004h        ;starting sams register (memory >2000)
        li      r12,1e00h       ;cru address of sams card
        sbo     0               ;turn card on
        li      r5,2000h        ;base memory address
        a       *r3,r5          ;apply byte offset
        mov     *r3,r0          ;store offset in byte counter at start
        mov     *r10,r3         ;get r/w code
        sbo     1               ;turn mapper on
nxtpage swpb    *r1
        mov     *r1,*r6         ;assign page to sams register
        swpb    *r1
rwops   ci      r3,1            ;is it a write operation?
        jne     getops
saveops mov     *r4+,*r5+       ;save 2 bytes at a time (word)
        jmp     contops
getops  mov     *r5+,*r4+       ;get 2 bytes at a time
contops dect    *r2
        jle     opsdone         ;no more data
        inct    r0
        ci      r0,4096         ;are we past 4k of data?
        jlt     rwops
        inc     *r1             ;next page number
        clr     r0
        li      r5,2000h
        jmp     nxtpage         ;continue data ops
opsdone li      r1,0200h        ;restore sams register to original page
        mov     r1,@4004h
        sbz     1               ;turn mapper off
        sbz     0               ;turn off sams card
        bl      @pcodeon
        mov     @procret,r11
        b       *r11

        .end

 

 

VDP utilities:

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           ;pme vr table

        .proc   vwtr,2
;vdp write to register
;usage: vwtr(regnum, byteval)

        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
        
        .proc   vsbr,2
;vdp single byte read
;usage: vsbr(vdpadr, bytevar)
        
        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
        movb    @vdprd,*r0      ;store vdp byte into variable
        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 value
        dec     r1              ;calculate vr address in table
        sla     r1,1
        ai      r1,vrtab
        movb    r0,*r1          ;save vr value in table
        b       *r11
        
        .end
        
        

 

 

 

 

SAMSUTIL.dsk

  • Like 2
Link to comment
Share on other sites

OK everything works as it should now. The p-system was never intended to be used in bitmap mode, so credit goes to @apersson850 for figuring out how to coerce it to do so. Only issue is getting the keyboard key capture working while in bitmap mode. I'll have to study @apersson850's Turtle unit to see how he did it.

 

SAMSUTIL.dsk

  • Like 8
Link to comment
Share on other sites

I'm using MAME but probably I'm doing something wrong.

 

If I kick <E> or <R> is complaining about missing compiler or editor.

 

image.thumb.png.27805ec2356dd097511a88aba28871de.png

image.thumb.png.b5ea3e37907aa72f1aac1a338617253e.png

 

image.thumb.png.574391b0059a6cdf22e26689a0ebcce6.png

 

This is my command lone for execution: ./mame ti99_4a -window -nomouse -skip_gameinfo -autoframeskip -natural -ioport peb -ioport:peb:slot2 32kmem -ioport:peb:slot3 tirs232 -ioport:peb:slot4 pcode -ioport:peb:slot8 tifdc -flop1 "software/ti99_4a/disks/SAMSUTIL.dsk"

 

Thanks!

 

  • Like 1
Link to comment
Share on other sites

1 hour ago, gferluga said:

I'm using MAME but probably I'm doing something wrong.

 

If I kick <E> or <R> is complaining about missing compiler or editor.

 

image.thumb.png.27805ec2356dd097511a88aba28871de.png

image.thumb.png.b5ea3e37907aa72f1aac1a338617253e.png

 

image.thumb.png.574391b0059a6cdf22e26689a0ebcce6.png

 

This is my command lone for execution: ./mame ti99_4a -window -nomouse -skip_gameinfo -autoframeskip -natural -ioport peb -ioport:peb:slot2 32kmem -ioport:peb:slot3 tirs232 -ioport:peb:slot4 pcode -ioport:peb:slot8 tifdc -flop1 "software/ti99_4a/disks/SAMSUTIL.dsk"

 

Thanks!

 

The editor/filer, compiler, and assembler/linker are all separate disks. I have attached all the system disks you need for the p-system. The Editor/Compiler disk needs to be inserted in one of the drives in addition to SAMSUTIL if you want to view/edit or run files from the latter.

ASM-LNK.DSK EDITOR-COM.dsk UCSD-UTI.DSK

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

5 minutes ago, mizapf said:

TIImageTool says that this disk image has 80 tracks. This won't work with the standard 5.25" drives in MAME; maybe try a 3.5" drive. Or copy the contents to a 40 track image.

It's not. I have a standard 40 track TIFDC on my system.

Link to comment
Share on other sites

I just tried, and it seems as if the disk system in MAME interprets the 180K disk as 40 tracks, overriding the information in the Volume Information Block.

 

00000000: 5341 4d53 5554 494c 2020 02d0 0944 534b  SAMSUTIL  ...DSK
00000010: 2050 0201 0000 0000 0000 0000 0000 0000   P..............
00000020: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000030: 0000 0000 0000 0000 ffff ffff ffff ffff  ................
00000040: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000050: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000060: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000070: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000080: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000090: ffff ffff ffff ffff ffff ffff ffff ffff  ................

 

The 0x50 value at 0x00000011 means 80 tracks in the standard TI file system. For 40 tracks, this should be 0x28.

 

Maybe in Pascal this value is ignored.

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...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...