It was part of an investigation into using a plasma based table for displaying the picture. We've all been wowed by Demos that do fancy plasma effects, so I though I would do something more useable with it. You can load a screen, then reveal it before you load the next block for example. Many other possibilities I'm sure too. If of interest to anyone, I'll tidy up the source and post it. Its 151 bytes for the routine and 192 for the Plasma.
It actually only does 1 frame per call, so you can use it along side something else, like a scroller or music I suppose
I'm sure it could be written more efficiently and shorter though.
Wonderful. A little extravagant, so should be used sparingly, but entirely impressive.
Yes maybe, but extravagance when done in not too many bytes just gives a nice finishing touch to games etc.
I'm rather appalled at how horribly I wrote it, so I'm just doing a re-write to its less embarassing! :))
I'm rather appalled at how horribly I wrote it, so I'm just doing a re-write so it’s less embarrassing!
Preach, brother! I just knocked five bytes off of my fade-to-black routine and sped it up quite a bit. Feel so silly about not seeing how unnecessary those five bytes were to begin with. But that’s (good) coding practice for you—do a rough proof-of-concept draft, then tune it to perfection.
Every man should plant a tree, build a house, and write a ZX Spectrum game.
Indeed. So many times you come back to an old project, and after re-figuring out how it works because you commented the original source so sparsely that even the Speccys struggling to keep up, you see things that just didn't occur to you at the time. I've re-written stuff I though was might clever and really short and ended up saving massive chunks.
Viewing it from a PC it seems to run a little fast, almost too fast to really appreciate the way it reveals. On a real or emulated Spectrum perhaps the pace is slower?
It is quite fast, but as I mentioned, it runs on repeated CALLs. So if you CALL the routine it only updates by one frame before RETurning. A full cycle to reveal the screen can be anywhere from 7-255, so you can either pause between frames a little to slow it down, or alter the plasma to make the reveal happen over a longer period.
basically the way plasma works, well in this case anyway, is that 1 frame decreases each byte of the plasma table by 1 Then it checks if that byte falls into the area in which it can start to reveal what occupies that 2x2 character square. Have I lost anyone yet?
There are 7 square masks from full 16 x 16 to only 2x2 pixels. Once a plasma byte is within the 00-07 range then it prints the corresponding square masked portion of the screen, 07 being the smallest, 00 the full monty!
The plasma can be quite difficult to code to make it flow nicely. There is a Sinus calc to do this, which I found somewhere years ago. Once you have your plasma table, its cyclically updated all relative to one another, so it doesn't get destroyed, but might need positioning correctly for displaying the screen again. You could of course just have multiple tables to display it differently each time with some simple random number generation to select the plasma pattern. Or if the table calc could be coded into Z80 simply enough then while the screen is displayed, it could make a new plasma table, then fade out, which of course is also possible too with a little alteration.
I've found a few neat tricks to speed it up and make it smaller, so I'm re-writing it at the moment.
I'll try and make it easier to use and understand, so it might be a useful addition to a game or loader for someone.
These are the type of things that I wrote before attempting games.
They helped with learning the way the screen and attributes were layered and tricks that could be used.
They have been lost to time, were my first attempts at real code and very nasty in the way they were written.
I've been playing around with lots of multicolour effects (NIRVANA etc) recently. I fancy looking at a multicolour version of plasma! One that leaves the pixels alone but does something interesting with the 8x2 attributes.
It is quite fast, but as I mentioned, it runs on repeated CALLs. So if you CALL the routine it only updates by one frame before RETurning. A full cycle to reveal the screen can be anywhere from 7-255, so you can either pause between frames a little to slow it down, or alter the plasma to make the reveal happen over a longer period.
I love this way of working. You can do a bunch of highly extravagant things, all apparently at once, just by spreading it all out in the time domain!
Nice work Arkannoyed!!!... Im likewise looking forward to seeing the sources for this one... Could be used for some interesting full screen explosion type effects, perhaps... ?... :)
Looks less impressive slowed down doesn't it!? That does illustrate the mechanics of the effect well though.
Re-writing is going ok, though I've hit a wall where something isn't right and I can't figure out what. I need that moment of inspiration, the lightbulb above the head, to get it fixed. Hopefully now though under 130 bytes, and moderately more efficiently coded!
I think his 'Save' comments actually mean 'Restore', but I get the gist.
He's got two parameters that he increases at different rates as he steps across the X-direction, and then resets them and steps two other parameters with each step in the Y-direction. And he uses those parameters to index into a Cosine table and adds up the four results, translating them into a colour.
Then after each frame he goes back to the initial values and tweaks them a bit, then starts again.
So really he's got two Sine / Cosine wave functions running in each of the X and Y directions, and combining them to make a colour contour map.
I thought there were more shortcuts to it than that though. I guess you could do the X-lookups first then the Y-lookups to make two 1D lists, then combine them to do the 2D X/Y plot..? That sounds too easy to me, but I can't see why it wouldn't work..?
Ok, basically plasma in this case works like this;
we have a routine that treats the screen as if it were 16 wide x 12 high squares. That gives 192 bytes with values of 00-ff (0-255). What we do is make things happen when those corresponding bytes fall within a particular range, in this instance, 00-07, which correspond to the 8 square masks.
On each call to the routine we increase each of the 192 bytes by 1, checking each in turn for its value and whether that indicates that we need to 'do' something. If it falls outside the 'active' range, then we just go to the next and repeat until all 192 are done.
So as you can see, with all the bytes in that 192 starting with different values, we get patterns emerging. A little demonstration below shows the plasma as a simple increasing number pattern with 00 as the first byte all the way up to 191 as the last (192nd). The resulting reveal pattern is obvious! Actually, we have to reverse the order of the numbers and they need to Descend, but you get the idea hopefully.
This is actually the fresh n' newly re-written version in action too, currently at 130 bytes, but that might slim down by a few more as usually happens. Just cleaning up the source too white I'm at it.
That's clear - I meant, how you generate and animate plasmas in the first place! But I think I get it now. You're just using one static frame of a plasma screen to give you the starting values for each cell of your effect.
You could simply do X+Y+N-28 for each cell and as N increases the cells go through 0..7 in a diagonal sweep. But with your method you get to make more interesting patterns. Although with only 192 squares I'd probably just program the starting numbers in by hand.
What would be cool is if you keep running the plasma effect so it's moving in waves AND add on a gradual offset, so the squares actually pulse in and out a bit before settling down. Have you tried that??? :!!
Ok, here it is then, at 130 bytes for now along with some example Plasma to get going with;
;square fade in
;using a plasma table
;fade in the screen display file
;
;plasma map at 0f940h but can be altered or moved elsewhere
;stored picture must reside at 0c000h - 49152
;
;CALL the set_up routine first
;Thereafter repeatedly CALL the entry point further in
;set_up: FA10h - RAND USR 64016
;entry : FA1Ch - RAND USR 64028
;
;JES Unknown - Nov 2017
;
org 0f940h
db 14h,14h,16h,19h,1dh,20h,23h,24h,24h,22h,1eh,19h,12h,0ah,09h,08h
db 1ch,1dh,1fh,22h,25h,29h,2bh,2dh,2dh,2bh,27h,21h,1ah,13h,0ch,09h
db 24h,24h,26h,29h,2dh,30h,33h,35h,35h,33h,2fh,29h,22h,1bh,13h,0dh
db 2ah,2bh,2dh,30h,34h,37h,3ah,3bh,3bh,39h,35h,30h,29h,21h,1ah,13h
db 30h,30h,32h,35h,39h,3ch,3fh,40h,40h,3eh,3ah,35h,2eh,26h,1fh,19h
db 33h,33h,35h,38h,3ch,3fh,42h,43h,43h,41h,3dh,38h,31h,2ah,22h,1ch
db 33h,34h,36h,39h,3dh,40h,43h,44h,44h,42h,3eh,39h,32h,2ah,23h,1dh
db 32h,33h,35h,38h,3bh,3fh,41h,43h,43h,41h,3dh,37h,31h,29h,22h,1bh
db 2fh,2fh,31h,34h,38h,3bh,3eh,3fh,3fh,3dh,39h,34h,2dh,26h,1eh,18h
db 29h,2ah,2ch,2fh,32h,36h,38h,3ah,3ah,38h,34h,2eh,28h,20h,19h,12h
db 22h,23h,25h,28h,2bh,2fh,31h,33h,33h,31h,2dh,27h,21h,19h,12h,0bh
db 1ah,1bh,1dh,20h,23h,27h,29h,2bh,2bh,29h,25h,1fh,19h,11h,0ah,08h
org 0fa00h
data_squares:
db 01h,80h,03h,0c0h,07h,0e0h,0fh,0f0h
db 1fh,0f8h,3fh,0fch,7fh,0feh,0ffh,0ffh
set_up:
ld hl,5affh ;ATTRs end
xor a ;Black PAPER, Black INK
slp0:
ld (hl),a ;
dec hl ;
bit 3,h ;
jr nz,slp0 ;
out (0feh),a ;BORDER 0
entry:
ld hl,0f940h ;plasma table 16 x 12 blocks = 192 bytes
ld de,0d820h ;
mlp0:
inc (hl)
ld a,(hl)
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 plasma table position
xor (hl) ;retain just bits 0-3 (00-07)
add a,a ;x2
ld l,a ;
inc h ;HL = address of mask bytes 0FAxx
ld b,(hl) ;B=left mask
inc l ;
ld c,(hl) ;C=right mask
ld h,b ;
ld l,c ;HL=map counter
a2s_addr:
push de ;pushed DE = stored ATTRs address
ld a,d ;hi-byte of ATTRs addr
and 0bh ;mask
add a,a ;x2
add a,a ;x4
add a,a ;x8
or 87h ;point to stored screen address
ld d,a ;DE = stored screen address
mlp1:
add hl,hl ;uses mask bytes as a map of which lines to mask or ignore
jr nc,nlu ;next line up
ld a,(de) ;get byte
and b ;mask LHS
ex af,af' ;store result
inc e ;next byte
ld a,(de) ;get byte
and c ;mask RHS
res 7,d ;point DE to screen
ld (de),a ;put byte
dec e ;next
ex af,af' ;restore stored
ld (de),a ;put byte
set 7,d ;point DE back to stored scr
nlu:
ld a,d ;next line up.
dec d ;I'm not going to explain this
and 07h ;as if you aren't familiar with
jr nz,mlpe ;this by now, then you should
ld a,e ;be ashamed!
add a,0e0h ;
ld e,a ;
sbc a,a ;
and 08h ;
add a,d ;
ld d,a ;
mlpe
ld a,h ;check if counter is zero
or l ;
jr nz,mlp1 ;
mlp2: ;place ATTRs
pop hl ;ATTRs address now into HL
ld d,h ;
res 7,d ;
ld e,l ;point DE to screen equivalent ATTRs address
ldi ;copy byte
ldd ;copy byte
res 5,e ;next ATTRs line up
ld l,e ;
ldi ;copy byte
ldd ;copy byte
set 5,l ;back down 1 ATTRs line
ex de,hl ;DE now holds ATTRs addr of stored scr
pop hl ;plasma address into HL
nxt_block:
inc e ;next right
inc de ;next right and take care of D if it needs to INC
bit 5,e ;ensure that we only address odd lines (1,3,5,7)
jr nz,mlp3 ;
ld a,e ;
add a,20h ;
ld e,a ;
mlp3:
inc l ;next plasma byte
jr nz,mlp0 ;repeat
ret ;
I've been playing around with lots of multicolour effects (NIRVANA etc) recently. I fancy looking at a multicolour version of plasma! One that leaves the pixels alone but does something interesting with the 8x2 attributes.
If you could get it to run in regular time slices you could do it in 4x4 cells on a 128K, simply switching between display screens at the right moment to give you 8x4 attributes. Page the alternate screen into top RAM so you can write to both screens at once, and only flip the bit that chooses which screen to actually display.
4x4 cells would require a fair bit more programming, but a plasma table of only 48 bytes. I'm sure I've seen it done in Demos before.
If one was really creative, it could continue loading whilst revealing the screen maybe? Now that would look nice. Probably a little tricky though!
I'm just tidying up the basic listing for the Plasma creator that I've been using mostly. I've some recollection that it came from Russian demo site perhaps.
Generally thats fine, but in this instance, we don't need to cross the screen third boundary, so ld a,h,add a,8 ld h,a
isn't needed. We can optimise for just the parameters that it'll need to work within.
I've just saved another chunk by removing the bitmap masks for the squares. It's slowed ever so slightly, but now creates the masks as it goes.
;square fade in
;using a plasma table
;fade in the screen display file
;
;plasma map at 0f940h but can be altered or moved elsewhere
;stored picture must reside at 0c000h - 49152
;
;CALL the set_up routine first
;Thereafter repeatedly CALL the entry point further in
;set_up: FA00h - RAND USR 64000
;entry : FA0Ch - RAND USR 64012
;
;JES Unknown - Nov 2017
;v1.2
org 0fa00h
set_up:
ld hl,5affh ;ATTRs end
xor a ;Black PAPER, Black INK
slp0:
ld (hl),a ;
dec hl ;
bit 3,h ;
jr nz,slp0 ;
out (0feh),a ;BORDER 0
entry:
ld hl,0f940h ;plasma table 16 x 12 blocks = 192 bytes
ld de,0d820h ;
mlp0:
inc (hl)
ld a,(hl)
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 plasma table position
xor (hl) ;retain just bits 0-3 (00-07)
ld b,a
xor a
inc b
tst_l0:
sll a
djnz tst_l0
ld h,a
tst_l1:
rlca
jr nc,tst_l1
rrca
ld l,a
ld b,h
ld c,l
a2s_addr:
push de ;pushed DE = stored ATTRs address
ld a,d ;hi-byte of ATTRs addr
and 0bh ;mask
add a,a ;x2
add a,a ;x4
add a,a ;x8
or 87h ;point to stored screen address
ld d,a ;DE = stored screen address
mlp1:
add hl,hl ;uses mask bytes as a map of which lines to mask or ignore
jr nc,nlu ;next line up
ld a,(de) ;get byte
and b ;mask LHS
ex af,af' ;store result
inc e ;next byte
ld a,(de) ;get byte
and c ;mask RHS
res 7,d ;point DE to screen
ld (de),a ;put byte
dec e ;next
ex af,af' ;restore stored
ld (de),a ;put byte
set 7,d ;point DE back to stored scr
nlu:
ld a,d ;
dec d ;
and 07h ;
jr nz,mlpe ;
ld a,08 ;
add a,d ;
ld d,a ;
res 5,e ;
mlpe
ld a,h ;check if counter is zero
or l ;
jr nz,mlp1 ;
mlp2: ;place ATTRs
pop hl ;ATTRs address now into HL
ld d,h ;
res 7,d ;
ld e,l ;point DE to screen equivalent ATTRs address
ldi ;copy byte
ldd ;copy byte
res 5,e ;next ATTRs line up
ld l,e ;
ldi ;copy byte
ldd ;copy byte
set 5,l ;back down 1 ATTRs line
ex de,hl ;DE now holds ATTRs addr of stored scr
pop hl ;plasma address into HL
nxt_block:
inc e ;next right
inc de ;next right and take care of D if it needs to INC
bit 5,e ;ensure that we only address odd lines (1,3,5,7)
jr nz,mlp3 ;
ld a,e ;
add a,20h ;
ld e,a ;
mlp3:
inc l ;next plasma byte
jr nz,mlp0 ;repeat
ret ;
Comments
It actually only does 1 frame per call, so you can use it along side something else, like a scroller or music I suppose
I'm sure it could be written more efficiently and shorter though.
https://mb.boardhost.com/BikerMike/index.html?1593001131
Using the same plasma field, you can do it a lot easier and quicker using just the ATTRs, which is still nice. I have an example ....somewhere.
Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
Member of the team that discovered, analyzed, and detailed the floating bus behavior on the ZX Spectrum +2A/+3.
A few Spectrum game fixes.
I'm rather appalled at how horribly I wrote it, so I'm just doing a re-write to its less embarassing!
:))
Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
Member of the team that discovered, analyzed, and detailed the floating bus behavior on the ZX Spectrum +2A/+3.
A few Spectrum game fixes.
https://mb.boardhost.com/BikerMike/index.html?1593001131
basically the way plasma works, well in this case anyway, is that 1 frame decreases each byte of the plasma table by 1 Then it checks if that byte falls into the area in which it can start to reveal what occupies that 2x2 character square. Have I lost anyone yet?
There are 7 square masks from full 16 x 16 to only 2x2 pixels. Once a plasma byte is within the 00-07 range then it prints the corresponding square masked portion of the screen, 07 being the smallest, 00 the full monty!
The plasma can be quite difficult to code to make it flow nicely. There is a Sinus calc to do this, which I found somewhere years ago. Once you have your plasma table, its cyclically updated all relative to one another, so it doesn't get destroyed, but might need positioning correctly for displaying the screen again. You could of course just have multiple tables to display it differently each time with some simple random number generation to select the plasma pattern. Or if the table calc could be coded into Z80 simply enough then while the screen is displayed, it could make a new plasma table, then fade out, which of course is also possible too with a little alteration.
I've found a few neat tricks to speed it up and make it smaller, so I'm re-writing it at the moment.
I'll try and make it easier to use and understand, so it might be a useful addition to a game or loader for someone.
These are the type of things that I wrote before attempting games.
They helped with learning the way the screen and attributes were layered and tricks that could be used.
They have been lost to time, were my first attempts at real code and very nasty in the way they were written.
Download the latest version of Bomb Munchies Ver2210 4th July 2020
SevenFFF / Threetwosevensixseven / colonel32
NXtel • NXTP • ESP Update • ESP Reset • CSpect Plugins
SevenFFF / Threetwosevensixseven / colonel32
NXtel • NXTP • ESP Update • ESP Reset • CSpect Plugins
I love this way of working. You can do a bunch of highly extravagant things, all apparently at once, just by spreading it all out in the time domain!
SevenFFF / Threetwosevensixseven / colonel32
NXtel • NXTP • ESP Update • ESP Reset • CSpect Plugins
Re-writing is going ok, though I've hit a wall where something isn't right and I can't figure out what. I need that moment of inspiration, the lightbulb above the head, to get it fixed. Hopefully now though under 130 bytes, and moderately more efficiently coded!
- IONIAN-GAMES.com -
http://www.pygame.org/pcr/numpy_plasma/index.php
I think his 'Save' comments actually mean 'Restore', but I get the gist.
He's got two parameters that he increases at different rates as he steps across the X-direction, and then resets them and steps two other parameters with each step in the Y-direction. And he uses those parameters to index into a Cosine table and adds up the four results, translating them into a colour.
Then after each frame he goes back to the initial values and tweaks them a bit, then starts again.
So really he's got two Sine / Cosine wave functions running in each of the X and Y directions, and combining them to make a colour contour map.
I thought there were more shortcuts to it than that though. I guess you could do the X-lookups first then the Y-lookups to make two 1D lists, then combine them to do the 2D X/Y plot..? That sounds too easy to me, but I can't see why it wouldn't work..?
- IONIAN-GAMES.com -
we have a routine that treats the screen as if it were 16 wide x 12 high squares. That gives 192 bytes with values of 00-ff (0-255). What we do is make things happen when those corresponding bytes fall within a particular range, in this instance, 00-07, which correspond to the 8 square masks.
On each call to the routine we increase each of the 192 bytes by 1, checking each in turn for its value and whether that indicates that we need to 'do' something. If it falls outside the 'active' range, then we just go to the next and repeat until all 192 are done.
So as you can see, with all the bytes in that 192 starting with different values, we get patterns emerging. A little demonstration below shows the plasma as a simple increasing number pattern with 00 as the first byte all the way up to 191 as the last (192nd). The resulting reveal pattern is obvious! Actually, we have to reverse the order of the numbers and they need to Descend, but you get the idea hopefully.
You could simply do X+Y+N-28 for each cell and as N increases the cells go through 0..7 in a diagonal sweep. But with your method you get to make more interesting patterns. Although with only 192 squares I'd probably just program the starting numbers in by hand.
What would be cool is if you keep running the plasma effect so it's moving in waves AND add on a gradual offset, so the squares actually pulse in and out a bit before settling down. Have you tried that??? :!!
- IONIAN-GAMES.com -
;square fade in ;using a plasma table ;fade in the screen display file ; ;plasma map at 0f940h but can be altered or moved elsewhere ;stored picture must reside at 0c000h - 49152 ; ;CALL the set_up routine first ;Thereafter repeatedly CALL the entry point further in ;set_up: FA10h - RAND USR 64016 ;entry : FA1Ch - RAND USR 64028 ; ;JES Unknown - Nov 2017 ; org 0f940h db 14h,14h,16h,19h,1dh,20h,23h,24h,24h,22h,1eh,19h,12h,0ah,09h,08h db 1ch,1dh,1fh,22h,25h,29h,2bh,2dh,2dh,2bh,27h,21h,1ah,13h,0ch,09h db 24h,24h,26h,29h,2dh,30h,33h,35h,35h,33h,2fh,29h,22h,1bh,13h,0dh db 2ah,2bh,2dh,30h,34h,37h,3ah,3bh,3bh,39h,35h,30h,29h,21h,1ah,13h db 30h,30h,32h,35h,39h,3ch,3fh,40h,40h,3eh,3ah,35h,2eh,26h,1fh,19h db 33h,33h,35h,38h,3ch,3fh,42h,43h,43h,41h,3dh,38h,31h,2ah,22h,1ch db 33h,34h,36h,39h,3dh,40h,43h,44h,44h,42h,3eh,39h,32h,2ah,23h,1dh db 32h,33h,35h,38h,3bh,3fh,41h,43h,43h,41h,3dh,37h,31h,29h,22h,1bh db 2fh,2fh,31h,34h,38h,3bh,3eh,3fh,3fh,3dh,39h,34h,2dh,26h,1eh,18h db 29h,2ah,2ch,2fh,32h,36h,38h,3ah,3ah,38h,34h,2eh,28h,20h,19h,12h db 22h,23h,25h,28h,2bh,2fh,31h,33h,33h,31h,2dh,27h,21h,19h,12h,0bh db 1ah,1bh,1dh,20h,23h,27h,29h,2bh,2bh,29h,25h,1fh,19h,11h,0ah,08h org 0fa00h data_squares: db 01h,80h,03h,0c0h,07h,0e0h,0fh,0f0h db 1fh,0f8h,3fh,0fch,7fh,0feh,0ffh,0ffh set_up: ld hl,5affh ;ATTRs end xor a ;Black PAPER, Black INK slp0: ld (hl),a ; dec hl ; bit 3,h ; jr nz,slp0 ; out (0feh),a ;BORDER 0 entry: ld hl,0f940h ;plasma table 16 x 12 blocks = 192 bytes ld de,0d820h ; mlp0: inc (hl) ld a,(hl) 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 plasma table position xor (hl) ;retain just bits 0-3 (00-07) add a,a ;x2 ld l,a ; inc h ;HL = address of mask bytes 0FAxx ld b,(hl) ;B=left mask inc l ; ld c,(hl) ;C=right mask ld h,b ; ld l,c ;HL=map counter a2s_addr: push de ;pushed DE = stored ATTRs address ld a,d ;hi-byte of ATTRs addr and 0bh ;mask add a,a ;x2 add a,a ;x4 add a,a ;x8 or 87h ;point to stored screen address ld d,a ;DE = stored screen address mlp1: add hl,hl ;uses mask bytes as a map of which lines to mask or ignore jr nc,nlu ;next line up ld a,(de) ;get byte and b ;mask LHS ex af,af' ;store result inc e ;next byte ld a,(de) ;get byte and c ;mask RHS res 7,d ;point DE to screen ld (de),a ;put byte dec e ;next ex af,af' ;restore stored ld (de),a ;put byte set 7,d ;point DE back to stored scr nlu: ld a,d ;next line up. dec d ;I'm not going to explain this and 07h ;as if you aren't familiar with jr nz,mlpe ;this by now, then you should ld a,e ;be ashamed! add a,0e0h ; ld e,a ; sbc a,a ; and 08h ; add a,d ; ld d,a ; mlpe ld a,h ;check if counter is zero or l ; jr nz,mlp1 ; mlp2: ;place ATTRs pop hl ;ATTRs address now into HL ld d,h ; res 7,d ; ld e,l ;point DE to screen equivalent ATTRs address ldi ;copy byte ldd ;copy byte res 5,e ;next ATTRs line up ld l,e ; ldi ;copy byte ldd ;copy byte set 5,l ;back down 1 ATTRs line ex de,hl ;DE now holds ATTRs addr of stored scr pop hl ;plasma address into HL nxt_block: inc e ;next right inc de ;next right and take care of D if it needs to INC bit 5,e ;ensure that we only address odd lines (1,3,5,7) jr nz,mlp3 ; ld a,e ; add a,20h ; ld e,a ; mlp3: inc l ;next plasma byte jr nz,mlp0 ;repeat ret ;Don't forget to plonk a screen at 49152! Enjoy :)
- IONIAN-GAMES.com -
4x4 cells would require a fair bit more programming, but a plasma table of only 48 bytes. I'm sure I've seen it done in Demos before.
If one was really creative, it could continue loading whilst revealing the screen maybe? Now that would look nice. Probably a little tricky though!
I'm just tidying up the basic listing for the Plasma creator that I've been using mostly. I've some recollection that it came from Russian demo site perhaps.
saved 3 bytes on the Next line up calc, as it doesn't cross a screen 1/3
nlu: ld a,d ; dec d ; and 07h ; jr nz,mlpe ; ld a,08 ; add a,d ; ld d,a ; res 5,e ;Now 127 bytes
16 bytes
Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
Member of the team that discovered, analyzed, and detailed the floating bus behavior on the ZX Spectrum +2A/+3.
A few Spectrum game fixes.
isn't needed. We can optimise for just the parameters that it'll need to work within.
I've just saved another chunk by removing the bitmap masks for the squares. It's slowed ever so slightly, but now creates the masks as it goes.
;square fade in ;using a plasma table ;fade in the screen display file ; ;plasma map at 0f940h but can be altered or moved elsewhere ;stored picture must reside at 0c000h - 49152 ; ;CALL the set_up routine first ;Thereafter repeatedly CALL the entry point further in ;set_up: FA00h - RAND USR 64000 ;entry : FA0Ch - RAND USR 64012 ; ;JES Unknown - Nov 2017 ;v1.2 org 0fa00h set_up: ld hl,5affh ;ATTRs end xor a ;Black PAPER, Black INK slp0: ld (hl),a ; dec hl ; bit 3,h ; jr nz,slp0 ; out (0feh),a ;BORDER 0 entry: ld hl,0f940h ;plasma table 16 x 12 blocks = 192 bytes ld de,0d820h ; mlp0: inc (hl) ld a,(hl) 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 plasma table position xor (hl) ;retain just bits 0-3 (00-07) ld b,a xor a inc b tst_l0: sll a djnz tst_l0 ld h,a tst_l1: rlca jr nc,tst_l1 rrca ld l,a ld b,h ld c,l a2s_addr: push de ;pushed DE = stored ATTRs address ld a,d ;hi-byte of ATTRs addr and 0bh ;mask add a,a ;x2 add a,a ;x4 add a,a ;x8 or 87h ;point to stored screen address ld d,a ;DE = stored screen address mlp1: add hl,hl ;uses mask bytes as a map of which lines to mask or ignore jr nc,nlu ;next line up ld a,(de) ;get byte and b ;mask LHS ex af,af' ;store result inc e ;next byte ld a,(de) ;get byte and c ;mask RHS res 7,d ;point DE to screen ld (de),a ;put byte dec e ;next ex af,af' ;restore stored ld (de),a ;put byte set 7,d ;point DE back to stored scr nlu: ld a,d ; dec d ; and 07h ; jr nz,mlpe ; ld a,08 ; add a,d ; ld d,a ; res 5,e ; mlpe ld a,h ;check if counter is zero or l ; jr nz,mlp1 ; mlp2: ;place ATTRs pop hl ;ATTRs address now into HL ld d,h ; res 7,d ; ld e,l ;point DE to screen equivalent ATTRs address ldi ;copy byte ldd ;copy byte res 5,e ;next ATTRs line up ld l,e ; ldi ;copy byte ldd ;copy byte set 5,l ;back down 1 ATTRs line ex de,hl ;DE now holds ATTRs addr of stored scr pop hl ;plasma address into HL nxt_block: inc e ;next right inc de ;next right and take care of D if it needs to INC bit 5,e ;ensure that we only address odd lines (1,3,5,7) jr nz,mlp3 ; ld a,e ; add a,20h ; ld e,a ; mlp3: inc l ;next plasma byte jr nz,mlp0 ;repeat ret ;Now 118 or 106 bytes.