| |
Trash
Registered: Jan 2002 Posts: 122 |
REU detection problem
Hi all, I have a small problem with my REU-detectioncode.
It correctly detects REUs on all machines I have tested it on but if the REU is 1024kb or larger it reports 255 banks (16mb) in $fe instead of the correct number of banks. 128 -> 512 kb works just fine.
Can anybody see were I've got it wrong?
;----------------------------------------------------------
; Determines if we have a REU present or not
;----------------------------------------------------------
; Note: interrupt-flag must be set (sei)
; this trashes the content of the REU (transfers $0000 - $00ff to each bank of the REU)
;----------------------------------------------------------
; The MSB of $ff will be set if REU is present
; $ff == %1xxxxxxx - REU present
; $ff == %0xxxxxxx - REU not present
; $fe will contain the 0-based number of accessible banks
;----------------------------------------------------------
REU_PRESENT
;----------------------------------------------------------
lda #$00
sta $fe
ldx #8
- sta $df00, x ; Set address $0000 from c64, transfer length $0000 and $000000 to REU
dex
bpl -
sta $df0a ; C64 not fixed, REU not fixed
lda #66
sta $df07 ; We want to move 66 bytes in order for the operation to take more than 65 cycles (the maximum no of cycles on a rasterrow)
lda #%10110000
sta $df01
lda $d012
- cmp $d012
beq -
lda #$fb
- cmp $d012
bne -
lda #%10110000
sta $df01
ldy $d012
lda $ff
and #%01111111
cpy #$fb
beq + ; No REU since the execution of the transfer took less than a rasterline
ora #%10000000 ; REU exists
+ sta $ff
lda $ff
bmi + ; REU exists, determine number of banks
rts
+ lda #1
sta $df07
lda #<counter
sta $df02
lda #>counter
sta $df03
lda #%10110000
ldx #0
- stx $df06 ; Set bank
sta $df01 ; Transfer 1 byte from c64 to REU
dec counter ; Decrease counter
inx ; Increase bank-number
bne -
lda #%10110001
stx $df06
sta $df01 ; Transfer the first value from REU @ $000000 to address of counter
ldx counter
stx $fe
rts
counter .byte $ff
|
|
| |
chatGPZ
Registered: Dec 2001 Posts: 11386 |
$ff is not initialized? |
| |
Trash
Registered: Jan 2002 Posts: 122 |
Quote: $ff is not initialized?
It is... |
| |
chatGPZ
Registered: Dec 2001 Posts: 11386 |
where? (however, that doesnt seem to be the problem)
you gotta explain how the loop at the bottom is supposed to work, i somehow dont see it working at all :) |
| |
Trash
Registered: Jan 2002 Posts: 122 |
Quote: where? (however, that doesnt seem to be the problem)
you gotta explain how the loop at the bottom is supposed to work, i somehow dont see it working at all :)
This code will always ensure that $ff contains a negative or a positive value in all outcomes. And you are right, that isn't the problem.
All REUs is detected to the level that it finds if a REU is plugged in or not so the problem is somewhere after the first rts.
lda $ff
and #%01111111
cpy #$fb
beq +
ora #%10000000
+ sta $ff
|
| |
chatGPZ
Registered: Dec 2001 Posts: 11386 |
i think i got the idea of the last loop now... you are writing $ff, $fe etc into increasing bank numbers, then because of the wraparound after $100 iterations the first bank will contain the number of total banks.
i vaguely remember a problem with this... you might check the vice source. ie in some implementations of the REU (hardware i mean) the wraparound doesnt work that way, you will get "open" banks instead |
| |
Trash
Registered: Jan 2002 Posts: 122 |
Correct, will check Vice sources tonight in order to understand how to solve the problem or just determine that I support up to 512kb with my detection code...
Thanks! |
| |
chatGPZ
Registered: Dec 2001 Posts: 11386 |
did a quick check, apparently the sdram wraparound is indeed the same for all sizes >=1024. so to tell larger sizes apart you need to use a different way. which is a good idea in any case - because this is something that is completely undefined. |
| |
tlr
Registered: Sep 2003 Posts: 1790 |
Yes, the wrapping as a bit strange as groepaz notes.
This is the detection code i use in Superfluid V0.6:(returns size >> 16 in Acc)
;************************************************************************* *
;*
;* NAME detect_reu
;*
;* DESCRIPTION
;* Detect REU presence and size (type)
;*
;* We do this by checking the start of each power of 2 bank for the
;* presence of ram (pattern $55 and $aa), and then verifying that the
;* start of bank 0 wasn't affected (i.e aliasing).
;*
;******
detect_reu:
php
sei
lda #%00000001
dr_lp1:
pha
jsr dr_testpage
pla
bcc dr_ex1
asl
bne dr_lp1
dr_ex1:
ror
beq dr_ex2
; adjust to be mask
sec
sbc #1
rol
dr_ex2:
plp
rts
dr_testpage:
tay
; preserve initial contents
jsr dr_from_reu
pha
lda #$55
jsr dr_testpage2
lda #$aa
jsr dr_testpage2
; restore initial contents
pla
jsr dr_to_reu
; check result
lda #%00001010
bit detect_res_zp
bne drt_fl1
lsr
; lda #%00000101
bit detect_res_zp
beq drt_fl1
sec
rts
drt_fl1:
clc
rts
dr_testpage2:
sty detect_tmp_zp
sta detect_cmp_zp
jsr dr_to_reu
jsr drt2_common
ldy #0
drt2_common:
jsr dr_from_reu
clc
eor detect_cmp_zp
beq drt2_skp1
sec
drt2_skp1:
rol detect_res_zp
ldy detect_tmp_zp
rts
; Acc = data, Y = page, C = direction (1 = REU -> C64)
dr_to_reu:
sta detect_data_zp
clc
dc.b $24
dr_from_reu:
sec
ldx #%00000000
stx $df0a ; control
; set c64 address
lda #<detect_data_zp
sta $df02
stx $df03
; set REU address
stx $df04
stx $df05
sty $df06
; set len
lda #1
sta $df07
stx $df08
; commence
lda #%10010000 >> 1
rol
sta $df01
lda detect_data_zp
rts |
| |
AlexC
Registered: Jan 2008 Posts: 299 |
Just a side note: SuperFluid 0.6 detection code work with 16mb reu in Ultimate64 with 1.10 firmware. Just make sure to reboot U64 after mounting cartridge. |
| |
Walt
Registered: May 2004 Posts: 47 |
Hi...
Here is my detection routine, written in KickAss.
Tested on VICE 2.4 and 1541U2+ :)
You can of course skip the backup and restore parts if you want...
.const REUStatus = $df00
.const REUCommand = $df01
.const REUC64 = $df02
.const REUREU = $df04
.const REUTransLen = $df07
.const REUIRQMask = $df09
.const REUAddrMode = $df0a
.const REUStatusFault = 32 // Error during compare
.const REUCMDExecute = 128+16 // Start transfer/compare/swap without waiting for write to $ff00
.const REUCMDExecuteFF00 = 128 // Start transfer/compare/swap after write access to $ff00 (for using RAM below I/O area $d000-$dfff)
.const REUCMDAutoload = 32 // Restore address and length registers after execute
.const REUCMDTransToREU = 0 // Bit 0-1 : 00 = transfer C64 -> REU
.const REUCMDTransToC64 = 1 // Bit 0-1 : 01 = transfer REU -> C64
.const REUCMDSwap = 2 // Bit 0-1 : 10 = swap C64 <-> REU
.const REUCMDCompare = 3 // Bit 0-1 : 11 = compare C64 - REU
.const REUAddrFixedC64 = 128 // Bit 7 : C64 ADDRESS CONTROL (1 = fix C64 address)
.const REUAddrFixedREU = 64 // Bit 6 : REU ADDRESS CONTROL (1 = fix REU address)
Byte: .byte 0
REUFound: .byte 0 // 0 = No REU
REUSize: .byte 0 // Number of 64KB pages :
// 2 = 128KB, 4 = 256KB, 8 = 512KB, 16 = 1MB, 32 = 2MB, 64 = 4MB, 128 = 8MB, 255=16MB
CheckREUSize: lda #0
tax
ClearREUOut: sta REUOut,x
sta REUCount,x
inx
bne ClearREUOut
lda #0
sta REUCommand
sta REUIRQMask
sta REUAddrMode // No fixed addresses (increment both C64 and REU counters)
lda REUStatus
// Backup REU first byte of each 64K block ( $xx0000 )
ldx #0
ldy #0
BackupLoop: stx REUC64 // Location of backup buffer, $100 aligned
lda #>REUBackup
sta REUC64+1
sty REUREU // REU address
sty REUREU+1
stx REUREU+2
lda #1 // Tell REU to transfer 1 byte
sta REUTransLen
sty REUTransLen+1
lda #REUCMDExecute+REUCMDTransToC64 // Do the transfer
sta REUCommand
inx
bne BackupLoop
// Write $00-$ff in $xx0000
WriteLoop: lda #<Byte
sta REUC64
lda #>Byte
sta REUC64+1
sty REUREU
sty REUREU+1
stx REUREU+2
lda #1
sta REUTransLen
sty REUTransLen+1
stx Byte
lda #REUCMDExecute+REUCMDTransToREU
sta REUCommand
inx
bne WriteLoop
ReadLoop: lda #<Byte
sta REUC64
lda #>Byte
sta REUC64+1
sty REUREU
sty REUREU+1
stx REUREU+2
lda #1
sta REUTransLen
sty REUTransLen+1
sty Byte
lda #REUCMDExecute+REUCMDTransToC64
sta REUCommand
lda Byte
sta REUOut,x
inx
bne ReadLoop
RestoreLoop: stx REUC64 // Location of backup buffer, $100 aligned
lda #>REUBackup
sta REUC64+1
sty REUREU // REU address
sty REUREU+1
stx REUREU+2
lda #1 // Tell REU to transfer 1 byte
sta REUTransLen
sty REUTransLen+1
lda #REUCMDExecute+REUCMDTransToREU // Do the transfer
sta REUCommand
inx
bne RestoreLoop
// Count
lda #1
CountLoop1: ldy REUOut,x
sta REUCount,y
inx
bne CountLoop1
inx // Skip 0
lda #0
CountLoop2: clc
adc REUCount,x
inx
bne CountLoop2
sta REUSize
lda REUCount+1
ora REUCount+255
sta REUFound
rts
.pc = $8000 "REU data" virtual
REUBackup: .fill $100,0 // Backup of actual content at $xx0000
REUOut: .fill $100,0 // Bytes read from $xx0000
REUCount: .fill $100,0 // REUOut positions set to 1 in this table |