Plasma Squares

The place for codemasters or beginners to talk about programming any language for the Spectrum.
Post Reply
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Plasma Squares

Post by arkannoyed »

Having a little 'holiday' from Chess madness!

So I'm revisiting some of my old projects to have a play and see if they can be shrunk a bit and maybe improved.

This one was posted on WOS in 2017 I think originally. Its a square reveal screen fade-in (for want of a catchier name!) that uses a 192 byte plasma field to take a screen stored in a buffer and send it to the display in an interesting way thus;

Image

Many variations upon the exact pattern for how its revealed are possible just by manipulating the plasma data. Imagine the screen loading into the buffer, then call this routine to show it before then loading the code part for example.

Anyway, having played about with it a bit I've reduced the size to 68 bytes for the routine.

some of you might find a use for it perhaps. Source, commented as best I could here;

Screen stored at 49152
Plasma can be anywhere as long as its aligned to end on a 256 byte boundary, so 5b40, fa40 etc
or in reverse if you change the INC L to DEC L at the end of the routine.

As long as the plasma has good separation and has no more than about 20 active squares at any one frame, then it'll give a good smooth performance

The routine needs to be repeatedly CALLed, so could be run on interrupts or along with something else. Don't let it run on too far past the screen being fully displayed, or it will give odd effects as it tries to print it again.

Code: Select all

entry:
          ld de,0d820h    ;ATTRs start + 1 line (20h)
          ld hl,0bf40h    ;plasma table of 192 bytes address
mlp0:
          ld a,(hl)       ;get plasma cell byte
          inc (hl)        ;INC value in the plasma table
          and 0f8h        ;only the 0-7 portion on the plasma byte controls the fade-in
          jr nz,nxt_block ;if not 0-7 then skip to next

          push hl         ;save the plasma table address

          ld b,(hl)       ;counter in B
          ld h,a          ;H=00
mask_l:
          inc a           ;set bit 0,A
          rrca            ;rotate into bit 7
          rl h            ;x2 +1
          djnz mask_l     ;loop

          ld b,h          ;B=left hand mask, copied to H as a counter/ map
          ld c,a          ;C=right hand mask

a2s_addr:
          ld a,d          ;use D to create the SCReen address Hi-byte from the ATTRs Hi byte
          add a,a         ;x2
          add a,a         ;x4
          add a,a         ;x8
          ld l,a          ;and put into L

          push de         ;save ATTRs address
a2s_a:
          ld a,(de)       ;get byte from SCReen buffer
a2s_b:
          res 7,d         ;remove 80h from D to point to actual SCReen
          ld (de),a       ;place byte
a2s_c:
          ld d,l          ;make DE buffer address
          inc l           ;next line down
mlp1:
          ld a,(de)       ;get SCReen buffer byte
          and b           ;mask
          srl h           ;uses mask bytes as a map of which lines to mask or ignore
          jr c,a2s_b      ;if a Carry occurs, then write a byte
nlu:
          jr nz,a2s_c     ;if no write, is the map=00 (finished)?
btm2top:
          pop de          ;ATTRs address restored into DE
          ld h,c          ;upper mask as counter map into H

          ld a,e          ;lo ATTRs byte
          res 5,e         ;RES to upper CHR line of the square
          cp e            ;test against A, is it the same or not?
          jr nz,a2s_addr  ;if not, then loop back to do the upper CHR square
left_swap:
          ld h,b          ;restore mask for lower into H
          ld b,c          ;swap masks (right into left)

          xor 21h         ;make the ATTRs address INC & lower CHR line
          ld e,a          ;
          rra             ;test BIT 0
          jr c,a2s_addr   ;if ='1' then loop again, if '0' then we're finished
                          ;the plasma 2x2 square
          pop hl          ;restore plasma address into HL
nxt_block:
          inc e           ;next right
          inc de          ;next right and take care of D if it needs to INC
          set 5,e
mlp3:
          inc l           ;next plasma byte
          jr nz,mlp0      ;repeat
          ret             ;
.TAP of the assembly
https://dl.dropbox.com/s/9u3ooxgvwzll8j ... 1.tap?dl=1

A couple of example Plasmas

https://dl.dropbox.com/s/eqlensqp5s520q ... t.bin?dl=1

https://dl.dropbox.com/s/4rov6rn923ti3n ... t.bin?dl=1
dfzx
Manic Miner
Posts: 673
Joined: Mon Nov 13, 2017 6:55 pm
Location: New Forest, UK
Contact:

Re: Plasma Squares

Post by dfzx »

I thing I always seem to need with the code you present is a description of how it works. I don't mean on a Z80 instruction level (the code is well commented) but more high level: how does that work?

The comments include references to a plasma table, masks, maps, and other stuff, but I have no clue how it fits together to produce the effect. My Z80 ASM is unlikely to ever be good enough for me to read the code and think "oh yeah, I see what he's doing".

Can you give a psuedo code style listing of what it's doing?
Derek Fountain, author of the ZX Spectrum C Programmer's Getting Started Guide and various open source games, hardware and other projects, including an IF1 and ZX Microdrive emulator.
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Plasma Squares

Post by arkannoyed »

At a very basic level;

the 192 bytes of the plasma table relate to 192 (2x2) blocks that the screen gets divided into (16 x 12)

Each plasma byte is checked and incremented upon each pass through the routine. Once the byte is within the range 00-07 then the square is 'active'.
Being active means that on a pixel level we display a series of concentrically sized squares as follows:

00 = 2x2 px
01 = 4x4 px
02 = 6x6 px
03 = 8x8 px
04 = 10x10 px
05 = 12x12 px
06 = 14x14 px
07 = 16x16 px (full square displayed)

If the plasma is outside that range then nothing happens with that square. As Yoda might say Do or Do Not?! :roll:

Each CALL to the routine lets it cycle through 192 bytes either updating the active squares or moving onto the next.

The routine uses no data for the masks and so creates them on the fly as and when they are needed per square. These are also used to determine which lines are printed. The square addressing is carefully done so that it always moves 2 character squares along or 2 down to find the next square position.

Its actually really simplistic, but with the right plasma table can give a very pleasing effect. SCREEN$ with lots of ATTRs, mainly Paper colours don't work well as a rule.

I do have a plasma creator in basic with some paramaters that can be fiddled with to give a wide range of results. I might try and do a super fast z80 version as it uses COS and SIN a lot and its painfully slow!
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Plasma Squares

Post by arkannoyed »

Another example, using one of RedBalloons Lovely creations For one of Einars Games (I think?)

Benefits from being mono and heavy on the pixels side of things.

Image
dfzx
Manic Miner
Posts: 673
Joined: Mon Nov 13, 2017 6:55 pm
Location: New Forest, UK
Contact:

Re: Plasma Squares

Post by dfzx »

arkannoyed wrote: Tue May 21, 2019 3:26 pm At a very basic level;
Yep, that's the one, thanks! :)

I like it, the technique's clever in its simplicity.

You're feeling pleased because you did something clever. I'm feeling pleased because I now kinda understand how you did it. So on our respective levels, we're both now happy. :lol:
Derek Fountain, author of the ZX Spectrum C Programmer's Getting Started Guide and various open source games, hardware and other projects, including an IF1 and ZX Microdrive emulator.
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Plasma Squares

Post by arkannoyed »

I'm also happy that my explanation managed to convey the mechanics of it in a clear enough way.

I'm trying to work on a Screen Clear version, but the attributes are making it look clumsy. I'm also planning the plasma creator and perhaps a version that creates plasma based upon some random values, then displays the screen using it, thus giving greater entropy or predictability.
User avatar
zxbruno
Manic Miner
Posts: 213
Joined: Sun Mar 04, 2018 6:13 am

Re: Plasma Squares

Post by zxbruno »

Speaking of machine code routines that display screens in an original way, have you ever thought of doing something with vectors? 33 years ago I saw a machine code routine that would process a black and white screen and turn it into vectors, which could then be redrawn at the fastest possible speed. When I think "vectors" on the Speccy adventure games come to mind right away. This machine code routine, however, drew complex pictures. All I remember is the "vectorizer" would erase lines while working, until the whole image disappeared.
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Plasma Squares

Post by arkannoyed »

Would be good to see an example of such a thing, though that sounds like a rather more complex animal than I'm used to producing.

Incidentally, I made a version of this one that works on character squares, 768 of them, but its crap! Its far too slow, even with unrolled loops. I've a little work still to do on it to try and optimise the hell out of it, but its far less impressive than its bigger squared cousin
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Plasma Squares

Post by arkannoyed »

This demonstrates the slow and clunky look of the character square version;

Image

I've just about optimized the core of it about as much as possible and its still a bit too pedestrian in my opinion
User avatar
Fahnn
Microbot
Posts: 135
Joined: Sun Jan 27, 2019 7:56 pm
Location: Redcar, UK
Contact:

Re: Plasma Squares

Post by Fahnn »

arkannoyed wrote: Fri May 24, 2019 9:03 amI've just about optimized the core of it about as much as possible and its still a bit too pedestrian in my opinion
I think it's just about the perfect speed, actually; it doesn't seem slow or clunky at all to me. Really nice effect!
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Plasma Squares

Post by arkannoyed »

Glad you like it, but I still think 50% faster would give a more fluid feel to it.

Still fiddling to try and squeeze more speed out of it though.
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Plasma Squares

Post by arkannoyed »

Ahhhhhh, now then, it works better when we reduce the separation span in the plasma data;

Image
User avatar
patters
Manic Miner
Posts: 467
Joined: Thu Apr 11, 2019 1:06 am

Re: Plasma Squares

Post by patters »

A bit off topic, but how did you make those GIFs? My own attempts using Fuse to record to an AVI and then convert always look a bit rubbish.
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Plasma Squares

Post by arkannoyed »

Well, I use Spectaculator generally, as I like it. But, that only saves rzx files. Spin however can save an animated gif. So, I make a snapshot in spectaculator, and load onto Spin. It does fail quite often, but if anyone’s a better solution then I’m all ears!
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Plasma Squares

Post by arkannoyed »

Well, I'm still not sure it looks fluid enough, but here it be anyway and at just 54 bytes;

Code: Select all

entry:
          ld de,0daffh    ;ATTRs in buffer end
          ld hl,plasma    ;plasma table of 768 bytes address
mlp0:
          ld a,(hl)       ;get plasma cell byte
          inc (hl)        ;INC value in the plasma table
          and 0fch        ;only the 0-3 portion on the plasma byte controls the fade-in
          jr nz,nxt_chr   ;if not 0-3 then skip to next

          push hl
          push de
          ld b,(hl)       ;counter in B
          ld c,10h        ;initialise C map / mask
mask_l:
          add a,a         ;shift left
          or c            ;overlay seed
          ld c,a          ;update seed
          rra             ;shift right
          or c            ;overlay seed
          ld c,a          ;update seed
          djnz mask_l     ;loop
          
          ld b,c          ;B=mask, C=map
a2s_addr:
          ld a,d          ;use D to create the SCReen address Hi-byte from the ATTRs Hi byte
          add a,a         ;x2
          add a,a         ;x4
          add a,a         ;x8
          ld l,a          ;and put into L
a2s_a:
          ld a,(de)       ;get ATTR byte
a2s_b:
          res 7,d         ;copy to SCReen
          ld (de),a       ;
a2s_c:
          ld d,l          ;point to SCReen info in buffer
          inc l           ;next line down
mlp1:
          ld a,(de)       ;get byte
          and b           ;mask
          srl c           ;check map
          jr c,a2s_b      ;if a Carry occurs then write the masked byte
          jr nz,a2s_c     ;if no Carry and the map is not yet 00 then loop
btm2top:
          pop de          ;ATTRs address restored into DE
          pop hl          ;restore plasma address into HL
nxt_chr:
          dec de          ;next CHR (ATTR)
mlp3:
          inc hl          ;next plasma byte
          bit 3,d         ;have we reached D7h yet?
          jr nz,mlp0      ;repeat
          ret             ;
                          ;54 bytes
Hopefully commented enough that it makes some sense. Still quietly working on a plasma creator, but if you want the version in BASIC thats painfully slow (thank heavens we can speed emulators up!) then let me know
User avatar
zxbruno
Manic Miner
Posts: 213
Joined: Sun Mar 04, 2018 6:13 am

Re: Plasma Squares

Post by zxbruno »

This is the type of effect that could make text adventures, and many games, a bit more interesting.
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Plasma Squares

Post by arkannoyed »

Yes, I agree. Simple screen fade-in/ out effects make the ordinary far more exciting to look at. Once I have a plasma generator working in z80 then it can generate its own random plasma for each time the effect needs to be used, which would look lovely! :P
Post Reply