Author Topic: CORSAIR_Trainer  (Read 1499 times)

0 Members and 1 Guest are viewing this topic.

Offline Axelay

  • 6128 Plus
  • ******
  • Posts: 584
  • Country: au
  • Liked: 383
  • Likes Given: 87
Re: CORSAIR_Trainer
« Reply #25 on: 16:24, 19 October 20 »
Man...this game is hard!

I own Radiant Silvergun, Battle Garegga on my Sega Saturn and Ketsui and Esp.Rade on my PS3 and PS4. All of these are tricky games and Corsair Trainer has now joined them in the difficulty ranks :D .
Congrats to the team for producing an excellent game. Wonderful coding by Axelay as usual. Rexbeng - wonderful job on the artwork and McKlain's solid sound engineering completes this package.
Well done!


Can't say I had those games in mind when I was thinking of the difficulty, but thanks for the comparison.  :)


Do you think it would be possible to update your code to hide the redraw at the top of the screen? I want to try my hand at an arcade game, im ok with Z80 code,i would just like a routine that works. The mode 2 proposal with colour change where both colours are the same seems like a good fix but can it be interrupt driven or does it need specific timing( which sux :) )



Here you go.  Bear in mind this is that old prototype with the screen movement at the top hidden.  No update of the comments, nor updating with whatever changes I might have subsequently made to the current code base for Corsair.  It waits during the first interrupt for quite some time to show the highest possible line of the screen.  If you don't want to find stable code to put there in the interrupt and not waste cpu time, you can remove the delay and move the second mode/colour change to the second interrupt, but you'll lose 2 characters from the top of the screen.



Code: [Select]

org &4000
nolist
run start


start:
;; standard screen is 39 chars tall and vsync at 30
;; with 25 chars displayed
;;
;; we want to change this to 26 chars displayed with vsync at 31
;;
;; Char Lines to end of screen: 39-31 = 8
;; Scan Lines to end of screen: 8*8 = 64
;; Interrupt occurs two lines after VSYNC, so lines until end of screen when interrupt occurs: 64-2 = 62
;;
;; If we then wait for one interrupt, we will be 10 (62-52 = 10) lines into the next screen.
;;
;; Then interrupts are:
;; 10, 62, 114, 166, 218
;;
;; And we will then be 10 lines into second screen.




di
ld bc,&7f10
out (c),c
ld bc,&7f54
out (c),c


; narrow the screen
ld bc,&bc01
out (c),c
ld bc,&bd00+32
out (c),c
; and centre it
ld bc,&bc02
out (c),c
ld bc,&bd00+42
out (c),c




;; set new vsync we want
ld bc,&bc07
out (c),c
ld bc,&bd00+31+4
out (c),c


;; wait for 2 vsyncs to allow it to stabalise and so that we can sync with that
ld e,2
wait_two_vsyncs:
ld b,&f5
wait_vsync_end:
in a,(c)
rra
jr c,wait_vsync_end
wait_vsync_start:
in a,(c)
rra
jr nc,wait_vsync_start
dec e
jp nz,wait_two_vsyncs


;; synchronised with start of vsync and we are synchronised with CRTC too, and we have the
;; same number of lines to next screen as we want.


;; set initial interrupt routine
ld hl,int_rout1
ld (int_rout_ptr+1),hl


;; set interrupt
ld a,&c3
ld hl,int_start
ld (&0038),a
ld (&0039),hl
;; enable
ei


main_loop:
ld b,&f5
vsync:
in a,(c)
rra
jr nc,vsync


halt


halt


call scroll_down


jp main_loop


;;---------


int_start:
push bc
push hl
push af
int_rout_ptr:
jp int_rout1




;;---------
;; first interrupt after vsync
int_rout1:
;;ld bc,&7f10
;;out (c),c
;;ld bc,&7f4b
;;out (c),c


;; set vsync position to turn it off
ld bc,&bc07
out (c),c
ld bc,&bdff
out (c),c


;; screen address for main part of screen
;; will not trigger until screen restarts
ld hl,(scroll_offset)
ld a,&30
or a,h
ld bc,&bc0c
out (c),c
inc b
out (c),a
ld bc,&bc0d
out (c),c
inc b
out (c),l


;; set height of main part of screen
;; since we are already past the end of the previous screen
;; this will take no effect.
ld bc,&bc06
out (c),c
ld bc,&bd00+25+4
out (c),c


ld bc,&bc05         ;; select vertical adjust register of CRTC
out (c),c
inc b
ld a,(scroll_fine_next)
out (c),a
ld (scroll_fine),a


; mask movement of screen top
;set mode 2
  ld bc,&7F8e
  out (c),c
; set colours to border
  ld bc,&7f00
  out (c),c
  ld a,&54
  out (c),a ; background to match border
  inc c
  out (c),c
  out (c),a ; ink 1 to match border


; wait until at lowest point of screen top
  ld b,246
.int1delaylp
  defs 5 ; some nops
  djnz int1delaylp
;set mode 1
  ld bc,&7F8d
  out (c),c
; set colours to standard mode 1
  ld bc,&7f00
  out (c),c
  ld a,&44
  out (c),a ; background to dark blue
  inc c
  out (c),c
  ld a,&4a
  out (c),a ; ink 1 to yellow


ld hl,int_rout2
jp int_end


;;---------
int_rout2:
;; 10 lines until end of screen
;;ld bc,&7f10
;;out (c),c
;;ld bc,&7f43
;;out (c),c


ld hl,int_rout3
jp int_end


;;---------
int_rout3:
;;ld bc,&7f10
;;out (c),c
;;ld bc,&7f42
;;out (c),c


;; now at line 42.
ld bc,&bc04
out (c),c
ld bc,&bd00+25-1+4-1 ; less 1 because of R5 offset
out (c),c




ld hl,int_rout4
jp int_end


;;---------
int_rout4:


;;ld bc,&7f10
;;out (c),c
;;ld bc,&7f40
;;out (c),c




ld hl,int_rout5
jp int_end


;;---------
int_rout5:


;;ld bc,&7f10
;;out (c),c
;;ld bc,&7f49
;;out (c),c




ld bc,&bc0c
out (c),c
ld bc,&bd00+&18
out (c),c
ld bc,&bc0d
out (c),c
ld bc,&bd00
out (c),c


ld bc,&bc05         ;; select vertical adjust register of CRTC
out (c),c
inc b
ld a,(scroll_fine)
xor a,7
inc a
out (c),a


ld hl,int_rout6
jp int_end


;;---------
int_rout6:
;;ld bc,&7f10
;;out (c),c
;;ld bc,&7f53
;;out (c),c


;; 2 lines before end of screen


;; 128 cycles
ld b,42-1 ; need one less after addition of push af
int_delay:
djnz int_delay


;; set display height of screen
ld bc,&bc06
out (c),c
ld bc,&bd00+1+3
out (c),c


;; set height of screen
ld bc,&bc04
out (c),c
ld bc,&bd00+14-1-4
out (c),c


;; set vsync position
ld bc,&bc07
out (c),c
ld bc,&bd00+6
out (c),c


ld hl,int_rout1
jp int_end


int_end:
ld (int_rout_ptr+1),hl
pop af
pop hl
pop bc
ei
ret


;;end start


.scroll_down
;; check fine value first
    ld a,(scroll_fine_next)
    inc a
    and 7
    ld (scroll_fine_next),a
    or a
    ret nz


;; get the current scroll offset
    ld hl,(scroll_offset)
    ld bc,32
    or a
    sbc hl,bc


;; ensure scroll offset is in range &000-&3ff
    ld a,h
    and &3
    ld h,a


;; store new scroll offset. It is now ready to be written to the CRTC.
    ld (scroll_offset),hl
    ret


;; the scroll offset in CRTC character units
.scroll_offset
    defw 0
;; offset for fine scroll
.scroll_fine
    defb 0
.scroll_fine_next
    defb 0

Offline lmimmfn

  • CPC464
  • **
  • Posts: 17
  • Country: ie
  • Liked: 11
  • Likes Given: 13
Re: CORSAIR_Trainer
« Reply #26 on: 22:32, 19 October 20 »
Which page are you referring to?
Ignore this
« Last Edit: 22:42, 19 October 20 by lmimmfn »

Offline lmimmfn

  • CPC464
  • **
  • Posts: 17
  • Country: ie
  • Liked: 11
  • Likes Given: 13
Re: CORSAIR_Trainer
« Reply #27 on: 22:38, 19 October 20 »
Thanks very much Axelay, will give it a whirl tonight.


@Gryzor, ignore my previous post, can you Sticky Axelays vertical scrolling routine above in the programming section?
« Last Edit: 23:00, 19 October 20 by lmimmfn »

Offline lmimmfn

  • CPC464
  • **
  • Posts: 17
  • Country: ie
  • Liked: 11
  • Likes Given: 13
Re: CORSAIR_Trainer
« Reply #28 on: 02:12, 20 October 20 »

Can't say I had those games in mind when I was thinking of the difficulty, but thanks for the comparison.  :)




Here you go.  Bear in mind this is that old prototype with the screen movement at the top hidden.  No update of the comments, nor updating with whatever changes I might have subsequently made to the current code base for Corsair.  It waits during the first interrupt for quite some time to show the highest possible line of the screen.  If you don't want to find stable code to put there in the interrupt and not waste cpu time, you can remove the delay and move the second mode/colour change to the second interrupt, but you'll lose 2 characters from the top of the screen.



Code: [Select]

org &4000
nolist
run start


start:
;; standard screen is 39 chars tall and vsync at 30
;; with 25 chars displayed
;;
;; we want to change this to 26 chars displayed with vsync at 31
;;
;; Char Lines to end of screen: 39-31 = 8
;; Scan Lines to end of screen: 8*8 = 64
;; Interrupt occurs two lines after VSYNC, so lines until end of screen when interrupt occurs: 64-2 = 62
;;
;; If we then wait for one interrupt, we will be 10 (62-52 = 10) lines into the next screen.
;;
;; Then interrupts are:
;; 10, 62, 114, 166, 218
;;
;; And we will then be 10 lines into second screen.




di
ld bc,&7f10
out (c),c
ld bc,&7f54
out (c),c


; narrow the screen
ld bc,&bc01
out (c),c
ld bc,&bd00+32
out (c),c
; and centre it
ld bc,&bc02
out (c),c
ld bc,&bd00+42
out (c),c




;; set new vsync we want
ld bc,&bc07
out (c),c
ld bc,&bd00+31+4
out (c),c


;; wait for 2 vsyncs to allow it to stabalise and so that we can sync with that
ld e,2
wait_two_vsyncs:
ld b,&f5
wait_vsync_end:
in a,(c)
rra
jr c,wait_vsync_end
wait_vsync_start:
in a,(c)
rra
jr nc,wait_vsync_start
dec e
jp nz,wait_two_vsyncs


;; synchronised with start of vsync and we are synchronised with CRTC too, and we have the
;; same number of lines to next screen as we want.


;; set initial interrupt routine
ld hl,int_rout1
ld (int_rout_ptr+1),hl


;; set interrupt
ld a,&c3
ld hl,int_start
ld (&0038),a
ld (&0039),hl
;; enable
ei


main_loop:
ld b,&f5
vsync:
in a,(c)
rra
jr nc,vsync


halt


halt


call scroll_down


jp main_loop


;;---------


int_start:
push bc
push hl
push af
int_rout_ptr:
jp int_rout1




;;---------
;; first interrupt after vsync
int_rout1:
;;ld bc,&7f10
;;out (c),c
;;ld bc,&7f4b
;;out (c),c


;; set vsync position to turn it off
ld bc,&bc07
out (c),c
ld bc,&bdff
out (c),c


;; screen address for main part of screen
;; will not trigger until screen restarts
ld hl,(scroll_offset)
ld a,&30
or a,h
ld bc,&bc0c
out (c),c
inc b
out (c),a
ld bc,&bc0d
out (c),c
inc b
out (c),l


;; set height of main part of screen
;; since we are already past the end of the previous screen
;; this will take no effect.
ld bc,&bc06
out (c),c
ld bc,&bd00+25+4
out (c),c


ld bc,&bc05         ;; select vertical adjust register of CRTC
out (c),c
inc b
ld a,(scroll_fine_next)
out (c),a
ld (scroll_fine),a


; mask movement of screen top
;set mode 2
  ld bc,&7F8e
  out (c),c
; set colours to border
  ld bc,&7f00
  out (c),c
  ld a,&54
  out (c),a ; background to match border
  inc c
  out (c),c
  out (c),a ; ink 1 to match border


; wait until at lowest point of screen top
  ld b,246
.int1delaylp
  defs 5 ; some nops
  djnz int1delaylp
;set mode 1
  ld bc,&7F8d
  out (c),c
; set colours to standard mode 1
  ld bc,&7f00
  out (c),c
  ld a,&44
  out (c),a ; background to dark blue
  inc c
  out (c),c
  ld a,&4a
  out (c),a ; ink 1 to yellow


ld hl,int_rout2
jp int_end


;;---------
int_rout2:
;; 10 lines until end of screen
;;ld bc,&7f10
;;out (c),c
;;ld bc,&7f43
;;out (c),c


ld hl,int_rout3
jp int_end


;;---------
int_rout3:
;;ld bc,&7f10
;;out (c),c
;;ld bc,&7f42
;;out (c),c


;; now at line 42.
ld bc,&bc04
out (c),c
ld bc,&bd00+25-1+4-1 ; less 1 because of R5 offset
out (c),c




ld hl,int_rout4
jp int_end


;;---------
int_rout4:


;;ld bc,&7f10
;;out (c),c
;;ld bc,&7f40
;;out (c),c




ld hl,int_rout5
jp int_end


;;---------
int_rout5:


;;ld bc,&7f10
;;out (c),c
;;ld bc,&7f49
;;out (c),c




ld bc,&bc0c
out (c),c
ld bc,&bd00+&18
out (c),c
ld bc,&bc0d
out (c),c
ld bc,&bd00
out (c),c


ld bc,&bc05         ;; select vertical adjust register of CRTC
out (c),c
inc b
ld a,(scroll_fine)
xor a,7
inc a
out (c),a


ld hl,int_rout6
jp int_end


;;---------
int_rout6:
;;ld bc,&7f10
;;out (c),c
;;ld bc,&7f53
;;out (c),c


;; 2 lines before end of screen


;; 128 cycles
ld b,42-1 ; need one less after addition of push af
int_delay:
djnz int_delay


;; set display height of screen
ld bc,&bc06
out (c),c
ld bc,&bd00+1+3
out (c),c


;; set height of screen
ld bc,&bc04
out (c),c
ld bc,&bd00+14-1-4
out (c),c


;; set vsync position
ld bc,&bc07
out (c),c
ld bc,&bd00+6
out (c),c


ld hl,int_rout1
jp int_end


int_end:
ld (int_rout_ptr+1),hl
pop af
pop hl
pop bc
ei
ret


;;end start


.scroll_down
;; check fine value first
    ld a,(scroll_fine_next)
    inc a
    and 7
    ld (scroll_fine_next),a
    or a
    ret nz


;; get the current scroll offset
    ld hl,(scroll_offset)
    ld bc,32
    or a
    sbc hl,bc


;; ensure scroll offset is in range &000-&3ff
    ld a,h
    and &3
    ld h,a


;; store new scroll offset. It is now ready to be written to the CRTC.
    ld (scroll_offset),hl
    ret


;; the scroll offset in CRTC character units
.scroll_offset
    defw 0
;; offset for fine scroll
.scroll_fine
    defb 0
.scroll_fine_next
    defb 0
This is beautiful, thank you so much.

Offline Gryzor

  • Administrator
  • 6128 Plus
  • *****
  • Posts: 16.011
  • Country: gr
  • CPC-Wiki maintainer
    • CPCWiki
  • Liked: 3452
  • Likes Given: 6194
Re: CORSAIR_Trainer
« Reply #29 on: 09:28, 20 October 20 »
Thanks very much Axelay, will give it a whirl tonight.


@Gryzor, ignore my previous post, can you Sticky Axelays vertical scrolling routine above in the programming section?

It must be a separate post to be pinned, I can't just take a text snippet... Feel free anyone to create a new post in that forum and notify me to pin it :)

Offline lmimmfn

  • CPC464
  • **
  • Posts: 17
  • Country: ie
  • Liked: 11
  • Likes Given: 13
Re: CORSAIR_Trainer
« Reply #30 on: 21:30, 20 October 20 »
It must be a separate post to be pinned, I can't just take a text snippet... Feel free anyone to create a new post in that forum and notify me to pin it :)
No problem, i can create a thread tomorrow with Axelay's code, linking related threads and of course attributing the work to those involved and ping you afterwards.


Offline Gryzor

  • Administrator
  • 6128 Plus
  • *****
  • Posts: 16.011
  • Country: gr
  • CPC-Wiki maintainer
    • CPCWiki
  • Liked: 3452
  • Likes Given: 6194
Re: CORSAIR_Trainer
« Reply #31 on: 21:35, 20 October 20 »
Sounds great! Perhaps a wiki article would be better suited, but whatever people want 😁

Offline lmimmfn

  • CPC464
  • **
  • Posts: 17
  • Country: ie
  • Liked: 11
  • Likes Given: 13
Re: CORSAIR_Trainer
« Reply #32 on: 23:18, 20 October 20 »
Sounds great! Perhaps a wiki article would be better suited, but whatever people want 😁
Actually you're correct, wiki would be better, will take longer so will do that at the weekend.
Thanks!

Offline Gryzor

  • Administrator
  • 6128 Plus
  • *****
  • Posts: 16.011
  • Country: gr
  • CPC-Wiki maintainer
    • CPCWiki
  • Liked: 3452
  • Likes Given: 6194
Re: CORSAIR_Trainer
« Reply #33 on: Yesterday at 11:53 »
No problem :) If you need any help let me know :)

Offline fgbrain

  • CPC6128
  • ****
  • Posts: 240
  • Country: gr
    • index.php?action=treasury
    • Chaos CPC Homepage
  • Liked: 141
  • Likes Given: 313
Re: CORSAIR_Trainer
« Reply #34 on: Yesterday at 20:16 »
Quote
It is really weird, for the Amiga( my second machine ) most of the optimization info/tricks are freely available but not in the CPC world?


About vertical pixel perfect hw scrolling,  Pict from Logon System did an article in A 100% back in May 1993.
Can be found now at: https://cpcrulez.fr/coding_logon48-scroll_vertical.htm

_____

6128 (UK keyboard, Crtc type 0/2), 6128+ (UK keyboard), 3.5" and 5.25" drives, Reset switch and Digiblaster (selfmade), Inicron Romram box, Bryce Megaflash, SVideo & PS/2 mouse, , Magnum Lightgun, X-MEM, X4 Board, C4CPC, Multiface2 X4, RTC X4 and Gotek USB Floppy emulator.

Offline lmimmfn

  • CPC464
  • **
  • Posts: 17
  • Country: ie
  • Liked: 11
  • Likes Given: 13
Re: CORSAIR_Trainer
« Reply #35 on: Today at 00:38 »


About vertical pixel perfect hw scrolling,  Pict from Logon System did an article in A 100% back in May 1993.

Can be found now at: https://cpcrulez.fr/coding_logon48-scroll_vertical.htm


Thanks, i did read this before and article is great but running the logon 48 demo, it wouldnt work unless playing with vsynch in WinApe, but when i update the wiki ill add this also.