%begin
%include "pr:ng"

%const %integer MaxCM = 7
%record %format Ct (%half %array M (0:255))
%record (Ct) %array CMA (0:MaxCM)
%record (Ct) %name CMAp
%half %array %name CMp (0:255)
%half %integer %name CM
%integer NumCM = 0, CurCM = 0
%integer i,j,k
%string (30) IFile, OFile, As, Bs
%byte Restore

%const %integer MY = 50, BY = 150, GY = 250, RY = 350, XBase = 100,
                Ht = 32, Maps = 3

%integer X, Y, Val

%half %array CMs (0:7)
%const %half %array Basic8 (0:7) = 0,31,31<<5,31<<5+31,31<<10,31<<10+31,
                                   31<<10+31<<5,31<<10+31<<5+31

%const %integer %array YBase (1:4) = RY, GY, MY, BY
%const %integer %array YShift(1:4) = 0, 5, 0, 10

%routine Bars (%integer Type, Lo, Hi)
   Y = YBase(Type)+4
   Val = Yshift (Type)
   Colour (Black)
   X = XBase+4
   Fill (X+Lo<<1, Y, X+2+Hi<<1, Y+Ht)
   Colour (Type)
   Fill (X+i<<1, Y, X+2+i<<1, Y+(CMp(i)>>Val)&31) %for i = Lo,1,Hi
%end

%routine Draw Map (%integer Type)
%integer i
   Colour (White)
   Y = YBase (Type)
   Fill (XBase, Y, XBase+520, Y+8+Ht)
   Colour (Black)
   Fill (XBase+2, Y+2, XBase+518, Y+6+Ht)
   %if Y = MY %start
      %for i = 0,1,255 %cycle
         Colour (i)
         Fill (XBase+4+i<<1, Y+4, XBase+6+i<<1, Y+4+Ht)
      %repeat
   %else
      Bars (Type, 0, 255)
   %finish
%end

%routine Save8
   %for i = 0,1,7 %cycle
      CMs(i) = Cmp(i)
      CMp(i) = Basic8(i)
      Colour Map (i) = CMp(i)
   %repeat
%end

%routine Restore8
   CMp(i) = CMs(i) %and Colour Map (i) = CMp(i) %for i = 0,1,7
%end

%routine PrintShort (%short P)
   PrintSymbol ((P >> 8) & 16_FF)
   PrintSymbol (P & 16_FF)
%end

%shortfn Get Short
%byte a,b
   Read Symbol (a); Read Symbol (b)
   %result = a<<8 ! b
%end

%routine Load Map
%integer Lo = 0, Hi = 255
   %return %if NumCM = MaxCM
   Prompt ("IFile : "); Read (IFile)
   %if Ifile -> As.(".").Bs %then IFile = As.".".Bs %else IFile = Ifile.".Map"
   NumCM = NumCM + 1
   CurCM = NumCM
   CMp == CMA(NumCM)_M
   Open Input (3,IFile)
   Select Input (3)
   %for i = Lo,1,Hi %cycle
      Get Short(CMp(i))
      Bars (Red, i, i)
      Bars (Green, i, i)
      Bars (Blue, i, i)
      Colour Map (i) = CMp(i) %if Restore = 8 %or i > 7
      CMs(i) = Cmp(i) %if i < 8 %and Restore = 0
   %repeat
   Close Input
   Select Input (0)
%end

%routine Save Map
   Prompt ("OFile : "); Read (OFile)
   %if OFile -> As.(".").Bs %then OFile = As.".".Bs %else OFile = OFile.".Map"
   Open Output (3,OFile)
   Select Output (3)
   %if Restore = 0 %start
      Print Short (CMs(i)) %for i = 0,1,7
   %else
      Print Short (CMp(i)) %for i = 0,1,7
   %finish
   Print Short (CMp(i)) %for i = 8,1,255
   Close Output
   Select Output (0)
   Newline; PrintString ("Finished");Newline
%end

%routine Mix CM (%integer C, %integer R, G, B)
   CMp (C)=(R+G<<5+B<<10) & 16_FFFF
%end

%integer %function Fun(%integer x)
   x = 31-x&31
   x = x*x
   x = (x//45)&31
   %result = 31-x
%end

%routine Update (%half %array %name CMp (0:255))
   CM == Cmp(0)
   Update Colour Map (Cm)
%end

%routine Init
   CMp(0) = 0
   Mix CM (i,Fun(31-i&31),Fun(i&31),0) %for i = 1,1,31
   Mix CM (i,0,Fun(31-i&31),Fun(i&31)) %for i = 32,1,63
   Mix CM (i,Fun(i&31),0,Fun(31-i&31)) %for i = 64,1,95

   Mix CM (i,Fun(31-i&31),Fun(i&31),0) %for i = 96,1,127
   Mix CM (i,0,Fun(31-i&31),Fun(i&31)) %for i = 128,1,159
   Mix CM (i,Fun(i&31),0,Fun(31-i&31)) %for i = 160,1,191

   Mix CM (i,Fun(31-i&31),Fun(i&31),0) %for i = 192,1,223
   Mix CM (i,0,Fun(31-i&31),Fun(i&31)) %for i = 224,1,255
%end

%integer %array R,G,B,Map(1:2)
%integer Inc, Fix = 1
%real dR, dG, dB, RR, GG, BB
%integer MapDist
%const %string (1) %array F (1:2) = "1", "2"

%routine Change Band
   %if i = 's' %start
      Map(1) = Map(2)
      R(1) = R(2)
      B(1) = B(2)
      G(1) = G(2)
      Fix = 2
      PrintString ("Map 1 is now [");Write(Map(1),0)
      PrintSymbol(',');Write(R(1),0)
      PrintSymbol(',');Write(G(1),0)
      PrintSymbol(',');Write(B(1),0)
      PrintSymbol(']');Newline
   %finish
   Prompt ("Map ".F(Fix)." Number : ");Read(Map(Fix))
   Prompt ("Point ".F(Fix)." - R : ");Read(R(Fix))
   Prompt ("Point ".F(Fix)." - G : ");Read(G(Fix))
   Prompt ("Point ".F(Fix)." - B : ");Read(B(Fix))
   Mix CM (Map(Fix),R(Fix),G(Fix),B(Fix))
   Fix = 2 %and %return %if Fix = 1
   
   MapDist = Map(2) - Map(1)
   dR = (R(2)-R(1))/MapDist
   dG = (G(2)-G(1))/MapDist
   dB = (B(2)-B(1))/MapDist
   RR = R(1); GG = G(1); BB = B(1)
   Inc = 1; %if MapDist < 0 %then Inc = -1
   %for i = Map(1),Inc,Map(2) %cycle
      Mix CM (i,Int(RR),Int(GG),Int(BB))
      Bars (Red,i,i); Bars (Blue,i,i); Bars (Green,i,i)
      RR = RR + dR; GG = GG + dG; BB = BB + dB
      Colour Map (i) = CMp (i)
   %repeat
   Fix = 1
%end

%routine Show Val
   Prompt ("Map : ");Read(i)
   j = CMp(i)
   PrintSymbol('[');Write(i,0)
   PrintSymbol(',');Write(j&31,0)
   PrintSymbol(',');Write((j>>5)&31,0)
   PrintSymbol(',');Write((j>>10)&31,0)
   PrintSymbol(']');Newline
%end

%routine ClearMap
   CMp(i) = 0 %for i = Restore,1,255
   Update (CMp)
   Draw Map (j) %for j = 1,1,4
%end

Setup
Clear
CMp == CMA(0)_M
Init
Update (CMp)
Draw Map (j) %for j = 1,1,4
Restore = 8
%cycle
   i = Testsymbol %until i = -1
   i = Testsymbol %until i # -1
   %if i = 'r' %start
      Restore = 8 - Restore
      %if Restore = 0 %then Save8 %else Restore8
   %finish
   Load Map %if i = 'l'
   Save Map %if i = 'm'
   ClearMap %if i = 'c'
   Change Band %if i = 'f' %or i = 's'
   Show Val %if i = 'q'
   Fix = 1 %if i = 'k'
   %exit %if i = 'x'
%repeat

%endofprogram
