Hardcore Retrogaming

Démarré par upsilandre, Novembre 09, 2013, 04:00:23 PM

« précédent - suivant »

upsilandre

...et le code source (qui entrait pas dans l'autre post)
Spoiler

Citation
   
    processor 6502
    include vcs2600.h
    org $F000


           
VTankP0 = $80
VTankP1 = $81
RotP0 = $82
RotP1 = $83
WaitRotP0 = $84
WaitRotP1 = $85
CurPF0 = $86
CurPF1 = $87
CurPF2 = $88
VBoost = $89
JaugeP0 = $8A
JaugeP1 = $8B
CurSpriteP0 = $8C
CurSpriteP1 = $94
WaitDepP0 = $9C
WaitDepP1 = $9D
OldVTankP0 = $9E
OldVTankP1 = $9F
STHMP0 = $A0
STHMP1 = $A1
VMissP0 = $A2
VMissP1 = $A3
ScoreP0 = $A4
ScoreP1 = $A5
AudioFire = $A6
WaitFireP0 = $A7
WaitFireP1 = $A8
PFScoreP0 = $A9
PFScoreP1 = $AE
Digit1P0 = $B3
Digit2P0 = $B4
Digit1P1 = $B5
Digit2P1 = $B6
DigiTemp = $B7
CurVBoost = $B8
WaitBoost = $B9
HighFreq = $BA
BoostP0 = $BB
BoostP1 = $BC
StrikeP0 = $BD
StrikeP1 = $BE

PFSelect = $F0
TitleScreen = $F1


;***********************intitalisation**************************   


Start
    LDA #0
    STA PFSelect
    STA TitleScreen

Reset
    CLD
    LDX #$EF
    TXS
    LDA #0

EraseRAM
    STA 0,X
    DEX
    BNE EraseRAM

    STA WSYNC
    LDX #4
InitHP0   
   DEX
    BNE InitHP0
    STA RESP0
    LDA #32
    STA HMP0

    STA WSYNC
    LDX #13
InitHP1   
   DEX
    BNE InitHP1
    STA RESP1
    LDA #255
    STA HMP1

    STA COLUBK
    STA CurVBoost

HoldSelect
    LDA SWCHB
    AND #%00000010
    BEQ HoldSelect

    LDA #1
    STA VDELP0

    LDA #4
    STA RotP0

    LDA #12
    STA RotP1

    LDA #10
    STA WaitBoost

    LDA #242
    STA COLUPF

    LDA #44
    STA VTankP0   
    STA VTankP1   
    STA OldVTankP0
    STA OldVTankP1

    LDA #2
    STA WaitRotP0
    STA WaitRotP1
    STA WaitDepP0
    STA WaitDepP1     
   STA WaitFireP0     
   STA WaitFireP1     
   STA RESMP0
    STA RESMP1
    STA AUDC0 


;*******************************Vsync****************************


Frame
    LDA #2
    STA VSYNC   
   STA WSYNC
    STA WSYNC
    STA WSYNC
    LDA #0
    STA VSYNC
    LDX #39
    STX TIM64T   


;******************************Ecran Titre***************************


    LDA TitleScreen
    BNE InGame

    STA COLUBK
    STA CTRLPF
    LDY #17
    LDA #150
    STA TIM64T

TitleBlanking   
   LDA INTIM
    BNE TitleBlanking
    STA VBLANK

StartTitle
    STA WSYNC   
    STA COLUPF
    TYA
    LSR
    TAX           
    LDA TitlePF0Gauche,X
    STA PF0
    LDA TitlePF1Gauche,X
    STA PF1
    LDA TitlePF2Gauche,X
    STA PF2       
   LDA TitlePF0Droite,X
    STA PF0
    LDA TitlePF1Droite,X
    STA PF1
    LDA TitlePF2Droite,X
    STA PF2 
    TYA
    ADC HighFreq
    DEY
    BPL StartTitle

    DEC HighFreq
    BNE TitleON

    INC TitleScreen   
    JMP Reset

TitleON
    LDX #137
    JMP TitleOverscan


InGame


;********************************Audio*******************************


;*****Audio Engine*****


    LDA #8
    STA AUDV0
    STA AUDC1
    LDX #16
    LDA SWCHA
    AND #16
    BNE Audio1

    LDA BoostP0
    BNE Audio2

    LDX #8

Audio1
    LDA SWCHA
    AND #1
    BNE AudioF0

    LDA BoostP1
    BNE Audio2

    LDX #8
    JMP AudioF0

Audio2
    LDX #6

AudioF0
    STX AUDF0


;*****Audio Fire*****


    LDX AudioFire
    BEQ NoAudioFire

    DEX
    STX AudioFire

NoAudioFire
    STX AUDV1   
 

;******************************Collisions*******************************


    LDX #1


;*****Player-player/playfield*****


StartCollision
    LDA StrikeP0,X
    BNE NoCXP0BL

    LDA CXPPMM
    BMI GoCXP0P1       

    LDA CXP0FB,X
    BPL NoCXP0PF

GoCXP0P1
    LDA OldVTankP0,X
    STA VTankP0,X
    LDA STHMP0,X
    LSR
   LSR
    LSR
    LSR
    TAY
    DEY
    TYA
    EOR #255
    ASL     
    ASL
    ASL
    ASL
    STA HMP0,X
    LDA #0
    STA STHMP0,X


;*****Missile-Playfield*****


NoCXP0PF
    LDA CXM0FB,X
    BPL NoCXM0PF

    LDA #2
    STA RESMP0,X
    LDA #0
    STA VMissP0,X
    LDA #4
    STA AUDF1
    LDA #8
    STA AudioFire


;*****Missile-Player*****


NoCXM0PF
    LDA CXM0P,X
    BPL NoCXM0P1

    LDA #2
    STA RESMP0,X
    LDA #0
    STA VMissP0,X
    TXA
    EOR #%00000001   
    TAY
    LDA #0
    STA BoostP0,Y
    LDA ScoreP0,X
    SED
    CLC
    ADC #1   
    STA ScoreP0,X 
    CLD
    TXA
    EOR #%00000001   
    TAY
    LDA #20
    STA StrikeP0,Y   
    LDA #8
    STA AUDF1   
   LDA #16
    STA AudioFire

NoCXM0P1


;*****Boost-Player0*****


    LDA CXP0FB,X
    AND #%01000000
    BEQ NoCXP0BL

    LDA #0
    STA HighFreq
    LDA #15
    STA WaitBoost
    LDA #255
    STA CurVBoost     
   LDA #3
    STA BoostP0,X

NoCXP0BL


;*****Collision Player2*****

    DEX
    BMI EndCollision

    JMP StartCollision

EndCollision


;*********************input Select Playfield******************


    LDA SWCHB
    AND #%00000010
    BNE NoPFSwitch

    LDA PFSelect
    CLC
    ADC #24
    CMP #240
    BNE GoSwitch

    LDA #0

GoSwitch
    STA PFSelect
    JMP Reset

NoPFSwitch


;***********************input Player***********************


    LDX #1


;*****Strike phase*****


StartInputs
    LDA StrikeP0,X
    BEQ NoStrikeP0

    CMP #1
    BNE MainStrikeP0

    LDA CXPPMM
    ORA CXP0FB,X
    BPL StopStrikeP0

    INC StrikeP0,X
    JMP MainStrikeP0

StopStrikeP0       
    DEC StrikeP0,X
    JMP NoStrikeP0   

MainStrikeP0
    DEC StrikeP0,X
    INC RotP0,X
    TXA
    EOR #%00000001   
    TAY
    LDA RotP0,Y
   ASL
    TAY
    LDA VTankP0,X
    STA OldVTankP0,X
    CLC
    ADC CoefDeplacement,Y
    CMP #95
    BMI NoTOPOOBP0

   LDA #250

NoTOPOOBP0   
    CMP #250
    BPL NoBOTOOBP0

    LDA #95

NoBOTOOBP0
    STA VTankP0,X
    INY
    LDA CoefDeplacement,Y
    STA HMP0,X
    STA STHMP0,X
    JMP SpriteSelectP0

NoStrikeP0


;*****Deplacement*****


DeplacementP0

    LDA VTankP0,X
    STA OldVTankP0,X
    LDA #0
    STA STHMP0,X   
   DEC WaitDepP0,X
    BNE EndepP0

    LDA SWCHA
    TXS
    TSX
    BNE AvantP1

    AND #16
    BNE ZeroWaitDepP0
    JMP AvantP0

AvantP1
    AND #1
    BNE ZeroWaitDepP0

AvantP0
    LDA RotP0,X
   ASL
    TAY
    LDA VTankP0,X
    CLC
    ADC CoefDeplacement,Y
    STA VTankP0,X
    INY
    LDA CoefDeplacement,Y
    STA HMP0,X
    STA STHMP0,X
    LDA BoostP0,X
    BEQ NoBoostDepP0

    LDA #8
    STA WaitDepP0,X
    JMP EndepP0   

NoBoostDepP0
    LDA #16
    STA WaitDepP0,X
    JMP EndepP0

ZeroWaitDepP0
    INC WaitDepP0,X

EndepP0


;*****Fire*****


    LDA VMissP0,X
    BNE FireP0

    DEC WaitFireP0,X
    BNE NoFireP0

    LDA INPT4,X
    BMI ZeroWaitFireP0

ReculeP0
    LDA RotP0,X
   EOR #%00001000
    ASL
    TAY
    LDA VTankP0,X
    STA OldVTankP0,X
    CLC
    ADC CoefDeplacement,Y
    STA VTankP0,X
    INY
    LDA CoefDeplacement,Y
    STA HMP0,X
    STA STHMP0,X

initFireP0
    LDA #0
    STA RESMP0,X
    LDA #200
    STA WaitFireP0,X
    LDA #16
    STA AUDF1
    LDA #16
    STA AudioFire
    LDY OldVTankP0,X
    INY
    INY
    INY
    INY
    STY VMissP0,X

FireP0               
   DEC WaitFireP0,X
    LDA RotP0,X
   ASL
    TAY
    LDA VMissP0,X
    CLC
    ADC CoefDeplacement,Y
    STA VMissP0,X
    INY
    LDA CoefDeplacement,Y
    STA HMM0,X
    JMP NoFireP0

ZeroWaitFireP0
    INC WaitFireP0,X


NoFireP0     


;*****Rotation*****


InputRotP0
    DEC WaitRotP0,X
    BNE EndRotP0

gaucheP0
    LDA SWCHA
    TXS
    TSX
    BNE GinputP1

    AND #64
    BNE droiteP0
    JMP GinputP0

GinputP1
    AND #4
    BNE droiteP0

GinputP0
    INC RotP0,X
    JMP InitWaitRotP0

droiteP0
    LDA SWCHA
    TXS
    TSX
    BNE DinputP1

    AND #128
    BNE ZeroWaitRotP0
    JMP DinputP0

DinputP1
    AND #8
    BNE ZeroWaitRotP0

DinputP0
    DEC RotP0,X

InitWaitRotP0
    LDA BoostP0,X
    BEQ NoBoostRotP0

    LDA #8
    STA WaitRotP0,X
    JMP EndRotP0

NoBoostRotP0
    LDA #16
    STA WaitRotP0,X

EndRotP0


;*****Load Sprite*****


SpriteSelectP0
    LDA RotP0,X
    AND #15
   STA RotP0,X
    ASL
    ASL
    ASL
    TAY

    TXS
    TSX
    BNE SpriteP1

    LDX #7
LoadSpriteP0
    LDA TankSprites,Y
    STA CurSpriteP0,X   
    INY
   DEX
    BPL LoadSpriteP0   

   TSX
    JMP EndLoadSpriteP0   

SpriteP1
    LDX #7
LoadSpriteP1
    LDA TankSprites,Y
    STA CurSpriteP1,X   
    INY
   DEX
    BPL LoadSpriteP1   

   TSX
    JMP EndLoadSpriteP0

ZeroWaitRotP0
    INC WaitRotP0,X

EndLoadSpriteP0


;*****Input Player 2*****


    DEX
    BMI EndInputs

    JMP StartInputs

EndInputs   


;*************************Bonus Boost***************************


    LDA CXBLPF
    BMI BoostCollision

    LDA CurVBoost
    BPL BoostFlick

    LDA HighFreq
    BNE BoostFlick

    DEC WaitBoost
    BNE BoostFlick

   
;*****Random Select*****


BoostCollision
    LDA VTankP0
    CLC
    ADC VTankP1
    AND #%00001111
    TAX
    LDA BoostIndex,X
    TAX
    LDA BoostCoord,X
    TAY
    STA WSYNC
InitHBoost
    DEY
    BPL InitHBoost
    STA RESBL
    INX
    LDA BoostCoord,X
    STA HMBL
    INX
    LDA BoostCoord,X
    STA CurVBoost


;*****Boost Flickering*****


BoostFlick
    LDA HighFreq
    AND #%00001000
    BNE BoostON

    LDA #255
    STA VBoost
    JMP BoostOFF

BoostON
    LDA CurVBoost
    STA VBoost

BoostOFF
    DEC HighFreq


;*****Player0 Flickering*****


    LDA BoostP0
    BEQ NoBoostP0

    LDA HighFreq
    BNE FlickP0

    DEC BoostP0
     
FlickP0
    AND #%00000100       
    BNE NoBoostP0

    LDA #56
    STA COLUP0   
    JMP EndBoostP0

NoBoostP0
    LDA #68
    STA COLUP0   

EndBoostP0


;*****Player1 Flickering*****


    LDA BoostP1
    BEQ NoBoostP1

    LDA HighFreq
    BNE FlickP1

    DEC BoostP1
     
FlickP1
    AND #%00000100       
    BNE NoBoostP1

    LDA #140
    STA COLUP1   
    JMP EndBoostP1

NoBoostP1
    LDA #134
    STA COLUP1   

EndBoostP1


;**********************Deplacement horizontal************************


    STA WSYNC
    STA HMOVE


;***************************fin blanking****************************   


blanking
    LDA INTIM
    BNE blanking
    STA VBLANK


;**************************construction image*********************** 


    STA CXCLR


;*****Score*****


;InitScore

    LDA #2
    STA CTRLPF

    LDA WaitFireP0
    LSR
    LSR
    LSR
    LSR   
    STA JaugeP0

    LDA WaitFireP1
    LSR
    LSR
    LSR
    LSR   
    STA JaugeP1
   
   LDA ScoreP0
    AND #%00001111
    ASL
    ASL
    ASL
    STA Digit1P0

    LDA ScoreP0
    AND #%11110000
    LSR
    STA Digit2P0

    LDA ScoreP1
    AND #%00001111
    ASL
    ASL
    ASL
    STA Digit1P1

    LDA ScoreP1
    AND #%11110000
    LSR
    STA Digit2P1

    LDY #4

LoadScorePF
    LDX Digit1P0
    LDA AllDigits,X
    STA DigiTemp

    LDX Digit2P0
    LDA AllDigits,X
    ASL
    ASL
    ASL
    ASL
    ORA DigiTemp
    INC Digit1P0
    INC Digit2P0
    STA PFScoreP0,Y

    LDX Digit1P1
    LDA AllDigits,X
    STA DigiTemp

    LDX Digit2P1
    LDA AllDigits,X
    ASL
    ASL
    ASL
    ASL
    ORA DigiTemp
    INC Digit1P1
    INC Digit2P1
    STA PFScoreP1,Y

    DEY
    BPL LoadScorePF

    LDY #9

ScanScore
    STA WSYNC
    LDA #0
    STA PF2

ScanScoreP0
   TYA
    LSR
    TAX
    LDA PFScoreP0,X       
   STA PF1

ScanJaugeP0
    TYA
    SEC
    SBC JaugeP0
    BPL ScanScoreP1
    LDA #24
    STA PF2   

ScanScoreP1
    TYA
    LSR
    TAX
    LDA PFScoreP1,X       
   STA PF1
    LDA #0
    STA PF2

ScanJaugeP1
    TYA
    SEC
    SBC JaugeP1
    BPL NextScoreLine
    LDA #24
    STA PF2 

NextScoreLine
    DEY
    BPL ScanScore

    STA WSYNC
    LDA #0
    STA PF1
    STA PF2


;*****Playfield*****


    LDY #95
    LDA #17
    STA CTRLPF


Playfield
    TYA
    LSR
    LSR
    TAX
    LDA ArenePF0,X
    STA CurPF0
    TXA
    CLC
    ADC PFSelect
    TAX
    LDA ArenePF1,X
    STA CurPF1
    LDA ArenePF2,X
    STA CurPF2   

Boost
    CPY VBoost
    BNE NoBoost

    LDA #2
    STA ENABL
    JMP TankP0

NoBoost
    LDA #0
    STA ENABL


;*****Players*****


TankP0
    TYA
    SEC
    SBC VTankP0
    TAX
    AND #%11111000
    BEQ ActiveP0

    LDA #0
    STA GRP0
    JMP MissP0

ActiveP0
    LDA CurSpriteP0,X
    STA GRP0

MissP0
    CPY VMissP0
    BNE ActiveMissP0

    LDX #2
    TXS
    JMP TankP1

ActiveMissP0
    LDX #0
    TXS       

TankP1
    TYA
    SEC
   SBC VTankP1
    TAX
    AND #%11111000
    BEQ ActiveP1

    LDA #0
   JMP MissP1

ActiveP1
    LDA CurSpriteP1,X

MissP1   
    CPY VMissP1
    BNE ActiveMissP1

    LDX #2
    JMP EndPlayers   

ActiveMissP1
    LDX #0

EndPlayers   


;*****Remplissage des registres*****


    STA WSYNC
    STA GRP1
    LDA CurPF0
    STA PF0
    LDA CurPF1
    STA PF1
    STX ENAM1
    TSX
    STX ENAM0
    LDA CurPF2
    STA PF2

    DEY
    BPL Playfield


;******************************Overscan****************************


    STA WSYNC
    LDX #19

TitleOverscan
    STA WSYNC

    LDA #0
    STA PF0
    STA PF1
    STA PF2
    STA GRP0
    STA GRP1
    STA ENAM0
    STA ENAM1
    STA HMCLR
   

   STX TIM64T
overscan
    LDA INTIM
    BNE overscan
    LDA #2
    STA VBLANK
    JMP Frame


;*********************************Data*****************************


;*****Deplacement*****


CoefDeplacement
    BYTE 254,0
    BYTE 254,255
    BYTE 254,239
    BYTE 255,239
    BYTE 0,239
    BYTE 1,239
    BYTE 2,239
    BYTE 2,255
    BYTE 2,0
    BYTE 2,16
    BYTE 2,32
    BYTE 1,32
    BYTE 0,32
    BYTE 255,32
    BYTE 254,32   
    BYTE 254,16

BoostCoord
    BYTE 8,239,47
    BYTE 4,64,84
    BYTE 12,143,10
    BYTE 4,64,10
    BYTE 12,143,84

BoostIndex
    BYTE 0,3,6,9,12,0,3,6,9,12,0,3,6,9,12,0


;*****sprites*****


TankSprites
    BYTE $63,$63,$7F,$7F,$7F,$6B,$08,$08
    BYTE $04,$0E,$4E,$FF,$FF,$79,$64,$24
    BYTE $18,$1C,$0E,$DF,$FF,$7C,$3A,$19
    BYTE $18,$3E,$1F,$1C,$7C,$FB,$78,$1C
    BYTE $FC,$FC,$38,$3F,$38,$FC,$FC,$00
    BYTE $1C,$78,$FB,$7C,$1C,$1F,$3E,$18
    BYTE $19,$3A,$7C,$FF,$DF,$0E,$1C,$18
    BYTE $24,$64,$79,$FF,$FF,$4E,$0E,$04
    BYTE $08,$08,$6B,$7F,$7F,$7F,$63,$63
    BYTE $24,$26,$9E,$FF,$FF,$72,$70,$20
    BYTE $98,$5C,$3E,$FF,$FB,$70,$38,$18
    BYTE $38,$1E,$DF,$3E,$38,$F8,$7C,$18
    BYTE $3F,$3F,$1C,$FC,$1C,$3F,$3F,$00
    BYTE $18,$7C,$F8,$38,$3E,$DF,$1E,$38
    BYTE $18,$38,$70,$FB,$FF,$3E,$5C,$98
    BYTE $20,$70,$72,$FF,$FF,$9E,$26,$24


TitlePF0Gauche
    BYTE $EF,$2F,$2F,$2F,$2F,$2F,$AF,$2F,$EF
TitlePF1Gauche
    BYTE $FF,$00,$95,$95,$9D,$95,$DD,$00,$FF
TitlePF2Gauche
    BYTE $FF,$00,$54,$56,$36,$55,$55,$00,$FF
TitlePF0Droite
    BYTE $FF,$0F,$EF,$2F,$EF,$8F,$EF,$0F,$FF
TitlePF1Droite
    BYTE $FF,$00,$77,$55,$75,$45,$77,$00,$FF
TitlePF2Droite
    BYTE $3F,$20,$2E,$2A,$2A,$2A,$2E,$20,$3F


ArenePF0
    BYTE $FF,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$FF


ArenePF1
    BYTE $FF,$00,$00,$00,$00,$00,$00,$00,$60,$20,$20,$21,$21,$20,$20,$60,$00,$00,$00,$00,$00,$00,$00,$FF
    BYTE $FF,$00,$00,$00,$F0,$E0,$C1,$83,$06,$0C,$18,$18,$18,$18,$0C,$06,$83,$C1,$E0,$F0,$00,$00,$00,$FF
    BYTE $FF,$00,$00,$00,$00,$78,$78,$78,$78,$78,$00,$00,$00,$00,$78,$78,$78,$78,$78,$00,$00,$00,$00,$FF
    BYTE $FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF
    BYTE $FF,$00,$00,$00,$43,$40,$40,$40,$40,$7F,$00,$00,$00,$00,$7F,$40,$40,$40,$40,$43,$00,$00,$00,$FF
    BYTE $FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF
    BYTE $FF,$00,$00,$00,$FF,$80,$80,$80,$80,$80,$80,$80,$80,$80,$80,$80,$80,$80,$80,$FF,$00,$00,$00,$FF
    BYTE $FF,$00,$00,$00,$00,$00,$06,$06,$06,$06,$07,$07,$01,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF
    BYTE $FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF
    BYTE $FF,$80,$80,$80,$80,$84,$84,$84,$84,$84,$84,$84,$84,$84,$84,$84,$84,$84,$84,$04,$04,$04,$04,$FF


ArenePF2
    BYTE $FF,$00,$00,$00,$80,$80,$80,$80,$00,$00,$00,$07,$07,$00,$00,$00,$80,$80,$80,$80,$00,$00,$00,$FF
    BYTE $FF,$C0,$C0,$C0,$06,$03,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$01,$03,$06,$C0,$C0,$C0,$FF
    BYTE $FF,$C0,$80,$00,$00,$30,$60,$C0,$82,$06,$0E,$1E,$1E,$0E,$06,$82,$C0,$60,$30,$00,$00,$80,$C0,$FF
    BYTE $FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$C0,$C0,$C0,$C0,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF
    BYTE $FF,$00,$00,$00,$FF,$00,$00,$00,$00,$87,$80,$80,$80,$80,$87,$00,$00,$00,$00,$FF,$00,$00,$00,$FF
    BYTE $FF,$00,$00,$00,$1E,$1E,$1E,$1E,$FE,$FE,$FE,$FE,$FE,$FE,$9E,$9E,$80,$80,$80,$80,$00,$00,$00,$FF
    BYTE $FF,$00,$00,$00,$3F,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3F,$00,$00,$00,$FF
    BYTE $FF,$00,$00,$00,$78,$78,$06,$06,$FE,$FE,$FF,$FF,$F7,$F7,$FE,$FE,$18,$18,$06,$06,$00,$00,$00,$FF
    BYTE $FF,$80,$80,$00,$00,$80,$80,$80,$80,$80,$80,$80,$80,$80,$80,$80,$80,$80,$80,$00,$00,$80,$80,$FF
    BYTE $FF,$04,$04,$04,$04,$84,$84,$84,$84,$84,$84,$84,$84,$84,$84,$84,$84,$84,$84,$80,$80,$80,$80,$FF


AllDigits
    BYTE %00001110
    BYTE %00001010
    BYTE %00001010
    BYTE %00001010
    BYTE %00001110
    BYTE 0,0,0

   BYTE %00000010
    BYTE %00000010
    BYTE %00000010
    BYTE %00000010
    BYTE %00000010
    BYTE 0,0,0

    BYTE %00001110
    BYTE %00000010
    BYTE %00001110
    BYTE %00001000
    BYTE %00001110
    BYTE 0,0,0

    BYTE %00001110
    BYTE %00000010
    BYTE %00000110
    BYTE %00000010
    BYTE %00001110
    BYTE 0,0,0

    BYTE %00001010
    BYTE %00001010
    BYTE %00001110
    BYTE %00000010
    BYTE %00000010
    BYTE 0,0,0

    BYTE %00001110
    BYTE %00001000
    BYTE %00001110
    BYTE %00000010
    BYTE %00001110
    BYTE 0,0,0

    BYTE %00001110
    BYTE %00001000
    BYTE %00001110
    BYTE %00001010
    BYTE %00001110
    BYTE 0,0,0

    BYTE %00001110
    BYTE %00000010
    BYTE %00000010
    BYTE %00000010
    BYTE %00000010
    BYTE 0,0,0

    BYTE %00001110
    BYTE %00001010
    BYTE %00001110
    BYTE %00001010
    BYTE %00001110
    BYTE 0,0,0

    BYTE %00001110
    BYTE %00001010
    BYTE %00001110
    BYTE %00000010
    BYTE %00001110
    BYTE 0,0,0



    org $F7FC   
    WORD Start 
    WORD Start 
[Fermer]

upsilandre

Je me suis commandé ca



Une cartouche special pour y stocker les roms que je veux. De quoi mettre tous mes programmes (j'ai une vieille carte SD 1Go ca suffirat pour y mettre des centaines de milliers de ROMs homebrew) et les faire tourner sur une vrai console comme a l'epoque en passant par une EPROM. Idealement j'aurais préféré le faire sur une console NTSC mais bon je me contenterais de ca

Je me suis commandé ca aussi car je n'ai plus les joystick originaux et c'est incontournable pour jouer sur 2600!
http://www.priceminister.com/offer?action=desc&aid=672651279&productid=235386158

Par contre j'ai pas reussi a trouver le signal sur mon plasma meme en SECAM. Les tunners des TV modernes ont vraiment du mal avec le signal des vieilles consoles, domage l'emulateur rendait pas mal sur mon plasma.
Mais j'ai reussi a trouver un bon signal sur ma petite TV a tube 13" que j'ai installé a coté de mon plasma donc ca ira comme ca, 100% oldschool.
J'ai installé ma 2600 au dessus de ma PS4 et j'ai pu faire tourner cote a cote Defender sur 2600 et Resogun sur PS4  :cool: (Resogun est un remake de Defender)



upsilandre

#47
J'ai recu mes 2 joystick originaux, nickel c'est du neuf. j'aime vraiment bien cette manette, elle est agreable, content de la retrouver.

J'ai recu aussi ma cartouche magique "HARMONY", nickel aussi, c'est du beau boulot, en aparence c'est exactement comme une vrai cartouche de jeu. pour la faire fonctionner me manquait une carte SD et un lecteur de carte SD.
Pour la carte SD finallement j'en ai retrouvé une de 1Go dans un vieux APN (sachant que l'integralité des ROMs officiels c'est 3.5Mo) et au moment d'aller acheter un lecteur de carte SD j'ai decouvert que j'en avais un sur mon PC   :vice:

Normalement faut changer le firmware de la cartouche car par defaut c'est du NTSC mais j'ai testé tout de suite la cartouche et c'est passé quand meme (ma TV suporte le 60hz) mais en noir et blanc et du coup j'ai pu tout de suite lancer mon jeu Tank2600 et le voir tourner sur une vrai console, magique   :love:

Du coup ca a si bien fonctionné que j'ai tout de suite fait une adaptation PAL de mon jeu (a l'arrache comme on l'a toujours subit nous meme sur nos consoles de l'epoque, c'est a dire ajouter des bandes en haut et en bas, modifier la palette, et donc un jeu ralenti de 20%) pour me rendre compte que c'etait pas une console PAL mais bien une console SECAM que j'avais (le privilege francais de l'epoque, les consoles sont ensuite rapidement passé au PAL mais comme c'est un model plus recent j'esperais que ca soit du PAL...) et la palette de couleur est une horreur   :burp:

en NTSC t'as une palette de 128 couleurs, en SECAM t'as... 8 couleurs  :nerd:  (enfin 6 et un noir et un blanc).
Toutes les VCS ont un switch pour passer la console en Noir&blanc et en faite la VCS SECAM est tout le temps en mode noir&blanc. elle n'utilise pas les 4bit de couleur du registre dédié a cela, juste les 3bit de luminance comme en mode noir et blanc sauf qu'elle remplace les 6 teintes de gris par quelques couleurs bien flashy, une horreur
c'est pour ca que j'ai ete surpris de decouvrir qu'il y avait une palette de 128 couleurs en commancant la programmation car c'est pas le souvenir que j'en avais, tu m'etonnes  :nerd:


un exemple de jeu PAL sur une console PAL




et le meme jeu sur une console francaise SECAM




C'est en france qu'on a eu la VCS la plus pourri au monde, c'est un peu triste  :/
Du coup je vais peut etre me prendre une 2600jr qui est la premiere VCS francaise en PAL


en tout cas bravo a l'emulateur, mon jeu tourne pareille que sur l'emulateur. Emulateur qui dailleurs emule bien aussi la palette SECAM si on veut.
Pouvoir programmer et en quelques secondes faire tourner son propre jeu sur une vrai console de l'epoque et une vieille TV c'est vraiment magique et excitant et d'une simplicité enfantine. ca marche super bien.


Mon installation actuel

upsilandre

Maintenant que je peux faire des tests sur une vrai TV et vu que sur la VCS c'est toi qui controle les scanlines et la Vsync le premier truc que t'as envie de tester c'est les limites de ta TV

- Premier constat quand j'affiche un nombre de scanline impair entre 2 Vsync ca bug un peu niveau couleur (une bande rose en haut de l'ecran) donc faut cibler un nombre pair de scanline a priori
- Je peux monter jusqu'a 54hz sur ma TV ensuite je perd la couleur (j'ai pas testé jusqu'a ou je peux monter sans perdre la stabilité de l'image mais c'est au moins 60hz)
- Je peux descendre jusuq'a 46hz ensuite je perd la stabilité


J'ai testé aussi la durée du signal de Vsync car dans les docs on te dit d'envoyer un signal de Vsync d'une durée de 3 scanlines pas plus ni moins donc envie de tester les limites de cette injonction.

- Avec une durée de 1 ou 2 scanlines ca passe toujours sur ma TV qui sont forcement moins capricieuse qu'a l'epoque.
- Avec une durée la plus courte possible de seulement quelques cycles CPU ca ne marche plus, faut quand meme viser plutot une durée de 1 scanline minimum (mais vaut mieux sans doute s'en tenir a la regle de 3 pour une bonne compatibilité).
- J'ai testé aussi une durée jusqu'a 20 scanlines et ca pose pas de probleme, y a pas de limite maximum je pense si ce n'est que ca finit par deborder de l'overscan et ca te trace des lignes vertes en haut de l'ecran et que ca n'a aucun interet de faire durer le signal de Vsync audela du necessaire

upsilandre

Aparement on peut faire de l'entrelacé 480i en jouant avec la Vsync. une frame sur 2 tu balances la Vsync pile au milieu d'une scanline (donc entre 2 Hsync) pour avoir un decalage vertical d'une demi-ligne.
Pas tres interressant a utiliser vu que meme sans cela c'est deja la resolution horisontal qui est largement a la traine donc ca ne fait que creuser le gap (et ajouter du flickering) mais bon a savoir

En faite toutes nos vieilles consoles 2D de la VCS a la neogeo ont la meme resolution vertical qui est imposé par la technologie des TV, les quelques differences de resolutions se font principalement sur l'horisontal qui elle est impacté par la velocité du chip graphique

upsilandre

#50
Je me prépare doucement a attaquer un second projet sur la 2600 mais j'ai pas pu m'empecher de feuilleter les documents de la Channel F de Fairchild (ou VES), la premiere console de jeu sortie l'année precedent la 2600 et que j'ai dans ma collection




Si j'avais le temps je m'amuserais bien a programmer un truc dessus mais ca a l'aire hard, a part les documents originaux de 1976 y a pas grand chose et pas de communauté. je sais juste que DASM qui me sert pour compiler le code 6502 serait capable aussi de compiler du code F8 (le cpu exotique de la channel F) mais c'est chaud.

Faut savoir que Fairchild c'est un fabriquant de semi-conducteur, ils ont inventé le circuit integré et ce sont les fondateurs de Fairchild qui ont ensuite fondé le concurent Intel, ca c'est pour le contexte...
Ils etaient donc la a la naissance des semi-conducteurs ce qui leur a donné cette position favorable pour commercialiser la toute premiere console de jeu en y mettant leur premier CPU qui est asser exotique d'ou la difficulté de la tache.
Meme les mnemoniques de l'op-code ont rien a avoir avec ceux qu'on utilise en assembleur pour les autres cpu, a priori c'est vraiment pas acueillant.

Pas vraiment de RAM pour le CPU mais un scratchpad qui est une sorte de RAM interne au CPU qu'on utilise comme des registres. y en a 64 ca represente la moitié de la RAM de la 2600 donc de ce coté ca reste asser proche mais la facon d'y acceder est un peu tordu, c'est pas vraiment de la RAM donc y a pas d'adressage mais on peut pas non plus acceder directement a ces 64 registres, y en a seulement 16 accessibles directement et ensuite y a une forme d'indexation avec un autre registre pour permettre d'acceder a l'ensemble donc un peu plus compliqué...

Y a pas non plus vraiment de bus d'adressage direct pour la ROM avec des instructions dédiées. Pour acceder a une donnée dans la ROM faut dabord placer une valeur dans un registre 16bit qui va servir d'adresse pour ensuite utiliser une autre instruction qui ira chercher la donnée a cette adresse (en plusieurs cycles pour adresser la ROM, au moins 3 vu que sur les shema de cablage je vois seulement 5 lignes d'adressage pour la ROM) donc ca complique aussi un peu la tache par contre a priori y a moyen d'acceder a bien plus de ROM que sur la 2600 qui sans bank switching est limité a 4Ko. la je dirais que ca doit etre dans les 32Ko (mais bon au final les jeux Channel F sont tous sur des ROMs de 2Ko, + etait trop couteux)

la tres grosse difference avec la 2600 (c'est le bute de ma demarche, identifier les differences) c'est la gestion de la video.
Dans la Channel F y a de la VRAM contrairement a la 2600 qui n'en a pas du tout ce qui fait sa particularité. Et elle en a quand meme 2Ko ce qui est enorme pour l'epoque, c'est autant que la VRAM de la NES (c'est 16x plus que la Main RAM de la 2600) et non seulement elle a de la VRAM mais celle ci est utilisé tel qu'on l'utilise aujourd'hui c'est a dire pour contenir le framebuffer (donc pour stocker un par un le code couleur de chaque pixel a afficher) alors que meme les consoles 2D suivante qu'on connait comme la NES et les autres utiliseront plutot la VRAM de facon indirect pour construire une image en assemblant des tiles (des bloc de 8x8 pixels) pas vraiment sous la forme d'un framebuffer.

Donc effectivement ca tranche fortement avec la 2600 mais la partie video de la Channel F s'arrete la. c'est a dire qu'en realité y a pas de fonction graphique, tu remplis cette memoire avec le CPU selon ce que tu veux afficher et puis c'est tout (dailleurs pour acceder a cette VRAM faut passer par des ports qui sont ceux utilisés aussi par les manettes, tu utilises ces ports en ecriture pour ecrire dans la VRAM que tu ne peux pas relire car la lecture sert pour lire les inputs des manettes)
Alors que sur la 2600 y a quand meme le chip TIA (ou "stella") qui malgres son coté minimaliste propose de vrais fonctions graphiques (et audio) avec un semblant de gestion de sprite ou de collision deja plus dans l'esprit console de jeu (mais en meme temps ils avaient pas le choix en l'absence de VRAM), la channel F penche plus du coté micro-informatique ou le CPU est vraiment l'element central (meme si sur 2600 il le devient aussi de part l'absence de VRAM)

Donc vraiment une aproche tres differente qui devrait permettre des choses differentes (mais difficile a jauger sans essayer vraiment).
Niveau resolution c'est plutot du 96x58 donc evidement plus faible que sur la 2600 mais on fait ce qu'on veut de chaque pixel vu qu'il y a un vrai framebuffer (pas de limite tel que le "playfield" sur 2600 bridé a 40 pixels horisontal et avec une symetrie), y a pas besoin d'user de multiple trick.
Niveau couleur la aussi ont est loin de la 2600 sauf si on prend en compte la version francaise "SECAM" c'est du meme ordre, 8 couleurs.

Pour la partie audio la aussi on est tres loin de la 2600, juste un seul speaker dans la console (le son passe pas par la TV dans le premier model) avec seulement 3 tons et pas de gestion de volume alors que sur la 2600 on a une sorte de petite bibliotheque de son dont on peut ajuster la frequence (ce qui nous donne environ 300 sons differents) ainsi que le volume et sur 2 voix simultanées, c'est du caviar a coté de la channel F.
Au niveau audio et video la 2600 a vraiment le droit a des fonctions custom tel qu'on l'attend d'une console de jeu, pourtant j'avais pas trop cette vision la de la 2600 avant de m'y interressé de plus pret.

Reste un point fort de la Channel F, en plus de cette VRAM enorme elle a aussi un bios de 1Ko (y a rien dans la 2600). il a ete decompilé, on voit dedans juste quelques lignes de code pour initialiser la machine comme mettre a zero les registres/scratchpad, le genre de truc qu'il faut faire soit meme sur 2600 (effacer la RAM, initialiser la pile, mais bon c'est un detail) puis ensuite ca test si y a une cartouche valide et si c'est pas le cas ca lance un jeu interne (un pong avec 2 mode de jeu, tennis et hockey) donc ca c'est la classe!
Y a aussi 2 ou 3 subroutines dans ce jeu integré auxquelles on doit pouvoir acceder a partir d'autre jeu, ca peut permettre d'economiser de la ROM sur la cartouche.

En resumé la Channel F est mal pourvu en features audio et video par contre elle integre cette enorme quantité de VRAM et meme de la ROM mais un CPU qui aujourd'hui passe pour tres exotique alors que le 6502 de la 2600 est aujourd'hui celebre (2600, C64, AppleII, NES, SNES, PC-engine...) et documenté donc tres accessible (et un peu l'ancetre des CPU RISC comme les ARM)

Y a eu seulement une vingtaine/trentaine de jeu sur Channel F, elle a ete comercialisé seulement au US a 250 000 exemplaires

upsilandre

#51
Je viens de voir qu'il y a quand meme pas mal de jeux VCS officiels d'Atari qui utilisent des cartouches boostées pour faire du bank switching et proposer des jeux de 8Ko (y en a beaucoup) voir 16Ko.
Un jeu celebre comme Defender (Resogun) utilise une cartouche de 16Ko (soit 4x plus que ce que la console suporte nativement) et integre 128 octets de RAM suplementaire pour doubler la RAM (faut dire aussi que c'est probablement le premier jeu console a scroling et avec une map et un radar)
Par contre dans pitfall pas de triche, c'est du simple 4ko de base et sans boost RAM, ca le rend d'autant plus impressionnant avec son aventure de 256 ecrans (auto-généré)

Le Bank switching faudra de toute facon que j'y passe au moins une fois pour connaitre, c'est pas un truc evident a maitriser donc ca merite de s'y pencher (c'est un coup de main a prendre je pense et meme sur NES faudra sans doute y passer j'imagine, a vu de nez je dirais qu'on doit etre limité nativement a 32Ko sur NES je pense).

upsilandre

#52
Le Kernel
Ce qu'on appelle le Kernel dans le contexte de la 2600 c'est ce petit bout de code CPU de quelques dizaines d'instructions au mieux qui va gerer l'affichage en alimentant le TIA pendant le balayage de l'ecran.

Si on devait resumer la programmation sur 2600 c'est sans hésité cela qui caracterise le mieux la 2600. La programmation du Kernel c'est une demarche intellectuel vraiment a part, y a le Kernel et le reste du code.
C'est meme quelque chose qu'apriori on ne retrouve sur aucune autre machine, ni la Channel F ni la NES ou autres donc si on veut s'interresser a la programmation Atari 2600 c'est la dessus qu'il faut se pencher, c'est la qu'est le fun.
Dailleurs quand on a une idée de jeu 2600 la premiere chose a faire c'est le Kernel. C'est lui qui va definir ton jeu de par les fortes contraintes d'affichages qui sont omnipresentes. Pas la peine de partir sur une idée de jeu si tu n'as pas dabord verifier que tu auras un Kernel qui poura afficher les elements dont tu as besoin.
Le Kernel est vraiment comme un puzzle, chaque instructions doit resulter d'une longue reflexion et toutes les notions de timing doivent etre parfaitement maitrisées.


----------------------------------------------------------------------------


Sur Combat le Kernel est simple dans le sens ou il utilise pas vraiment de trick si ce n'est que (surtout dans ma version boosté) il a fallu quand meme que je combine tous les elements graphiques (les elements playfield PF0,PF1 et PF2 + les sprite P0 et P1 + les missiles P0 et P1 + la balle + la possibilité de switcher le playfield avec le meme Kernel) ce qui au final a demander des efforts pour tout faire entrer, en général t'evite de tout utiliser en meme temps.


Sur Space Invaders c'est un Kernel plus complexe car faut passer par des tricks, la 2600 etant faite pour afficher seulement 2 sprites (8x1) c'est pour ca que je m'y interresse.
Space invaders necessite l'affichage de beaucoup de sprites a l'ecran et notement de 6 sprites sur la meme scanline (+ au moins un missile).
Faut se poser la question du niveau d'independance de ces sprites qui heureusement ne le sont pas enormement. Ils ne sont pas visuellement independant (ils ont la meme aparence sur toutes la lignes) et ne sont pas independant non plus dans leur mouvement (ils se deplacent a l'unisson) mais sont independants en ce qui concerne leur vie et leur mort, faut pouvoir gerer individuellement leur affichage (c'est la que se trouve la difficulté).


Moi ce qui m'interresserait c'est pas de faire une copie conforme bien sure sinon l'excercice est moins motivant.
j'ai 2 idées pour Space invaders, soit tenter de faire une version qui se raproche + de la version arcade (qui a des lignes de 11 aliens au lieu de 6 dans la version 2600) soit une autre idée que je devoilerais pas puisque l'interet est dans la surprise (je pense qu'il y a un truc a faire en reprenant des vieux jeux comme ca srtictement a l'identique mais en changeant un truc pour prendre le joueur a contre-pied)
Je vais de toute facon commencer dabord par la premiere idée.


------------------------------------------------------------------


Pour augmenter le nombre de sprite sur une meme ligne (tout en pouvant gerer individuellement leur affichage) j'ai 3 idées de kernel toutes radicalements differentes et avec des inconvenients differents, difficile de se décider.

- Ma premiere technique serait de reprendre la methode de l'original et simplement de répartir le kernel sur 2 frames et donc afficher 2x6=12 sprites mais en flickering (6 sur une frames, 6 sur une autres), ca au moins c'est quasi sur que ca marchera (meme si ca sera pas facile quand meme) et le resultat sera correct modulo le flickering

- la seconde idée que j'ai eu et que j'aime beaucoup utilise des trick de timing et de reset des sprites compliqué a expliqué et surtout de combiner ca a l'idée de placer le Kernel en RAM au lieu qu'il soit en ROM
Sur atari 2600 on met pas de code en RAM, le code est en ROM et la RAM sert juste pour les variables mais un kernel d'une seul scanline ca peut tenir en RAM. Ca me prendra alors une bonne moitié de la RAM et donc ca me laissera l'autre moitié pour le jeu, ca peut le faire (sur tank2600 j'ai utilisé seulement la moitié de la RAM)
Et surtout avoir le Kernel en RAM combiné a la programmation en assembleur ca permet un truc enorme qui est de produire du code qui va pas juste produire et modifier des datas mais produire et modifier de l'op-code et donc modifier du code avec du code!
Quelle interet de modifier son propre code avec du code? normalement quand on veut un code dynamique on se contente d'y mettre des branchements conditionnels (si "ceci" alors executer tel code sinon executer tel autre code) sauf que ces branchement conditionnels ca prend du temps d'execution qu'on a pas ici.
Avec un Kernel en RAM je peux remplacer ces branchements conditionnels (qui ici servirait a decider si tel ou tel sprite de la ligne est vivant ou mort et donc si on doit l'afficher) par des modifications direct du code du Kernel pendant l'execution du jeu et donc me passer de ces branchement qui de toute facon ne pourait jamais entrer dans le Kernel donc ca ouvre de nouvelle possibilité.
Reste qu'il faut quand meme trouver le moyen d'afficher tous ces sprites et pour l'instant la solution que j'ai n'est pas completement satisfaisante, je peux afficher les 11 sprites de la version arcade (et cette fois sur la meme frame, sans flickering) et controler individuellement l'affichage de chaque sprite (si j'arrive a mettre mon kernel en RAM) mais ca me cause des problemes d'alignements. les sprites ne sont pas parfaitement espacés, un coup y en a un 2 pixels trop a gauche, l'autre 2 pixels trop a droite... et de plus ca pose aussi des problemes pour afficher l'explosion de l'ennemie quand on le touche.
Ca peut sans doute marcher comme cela mais ca sera pas propre (probablement moins finalement que la methode avec flickering) et pour des raisons complexes de timing ce n'est apriori pas soluble mais juste parce que j'adore cette idée de Kernel en RAM ca me donne quand meme envie d'essayer meme si ca me parait beaucoup de boulot pour pas grand chose si le resultat est trop crade.

- la 3eme technique que je peux pas expliquer non plus en 2 lignes me permetrait d'afficher 8 sprites sur la meme frame (sans flickering mais 8 c'est pas comme l'arcade quand meme) et sans probleme pour gerer l'explosion des ennemies mais des espaces trop grand entre les sprites.
Au final pas interressant a utiliser ici mais quand meme interressant par le faite que c'est encore une autre methode completement differente et ingenieuse qui merite d'exister.




Pour l'instant je sais pas trop par quoi commencer pour ce space invaders mais en tout cas je suis pret a y aller.
J'ai pris le temps de creuser certain element notement le fonctionnement interne du systeme de positionnement horisontal des elements graphiques. J'ai tout bien compris, les systemes des compteurs internes, de syncronisation, pourquoi y a pas de foutu registre de position horisontal, comment fonctionne en interne le HMOVE et pourquoi il crée une ligne noire de 8 pixels en debut de scanline ect... j'ai tout capté. Pour l'instant j'ai plus vraiment de point d'interrogation sur le hardware Atari 2600 (meme le bank switching que j'ai pas encoré exploré j'ai quand meme une idée asser precise de comment ca marche).
J'ai aussi revu ma facon d'organiser le code que ce soit visuellement ou structurellement pour partir sur une meilleur base, me manque plus que l'experience que rien ne peut remplacer...

upsilandre

#53
Sur Atari 2600 y a eu un accessoire tiers interressant qui s'appelait le Supercharger




On enfilait ca dans le port cartouche puis on branchait la prise jack sur n'importe quelle lecteur de cassette audio et on pouvait alors charger des jeux a partir de cassette audio (comme sur les micro-ordinateur) dans une RAM de 6Ko
Ca boostait pas mal les possibilités des quelques jeux qui utilisaient cette accessoire (j'ai lu un peu les details techniques, apres calcule je dirais que ca donne un debit aproximatif de 0.4Ko/s + des phases de préparation avant et apres)
C'est un peu le 64DD ou le disk system de l'Atari2600 (enfin pas vraiment puisque c'etait pas un accessoire Atari, juste un editeur tiers)

Frogger version classic




Frogger version Superchager




Le truc sympa c'est qu'en suite ca a servie en quelque sorte de devkit pour le homebrew, ca permetait de programmer ses jeux sur PC et ensuite de les convertir en fichier audio .WAV et de les envoyer dans le supercharger pour y jouer.
Y a eu aussi des compiles de jeux sur CD audio



des manettes wirless






Un des derniers jeux d'Atari que j'ai decouvert et que je trouve tres impressionnant autant pour la physique de la balle que pour la definition de l'affichage.
La 2600 est vraiment pas faite pour afficher des graphismes aussi fin (seul les sprites ont cette precision donc le flipper est a priori un assemblage de sprite 8x1 monochrome tres ingenieux, il a fallut organiser chaque ligne du flipper pour que l'agencement des pixels soit compatible avec une combinaison de sprite et de couleur)





Sinon j'aimerais bien aussi avoir le temps d'essayer de faire une demo 3D, juste faire tourner un cube en flat 2 couleurs en 3D avec le joystick. Je me dis que c'est peut etre possible, dans une fenetre de 48x48pixels en flickering pour avoir les 2 couleurs reste toujours le probleme de l'absence de VRAM
Pour faire de la 3D faut pouvoir rasteriser les polygones dans un buffer, je pourais me faire un semblant de framebuffer 48x48 en RAM mais il me faudrait au moins 350 octets de RAM en tout (300 pour le framebuffer et une cinquantaine pour le reste) mais y en a que 128 dans la 2600

Mais dans la liste des nombreuses cartouches customs qui ont ete commercialisées (avec different mode de bankswitching pour étendre les capacités) y avait notement les FA de CBS (les noms des types de cartouche sont souvent liés a leur systeme de bankswitching et notement au hotspot, ces adresses particulieres qu'on utilise pour faire switcher les banks, FA est une adresse en hexadecimal, y avait aussi les cartouches F4, F6, F8...) qui ont servies pour quelques jeux edités par CBS.
J'en ai trouvé seulement 3 dont un dans une sorte de raycasting facon wolfenstein + une 4eme resté a l'etat de prototype d'une sorte de simulateur de vole.

L'interet de ces cartouches FA de CBS c'est qu'au dela du tripple bank switching (donc 12Ko) elles ajoutaient 256 octets de RAM (les cartouches "superchip" d'Atari ajoutait seulement 128 octets de RAM), du coup 128 + 256 = 384 octets de RAM, ca pourait coller pour faire une petite demo 3D
Reste a voir si y a suffisement de temps CPU (toujours dans le blanking vertical), va falloir faire des multiplications 16bit avec un CPU qui ne fait que des additions 8bit mais bon y a seulement 8 vertices dans un cube, meme si je suis obligé de rafraichir a 60fps ca parait pas insurmontable comme charge, la rasterisation reste probablement la charge la plus lourde.

Le probleme c'est aussi les couleurs, me faudrait 3 couleurs (+ background) pour faire un cube 3D correct (ou simuler le lighting des 3 faces visible) or pour en avoir 2 je vois deja pas comment faire sans bidouiller avec le flickering (2 frames monochrome) et a 2 couleurs ca va pas rendre terrible
Sinon le faire en wireframe.
enfin tout ca c'est si j'avais le temps...

upsilandre

#54
Le truc a savoir avec ces cartouches qui integre de la RAM c'est que le port cartouche n'est pas cablé en signal W/R (write/read) contrairement a la RAM interne a la console par exemple et ce signal W/R envoyé par le CPU (selon le type d'instructions executés) est important pour que la RAM sache si c'est une phase d'ecriture ou de lecture du coup la RAM de ces cartouches ,qui est handicapé sur ce point, utilise une ruse.
Chaque octet de cette RAM est accessible par 2 adresses differentes, une adresse qui sert a lire et une qui sert a ecrire (au lieu d'avoir simplement une seul adresse couplé a un signal W/R). En faite ca revient a utiliser l'une des 13 lignes d'adressage comme un signal W/R mais en utilisant cette ligne d'adressage ont divise alors par 2 la gamme d'adressage avec donc cette effet mirroir ou chaque cellule RAM se retrouve avec 2 adresses.

Reste un inconvénient sans solution c'est que certaines instructions CPU combinent a la fois lecture et ecriture a une seul et meme adresse, par exemple l'instruction d'incrementation d'une valeur en memoire (INC $XX) qui consiste dabord a lire la valeur a l'adresse $XX puis incrémenter puis ecrire la nouvelle valeur a l'adresse $XX tout ca en une seul instruction CPU. Ce genre d'instructions ne peut pas fonctionner avec les upgrades de RAM dans les cartouches.

Faut aussi prendre en consideration que la RAM interne a la console de 128 octets a cette particularité d'etre dans la toute premiere page d'adressage c'est a dire dans les 256 premiers octets des 8Ko adressable par le CPU (c'est le cas aussi des registres du TIA, le chip video/audio) et y a des instructions CPU qui sont specifique a l'adressage de cette page 0 qui a l'avantage de pouvoir donc etre adressé avec une simple adresse 8bit au lieu d'une adresse 16bit et du coup ce sont des instructions qui en general s'execute en 3 cycles au lieu de 4 donc plus rapidement qu'on pourait le faire avec la RAM des cartouches dont la zone d'adressage se trouve dans la seconde moitié des 8ko (plutot page 16 et 17)

Tout ca implique aussi une emprunte sur la ROM car cette RAM integré aux cartouches vient prendre des pages d'adresse a la ROM qui donc perd certaine pages qui deviennent inacessibles et cela pour chaque bank car dans ces cartouches en général la RAM est accessible quelle que soit le bank sur lequel tu as switchés
Ca veut dire par exemple que sur la cartouche FA de CBS qui est composé de 3 banks de 4Ko, les 256 octets de RAM occupent en faite 512 octets (pour la lecture et l'ecriture) mais cela dans chacune des banks soit en tout 1.5Ko!
Donc au final les 256 octets de RAM font perdre 1.5Ko de ROM (donc en tout on a pas 12Ko de ROM mais 10.5Ko + ce que coute le bankswitching qui necessite de dupliquer plus ou moins de code dans chaque bank)


C'est aussi ce que j'aime dans cette demarche c'est d'aller jusqu'a apprehender le cablage electronique pour mieux comprendre, pas forcement une nécéssité mais ca aide, pareille pour le chip video, vaut mieux comprendre certain cablage et fonctionnement interne pour mieux anticiper les comportements.

Jb

Grand malade :laporte:
Mega intéressant en tout cas, merci pour tes feedbacks super précis !

pippoletsu

Clairement, en plus c'est qq chose que j'ai tjs voulu faire, je saurais comment commencer.

upsilandre

#57
C'est vrai que c'est un peu arride comme sujet, ca peut pas interresser tout le monde evidement mais ca peut se picorer, comprendre un truc par ci par la parfois ca suffit a se faire une image globale plus precise sur ce qu'etait les machines de cette epoque sans avoir besoin de tout comprendre.
Moi c'est vraiment la demarche archeologique qui m'interresse. C'est pas pour repondre a un desir de creation de jeu, pour ca vaut mieux aller sur PC avec des outils modernes qui offrent tellement plus de possibiliter, c'est pour ca que je préfere utiliser le terme hardcore retrogaming que homebrew dans mon cas.

J'ai cherché un peu pour voir si y avait une communauté francophone mais difficile a trouver, elle existe surement mais elle est diffuse et tout se passe uniquement sur les forums anglophones (AtariAge pour la 2600), c'est mon seul regret car l'anglais (et le francais) et moi ca fait 2, j'aurais bien aimé trouver un endroit francophone avec quelques personnes dans le delire.
Au moins je deblaye, je peux deja repondre a pas mal de question sur la 2600 et en francais  :cool: (ou presque)



upsilandre

#58
Citation de: pippoletsu le Décembre 29, 2013, 01:21:32 AM
Clairement, en plus c'est qq chose que j'ai tjs voulu faire, je saurais comment commencer.

On pourait se demander si c'est le bon moment mais je pense que y a pas de bon ou de mauvais moment.
Le sentiment est double, d'un coté tu te dis que t'arrive 35ans en retard et que tout a deja ete fait et c'est vrai en quelque sorte, y a meme des gars qui font du homebrew 2600 depuis 20 ans, tu peux pas lutter donc y a quand meme quelque chose de frustrant car du point de vue de la creation pure y a peu d'opportunité (meme si on peut toujours trouver une idée qui nous touche personnellement) mais d'un autre coté tu profites de tout ce qui a ete fait jusqu'alors. Les documents, les emulateurs/debugeurs, les bricolages. Du coup t'as cette chance de pouvoir avancer plus vite et avec moins de frustration purement technique (la vrai frustration c'est le temps, programmer ca prend enormement de temps et on l'a pas, faudrait etre libre a plein temps et pas avoir de boulot).
Disont que plus le temps passe plus la demarche creative se tranforme en demarche archeologique/historique ou le plaisir est dans la comprehension de ces vieilles machines tellements differentes des notres (et de plus en plus), de ces vieux jeux et des petites histoires qui vont avec et sur ce point on est mieux lotie aujourd'hui qu'il y a 20ans (Reste qu'il faut quand meme aimer la technologie dans cette demarche).


Le jour ou je passerais a la NES ca te parlera sans doute encore plus, tu poura pas resister  :vice:
La NES c'est deja une infinité de possibilité (c'est pas vraiment le cas de la 2600) mais faire un jeu NES c'est aussi deja tres lourd en investissement, vaut mieux pas etre seul. Si un jour j'experimente la NES et soyont fou je decide de faire un jeu original meme modeste alors me faudrait au moins quelqu'un pour la musique et quelqu'un pour le pixel-art.
Comme ce qui m'interresse c'est surtout de comprendre la machine le plus probable c'est que je me dirige sur des materiaux deja existant, par exemple faire un portage d'un jeu master system sur NES ca serait un bon excercice et t'as deja du materiau, tu pars pas de zero. J'ai surtout joué a la master systeme que j'ai eu en 1987 donc moi ca me branche, convertir Alex kidd ou The Ninja sur NES  :o  tout du moins trouver un truc qui n'a pas deja ete fais tant qu'a faire.
Si quelqu'un connait deja une communauté homebrew NES francophone qu'il le dise


upsilandre

N'ayant pas trouvé de solution pour afficher un cube en 3 couleurs j'ai préféré laisser tomber cette idée et partir sur Space Invaders comme prevu

Je suis donc partie sur la methode qui utiliserait du flikering pour afficher 12 aliens par ligne (6 sur les frames paires et 6 sur les frames impaires).
J'ai bien reussi a les afficher mais pour les deplacements ca va etre plus chiant que ce que j'imaginais et surtout je me suis rendu compte que pour les tires (alien ou du joueur) je pourais pas utiliser les elements graphiques "missiles" car ils sont intimement liés aux sprites Player0 et Player1 que j'utilise pour afficher les aliens et dans un mode particulier qui empeche de pouvoir afficher en meme temps un missile convenablement.
Ainsi je suis obligé d'afficher tous les projectiles avec l'element graphique "ball" et donc pour pouvoir afficher en meme temps sur la meme ligne un tire ennemie qui tombe et un tire du joueur qui monte va falloir encore utiliser du flickering (afficher le tire des aliens sur les frame paires et le tire du joueur sur les frames impaires).

Du coup je comprend pourquoi dans la version original y a du flickering sur les tires (ca scintille) et ca m'a donné envie de tester le mode 2 joueurs car je me suis demandé comment ils geraient la situation ou les 2 joueurs tire en meme temps (ce qui peut vouloir dire au moins 3 tires sur la meme ligne) et bien ils l'ont géré tout simplement en t'empechant de tirer en meme temps que l'autre joueur   :vice: 

Comme pour dans "combat", c'est ca qui est marrant quand t'essais de refaire ces vieux jeu tu comprend bien mieux certain choix inevitable pour cause de limitation hardware, c'est la que c'est interressant.

Au final cette histoire de devoir passer par la  "ball" ca me complique les choses car j'ai deja les aliens qui sont affichés en flickering, si jamais le tire du joueur est aussi en flickering ca veut dire que le tire du joueur ne sera jamais affiché en meme temps que l'autre moitié des aliens qui sont affichés sur les frames paires. Du coup ca m'empeche d'utiliser les features de collision cablé dans la TIA (en gros il te previent quand il trace sur le meme pixel differents elements graphiques ce qui peut servir de test de collision "free") et m'obligera a coder en plus le systeme de collision


------------------------------------------------------------------


Du coup ces complications m'ont données envie de laisser ca de coté quelques temps et d'aller faire un tour du coté de la seconde methode que j'avais en tete, celle du code Kernel qui s'autogénère en RAM et qui me permet alors d'afficher 11 aliens comme en arcade et cette fois sans flickering.
Meme si je sais que le resultat ne sera pas bon car les deplacements seront un peu chaotique (je peux pas gérer la positions des sprites au pixel pret avec cette methode) cette idée de coder un Kernel qui s'autogénère en RAM est tellement exotique que ca donne envie de le faire juste pour le fun (et parce que ca donne toute sa legitimité au faite de coder en assembleur qui permet ce genre de fantaisie) car a ma connaissance jamais on fait ca en programmation.

J'ai effectivement reussi a placer mon Kernel special en RAM et a l'executer ainsi. Pour l'instant il s'autogénère pas mais au moins ca fonctionne et en plus ca ne m'a prit que 44 octets de RAM, si on ajoute les 4 que je réserve a la pile ca me laisse 80 octets de RAM pour le jeu, plus que j'esperais (je visais plutot les 50 octets) donc au moins sur ce point c'est parfaitement viable, un Kernel en RAM c'est possible sans bouffer toute ta RAM.

Mon bute ne va pas etre de faire le jeu complet avec cette methode, je voudrais juste faire vite fait un proto fonctionnel qui montre une ligne de 11 aliens qui se deplace de droite a gauche et vice et versa et que lorsqu'on appuit sur le bouton cela fasse disparaitre un alien au hasard puis 2, puis 3... juste pour démontrer que ca fonctionne (et voir a quelle point les deplacements sont chaotique selon les aliens qui disparaissent)


J'ai aussi eu l'occasion sur ces tests de faire mon premier Kernel "auto-synchrone".
Normalement le Kernel doit etre synchronisé avec le balayage horisontal de l'ecran et pour cela y a une fonction du chip graphique qu'on nomme "WSYNC".
Quand ont active ce registre du TIA alors le CPU se met en standby jusqu'a ce que la ligne en cours ait finit de s'afficher et que le TIA envoie alors le signal de synchro horisontal, a ce moment le CPU reprend son boulot et donc de facon synchrone avec l'affichage.
Mais la solution ultime c'est de coder un Kernel dont le temps d'execution soit exactement celui du balayage d'une ligne horisontal c'est a dire 76 instructions CPU. Ainsi tu n'as pas besoin d'utiliser la fonction WSYNC et donc tu economises 3 cycles CPU ce qui te permet de placer une instruction de plus dans ton Kernel, c'est la classe.

J'avais pas encore tenté de faire un Kernel auto-synchrone alors j'ai essayé.
Suffit donc de compter le temps d'execution de chaque instruction jusqu'a arriver a tomber sur le bon chiffre de 76 (quite a rajouter un cycle en utilisant par exemple un adressage 16bit sur une instruction qui pourait se contenter d'un adressage 8bit pour faire perdre un cycle)
On a beau savoir qu'en theorie ca doit fonctionner le faite de voir fonctionner du premier coup son premier Kernel auto-synchro c'est emouvant   :cry2: 

puis ensuite je l'ai viré car j'avais pas besoin d'un Kernel aussi long qui au contraire d'en mon cas etait penalisant vu qu'il occupe de la place en RAM mais au moins j'ai vu que ca marchait vraiment (sur Tank2600 ca m'aurait servie de gagner 3 cycles CPU sur mon Kernel)