10 REM > PALSUB/S
   20 REM Source for PALSUB - 12-bit palette control code
   30 REM Code is position independent, so can be loaded anywhere
   40 :
   50 REM Use in a program running in the I/O processor with:
   60 REM   DIM PALETTE 200
   70 REM   OSCLI "LOAD PALSUB "+STR$~PALETTE
   80 REM   CALL PALETTE+3
   90 REM
  100 REM To change the palette use:
  110 REM   CALL PALETTE,colour,red,green,blue
  120 REM   where colour,red,green,blue are all 0-15
  130 :
  140 DEFFNif(A%):IFA%:z%=-1:=opt% ELSE z%=P%:=opt%
  150 DEFFNendif:IFz%=-1:=opt% ELSE z%=P%-z%:P%=P%-z%:O%=O%-z%:=opt%
  160 :
  170 DIM mcode% &100
  180 clwyd% =TRUE  :REM Clwyd Palette Expander
  190 cc500% =FALSE :REM CTS Colour Card
  200 pmate% =FALSE :REM WildVision PaletteMate
  210 chamel%=FALSE :REM Chameleon
  220 vnula% =FALSE :REM VideoNuLA
  230 :
  240 PROCassem:END
  250 :
  260 DEFPROCassem
  270 load%=&C00
  280 OSBYTE=&FFF4
  290 FOR opt%=4 TO 7 STEP 3
  300   P%=load%:O%=mcode%
  310   [OPT opt%
  320   .load%
  330   CLC:BCC select           :\ Main entry point
  340   .exec%
  350   .L0C1A
  360   RTS                      :\ Initialise at exec%+3
  370   .select                  :\ Get initial parameters
  380   LDA #&00:STA &70         :\ &70=0, number of parameters read
  390   :       :STA &72         :\ &72=0, index into CALL buffer
  400   STA &73:LDA #&06:STA &74 :\ &73/4=>&600, CALL buffer
  410   LDA &0600:STA &71        :\ &71=number of parameters
  420   :
  430   CMP #&04:BNE L0C1A       :\ Not four parameters, exit
  440   .L0C09
  450   LDY &72                  :\ Get index into CALL buffer
  460   INY:LDA (&73),Y:STA &75  :\ &75/6=>data
  470   INY:LDA (&73),Y:STA &76
  480   INY:LDA (&73),Y:STA &77  :\ &77=type
  490   STY &72                  :\ Save updated index
  500   :
  510   LDY #&00:LDA (&75),Y:TAX :\ Get byte 0 of data
  520   INY:LDA (&75),Y          :\ Get byte 1 of data
  530   :
  540   PHA:LDA &77              :\ Get data type
  550   CMP #&04:BEQ L0C70       :\ Integer
  560   CMP #&05:BNE L0C73       :\ Not float
  570   TXA:AND #&7F:TAX
  580   PLA:ORA #&80
  590   CPX #&00:BEQ L0C73       :\ &00,&00 -> zero
  600   CLC                      :\ Convert float to integer
  610   .L0C6A
  620   ROL A:DEX:BNE L0C6A
  630   ROL A:PHA
  640   .L0C70
  650   PLA:TAX                  :\ Already integer
  660   .L0C73
  670   TXA
  680   :
  690   LDX &70:STA &80,X        :\ Store at &80+n
  700   INC &70:LDA &70          :\ Step to next parameter
  710   CMP &71:BNE L0C09        :\ Loop until all done
  720   :
  730   \ Now use the four bytes at &80-&83, C,R,G,B
  740   LDA #&13:JSR OSBYTE      :\ Wait for HSync
  750   \ 100
  760   :
  770   OPT FNif(clwyd%)
  780   \ Clwyd Expander:
  790   \ Write to user port:
  800   \  %cccc1000 - colour number
  810   \  %rrrr1001 - RED
  820   \  %gggg1010 - GREEN
  830   \  %bbbb1011 - BLUE
  840   \ Data written with b3=0, b3=1, b3=0, b3=1
  850   \ ie, write xxxx0xxx
  860   \     write xxxx1xxx
  870   \     write xxxx0xxx
  880   \     write xxxx1xxx
  890   \
  900   LDA #&FF:STA &FE62       :\ I/O=output
  910   LDA #&00:STA &FE60
  920   LDX #0
  930   .L0CA0
  940   LDA &80,X                :\ Get C,R,G,B
  950   ASL A:ASL A:ASL A:ASL A  :\ *16
  960   ORA #&08:STA &80,X
  970   TXA:ORA &80,X            :\ %nnnn10yy, yy=0/1/2/3 for C/R/G/B
  980   AND #&F7:STA &FE60       :\ Write xxxx0xxx
  990   ORA #&08:STA &FE60       :\ Write xxxx1xxx
 1000   AND #&F7:STA &FE60       :\ Write xxxx0xxx
 1010   LDA #&00:STA &FE60       :\ Write xxxx1xxx
 1020   INX:CPX #4:BNE L0CA0
 1030   RTS
 1040   OPT FNendif
 1050   :
 1060   OPT FNif(cc500%)
 1070   \ CTS Colour Card 500:
 1080   \ Write to colour card:
 1090   \  %xxxxrrrr to &FCA0+L - RED
 1100   \  %xxxxgggg to &FCA8+L - GREEN
 1110   \  %xxxxbbbb to &FCB0+L - BLUE
 1120   \
 1130   LDA &80:AND #7:TAX       :\ Colour number
 1140   LDA &81:STA &FCA0,X      :\ Write RED
 1150   LDA &82:STA &FCA8,X      :\ Write GREEN
 1160   LDA &83:STA &FCB0,X      :\ Write BLUE
 1170   RTS
 1180   OPT FNendif
 1190   :
 1200   OPT FNif(chamel%)
 1210   \ Chameleon:
 1220   \ Write to User port:
 1230   \  %000xrrrr - inverted RED
 1240   \  %010xgggg - inverted GREEN
 1250   \  %100xbbbb - inverted BLUE
 1260   \  %111xcccc - colour number
 1270   \
 1280   LDA #&FF:STA &FE62   :\ I/O=output
 1290   LDA #&AE:STA &FE6C   :\ Toggle CB2 on writes
 1300   LDA &80:ORA #&E0:STA &FE60
 1310   LDA &81:ORA #&00:EOR #15:STA &FE60
 1320   LDA &82:ORA #&40:EOR #15:STA &FE60
 1330   LDA &83:ORA #&80:EOR #15:STA &FE60
 1340   RTS
 1350   OPT FNendif
 1360   :
 1370   OPT FNif(vnula%)
 1380   \ VideoNuLA:
 1390   \ Write to &FE23=%ccccrrrr, then %ggggbbbb
 1400   \
 1410   LDA &80:ASL A:ASL A:ASL A:ASL A
 1420   ORA &81:STA &FE23
 1430   LDA &82:ASL A:ASL A:ASL A:ASL A
 1440   ORA &83:STA &FE23
 1450   RTS
 1460   OPT FNendif
 1470   :
 1480 ]:NEXT
 1490 PRINT "*SAVE PALSUB ";~mcode%;" ";~O%;" ";~exec%;" ";~load%
 1500 ENDPROC
 1510 :
 1520 DEFPROCall
 1530 DIM mcode% &100
 1540 clwyd%=1:cc500%=0:pmate%=0:chamel%=0:vnula%=0:PROCassem
 1550 OSCLI "SAVE PALSUBcl "+STR$~mcode%+" "+STR$~O%+" C03 C00"
 1560 clwyd%=0:cc500%=1:pmate%=0:chamel%=0:vnula%=0:PROCassem
 1570 OSCLI "SAVE PALSUBcc "+STR$~mcode%+" "+STR$~O%+" C03 C00"
 1580 clwyd%=0:cc500%=0:pmate%=1:chamel%=0:vnula%=0:PROCassem
 1590 OSCLI "SAVE PALSUBpm "+STR$~mcode%+" "+STR$~O%+" C03 C00"
 1600 clwyd%=0:cc500%=0:pmate%=0:chamel%=1:vnula%=0:PROCassem
 1610 OSCLI "SAVE PALSUBch "+STR$~mcode%+" "+STR$~O%+" C03 C00"
 1620 clwyd%=0:cc500%=0:pmate%=0:chamel%=0:vnula%=1:PROCassem
 1630 OSCLI "SAVE PALSUBvn "+STR$~mcode%+" "+STR$~O%+" C03 C00"
 1640 ENDPROC