Now up to this point we have the graphics card pretty much figured out. We have the framebuffer control on its fundamental levels where we can set palettes and viewports and their resolutions.
The next part of this puzzle though is how do we achieve animation? the weather icons used on the WS4000 had an animation to them where you can see the rain falling, such as:
How do we achieve this effect on the WS4000, and how did they do this originally?
Well, they use palette swapping trickery. Thing is, you can upload a palette to the RAMDAC as we explained in an earlier post, and you can rotate colors around on the index to do this.
BUT. the WS4000 actually offers a method to do this on its own, which is identified by this function from ROM that I had documented here:
code:00000776 CHECK_FOR_ANIMATE: ; CODE XREF: code:0000111Cp
code:00000776 ; code:0000113Fp ...
code:00000776 mov A, RAM_39
code:00000778 jz code_782
code:0000077A mov DPTR, #0x601
code:0000077D clr A
code:0000077E movx @DPTR, A
code:0000077F lcall Animate_Palette
code:00000782
code:00000782 code_782: ; CODE XREF: CHECK_FOR_ANIMATE+2j
code:00000782 lcall code_734
code:00000785 ret
code:00000785 ; End of function CHECK_FOR_ANIMATE
code:00000785
code:00000786
code:00000786 ; =============== S U B R O U T I N E =======================================
code:00000786
code:00000786
code:00000786 Animate_Palette: ; CODE XREF: CHECK_FOR_ANIMATE+9p
code:00000786 ; Animate_Palettej ...
code:00000786 jb RAM_20.3, Animate_Palette ; Wait for previous operations to clear
code:00000789 mov R7, RAM_39 ; How many color blocks to copy
code:0000078B mov R0, #0x35 ; '5' ; Beginning location for RAMDAC Palette Addresses
code:0000078D
code:0000078D code_78D: ; CODE XREF: Animate_Palette+4Ej
code:0000078D mov DPTR, #0x601 ; Location Pointer to Palette Table
code:00000790 movx A, @DPTR
code:00000791 mov R1, A ; Store Value at RAM 0x0601 into R1
code:00000792 mov A, @R0
code:00000793 mov P2, #0x80 ; 'Ç' ; Set Palette Write Address
code:00000796 movx @R0, A ; Store Value in I-RAM 0x35 as RAMDAC Palette Address
code:00000797 mov P2, #0x88 ; 'ê' ; Set RAMDAC to Palette Memory
code:0000079A mov A, #7
code:0000079C clr C
code:0000079D subb A, R1 ; Subtract 7 from the contents in 0x0601
code:0000079E mov R2, A ; Store Result into R2
code:0000079F mov A, @R0 ; Read Palette Address from I-RAM 0x35
code:000007A0 add A, R1 ; Add Current 0x0601 Value to RAMDAC Palette Address
code:000007A1 mov B, #3 ; B Register
code:000007A4 mul AB ; Multiply Added Palette Address with 3. A contains Low byte, B contains High Byte Result
code:000007A5 mov DPL, A ; Data Pointer, Low Byte
code:000007A7 mov A, B ; B Register
code:000007A9 add A, #0 ; Store 16-bit Multiply Result into Data Pointer.
code:000007AB mov DPH, A ; Data Pointer, High Byte
code:000007AD
code:000007AD code_7AD: ; CODE XREF: Animate_Palette+30j
code:000007AD movx A, @DPTR ; Read Red Value from RAM @DPTR
code:000007AE inc DPTR ; Advance to Next Value (Green)
code:000007AF movx @R0, A ; Write Red Value to RAMDAC Palette
code:000007B0 movx A, @DPTR ; Read Green Value from RAM @DPTR
code:000007B1 inc DPTR ; Advance to Next Value (Blue)
code:000007B2 movx @R0, A ; Write Green into RAMDAC Palette
code:000007B3 movx A, @DPTR ; Read Blue Value from RAM @DPTR
code:000007B4 inc DPTR ; Advance to Next Value (Red)
code:000007B5 movx @R0, A ; Write Blue into RAMDAC Palette
code:000007B6 djnz R2, code_7AD ; Decrement R2, Repeat Palette Write until 0
code:000007B8 mov A, R1
code:000007B9 jz code_7D3
code:000007BB mov A, @R0
code:000007BC mov B, #3 ; B Register
code:000007BF mul AB
code:000007C0 mov DPL, A ; Data Pointer, Low Byte
code:000007C2 mov A, B ; B Register
code:000007C4 add A, #0
code:000007C6 mov DPH, A ; Data Pointer, High Byte
code:000007C8
code:000007C8 code_7C8: ; CODE XREF: Animate_Palette+4Bj
code:000007C8 movx A, @DPTR
code:000007C9 inc DPTR
code:000007CA movx @R0, A
code:000007CB movx A, @DPTR
code:000007CC inc DPTR
code:000007CD movx @R0, A
code:000007CE movx A, @DPTR
code:000007CF inc DPTR
code:000007D0 movx @R0, A
code:000007D1 djnz R1, code_7C8
code:000007D3
code:000007D3 code_7D3: ; CODE XREF: Animate_Palette+33j
code:000007D3 inc R0
code:000007D4 djnz R7, code_78D
code:000007D6 mov DPTR, #0x601
code:000007D9 movx A, @DPTR
code:000007DA inc A
code:000007DB cjne A, #7, code_7DF
code:000007DE clr A
code:000007DF
code:000007DF code_7DF: ; CODE XREF: Animate_Palette+55j
code:000007DF movx @DPTR, A
code:000007E0 ret
code:000007E0 ; End of function Animate_Palette
As we can see, this function is built into ROM. and within the CMD01, it looks for the number of blocks of 7 colors in the palette to rotate. So you would send the speed at which the palette swapping occurs, and then you send each index number which includes the 7 colors that will swap around.
Like so:
//Set up Animating Palette.
GPUFIFO = 3; //Number of Color Blocks to Animate
GPUFIFO = 0xC0; //Target Slot on Palette (In groups of 7 Colors)
GPUFIFO = 0xC7; //Target Slot on Palette (In groups of 7 Colors)
GPUFIFO = 0xCE; //Target Slot on Palette (In groups of 7 Colors)
GPUFIFO = 8; //Number of NTSC Frames per Step.
This breaks down in detail how this works with the WS4000. you send the number of color blocks to rotate, the index of the beginning of the first of 7 colors in the palette, for each block. And then the speed in NTSC fields.
So the color palette would look something like this:
This would be your rain colors! the pointer to this block would be on the left of the group of colors here, and it will rotate one at a time, that entire block of 7 colors, but not touch the 8th color on the right side.
this one was palette swapping too :-)
Now, we have animation down, we need to take a look at how to run the hardware overall as a whole. The graphics card has been entirely figured out for the critical stuff...
Time to look at the I/O card.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.