New custom loader - Sedge Warbloader - v1

Show us what you're working on, (preferably with screenshots).
Post Reply
User avatar
MonkZy
Manic Miner
Posts: 279
Joined: Thu Feb 08, 2018 1:01 pm

New custom loader - Sedge Warbloader - v1

Post by MonkZy »

I present the Sedge Warbloader :

Image

sedge-WL-v1.tap
SEDGE.WAV

As a kid I always wondered how it was possible to have animated graphics during loading. The first time I saw such loaders was during loading on Mastertronics 'Future Games'.

After examining the ROM loader routine (thanks to skoolkid.github.io) I noticed a perfect opportunity for squeezing in 358 T-states worth of graphics code.

Code: Select all

LD_EDGE_1 	LD A,$16 	;Wait 358 T states before entering the sampling loop.
LD_DELAY 	DEC A
		JR NZ,LD_DELAY
This provided enough CPU time for this replacement code :

Code: Select all

ld_edge_1:
	push hl			; 11T	[11]
	ld a,l			; 4T	[15]
	and %00000001		; 7T	[22]
	ld a,(counter)		; 13T 	[35]
	jp z,padding		; 10T	[45]	;if last loaded bit is set, skip increment
	inc a			; 4T	[49]
	jp tests		; 10T	[59]
padding:
	ld a,a			; 4T	[49]	; keep T-states regular
	jp tests		; 10T	[59]
tests:	
	ld (counter),a		; 17T	[76]	
	cp 127			; 7T  	[83]
	jp nz,next_check	; 10T 	[93]

;;; open beak 195T

	ld hl,22823
	ld a,%00111000		; change attributes to reveal open beak
	ld (hl),a
	inc l
	ld (hl),a
	inc l
	ld (hl),a

	ld hl,22791
	ld a,%00111111		; change attributes to hide closed beak
	ld (hl),a
	inc l
	ld (hl),a
	
	ld hl,18953
	ld a,%00000111
	ld (hl),a
	inc h
	ld a,%00000001
	ld (hl),a
	inc h
	ld a,%00000111
	ld (hl),a
	inc h
	ld a,%00011101
	ld (hl),a
	inc h
	ld a,%00110110
	ld (hl),a
	inc h
	ld a,%01100100
	ld (hl),a	

;;; end of open beak

	ld a,a			; 4T	[292]
	ld a,3			; 7T  	[299]
	jp common		; 10T	[309]

next_check:
	cp 255			; 7T  [100]
	jp nz,no_change		; 10T [110]

;;; close beak 195T

	ld hl,22791
	ld a,%00111000		; change attributes to reveal closed beak
	ld (hl),a
	inc l
	ld (hl),a

	ld hl,22823
	ld a,%00111111		; change attributes to conceal open beak
	ld (hl),a
	inc l
	ld (hl),a
	inc l
	ld (hl),a

	ld hl,18953		; ovewrite 6 screen bytes
	ld a,%11111111
	ld (hl),a
	inc h
	ld a,%00001110
	ld (hl),a
	inc h
	ld a,%00011000
	ld (hl),a
	inc h
	ld a,%11000000
	ld (hl),a
	inc h
	ld a,%00111111
	ld (hl),a
	inc h
	ld a,%00000011
	ld (hl),a

;;; end close beak

	ld a,a			; 4T	[309]
	ld a,1			; 7T	[316]
	jp common		; 10T	[326]

no_change:
	ld a,15			; 7T	[117]

common:
	pop hl			; 10T 

;;; open beak = 319T
;;; closed beak = 336T
;;; no-change = 127T 
	
ld_delay:
	dec a			; 4T
	jr nz,ld_delay		; 7T | 12T 		; delay of 359 T States

;;; open beak = 358T
;;; closed beak = 359T
;;; no-change = 358T 	

I guess animated loaders are not so popular these days due to SD-Card storage and emulators with accelerated loaders. I had some fun coding it, so I thought I would show it off here!

Full asm source :

Code: Select all

;;;; Custom loader
	org 40000

	ld ix,dummy_header			;set IX to point to dummy header location
	ld de,17				;load header bytes
	xor a					;zero A for header
	scf					;set carry for LOAD not VERIFY

	call ld_bytes				;call load ROM routine

	ld ix,(dummy_header+13)			;set IX to data block destination from header
	ld de,(dummy_header+11)			;set DE to data block length from header
	ld a,255				;set A to FF for data block
	scf					;set CF for LOAD

	call ld_bytes				;call ROM routine

	ret



ld_bytes:
	inc d
	ex af,af'
	dec d
	di
	ld a,$0F				; BIN 00010000
	out ($FE),a
	ld hl,$053F
	push hl
	in a,($FE)
	rra
	and $20
	or $02
	ld c,a
	cp a
ld_break:
	ret nz
ld_start:
	call ld_edge_1
	jr nc,ld_break
	ld hl,$0415
ld_wait:
	djnz ld_wait
	dec hl
	ld a,h
	or l
	jr nz,ld_wait
	call ld_edge_2
	jr nc,ld_break
ld_leader:
	ld b,$9C
	call ld_edge_2
	jr nc,ld_break
	ld a,$C6
	cp b
	jr nc,ld_start
	inc h
	jr nz,ld_leader
ld_sync:
	ld b,$C9
	call ld_edge_1
	jr nc,ld_break
	ld a,b
	cp $D4
	jr nc,ld_sync
	call ld_edge_1
	ret nc

;;; load bytes

	ld a,c
	xor $03
	ld c,a
	ld h,$00
	ld b,$B0
	jr ld_marker
ld_loop:
	ex af,af'
	jr nz,ld_flag
	jr nc,ld_verify
	ld (ix+$00),l
	jr ld_next
ld_flag:
	rl c
	xor l
	ret nz
	ld a,c
	rra
	ld c,a
	inc de
	jr ld_dec
ld_verify:
	ld a,(ix+$00)
	xor l
	ret nz
ld_next:
	inc ix
ld_dec:
	dec de
	ex af,af'
	ld b,$B2
ld_marker:
	ld l,$01
ld_8_bits:
	call ld_edge_2
	ret nc
	ld a,$CB
	cp b
	rl l
	ld b,$B0
	jp nc,ld_8_bits
	ld a,h
	xor l
	ld h,a
	ld a,d
	or e
	jr nz,ld_loop
	ld a,h
	cp $01
	ret

ld_edge_2:
	call ld_edge_1
	ret nc
ld_edge_1:
	push hl			; 11T	[11]
	ld a,l			; 4T	[15]
	and %00000001		; 7T	[22]
	ld a,(counter)		; 13T 	[35]
	jp z,padding		; 10T	[45]	;if A<>7, skip increment
	inc a			; 4T	[49]
	jp tests		; 10T	[59]
padding:
	ld a,a			; 4T	[49]	; keep T-states regular
	jp tests		; 10T	[59]
tests:	
	ld (counter),a		; 17T	[76]	
	cp 127			; 7T  	[83]
	jp nz,next_check	; 10T 	[93]

;;; open beak 195T

	ld hl,22823
	ld a,%00111000		; change attributes to reveal open beak
	ld (hl),a
	inc l
	ld (hl),a
	inc l
	ld (hl),a

	ld hl,22791
	ld a,%00111111		; change attributes to hide closed beak
	ld (hl),a
	inc l
	ld (hl),a
	
	ld hl,18953
	ld a,%00000111
	ld (hl),a
	inc h
	ld a,%00000001
	ld (hl),a
	inc h
	ld a,%00000111
	ld (hl),a
	inc h
	ld a,%00011101
	ld (hl),a
	inc h
	ld a,%00110110
	ld (hl),a
	inc h
	ld a,%01100100
	ld (hl),a	

;;; end of open beak

	ld a,a			; 4T	[292]
	ld a,3			; 7T  	[299]
	jp common		; 10T	[309]

next_check:
	cp 255			; 7T  [100]
	jp nz,no_change		; 10T [110]

;;; close beak 195T

	ld hl,22791
	ld a,%00111000		; change attributes to reveal closed beak
	ld (hl),a
	inc l
	ld (hl),a

	ld hl,22823
	ld a,%00111111		; change attributes to conceal open beak
	ld (hl),a
	inc l
	ld (hl),a
	inc l
	ld (hl),a

	ld hl,18953		; ovewrite 6 screen bytes
	ld a,%11111111
	ld (hl),a
	inc h
	ld a,%00001110
	ld (hl),a
	inc h
	ld a,%00011000
	ld (hl),a
	inc h
	ld a,%11000000
	ld (hl),a
	inc h
	ld a,%00111111
	ld (hl),a
	inc h
	ld a,%00000011
	ld (hl),a

;;; end close beak

	ld a,a			; 4T	[309]
	ld a,1			; 7T	[316]
	jp common		; 10T	[326]

no_change:
	ld a,15			; 7T	[117]

common:
	pop hl			; 10T 

;;; open beak = 319T
;;; closed beak = 336T
;;; no-change = 127T 
	
ld_delay:
	dec a			; 4T
	jr nz,ld_delay		; 7T | 12T 		; delay of 359 T States

;;; open beak = 358T
;;; closed beak = 359T
;;; no-change = 358T 	

	and a
ld_sample:
	inc b
	ret z
	ld a,$7F
	in a,($FE)
	rra
	ret nc
	xor c
	and $20
	jr z,ld_sample
	ld a,c
	cpl
	ld c,a
	and $07
	or $08
	out ($FE),a
	scf
	ret

counter:
	defb 0

dummy_header:
User avatar
R-Tape
Site Admin
Posts: 6402
Joined: Thu Nov 09, 2017 11:46 am

Re: New custom loader - Sedge Warbloader - v1

Post by R-Tape »

Good work! I wanted to do one of these for last year's Woot, but I got lost trying to unravel the ROM loader (did you see the cartoony mock-up I used in the end?).
User avatar
MatGubbins
Dynamite Dan
Posts: 1239
Joined: Mon Nov 13, 2017 11:45 am
Location: Kent, UK

Re: New custom loader - Sedge Warbloader - v1

Post by MatGubbins »

Impressive! By the end of the month Dave will have 10 little birds flying around the screen as his next epic game loads in....
User avatar
MonkZy
Manic Miner
Posts: 279
Joined: Thu Feb 08, 2018 1:01 pm

Re: New custom loader - Sedge Warbloader - v1

Post by MonkZy »

R-Tape wrote: Mon May 11, 2020 8:02 pm (did you see the cartoony mock-up I used in the end?).
I have read the last Woot, and thoroughly enjoyed it, but the inspiration is from the annual sedge-warbler thread :D
MatGubbins wrote: Mon May 11, 2020 10:20 pm Impressive! By the end of the month Dave will have 10 little birds flying around the screen as his next epic game loads in....
Anything is possible with 359 T-states. The edge sample routine cycles multiple times per frame, although you cannot sync with the screen refresh. I made an unusual rainbow effect by cycling a few paper attributes on each edge delay. Any effect is keyed to the incoming bits however. I skip 128 '1' bits between beak changes, in an attempt to sync the beak to the sound of the loading and slow down the open/close, and the beak still opens and closes pretty quickly,

It is a fun thing to code.
Patrik Rak
Microbot
Posts: 116
Joined: Mon Apr 13, 2020 3:07 pm

Re: New custom loader - Sedge Warbloader - v1

Post by Patrik Rak »

MonkZy wrote: Tue May 12, 2020 1:03 am Anything is possible with 359 T-states. The edge sample routine cycles multiple times per frame, although you cannot sync with the screen refresh.
Well, technically you CAN sync with the screen refresh. Check these original loaders by BusySoft.

Of course, the ultimate demo showing what can be done during load is the Ahh... the tape loading era!.

Good job nevertheless. I completely understand your drive - mastering the loaders was among my first goals as a kid as well.
User avatar
MonkZy
Manic Miner
Posts: 279
Joined: Thu Feb 08, 2018 1:01 pm

Re: New custom loader - Sedge Warbloader - v1

Post by MonkZy »

Thank you [mention]Patrik Rak[/mention] .

A fantastic collection of original loaders and demo's. I am a late-returner to the Spectrum and have so much to see! The innovation over the last 20 years is incredible. I do want to roll all my recent tinkering into a demo at some point. Never too late.
Pgyuri
Drutt
Posts: 25
Joined: Fri Apr 24, 2020 8:36 am

Re: New custom loader - Sedge Warbloader - v1

Post by Pgyuri »

One of the best ... https://www.worldofspectrum.org/infosee ... id=0002623 ... play during loading

Pgyuri
User avatar
R-Tape
Site Admin
Posts: 6402
Joined: Thu Nov 09, 2017 11:46 am

Re: New custom loader - Sedge Warbloader - v1

Post by R-Tape »

Pgyuri wrote: Tue May 12, 2020 1:07 pm One of the best ...
Or here: https://spectrumcomputing.co.uk/index.p ... 96&id=2623 :)

I wish I could do a custom loader like it. Once I managed one with a glowing end of a cigarette.
akeley
Dynamite Dan
Posts: 1043
Joined: Sat Feb 01, 2020 5:47 pm

Re: New custom loader - Sedge Warbloader - v1

Post by akeley »

Too cute. But how do I actually record to tape deck from a PC? Is there a guide somewhere?
User avatar
MonkZy
Manic Miner
Posts: 279
Joined: Thu Feb 08, 2018 1:01 pm

Re: New custom loader - Sedge Warbloader - v1

Post by MonkZy »

akeley wrote: Tue May 12, 2020 2:26 pm Too cute. But how do I actually record to tape deck from a PC? Is there a guide somewhere?
I have been using a command line tool TZX2WAV.EXE (WOS Link)

It produces a .wav file that can be played on a media player for recording to a cassette. It works fine using wine on linux. I have only tested it with my own software, so I am not 100% certain all custom loaders will work.
User avatar
kolbeck
Manic Miner
Posts: 310
Joined: Mon Nov 13, 2017 9:04 pm

Re: New custom loader - Sedge Warbloader - v1

Post by kolbeck »

[mention]MonkZy[/mention] - Can I add it to my page?:-)
https://zxinfo.dk/animated

/thomas
https://api.zxinfo.dk/v3/ - ZXDB API for developers
zxinfo-file-browser - Cross platform app to manage your files
https://zxinfo.dk - another ZXDB frontend
User avatar
MonkZy
Manic Miner
Posts: 279
Joined: Thu Feb 08, 2018 1:01 pm

Re: New custom loader - Sedge Warbloader - v1

Post by MonkZy »

[mention]kolbeck[/mention] hehe, of course.

That is a great collection. I had forgotten the Heavy on the Magick loader, another loader that impressed me as a kid.You should include 'Future Games' too, the animated loader and Tim Follins banger of a tune were the games only redeeming value.
User avatar
kolbeck
Manic Miner
Posts: 310
Joined: Mon Nov 13, 2017 9:04 pm

Re: New custom loader - Sedge Warbloader - v1

Post by kolbeck »

[mention]MonkZy[/mention] - great suggestions, will try to find them and add together with your bird..

Tweet...
https://api.zxinfo.dk/v3/ - ZXDB API for developers
zxinfo-file-browser - Cross platform app to manage your files
https://zxinfo.dk - another ZXDB frontend
Post Reply