What's new
iamretro

Wow! It seems you have yet to create an account with us! Needless to say, you have to register in order to get the full "iamretro" experience! You will then be able to create your own topics, reply to posts and be an active member of the MOST prolific community in Greece (even further than that, but we're being modest for now). So don't delay! REGISTER!

QL Sprites in Basic

lliont

Retro Member
Comrade
Joined
Aug 3, 2017
Messages
115
Όταν ήμουν μικρός είχα το TI-99/4 όπου έμαθα προγραμματισμό σε BASIC, και ο ΤΙ είχε sprites. Μετά πήρα τον Spectrum όπου έπαιζα μόνο παιχνίδια.
Όταν πήρα τον QL ασχολήθηκα με 68000 assembly. Ο QL δεν είχε sprites και έχοντας καλομάθει από τον ΤΙ μου έλειπαν. Ο QL όμως είχε το καλό ότι μπορούσες εύκολα να προσθέσεις εντολές στην basic. Έτσι έφτιαξα τις δικές μου εντολές για στοιχειώδη προσομοίωση sprites στην basic του QL. Τώρα τελευταία που ασχολήθηκα με το qubide και έφτιαξα μια δικιά μου έκδοση του pcb με 768K ram και συνέχιση του expansion port μπόρεσα να μεταφέρω παλιά προγράμματά μου από δισκέτα σε sd και μετά στο pc και θυμήθηκα τα sprites και έτρεξα το μικρό test πρόγραμμα και χάρηκα (ότι θυμάμαι χαίρομαι που λένε).

Οι εντολές που όριζαν, τοποθετούσαν, κινούσαν και σκότωναν το sprite ήταν οι sgc, spr, ssp και skl. Τα sprites ήταν μαλλον μόνο 8x8 και μπορούσες να ορίσεις καμμιά 10αρια, δεν ασχολήθηκα παραπάνω. Επίσης από ότι βλέπω στο Basic πρόγραμμα υπήρχαν και δύο functions spx(n), spy(n) που επέστρεφαν τις συντεταγμένες του sprite.

To τεστ πρόγραμμα σε basic ένα "κανονάκι" που κάνει μια μικρή περιστροφική κίνηση όχι κάτι εντυπωσιακό αλλά δείχνει ότι λειτουργούν.


https://drive.google.com/file/d/1TcXmSVZZi8EMSWPdZxzTMISorRYxtWhY/preview


Ο κώδικας σε 68000 assembly (ίσως όχι ο βέλτιστος γιατί τότε μάθαινα):

Code:
hjob  MACRO
      move.w   d1,0(a5)
      move.b   1(a5),2(a5)
      move.b   #0,1(a5)
      move.b   #0,3(a5)
      move.l   0(a5),d6
      lsr.l    d3,d6
      move.l   d6,0(a5)
      move.b   2(a5),d7
      move.b   1(a5),2(a5)
      move.b   d7,1(a5)
      move.w   0(a5),d6
      move.w   2(a5),d1
      ENDM
      move.w   $110,a0
      lea.l    pdef,a1
      jsr      (a0)
      moveq    #0,d0
      rts
pdef  dc.w     4
      dc.w     start-*
      dc.b     3,'spr'
      dc.w     ssped-*
      dc.b     3,'ssp'
      dc.w     sgrac-*
      dc.b     3,'sgc'
      dc.w     skill-*
      dc.b     3,'skl'
      dc.w     0
      dc.w     2
      dc.w     sxpos-*
      dc.b     3,'sxp'
      dc.w     sypos-*
      dc.b     3,'syp'
      dc.w     0
      dc.w     0
start move.w   $112,a2
      jsr      (a2)
      subi.w   #3,d3
      bne      errb
      moveq    #0,d0
      move.w   0(a6,a1.l),d0
      cmpi.w   #10,d0
      bgt      outr
      mulu     #2,d0
      lea.l    sx,a2
      lea.l    sy,a4
      move.w   2(a6,a1.l),0(a2,d0.w)
      move.w   4(a6,a1.l),0(a4,d0.w)
here  move.w   0(a2,d0.w),d2
      move.w    0(a4,d0.w),d5
      divu     #8,d2
      swap     d2
      move.w   d2,d3
      andi.b   #6,d3
      swap     d2
      mulu     #2,d2
      mulu     #16,d0
      mulu     #128,d5
      add.w    d5,d2
      cmpi.w   #31744,d2
      bgt      outr
      lea.l    grac,a0
      move.l   scram,a4
      lea.l    bbuf,a5
      move.w   0(a0,d0.w),d1
      hjob
      eor.w    d6,0(a4,d2.w)
      eor.w     d1,2(a4,d2.w)
      move.w   2(a0,d0.w),d1
      hjob
      eor.w     d6,2(a4,d2.w)
      eor.w     d1,4(a4,d2.w)
      addi.w   #128,d2
      move.w   4(a0,d0.w),d1
      hjob
      eor.w     d6,0(a4,d2.w)
      eor.w     d1,2(a4,d2.w)
      move.w   6(a0,d0.w),d1
      hjob
      eor.w    d6,2(a4,d2.w)
      eor.w     d1,4(a4,d2.w)
      addi.w   #128,d2
      move.w   8(a0,d0.w),d1
      hjob
      eor.w    d6,0(a4,d2.w)
      eor.w     d1,2(a4,d2.w)
      move.w   10(a0,d0.w),d1
      hjob
      eor.w    d6,2(a4,d2.w)
      eor.w     d1,4(a4,d2.w)
      addi.w   #128,d2
      move.w   12(a0,d0.w),d1
      hjob
      eor.w    d6,0(a4,d2.w)
      eor.w     d1,2(a4,d2.w)
      move.w   14(a0,d0.w),d1
      hjob
      eor.w   d6,2(a4,d2.w)
      eor.w     d1,4(a4,d2.w)
      addi.w   #128,d2
      move.w   16(a0,d0.w),d1
      hjob
      eor.w   d6,0(a4,d2.w)
      eor.w     d1,2(a4,d2.w)
      move.w   18(a0,d0.w),d1
      hjob
      eor.w   d6,2(a4,d2.w)
      eor.w     d1,4(a4,d2.w)
      addi.w   #128,d2
      move.w   20(a0,d0.w),d1
      hjob
      eor.w   d6,0(a4,d2.w)
      eor.w     d1,2(a4,d2.w)
      move.w   22(a0,d0.w),d1
      hjob
      eor.w   d6,2(a4,d2.w)
      eor.w     d1,4(a4,d2.w)
      addi.w   #128,d2
      move.w   24(a0,d0.w),d1
      hjob
      eor.w   d6,0(a4,d2.w)
      eor.w     d1,2(a4,d2.w)
      move.w   26(a0,d0.w),d1
      hjob
      eor.w    d6,2(a4,d2.w)
      eor.w     d1,4(a4,d2.w)
      addi.w   #128,d2
      move.w   28(a0,d0.w),d1
      hjob
      eor.w   d6,0(a4,d2.w)
      eor.w     d1,2(a4,d2.w)
      move.w    30(a0,d0.w),d1
      hjob
      eor.w     d6,2(a4,d2.w)
      eor.w     d1,4(a4,d2.w)
      bra       exit
ssped move.w   $112,a2
      jsr      (a2)
      subi.w   #3,d3
      bne      errb
      moveq    #0,d0
      move.w   0(a6,a1.l),d0
      cmpi.w   #10,d0
      bgt      outr
      mulu     #2,d0
      lea.l    offs,a5
      move.w   d0,0(a5)
      move.w   2(a6,a1.l),d2
      lea.l    sux,a2
      move.w   d2,0(a2,d0.w)
      lea.l    suy,a2
      move.w   4(a6,a1.l),d2
      move.w   d2,0(a2,d0.w)
lo1   lea.l    sx,a2
      lea.l    sy,a4
      jsr      here
      lea.l    sux,a3
      lea.l    offs,a5
      move.w   0(a5),d0
      lea.l    sx,a2
      move.w   0(a2,d0.w),d5
      add.w    0(a3,d0.w),d5
      move.w   d5,0(a2,d0.w)
      lea.l    suy,a3
      lea.l    sy,a4
      move.w   0(a4,d0.w),d5
      add.w    0(a3,d0.w),d5
      move.w   d5,0(a4,d0.w)
      jsr      here
      bra      exit
sgrac move.w   $112,a2
      jsr      (a2)
      subi.w   #17,d3
      bne      errb
      moveq    #0,d0
      move.w   0(a6,a1.l),d0
      cmpi.w   #10,d0
      bgt      outr
      mulu     #32,d0
      moveq    #15,d1
      lea.l    grac,a0
      lea.l    2(a6,a1.l),a2
      lea.l    0(a0,d0.w),a3
loo   move.w   (a2)+,(a3)+
      dbmi     d1,loo
      bra      exit
skill move.w   $112,a2
      jsr      (a2)
      subi.w   #1,d3
      bne      errb
      move.w   0(a6,a1.l),d0
      mulu     #2,d0
      lea.l    sx,a2
      lea.l    sy,a4
      jsr      here
      bra      exit
sxpos move.w   $112,a2
      jsr      (a2)
      subi.w   #1,d3
      bne      errb
      moveq    #0,d1
      move.w   0(a6,a1.l),d1
      mulu     #2,d1
      lea.l    sx,a2
      move.l   $58(a6),a1
      subq     #2,a1
      move.l   a1,$58(a6)
      move.w   0(a2,d1.w),0(a6,a1.l)
      moveq    #3,d4
      bra      exit
sypos move.w   $112,a2
      jsr      (a2)
      subi.w   #1,d3
      bne      errb
      moveq    #0,d1
      move.w   0(a6,a1.l),d1
      mulu     #2,d1
      lea.l    sy,a2
      move.l   $58(a6),a1
      subq     #2,a1
      move.l   a1,$58(a6)
      move.w   0(a2,d1.w),0(a6,a1.l)
      moveq    #3,d4
exit  moveq    #0,d0
      rts
errb  moveq    #-15,d0
      rts
outr  moveq    #-4,d0
      rts
scram dc.l     $20000
bbuf  ds.l     2
grac  ds.w     170
sx    ds.w     11
sy    ds.w     11
sux   ds.w     11
suy   ds.w     11
offs  ds.w     2
      end
 
Last edited:

lliont

Retro Member
Comrade
Joined
Aug 3, 2017
Messages
115
Μάλλον κάπου 86-87 και οι έξτρα εντολές φορτώνονται στον QL με πρόγραμμα, έχει μηχανισμό με system call που περνάς κάποιο structure, έτσι δεν άλλαξα την rom, είναι πολύ συνηθισμένο στον QL. Άσε που δεν είχα τότε eprom programmer που τέτοια πολυτέλεια.
 

lliont

Retro Member
Comrade
Joined
Aug 3, 2017
Messages
115
Στο zip υπάρχουν τα αρχεία.
Οι εντολές προστίθονται στον QL αv έχετε το toolkit II δίνοντας: lrespr my_sprc
αλλιώς: a=respr(2100) : lbytes my_sprc,a : call a
και το πρόγραμμα της basic με lrun my_spdemo

H εντολή sgc ορίζει ένα sprite, παίρνει πρώτη παράμετρο το νούμερο του sprite και μετά άλλα 16 bytes που καθορίζουν το σχήμα του sprite
Όπως βλέπω από τα προπολεμικά σχήματά μου κάθε pixel αποτελίται από 2 bits οπότε κάθε byte είναι 4 pixels, χρώματα φαντάζομαι άσπρο πράσινο κόκκινο μαύρο
Οπότε SGC 1,0,0,2,128,2,128,10,160,42,168,42,168,170,170,170,170 ορίζει το σχήμα από το "κανονάκι"
Η εντολή SPR 1,100,100 εμφανίζει το sprite 1 στη θέση x=100, y=100
Η εντολή SSP 1,dx,dy μετακινεί το sprite 1 κατά dx στον άξονα x και κατά dy στον άξονα y
H εντολή SKL 1 εξαφανίζει το sprite 1
Η x=SPX(1) θα βάλει στην μεταβλητή x την τρέχουσα συντεταγμένη του sprite 1 στον άξονα x, αντίστοιχα η SPY(n).

και ναι είχα έγχρωμο dot matrix τότε SEIKOSHA κάτι

qlspriteg.jpg
 

Attachments

  • qlsprites.zip
    2 KB · Views: 4

lliont

Retro Member
Comrade
Joined
Aug 3, 2017
Messages
115
Δεν το έχω με τα video αλλιώς θα είχα κάνει πολλά κυρίως για τον Lion.
H πλάκα είναι ότι ο QL δεν έχει καν κουμπί για να ανάψει τον βάζεις στην πρίζα και bootαρει οπότε δεν θα έχεις πρόβλημα. :)
Εγώ του έβαλα ένα δικόπτη τότε από πορτατίφ. Το βιντεάκι με το sprite στο πρώτo post το είδες φαντάζομαι.
 
Last edited:

sly*m

Retro Addict
Comrade
Joined
Oct 30, 2018
Messages
636
Διακόπτες για καλώδιο - πορτατίφ κλασικά τότε για ιδιοκατασκευές (φωτορυθμικά κλπ) και υπολογιστές! :emoji_smile:
 

lliont

Retro Member
Comrade
Joined
Aug 3, 2017
Messages
115
Αφού διάβασα λίγο τον κώδικα να διορθώσω κάτι η SGC παίρνει μετά την πρώτη παράμετρο 16 words όχι bytes και ορίζει ένα sprite 8x8 με 8 χρώματα και flashing σε mode 256x256 ή ένα sprite 16x8 σε mode 512x256 με τέσσερα χρώματα, λίγο καλύτερα από ότι νόμιζα. Επειδή τα sprites ζωγραφίζονται με xor το χρώμα τους αλλάζει ανάλογα με το background color.
Το πως κωδικοποιούνται τα pixels/χρώματα σε κάθε word εξηγείται στην παράγραφο 10.2 του QL Technical Guide.
Το μέγεθος και το πλήθος των sprite θα μπορούσε να μεγαλώσει εύκολα με κανένα περιορισμό εκτός της διαθέσιμης μνήμης.
 
Top