Posts Tagged ‘borland turbo pascal

06
Apr
15

Creating a benchmark: Part 4

Last time I used the  in-line assembler to improve the speed of the sprite blitting functions with lots of success. Other functions such as line drawing however still suffered speed issues on systems with out a built-in FPU such as the 386sx.

The reason for the slow line drawing was simple, I had used a simple slope based algorithm that used floating point. On a system with a FPU this was quite fast, about as fast as anything else, but obviously it wasn’t going to cut the mustard when it came to the old processors I’m targeting. So I decided to give fixed point arithmetic a go.

Fixed point numbers are a variation on basic integers, using some of the bits to represent the fractional part. You can then use integer instructions to do some basic math that involves fractions. This is much faster for processors lacking hardware floating point support. Check out more details of fixed point here or at Wikipedia. It’s a very common technique for embedded systems, but was also used in games such as Doom for speed.

I however ran into a problem. Because the integer in turbo pascal is 16bits I didn’t have enough bits for addressing all the pixels and have enough precision to for the fractional part of the slope. For the integer part I needed to have a range of 0-319, requiring 9 bits unsigned. The fractional part was thus left with 7 bits, with the smallest representable fraction being 1/128th. The smallest conceivable slope in 320×200 is 1/320 which obviously is much smaller. I could have switched to using longints or storing the fractional part separately but this would have added extra overhead that would make line drawing slower.

I set the line drawing problem aside for the moment to look for a quick circle drawing algorithm. Something I hadn’t implemented yet. The SWAG archive came up with suitable options, but also had some algorithms for line drawing. In particular the Bresenham line drawing algorithm.

Not having coded my own low level line drawing routines before I hadn’t heard of it, but it uses all integer math in a clever way to produce the correct slope. I modified the algorithm I found to reduce the amount of calculations for the screen address when plotting points in the line. The resulting code was slightly faster than previous line drawing code, but not overwhelmingly so.

Returning to implementing circle drawing, the algorithms I found unfortunately used floating point math. They all use the basic formula for a circle, x^2 + y^2 = r^2, thus requiring the use of a square root function to calculate the co-ordinates. Unfortunately it is one of the more expensive floating point operations.

One algorithm I looked at used the square root function, but rounded it to an integer immediately. This got me thinking, if I could implement an approximation of square root using integer arithmetic I could draw circles quickly. So after a bit of research I wrote exactly that. Code follows.

function intSqrt(num: word):word;
var
   xo,xn:word;
begin
     {we're using Newtons method for approximating the sqrt}
     if (num=0) then
     begin
         intSqrt:=0;
         exit;
     end;
     xo := 0;
     xn := num;
     if xn=0 then xn:=1;
     while (abs(xo-xn) > 1) do
     begin
          xo := xn;
          xn := (xo + (num div xo)) shr 1;
     end;
     intSqrt := xn;
end;

As stated in the comment, I’ve used Newton’s method for calculating the root, mostly because it’s a simple method I know. I did a little testing, and it turns out this returns pretty much the same result as rounding the built-in sqrt function that uses floating point, only quicker. Once I finished the circle drawing code it drew around 36% more circles in the same time as the BGI code. That’s not bad, but I think there may be more room for optimisation here.

Next time I hope to have optimised the circle routine, and I’ll test the code on some hardware to see how all the different libraries compare to each other on different platforms.

06
Jan
13

Memory Allocation – Heap and Stack

A question I recently saw online was about how memory is allocated and used within the Java programming language. There was a little confusion about what the heap and stack are. Both the stack and heap are common to many languages such as pascal, C, and many more.

Stack space is a special construct in hardware used for storing temporary variables, return values and return addresses for functions. Most languages use the stack to store any local variables that will fall out of scope when a procedure (or method in OO language) finishes or returns. Java has the same style of stack construct for the virtual machine used for the same purpose. The Java language will however only store primitives (char, int, byte etc) and references to objects on the stack.

Heap space is a software construct and will be different depending on the language. It’s used for dynamically allocating memory usually for longer term storage of larger chunks of data. In languages like pascal and C, data on the heap is usually handled and referred to by a primitive called pointers. A pointer basically holds the memory location of whatever it is pointing to, they can be difficult to program.

Java doesn’t have a pointer primitive so it uses a different mechanism. Instead of having pointers, Java has references which are subtly different. A reference is different in that the memory location information is not available to the programmer where as it is with a pointer. This means you can’t do pointer arithmetic or try to access memory directly. The intent of this is to protect programmers from themselves and to make Java more secure. Java references are used for storing objects and arrays on the heap. The garbage collector keeps track of how many references are pointing to each item in the heap, and disposes of items that are no longer in use.

Older languages that target DOS and the older systems will allocate global variables to what is called the data segment. DOS and earlier processors used segmented memory addressing and in part comes from the 8086 machines assembly language. There are three types of segment, code, stack, and data. Code segments are for storing the machine code for the program and are pretty straight forward, there can be many of them but on DOS and 8086 machines the maximum size of each is 64Kb. The stack segment is singular and unique and is for the processor stack, there can be only one again with a maximum size of 64Kb. The data segment is as I said for statically defined data, and each segment is 64K in size. Borland Turbo Pascal only allowed one data segment and I suspect most other languages did the same. The heap would be outside the segments and would use the remaining memory, it was typically managed by a system library that was a part of the language used.

Java is fairly similar to native languages but does not use a segmented model, as many modern languages don’t. This is partly because hardware and software has changed in such a way as they are no longer needed.

03
Jul
12

Using the inline assembler in Pascal

I’ve been asked recently how you go about adding assembly instructions in old pascal program using the compilers inline facility. Assembly is important if you want to write your own hardware handling routines, or need to do something as fast as possible. It can be difficult writing assembly code, but by and large it is actually a fairly simple language. With the old Borland Turbo Pascal 6 and 7 you did this using one of a few different structures.

You could use the asm directive to write assembly in a code block of its own, and this is my preferred way. The only issue is you are limited to using 286 instructions as these are the only ones that turbo pascal ever supported. So if you required 386 instructions or higher you were out of luck!

Here is some sample code I have used. It could be more efficient, but as a sample it suffices.

procedure copymem16(srcseg,srcofs,desseg,desofs,size:word);
var c,of1,of2:word;
begin
 c:=0;
 while c< size do
 begin
    of1:=c+ srcofs;
    of2:=c+ desofs;
    asm
     push es
     push di
     mov ax,srcseg
     mov es,ax
     mov di,of1
     mov bx,[es:di]
     mov ax,desseg
     mov es,ax
     mov di,of2
     mov [es:di],bx
     pop di
     pop es
    end;
   c:=c+2;
 end;
end;

procedure copymem(source,dest:pointer;size:word);
var c,of1,of2,srcseg,srcofs,desseg,desofs:word;
begin
 srcseg:= seg(source^);
 srcofs:= ofs(source^);
 desseg:= seg(dest^);
 desofs:= ofs(dest^);
 if (size mod 2) = 0 then
  begin
   copymem16(srcseg,srcofs,desseg,desofs,size);
   exit;
  end;
 for c:=0 to (size-1) do
  begin
    of1:=c+ srcofs;
    of2:=c+ desofs;
    asm
     push es
     push di
     mov ax,srcseg
     mov es,ax
     mov di,of1
     mov bh,[es:di]
     mov ax,desseg
     mov es,ax
     mov di,of2
     mov [es:di],bh
     pop di
     pop es
    end;
  end;
end;

There are some other ways of adding assembler if you need them.

You can use the inline statement to add bytes directly into your executable, but this means you need to actually write the code directly in hex instead of using the standard mnemonics for instructions. This makes this method very cumbersome, but good if you only want to add one or two instructions.

You can also link in obj files that you have made with other assembler tools. There are a lot of pitfalls to this method however. You need to convert the obj files into binary format for including in the executable, and they must be self-contained and use a small memory model. That is one segment for code, and one segment for data at the most. The stack space used by the rest of the program would be shared with the imported code. To call any of the code you have to know and work out the call address yourself (which will depend on where in ram you stored it!) in order to be able to use it. It can make having more than one procedure or function very difficult, especially if you make any changes to your code. If you want the assembler routines to be callable like pascal ones you have to be careful to use the pascal call model, and to not clobber any local variables in the stack. Finally you can’t access Pascal global variable or functions easily within your assembler code. You will generally have to push pointers on the stack (as a method of parameter passing) to be able to find out where the data is.

There are a couple of advantages to this last method. The main one being you can write using whatever assembler you see fit even using instructions for a processor Pascal doesn’t support. Also if you do it correctly you can load your code dynamically and throw it out of memory when you are done with it. This is how the BGI graphics drivers work, and a simplified version of how the overlay system works.

However if you don’t need better than 286 instructions (or want your product to support the 286) you might as well use the asm blocks as this allows you to have much more flexibility in what you can do.

29
May
12

Pong Clone in Pascal

One of the every first graphical programs I wrote in pascal was a very basic pong clone. All the graphics were done using the Borland graphics library using vector style graphics. So you will need the bgi and chr files to build and run this program. Again I had to adjust the timing for this program as the original timing system would have only worked on the old 386 I developed this on! You’ll notice that the program made use of the goto statement in pascal which is generally frowned upon. This is because it is one of my earlier pascal programs, and I still had many bad habits from writing many programs in BASIC.

Continue reading ‘Pong Clone in Pascal’

24
May
12

Num Drop Pascal source code

This is a pascal version of one of the very first gwbasic games I ever made. I’ve made improvements over the original but it is still pretty true to what it was. It should be pretty simple to compile as it only requires the dos and crt units to function. Source code follows…

Continue reading ‘Num Drop Pascal source code’

21
May
12

Turbo Pascal for DOS

Turbo Pascal 6 about Screen

Turbo Pascal 6 about Screen

When I was a teenager I mostly wrote programs using gwbasic or qbasic. Around the time when I was about 15 or 16, my computer studies teacher gave me a copy of Borland turbo pascal 6 to try out and learn. It was a much different language to BASIC, and I unfortunately didn’t have any books to help me learn about it. Fortunately my teacher gave me a couple of sample programs so I could learn the structure and basic syntax of the language. I also compiled and inspected the code samples that came with it, and found them informative. However with out more good examples and information about hardware there were many tasks that were difficult.

One of  the main differences in pascal is the way that variables and functions are declared. Unlike C and other languages, variables can not be declared in the middle of a piece of code. There is a separate declaration portion to define them and their data types before they are used any where. This is good in some ways as it forces you to think about what you are going to need for your program, function or unit.

One of the very new things that I learned about that is very common, but not available in BASIC, was pointers. For the uninitiated a pointer is basically a number that “points” to a memory location in the computer. They are useful for dynamically allocating memory or dealing with large chunks of data. They are necessary in pascal to avoid filling up your data segment. Unfortunately they are also one of the easier things to get wrong. I avoided them when I first started writing in pascal as I had no knowledge about how they were used. Also I had very little need as my programs typically did not fill the data segment, but as the programs grew and I started using bit-mapped graphics, they became necessary.

A Open Program

An Open Program

Graphics and sound were also a very big change for me. Graphics was through a unit (library) called graph which utilised something called BGI (the borland graphics interface). Unfortunately I couldn’t get it to support the graphics modes that I was after at the time (320x200x256), as there was no BGI driver available for it in the language. Bit-mapped graphics also required that I used what was unfamiliar; pointers. So for quite a while graphics were right out of the question until I over came these hurdles later.

Later when I went to university I started to solve these problems, I found BGI drivers that supported VGA and VESA graphics modes, and learned the proper use of pointers for storing data as well as doing graphics. I later started writing in-line assembler into my programs to create my own hardware interface routines, the one I use the most being one I wrote for the adlib sound card.

Bob’s Fury

Bob's Fury Title Screen

Bob’s Fury Title Screen

Bob’s fury was one of the first projects I started back in 1999, it is a port of the original game that I wrote in QBasic. Arriving at university I had my first access to the internet and found solutions that had previously stopped me porting this to pascal. I found myself some BGI drivers that allowed the graphics mode I was after but also a higher resolution mode. I also found a nice pascal library that implemented the BASIC play statement. This made porting the sound from the original much easier.

Bob's Fury gameplay

Bob’s Fury Gameplay

I have continued to work on this game to this day, and it has changed a lot since the early days. I’ve added many features to the engine that weren’t possible in QBasic, and created more content for it. More recently I have been adding some of my own hardware interfaces, such as one for the keyboard and one for adlib sound cards, although I am yet to make some decent music for it, or the utility to create it. I’ve actually completed most of the game, but need to now create some new original levels for it as well as some story.

Romulus

Romulus in action

Romulus in action

My brothers and myself occasionally play a game called VGA planets. One of the enduring problems for us was that it would take too long with us playing so many of the human players, and there have not been any reasonably good AI players who also play as the shareware player. I know it’s sorta strange we liked playing the restricted version, but for us it introduced strategy elements that are not present in the registered version. So to help solve the problem I started to implement my own AI that would be better than many of the basic AI utilities out there.

I implemented it to behave the same way a player would as best as possible. The player reads result files and outputs turn files instead of modifying the host files directly like many other AI programs do. In this way Romulus cannot cheat, much the same way that spacelord doesn’t cheat. My focus has been to make the player reasonable good at taking advantage of the various abilities, and to be able to respond to various messages and threats such as ion storms. I’ve even attempted to implement a basic system of diplomacy which allows the player to select who it wants to wage war on.

It still needs quite a bit of work on it before I consider it complete. There are also a few segments I need to redesign and implement as the player doesn’t always do what I’d like it to. The main thing I need to do is to add more of the special abilities to the player.

Pascal Resources

There are many pascal resources around the web, but one of the best resources you can find for writing pascal on DOS is called the SWAG. Basically it is a collection of documentation, forum/BBS questions and answers, and code snippets sorted into different categories covering all the major aspects of programming in pascal. Information about programming the x86 hardware is some of the best and most useful content, especially if you are programming for DOS. I would highly recommend getting it if you can.

Pascal isn’t dead

There is a nice open source project called free pascal that implements a full pascal language including object-oriented extensions. Fortunately it is mostly syntax compatible with your old Borland pascal version 6 and 7. So you can use it to port old programs. I have noted it will also generate code for multiple platforms, including most of the operating systems and architectures that I am interested in. There is also a Delphi equivalent called Lazarus that will help you create new applications! The free pascal website is very useful, and has documentation to help you port your old programs and for the API.




Blogs I Follow

Enter your email address to follow this blog and receive notifications of new posts by email.


Mister G Kids

A daily comic about real stuff little kids say in school. By Matt Gajdoš

Random Battles: my life long level grind

completing every RPG, ever.

Gough's Tech Zone

Reversing the mindless enslavement of humans by technology.

Retrocosm's Vintage Computing, Tech & Scale RC Blog

Random mutterings on retro computing, old technology, some new, plus radio controlled scale modelling.

ancientelectronics

retro computing and gaming plus a little more

Retrocomputing with 90's SPARC

21st-Century computing, the hard way

lazygamereviews

MS-DOS game reviews, retro ramblings and more...