Author Topic: cd_loadvram function  (Read 501 times)

touko

  • Hero Member
  • *****
  • Posts: 953
cd_loadvram function
« on: May 21, 2010, 03:29:07 AM »
hi all, have you some speed problems with this function ??? ..

on real hardware of course !!

TheOldMan

  • Hero Member
  • *****
  • Posts: 958
Re: cd_loadvram function
« Reply #1 on: May 21, 2010, 04:56:55 AM »
Yes.... I assume it's due to the cd reading 1 byte at a time (I'm not sure where I read that, so I'm not positive it's true) and the need to bank the i/o buffers in/out of cpu memory.
I do remember reading somewhere that later games re-wrote the cd read functions, and significantly improved performance.

touko

  • Hero Member
  • *****
  • Posts: 953
Re: cd_loadvram function
« Reply #2 on: May 21, 2010, 05:44:00 AM »
Ok, but i think the problem is direct vram transfert by cd bios ..
Because using cd ram as a buffer, and transfert data to vram make a significant speed up.
« Last Edit: May 21, 2010, 09:27:27 AM by touko »

TheOldMan

  • Hero Member
  • *****
  • Posts: 958
Re: cd_loadvram function
« Reply #3 on: May 21, 2010, 07:43:36 AM »
Now, I'm intrigued.... I did some looking at the docs I have, and it looks like cd_loadvram() is a magic kit library function. At least, I have no info on it in the docs I have on the cd-bios.
But I do remember looking at the assembler (I'm not an assembler person, so look was about all I did.), and seeing that it used 2 pages of memory to do the reads...
Leads me to believe magickit is reading into a memory buffer (probably from the cd buffer), and then transferring that to vram. Which would mean it's getting buffered twice.
That's probably due to magic kit supporting reading more than 2K at a time...
But I'm not sure about that...

Love to know if you find a better/faster way. Right now I'm loading about 8K into vram through cd_loadvram(), and it is definately causing major slow-downs :-(

touko

  • Hero Member
  • *****
  • Posts: 953
Re: cd_loadvram function
« Reply #4 on: May 21, 2010, 09:31:37 AM »
If you looks in huc libraries, you should see that cd_loadvram function is very small.
this function use a cd bios routine called cd_load, once, no loop ..

This routine can transfert datas in cd ram, in vram or in mprs ..

A person has found a routine who's using cd ram as buffer and divide by 4 load time.

Code: [Select]
/* FastVRamCDLoad by Orion_ [06/2009]

  Read CD Data by Chunk of 24k in SCD RAM, then Transfer in VRAM

  FastVRamCDLoad(Overlay Index, Sector Base, VRAM Address, Size);

  (use same parameters as cd_loadvram function) */

int FVCLtmpadrs;
int FVCLtmpsize;
int FVCLtmpsect;

#pragma fastcall FastVRamCDLoad(byte al, word bx, word dx, word cx);

FastVRamCDLoad()
{
#asm
_FastVRamCDLoad.4:

; _al = Overlay index
; _bx = Sector
; _cx = Size
; _dx = VRAM Address

; Save MPRs
tma #2
pha
tma #3
pha
tma #4
pha

; Save Parameters
stw _bx,_FVCLtmpsect
stw _dx,_FVCLtmpadrs
stw _cx,_FVCLtmpsize

.loop:
lda _al
pha

; If Size > 24k, then read first 24k
cmpw #24*1024,_cx
blo .ok
stw #24*1024,_cx
.ok:

; Save Size
lda _cx
pha
lda _cx+1
pha

; Modify TIA with VRAM Address
lda _dx
sta .TIASMCL+1
lda _dx+1
sta .TIASMCH+1
stw _cx,.TIASMC+5 ; and Size

; Get Overlay Sector from Index in _ax
lda <_al
asl a
asl a
tay
map ovlarray
ldx ovlarray,Y
iny
lda ovlarray,Y
stx <_al
sta <_ah

; Map 24k of SCD Ram to $4000-$A000
; Free SCD Ram from $DA000 ($6D)
lda #$6D
tam #2
inc a
tam #3
inc a
tam #4

; Add our Sector Offset
addw _bx,_ax

; Store Sector Offset Part 1
lda <_al
sta <_dl

; Compute N Sector to load from Size
addw #2047,_cx ; Round up Size to 2048
lda <_ch
lsr a
lsr a ; = Size / 2048
lsr a
sta <_al

; Store Sector Offset Part 2
lda <_ah
sta <_ch
stz <_cl

; Local Ram Load
lda #1
sta <_dh

; Ram Address
stw #$4000,_bx

; Go Read !
jsr cd_read

; VRAM Transfer
st0 #0
.TIASMCL:
st1 #LOW(0)
.TIASMCH:
st2 #HIGH(0)
st0 #2
.TIASMC:
tia $4000, 2, 0

; Restore Parameters
pla
sta _cx+1
pla
sta _cx
pla
sta _al

; Add 12 Sectors (24k) to Sector Base
addw #12,_FVCLtmpsect
stw _FVCLtmpsect,_bx

; Substract Readed Size from Size
subw _cx,_FVCLtmpsize
beq .end

; If not 0, then read again
lsrw _cx ; Size / 2, because VRAM is word !
addw _cx,_FVCLtmpadrs ; Increment VRAM Address from Readed Size
stw _FVCLtmpadrs,_dx
stw _FVCLtmpsize,_cx ; Remaining Size to Read
jmp .loop

.end:
; Restore MPRs
pla
tam #4
pla
tam #3
pla
tam #2
#endasm
}

The problem is that routine need 24 Kb of cd-ram to works .
« Last Edit: October 14, 2010, 10:37:13 PM by touko »

TheOldMan

  • Hero Member
  • *****
  • Posts: 958
Re: cd_loadvram function
« Reply #5 on: May 21, 2010, 11:16:13 AM »
Haven't really looked at the huc stuff that closely. Sample code is always apreciated...
But, -assuming- I read that right, he's using 3 banks of scd memory to read the cd-data into, then doing a massive tia to send it to vram ? (is that really what it's doing?)

Why? From what I've read in the docs, the cd_read bios function can send straight to vram.
Granted, only 2K at a time, but a tight loop should allow sending without buffering the read at all..? Now I'm gonna have to take some time and really look into this....

touko

  • Hero Member
  • *****
  • Posts: 953
Re: cd_loadvram function
« Reply #6 on: May 21, 2010, 08:28:26 PM »
Haven't really looked at the huc stuff that closely. Sample code is always apreciated...

i post here the HUC's cd_loadvram function
Code: [Select]
; char cd_loadvram(int ovl_index [di], int sect_offset [si], int vramaddr [bx], int bytes [acc])
; ----
; Load CDROM data directly into VRAM
; ----
;
_cd_loadvram.4:
      __stw <_ax
      __ldw <_di
jsr prep_rdsect
      __addw <_si
stz <_cl
sta <_ch
stx <_dl
lda #$FE
sta <_dh
jsr cd_read
tax
cla
rts

As you see it's very small.
but this part of code is interesting
Code: [Select]
lda #$FE
sta <_dh

In this part ,you set the transfert mode of cd_load, $FE set tranfert to vram

Quote
But, -assuming- I read that right, he's using 3 banks of scd memory to read the cd-data into, then doing a massive tia to send it to vram ? (is that really what it's doing?)

Why? From what I've read in the docs, the cd_read bios function can send straight to vram.
Granted, only 2K at a time, but a tight loop should allow sending without buffering the read at all..? Now I'm gonna have to take some time and really look into this....

Yes Orion's routine use 3 scd bank for buffering, and in fact this is the vram transfert who's improving performance.
Why ???
I don't know, vram transfert of scd bios routine is probably very bad.
« Last Edit: May 21, 2010, 08:38:14 PM by touko »

TheOldMan

  • Hero Member
  • *****
  • Posts: 958
Re: cd_loadvram function
« Reply #7 on: May 22, 2010, 03:15:03 AM »
The are only reason I can think of for that to happen is that the cdread function would have to have a loop that transfers single bytes to vram; the tia would eliminate the loop overhead.
Okay, I'm gonna work on some way to actually measure how long this is taking. I'm real curious now, especially since you pointed out that magic kit is using the $FE method to do the read...
But I'm fairly sure that if the vram method is faster, we should be able to speed up the whole cd-load routine, which helps everyone.

touko

  • Hero Member
  • *****
  • Posts: 953
Re: cd_loadvram function
« Reply #8 on: May 22, 2010, 03:52:26 AM »
But I'm fairly sure that if the vram method is faster, we should be able to speed up the whole cd-load routine, which helps everyone.

Yes ,i have thinked the same, this is the reason why i have posted about cd_load  :wink:
Overlays loading is a principal element of a good scd project with HUC, and speed with cd_loadvram is very critical on real hardware.

« Last Edit: May 22, 2010, 03:55:55 AM by touko »