For a game I am making, which uses interrupt-based 4-level greyscale, I am trying to superimpose a static effect onto the screen, using xor. However, Im at an impasse as to how to do this. I could use a pre-set xor value and apply the same effect to every byte on the front buffers, or use a few full-screen bitmaps and xor them to the front buffers. However, I wanted to avoid option 2 because I was aiming for a relatively small program, and I already have 2 full-screen images, greyscale. Not to mention a few sprites left to add.

The details on the static is this: it only occurs under two very specific circumstances, and the static is white. I can't give any more details without giving away the project (and I kind of want it to be a surprise). If you already know, sssh.

Anyone any ideas?
If you're running the game at 15MHz, you can insert a LFSR right into the 4 level grayscale routine.

8-bit LFSR:


16-bit LFSR:


Both are fairly fast and you can do whatever you want with the data it generates. Also, you can change the masks to something else to achieve "different" effects.


Code:

;16-stage Galois LFSR, taps set at (implied 16),14,13, and 11
;Cycles in the opposite direction, so the taps will be bits 1,2, and 4 (from zero)
;Returns: A=low byte of HL, HL= PR value.
;Interim state is kept inside routine via SMC.
 
lfsr16:
LFSR16_DATA .equ $+1
 ld hl,1
 ld a,L
 add hl,hl
 rla
 ld L,a
 rra      ;get the bit out
 ld a,0
 sbc a,0  ;set A to $FF if a 1 was shuffled out
LFSR16_MASK .equ $+1
 and %00010110
 xor L
 ld L,a
 ld (LFSR16_DATA),hl
 ret
 

;8-stage Galois LFSR, taps set at (implied 8),6,5, and 4
;C=spare register, A=result
;State of LSFR is kept inside as SMC'd value
;Can use any other register besides C as long as it's consistent.
lfsr8:
LFSR8_DATA .equ $+1
 ld c,1  ;initial value must be a nonzero number to be valid
 ld a,0  ;prepare A for "sign-extension"
 rrc c   ;rotate circ, with bit leaving also appearing in carry
 sbc a,0 ;which is then extended to $FF if carry had something in it
LFSR8_MASK .equ $+1
 and %01110000  ;and is then masked out to form our taps
 xor c   ;which is then used on our number.
 ld (LFSR8_DATA),a
 ret



I hope this helps!

EDIT: Remembered that I had another variation of a LFSR that I did for an older project, which uses a different (and probably much more optimum) method of generating "random" values.


Code:


lfsr16_2:
LFSR16_2_DATA .equ $+1
 ld hl,1
 ld a,h
 rlca
 rlca  ;comment out these two "rlca" instructions
 rlca  ;to generate the less randomish screenie
 xor h
 rlca
 adc hl,hl
 ld (LFSR16_2_DATA),hl
 ld a,L
 ret


Code modified from original to get it to look similar to the 16-bit test

Code originally found in the audio driver routine, used to generate this:
These are PERFECT!!

Numbering the images from top to bottom, I could probably use #2 or 3 for the game ending static, but for the in-game static it might need to be a bit... err..fainter.
The screenshots in the first post use monochrome images. If you want something a bit fainter, you can try to clear out the dark gray buffer and apply the LFSR to the light gray buffer.


EDIT:

Play around with the masks and see what you can come up with. Tho the results aren't static-y, they do make interesting effects.

Neglected to mention that while the first two screenshots were generated with a Galois LFSR, the latter two were generated with a Fibonacci LFSR. The masks in the latter routines are changed with the number of shifts you do, rather than an actual mask.
ah ok. I might use the 16-bit Galois FFSR bc the effect is closer to what I want to do. And for the lighter effect, do as you say.

Now, is there a way to basically set in the program whether to apply static, apply dark static, or apply light static, so that when the interrupt fires, it will do only what it is supposed to?

Edit: If the result of a conditional reveals that light static should be displayed, the define staticFunc is set to 1. If dark static, then its set to 2. If no static, then 0. Then the interrupt reads out the value of staticFunc
ACagliano wrote:
ah ok. I might use the 16-bit Galois FFSR bc the effect is closer to what I want to do. And for the lighter effect, do as you say.

Now, is there a way to basically set in the program whether to apply static, apply dark static, or apply light static, so that when the interrupt fires, it will do only what it is supposed to?


If the grayscale routine separates the current input bytes from the buffers into two different registers (like how E:SoR does), then doing this should be pretty trivial, with the only real variations being which byte goes where.

For light: LSFR -> light ; 0 -> dark
For dark: 0 -> light ; LFSR -> dark
For regular: LFSR -> light ; LFSR -> dark.

The actual logic on how to do it is up to you, tho if you want a hint or possible suggestions, here's a relevent snippet from E:SoR that does color layer effects, among other things, right in the LCD routine via jp (ix) and copying the routines to RAM:


Code:

DGC2MASK1  equ %10110110
DGC2MASK1E equ         %0110110111011011
DGC2MASK2  equ %01101101         
DGC2MASK2E equ         %1101101110110110
DGC2MASK3  equ %11011011         
DGC2MASK3E equ         %1011011001101101

DGC1INIT:
 bit dotilemap,(iy+sysflags)
 jp nz,DGC1TILE
 ld bc,DGC2MASK1+(256*64)      ;10 10
 ld hl,DGC2MASK1E              ;10 20
 jp DGC2CONT                   ;10 30

DGC2INIT:
 xor a
 ld hl,movetrack  ;10 42
 ld (hl),a
 inc (hl)         ;07 66
 ld L,a           ;04 70
 ld h,$8A         ;07 77
 ld a,(hl)        ;07 84
 ld L,$00         ;07 91
 rra \ rr L       ;12 103
 rra \ rr L       ;12 115
 or %11000000     ;07 122
 ld h,a           ;04 126
 ex de,hl         ;04 130
 ld bc,DGC2MASK2+(256*64)      ;10 10
 ld hl,DGC2MASK2E              ;10 20
 jp DGC2CONT                   ;10 30
 
DGC3INIT:
 ld hl,gamecount \ inc (hl)
 or a
 ld hl,movetrack  ;10 42
 ld a,(hl)        ;07 59
 inc (hl)         ;07 66
 ld L,a           ;04 70
 ld h,$8A         ;07 77
 ld a,(hl)        ;07 84
 ld L,$00         ;07 91
 rra \ rr L       ;12 103
 rra \ rr L       ;12 115
 or %11000000     ;07 122
 ld h,a           ;04 126
 ex de,hl         ;04 130
 ld bc,DGC2MASK3+(256*64)      ;10 10
 ld hl,DGC2MASK3E              ;10 20
 jp DGC2CONT                   ;10 30

DGC2CONT:
; xor a
; ld (moving),a ;dummied out for now
; ld (screenfx),a ;dummied for now
 push bc                       ;11 41
  exx  ;HL out of our way now. ;04 45
 
  ld a,(screenfx)              ;13 58
  add a,a  ;x2                 ;04 62
  ld L,a   ;x2sav              ;04 66
  add a,a  ;x4                 ;04 70
  add a,L  ;x6                 ;04 74
  ld hl,ScrnFXTbl01            ;10 84
  ld c,a                       ;04 88
  ld b,0                       ;07 95
  add hl,bc                    ;11 106
  push hl  ;save 1st copy loc  ;11 117
   ld a,(myflags+travelflags)  ;13 130
   rlca                        ;04 134
   and %00000100 ;airshipflag  ;07 141
   ld L,a                      ;04 145
   ex af,af'                   ;04 149
   ld a,$80                    ;07 156
   out (10h),a                 ;11 167
   ex af,af'                   ;04 4
   ld a,(movedir)              ;13 17
   add a,L                     ;04 21
   ld L,a  ;x1sav              ;04 29
   add a,a ;x2                 ;04 25
   add a,a ;x4                 ;04 33
   add a,L ;x5                 ;04 37
   ld c,a                      ;04 41
   ld hl,ScrnFXTbl03           ;10 51
   add hl,bc                   ;11 62
   ex (sp),hl ;1st copy loc    ;11 73
   ld bc,6                     ;10 83
   ld de,ramseg4               ;10 93
   ldir                        ;.. OVER
   ld hl,ScrnFXTbl02
   ld bc,5
   ldir
  pop hl  ;holds ScrnFXTbl3+nn
  ld bc,5
  ldir
  ld bc,6
  ld hl,ScrnFXTbl04
  ldir
 pop bc
 ld a,$20           
 ld hl,$8000       
 ld ix,ramseg4
;HL=bufferaddress DE=temp B=loopcount C=temp
;HL'=mask C'=mask B'=unused DE'=(when rotating) pointer to tiles to rotate
DGC2ML:
 out (10h),a      ;11 11
 ex af,af'        ;04 15
DGC21L:           ;--
 ld e,(hl)        ;07 07  22
 inc L            ;04 11  26
 ld d,(hl)        ;07 18  33
 inc HL           ;06 24  39
 jp (ix)          ;08 32  47
DGC2ILB:          ;94 126 141
 ld a,c           ;04 130 145
 xor e            ;04 134 149
 and d            ;04 138 153
 xor e            ;04 142 157
 out (11h),a      ;11 153 168
 djnz DGC21L      ;13 166 24
 exx              ;04 28
 ex de,hl         ;04 32
 ld hl,movetrack  ;10 42
 ld a,(hl)        ;07 59
 inc (hl)         ;07 66
 ld L,a           ;04 70
 ld h,$8A         ;07 77
 ld a,(hl)        ;07 84
 ld L,$00         ;07 91
 rra \ rr L       ;12 103
 rra \ rr L       ;12 115
 or %11000000     ;07 122
 ld h,a           ;04 126
 ex de,hl         ;04 130
 ld a,c           ;04 134
 ld c,l           ;04 138
 ld l,h           ;04 142
 ld h,a           ;04 146
 exx              ;04 150
 ex af,af'        ;04 154
 inc a            ;04 158
 ld b,64          ;07 165
 cp $20+12        ;07 172
 jr nz,DGC2ML     ;12 184
 ld hl,movetrack
 dec (hl)
 ret 


ScrnFXTbl01:  ;routinejump, effects.
;E -> C dg
;D -> E lg
;[0] None        [1] 1Light       [2] 2Light       [3] 3Light       [4] 1Dark       
;[5] 2Dark       [6] 3Dark        [7] InvertAll    [8] InvertGrey   [9] DivCol 
;[A] MonoChrome  [B] UnknownSwap 
;EFFECT none
 ld c,e \ ld e,d \ nop
 nop    \ nop    \ nop
;EFFECT one lighter
 ld a,e \ and d  \ ld c,a
 xor e  \ ld e,a \ nop
;EFFECT two lighter
 ld a,e \ and d  \ ld e,a
 xor a  \ ld c,a \ nop   
;EFFECT all lighter
 xor a  \ ld c,a \ ld e,a
 nop    \ nop    \ nop
;EFFECT one darker
 ld a,e \ or d   \ ld c,a
 xor e  \ cpl    \ ld e,a
;EFFECT two darker
 ld a,e \ or d   \ ld e,a
 cpl    \ or e   \ ld c,a
;EFFECT all darker
 xor a  \ cpl    \ ld c,a
 ld e,a \ nop    \ nop
;EFFECT invert all
 ld a,e \ cpl    \ ld c,a
 ld a,d \ cpl    \ ld e,a
;EFFECT invert gray
 ld c,d \ nop    \ nop
 nop    \ nop    \ nop
;EFFECT diverge
 ld c,e \ ld a,e \ cpl
 ld e,a \ nop    \ nop
;EFFECT monocrhome
 ld c,e \ nop    \ nop
 nop    \ nop    \ nop
;EFFECT unkown
 ld c,d \ ld a,d \ cpl
 ld e,a \ nop    \ nop

ScrnFXTbl02:  ;5 bytes
 exx
 ld a,h
 ld h,c
 ld c,L
 ld L,a
ScrnFXTbl03:  ;entries are 5 bytes wide. Each takes 28ccs.
 inc sp    \ dec sp \ inc sp \ dec sp    \ nop
 ld a,(de) \ rlca   \ nop    \ ld (de),a \ inc de
 ld a,(de) \ rrca   \ nop    \ ld (de),a \ inc de
 inc sp    \ dec sp \ inc sp \ dec sp    \ nop
 inc sp    \ dec sp \ inc sp \ dec sp    \ nop
 ld a,(de) \ rlca   \ rlca   \ ld (de),a \ inc de
 ld a,(de) \ rrca   \ rrca   \ ld (de),a \ inc de
 inc sp    \ dec sp \ inc sp \ dec sp    \ nop

ScrnFXTbl04: ;6 bytes
 ld a,c
 exx
 ld d,a
 jp DGC2ILB



Important note: Do NOT attempt to use this routine verbatim. It does things only insane people do under conditions that only insane people would run it under.
Fair enough. Hey, talked to Sorunome. The greyscale I use is actually the one you helped him with. That's portable to this, right?
ACagliano wrote:
Fair enough. Hey, talked to Sorunome. The greyscale I use is actually the one you helped him with. That's portable to this, right?


The code I used in E:SoR is not portable anywhere in any form. You shouldn't even try to use it. I posted it to demonstrate that you can call a different piece of code by use of jp (ix) to change what sort of transform you do between data retrieval from the grayscale buffer and output to the screen.

The exercise of writing or finding a suitable 4 level grayscale routine, then modifying the routine is up to you.
Iambian wrote:
ACagliano wrote:
Fair enough. Hey, talked to Sorunome. The greyscale I use is actually the one you helped him with. That's portable to this, right?


The code I used in E:SoR is not portable anywhere in any form. You shouldn't even try to use it. I posted it to demonstrate that you can call a different piece of code by use of jp (ix) to change what sort of transform you do between data retrieval from the grayscale buffer and output to the screen.

The exercise of writing or finding a suitable 4 level grayscale routine, then modifying the routine is up to you.


Let me rephrase. The 4-layer greyscale Sorunome uses (which I can inbox to you for reference, if you like). Would it be trivial to modify that to add this static effect?
bump:

Here's a paste-bin of the greyscale interrupt routine.
http://pastebin.com/KXFUi8Ux#

I'm wondering where in that would the LSFR be inserted? Right at the beginning, after Disp4Lvl? And what buffer does that interact with? How would you change that?


Edit: Wait, geekboy helped me understand. That 16-bit LSFR routine generates a random mask. I then go into the greyscale routine and xor the mask not onto the buffers, but directly onto the byte that is being written to the LCD port. And (not sure how to do this bit), but for the darker static, apply the mask to where it writes from the dark grey buffer. For lighter, do it where it writes from the light grey buffer. For no static, just don't xor it.
Right. That code as it stands won't run at 15MHz. You'll need to add in a bunch of delay cycles between writes. At 6MHz, adding in the LFSR will effectively double the amount of time the routine needs to render to the screen. If you still want to do it at 6MHz, you can (probably?) do it this way:


Code:
;Just set IX prior to entry to the address of the extra routines you want to use,
;or __Disp4LvlJumpSkip if you don't want to use any of them.
;
;relevant part of the gs routine
__Disp4LvlLoop:
        ex    af,af'
        rra
        ld    c,a
        ex    af,af'
        jp (ix)      ;these two lines were added.
__Disp4LvlJumpSkip:  ;This label is used to reset routine to default operation
        ld    a,(de)
        xor   (hl)
        and   c
        xor   (hl)
        inc   de
        inc   hl
        out   ($11),a                ;71cc into, 77cc loop
__Disp4LvlLoopSkip:  ;this line added for jumpback
        djnz  __Disp4LvlLoop



;extra routines:
__Disp4LvlDEBufferStatic:
        push hl
          call lfsr16
        pop hl
        xor   (hl)
        and   c
        xor   (hl)
        inc   de
        inc   hl
        out   ($11),a
        jp __Disp4LvlLoopSkip

__Disp4LvlHLBufferStatic:
        ld a,c
        cpl
        ld c,a  ;invert mask then invert buffers
        ex de,hl
        push hl
          call lfsr16
        pop hl
        xor   (hl)
        and   c
        xor   (hl)
        inc   de
        inc   hl
        out   ($11),a
        ex de,hl
        jp __Disp4LvlLoopSkip
       
__Disp4LvlAllBufferStatic:
        push hl
          call lfsr16
          ld c,h      ;Remove this line if not staticy enough
        pop hl
        inc hl
        inc de
        out ($11),a
        jp __Disp4LvlLoopSkip
what about this bit:


Code:

__Disp4LvlDone:
   ld    a,$05
   out   ($10),a           ;73cc into
   ret


That still go after the djnz __Disp4LvlLoop ?
ACagliano wrote:
what about this bit:


Code:

__Disp4LvlDone:
   ld    a,$05
   out   ($10),a           ;73cc into
   ret


That still go after the djnz __Disp4LvlLoop ?


Aren't you missing this bit too?

Code:
        djnz  __Disp4LvlLoop
        inc   bc                    ;waste
        ex    af,af'
        rra
        ex    af,af'
        pop   af
        inc   a
        bit   6,a
        jr    z,__Disp4LvlEntry
__Disp4LvlDone:
        ld    a,$05
        out   ($10),a                ;73cc into
        ret


I didn't put that down because it wasn't relevant to what's being changed, but is understood to be there because it's relevant to the overall code.
Yeah, thats what I meant. Well, that completes this. Now... one more thing....and then its done... \m/
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement