view level1/modules/covdg.asm @ 3295:6b7a7b233925 default tip

makefile: Allow PORTS with level1/2 mix https://sourceforge.net/p/nitros9/feature-requests/10/
author Tormod Volden <debian.tormod@gmail.com>
date Tue, 19 Apr 2022 18:12:17 +0200
parents 13737f3608e6
children
line wrap: on
line source

********************************************************************
* CoVDG - VDG Console Output Subroutine for VTIO
*
* $Id$
*
* Edt/Rev  YYYY/MM/DD  Modified by
* Comment
* ------------------------------------------------------------------
*   1      ????/??/??
* From Tandy OS-9 Level One VR 02.00.00
*
*          2003/09/22  Rodney Hamilton
* recoded dispatch table fcbs, fixed cursor color bug
*
*          2017/12/20  Boisy Pitre
* Added support for CoCoVGA 64x32 mode
*
*   2      2018/03/02  David Ladd
*        - 2018/03/24  L. Curtis Boyle
* General optimizations, and support for new V.ClrBlk and V.CpyBlk
*   vector calls (from VTIO) for either 6309 TFM for mini-stack blasting
*   (4 bytes/chunk) for screen scroll and screen clears (full & partial)
* Also, CoVGA support integrated/completed for 64x32 text mode, and SS.Cursr
*   GetStat call bugs fixed (for both CoVGA and CoVDG)

         nam   CoVDG
         ttl   VDG Console Output Subroutine for VTIO

* Disassembled 98/08/23 17:47:40 by Disasm v1.6 (C) 1988 by RML

         ifp1
         use   defsfile
         use   cocovtio.d
         endc

tylg     set   Systm+Objct   
atrv     set   ReEnt+rev
rev      set   $00
edition  set   2

         mod   eom,name,tylg,atrv,start,size

		 IFNE  COCOVGA
COLSIZE  equ   64
ROWSIZE  equ   32
MODFLAG  equ   ModCoVGA
		 ELSE
COLSIZE  equ   32
ROWSIZE  equ   16
MODFLAG  equ   ModCoVDG
		 ENDC

u0000    rmb   0
size     equ   .
         fcb   $07 

name     equ   *
		IFNE	COCOVGA
         fcs   /CoVGA/
		ELSE
         fcs   /CoVDG/
		ENDC
         fcb   edition

* Init
Init     pshs  y,x            save regs
         lda   #$AF
         sta   <V.CColr,u     save default color cursor
         pshs  u              save static ptr
         ldd   #COLSIZE*ROWSIZE+256 allocate screen + 256 bytes for now
         os9   F$SRqMem       get it
         tfr   u,d            put ptr in D
         leax  ,u             and X
         bita  #$01           odd page?
         beq   L0052          branch if not
         leax  >256,x         else move X up 256 bytes
         bra   L0056          and return first 256 bytes

L0052    leau  >COLSIZE*ROWSIZE,u   else move X up 512 bytes
L0056    ldd   #256           and return last 256 bytes
         os9   F$SRtMem       free it!
         puls  u              restore static ptr
         stx   <V.ScrnA,u     save VDG screen memory
         pshs  y
         leay  -$0E,y
         clra
         clrb
         jsr   [<V.DspVct,u]  display screen (SetDsply routine in VTIO) (Preserves X)
         puls  y
         stx   <V.CrsrA,u     save start cursor position
         leax  >COLSIZE*ROWSIZE,x   point to end of screen
         stx   <V.ScrnE,u     save it
LDClrCh  lda   #$60           get default character
         sta   <V.CChar,u     put character under the cursor
         sta   <V.Chr1,u      only referenced here ??

     IFNE	COCOVGA
***** START OF COCOVGA 64x32 MODE
         clr   <V.Caps,u      lowercase mode
         pshs  cc,u
         orcc  #IntMasks      Shut off IRQ/FIRQ
         ldx   #$FF03         Point to PIA
         lda   ,x             Get current state of PIA
         pshs  a              Save copy
         lda   ,x             Now, force things necessary for CocoVGA to work
         ora   #$04           ensure PIA 0B is NOT dir setting
         sta   ,x
         lda   ,x
         anda  #$fd           vsync irq - trigger falling edge
         sta   ,x
         lda   ,x
         ora   #$01           enable vsync IRQ
         sta   ,x
         leax  VGASetup,pcr   Point to set up values (9 of them)
         ldu   <V.ScrnA,u     CoVGA requires are setup sequence to be at start of 512 byte boundary 
         ldb   #VGASetupLen   This routine copies our 9 bytes to the start of the screen (Based on
x@       lda   ,x+
         sta   ,u+
         decb
         bne   x@

         lda   $FF02          clear any pending vsync
tlp@     lda   $FF03          wait for flag to indicate
         bpl   tlp@           falling edge of FS
         lda   $FF02          clear vsync interrupt flag

* PROGRAM THE COCOVGA COMBO LOCK
BT13     ldx   #$FF22         Point to PIA
         lda   ,x             GET CURRENT PIA VALUE
         tfr   A,B            COPY TO B REG TOO
         anda  #$07           MASK OFF BITS WE'LL CHANGE
         ora   #$90           SET COMBO LOCK 1 BITS
         sta   ,x             WRITE TO PIA FOR COCOVGA
         anda  #$07           CLEAR UPPER BITS
         ora   #$48           SET COMBO LOCK 2 BITS
         sta   ,x             WRITE TO PIA
         anda  #$07           CLEAR UPPER BITS
         ora   #$A0           SET COMBO LOCK 3 BITS
         sta   ,x             WRITE TO PIA
         anda  #$07           CLEAR UPPER BITS
         ora   #$F8           SET COMBO LOCK 4 BITS
         sta   ,x             WRITE TO PIA
         lda   ,x             get current PIA value
         anda  #$07           CLEAR UPPER BITS
* 6809/6309 - Isn't this next line useless? It does not change any bits, ever
         ora   #$00           SET REGISTER BANK 0 FOR COCOVGA
         sta   ,x             WRITE TO PIA
         sta   $FFC0          clear SAM_V0  (Force SAM to text mode)
         sta   $FFC2          clear SAM_V1
         sta   $FFC4          clear SAM_V2

* Wait for next VSYNC so CoCoVGA can process data from the current video page
tlp@     lda   $FF03
         bpl   tlp@

* Restore PIA state and return to text mode - restore original video mode, SAM page
* VDG -> CG2:
         lda   ,x
         anda  #$8F
         ora   #$A0
         sta   ,x

* SAM -> CG2:
         sta   $FFC0          clear GM0
         sta   $FFC3          set GM1
         sta   $FFC4          clear GM2 FFC4
         puls  a
         sta   $FF03          Restore PIA to original state
         puls  u,cc
***** END OF COCOVGA 64x32 MODE
     ENDC
         lbsr  ClrScrn        clear the screen
* Setup page to
         ldb   <V.COLoad,u
         orb   #MODFLAG       set to CoVDG found (?)
L0086    stb   <V.COLoad,u
         clrb
*The next line is only for testing to see where VGA is breaking
         puls  pc,y,x

     IFNE  COCOVGA
***** START OF COCOVGA 64x32 MODE         
VGASetup fcb   $00            Reset register
         fcb   $81            Edit mask
         fcb   $00            Reserved
         fcb   $03            Font (lowercase/t1 character set enabled)
         fcb   $00            Artifact (off)
         fcb   $00            Extras (off)
         fcb   $00            Reserved
         fcb   $00            Reserved
         fcb   $02            Enhanced Modes (64 column enabled)
VGASetupLen equ *-VGASetup
***** END OF COCOVGA 64x32 MODE         
     ENDC

start    lbra  Init           Hopefully once we tighten INIT code, this can go back to BRA
         bra   Write
         nop                  Can be used for a constant
         lbra  GetStat
         lbra  SetStat
Term     pshs  y,x
         pshs  u              save U
         ldd   #COLSIZE*ROWSIZE  VDG memory size
         ldu   <V.ScrnA,u     get pointer to memory
         os9   F$SRtMem       return to system
         puls  u              restore U
         ldb   <V.COLoad,u
         andb  #~MODFLAG
         bra   L0086
* Write
* Entry: A = char to write
*        Y = path desc ptr
Write    tsta                 Alt (hi bit) char?
         bmi   L00D0          Yes, go straight to print
         cmpa  #$1F           Ctrl char? ($00-$1F)?
         bls   Dispatch       Yes, special handling
         ldb   <V.CFlag,u     regular ASCII char; get true lowercase flag
         beq   L00B0          Not set, skip ahead
* VDG-T1 translations
         cmpa  #$5E           ^ symbol?
         bne   L00A0          Nope, check next 
         clra                 0 char on VDG
         bra   L00D0          Put on screen

L00A0    cmpa  #$5F           _ Underline char?
         bne   L00A8          No, check next
         lda   #$1F           $1F char on VDG
         bra   L00D0          Put on screen

L00A8    cmpa  #$60           ' Single quote?
         bne   L00C0          No, skip ahead to common translations
         lda   #$67           $67 char on VDG
         bra   L00D0

* Regular VDG translations
L00B0    cmpa  #$7C           | Pipe symbol?
         bne   L00B8          No, check next
         lda   #$21           Yes, change to ! pipe symbol
         bra   L00D0          Put on screen

L00B8    cmpa  #$7E           ~ Tilde symbol?
         bne   L00C0          Nope, go do common translations
         lda   #$2D           Tilde symbol for VDG
         bra   L00D0          Put on screen

* Common translation to both VDG chips
L00C0    cmpa  #$60           Char below $60?
         blo   L00C8          Yes, check next range
         suba  #$60           Drop by $60 for VDG translation
         bra   L00D0          Put on screen

L00C8    cmpa  #$40           Char below $40?
         blo   L00CE          Yes, Flip case bit only
         suba  #$40           Drop for VDG
L00CE    eora  #$40           Force to non-inverse chars on regular VDG
L00D0    ldx   <V.CrsrA,u     get cursor address in X
         sta   ,x+            store character at address
         stx   <V.CrsrA,u     update cursor address
         cmpx  <V.ScrnE,u     end of screen?
         blo   L00DF          No, just display the cursor
         bsr   SScrl          Yes, scroll the screen first
L00DF    bra   ShowCrsr       And turn the cursor back on

* Screen Scroll Routine
SScrl    ldd   #COLSIZE*ROWSIZE-COLSIZE  Size of screen minus one line
         ldx   >V.ClrBlk,u    Get Clear block vector for later
         pshs  u,x            Save static mem ptr & Clear block vector
         ldx   >V.CpyBlk,u    Get vector to Copy block
         ldy   <V.ScrnA,u     Get ptr to start of text screen
         leau  <COLSIZE,y     Point to start of 2nd line
         jsr   ,x             Call copy block vector (U will point to end of screen+1)
         ldx   #COLSIZE       Size of block to clear (bottom line)
         ldb   #$60           VDG Space char
         puls  y              Get clear block vector
         jsr   ,y             Clear last line (U was pointing to end of last line from above, so it picks up where it left off. I think)
* Since 6309 returns with U=ptr to end of screen, and 6809 returns with ptr to start of last line,
*   we need to differentiate here
       IFNE  H6309
         leax  -COLSIZE,u     6309 - Bump back to start of last line
       ELSE
         leax  ,u             6809 - already pointing to start of last line
       ENDC
         puls  u              Get back static mem ptr
         stx   <V.CrsrA,u     Save new cursor position (Start of last line)
         rts                  & return

* Ctrl char ($00-$1F) special char dispatch
Dispatch cmpa  #$1B           escape code?
         bhs   bad            branch if same or greater (special control codes for screen controls)
         cmpa  #$0E           $0E?
         bhi   L0102          branch if higher than
         leax  <DCodeTbl,pcr  deal with screen codes
         lsla                 adjust for table entry size
         ldd   a,x            get address in D
         jmp   d,x            and jump to routine
* 
bad      comb                 Exit with Write Error
         ldb   #E$Write
L0102    rts   

* display functions dispatch table.
DCodeTbl fdb   L014D-DCodeTbl     $00:no-op (null)
         fdb   CurHome-DCodeTbl   $01:HOME cursor
         fdb   CurXY-DCodeTbl     $02:CURSOR XY
         fdb   DelLine-DCodeTbl   $03:ERASE LINE
         fdb   ErEOLine-DCodeTbl  $04:CLEAR TO EOL
         fdb   Do05-DCodeTbl      $05:CURSOR ON/OFF
         fdb   CurRght-DCodeTbl   $06:CURSOR RIGHT
         fdb   L014D-DCodeTbl     $07:no-op (bel:handled in VTIO)
         fdb   CurLeft-DCodeTbl   $08:CURSOR LEFT
         fdb   CurUp-DCodeTbl     $09:CURSOR UP
         fdb   CurDown-DCodeTbl   $0A:CURSOR DOWN
         fdb   ErEOScrn-DCodeTbl  $0B:ERASE TO EOS
         fdb   ClrScrn-DCodeTbl   $0C:CLEAR SCREEN
         fdb   Retrn-DCodeTbl     $0D:RETURN
         fdb   DoAlpha-DCodeTbl   $0E:DISPLAY ALPHA

* $0D - move cursor to start of line (carriage return)
Retrn    bsr   HideCrsr       hide cursor
       IFNE  H6309
         aim   #~(COLSIZE-1),<V.CrsAL,u  Force cursor to beginning of current line (clear low 5 OR 6 bits of address)
       ELSE
         tfr   x,d            put cursor address in D
         andb  #~(COLSIZE-1)  place at start of line
         stb   <V.CrsAL,u     and save low cursor address
       ENDC
ShowCrsr ldx   <V.CrsrA,u     get cursor address
         lda   ,x             get char at cursor position
         sta   <V.CChar,u     save it
         lda   <V.CColr,u     get cursor character
         beq   L014D          If cursor off, don't put on screen
L014B    sta   ,x             else turn on cursor
L014D    clrb                 & exit w/o error
         rts   

* $0A - cursor down (line feed)
CurDown  bsr   HideCrsr       hide cursor
         leax  <COLSIZE,x     move X down one line
         cmpx  <V.ScrnE,u     at end of screen?
         blo   L0162          branch if not
         leax  <-COLSIZE,x    else go back up one line
         pshs  x              save cursor position
         lbsr  SScrl          & scroll the screen
         puls  x              restore pointer
L0162    stx   <V.CrsrA,u     save cursor pointer
         bra   ShowCrsr       show cursor

* $08 - cursor left
CurLeft  bsr   HideCrsr       hide cursor
         cmpx  <V.ScrnA,u     compare against start of screen
         bls   L0173          ignore it if at the screen start
         leax  -1,x           else back up one
         stx   <V.CrsrA,u     save updated pointer
L0173    bra   ShowCrsr       and show cursor

* $06 - cursor right
CurRght  bsr   HideCrsr       hide cursor
         leax  1,x            move to the right
         cmpx  <V.ScrnE,u     compare against end of screen
         bhs   L0181          if past end, ignore it
         stx   <V.CrsrA,u     else save updated pointer
L0181    bra   ShowCrsr       and show cursor

* $0B - erase to end of screen
ErEOScrn bsr   HideCrsr       kill the cusror
         bra   L0189          and clear rest of the screen

* $0C - clear screen
ClrScrn  bsr   CurHome        home cursor (and set X=ptr to start of screen)
* Entry point for partial screen clear
* Entry: X=ptr to start address to clear from
* For V.ClrBlk,u, entry is: B=value to clear with, X=size to clear, U=End of clear block address+1
L0189    
       IFNE  H6309
         pshs  u              Save static mem ptr
         ldy   <V.ScrnE,u     Get ptr to end of screen
         subr  x,y            Calc size of clear by subtracting current cursor address
         leax  ,y             X=size to clear
         ldy   >V.ClrBlk,u    Get Clear Block subroutine address
       ELSE
         pshs  x              Save start addr to clear from
         ldd   <V.ScrnE,u     Get ptr to end of screen
         subd  ,s++           Calc size of clear (subtract start addr)
         tfr   d,x            Move size to X
         ldy   >V.ClrBlk,u    Get Clear Block subroutine address
         pshs  u              Save static mem ptr
       ENDC
         ldu   <V.ScrnE,u     Point to end address of screen
         ldb   #$60           VDG Space char
         jsr   ,y             Go clear
         puls  u              Get static mem ptr back
         bra   ShowCrsr       Turn cursor back on
         
* $01 - home cursor
CurHome  bsr   HideCrsr       hide cursor
         ldx   <V.ScrnA,u     get pointer to screen
         stx   <V.CrsrA,u     save as new cursor position
         bra   ShowCrsr       and show it

* Hides the cursor from the screen
* Exit: X = address of cursor
HideCrsr ldx   <V.CrsrA,u     get address of cursor in X
         lda   <V.CChar,u     get value of char under cursor
         sta   ,x             put char in place of cursor
NoErr1   clrb                 must be here, in general, for [...] BRA HideCrsr
         rts   

* $05 XX - set cursor off/on/color per XX-32
Do05     ldb   #$01           need additional byte
         leax  <CrsrSw,pcr    Get vector to return to after we get byte
         bra   L01E5          Save vector, and go get parameter byte

CrsrSw   lda   <V.NChr2,u     get next char
         suba  #C$SPAC        take out ASCII space
         bne   L01BB          branch if not zero
         sta   <V.CColr,u     else save cursor color zero (no cursor)
         bra   HideCrsr       and hide cursor

L01BB    cmpa  #11            >=11?
         bge   NoErr1          yep, ignore & return w/o error
         cmpa  #1             is it one (Blue cursor from level 1)?
         bgt   L01C7          No, try next
         lda   #$AF           Yes, default blue cursor color
         bra   L01D7          and save it
         
L01C7    cmpa  #2             is it two (black cursor from level 1)?
         bgt   L01CF          branch if larger
         lda   #$A0           else get black cursor color
         bra   L01D7          and save it
         
L01CF    lsla                 shift into upper nibble
         lsla  
         lsla  
         lsla  
         ora   #$8F
L01D7    sta   <V.CColr,u     save new cursor
         ldx   <V.CrsrA,u     get cursor address
         lbra  L014B          branch to save cursor in X

* $02 XX YY - move cursor to col XX-32, row YY-32
CurXY    ldb   #2             we neeed two more parameters
         leax  <DoCurXY,pcr   Get vector to return to after we get params
L01E5    stx   <V.RTAdd,u     Save it
         stb   <V.NGChr,u     Save # chars needed as params
         clrb                 No error, and go get missing param bytes
         rts   

DoCurXY  bsr   HideCrsr       hide cursor
         ldb   <V.NChr2,u     get ASCII Y-pos
         subb  #C$SPAC        take out ASCII space
         lda   #COLSIZE       Calculate vertical offset from start of screen to line we want
         mul                  multiply it
         addb  <V.NChar,u     add in X-pos
         adca  #$00
         subd  #C$SPAC        take out another ASCII space
         addd  <V.ScrnA,u     add top of screen address
         cmpd  <V.ScrnE,u     past end of screen?
         bhs   NoErr1         Yes, ignore & exit w/o error
         std   <V.CrsrA,u     otherwise save new cursor address
         lbra  ShowCrsr       and show cursor

* $04 - erase to end of line
ErEOLine bsr   HideCrsr       hide cursor
         tfr   x,d            move current cursor position to D
         andb  #COLSIZE-1     number of characters put on this line
         pshs  b
         ldb   #COLSIZE       Calculate # of chars left in line
         subb  ,s+
         bra   L0223          and clear that many

* $03 - erase line
DelLine  lbsr  Retrn          do a CR
         ldb   #COLSIZE       line length
* Entry: B=# of bytes to erase, X=ptr to start of copy
L0223    ldy   >V.ClrBlk,u    Get ClrBlk vector (before we destroy u)
         pshs  u              Save static mem ptr
         leau  b,x            Point U to end of line
         clra                 D=size
         tfr   d,x            Move to X for ClrBlk
         ldb   #$60           VDG space char
         jsr   ,y             Call ClrBlk
         puls  u              Get static mem back
         lbra  ShowCrsr       Turn cursor back on & return from there

* $09 - cursor up
CurUp    lbsr  HideCrsr       hide cursor
         leax  <-COLSIZE,x    move X up one line
         cmpx  <V.ScrnA,u     We past top of screen?
         blo   L023E          Yes, leave cursor pos along and turn it back on
         stx   <V.CrsrA,u     No, save new cursor Y position
L023E    lbra  ShowCrsr       Show cursor & return from there

* $0E - switch screen to alphanumeric mode
DoAlpha  clra                 
         clrb                 Text mode
         jmp   [<V.DspVct,u]  display screen (routine in VTIO)

* GetStat
GetStat  ldx   PD.RGS,y       get caller's regs
         cmpa  #SS.AlfaS      AlfaS?
         beq   Rt.AlfaS       branch if so
         cmpa  #SS.Cursr      Cursr?
         beq   Rt.Cursr       branch if so

* SetStat - All SetStat calls return "Unknown Service" error
SetStat  comb  
         ldb   #E$UnkSvc
         rts   

* SS.AlfaS getstat
Rt.AlfaS ldd   <V.ScrnA,u   memory address of buffer
         std   R$X,x        save in caller's X
         ldd   <V.CrsrA,u   get cursor address
         std   R$Y,x        save in caller's Y
         lda   <V.Caps,u    save caps lock status in A and exit
         bra   SaveA

* SS.Cursr getstat. NOTE: It appears that X,Y coords are returned with +$20 built in (to match
*   the original CurXY ($02 xx+$20 yy+$20) display code).
Rt.Cursr ldd   <V.CrsrA,u     get address of cursor
         subd  <V.ScrnA,u     subtract screen address
         pshs  d              D now holds cursor position relative to screen
         clra  
         andb  #COLSIZE-1     Keep X coord bits only (0-31 or 0-63)
         addb  #$20           compute column position (+$20 for CurXY offsets)
         std   R$X,x          save column position to caller's X
         puls  d              then divide by 32 for VDG, and 64 for VGA
       IFNE  COCOVGA
         lsra                 Need three 16 bit divides (/8) - now 8 bit (2048->1024->512->256)
         rorb
         lsra
         rorb
         lsra
         rorb
         lsrb                 Finish divide by 64 with just 8 bit divides
         lsrb
         lsrb
       ELSE
         lsra                 16 bit divide - now our result is within 8 bit range(512->256)
         rorb  
         lsrb                 Finish divide by 32 with just 8 bit divides
         lsrb  
         lsrb
         lsrb
       ENDC
         addb  #$20           compute row (+$20 for CurXY offsets
         std   R$Y,x          and save column to caller's Y
         ldb   <V.CFlag,u     Get true lowercase flag
         lda   <V.CChar,u     get character under cursor
         bmi   SaveA          if hi bit set, return that value to caller
         cmpa  #$60           Lowercase?
         bhs   L02A5          Yes, skip ahead
         cmpa  #$20           #, uppercase, some punctuation?
         bhs   L02A9          Yes, Change if VDG-T1
         tstb                 Real lowercase enabled?
         beq   L02A3          No, convert to ASCII from VDG code
         tsta                 VDG caret?
         bne   L029B          No, try some other special ones
         lda   #$5E           Replace with ASCII caret ^
         bra   SaveA          save it and exit

L029B    cmpa  #$1F           VDG underscore?
         bne   L02A3          No, done special checks
         lda   #$5F           Yes, replace with underscore
         bra   SaveA

L02A3    ora   #$20           turn it into ASCII from VDG codes
L02A5    eora  #$40           Switch to uppercase
         bra   SaveA

L02A9    tstb                 True lowercase on with VDG-T1?      
         bne   SaveA          yes, save char
         cmpa  #$21           No, remap specific codes - exclamation/pipe?
         bne   L02B4          No, try one more special one
         lda   #$7C           Replace with actual ASCII pipe
         bra   SaveA

L02B4    cmpa  #$2D
         bne   SaveA
         lda   #$7E           Replace with ASCII tilde
SaveA    sta   R$A,x
         clrb  
         rts   

         emod
eom      equ   *
         end