Asmusr Posted April 1 Share Posted April 1 35 minutes ago, gferluga said: Looks like SAMS card is not available in Mame 🤔 Have you tried -ioport:peb:slot2 samsmem ? 1 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted April 1 Author Share Posted April 1 (edited) The p-system doesn't care about the disk format at all. It just uses the sector read/write subroutine and let the low level bios figure out how to access the disk. When using bitmap with the p-system you must move the keyboard buffer, since it's disturbing your graphics otherwise. Why save the VDP memory prior to doing bitmap graphics? There's nothing to save, since that's the whole reason for why you can reserve the space. Edited April 1 by apersson850 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted April 1 Share Posted April 1 1 hour ago, apersson850 said: Why save the VDP memory prior to doing bitmap graphics? There's nothing to save, since that's the whole reason for why you can reserve the space. It seemed like the safe thing to do as I frankly was not sure if there was something worth preserving. It was painless enough to do One question: Do I need to update the Pascal VDP registers vr1-7 in low memory when I switch to bitmap before calling the keyboard scan routine? Also your code mentions a keyboard layout area. What is that? Quote Link to comment Share on other sites More sharing options...
apersson850 Posted April 2 Author Share Posted April 2 Regarding VDP memory: Either you can do the bitreserve without any issue. If you can, then that's because there is nothing worth saving in VDP memory in that area which the bitmap mode needs. Or you can't do bitreserve, since the area needed is already occupied by something the p-system needs. That "something" is then code, since that's the only thing the p-system will store in that area. If there is code there you need to save it prior to showing bitmap images. But, and that's a big but, that also implies that you most likely can't return from your assembly code handling bitmap, since if you want to do that, you have to restore VDP memory and then you destroy your image. Or you don't restore just because you return and then you may try to run the bitmap image as code. Which of course will not end well. Thus the result is that saving the VDP is either not necessary or doesn't make any difference. The p-system holds a keyboard buffer (the type ahead queue) and information about which keys are to be interpreted for certain functions in VDP RAM. For some reason - maybe they didn't at the time that decision was taken realize that they would get some unused RAM left over at the top of the low memory expansion. You have to move these things out of the way for the bitmap mode. Fortunately there are some holes in the VDP RAM usage for bitmap. 3 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted April 2 Share Posted April 2 So here's my question about backing up the VDP RAM. The lower 4K will hold the standard character definitions which will get overwritten by a bitmap image. I did notice that even without manually restoring that area, somehow the definitions get restored when I return from bitmap. How is that possible? I knew about the keyboard buffer, but not the layout area. Is that the area which hold the key information you mention (120 bytes)? Also what about the Pascal VDP registers? You update them in your code after changing the standard VDP registers and I'm not too clear as to why. It's really important for me to understand fully how to do the bitmap switch back and forth while preserving as much function as possible, hence why I am peppering you with questions. You're the only person alive as far as I know with such in-depth knowledge of the system and I'm trying to leech as much of that priceless info as possible before it's too late! 😁 I also heard that you will be writing a series of articles on the p-system for the Chicago User Group newsletter. I'm looking forward to reading those. 5 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted April 2 Author Share Posted April 2 (edited) Here are some pieces of the code. I've added some more comments (not syntactically correct to assemble). What's shown here is how to enter into bitmap mode. The last part clears the screen and loads values into all VDP memory that's used for bitmap. It can be called separately to just clear the screen. Then there's a corresponding routine not copied below that returns from bitmap mode to something normal. It kind of moves everything back to where it came from, character definitions included. That's why various pointers in the .EQU section have two values. KEYBUF1 is used normally by the p-system, KEYBUF2 when the bitmap mode is active and so on. If you don't take care of the character definitions it could be that they are re-loaded from OS:SYSTEM.CHARAC when your program terminates. I've not checked that. If you have looked at my screenshots you may have noticed that I have a different default character set than you have. You can make your own character definitions and store as *SYSTEM.CHARAC Note that I set up to be able to use sprites, but I haven't done anything to handle that. You can not use the supplied unit sprite, since it will assume the sprite table to be in the normal place, where it can't be with bitmap. SP .EQU 10 PASCALWS .EQU 8380H VDPRD .EQU 8800H ;VDP read data address VDPWD .EQU 8C00H ;VDP write data address VDPWA .EQU 8C02H ;VDP write address address KEYBUFPNT: .EQU 288AH ;Keyboard buffer pointer LAYOUTPNT: .EQU 288CH ;Keyboard layout pointer KEYBUF1 .EQU 0BE0H ;Normal key buffer KEYBUF2 .EQU 1B80H ;Bit-map key buffer LAYOUT1 .EQU 0D80H ;Normal layout area LAYOUT2 .EQU 1BA0H ;Bit-map layout area REGCOPY .EQU 2810H ;PME copy table of VDP R1..R7 PATTERN1 .EQU 0 ;Pattern generator table PATTERN2 .EQU 2000H COLTAB1 .EQU 0BC0H ;Color table COLTAB2 .EQU 0 IMAGE1 .EQU 0800H ;Screen image table IMAGE2 .EQU 1800H SAB1 .EQU 0C00H ;Sprite attribute table SAB2 .EQU 1B00H SAVE2A .EQU 1C18H ;Otherwise unused area between tables ; Now used to hold character definitions SAVE2B .EQU 3800H ;Additional save area This is where bitmap mode is set up and the screen is cleared. .PROC BITMAP,1 .DEF VMBR,VMBW,VSBW,VSBR,VWTR,VFILL .DEF INITSTUFF Start by moving the beyboard type ahead buffer out of harm's way and update the pointer. LI R0,KEYBUF1 ;Move keyboard buffer MOV *SP+,R1 ;Get address of general buffer LI R2,20H ;Size of buffer BLWP @VMBR LI R0,KEYBUF2 BLWP @VMBW MOV R0,@KEYBUFPNT Do the same with the keyboard layout area. LI R0,LAYOUT1 ;Move layout area LI R2,120 ;Size of area BLWP @VMBR LI R0,LAYOUT2 BLWP @VMBW MOV R0,@LAYOUTPNT Set up VDP registers and save a copy for the PME, in case it thinks it should restore them. LI R0,81A0H ;Blank screen BLWP @VWTR LI R0,8002H ;Set control registers for bit map mode BLWP @VWTR ;No PME copy of VDP R0 LI R0,8206H BLWP @VWTR MOV R0,@REGCOPY+2 ;Update PME copies of VDP regs LI R0,837FH BLWP @VWTR MOV R0,@REGCOPY+4 LI R0,8407H BLWP @VWTR MOV R0,@REGCOPY+6 LI R0,8536H BLWP @VWTR MOV R0,@REGCOPY+8 Save the character definitions as they are when entering bitmap. I use them in the procedure to write a character anywhere on the bitmap screen. All of them doesn't fit in the same place. LI R0,PATTERN1 ;Save first 24 bytes of pattern table LI R2,24 ;Corresponds to chr(0)..chr(2) BLWP @VMBR LI R0,SAVE2B BLWP @VMBW LI R0,PATTERN1+24 ;Save next 1000 bytes LI R2,1000 ;Corresponds to chr(3)..chr(127) BLWP @VMBR ;chr(128)..chr(255) not saved LI R0,SAVE2A BLWP @VMBW LI R0,SAB2 ;Disable first sprite LI R1,0D000H BLWP @VSBW Finalize the setup by clearing the screen and loading all values in the character, pattern and color tables. ; This is an entry point for initbitmap. Here you start running if you are already in bitmap mode, but want to erase all graphics to clear the screen. ; INITSTUFF: LI R0,COLTAB2 ;Set color table to black on transparent LI R1,1000H LI R2,1800H BLWP @VFILL LI R0,IMAGE2 .OR 4000H ;Initiate screen image table SWPB R0 MOVB R0,@VDPWA SWPB R0 MOVB R0,@VDPWA LI R0,3 ;00..FF repeated three times LOOP2 CLR R1 LI R2,100H ;Counter LOOP1 MOVB R1,@VDPWD AI R1,100H DEC R2 JNE LOOP1 DEC R0 JNE LOOP2 LI R0,PATTERN2 ;Set pattern table to all blank CLR R1 LI R2,1800H BLWP @VFILL LI R0,81E0H ;Enable screen in graphics mode BLWP @VWTR MOV R0,@REGCOPY B *R11 As a general comment: Feel free to understand what it's doing, but use my unit to get into and out of bitmap mode, so we have the same base to build on. I've got some ideas about implementing a store/retreive function of part of the screen, which I of course would base on my own turtlegraphics unit. If I come to that, and you do some other enhancement based on the same unit, then we can easily combine the result of our efforts and come up with a better unit. Edited April 2 by apersson850 2 Quote Link to comment Share on other sites More sharing options...
gferluga Posted April 2 Share Posted April 2 On 4/1/2024 at 8:14 PM, Asmusr said: Have you tried -ioport:peb:slot2 samsmem ? Yes... ./mame ti99_4a -window -nomouse -skip_gameinfo -autoframeskip -natural -ioport peb -ioport:peb:slot2 samsmem -ioport:peb:slot8 bwg -ioport:peb:slot8:bwg:2 525dd -ioport:peb:slot3 pcode -flop1 "software/ti99_pcode/SAMSUTIL.dsk" Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted April 2 Share Posted April 2 3 hours ago, gferluga said: Yes... ./mame ti99_4a -window -nomouse -skip_gameinfo -autoframeskip -natural -ioport peb -ioport:peb:slot2 samsmem -ioport:peb:slot8 bwg -ioport:peb:slot8:bwg:2 525dd -ioport:peb:slot3 pcode -flop1 "software/ti99_pcode/SAMSUTIL.dsk" It's actually a bug in my code. When reading the SAMS registers, a real SAMS card will only return the MSB (the page #) but not the LSB, whereas Classic 99 will return both as a word instead of a byte. MAME accurately emulates the SAMS behavior, including how the registers are read, which is why the program failed to detect the card. Same behavior on real hardware. Attached is a corrected version (replacing a C instruction by a CB one...) which fixes the issue. Sorry about that. SAMSUTIL.dsk 2 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted April 2 Share Posted April 2 You are allowed one bug a week I believe. I am always over my limit. 4 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted April 2 Share Posted April 2 Just now, TheBF said: You are allowed one bug a week I believe. I am always over my limit. (That's my weird way to say I think you are doing amazing stuff with the P code card.) 3 1 Quote Link to comment Share on other sites More sharing options...
Tursi Posted April 3 Share Posted April 3 2 hours ago, Vorticon said: When reading the SAMS registers, a real SAMS card will only return the MSB (the page #) but not the LSB, whereas Classic 99 will return both as a word instead of a byte. MAME accurately emulates the SAMS behavior, including how the registers are read, which is why the program failed to detect the card. Classic99 is perfectly accurate for the 32MB card it's emulating, thank you. If it didn't return both bytes you wouldn't be able to tell what page was mapped. Now whether that 32MB card will ever be released I don't know. 2 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted April 3 Share Posted April 3 25 minutes ago, Tursi said: Classic99 is perfectly accurate for the 32MB card it's emulating, thank you. If it didn't return both bytes you wouldn't be able to tell what page was mapped. Now whether that 32MB card will ever be released I don't know. And in fact the hardware on the 1M card does the same as we can see in the image. Here I turn on the card and then dump the registers at >4000. 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted April 3 Share Posted April 3 40 minutes ago, TheBF said: And in fact the hardware on the 1M card does the same as we can see in the image. Here I turn on the card and then dump the registers at >4000. Not on my 1meg card. The detection failed just as in MAME with my original code. Are there different versions of the card? 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted April 3 Share Posted April 3 1 hour ago, Tursi said: Classic99 is perfectly accurate for the 32MB card it's emulating, thank you. If it didn't return both bytes you wouldn't be able to tell what page was mapped. Now whether that 32MB card will ever be released I don't know. True, but it's still problematic if one wants to support current existing hardware. There used to be an option to choose the size of the SAMS in Classic99, but it's now grayed out. 1 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted April 3 Share Posted April 3 Could it be that different 1M cards work in different ways (some return the register value in both MSB and LSB and others only return it in the MSB)? I implemented the behavior that TheBF demonstrated in JS99er, but that broke the Stevie editor, so I changed it back. 4 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted April 3 Share Posted April 3 I got the keyboard scanning routine to work in bitmap mode following @apersson850's method of relocating the keyboard buffers, but I also needed to restore the Pascal VR1 in low memory prior to exiting the routine as it seemed that the KSCAN routine was affecting it somehow. Otherwise I would get a garbage screen from an incorrectly set VR1. I don't have a clear explanation for this because the scanning routine copies the Pascal VRs to the RAMPAD and KSCAN is supposed to only use that area and should not affect the Pascal VR's. More often than not the p-system feels like it's finely balanced on the tip of a needle, and any unsanctioned activity like bitmap access will upset that balance and lead to unexpected behavior... Still waiting for that wig Anders... Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted April 3 Share Posted April 3 13 hours ago, Vorticon said: True, but it's still problematic if one wants to support current existing hardware. There used to be an option to choose the size of the SAMS in Classic99, but it's now grayed out. 12 hours ago, Asmusr said: Could it be that different 1M cards work in different ways (some return the register value in both MSB and LSB and others only return it in the MSB)? I implemented the behavior that TheBF demonstrated in JS99er, but that broke the Stevie editor, so I changed it back. To be compatible with current SAMS hardware, the returned LSB should always be ignored when reading the SAMS registers. SAMS hardware merely repeats the page number of the MSB in both bytes, whereas Classic99 does, in fact, return the bank# in the LSB and the page# in the MSB. ...lee 4 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted April 3 Share Posted April 3 37 minutes ago, Lee Stewart said: To be compatible with current SAMS hardware, the returned LSB should always be ignored when reading the SAMS registers. SAMS hardware merely repeats the page number of the MSB in both bytes, whereas Classic99 does, in fact, return the bank# in the LSB and the page# in the MSB. If I wrote a program for the TI, I would never rely on the LSB unless I had detected a card bigger than 1 MB. But as the developer of an emulator, I would like to know the most correct way to emulate a 1 MB card. It sounds like there are at least 2 types of card: one that returns zero in the LSB (Vorticon + retroclouds) and one that returns a copy of the MSB (TheBF + emulated in MAME). 2 Quote Link to comment Share on other sites More sharing options...
+mizapf Posted April 3 Share Posted April 3 The MAME implementation is not suitable as a reference, since I simply did the following: if (m_access_mapper && in_dsr_space(offset, false)) { *value = m_mapper[(offset>>1)&0x000f]; } So it seems as if I did it the simple way: If the access to the mapper registers is active, and the address is within the DSR space, get the value by indexing the mapper chip, where the index is gained by shifting the address one to the right and masking away all but the last 4 bits. This means that odd addresses are treated like even addresses (losing the rightmost bit) and that the mapper is mirrored throughout the DSR area. I'd have to study the schematics more closely to give a meaningful answer. 4 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted April 3 Share Posted April 3 1 hour ago, mizapf said: The MAME implementation is not suitable as a reference, since I simply did the following: if (m_access_mapper && in_dsr_space(offset, false)) { *value = m_mapper[(offset>>1)&0x000f]; } So it seems as if I did it the simple way: If the access to the mapper registers is active, and the address is within the DSR space, get the value by indexing the mapper chip, where the index is gained by shifting the address one to the right and masking away all but the last 4 bits. This means that odd addresses are treated like even addresses (losing the rightmost bit) and that the mapper is mirrored throughout the DSR area. I'd have to study the schematics more closely to give a meaningful answer. I tried it now, and my real sidecar SAMS is also returning a duplicate of the MSB in the LSB (inspected using Easybug) and it's mirrored throughout the DSR area. 3 Quote Link to comment Share on other sites More sharing options...
Tursi Posted April 3 Share Posted April 3 16 hours ago, Vorticon said: True, but it's still problematic if one wants to support current existing hardware. There used to be an option to choose the size of the SAMS in Classic99, but it's now grayed out. It actually never worked. It was always 1MB until I was asked to support the 32MB version. I greyed it out to remove the confusion. I do recognize this causes some issues for some people, but nobody has ever asked me to fix it! 3 Quote Link to comment Share on other sites More sharing options...
Tursi Posted April 3 Share Posted April 3 I think a challenge is that there are multiple iterations of AMS-like memory cards. I'm not at all surprised that some return 0 and some return a duplicate. This is not entirely unlike the issue we discussed a decade or so ago that the TI memory expansion card, based on DRAM, tends to init with an alternating pattern of 00 FF, while SRAM expansions tend to initialize with 00 (and that this actually broke one or two programs that assumed). It's unclear whether the extended card that I implemented will ever be released, but Nouspikel also describes such a thing to take it to 16MB: https://www.unige.ch/medecine/nouspikel/ti99/superams.htm For maximum flexibility, anything not part of the actual specification should generally be treated as "ignore" rather than to assume a pattern observed there will be consistent. This is standard practice in most embedded hardware. @Asmusr's suggestion was the one that I thought had been adopted - to simply ignore the LSB unless you are expecting to find more than 1MB. I don't remember now, but we had someone build a top-end AMS tester a few years ago. Does it handle more than 1MB? If yes, what was its approach? My understanding was treating it in this manner should allow both the 1MB card and the 32MB card to function with the same code. Is that untrue? None of this to be meant that you can't write whatever code you want. I mean, we don't have a huge community and it's all for fun anyway. But understanding what does and doesn't work, and what practices are followed, can help the emulation get better too. 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted April 3 Share Posted April 3 Well one way that would universally work would be to write a discordant value, say >0102 to the registers, then on a first pass test the MSB. If it passes, then test for the whole word. If it passes again then we have a card larger than 1 meg, otherwise it's smaller or equal. LI R1,>0102 MOV R1,@>401E CB R1,@>401E JNE NOCARD C R1,@>401E JNE SMCARD JMP LGCARD 1 Quote Link to comment Share on other sites More sharing options...
+chue Posted April 3 Share Posted April 3 1 hour ago, Tursi said: we had someone build a top-end AMS tester a few years ago. Does it handle more than 1MB? If yes, what was its approach? I know nothing about implementation, but JediMatt's RAM tester sees greater than 1MB on Classic99, as well as JasonAct's PicoPEB: According to the github, the tester will see up to 16MB: https://github.com/jedimatt42/ti994a-memtest 4 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted April 4 Share Posted April 4 I applied my little scheme above to detect large capacity SAMS cards and it works. Classic99 QI399.065 2024-04-04 05-18-45.mp4 Spoiler .func samsinit ;initialize the sams card and verify card is present ;returns 0 for absent, 1 if <= 1Mb and 2 if > 1 Mb ;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 cb r1,@401eh ;if match then card present jne nocard li r1,0102h mov r1,@401eh c r1,@401eh jeq lgcard li r2,1 jmp endinit lgcard li r2,2 jmp endinit nocard clr r2 endinit li r1,0f00h mov r1,@401eh mov r2,*r10 ;place card indicator on return stack sbz 0 ;turn sams card off bl @pcodeon mov @procret,r11 b *r11 And here it is on real hardware with my 1mb card: 5 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.