Jump to content

apersson850

Members
  • Posts

    2,065
  • Joined

  • Last visited

  • Days Won

    2

Everything posted by apersson850

  1. I assume you're joking. It's very easy to figure out where the idea with larger and smaller capital letters came from.
  2. He probably has some AI-inspired BASIC interpreter according to the "Do what I mean, not what I say" principle. To be (slightly) serious, cosine is a periodic function, so with some luck you get something similar, regardless of what kind of data you put in.
  3. That's correct. I tried to stay as close to the implementation of turtlegraphics in Apple Pascal for Apple ][ as I could, to make it as easy as possible to run programs originally designed for that computer. It wasn't possible to match it completely, since the Apple has a different way of handling colors than the TI. Not the same video processor.
  4. The turtlegraphics unit is in a "proof of concept" phase, and has been like that for 35+ years. There are some functions in the different write modes that don't work and some other stuff that's not implemented. But if you include uses support and then set the screen color the normal way, I think that's compatible with the turtlegraphics unit too, since it only changes a VDP register. Update: I checked in one of my test programs. It does uses support and then starts with this sequence. (* Gives a darker background *) set_scr_color(ord(black),ord(red2)); grafmode; The color change is done prior to entering bitmap mode. Not sure what happens if you do it with bitmap mode active. But the default background color for screen items is transparent, so the backdrop should be visible.
  5. The best thing I see with it is that you more or less took the original code, changed the syntax from BASIC to Pascal and it ran!
  6. Looks like it's some preferred way at TI (if you don't have a TI 990 mini computer) to write assembly language subroutines before the Editor/Assembler package was introduced.
  7. It may make sense anyway, since the JEQ will test the last thing that happened in the subroutine. As stated before, CLR doesn't change any status bits since the result is obvious anyway.
  8. Yes, but using Setltype (Set Language Type) is easier than doing the linking. As always (?) with the p-system, there are more to it than that. Let's recap how units work. Separate compilation One of the advantages of the unit concept in UCSD Pascal is that you can compile parts of your program separately. If the program is very large that's a necessity, since our little computer doesn't have memory enough to compile too large programs. By compiling a unit instead of a program, you create a support file for your program. The unit comtains an interface part which defines to the main program the data and procedures available and an implementation part which contains the code to execute. The user of a unit doesn't need to know how the procedures are implemented, only how to call them. You can even change the implementation without having to re-compile the programs using the unit, as long as the interface is the same. Compiling the unit This is as easy as compiling a program. Just run the compiler and it creates the code file for you. The basic structure of a unit is as below. unit example; interface type extype = record this, that: integer; end; procedure doexample(handle: extype); implementation procedure doexample; begin (* Code *) end; end. Compiling the program When a program uses a unit, it must know where to find the unit's code file. Easiest is if it's included in the *SYSTEM.LIBRARY file. Then it's all automatic. (Note that the * in the filename represents the system volume, i.e. the boot disk that was in #4: when starting the system. It's not part of the file name, but equivalent to passys: if the system disk is called passys. In such a case, *SYSTEM.LIBRARY is equivalent to PASSYS:SYSTEM.LIBRARY or #4:SYSTEM.LIBRARY, provided pasys is actually mounted in drive #4:.) In the case the unit is in a separate code file you need to tell the compiler where to find it. In the example below the first unit is in *SYSTEM.LIBRARY but the second is not. program unittest; uses support; (*$U develop:exfile.code *) example; Running the program When you run the program the same is true: If the unit is in *SYSTEM.LIBRARY everything works automatically. The build_env procedure in the operating system will locate the units referred to by your program and build the run-time environment records and vectors so the system can locate the files needed when they are needed. However, if the unit is still in a separate file, you need to tell the build_env where to locate it. This can be done by a text file listing the library files to search, just as @Vorticon showed above. In this example the content of the text file would simply be this: develop:exfile.code If you do store this in the text file called *USERLIB.TEXT (note that it must be on the system disk), then the program will find your unit. However, when you are designing your program you may not want to mess with a perhaps already existing *USERLIB.TEXT file. You can create a separate library reference file for your experiments. The content would still be like above, but you can store it in DEVELOP:EXLIBS.TEXT. But that's not where the run-time system will look by default. To make this work at runtime you have to use an execution option. You set it up by pressing X (for eXectue) at the top system level. But instead of entering a file name of a program to execute, you type in L=develop:exlibs.text. Now you've told the system you have a user-defined library reference file, so it can find it and through the information in it find your unit. You can list more than one unit in such a file, if you have your units spread all over the place.
  9. You already know how to do poke and peek in Pascal, with the dual data type. Poke the VDP read address port to the VDP, then peek the VDP read data port from the VDP. If you want to write to VDP RAM or to VDP registers, you need to set the second or first bit in the address. Remember that UCSD Pascal can do bitwise logic functions by using the odd and ord functions. So you can do VDP_address := ord(odd(16384) or odd(your_address)); where both VDP_address and your_address are integers. That will set the VDP address for a write (which you don't need for GCHAR, of course). Also note that you'll need to create a swapbyte function, but there you can do a dual data type with an integer and a packed array[0..1] of byte, where byte is 0..255, to handle that. A word of caution! In the example above the constant 4000H is represented by the 2's complement decimal number 16384. If you want to get the equivalent of 8000H into a decimal number, you can not use the constant -32768! Since that number can't be negated without an overflow (there is no +32768 in the range of 2's complement 16-bit numbers) it will be handled like a long integer constant, occupying two words, not one. But you can use 32767+1, as UCSD Pascal does no overflow detection on integer arithmetic. As long as you don't divide by zero, that is. Note that for this direct VDP access to work you need to manually set the code type to M_9900, since if it's M_PSEUDO then the code usually will be loaded in VDP RAM. If you then change the read address the PME will get lost about where the code is. The PME will only set the VDP read address when performing a jump. If you link in an assembly procedure into your Pascal program the linker will set the code type automatically, since assembly can't run from VDP RAM. But the compiler can't know which memory you'll access in a Pascal program, so there it's not automatic.
  10. If you aren't going to use it too frequently you can write the whole thing in Pascal. Then you don't need the linking. But otherwise you're correct.
  11. Now I don't know what kind of game you are planning to convert, but if it's something that has some kind of action, then you should be aware of that if you put such a function as @Vorticon provided above in a pre-compiled unit, then you have a very convenient way of handling it. But you also have the absolutely slowest possible call command to use it. A global external inter-segment call is by far the most complex way there is to invoke a procedure. So if you intend to call this gchar equivalent frequently I recommend you include it in your main program instead.
  12. The whole thing is further complicated by the fact that the p-system really is an 80 column screen system. All printout is on the 80 column screen, and then you select which part of that you want to show on your physical screen. So you have to decide if you want to read things from the physical or logical screen. The operating system also has a data area with a pointer to the 80 column screen and the physical screen's height and width. You can also see which is the current window shown on the screen. Here's an extract of some system data. The simplest way to see if you are in text or graphics mode is to check the value at 2CC6H. If it's 40 you are in text mode. If it's 32 it's graphics mode. 2CAC AA00 DATA DSR validation code 2CAE 0080 2CB0 81F0 DATA VDP copy R1 2CB2 8202 DATA VDP copy R2 2CB4 832F / DATA VDP copy R3 2CB6 8400 DATA VDP copy R4 2CB8 8518 DATA VDP copy R5 2CBA 8600 DATA VDP copy R6 2CBC 001F DATA VDP copy R7 2CBE 2000 DATA Pointer 80 column screen 2CC0 0017 DATA Current line 2CC2 0000 DATA Current column 2CC4 2730 '0 DATA Current 80 column address 2CC6 0028 ( DATA Screen width 2CC8 0018 DATA Screen height 2CCA 0000 DATA Current screen window 2CCC 0730 0 DATA Number of bytes in 23 lines (for scroll)
  13. Exactly. Which is why I wrote hardly in a general manner. It doesn't work well on a standard machine, since the memory is too small.
  14. Thinking a bit further about the procedure to enter and leave bitmap mode, I can see that there is one thing which I do not save, and that is character definitions in the range 128..255. The reason for that is of course that I would have had to save them in a file, as there's no room without some kind of memory expansion. My decision was that it was not worth it, since if you actually do use these character definitons, then it's probably because you want to do some minor graphic thing, in which case you don't use bitmap. If you do use bitmap, on the other hand, it's not too likely that you also in the same program want to use special definitions of characters 128..255. Since I have no definitions for them I don't print them on the screen with the wchar function unit turtlegraphics supports anyway. The next step in a possible further development of unit turtlegraphics is probably to allow a copy/paste functionality of the screen. I envision that to work like this: Define a viewport on the screen. Copy the graphics inside the viewport and store in a file (because that's the only way if it's the full screen). Define a new viewport. Paste the copied file into that viewport. Steps 3-4 can of course be repeated to create multiple copies of the graphics on the screen. If the viewport is defined to cover the whole screen you'll effectively create screen images, which you can restore by reading in the files. Pasting a graphic object can be done in several ways, just like when drawing lines. Just overwrite what's there is simplest, but you can also imagine adding it to the existing graphics, subtract it and so on. The current functions in unit turtlegraphics can also handle just the image or the image and color as a unit. Some systems do allow you do manipulate graphics as a separate non-visible object, then copy that to the screen when it's ready. Doable on the 99/4A too, but hardly in a general manner, since the largest images will be troublesome to have in memory together with the bitmap mode and a meaningful software handling them, all at the same time. Anyway, storing these graphic objects as files has the advantage that it works on all systems but can also work almost at RAM speed if there is a RAMdisk defined in the system. If you want to make a program that rolls through a number of screens you can predefine those as files on a disk, copy these files to the RAMdisk when starting the program and then run them from the RAMdisk to reduce delays.
  15. Unless there's some other possibility to save in execution time, that opens up as a result of the change, it does indeed not look like any saving from that only thing you show in the post.
  16. Such things have probably happened everywhere. In my small town of birth, Örkelljunga (population around 5000), there were six different power suppliers a hundred years ago. Each with their own transformer and own distribution network. Many of these inagurated as suppliers of some local industry and then sold what was left over to households for illumination. It soom became obvious that it would not be feasible to continue to build a lot of parallel systems, but instead a power supplier could lease capacity in a network owner's grid, and vice versa. For that to be possible they had to unite on a common specification. Which in Sweden became 220/380 VAC 50 Hz. Today normalized with the rest of Europe to 230/400 V. There were 25 Hz and DC suppliers here too before this era. Still today the Swedish railways run on 16 2/3 Hz at 16 kV. Denmark uses 25 kV at 50 Hz. This again is because Sweden was early adopters. With companies like ASEA in the country, electric railway propulsion was early and expanded a lot during that same second world war, due to the shortages of coal. Back then, traction motors ran better on lower frequencies and it also made it more difficult to steal electric current from the railway supply lines. A drawback of higher frequencies is that motors become less effective. Smaller, but less effective. In the aircraft industry 400 Hz is common, but there low weight is considered more important than high efficiency.
  17. If it hadn't been for the second world war... Today, the monitor refresh rate doesn't have to be linked to the supply frequency, but with analogue TV that was the most convenient. In Europe, before the second world war, there were a lot of different voltages and frequencies, DC included, in the public grids. When rebuilding after the war it was considered an advantage if everybody did it the same way, so everything that was rebuilt aimed for 230 V 50 Hz. The few exceptions were countries where war had not raged on their soil, like the United Kingdom and Sweden. Sweden has later adapted, UK is still at 240 V, but all at 50 Hz. In the US, however, there was no infrastructure destruction and USA was also pretty early with electricity in homes and industries. So although it was realized that the European system now being built was better, it was too late. Too many refrigerators were already out there to make it unrealistic to change. Japan had no real choice. Although the war never reached their home islands, they were heavily bombed. After the war, they had to use what they could get. That ended up being a mess of mobile generators, collected by the winning powers in preparation for an invasion. It was too expensive to bring these devices back home, so they stayed in Japan to power the country while the grids were repaired. Since it was a mishmash of European 50 Hz and US 60 Hz generators, the decided to move those of the same type to the same end of the country. To this day Japan has both 50 and 60 Hz, together with four big converter sites, allowing for power transfer between the north and south.
  18. There's not much to learn by testing status bits after doing a CLR, regardless of whether it is possible or not. You already know that the result it pretty close to zero. A method you haven't mentioned yet is taking advantage of the peculiar design of the TMS 9900. If you want to access R7 byte by byte you can simply do MOVB R7,somewhere MOVB @MYREGS+15,somewhere+1 In the case you don't know what registers you are running with you can do this MOVB R7,somewhere STWP R4 MOVB @15(R4),somewhere+1 The result at somewhere is the same as after MOVB R7,somewhere SWPB R7 MOVB R7,somewhere+1 The first two have the possible advantage that the content of R7 is not disturbed.
  19. Here is what unit turtlegraphics uses to come back from bitmap to standard text mode again. The addresses used where defined in my post about how to enter bitmap. ; procedure nobitmap(var buffer: sometype, 1000 bytes large); ; .PROC NOBITMAP,1 .REF VMBR,VMBW,VSBW,VWTR,VFILL LI R0,KEYBUF2 ;Restore keyboard buffer MOV *SP+,R1 ;Buffer LI R2,32 BLWP @VMBR LI R0,KEYBUF1 BLWP @VMBW MOV R0,@KEYBUFPNT LI R0,LAYOUT2 ;Restore keyboard layout area LI R2,120 BLWP @VMBR LI R0,LAYOUT1 BLWP @VMBW MOV R0,@LAYOUTPNT LI R0,81A0H ;Disable screen during manipulations BLWP @VWTR CLR R0 BLWP @VWTR ;No bit-map LI R0,8202H BLWP @VWTR MOV R0,@REGCOPY+2 ;PME copies of VDP regs LI R0,832FH BLWP @VWTR MOV R0,@REGCOPY+4 LI R0,8400H BLWP @VWTR MOV R0,@REGCOPY+6 LI R0,8518H BLWP @VWTR MOV R0,@REGCOPY+8 LI R0,8717H BLWP @VWTR MOV R0,@REGCOPY+12 LI R0,SAVE2B ;Restore character definitions LI R2,24 ;chr(128)..chr(255) are blanked BLWP @VMBR LI R0,PATTERN1 BLWP @VMBW LI R0,SAVE2A LI R2,1000 BLWP @VMBR LI R0,PATTERN1+24 BLWP @VMBW LI R0,PATTERN1+1024 CLR R1 ;Blank unsaved definitions MOV R0,R1 BLWP @VFILL LI R0,COLTAB1 ;Set color to black/transp. LI R1,1000H LI R2,32 BLWP @VFILL LI R0,SAB1 ;Disable first sprite LI R1,0D000H BLWP @VSBW MOV R11,R7 BL @47D2H ;Put back previous text on screen LI R0,40 MOV R0,@2CC6H ;Set screen width for text mode LI R0,81F0H ;Set VDP to text mode BLWP @VWTR MOV R0,@REGCOPY B *R7
  20. I agree. It's mainly if you need access to larger global data areas from the subroutine that the GOSUB-RETURN construct is the one you have to use.
  21. I've never used PERMANENT with any SUB in Extended BASIC. I've used a lot of SUBs, though. The different handling in CALL SUBROUTINE(X) and CALL SUBROUTINE((X)) is due to that in the latter, Extended BASIC interprets the argument as an expression, not a variable. Since you can't redefine an expression from inside a SUB, the effect is a value parameter instead of a reference one. In Pascal you would use procedure subroutine(var x: integer); as an alternative to procedure subroutine(x: integer); A big difference is that local variables in procedures in Pascal aren't static. They are forgotten as soon as you exit the procedure and thus don't keep their value for the next call. This is also why you can call a procedure recursively in Pascal, but you can't do that with a SUB in Extended BASIC.
  22. I'd rather say that the more you learn about the PME's details, the better you'll find out that it's actually a pretty robust system, well modularized and where virtually all critical code items are referenced by tables in RAM. This makes it possible to exchange parts of the system as needed. Just plug in the new code somewhere and adjust a pointer, in spite of the original code being in ROM. Likewise, the p-system running on top of the PME is almost completely hosted in the multi-segment file OS:SYSTEM.PASCAL. That file can, segment by segment, be replaced by a new segment with the same name residing on the system disk. At the cost of using more RAM (the PME can execute the segments in OS:SYSTEM.PASCAL directly from the GROM chips it's stored in) you can change whatever you like in the part of the operating system, which is mainly written in Pascal. This is of course not really feasible without access to the source code, but if you do have that knowledge it's technically easy. Looking at how short the code to enter and exit bitmap mode, a mode not at all planned for in the p-system designers, really is, it's pretty amazing that you can make such a significant change in the memory layout and still return to Pascal level with the bitmap mode active. We aren't talking about something that will live only as long as your assembly program is running. You can continue on Pascal level and do virtually everything except using the normal screen related IO routines, which is very reasonable.
  23. I've not published my return from bitmap yet in this thread. I can do so. Thus you can compare. But the entry into bitmap implies changing every VDP register, I think, so it makes sense they all need to be restored.
  24. As long as you have working batteries in the calculator, it will keep the memory alive. You may be able to change them without losing memory, even in the module, if you do it quickly. I've not opened my RAM module, so I don't know for sure what happens. But there's always a sharp knife and crazy glue. The battery is probably welded, not soldered. Then the welded connectors are soldered to the PCB. I just realized I've never replaced the battery in my RAM module. But since I keep it in the calculator all the time (it's the only module I have for it), I would probably not notice if it dies.
×
×
  • Create New...