Logicielsmoto.com

Nous sommes le 28 Mar 2024, 19:07

Heures au format UTC + 1 heure




Poster un nouveau sujet Répondre au sujet  [ 598 messages ]  Aller à la page Précédente  1 ... 26, 27, 28, 29, 30, 31, 32 ... 40  Suivante
Auteur Message
MessagePosté: 11 Juil 2022, 16:11 
Hors ligne

Inscription: 21 Avr 2019, 21:48
Messages: 433
Localisation: Var
Hier j'ai pris un peu de temps pour implémenter une version backward de l'algo de décompression zx0 pour 6809.
J'ai juste eu besoin de faire quelques ajustements par rapport au code (version mega) : https://github.com/dougmasten/zx0-6x09
Ma version est compatible zx0 v2 (dernière version) : https://github.com/wide-dot/thomson-to8-game-engine/blob/main/Engine/Compression/zx0/zx0_6809_mega_back.asm

On peut maintenant choisir entre exomizer ou zx0 pour les projets.
Rappel : toutes les données chargées en RAM sont issues de données compressées sur la disquette ou T.2.

Comparatif sous dcmoto avec la démo Sonic 2
---------------------------------------------------------

Option de simulation de temps de lecture disquette désactivé
Chargement de la page RAM 1 et 4 à 27 incluse
zx0 : 17 472 969 cycles de 4000 à 6100 soit 17,4 secondes (reste 9931 octets inutilisés)
exo : 72 018 196 cycles de 4000 à 6100 soit 72 secondes (reste 9775 octets inutilisés)

Le temps global de chargement est donc divisé par 4,12 dans ce cas de test !
On se paye même le luxe de gagner quelques octets ...

Option de simulation de temps de lecture disquette activé
zx0 : 45 226 029 cycles (soit 27 753 060 cycles supplémentaires pour la lecture disquette)
exo : 100 331 116 cycles (soit 28 312 920 cycles supplémentaires pour la lecture disquette)

Soit un temps de chargement 2,2x plus rapide au final (depuis la disquette) !
Sur la T.2 on devrait donc avoir une decompression 4x plus rapide (test à venir).

Remarque :
On conserve bien sûr la possibilité d'utiliser Exomizer par respect pour le travail effectué par les membres du forum.


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 11 Juil 2022, 16:59 
Hors ligne

Inscription: 21 Aoû 2006, 09:06
Messages: 1802
Localisation: Brest
Test super intéressant qui semble indiquer que zx0 est probablement le top du domaine en ce moment.

Question : le commentaire https://github.com/wide-dot/thomson-to8 ... ck.asm#L53 parle du format v1, mais ici tu as parlé de v2. Normal ou pas?

_________________
Good morning, that's a nice Tnetennba


Dernière édition par Samuel Devulder le 11 Juil 2022, 17:18, édité 2 fois.

Haut
 Profil  
Répondre en citant le message  
MessagePosté: 11 Juil 2022, 17:13 
Hors ligne
M. DCMOTO

Inscription: 06 Juin 2004, 08:23
Messages: 681
Localisation: Provence (France)
L'option de dcmoto pour simuler la vitesse réelle de la disquette est une simple temporisation pour éviter que les données se chargent trop vite (typiquement pour avoir le temps de lire un écran avant qu'il soit effacé par le programme suivant). Il n'a rien de réaliste et ne peut pas remplacer un test avec la vraie machine. Il ne changera pas la conclusion sur la rapidité de zx0, mais le rapport de 2,2 n'a aucune précision ni justification scientifique.


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 11 Juil 2022, 17:23 
Hors ligne

Inscription: 21 Aoû 2006, 09:06
Messages: 1802
Localisation: Brest
Teo est en principe plus précis sur les temps de chargement dans la mesure où il implémente la machine à état du controller de diskette je crois.

_________________
Good morning, that's a nice Tnetennba


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 11 Juil 2022, 17:50 
Hors ligne

Inscription: 21 Avr 2019, 21:48
Messages: 433
Localisation: Var
Tout à fait d'accord Daniel, tu as raison de préciser le fonctionnement de cette option.

Ces chiffres reflètent une utilisation sous dcmoto avec différentes options.
Les mesures sur machine réelle seront effectuées dans les jours qui viennent.

Par contre je sais déjà que la lecture disquette (sur machine) n'est pas optimisée car je n'ai appliqué aucun entrelacement aux données ;-)
C'est sur la (longue très longue) todo list ;-)

Une autre mesure, ici on ne compte que le temps de la routine de décompression, mais sur un échantillon de données plus restreint (15 640 octets) :
465 680 cycles (zx0) gain : 3,4x
1 578 517 cycles (exo)

Evidement le temps de décompression dépend du type de données, donc c'est purement indicatif.
Par curiosité je regarderai le temps de décompression sur une page de données contenant des sprites compilés (code assez répétitif) pour voir l'impact.

Merci Sam pour l'info, il y a effectivement un fichier thmfc1.c dans teo avec 1600 lignes de code ...


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 17 Juil 2022, 15:00 
Hors ligne

Inscription: 21 Avr 2019, 21:48
Messages: 433
Localisation: Var
C'est le moment de publier une nouvelle vidéo :

- Gestion des anneaux
- HUD time, rings

phpBB [video]

https://youtu.be/-uSthQrtx4o

Je n'ai pas avancé sur mes bugs de collision par contre ;-(

Si vous voulez jouer, c'est encore périeux ... mais possible :
Fichier(s) joint(s):
sonic-2_fd.zip [163.56 Kio]
Téléchargé 102 fois

Fichier(s) joint(s):
sonic-2_sd.zip [175.92 Kio]
Téléchargé 83 fois


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 17 Juil 2022, 19:36 
Hors ligne

Inscription: 21 Aoû 2006, 09:06
Messages: 1802
Localisation: Brest
Ça a l’air bien vu de loin. Quel est le problème des collisions?

Les anneaux ne font pas de ding ding par contre, mais ça vient pas des collisions je suppose :W

_________________
Good morning, that's a nice Tnetennba


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 18 Juil 2022, 07:10 
Hors ligne

Inscription: 21 Avr 2019, 21:48
Messages: 433
Localisation: Var
L'effet sonore pour les anneaux sera dans la prochaine version.

En ce qui concerne les collisions, il y a des problèmes lorsque :
- Sonic est en mode marche/course mais détaché du sol (in air) avec une vitesse élevée, à ce moment là il passe au travers du sol. (a basse vitesse, il s'enfonce dans le sol et remonte)
- Dans une pente avec une faible vitesse du personnage, il se produit un détachement du sol (normal), mais le personnage ne redescend pas la pente, il reste bloqué

Le passage des loops est lié à des objets non implémentés donc ce n'est pas un bug pour le moment ;-).


Dernière édition par Bentoc le 18 Juil 2022, 07:38, édité 1 fois.

Haut
 Profil  
Répondre en citant le message  
MessagePosté: 18 Juil 2022, 07:34 
Hors ligne

Inscription: 21 Avr 2019, 21:48
Messages: 433
Localisation: Var
En ce qui concerne les anneaux, le principe est simple :

Un tableau contient toutes les positions des anneaux, triées par coordonnées x.
Chaque entrée du tableau vaut :
- position x (2 octets)
- position y (2 octets)

A l'init :
- A partir de la position de camera on fait le parcours du tableau depuis le début pour trouver la position de début et de fin des anneaux visibles à l'écran. Ces deux positions sont sauvegardées.

A chaque boucle principale :
- On met à jour les deux positions (début et fin) en recherchant en avant et ou en arrière, par rapport à la nouvelle position de camera
- On affiche les anneaux entre ces deux positions.

Pour la "consommation" des anneaux, un tableau dédié stocke l'information du statut.
Un tableau autre stocke les informations d'animation pour afficher les "étoiles" des anneaux en cours de consommation.


Code:
; ---------------------------------------------------------------------------
; Load_Rings
;
; This is the Ring manager for Sonic 3, with some changes to fit sonic 2
;
; ---------------------------------------------------------------------------

        INCLUDE "./Engine/Macros.asm"   

; All sprites coordinates are image centered
Rings_width             equ 8
Rings_height            equ 16
Rings_view_width        equ 136
Rings_view_height       equ 160

nb_rings                equ dp_engine

Load_Rings                                            *Load_Rings:
                                                      *                moveq   #0,d0
        ; a is set by caller                          *                move.b  (Rings_manager_routine).w,d0
        ldx   #Rings_Routines                         *                move.w  off_E8B8(pc,d0.w),d0
        jmp   [b,x]                                   *                jmp     off_E8B8(pc,d0.w)
                                                      *; End of function Load_Rings
                                                      *
Rings_Routines                                        *; ---------------------------------------------------------------------------
        fdb   Rings_Init                              *off_E8B8:       dc.w loc_E8BE-off_E8B8
        fdb   Rings_Main                              *                dc.w loc_E942-off_E8B8
        fdb   Render_Rings ; used for external call
        fdb   Touch_Rings  ; used for external call
                                                      *                dc.w loc_E9CA-off_E8B8
                                                      *; ---------------------------------------------------------------------------
                                                      *
Rings_Init                                            *loc_E8BE:

        ; this routine init start and end pointers
        ; to rings position and consumption arrays
        ; based on camera x position

        ; a is set by caller                          *                addq.b  #2,(Rings_manager_routine).w
        jsr   Rings_Setup                             *                bsr.w   sub_EB1A
                                                      *                cmpi.b  #$14,(Current_zone).w
                                                      *                beq.s   loc_E904
        ldx   Ring_start_addr_layout                  *                movea.l (Ring_start_addr_ROM).w,a1
        ldu   #Ring_status_table                      *                lea     (Ring_status_table).w,a2
        ldd   glb_camera_x_pos                        *                move.w  (Camera_X_pos).w,d4
        subd  #Rings_width/2                          *                subq.w  #8,d4
        bhi   >                                       *                bhi.s   loc_E8E6
        ldd   #1 ; no negative values allowed         *                moveq   #1,d4
        bra   >                                       *                bra.s   loc_E8E6
                                                      *; ---------------------------------------------------------------------------
                                                      *
@a                                                    *loc_E8E2:
        leax  4,x ; load next ring                    *                addq.w  #4,a1
        leau  2,u                                     *                addq.w  #2,a2
                                                      *
!                                                     *loc_E8E6:
        cmpd  ,x ; ring X pos < camera X pos?         *                cmp.w   (a1),d4
        bhi   @a ; if yes move to next ring           *                bhi.s   loc_E8E2

        ; start position found, store index
        stx   Ring_start_addr_layout                  *                move.l  a1,(Ring_start_addr_ROM).w
        stu   Ring_start_addr_status                  *                move.w  a2,(Ring_start_addr_RAM).w
        ; advance by a screen
        addd  #(Rings_width/2)+Rings_view_width       *                addi.w  #$150,d4
        bra   >                                       *                bra.s   loc_E8FA
                                                      *; ---------------------------------------------------------------------------
                                                      *
@b                                                      *loc_E8F8:
        leax  4,x ; load next ring                    *                addq.w  #4,a1
                                                      *
!                                                     *loc_E8FA:
        cmpd  ,x ; ring X pos < camera X + screen?    *                cmp.w   (a1),d4
        bhi   @b                                      *                bhi.s   loc_E8F8
        ; end position found, store index
        stx   Ring_end_addr_layout                    *                move.l  a1,(Ring_end_addr_ROM).w
        rts                                           *                rts
                                                      *; ---------------------------------------------------------------------------
                                                      *
        ; special stage unimplemented                 *loc_E904:
                                                      *                addq.b  #2,(Rings_manager_routine).w
                                                      *                movea.l (Ring_start_addr_ROM).w,a1
                                                      *                lea     (Ring_status_table_2).w,a2
                                                      *                move.w  (Camera_Y_pos).w,d4
                                                      *                subq.w  #8,d4
                                                      *                bhi.s   loc_E920
                                                      *                moveq   #1,d4
                                                      *                bra.s   loc_E920
                                                      *; ---------------------------------------------------------------------------
                                                      *
                                                      *loc_E91C:
                                                      *                addq.w  #4,a1
                                                      *                addq.w  #2,a2
                                                      *
                                                      *loc_E920:
                                                      *                cmp.w   2(a1),d4
                                                      *                bhi.s   loc_E91C
                                                      *                move.l  a1,(Ring_start_addr_ROM).w
                                                      *                move.w  a2,(Ring_start_addr_RAM).w
                                                      *                addi.w  #$F0,d4
                                                      *                bra.s   loc_E936
                                                      *; ---------------------------------------------------------------------------
                                                      *
                                                      *loc_E934:
                                                      *                addq.w  #4,a1
                                                      *
                                                      *loc_E936:
                                                      *                cmp.w   2(a1),d4
                                                      *                bhi.s   loc_E934
                                                      *                move.l  a1,(Ring_end_addr_ROM).w
        ; end of special stage specific               *                rts
                                                      *; ---------------------------------------------------------------------------
                                                      *

Rings_Main                                            *loc_E942:
        jsr   Rings_Consume                           *                bsr.s   sub_E994
        ldy   Ring_start_addr_layout                  *                movea.l (Ring_start_addr_ROM).w,a1
        ldu   Ring_start_addr_status                  *                movea.w (Ring_start_addr_RAM).w,a2
        ldx   glb_camera_x_pos                        *                move.w  (Camera_X_pos).w,d4
        leax  -(Rings_width/2),x                      *                subq.w  #8,d4
        cmpx  #1
        bge   >                                       *                bhi.s   loc_E95C
        ldx   #1 ; camera x pos capped to 1           *                moveq   #1,d4
        bra   >                                       *                bra.s   loc_E95C
                                                      *; ---------------------------------------------------------------------------
                                                      *
@a                                                    *loc_E958:
        leay  4,y                                     *                addq.w  #4,a1
        leau  2,u                                     *                addq.w  #2,a2
                                                      *
!                                                     *loc_E95C:
        cmpx  ,y                                      *                cmp.w   (a1),d4
        bhi   @a ; search first ring for this         *                bhi.s   loc_E958
        bra   >  ; camera x position moving forward   *                bra.s   loc_E966
                                                      *; ---------------------------------------------------------------------------
                                                      *
@b                                                    *loc_E962:
        leay  -4,y                                    *                subq.w  #4,a1
        leau  -2,u                                    *                subq.w  #2,a2
                                                      *
!                                                     *loc_E966:
        cmpx  -4,y ; search moving rearward           *                cmp.w   -4(a1),d4
        bls   @b                                      *                bls.s   loc_E962
        sty   Ring_start_addr_layout                  *                move.l  a1,(Ring_start_addr_ROM).w
        stu   Ring_start_addr_status                  *                move.w  a2,(Ring_start_addr_RAM).w
        ldu   Ring_end_addr_layout                    *                movea.l (Ring_end_addr_ROM).w,a2
        leax  (Rings_width/2)+Rings_view_width,x      *                addi.w  #$150,d4
        bra   >                                       *                bra.s   loc_E980
                                                      *; ---------------------------------------------------------------------------
                                                      *
@c                                                    *loc_E97E:
        leau  4,u                                     *                addq.w  #4,a2
                                                      *
!                                                     *loc_E980:
        cmpx  ,u ; search last ring for this          *                cmp.w   (a2),d4
        bhi   @c ; camera x position moving forward   *                bhi.s   loc_E97E
        bra   >                                       *                bra.s   loc_E988
                                                      *; ---------------------------------------------------------------------------
                                                      *
@d                                                    *loc_E986:
        leau  -4,u                                    *                subq.w  #4,a2
                                                      *
!                                                     *loc_E988:
        cmpx  -4,u ; search moving rearward           *                cmp.w   -4(a2),d4
        bls   @d                                      *                bls.s   loc_E986
        stu   Ring_end_addr_layout                    *                move.l  a2,(Ring_end_addr_ROM).w
        rts                                           *                rts
                                                      *

                                                      *; =============== S U B R O U T I N E =======================================
                                                      *
                                                      *

Rings_Consume                                         *sub_E994:
        ldx   #Ring_consumption_table                 *                lea     (Ring_consumption_table).w,a2
        ldy   ,x++ ; rings currently being consumed?  *                move.w  (a2)+,d1
        ;                                             *                subq.w  #1,d1
        beq   @end ; exit if no ring                  *                bcs.s   locret_E9C8
                                                      *
@loop                                                 *loc_E99E:
        ldu   ,x++  ; is there a ring in this slot?   *                move.w  (a2)+,d0
        beq   @loop ; branch if not                   *                beq.s   loc_E99E
        ;                                             *                movea.w d0,a1
        lda   ,u
        suba  Vint_Main_runcount
        sta   ,u    ; decrement timer                 *                subq.b  #1,(a1)
        bpl   @next ; branch if not ready             *                bne.s   loc_E9C4
        adda  #6                                      *                move.b  #6,(a1)
        sta   ,u    ; reset timer
        lda   1,u                                     *                addq.b  #1,1(a1)
        inca        ; increment frame (stars)
        sta   1,u
        cmpa  #8    ; is it destruction time yet ?    *                cmpi.b  #8,1(a1)
        bne   @next                                   *                bne.s   loc_E9C4
        ldd   #-1
        std   ,u    ; destroy ring                    *                move.w  #-1,(a1)
        ldd   #0
        std   -2,x  ; clear ring entry                *                clr.w   -2(a2)
        ldd   Ring_consumption_table                  *                subq.w  #1,(Ring_consumption_table).w
        subd  #1
        std   Ring_consumption_table ; subtract count
                                                      *
@next                                                 *loc_E9C4:
        leay  -1,y
        bne   @loop ; next ring, else exit            *                dbf     d1,loc_E99E
                                                      *
@end                                                  *locret_E9C8:
        rts                                           *                rts
                                                      *; End of function sub_E994
                                                      *
                                                      *; ---------------------------------------------------------------------------
                                                      *
        ; unused (special stage)                      *loc_E9CA:
                                                      *                bsr.s   sub_E994
                                                      *                movea.l (Ring_start_addr_ROM).w,a1
                                                      *                movea.w (Ring_start_addr_RAM).w,a2
                                                      *                move.w  (Camera_Y_pos).w,d4
                                                      *                subq.w  #8,d4
                                                      *                bhi.s   loc_E9E4
                                                      *                moveq   #1,d4
                                                      *                bra.s   loc_E9E4
                                                      *; ---------------------------------------------------------------------------
                                                      *
                                                      *loc_E9E0:
                                                      *                addq.w  #4,a1
                                                      *                addq.w  #2,a2
                                                      *
                                                      *loc_E9E4:
                                                      *                cmp.w   2(a1),d4
                                                      *                bhi.s   loc_E9E0
                                                      *                bra.s   loc_E9F0
                                                      *; ---------------------------------------------------------------------------
                                                      *
                                                      *loc_E9EC:
                                                      *                subq.w  #4,a1
                                                      *                subq.w  #2,a2
                                                      *
                                                      *loc_E9F0:
                                                      *                cmp.w   -2(a1),d4
                                                      *                bls.s   loc_E9EC
                                                      *                move.l  a1,(Ring_start_addr_ROM).w
                                                      *                move.w  a2,(Ring_start_addr_RAM).w
                                                      *                movea.l (Ring_end_addr_ROM).w,a2
                                                      *                addi.w  #$F0,d4
                                                      *                bra.s   loc_EA0A
                                                      *; ---------------------------------------------------------------------------
                                                      *
                                                      *loc_EA08:
                                                      *                addq.w  #4,a2
                                                      *
                                                      *loc_EA0A:
                                                      *                cmp.w   2(a2),d4
                                                      *                bhi.s   loc_EA08
                                                      *                bra.s   loc_EA14
                                                      *; ---------------------------------------------------------------------------
                                                      *
                                                      *loc_EA12:
                                                      *                subq.w  #4,a2
                                                      *
                                                      *loc_EA14:
                                                      *                cmp.w   -2(a2),d4
                                                      *                bls.s   loc_EA12
                                                      *                move.l  a2,(Ring_end_addr_ROM).w
 ; end of unsused code                                *                rts
                                                      *
                                                      *; =============== S U B R O U T I N E =======================================
                                                      *
                                                      *
Touch_Rings                                           *Test_Ring_Collisions:
        lda   invulnerable_time,u                     *                cmpi.b  #$5A,$34(a0)
        cmpa  #$5A
        bhs   @rts                                    *                bhs.w   locret_EAE4
        ;                                             *                movea.l (Ring_start_addr_ROM).w,a1
        ldx   Ring_start_addr_layout                  *                movea.l (Ring_end_addr_ROM).w,a2
        cmpx  Ring_end_addr_layout                    *                cmpa.l  a1,a2
        bne   >                                       *                beq.w   locret_EAE4 ; branch if no rings in this area
@rts    rts
!       ldy   Ring_start_addr_status                  *                movea.w (Ring_start_addr_RAM).w,a4
        ;                                             *                btst    #Status_LtngShield,status_secondary(a0) ; does Sonic have a Lightning Shield?
        ;                                             *                beq.s   Test_Ring_Collisions_NoAttraction
        ;ldd   x_pos,u                                *                move.w  $10(a0),d2
        ;subd  #$40
        ;std   glb_d2
        ;ldd   y_pos,u                                *                move.w  $14(a0),d3
        ;subd  #$40
        ;std   glb_d3
        ;                                             *                subi.w  #$40,d2
        ;                                             *                subi.w  #$40,d3
        ;                                             *                move.w  #6,d1
        ;                                             *                move.w  #$C,d6
        ;ldd   #$80
        ;std   glb_d4                                 *                move.w  #$80,d4
        ;std   glb_d5                                 *                move.w  #$80,d5
        ;bra   Test_Ring_Collisions_NextRing          *                bra.s   Test_Ring_Collisions_NextRing
                                                     *; ---------------------------------------------------------------------------
                                                      *
        ;                                             *Test_Ring_Collisions_NoAttraction:
        ldd   x_pos,u                                 *                move.w  $10(a0),d2
        ;                                             *                move.w  $14(a0),d3
        subd  #8                                                                         ; assume X radius to be 8
        std   glb_d2                                  *                subi.w  #8,d2
        anda  #0                                      *                moveq   #0,d5
        ldb   y_radius,u                              *                move.b  $1E(a0),d5
        subb  #3                                      *                subq.b  #3,d5
        std   glb_d5
        ldd   y_pos,u
        subd  glb_d5
        std   glb_d3                                  *                sub.w   d5,d3     ; subtract (Y radius - 3) from Y pos
        ;                                             *                move.w  #6,d1     ; set ring radius
        ;                                             *                move.w  #$C,d6    ; set ring diameter
        ldd   #$10
        std   glb_d4                                  *                move.w  #$10,d4   ; set Sonic's X diameter
        ldd   glb_d5       
        addd  glb_d5
        std   glb_d5                                  *                add.w   d5,d5     ; set Y diameter
                                                      *
Test_Ring_Collisions_NextRing                         *Test_Ring_Collisions_NextRing:
        ldd   ,y                                      *                tst.w   (a4)      ; has this ring already been collided with?
        bne   Touch_NextRing                          *                bne.w   loc_EADA  ; if it has, branch
        ldd   ,x                                      *                move.w  (a1),d0   ; get ring X pos
        subd  #3                                      *                sub.w   d1,d0     ; get ring left edge X pos
        subd  glb_d2                                  *                sub.w   d2,d0     ; subtract Sonic's left edge X pos
        bcc   >                                       *                bcc.s   loc_EAA0  ; if Sonic's to the left of the ring, branch
        addd  #6                                      *                add.w   d6,d0     ; add ring diameter
        bcs   @a                                      *                bcs.s   loc_EAA6  ; if Sonic's colliding, branch
        bra   Touch_NextRing                          *                bra.w   loc_EADA  ; otherwise, test next ring
                                                      *; ---------------------------------------------------------------------------
                                                      *
!                                                     *loc_EAA0:
        cmpd  glb_d4                                  *                cmp.w   d4,d0     ; has Sonic crossed the ring?
        bhi   Touch_NextRing                          *                bhi.w   loc_EADA  ; if he has, branch
                                                      *
@a                                                    *loc_EAA6:
        ldd   2,x                                     *                move.w  2(a1),d0  ; get ring Y pos
        subd  #6                                      *                sub.w   d1,d0     ; get ring top edge pos
        subd  glb_d3                                  *                sub.w   d3,d0     ; subtract Sonic's top edge pos
        bcc   >                                       *                bcc.s   loc_EAB8  ; if Sonic's above the ring, branch
        addd  #12                                     *                add.w   d6,d0     ; add ring diameter
        bcs   @b                                      *                bcs.s   loc_EABE  ; if Sonic's colliding, branch
        bra   Touch_NextRing                          *                bra.w   loc_EADA  ; otherwise, test next ring
                                                      *; ---------------------------------------------------------------------------
                                                      *
!                                                     *loc_EAB8:
        cmpd  glb_d5                                  *                cmp.w   d5,d0     ; has Sonic crossed the ring?
        bhi   Touch_NextRing                          *                bhi.w   loc_EADA  ; if he has, branch
                                                      *
@b                                                    *loc_EABE:
        ;                                             *                btst    #Status_LtngShield,status_secondary(a0) ; does Sonic have a Lightning Shield?
        ;                                             *                bne.s   Test_Ring_Collisions_AttractRing
                                                      *
                                                      *loc_EAC6:
        ldd   #$604
        std   ,y                                      *                move.w  #$604,(a4) ; set frame and destruction timer
        jsr   Touch_ConsumeRing                      *                bsr.s   sub_EAE6
        stx   @x
        ldx   #Ring_consumption_list                  *                lea     (Ring_consumption_list).w,a3
                                                      *
!                                                     *loc_EAD0:
        ldd   ,x++                                    *                tst.w   (a3)+      ; is this slot free?
        bne   <                                       *                bne.s   loc_EAD0   ; if not, repeat until you find one
        sty   ,--x                                    *                move.w  a4,-(a3)   ; set ring address
        ldd   Ring_consumption_table
        addd  #1
        std   Ring_consumption_table                  *                addq.w  #1,(Ring_consumption_table).w ; increase count
        ldx   #0
@x      equ   *-2
                                                      *
Touch_NextRing                                        *loc_EADA:
        leax  4,x                                     *                addq.w  #4,a1
        leay  2,y                                     *                addq.w  #2,a4
        cmpx  Ring_end_addr_layout                    *                cmpa.l  a1,a2
        bne   Test_Ring_Collisions_NextRing           *                bne.w   Test_Ring_Collisions_NextRing
                                                      *
                                                      *locret_EAE4:
        rts                                           *                rts
                                                      *; End of function Test_Ring_Collisions

                                                      *
                                                      *
                                                      *; =============== S U B R O U T I N E =======================================
                                                      *
                                                      *
Touch_ConsumeRing                                     *sub_EAE6:
        ;                                             *                subq.w  #1,(Perfect_rings_left).w
        jmp   CollectRing_Sonic                       *                jmp     (GiveRing).l
                                                      *; End of function sub_EAE6
                                                      *
                                                      *; ---------------------------------------------------------------------------
                                                      *
                                                      *Test_Ring_Collisions_AttractRing:
                                                      *                movea.l a1,a3
                                                      *                jsr     (Create_New_Sprite).l
                                                      *                bne.w   loc_EB16
                                                      *                move.l  #Obj_Attracted_Ring,(a1)
                                                      *                move.w  (a3),x_pos(a1)
                                                      *                move.w  2(a3),y_pos(a1)
                                                      *                move.w  a4,$30(a1)
                                                      *                move.w  #-1,(a4)
                                                      *                rts
                                                      *; ---------------------------------------------------------------------------
                                                      *
                                                      *loc_EB16:
                                                      *                movea.l a3,a1
                                                      *                bra.s   loc_EAC6
                                                      *
                                                      *; =============== S U B R O U T I N E =======================================
                                                      *
                                                      *
Rings_Setup                                           *sub_EB1A:
        ldx   #0                                      *                moveq   #0,d0
        tst   Respawn_table_keep                      *                tst.b   (Respawn_table_keep).w
        bne   @keep                                   *                bne.s   loc_EB30
        ldy   #Ring_status_table                      *                lea     (Ring_status_table).w,a1
        lda   #$FF                                    *                move.w  #$FF,d1
                                                      *
                                                      *loc_EB2A:
!       stx   ,y++                                    *                move.l  d0,(a1)+
        stx   ,y++                                    *                dbf     d1,loc_EB2A
        deca                                          *
        bne   <
@keep                                                 *loc_EB30:
        ldy   #Ring_consumption_table                 *                lea     (Ring_consumption_table).w,a1
        lda   #$1F                                    *                moveq   #$1F,d1
                                                      *
                                                      *loc_EB36:
!       stx   ,y++                                    *                move.l  d0,(a1)+
        deca                                          *                dbf     d1,loc_EB36
        bne   <
        ; special stage specific                      *                cmpi.b  #$14,(Current_zone).w
        ; unimplemented                               *                bne.s   loc_EB52
        ;                                             *                lea     (Ring_status_table_2).w,a1
        ;                                             *                move.w  #$FF,d1
                                                      *
        ;                                             *loc_EB4C:
        ;                                             *                move.l  d0,(a1)+
        ;                                             *                dbf     d1,loc_EB4C
                                                      *
        ;                                             *loc_EB52:
        ldd   Current_zone_and_act                    *                move.w  (Current_zone_and_act).w,d0
        ;                                             *                ror.b   #1,d0
        ;                                             *                lsr.w   #5,d0
        ldx   #RingLocPtrs                            *                lea     (RingLocPtrs).l,a1
        ldd   d,x                                     *                movea.l (a1,d0.w),a1
        std   Ring_start_addr_layout                  *                move.l  a1,(Ring_start_addr_ROM).w
        ; perfect ring count                          *                addq.w  #4,a1
        ; unimplemeted                                *                moveq   #0,d5
        ;                                             *                move.w  #$1FE,d0
        ;                                             *
        ;                                             *loc_EB70:
        ;                                             *                tst.l   (a1)+
        ;                                             *                bmi.s   loc_EB7A
        ;                                             *                addq.w  #1,d5
        ;                                             *                dbf     d0,loc_EB70
        ;                                             *
        ;                                             *loc_EB7A:
        ;                                             *                move.w  d5,(Perfect_rings_left).w
        ;                                             *                move.w  #0,(_unkFF06).w
        rts                                           *                rts
                                                      *; End of function sub_EB1A
                                                      *
                                                      *
                                                      *; =============== S U B R O U T I N E =======================================
                                                      *
                                                      *

Render_Rings                                          *Render_Rings:
                                                      *                movea.l (Ring_start_addr_ROM).w,a0
        ldd   Ring_end_addr_layout                    *                move.l  (Ring_end_addr_ROM).w,d2
        subd  Ring_start_addr_layout                  *                sub.l   a0,d2
        beq   @rts ; branch if no rings to display    *                beq.s   locret_EBEC
        _asrd
        _asrd
        stb   nb_rings
        ldx   Ring_start_addr_layout
        ldu   Ring_start_addr_status                  *                movea.w (Ring_start_addr_RAM).w,a4
                                                      *                lea     CMap_Ring(pc),a1
                                                      *                move.w  4(a3),d4
                                                      *                move.w  #$F0,d5
                                                      *                move.w  (Screen_Y_wrap_value).w,d3
                                                      *
@loop                                                 *loc_EBA6:
        tst   ,u++                                    *                tst.w   (a4)+
        bmi   @next ; branch if ring is consumed      *                bmi.s   loc_EBE6
        ldd   2,x   ; get ring Y pos                  *                move.w  2(a0),d1
        subd  glb_camera_y_pos                        *                sub.w   d4,d1
        addd  #Rings_height/2                         *                addq.w  #8,d1
        anda  #$07
        andb  #$FF  ; level Y loop                    *                and.w   d3,d1
        cmpd  #Rings_view_height+Rings_height         *                cmp.w   d5,d1
        bhs   @next ; ring is out of y screen range   *                bhs.s   loc_EBE6
        addb  #20-(Rings_height/2) ; on screen pos    *                addi.w  #$78,d1
        lda   1,x   ; get ring X pos                  *                move.w  (a0),d0
        anda  #%11111110 ; scroll step is 2px
        inca             ; fix ring position
        suba  glb_camera_x_pos+1                      *                sub.w   (a3),d0
        adda  #12   ; on screen position of camera    *                addi.w  #$80,d0
        lsra                                ; x=x/2, sprites moves by 2 pixels on x axis
        lsra                                ; x=x/2, RAMA RAMB interlace 
        bcs   @RAM2First                    ; Branch if write must begin in RAM2 first
@RAM1First
        sta   @dyn1
        lda   #40                           ; 40 bytes per line in RAMA or RAMB
        mul
        addd  #$C000                        ; (dynamic)
@dyn1   equ   *-1       
        std   <glb_screen_location_2
        suba  #$20
        std   <glb_screen_location_1     
        bra   @end
@RAM2First
        sta   @dyn2
        lda   #40                           ; 40 bytes per line in RAMA or RAMB
        mul
        addd  #$A000                        ; (dynamic)
@dyn2   equ   *-1       
        std   <glb_screen_location_2
        addd  #$2001
        std   <glb_screen_location_1
@end
        lda   -1,u  ; get ring frame                  *                move.b  -1(a4),d6
        bne   >     ; use specific frame (stars)      *                bne.s   loc_EBCE
        lda   Rings_anim_frame ; use global frame     *                move.b  (Rings_frame).w,d6
                                                      *
!                                                     *loc_EBCE:
        pshs  x,u
        ldu   glb_screen_location_2
        ldx   #Ring_Images
        asla
        jsr   [a,x]
        puls  x,u
                                                      *                lsl.w   #3,d6
                                                      *                lea     (a1,d6.w),a2
                                                      *                add.w   (a2)+,d1
                                                      *                move.w  d1,(a6)+
                                                      *                move.w  (a2)+,d6
                                                      *                move.b  d6,(a6)
                                                      *                addq.w  #2,a6
                                                      *                move.w  (a2)+,(a6)+
                                                      *                add.w   (a2)+,d0
                                                      *                move.w  d0,(a6)+
                                                      *                subq.w  #1,d7
                                                      *
@next                                                 *loc_EBE6:
        leax  4,x                                     *                addq.w  #4,a0
        dec   nb_rings                                *                subq.w  #4,d2
        bne   @loop                                   *                bne.s   loc_EBA6
                                                      *
@rts                                                  *locret_EBEC:
        rts                                           *                rts
                                                      *; End of function Render_Rings

                                                      *
                                                      *; ---------------------------------------------------------------------------
                                                      *; Custom mappings format. Compare to Map_Ring.
                                                      *
                                                      *; Differences include...
                                                      *;  No offset table (each sprite assumed to be 8 bytes)
                                                      *;  No 'sprite pieces per frame' value (hardcoded to 1)
                                                      *;  Sign-extended Y-pos value
                                                      *;  Sign-extended sprite size value
                                                      *
                                                      *CMap_Ring:
                                                      *;frame1:
                                                      *                dc.w $FFF8
                                                      *                dc.w $0005
                                                      *                dc.w $0000+make_art_tile(ArtTile_Ring,1,0)
                                                      *                dc.w $FFF8
                                                      *
                                                      *;frame2:
                                                      *                dc.w $FFF8
                                                      *                dc.w $0005
                                                      *                dc.w $0004+make_art_tile(ArtTile_Ring,1,0)
                                                      *                dc.w $FFF8
                                                      *
                                                      *;frame3:
                                                      *                dc.w $FFF8
                                                      *                dc.w $0001
                                                      *                dc.w $0008+make_art_tile(ArtTile_Ring,1,0)
                                                      *                dc.w $FFFC
                                                      *
                                                      *;frame4:
                                                      *                dc.w $FFF8
                                                      *                dc.w $0005
                                                      *                dc.w $0804+make_art_tile(ArtTile_Ring,1,0)
                                                      *                dc.w $FFF8
                                                      *
                                                      *;frame5:
                                                      *                dc.w $FFF8
                                                      *                dc.w $0005
                                                      *                dc.w $000A+make_art_tile(ArtTile_Ring,1,0)
                                                      *                dc.w $FFF8
                                                      *
                                                      *;frame6:
                                                      *                dc.w $FFF8
                                                      *                dc.w $0005
                                                      *                dc.w $180A+make_art_tile(ArtTile_Ring,1,0)
                                                      *                dc.w $FFF8
                                                      *
                                                      *;frame7:
                                                      *                dc.w $FFF8
                                                      *                dc.w $0005
                                                      *                dc.w $080A+make_art_tile(ArtTile_Ring,1,0)
                                                      *                dc.w $FFF8
                                                      *
                                                      *;frame8:
                                                      *                dc.w $FFF8
                                                      *                dc.w $0005
                                                      *                dc.w $100A+make_art_tile(ArtTile_Ring,1,0)
                                                      *                dc.w $FFF8

                                                      ; Sonic 2 code here ...
CollectRing_Sonic                                     *CollectRing_Sonic:
        ldd   Ring_count
        cmpd  #999                                    *        cmpi.w  #999,(Rings_Collected).w ; did Sonic collect 999 or more rings?
        bhs   >                                       *        bhs.s   CollectRing_1P          ; if yes, branch
        addd  #1                                      *        addq.w  #1,(Rings_Collected).w  ; add 1 to the number of collected rings
        std   Ring_count                              *
!                                                     *CollectRing_1P:
                                                      *
                                                      *    if gameRevision=0
                                                      *        cmpi.w  #999,(Ring_count).w     ; does the player 1 have 999 or more rings?
                                                      *        bhs.s   +                       ; if yes, skip the increment
                                                      *        addq.w  #1,(Ring_count).w       ; add 1 to the ring count
                                                      *+
                                                      *        ori.b   #1,(Update_HUD_rings).w ; set flag to update the ring counter in the HUD
        lda   #SndID_Ring                             *        move.w  #SndID_Ring,d0          ; prepare to play the ring sound
                                                      *    else
                                                      *        move.w  #SndID_Ring,d0          ; prepare to play the ring sound
                                                      *        cmpi.w  #999,(Ring_count).w     ; does the player 1 have 999 or more rings?
                                                      *        bhs.s   JmpTo_PlaySoundStereo   ; if yes, play the ring sound
                                                      *        addq.w  #1,(Ring_count).w       ; add 1 to the ring count
                                                      *        ori.b   #1,(Update_HUD_rings).w ; set flag to update the ring counter in the HUD
                                                      *    endif
                                                      *
                                                      *        cmpi.w  #100,(Ring_count).w     ; does the player 1 have less than 100 rings?
                                                      *        blo.s   JmpTo_PlaySoundStereo   ; if yes, play the ring sound
                                                      *        bset    #1,(Extra_life_flags).w ; test and set the flag for the first extra life
                                                      *        beq.s   +                       ; if it was clear before, branch
                                                      *        cmpi.w  #200,(Ring_count).w     ; does the player 1 have less than 200 rings?
                                                      *        blo.s   JmpTo_PlaySoundStereo   ; if yes, play the ring sound
                                                      *        bset    #2,(Extra_life_flags).w ; test and set the flag for the second extra life
                                                      *        bne.s   JmpTo_PlaySoundStereo   ; if it was set before, play the ring sound
                                                      *+
                                                      *        addq.b  #1,(Life_count).w       ; add 1 to the life count
                                                      *        addq.b  #1,(Update_HUD_lives).w ; add 1 to the displayed life count
                                                      *        move.w  #MusID_ExtraLife,d0     ; prepare to play the extra life jingle
                                                      *
                                                      *JmpTo_PlaySoundStereo ; JmpTo
        sta   Smps.SFXToPlay                          *        jmp     (PlaySoundStereo).l
                                                      *; ===========================================================================
        rts                                           *        rts
                                                      *; ===========================================================================

;--------------------------------------------------------------------------------------------------
Ring_start_addr_layout  fdb 0 ; address in the ring layout of the first ring whose X position is >= camera X position - 8
Ring_end_addr_layout    fdb 0 ; address in the ring layout of the first ring whose X position is >= camera X position + 328
Ring_start_addr_status  fdb 0 ; address in the ring status table of the first ring whose X position is >= camera X position - 8

Ring_status_table       fill 0,$400 ; 1 word per ring (512 rings max)
Ring_consumption_table             ; $80 bytes ; stores the addresses of all rings currently being consumed
Ring_consumption_count  fdb 0       ; the number of rings being consumed currently
Ring_consumption_list   fill 0,$7E  ; the remaining part of the ring consumption table

RingLocPtrs
        fdb   EHZ1_Rings
        fdb   EHZ2_Rings

EHZ1_Rings INCLUDEBIN ".\objects\managers\rings\EHZ_1_INDIVIDUAL.bin"
EHZ2_Rings INCLUDEBIN ".\objects\managers\rings\EHZ_2_INDIVIDUAL.bin"

Ring_Images
        fdb   draw_img_ring_1
        fdb   draw_img_ring_2
        fdb   draw_img_ring_3
        fdb   draw_img_ring_4
        fdb   draw_img_ring_sparkle_1
        fdb   draw_img_ring_sparkle_2
        fdb   draw_img_ring_sparkle_3
        fdb   draw_img_ring_sparkle_4

draw_img_ring_1

   leau  199,u

   lda   #$33
   sta   121,u
   lda   #$3f
   sta   -80,u
   sta   -120,u
   lda   #$54
   sta   81,u
   ldd   40,u
   anda  #$f0
   ora   #$03
   ldb   #$f5
   std   40,u
   ldd   ,u
   anda  #$f0
   andb  #$f0
   addd  #$0403
   std   ,u
   lda   -40,u
   anda  #$f0
   ora   #$05
   sta   -40,u
   leau  -280,u

   lda   #$3f
   sta   120,u
   sta   80,u
   lda   #$35
   sta   40,u
   sta   ,u
   ldd   -80,u
   anda  #$f0
   andb  #$f0
   addd  #$0503
   std   -80,u
   lda   -40,u
   anda  #$f0
   ora   #$05
   sta   -40,u
   ldd   -120,u
   anda  #$f0
   ora   #$04
   ldb   #$34
   std   -120,u
   leau  -179,u

   lda   #$55
   sta   20,u
   lda   #$ff
   sta   -20,u

   ldu    <glb_screen_location_1
   leau  199,u

   lda   120,u
   anda  #$f0
   ora   #$03
   sta   120,u
   lda   -119,u
   anda  #$f0
   ora   #$05
   sta   -119,u
   ldd   80,u
   lda   #$35
   andb  #$0f
   orb   #$30
   std   80,u
   ldd   40,u
   lda   #$5f
   andb  #$0f
   orb   #$40
   std   40,u
   ldd   ,u
   anda  #$0f
   ora   #$f0
   ldb   #$54
   std   ,u
   lda   #$35
   sta   -79,u
   lda   #$45
   sta   -39,u
   leau  -279,u

   lda   120,u
   anda  #$f0
   ora   #$05
   sta   120,u
   lda   80,u
   anda  #$f0
   ora   #$05
   sta   80,u
   lda   40,u
   anda  #$f0
   ora   #$05
   sta   40,u
   ldd   -81,u
   anda  #$0f
   ora   #$40
   ldb   #$4f
   std   -81,u
   lda   #$35
   sta   ,u
   lda   #$3f
   sta   -40,u
   ldd   -121,u
   lda   #$53
   andb  #$0f
   orb   #$50
   std   -121,u
   leau  -181,u

   ldd   20,u
   lda   #$55
   andb  #$0f
   orb   #$f0
   std   20,u
   lda   -20,u
   anda  #$f0
   ora   #$05
   sta   -20,u
        rts


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 18 Juil 2022, 15:06 
Hors ligne

Inscription: 21 Avr 2019, 21:48
Messages: 433
Localisation: Var
Bon j'ai fini par trouver le bug de collision ... et c'était tout simple.

Le code d'origine fait appel à une fonction atan2 (CalcAngle) pour calculer l'angle de déplacement à partir de la vélocité x et y du personnage.
En fonction de l'angle obtenu, une des 4 routines de collision est appelée (test plafond, sol, gauche et droite)
Cette fonction ne renvoyait pas la bonne valeur dans certains cas et donc on branchait sur le contrôle du plafond au lieu du sol ...

J'aurai mieux faire de lire le code plutôt que de chercher a porter cette méthode atan2 ... en effet il y a beaucoup plus simple :

Code:
        ldd   x_vel+dp                                *  move.w  x_vel(a0),d1
        ;                                             *  move.w  y_vel(a0),d2
        ; a more simple solution than atan2           *  jsr (CalcAngle).l
        bmi   @x_neg
        ldd   y_vel+dp
        bpl   >
        _negd
!       cmpd  x_vel+dp
        lble  Sonic_HitRightWall
        bra   @up_or_down
@x_neg
        ldd   y_vel+dp
        bpl   >
        _negd
!       cmpd  x_vel+dp
        lble  Sonic_HitLeftWall
@up_or_down
        lda   y_vel+dp
        lbmi  Sonic_HitCeilingAndWalls
        ;                                             *  subi.b  #$20,d0
        ;                                             *  andi.b  #$C0,d0
        ;                                             *  cmpi.b  #$40,d0
        ;                                             *  beq.w   Sonic_HitLeftWall
        ;                                             *  cmpi.b  #$80,d0
        ;                                             *  beq.w   Sonic_HitCeilingAndWalls
        ;                                             *  cmpi.b  #$C0,d0
        ;                                             *  beq.w   Sonic_HitRightWall
        jsr   CheckLeftWallDist                       *  bsr.w   CheckLeftWallDist


On gagne à la louche 300 cycles x 5 boucles (adaptation du frame rate) par boucle principale ... et on ne traverse plus les murs :sol:

Bon il doit rester d'autres bugs, mais celui là était le plus "visible"


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 18 Juil 2022, 17:42 
Hors ligne

Inscription: 21 Aoû 2006, 09:06
Messages: 1802
Localisation: Brest
Le mur transparent était donc le plus visible?! :voyons:

_________________
Good morning, that's a nice Tnetennba


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 18 Juil 2022, 17:58 
Hors ligne

Inscription: 21 Avr 2019, 21:48
Messages: 433
Localisation: Var
le plus remarquable alors :orni:


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 18 Juil 2022, 18:56 
Hors ligne

Inscription: 21 Aoû 2006, 09:06
Messages: 1802
Localisation: Brest
:lol:

_________________
Good morning, that's a nice Tnetennba


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 19 Juil 2022, 09:50 
Hors ligne

Inscription: 21 Avr 2019, 21:48
Messages: 433
Localisation: Var
Je partage avec vous cette petite astuce ...

ça fait un moment que je suis embêté par la routine qui efface les données d'un objet (une centaine d'octets à effacer).
Pour que ce soit le plus rapide possible, je le réalise en psh sans boucle. Le problème c'est que la taille de l'objet dépend de chaque projet et n'est donc pas fixe au niveau du moteur de jeu.
Par conséquent jusqu'à présent, il fallait dupliquer le code et l'adapter en fonction du besoin.

Voila le nouveau code (LWASM) :

Code:
* ---------------------------------------------------------------------------
* ClearObj
* --------
* Subroutine to clear an object data in OST
*
* input REG : [u] pointer on objet (OST)
* clear REG : none
* ---------------------------------------------------------------------------

ClearObj
        pshs  d,x,y

        leau  object_size,u ; move to end of data object structure
        ldd   #$0000        ; init regs to zero
        ldx   #$0000
        leay  ,x

        fill $36,(object_size/6)*2 ; generate object_size/6 assembly instructions $3636 (pshu  d,x,y)

        IFEQ object_size%6-5
        pshu  a,x,y
        ENDC

        IFEQ object_size%6-4
        pshu  d,x
        ENDC

        IFEQ object_size%6-3
        pshu  a,x
        ENDC

        IFEQ object_size%6-2
        pshu  d
        ENDC

        IFEQ object_size%6-1
        pshu  a
        ENDC

        puls  d,x,y,pc


Dernière édition par Bentoc le 19 Juil 2022, 11:20, édité 1 fois.

Haut
 Profil  
Répondre en citant le message  
MessagePosté: 19 Juil 2022, 10:17 
Hors ligne

Inscription: 21 Avr 2019, 21:48
Messages: 433
Localisation: Var
deleted


Dernière édition par Bentoc le 19 Juil 2022, 11:19, édité 1 fois.

Haut
 Profil  
Répondre en citant le message  
Afficher les messages postés depuis:  Trier par  
Poster un nouveau sujet Répondre au sujet  [ 598 messages ]  Aller à la page Précédente  1 ... 26, 27, 28, 29, 30, 31, 32 ... 40  Suivante

Heures au format UTC + 1 heure


Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 35 invités


Vous ne pouvez pas poster de nouveaux sujets
Vous ne pouvez pas répondre aux sujets
Vous ne pouvez pas éditer vos messages
Vous ne pouvez pas supprimer vos messages
Vous ne pouvez pas joindre des fichiers

Rechercher:
Aller à:  
Développé par phpBB® Forum Software © phpBB Group
Traduction par phpBB-fr.com