/***************************************************************************** * * ATARI.C * * from DKBTrace (c) 1990 David Buck * * This module implements the IBM-specific routines for DKBTrace. * * This software is freely distributable. The source and/or object code may be * copied or uploaded to communications services so long as this notice remains * at the top of each file. If any changes are made to the program, you must * clearly indicate in the documentation and in the programs startup message * who it was who made the changes. The documentation should also describe what * those changes were. This software may not be included in whole or in * part into any commercial package without the express written consent of the * author. It may, however, be included in other public domain or freely * distributed software so long as the proper credit for the software is given. * * This software is provided as is without any guarantees or warranty. Although * the author has attempted to find and correct any bugs in the software, he * is not responsible for any damage caused by the use of the software. The * author is under no obligation to provide service, corrections, or upgrades * to this package. * * Despite all the legal stuff above, if you do find bugs, I would like to hear * about them. Also, if you have any comments or questions, you may contact me * at the following address: * * David Buck * 22C Sonnet Cres. * Nepean Ontario * Canada, K2H 8W7 * * I can also be reached on the following bulleton boards: * * ATX (613) 526-4141 * OMX (613) 731-3419 * Mystic (613) 731-0088 or (613) 731-6698 * * Fidonet: 1:163/109.9 * Internet: David_Buck@Carleton.CA * The "You Can Call Me RAY" BBS (708) 358-5611 * * IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es: * * The "You Can Call Me RAY" BBS (708) 358-5611 * The Information Exchange BBS (708) 945-5575 * **************************************************************************** * * Adaptation au ST/TT par * * Gemini TT pour la r‚cup‚ration des sources et la premiere adaptation * Gemini TT + RedRackam pour l'adaptation au Lattice C et au Turbo C * ( detection et correction des bugs de la bibliotheque math‚matique du * coprocesseur 68882 ) * RedRackam pour le trac‚ en palette fixe et l'adaptation au Pure C * RedRackam + Oulan Bator ( utilisation de sa routine de calcul de palette * variable ) pour le trac‚ en palette variable optimis‚ et les options * d1,d2 et d3 * * version Atari ST/TT 1.26 du 17/04/1992 * ***************************************************************************/ /* Original IBM VGA "colour" output routines for MS/DOS by Aaron A. Collins. This will deliver approximate colorings using HSV values for the selection. The pallette map is divided into 4 parts - upper and lower half generated with full and half "value" (intensity), respectively. These halves are further halved by full and half saturation values of each range (pastels). There are three constant colors, black, white, and grey. They are used when the saturation is low enough that the hue becomes undefined, and which one is selected is based on a simple range map of "value". Usage of the pallette is accomplished by converting the requested color RGB into an HSV value. If the saturation is too low (< .25) then black, white or grey is selected. If there is enough saturation to consider looking at the hue, then the hue range of 1-63 is scaled into one of the 4 pallette quadrants based on its "value" and "saturation" characteristics. Further SVGA, MVGA mods by Aaron A. Collins: SVGA, MVGA assembler routines originally by John Bridges. VESA assembler routines from FRACTINT, by The Stone Soup Group AT&T VDC600 SVGA mods to DKB Trace 2.01 module IBM.C by John Gooding This file now represents the collective wisdom of the VGAKIT34 package, with support for all of the SVGA types known to mankind. Seriously, VGAKIT34 is an excellent technical reference for IBM programmers wishing to do any sort of SVGA video access, and it encompasses nearly all of the SVGA adapters in use today. It was written by John Bridges, a.k.a. CIS:73307,606, GENIE:J.BRIDGES. It was originally coded in IBM 80x86 assembler, and since DKBTrace is a completely "C"-based package, I have converted John's assembler routines all into "C". These may be a tad bit slower, but they should be compatible across a wide variety of 80x86/(S)VGA machines. Note if you have a regular cheapo VGA card like myself, included is "MODE13x" or MVGA (modified VGA) mode (some call it "tweaked", but I call it "Simulated SVGA"), which gives 360x480 on any reasonably register- compatible plain vanilla VGA card. This mode gives a good simulated 640 by 480 screen resolution. I did not implement all the neat hi-res modes of all the various SVGA adapters, if you select a trace size bigger than the program and/or card can handle (most likely 640x480), it is dynamically scaled to fit the available resolution, so you'll be able to see a rough approximation of an 800x600 trace even on any el-cheapo VGA card at 320x200 resolution. The VESA VGA mode was freely adapted from FRACTINT, whose GIF reading routines we are already using in DKBTrace. I hope my conversion of it works properly. There is still a reported problem with the EVEREX autodetect returning TRIDENT. In fact EVEREX uses a TRIDENT chip set, but apparently there is some difference in operation. There are cryptic diagnostic messages such as T0000, etc. printed as a result of the autodetection routines to help track down why the error is happening. If you are experiencing problems with EVEREX or TRIDENT, make note of the letter-4 digit code you are given. There is now an autodetect for VDC600 that I hope will work universally. A similar problem as the EVEREX exists, in that the VDC600 is detected as a PARADISE because it uses the PARADISE chip set. I am now looking for what I believe to be the model number in the BIOS ROM of the VDC600 to differentiate between the two. I hope this works with all VDC600's, as I only had one example to work from. Please send all bug reports to Aaron Collins at the "You Can Call Me RAY" BBS, the number is above in the header of this and the other DKB source files. */ #define _PURE_C_ #define DBL double #define PROMPTEXIT 8 #define ANTIALIAS 16 #define DEBUGGING 32 #define RGBSEPARATE 64 #define EXITENABLE 128 #define CONTINUE_TRACE 256 #define VERBOSE_FILE 512 #define ON_ERROR_WAIT_KEYBD_TO_QUIT 1024 #include #include #include #include #include #include #ifdef __TOS__ #include #include #else #include #include #endif #ifndef VGA_FALCON #include #endif /* avec la nouvelle version de PURE C (1.1), mode.h est inclus dans TOS.H et il n'est donc pas necessaire de definir */ /* a l'exeption de Vsetscreen (extension de setscreen) */ /* que je definis donc ici de toute facon */ #define VSetscreen(a,b,c,d) (int)xbios(5,a,b,c,d) extern unsigned int options; extern char DisplayFormat; /* #ifdef __TOS__ #define LineStyles LStyles #define FillStyles FStyles #endif */ #include /* definition du type de l'‚cran */ typedef enum { FALCON=1, MATRIX=2, AUTRES=0 } t_ecran; t_ecran ecran=AUTRES; void *inter; /* zone reservee pour stocker l'image */ int dim_x,dim_y; /* dimension en x et y de l'image totale */ int lastx=-1, lasty, lastline; /* Pixel / Line Caches */ int contrl[12]; /* vdi parameter arrays */ int intin[256]; int intout[128]; int ptsin[256]; int ptsout[128]; int work_in[11]; /* Input to GSX parameter array */ int work_out[57]; /* Output from GSX parameter array */ int phys_handle,handle,menu_acc,vdi_handle; int buffer[8]; size_t la_taille_ecran; int mode_in; int rez_in; int c_y; /* coordonnees en y ligne calculee */ int ap_id; int ap_id_dest; /* l'identification du programme destination */ char cookie_char[5]; FILE *res_abs; void *adr_ecran; typedef struct { int used; int x; int y; } coul_struct; int nb_cabs=0; int modecode; int old_mode; void *pb,*lb; long table_couleur[4096]; /* table dans laquelle est stock‚ le nombre d'occurence de chaque couleur */ int *ptr_ecran; /* adresse ou dkb range ses images en nb bits */ int *ptr_l1e; unsigned long *ptr_matrix; int len_ligne; void *inter; /* zone reservee pour stocker l'image */ int dim_x,dim_y; /* dimension en x et y de l'image totale */ int nb_plan; /* nombre de plan de bits */ int nb_bit_coul; /* calcul du nombre de bits par couleur */ int dec_droite; /* nombre de decalage vers la droite a effectuer */ char masque; /* masque a appliquer sur chaque couleur pour ne garder que les bits significatifs dans le choix de couleur courant */ int dec_red; /* decalage a gauche pour le rouge */ int dec_green; /* decalage a gauche de la composante verte */ double AspectRatio; /* Aspect ratio of a pixel on the screen*/ int MaxX, MaxY; /* The maximum resolution of the screen */ int MaxColors; /* The maximum # of colors available */ int ErrorCode; /* Reports any graphics errors */ int falcon; extern unsigned int Options; extern char DisplayFormat; /* prootype des fonction affichage appelees */ void affi_image(void); void open_vwork2(void); void affi_final(void); void display_finished2(void); /* ces deux routines sont necessaires pour un fonctionnement correct sous PC et latice C */ /*-------------------------------------------------------- PROCEDURE : get_cookie1 AUTEUR : M. Abramson DATE : 27/4/1992 DESCRIPTION: cette procedure renvoie le long mot associe au cookie pass‚ en parametre 1, et 0 si il n'y en a pas PARAMETRES: le mot a rechercher est dans la variable cookie_char RETURN : long : long mot associe au cookie MODIFICATIONS: AUTEUR : DATE : DESCRIPTION: --------------------------------------------------------*/ long get_cookie1(void) { const void ** ptr_cookie=(void **)0x5a0; /* adresse de base du cookie */ char *adr_first_cookie; char chaine_comp[5]; char *cookie_ident; long *cookie_val; int nb_cookie=0; adr_first_cookie=*ptr_cookie; /* recuperer le pointeur sur les cookies */ if (adr_first_cookie==0) return(0); cookie_ident=(char *)adr_first_cookie; cookie_val=(long *)((long)adr_first_cookie+4); while ((long *)*cookie_ident!=0) { nb_cookie++; sprintf(chaine_comp,"%4s",cookie_ident); chaine_comp[4]=0; if (strncmp(chaine_comp,cookie_char,4)==0) return(*cookie_val); cookie_ident+=8; cookie_val+=2; } return(-1); } /*-------------------------------------------------------- PROCEDURE : get_cookie AUTEUR : M. Abramson DATE : 27/4/1992 DESCRIPTION: cette procedure renvoie le long mot associe au cookie pass‚ en parametre 1, et 0 si il n'y en a pas PARAMETRES: arg1 : chaine a rechercher RETURN : long : long mot associe au cookie MODIFICATIONS: AUTEUR : DATE : DESCRIPTION: --------------------------------------------------------*/ long get_cookie(char *a) { sprintf(cookie_char,"%4s",a); return(Supexec(get_cookie1)); } void Wait_Keyboard_And_Quit(int q) { if (Options & ON_ERROR_WAIT_KEYBD_TO_QUIT) { printf ("\007\007"); /* long beep */ /* attendre que le clavier soit vide */ while (Crawio(0xFF)) Crawcin(); /* attendre une touche clavier */ Crawcin(); } exit(q); } void open_vwork(void) { int i; unsigned int tail_pal; long mch; int work_out2[57]; /* Output from GSX parameter array */ for (i=0;i<10;work_in[i++]=1); work_in[10]=2; v_opnvwk(work_in,&vdi_handle,work_out); mch=get_cookie("_MCH"); if (mch==0x30000L) { tail_pal=32767; falcon=1; ecran=FALCON; } else { tail_pal=work_out[39]; /* nombre de couleur dans la palette */ vq_extnd(vdi_handle,1,work_out2); if (work_out2[5]==0) /* si pas de look up table */ { if (work_out2[4]>=16) /* et si on a plus de 16 plans couleur */ ecran=MATRIX; } } if (ecran!=MATRIX) { nb_plan=log(tail_pal+1)/log(2); /* calcul du nombre de plan de bits */ nb_bit_coul=nb_plan/3; /* calcul du nombre de bits par couleur */ dec_droite=8-nb_bit_coul; /* nombre de decalage vers la droite a effectuer sur chaque index de couleur pour passer de 24 bits a x bits */ masque=(0xFF>>dec_droite)<=dim_x-1) lastx=-1; /* Translate RGB value to best of 256 pallete Colors (by HSV?) */ if (DisplayFormat!='0') /* si rendu max */ { /* on calcule la couleur sur le nombre de bits maximum de la palette */ /* 12 sur un STE/TT, 16 (15+1) sur un FALCON */ switch (ecran) { case FALCON: la_couleur=((Red&masque)<>dec_droite); *(ptr_l1e++)=la_couleur; break; case MATRIX: /* la couleur est sur 32 bits soit donc 2 acces */ /* en 16 bits */ coul_long=((size_t)Red<<16)+(Green<<8)+Blue; *(ptr_matrix++)=coul_long; break; default: la_couleur=((Red&masque)<>dec_droite); table_couleur[la_couleur]++; *(ptr_ecran++)=la_couleur; break; } if (x==dim_x-1) /* si on est en fin de ligne */ { switch (ecran) { case FALCON: ptr_ecran+=len_ligne; ptr_l1e=ptr_ecran; break; case MATRIX: ptr_ecran+=len_ligne; ptr_matrix=ptr_ecran; break; default: c_y=y; affi_image(); break; } } } } void display_finished () { FILE *RES; int i; long pile; void *buf_screen; if (!falcon) { affi_final(); } else { if (DisplayFormat=='1') { buf_screen=malloc(la_taille_ecran); if (buf_screen==0) { printf("erreur, plus de memoire\n"); Wait_Keyboard_And_Quit(-1); } VSetscreen( buf_screen, buf_screen, 3, modecode); memcpy(buf_screen, adr_ecran, la_taille_ecran); free(adr_ecran); /* liberer l'ecran de calcul */ adr_ecran=buf_screen; /* et pointer sur l'ecran physique */ } } if (DisplayFormat>'0') /* liberer les buffers memoire */ { if (Options & PROMPTEXIT) { printf ("\007\007"); /* long beep */ /* attendre que le clavier soit vide */ while (Crawio(0xFF)) Crawcin(); /* attendre une touche clavier */ Crawcin(); } } if (!falcon) { if (DisplayFormat>'0') /* liberer les buffers memoire */ { free(inter); } } else { /* si on avait change le mode, on retourne au mode initial */ if ((DisplayFormat=='1') || (DisplayFormat=='3')) { VSetscreen(lb, pb, 3, old_mode); } if (adr_ecran) { free((void *)adr_ecran); } } appl_exit(); /* fonction qui restaure la palette et liberant la memoire */ if (!falcon) { /* a supprimer dans la version 2 process */ display_finished2(); } } /***************************************************************/ void display_init(width, height) /* Set video to requested or best mode */ int width, height; { int type_mon; unsigned int u; int i; int xasp, yasp; /* Used to read the aspect ratio*/ unsigned long taille; long l, lt; char *ptr_buf; int big_screen; #define MASQUE 0x10F /* pour isoler les bits interessants */ /* les modes correspondant … un grand ecran */ #define BS1 COL80|VERTFLAG|BPS16 /*16 bits 80 col interlaced */ #define BS2 COL40|BPS16 /* 16 bits 40 col non entrelaces */ #define BS3 COL80|BPS8 /* 80 colonnes 8 bits non entrelace */ open_vwork(); ap_id=appl_init(); dim_x=width; dim_y=height; switch (ecran) { case FALCON: type_mon=mon_type(); if (type_mon==0) { fprintf(stderr,"d‚sol‚, affichage true color impossible\n sur moniteur N&B\n"); DisplayFormat='0'; }else { old_mode=Vsetmode(-1); type_mon=old_mode & VGA_FALCON; if (type_mon==VGA_FALCON) { len_ligne=320; /* vga */ /* on passe en 16 bits true color tout en conservant l'atat du flag pal */ modecode=BPS16|COL40|VGA_FALCON| (old_mode&112); }else { len_ligne=640; /* TV */ modecode=BPS16|COL80|TV|(old_mode&112)|VERTFLAG; } } if ((modecode & OVERSCAN)==OVERSCAN) { len_ligne*=1.2; } /* on recupere la taille de l'‚cran en fonction du modecode calcul‚ */ la_taille_ecran =VgetSize(modecode); if (DisplayFormat=='1') /* affichage final */ { adr_ecran=calloc(la_taille_ecran,1); if (adr_ecran==0) { fprintf(stderr,"d‚sol‚, plus assez de m‚moire pour calculer une image avec affichage"); DisplayFormat='0'; } ptr_l1e=ptr_ecran=adr_ecran; } else { if (DisplayFormat=='3') { /* on passe en true color */ /* on recupere les anciennes info ecran */ lb=Logbase(); pb=Physbase(); /* et on passe dans le nouveau mode */ /* on etudie l'ancienne config ecran */ switch (old_mode & MASQUE) { case BS1: VSetscreen(lb,pb,3,modecode); adr_ecran=0; ptr_l1e=ptr_ecran=pb; break; case BS2: case BS3: /* ancienne config, 80 col 8 bit non entrelace */ if (type_mon==VGA_FALCON) { VSetscreen(lb,pb,3,modecode); adr_ecran=0; ptr_l1e=ptr_ecran=pb; } else { adr_ecran=calloc(la_taille_ecran,1); VSetscreen(adr_ecran, adr_ecran, 3, modecode); ptr_l1e=ptr_ecran=adr_ecran; } break; default: adr_ecran=calloc(la_taille_ecran,1); if (adr_ecran==0) { fprintf(stderr,"d‚sol‚, plus assez de m‚moire pour calculer une image avec affichage"); DisplayFormat='0'; } VSetscreen(adr_ecran, adr_ecran, 3, modecode); ptr_l1e=ptr_ecran=adr_ecran; break; } /* du test sur le mode courant */ } /*du cas display format 3 */ } /* du test sur le mode overscan */ break; case MATRIX: lb=Logbase(); pb=Physbase(); ptr_matrix=ptr_ecran=pb; len_ligne=(work_out[0]+1)*2; break; default: if (DisplayFormat!='0') { taille=(unsigned long)dim_x*dim_y*2; /* les donnees sont conservees en memoire en nb_coul (nb<=32768) */ /* donc 2 octets par donnees*/ inter=malloc(taille); /* reserver une zone pour sauver l'image */ ptr_ecran=inter; } open_vwork2(); break; } } #if !__STDC__ /* ANSI Standard psuedo-random number generator */ static unsigned long int next = 1; /*int rand() { next = next * 1103515245L + 12345L; return ((int) (next / 0x10000L) & 0x7FFF); } void srand(seed) unsigned int seed; { next = seed; } */ #endif