Welcome, Guest. Please login or register.

Author Topic: Deluxe Paint 1 source code released  (Read 16689 times)

Description:

0 Members and 1 Guest are viewing this topic.

Offline bloodline

  • Master Sock Abuser
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 12113
    • Show only replies by bloodline
    • http://www.troubled-mind.com
Re: Deluxe Paint 1 source code released
« Reply #14 on: July 24, 2015, 12:18:19 PM »
Fascinating! Many thranks for looking the code over!

Offline Thorham

  • Hero Member
  • *****
  • Join Date: Oct 2009
  • Posts: 1149
    • Show only replies by Thorham
Re: Deluxe Paint 1 source code released
« Reply #15 on: July 24, 2015, 01:25:13 PM »
Quote from: Thomas Richter;793025
The program does not sit there to give you a drawing program on the Amiga. If you want a decent one, there is PPaint.
Or Brilliance 2. Allows you to load images that don't fit in chipmem. It basically only allocates chipmem for the visible part of the screen.
 

guest11527

  • Guest
Re: Deluxe Paint 1 source code released
« Reply #16 on: July 24, 2015, 01:39:45 PM »
Quote from: olsen;793034
From what I learned by looking over the source code, the need to use assembly language was not acute because "Deluxe Paint" could harness the Blitter. It even hardly mattered that the 'C' compiler used in 1985/1986 was not an optimizing compiler. Most of the work done with "Deluxe Paint" is driven by user interaction, which is slow...
It's not that assembler is the answer to all programming problems either. Indeed, if C is fast enough, use it.  In this particular case, though, the flood fill is not the flood fill from graphics, but a custom implementation, and that could have taken advantage of assembler. But it was probably not worth it. Same for the circle drawer (which is the nice conic section Bresenham algorithm, though with a couple of "issues" for small circles. It's not so easy to get this right.)  
Quote from: olsen;793034
The Macintosh applications did not have a co-processor which would have helped here, hence the need to use (presumably hand-optimized) assembly language. Also, the Macintosh Pascal and 'C' compilers were just as poor at producing optimized code as the Lattice 'C' compiler used for "Deluxe Paint" at the time.
But then, most programs on the Mac build on top of the Quickdraw calls, so they could have been in Pascal as well (Pascal was the prime language for the Mac, C came later). Mac Paint is really just QuickDraw in all its excellence and not much else, but that's an entirely different beast in first place, being one of the first (or the first?) vector graphics program. I don't know which language it was written in, but my guess is Pascal. (As most high-level stuff in the early Mac models).  
Quote from: olsen;793034
That said, the differences in these approaches even extends to the respective operating system. For example, the Amiga "graphics.library" is built around the co-processors (Denise, Agnus) and is written mostly in 'C' with significant portions rewritten or specifically written in assembly language. The original Macintosh QuickDraw by comparison was written entirely in assembly language, with no higher level language (Pascal) involved.

True. Though, on the plus side, QuickDraw kept a lot more care on proper coordinate computation and raster coordinates, much better than Amiga ever did. It was designed for something entirely different, namely point-precise layout for professional graphics production. Actually, the quickdraw line drawer is not the average Bresenham algorithm you find in the blitter hardware (and in software), but a fixed-point linear algebra based version, and it can do more than just "thin lines" graphics and the blitter does.
 

Offline olsen

Re: Deluxe Paint 1 source code released
« Reply #17 on: July 24, 2015, 02:42:23 PM »
Quote from: Thomas Richter;793043
It's not that assembler is the answer to all programming problems either. Indeed, if C is fast enough, use it.  In this particular case, though, the flood fill is not the flood fill from graphics, but a custom implementation, and that could have taken advantage of assembler. But it was probably not worth it.
At this resolution (640x400 pixels maximum; PAL resolutions would have to wait until "Deluxe Paint II" became available) it probably would not have mattered much. Comparing the "Deluxe Paint" flood fill code with the "graphics.library" V34 implementation (which seems to have been written in 1985), the "Deluxe Paint" implementation appears to be more robust and far less complex.

The "graphics.library" implementation is written almost entirely in 'C' with just one down-coded assembly language subroutine involved. If I understand correctly what it does, it builds a mask bitmap one pixel at a time, observing clipping rules which come about because of bitmap boundaries. That mask bitmap then goes through the elementary code underlying RectFill(), allowing for the area to be filled in a single colour or to use a fill pattern instead. The "Deluxe Paint" implementation neatly limits itself to the task at hand and does not have to shoulder the entire work which the operating system would have to perform.

Funny thing, "Deluxe Paint" has a call to the operating system flood fill function (called "Flood()") commented out in favour of its own implementation. Some part of "Deluxe Paint" (this should be easier to trace from within a debugger) actually still calls Flood(), though. Why do it that way? I am speculating: because the "graphics.library" flood fill code is of the same age as "Deluxe Paint", it might not have worked well enough at the time to let "Deluxe Paint" use it at all times. The "Deluxe Paint"-specific flood fill code may have been a workaround.

Quote
Same for the circle drawer (which is the nice conic section Bresenham algorithm, though with a couple of "issues" for small circles. It's not so easy to get this right.)   But then, most programs on the Mac build on top of the Quickdraw calls, so they could have been in Pascal as well (Pascal was the prime language for the Mac, C came later). Mac Paint is really just QuickDraw in all its excellence and not much else, but that's an entirely different beast in first place, being one of the first (or the first?) vector graphics program. I don't know which language it was written in, but my guess is Pascal. (As most high-level stuff in the early Mac models).
MacPaint is written almost entirely in Pascal, with many utility functions written in assembly language. Strangely, the utility functions are not all graphics-related but provide interfaces to operating system functions, too. This is an odd mix.

Quote

True. Though, on the plus side, QuickDraw kept a lot more care on proper coordinate computation and raster coordinates, much better than Amiga ever did. It was designed for something entirely different, namely point-precise layout for professional graphics production. Actually, the quickdraw line drawer is not the average Bresenham algorithm you find in the blitter hardware (and in software), but a fixed-point linear algebra based version, and it can do more than just "thin lines" graphics and the blitter does.
Yes, QuickDraw was designed with generalized 2D rendering in mind with specific rules governing how the rasterization would paint bitmap pixels. The original QuickDraw even included functionality for colour rendering which was replaced in later operating system versions when this design did not prove effective. If you look at the design, it fits very well with how PostScript accomplishes the same thing.

By comparison the Amiga model was decidedly about bitmap pixels in planar bitmaps, not points or vectors.
 

guest11527

  • Guest
Re: Deluxe Paint 1 source code released
« Reply #18 on: July 24, 2015, 06:42:04 PM »
Quote from: olsen;793046
At this resolution (640x400 pixels maximum; PAL resolutions would have to wait until "Deluxe Paint II" became available) it probably would not have mattered much. Comparing the "Deluxe Paint" flood fill code with the "graphics.library" V34 implementation (which seems to have been written in 1985), the "Deluxe Paint" implementation appears to be more robust and far less complex.

The "graphics.library" implementation is written almost entirely in 'C' with just one down-coded assembly language subroutine involved. If I understand correctly what it does, it builds a mask bitmap one pixel at a time, observing clipping rules which come about because of bitmap boundaries. That mask bitmap then goes through the elementary code underlying RectFill(), allowing for the area to be filled in a single colour or to use a fill pattern instead. The "Deluxe Paint" implementation neatly limits itself to the task at hand and does not have to shoulder the entire work which the operating system would have to perform.

Whether early flood() implementations had bugs I do not know, but the reason for the complexity in the graphics implementation is easily explained: You can setup the RastPort such that the flood-fill fills the area with a pattern (or invert it) instead of only a solid color. You cannot do that robustly without an extra plane, so graphics first computes the area to be filled by marking the bits to be filled in the TmpRas, and then runs through a BltTemplate() on the TmpRas to fill the selected areas with a pattern.

IIRC, DPaint I did not offer such a function, and for a simple solid color flood fill, you do not need the extra plane. Plus, it costs extra memory. If you only had 256K in the base Amiga model, you'd better try to get away with as little memory as possible and avoid the extra plane.

One of the strange things about graphics is that you had to allocate the TmpRas yourself, which makes the whole construction somewhat fragil. Probably the design idea was to make graphics entirely static where graphics resources are only allocated and released by the user, and graphics only "fills the structures". This required a lot of internal structures to be documented, which was a rather bad idea because it made it almost impossible to extend them. And caused such weird decisions to store extended graphics mode information in the colormap (!), the only structure not documented...
 

Offline olsen

Re: Deluxe Paint 1 source code released
« Reply #19 on: July 24, 2015, 07:25:06 PM »
Quote from: olsen;792972
I venture that "Deluxe Paint" could be ported to a contemporary AmigaOS, if one finds a solution for the dependencies on the Blitter hardware. It could be done :)

Replying to myself: I can now build "Deluxe Paint" with minimal changes using SAS/C and the resulting program actually works :)

The one thing which instantly crashes it, however, is loading the fonts. I have to investigate that...

The source code is missing a 32 bit fixed point multiplication function called FMULT() which should be defined in "lfmult.c", but isn't. It was easy to find a suitable implementation, though.

The airbrush operation runs as fast as it possibly can, which currently renders it somewhat useless, more like dumping a bucket of paint onto the canvas ;)

Brush transformations (bending, shearing, rotation) work. These operations all build upon the fixed point multiplication code.
« Last Edit: July 24, 2015, 07:33:47 PM by olsen »
 

Offline kamelito

Re: Deluxe Paint 1 source code released
« Reply #20 on: July 24, 2015, 10:09:07 PM »
@Olsen,
I think that you can post the makefile this is not forbidden AFAIK.
Can you also ask Hypérion to release the 1.0 AmigaOS too ?

Kamelito
 

Offline Trev

  • Zero
  • Hero Member
  • *****
  • Join Date: May 2003
  • Posts: 1550
  • Country: 00
    • Show only replies by Trev
Re: Deluxe Paint 1 source code released
« Reply #21 on: July 24, 2015, 11:58:32 PM »
Quote from: kamelito;793069
Can you also ask Hypérion to release the 1.0 AmigaOS too?

That would be cool, but you can learn just as much by reading the Wikipedia page on linked lists. ;-) And message queues. But it's more fun to tease about lists.
 

Offline olsen

Re: Deluxe Paint 1 source code released
« Reply #22 on: July 25, 2015, 08:37:54 AM »
Quote from: Thomas Richter;793058
Whether early flood() implementations had bugs I do not know, but the reason for the complexity in the graphics implementation is easily explained: You can setup the RastPort such that the flood-fill fills the area with a pattern (or invert it) instead of only a solid color. You cannot do that robustly without an extra plane, so graphics first computes the area to be filled by marking the bits to be filled in the TmpRas, and then runs through a BltTemplate() on the TmpRas to fill the selected areas with a pattern.

IIRC, DPaint I did not offer such a function, and for a simple solid color flood fill, you do not need the extra plane. Plus, it costs extra memory. If you only had 256K in the base Amiga model, you'd better try to get away with as little memory as possible and avoid the extra plane.

"Deluxe Paint" makes good use of TmpRas structures which it allocates as needed, but not in the flood fill operation. This is the first program which I have seen to use a TmpRas as the final parameter to BlitBitMap().

The flood fill operation fills the area line by line, after first figuring out which pixels should be affected on the current line. It then actually draws a line between these points using its own pattern fill function, which is equivalent to RectFill() but which directly uses the Blitter hardware.

Memory issues are a good explanation why "Deluxe Paint" uses this flood fill approach. Except for managing the fill span stack this implementation has minimal memory requirements.
 

Offline olsen

Re: Deluxe Paint 1 source code released
« Reply #23 on: July 25, 2015, 09:00:45 AM »
Quote from: kamelito;793069
@Olsen,
I think that you can post the makefile this is not forbidden AFAIK.
The makefile (or rather "smakefile") is part of the task, but a few things needed changing first.

Here is what I did:

- Changed all file names to all-lowercase letters.
- Replaced all by and removed all EOF characters.
- Corrected all '#include <..>' and '#include ".."' path names.
- Replaced "#if useTimer" in "reqcom.c" by "#ifdef useTimer", which corrects what appears to be a typo.
- Replaced "stscmp()" in "fnreq.c" by "strcmp()" which corrects what seems to be a bit flip. There is no function called "stscmp()" in the "Deluxe Paint" code, or for that matter the Lattice 'C' runtime library.
- Reconstructed the missing "lfmult.c" file which should contain the LFMULT() function. I borrowed the fixed point multiplication code from libfixmath (https://code.google.com/p/libfixmath/).
- All the header files in the "iff" drawer were missing. I copied the "iff" drawer from the original "EA IFF 85" source code, which matched perfectly.
- Tagged all built-in bitmap and sprite data as "__chip" for SAS/C, which has the effect of placing that data in chip memory.
- Replaced "BootIt()" in "prism.c" with '#define BootIt() ((void)0)'

A working "smakefile" looks like this, assuming that all the code is stored in a drawer named "prism" -- the 'idir="/prism"' will not work otherwise:

Code: [Select]
CFLAGS = params=stack data=far nostkchk idir=&quot;/prism&quot; cpu=any
LFLAGS = smallcode smalldata noicons

OBJS = \
   actbms.o airbrush.o bend.o bitmaps.o blend.o blitops.o \
   bmob.o box.o brxform.o ccycle.o chproc.o \
   clip.o conic.o ctrpan.o curbrush.o cursbms.o \
   cursor.o dalloc.o dispnum.o distance.o dopalett.o dosymreq.o \
   dotbms.o dpiff.o dpinit.o dpinit2.o dpio.o fill.o \
   fnbms.o fnreq.o fontinit.o geom.o hook.o hsv.o iffr.o \
   iffw.o ilbmr.o ilbmw.o initovs.o initread.o initwrit.o \
   keyjunk.o lfmult.o magbits.o magops.o magwin.o mainmag.o \
   makeicon.o maskblit.o menu.o message.o modes.o mousebut.o \
   packerf.o paintw.o palbms.o palette.o pane.o penmenu.o \
   pgraph.o polyf.o polyh.o print.o prism.o psym.o \
   random.o remap.o reqcom.o rot90.o rotate.o shade.o \
   shear.o spare.o stretch.o symreq.o text.o timer.o \
   unpacker.o

LIBS = lib:scnb.lib lib:amiga.lib lib:debug.lib

prism: $(OBJS)
   slink lib:c.o $(OBJS) to $@ lib $(LIBS) $(LFLAGS)
This builds a working "prism" program with SAS/C and V40 header files, although you will have to put up with some 2600 compiler warnings owing to the age and dialect in which the code was written ;)

If you want to build the code with a different compiler, you will need to replace the Lattice 'C' functions setmem() and movmem() as follows:
Code: [Select]
#define setmem(to,n,c) memset(to,c,n)
#define movmem(from,to,n) memmove(to,from,n)
Edited to add: I just discovered that "Deluxe Paint" also uses the Lattice 'C' function "stcu_d()", which however is not exactly the same as the variant which part of the SAS/C runtime library. This version has three parameters and works something like this:
Code: [Select]
int stcu_d(char *out,unsigned uivalue,size_t max_size) { return snprintf(out,maxsize,"%u",uivalue); }Mind you, SAS/C has no snprintf() function, it's just that the third parameter controls how many characters including the trailing NUL byte are written to the output buffer.


Quote
Can you also ask Hypérion to release the 1.0 AmigaOS too ?
I can ask, but untangling the Kickstart/Workbench 1.0 code from what was handed down is (in my opinion) not possible.

These operating system release versions were not clearly marked as being "v27", "1.0", "1.1", "1.2", etc. The change history does reach back to 1985 (RCS -> CVS -> SVN), but prior to that either SCCS was used or no SCM tool at all.

Meaning that the oldest coherent operating system source code is "1.2.1", which bears version number 34, its product name being "Kickstart 1.3".

In my opinion a more attainable goal would be in publishing the V34 "exec" and "intuition" source code (V34 is almost identical to V33), which both represent significant historic achievements, and which cover the whole span of Amiga operating system software from low complexity to high complexity. Both are very-well written and well-designed.
« Last Edit: July 26, 2015, 08:46:36 AM by olsen »
 

Offline kamelito

Re: Deluxe Paint 1 source code released
« Reply #24 on: July 25, 2015, 10:05:12 AM »
@Olsen
Thanks I'll try that.
Kamelito
 

Offline YasuTopic starter

  • Sr. Member
  • ****
  • Join Date: Mar 2012
  • Posts: 413
    • Show only replies by Yasu
Re: Deluxe Paint 1 source code released
« Reply #25 on: July 25, 2015, 04:08:04 PM »
Doesn't Cloanto own 1.0 to 3.1 since 2012?
 

guest11527

  • Guest
Re: Deluxe Paint 1 source code released
« Reply #26 on: July 25, 2015, 04:38:12 PM »
Quote from: Yasu;793108
Doesn't Cloanto own 1.0 to 3.1 since 2012?

To my very knowledge, they own a license that allows them to redistribute the kickstart and workbench disks and the ROM images. That's not the same as a license on the source code.

Hyperion has a license (and won a case for in in court) to use the 3.1 sources for continuous Os development (as in Os 4 and beyond). Whether they own the source code and can provide licenses on them for anything else (and for publication in particular) is another question that has not been brought to court yet. However, Hyperion is probably your "best guess" as whom you might want to ask.
 

Offline Gilloo

  • Full Member
  • ***
  • Join Date: Apr 2006
  • Posts: 124
    • Show only replies by Gilloo
Re: Deluxe Paint 1 source code released
« Reply #27 on: July 28, 2015, 11:02:21 AM »
@olsen great ! I do the same with SASC6.0 and V51 includes

1) I wonder if the missing LFMULT function is not like that : (lfmult.c file)

typedef long LongFrac ;

LongFrac LFMULT(LongFrac a, LongFrac b)
{
  return (a * b) >> 16 ;
}

2) Don't forget that the original DPaint program is overlayed... so the makefile should contain the OVERLAY keyword, a # and stars somewhere ;)

3) to try the different resolutions, just launch prism with arguments
prism l => 320x200 (default)
prism m => 640x200
prism h => 640x400 (stack overflow when tracing big lines...)

enjoy this 30 years old stuff !
 

Offline olsen

Re: Deluxe Paint 1 source code released
« Reply #28 on: July 28, 2015, 11:53:14 AM »
Quote from: Gilloo;793193
@olsen great ! I do the same with SASC6.0 and V51 includes

1) I wonder if the missing LFMULT function is not like that : (lfmult.c file)

typedef long LongFrac ;

LongFrac LFMULT(LongFrac a, LongFrac b)
{
  return (a * b) >> 16 ;
}
No, this is not sufficient. You can multiply two 16 bit numbers and the product will fit into a 32 number. But the factors are fixed point numbers, each of which consists of more than 16 bits of information. You are effectively multiplying two 32 bit numbers, which will yield a 64 bit product.

For example, let's say we want to multiply 4 and 16. In fixed point format 4.0 = 4 * 65536, 16.0 = 16 * 65536. Multiply these factors and the result is 274,877,906,944, which is larger than the range of an unsigned 32 bit integer (= 4,294,967,295) permits.

You need a more complex function to handle this properly. The fact that "Deluxe Paint" is broken up into so many small code fragments, each of which implement a complete self-contained set of functions, suggests that "lfmult.c" must be a self-contained code file.

If it were as simple as implementing it as a single line function, then I would have expected it to be in a macro definition in "prism.h", and not in a separate 'C' source file.

Here is a nicer version, adapted from Code found at https://code.google.com/p/libfixmath/:
Code: [Select]

#include <exec/types.h>

typedef LONG LongFrac;

LongFrac LFMULT(x,y) LongFrac x,y; {
/* Each argument is divided to 16-bit parts.
**          AB
**      *  CD
** -----------
**          BD  16 * 16 -> 32 bit products
**         CB
**         AD
**        AC
**       |----| 64 bit product
*/
LONG A = (x >> 16), C = (y >> 16);
ULONG B = (x & 0xFFFF), D = (y & 0xFFFF);

LONG AC = A*C;
LONG AD_CB = A*D + C*B;
ULONG BD = B*D;

LONG product_hi = AC + (AD_CB >> 16);

/* Handle carry from lower 32 bits to upper part of result. */
ULONG ad_cb_temp = AD_CB << 16;
ULONG product_lo = BD + ad_cb_temp;
if (product_lo < BD)
product_hi++;

return (LongFrac)((product_hi << 16) | (product_lo >> 16));
}


Quote

2) Don't forget that the original DPaint program is overlayed... so the makefile should contain the OVERLAY keyword, a # and stars somewhere ;)
I used overlays before, when I did not have much of a choice. They are an ugly solution to an ugly problem. Everything becomes harder when using overlays, including debugging. No, I'm not going to foist overlays on anybody.

Quote

3) to try the different resolutions, just launch prism with arguments
prism l => 320x200 (default)
prism m => 640x200
prism h => 640x400 (stack overflow when tracing big lines...)
There's more. The second parameter allows you to set the screen depth. The command line parameters are documented in the reference card, which is available on the same http://computerhistory.org page as the "Deluxe Paint" source code.
 

Offline woof

  • Jr. Member
  • **
  • Join Date: Feb 2003
  • Posts: 94
    • Show only replies by woof
    • http://uae.is.free.fr
Re: Deluxe Paint 1 source code released
« Reply #29 from previous page: July 28, 2015, 12:06:09 PM »
Hello
@Olsen
Perhaps you can suggest the Computer History Museum to host also your modified sources: It will pedagogically show how little modifications was needed to make  up to date this well written old source

Alain Thellier