     1                                  ; ****************************************************************************
     2                                  ; star97pm.s (TRDOS 386, TRDOS v2.0 - sample binary file, 'star97pm.prg')
     3                                  ; ----------------------------------------------------------------------------
     4                                  ; STAR97PM.PRG ! TEST program !  TRDOS 386 VGA Functionality test !
     5                                  ;
     6                                  ; 03/10/2016
     7                                  ;
     8                                  ; [ Last Modification: 03/10/2016 ]
     9                                  ;
    10                                  ; Derived from source code of 'STAR97.COM' (MSDOS) intro file
    11                                  ; (Source: STAR97.ASM, 15/05/1997, 97 bytes)
    12                                  ;
    13                                  ; STAR97.ASM by Deathlock / Assembler (TASM4)
    14                                  ; NASM version of STAR97.ASM: Erdogan Tan, 02/10/2016 (star97.s)
    15                                  ;
    16                                  ; Assembler: NASM 2.11
    17                                  ;
    18                                  ; (Original -msdos- code has been modifed for TRDOS 386 system calls and
    19                                  ; other protected mode (TRDOS 386) interrupts.)
    20                                  ; ****************************************************************************
    21                                  
    22                                  ; 19/05/2016
    23                                  ; 29/04/2016
    24                                  ; TRDOS 386 system calls (temporary list!)
    25                                  _ver 	equ 0
    26                                  _exit 	equ 1
    27                                  _fork 	equ 2
    28                                  _read 	equ 3
    29                                  _write	equ 4
    30                                  _open	equ 5
    31                                  _close 	equ 6
    32                                  _wait 	equ 7
    33                                  _creat 	equ 8
    34                                  _link 	equ 9
    35                                  _unlink	equ 10
    36                                  _exec	equ 11
    37                                  _chdir	equ 12
    38                                  _time 	equ 13
    39                                  _mkdir 	equ 14
    40                                  _chmod	equ 15
    41                                  _chown	equ 16
    42                                  _break	equ 17
    43                                  _stat	equ 18
    44                                  _seek	equ 19
    45                                  _tell 	equ 20
    46                                  _mount	equ 21
    47                                  _umount	equ 22
    48                                  _setuid	equ 23
    49                                  _getuid	equ 24
    50                                  _stime	equ 25
    51                                  _quit	equ 26	
    52                                  _intr	equ 27
    53                                  _fstat	equ 28
    54                                  _emt 	equ 29
    55                                  _mdate 	equ 30
    56                                  _video	equ 31
    57                                  _audio	equ 32
    58                                  _timer	equ 33
    59                                  _sleep	equ 34
    60                                  _msg    equ 35
    61                                  _geterr equ 36
    62                                  _rsrvd1	equ 37
    63                                  _pri	equ 38
    64                                  _rele 	equ 39
    65                                  
    66                                  %macro sys 1-4
    67                                      ; 29/04/2016 - TRDOS 386 (TRDOS v2.0)	
    68                                      ; 03/09/2015	
    69                                      ; 13/04/2015
    70                                      ; Retro UNIX 386 v1 system call.	
    71                                      %if %0 >= 2   
    72                                          mov ebx, %2
    73                                          %if %0 >= 3    
    74                                              mov ecx, %3
    75                                              %if %0 = 4
    76                                                 mov edx, %4   
    77                                              %endif
    78                                          %endif
    79                                      %endif
    80                                      mov eax, %1
    81                                      ;int 30h
    82                                      int 40h ; TRDOS 386 (TRDOS v2.0)	   
    83                                  %endmacro
    84                                  
    85                                  ; TRDOS 386 (and Retro UNIX 386 v1) system call format:
    86                                  ; sys systemcall (eax) <arg1 (ebx)>, <arg2 (ecx)>, <arg3 (edx)>
    87                                  
    88                                  ; STAR97.S (NASM version of STAR97.ASM)
    89                                  ;
    90                                  ;                              [ STARFIELD '97 ]
    91                                  ;
    92                                  ; [ Explanation ]
    93                                  ;
    94                                  ; well, here's an explanation of what's going on. first off we generate the
    95                                  ; starfeild data, star structures are qword aligned for easy offset calc's,
    96                                  ; and a floating random number seed is used. the initial random seed is mov'd
    97                                  ; into the very last star structure, and the next random seed is stored in
    98                                  ; the structure below, and this routine is followed to the very first star
    99                                  ; structure. instead using the modulus of the random number and using it as
   100                                  ; the saved value we mask off all the unwanted bits in the random number, and
   101                                  ; then modify the values to fit in the ranges we need. i was looking for a 4
   102                                  ; layer field (00000011b), and 16 scales of white (00001111b). nifty both
   103                                  ; numbers are binary constants, lucky me! most things don't work out so well.
   104                                  ;
   105                                  ; [ Excuses ]
   106                                  ;
   107                                  ; ok, your saying "Big woop!, i've seen 20 byte starfields". well this is
   108                                  ; true, so have i. however all those starfields are just random color shit.
   109                                  ; not only is the randomness shitty, but they don't check for a keypress, and
   110                                  ; they don't even look like a starfield, otherwise there not usable at all!
   111                                  ; this routine has parallax style scrolling of a 4 layer starfield, 16 random
   112                                  ; shades of stars, a fairly random placement of stars, it's fast, and it even
   113                                  ; checks for vertical retrace and keypress!
   114                                  ;
   115                                  ; [ Questions / Answers ]
   116                                  ;
   117                                  ; you may be scratching your head on some of the sections of this code, so
   118                                  ; let me give you my reasoning before you call me a dumbshit.
   119                                  ;
   120                                  ; Q: why don't you use 'in ax,40h' as a random number routine rather than
   121                                  ;    using imul and such?
   122                                  ;
   123                                  ; A: well 'in ax,40h' sucks, it's not random enough, try it. you'll see my
   124                                  ;    reasoning, the method used is much better. btw i got the random routine
   125                                  ;    i'm using by simplifying the random routine used by borland turbo c 3.0
   126                                  ;    i just disassembled the lib call and this is pretty much what i got.
   127                                  ;    otherwise i had no idea how to make random numbers, this concept was new
   128                                  ;    to me!, wow a learning experience.
   129                                  ;
   130                                  ; Q: why don't you use a 4 byte structure, a word for the address, and a byte
   131                                  ;    for the speed, and another byte for the color?
   132                                  ;
   133                                  ; A: well in the main loop you'll see that i add the speed to the address,
   134                                  ;    and that i store the address in di, well this means that if i wanted to
   135                                  ;    add anything to a 16bit register i would have to use another 16bit mem
   136                                  ;    location or register, and i can't otherwise it screws up. i wish there
   137                                  ;    was some kind of addzx instruction which added the contents of a smaller
   138                                  ;    register but internally masked it to the same size as the destination
   139                                  ;    with zero's extended. ohh well there are too many instructions anyways.
   140                                  ;
   141                                  ; Q: only 255 stars?
   142                                  ;
   143                                  ; A: it looks ok doesn't it?!, you can use up to something like 8000 stars if
   144                                  ;    you change the 'mov cl,NSTARS' to 'mov cx,NSTARS'. however the code size
   145                                  ;    will increase two bytes (this was my origional goal 99 bytes), however i
   146                                  ;    was told it would be "cooler" to release something that referenced the
   147                                  ;    current year??
   148                                  ;
   149                                  ; Q: my god your a moron, i could make this much smaller, and still retain
   150                                  ;    all of the kewl features you talk about.
   151                                  ;
   152                                  ; A: great, please do, and send me your changes to brandt@europa.com. i tried
   153                                  ;    to the best of my ability to make it smaller, i even got it to 87 bytes
   154                                  ;    using the 'in ax,40h', and commenting out the random number seed setup,
   155                                  ;    and the imul, along with the following mov. but like i said a couple of
   156                                  ;    questions above 'in ax,40h' looks shitty.
   157                                  ;
   158                                  ; ohh, one last thing i do use the following 80386 instructions:
   159                                  ;
   160                                  ; shl    reg16,immediate > 1
   161                                  ; imul   reg16,mem | reg16,reg16 | immediate
   162                                  ;
   163                                  ;                                      deathlock ; brandt@europa.com
   164                                  
   165                                  ; NASM version: Erdogan Tan, 03/10/2016
   166                                  
   167                                  NSTARS  EQU     255                     ; number of stars to draw
   168                                  
   169                                  [Bits 32] ; Protected Mode (TRDOS 386) Program
   170                                  
   171                                  [org 0]   ; TRDOS 386 PRG File
   172                                  
   173                                  start:
   174                                   ; DIRECT VGA MEMORY ACCESS
   175                                   ;xor    ebx, ebx
   176 00000000 B705                     mov     bh, 5 ; Direct access/map to VGA memory (0A0000h)
   177                                   ;mov    eax, _video ; 1Fh
   178 00000002 B01F                     mov     al, 1Fh ; sys _video ; TRDOS 386 Video functions
   179 00000004 CD40                     int     40h   ; TRDOS 386 system call
   180                                  
   181                                   ; eax = 0A0000h
   182 00000006 21C0                     and     eax, eax
   183 00000008 7475                     jz      terminate ; error (eax = 0)
   184                                  
   185 0000000A 89C7                     mov	edi, eax ; 0A0000h ; es = 0A000h ; VGA memory (frame buffer) address
   186                                  
   187 0000000C B013                     mov    al,13h                          ; function 00h, mode 13h 
   188                                   ;int   10h                             ; bios video interrupt
   189 0000000E CD31                     int    31h ; TRDOS 386 - Video interrupt
   190                                   
   191                                  ;[ initialize starfield variables ]------------------------------------------
   192                                  
   193 00000010 B1FF                     mov    cl,NSTARS                       ; cx = number of stars to initialize
   194 00000012 C605[88080000]01         mov    byte [NSTARS*8+stars+8],1       ; set the begining random number seed
   195                                  
   196                                  loop1:
   197 00000019 6689CB                   mov    bx,cx                           ; copy cx to bx for indexing
   198 0000001C 66C1E303                 shl    bx,3                            ; multiply bx by 8 (structure size)
   199 00000020 6681C3[8800]             add    bx,stars                        ; add the start offset of stars to bx
   200                                  
   201 00000025 66694308354E             imul   ax,word [ebx+8],4E35h           ; multiply to get next random number
   202 0000002B 668903                   mov    word [ebx],ax                   ; stars[cx].addr = ax
   203 0000002E 66250F03                 and    ax,0000001100001111b            ; mask off unwanted values
   204 00000032 040E                     add    al,14                           ; make sure al < 30 & al > 14
   205 00000034 66894302                 mov    word [ebx+2],ax                 ; stars[cx].col = ax
   206 00000038 66C1E808                 shr    ax,8                            ; shift hi byte to low byte
   207 0000003C FEC0                     inc    al                              ; stars[cx].spd can't be zero
   208 0000003E 66894304                 mov    word [ebx+4],ax                 ; stars[cx].spd = ax
   209 00000042 E2D5                     loop   loop1                           ; do this again for the next star
   210                                  
   211                                  ;[ the main loop, holy shit! ]-----------------------------------------------
   212                                  
   213                                  drawstars:
   214                                  
   215                                  vend:
   216 00000044 66BADA03                 mov    dx,03DAh                        ; vga status port for retrace
   217                                   ;in    al,dx                           ; al = vga status byte (03DAh)
   218                                   ;mov   ah,0 ; in (byte)
   219 00000048 CD34                     int    34h ; TRDOS 386 - IOCTL interrupt
   220 0000004A 2408                     and    al,08h                          ; keep the vretrace status bit
   221 0000004C 74F6                     jz     short vend                      ; not equal to 1?, check again
   222                                  
   223 0000004E B1FF                     mov    cl,NSTARS                       ; lets draw NSTARS to the screen
   224                                  
   225                                  loop2:
   226 00000050 6689CB                   mov    bx,cx                           ; copy cx to bx for indexing again
   227 00000053 66C1E303                 shl    bx,3                            ; multiply bx by 8 (structure size)
   228 00000057 6681C3[8800]             add    bx,stars                        ; add start offset of stars to bx
   229 0000005C 668B3B                   mov    di,word [ebx]                   ; di = stars.addr
   230 0000005F 8827                     mov    [edi],ah                        ; erase star (ah = 0)
   231 00000061 66037B04                 add    di,word [ebx+4]                 ; stars.addr = stars.addr + stars.spd
   232 00000065 8A4302                   mov    al,byte [ebx+2]                 ; al = stars.col
   233 00000068 8807                     mov    [edi],al                        ; draw new star to the screen
   234 0000006A 66893B                   mov    word [ebx],di                   ; save the updated star posistion 
   235 0000006D E2E1                     loop   loop2                           ; erase/draw all NSTARS to the screen
   236                                  
   237                                   ;in    al,60h                          ; al = port 60h, keyboard
   238 0000006F 66BA6000                 mov	dx,60h
   239 00000073 B400                     mov    ah,0 ; in (byte)
   240 00000075 CD34                     int    34h ; TRDOS 386 - IOCTL interrupt
   241 00000077 3C01                     cmp    al,1                            ; escape key pressed?
   242 00000079 75C9                     jnz    short drawstars                 ; was escape pressed, no do it again
   243                                  
   244 0000007B B003                     mov    al,03h                          ; escape was pressed, lets quit
   245                                   ;int   10h                             ; al = 03h text mode, int 10 video
   246 0000007D CD31                     int    31h ; TRDOS 386 - Video interrupt
   247                                  
   248                                  terminate:
   249                                   sys    _exit   ; INT 40h
   250                              <1> 
   251                              <1> 
   252                              <1> 
   253                              <1> 
   254                              <1>  %if %0 >= 2
   255                              <1>  mov ebx, %2
   256                              <1>  %if %0 >= 3
   257                              <1>  mov ecx, %3
   258                              <1>  %if %0 = 4
   259                              <1>  mov edx, %4
   260                              <1>  %endif
   261                              <1>  %endif
   262                              <1>  %endif
   263 0000007F B801000000          <1>  mov eax, %1
   264                              <1> 
   265 00000084 CD40                <1>  int 40h
   266                                  here:
   267 00000086 EBFE                     jmp    short here
   268                                  
   269                                  stars:                                  ; start of starfield structure
