Jump to content
IGNORED

Part 2 - CDFJ+ Details


SpiceWare

Recommended Posts

Note: a copy of Part 2 - CDFJ Details with addition of the Fast Fetchers section towards the bottom

 

CDFJ+ is built around data streams.  A data stream is a sequence of data elements made available over time - basically a list of values such as:

  • 10
  • 55
  • 20
  • 25
  • ...

 

The data stream will auto-advance so that the first time you read it you'd get 10, the next time you'd get 55, then 20 and so on. Data streams are very helpful during the kernel as you can update any TIA register in just 5 cycles:

LDA #DS0DATA
STA GRP0

 

 

General Purpose Data Streams

 

There are 32 general purpose data streams named DS0DATA thru DS31DATA. Each data stream has an increment value associated with it for the auto-advance feature. Example increments:

  • 1.0 for 1LK player graphics
  • 0.20 to repeat chunky playfield graphics over 5 scanlines
  • 2.0 to skip every other value. This is extremely useful for interlaced bitmap graphics, which are typical seen as 96 or 128 pixels across.

 

 

Communication Data Stream

 

There is a dedicated communication data stream named DSCOMM used for transferring data between the 6507 and ARM processors.

 

 

Jump Data Streams

 

There are 2 data streams for jumps named DSJMP1 and DSJMP2.  These override JMP $0000 and JMP $0001 respectively, providing 3 cycle flow control within the kernel. This means instead of counting scanlines and branching your kernel would look something like this kernel from Draconian:

; data stream usage for game screen
DS_GRP0             = DS0DATA
DS_GRP1             = DS1DATA
DS_HMP0             = DS2DATA
DS_HMP1             = DS3DATA
DS_MISSILE0         = DS4DATA   ; HMM0 and ENAM0
DS_MISSILE1         = DS5DATA   ; HMM1 and ENAM1
DS_BALL             = DS6DATA   ; HMBL and ENABL
DS_COLOR            = DS7DATA   ; color change for players and ball only
DS_SIZE             = DS8DATA   ; size change for all objects

NormalKernel:               ;   20
        lda #DS_SIZE        ; 2 22 <- just to keep stream in sync
nk1:    lda #DS_COLOR       ; 2 24 2 33 from Resm0Strobe28 <- just to keep stream in sync
        lda #DS_HMP0        ; 2 26
        sta HMP0            ; 3 29
        lda #DS_HMP1        ; 2 31
        sta HMP1            ; 3 34
        lda #DS_MISSILE0    ; 2 36
        tax                 ; 2 38
        stx HMM0            ; 3 41
        lda #DS_MISSILE1    ; 2 43
        tay                 ; 2 45
        sty HMM1            ; 3 48
        lda #DS_BALL        ; 2 50
        sta HMBL            ; 3 53
        sta ENABL           ; 3 56
        lda #DS_GRP0        ; 2 58
        sta GRP0            ; 3 61
        lda #DS_GRP1        ; 2 63
        sta WSYNC           ; 3 66/0
        sta HMOVE           ; 3  3
        sta GRP1            ; 3  6 <- also updates GRP0 and BL
        DIGITAL_AUDIO       ; 5 11
        stx ENAM0           ; 3 14
        sty ENAM1           ; 3 17
        jmp FASTJMP1        ; 3 20
        
ExitKernel:
        ...
        
Resm0Strobe23:                  ;   20
        sta RESM0               ; 3 23
        lda #DS_SIZE            ; 2 25
        sta NUSIZ0              ; 3 28  <- changes missile size
        jmp nk1                 ; 3 31
        
Resm0Strobe28: 
        ...

 

The data stream DSJMP1 is initially filled with addresses for NormalKernel, and ends with the address for ExitKernel.  The player, missile and ball reuse routines will change individual values in DSJMP1 to jump to reposition kernels such as Resm0Strobe23. 

 

 

Audio Data Stream

 

Lastly there's an audio data stream named AMPLITUDE. It will return a stream of data to play back a digital sample, or to play back 3 voice music with custom waveforms. The macro DIGIT_AUDIO in the above Draconian kernel is defined as:

    MAC DIGITAL_AUDIO
        lda #AMPLITUDE
        sta AUDV0
    ENDM

 

 

6507 Interface

 

From the Atari's point of view CDFJ only has 4 registers defined in the cartridge space.

  • DSWRITE at $1FF0
  • DSPTR at $1FF1
  • SETMODE at $1FF2
  • CALLFN at $1FF3

 

DSPTR is used to set the Display Data address for the DSCOMM data stream - basically setting the RAM location the 6507 code wishes to write to.  Write the low byte of the address first, then the high byte.

 

DSWRITE writes to the address set by DSPTR.  After writing, DSPTR advances to the next RAM location in preparation for the next write:

; define storage in Display Data
_DS_TO_ARM:        
_SWCHA:     ds 1        ; controller state to ARM code
_SWCHB:     ds 1        ; console switches state to ARM code
_INPT4:     ds 1        ; firebutton state to ARM code
_INPT5:     ds 1        ; firebutton state to ARM code

...

        ldx #<_DS_TO_ARM
        stx DSPTR
        ldx #>_DS_TO_ARM
        stx DSPTR
        ldx SWCHA           ; read state of both joysticks
        stx DSWRITE         ; written to _SWCHA 
        ldx SWCHB           ; read state of console switches
        stx DSWRITE         ; written to _SWCHB 
        ldx INPT4           ; read state of left joystick firebutton
        stx DSWRITE         ; written to _INPT4 
        ldx INPT5           ; read state of right joystick firebutton
        stx DSWRITE         ; written to _INPT5 

 

SETMODE controls Fast Fetch Mode and Audio Mode.  Fast Fetch mode overrides the LDA #immediate mode instruction and must be turned on to read from the data streams.  Audio Mode selects between digital sample mode or 3-voice music mode.

 

CALLFN is used to call the function main() in your C code. The value written to CALLFN determines if an interrupt will run to periodically update AUDV0. The interrupt is needed when playing back digital samples or 3-voice music.

        ldy #$FE    ; generate interrupt to update AUDV0 while running ARM code
        sty CALLFN

        ldy #$FF    ; do not update AUDV0
        sty CALLFN

 

Fast Fetchers

 

Fast Fetchers in CDFJ+ have seen 2 optional updates from CDFJ.

 

1) Besides LDA #, you can optionally use LDX # and/or LDY # for Fast Fetch mode. This would free up 4 cycles in the NormalKernel from above, look for the <*==-- comments:

 

NormalKernel:               ;   20
        lda #DS_SIZE        ; 2 22 <- just to keep stream in sync
nk1:    lda #DS_COLOR       ; 2 24 2 33 from Resm0Strobe28 <- just to keep stream in sync
        lda #DS_HMP0        ; 2 26
        sta HMP0            ; 3 29
        lda #DS_HMP1        ; 2 31
        sta HMP1            ; 3 34
        ldx #DS_MISSILE0    ; 2 36 <*==-- no longer need to use TAX for the deferred STX ENAM1
        nop                 ; 2 38 <*==-- 2 freed up cycles
        stx HMM0            ; 3 41
        ldy #DS_MISSILE1    ; 2 43 <*==-- no longer need to use TAY for the deferred STY ENAM0
        nop                 ; 2 45 <*==-- 2 freed up cycles
        sty HMM1            ; 3 48
        lda #DS_BALL        ; 2 50
        sta HMBL            ; 3 53
        sta ENABL           ; 3 56
        lda #DS_GRP0        ; 2 58
        sta GRP0            ; 3 61
        lda #DS_GRP1        ; 2 63
        sta WSYNC           ; 3 66/0
        sta HMOVE           ; 3  3
        sta GRP1            ; 3  6 <- also updates GRP0 and BL
        DIGITAL_AUDIO       ; 5 11
        stx ENAM0           ; 3 14
        sty ENAM1           ; 3 17
        jmp FASTJMP1        ; 3 20

 

2) You can now set a Fast Fetcher offset. By default the offset is 0 so only LDA #DS0DATA thru LDA #AMPLITUDE are overridden, while LDA #$24 thru LDA #$FF would put the normal value of #$24 thru $FF into the Accumulator.

 

If you change the offset to $80 then LDA #DS0DATA + $80 thru LDA #AMPLITUDE + $80 are overridden, while LDA #$00 thru LDA #$7F and LDA #$84 thru LDA #$FF would put the normal value of $00 thru $7F and $84 thru $ff into the Accumulator.

 

Macros are provided to make it easier to use the offset and LDA/X/Y # immediate mode instructions:

 

  • FFA - Fast Fetch using LDA #
  • FFX - Fast Fetch using LDX #
  • FFY - Fast Fetch using LDY #
  • FFSTA - Fast Fetch plus Store using LDA # / STA 
  • FFSTX - Fast Fetch plus Store using LDX # / STX
  • FFSTY - Fast Fetch plus Store using LDY # / STY
  • SLDA - Safe LDA # - validates that value is not overridden for data stream usage.
  • SLDX - Safe LDX # - validates that value is not overridden for data stream usage.
  • SLDY - Safe LDY # - validates that value is not overridden for data stream usage.

 

; macro
    FFA DS0DATA
    
; becomes
    LDA #(DS0DATA + OFFSET)
    
    
    
; macro
    FFSTX AMPLITUDE, AUDV0
    
; becomes
    LDX #$AMPLITUDE
    STX AUDV0
    
    

; macro
    SLDY 10
    
; If offset is 0 a compile time error will occur:

LDY # $a is within Fast Fetcher range of 0 and $23

; If OFFSET is > 10 becomes
    LDY #10

 

 

C Interface
 

From the C code a number of functions have been defined to interact with CDFJ and Display Data:

  • setPointer()
  • setPointerFrac()
  • setIncrement()
  • setWaveform()
  • setSamplePtr()
  • setNote()
  • resetWave()
  • getWavePtr()
  • getWavePtr()
  • getPitch()
  • getRandom32()
  • myMemset()
  • myMemcpy()
  • myMemsetInt()
  • myMemcpyInt()

 

 This section will be expanded upon later.

  • Like 2
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...