Using expanded CPC Plus palette from BASIC

Hi all!

As I’m a new user of this forum and this is my first post, let me introduce myself: My name is David and I’m from Barcelona, Spain. Although I’ve never owned an Amstrad computer (my first computer was a Commodore 64), I experienced the 8 and 16-bit computer boom of the 80s and early 90s and some of my friends had a CPC464 (and one of them a CPC6128).

Recently I’ve become interested in retro-programming in BASIC for vintage 8 bit and 16 bit systems, both for learning and for fun. Some months ago I wrote a simple game called “Mega Chase”, and I’ve been writing versions for different computers such as the Commodore 64, the MSX2+, the Amiga (AGA), the Atari ST/E, the Commodore VIC-20, the Commodore Plus/4, or the Mega65 (not a “vintage” system strictly speaking, though). Now I’m developing a version for the Amstrad CPC “plus” series, to take advantage of the expanded colour palette and the hardware sprites.

I’m facing a problem, though, when trying to use the 4096 colour palette for the main screen (the specific sprite palette works perfectly). When, for instance, I want to change the border colour (address &6420 and &6421 of the ASIC), the original colour is restored immediately, in the next frame. The results are the same even if I use de “DI” instruction to disable interrupts. It does the same both on WinApe (Windows) and in Amspirit (MacOS).

Is there a way to use the expanded palette from BASIC without the “immediate restoration” effect?

Best,

David (shad0wfax)

3 «Μου αρέσει»

I’d be interested to see if you can get that working. Could make for some very interesting projects.

Oh, our first new user! Welcome, hope you find some answers here :slightly_smiling_face:

We have this kind of issue in ASM when using hardware access (using Hardware registers and colors), the firmware just reset it on each new frame… To correct this, we disable firmware and take full control of the CPC.
So I am not sure that you can keep a CPC+ color inside a BASIC program because firmware is necessary for BASIC.

If you use FRAME (Basic 1.1) did you try to change it just after (to set it at beginning of each frame)?

The problem is the CPC firmware sets up and interrupt routine that changes colours every frame (this is how flashing colours work). You basically have two options:

  1. The easy way: Use B-Asic extensions which handle all this for you, as well as giving you a bunch of other useful RSX commands

  2. The marginally more difficult way: In AA114, in the Tech tips page, there is a short BASIC listing which handles removing the interrupt handlers for you. Don’t be tempted to follow the advice a few issues earlier, in the article about using the Plus features because it just does it in a nasty ha KY way that slows down keyboard responsiveness and probably messes up all the timers etc.

2 «Μου αρέσει»

Here’s the part @AndyCadley mentioned clipped out.

3 «Μου αρέσει»

That was a nice letter Rob sent in.

Yeah. Although he is incorrect about the need to re-lock the ASIC after changing colours etc, that is completely unnecessary.

Σας ευχαριστώ πολύ όλους για τις απαντήσεις σας. Είναι προφανές ότι πρόκειται για μια πολύ ενεργή και βοηθητική κοινότητα :slight_smile:

Κρίμα που η Amstrad δεν παρείχε μια ενημερωμένη έκδοση της Basic όταν κυκλοφόρησε τη σειρά «Plus», ώστε να αξιοποιήσει τις βελτιώσεις του ASIC, καθώς αυτό θα διευκόλυνε πολύ τα πράγματα. Δεν γνώριζα για την ύπαρξη της B-Asic, αλλά ούτως ή άλλως δεν μπορώ να τη χρησιμοποιήσω, καθώς ο χώρος της μνήμης χρησιμοποιείται ήδη από κάποια δεδομένα και τη ρουτίνα μουσικής διακοπών (interrupt music routine). Επιπλέον, θέλω να μείνω όσο το δυνατόν πιο πιστός στη Basic 1.1, καθώς θέλω να κάνω compile τον κώδικα με τον ABASC. Αυτό σημαίνει ότι αυτή τη φορά δεν θα χρησιμοποιήσω την εκτεταμένη παλέτα για τα γραφικά, παρά μόνο για τα sprites, αλλά και πάλι είναι αρκετά καλό, επειδή μπορώ να κάνω εφέ όπως εναλλαγή χρωμάτων (colour cycling) και fades.

Σας ευχαριστώ και πάλι για τη βοήθειά σας!

2 «Μου αρέσει»

Υπάρχει διαφορά μεταξύ της εντολής BASIC «DI» και της εντολής της γλώσσας assembly «DI». Ενώ η πρώτη απενεργοποιεί μόνο τις ρουτίνες που έχουν καταχωριστεί μέσω των «AFTER» ή «EVERY», η δεύτερη θα απενεργοποιήσει όλες τις ρουτίνες που βασίζονται σε διακοπές (interrupt-driven routines), ειδικότερα επίσης τη σάρωση του πληκτρολογίου και την αναπαραγωγή μουσικής. Ωστόσο, όσο εκτελούνται οι ρουτίνες του υλικολογισμικού (firmware), θα επαναπρογραμματίζουν τα χρώματα 50 φορές το δευτερόλεπτο ώστε να επιτρέπεται το αναβόσβημα των χρωμάτων (στη BASIC π.χ. με την εντολή BORDER 1,0). Αυτό σημαίνει ότι: Αν αλλάξετε κάτι στο υλικό (hardware), θα επανεγγραφεί (overwritten) στο επόμενο καρέ.

Kάτι ακόμα: Αν εμφανίσετε σταδιακά (blend in) τη προσομοιωμένη σελίδα μνήμης μαζί με τα ASIC controls, την ίδια στιγμή η κανονική σελίδα μνήμης εξαφανίζεται σταδιακά (blend out). Πρέπει να βεβαιωθείτε ότι η BASIC δεν χρησιμοποιεί αυτό το μεγάλο μπλοκ μνήμης (με την εντολή MEMORY), διαφορετικά θα συμβούν ανεπιθύμητα πράγματα (π.χ. η BASIC θα προσπαθήσει να ερμηνεύσει και να εκτελέσει τα ASIC controls ως πρόγραμμα BASIC). Για τον ασφαλή επαναπρογραμματισμό του ASIC, πιστεύω ότι μια μικρή ρουτίνα σε assembler θα ήταν χρήσιμη.

Anakalyp

MODE 2 : BORDER 0,1

10 MEMORY &9FFF       ' Προστασία μνήμης για τη μικρή ρουτίνα συμβολικής γλώσσας (assembler).
20 POKE &A000,&CF     ' RST &10    ;; LO JUMP
30 POKE &A001,&55     '   DEFB &55 ;; χαμηλό byte διεύθυνσης
40 POKE &A002,&0D+&80 '   DEFB &8D ;; υψηλό byte διεύθυνσης + ενεργοποίηση BASIC ROM
50 CALL &A000         ' Κλήση της προετοιμασμένης ρουτίνας συμβολικής γλώσσας.
60 OUT &7F00,1        ' GateArray: Επιλογή Πένας 1 (SELECT PEN 1)
70 OUT &7F00,&4A      ' GateArray: Ορισμός Χρώματος (INK) σε brightYellow

Θα χρειαστεί να τροποποιήσετε τη γραμμή 30 ανάλογα με το σύστημα. Οι τιμές είναι οι εξής:

  • 464 - &4F
  • 664 - &51
  • 6128 και Plus - &55

Ίσως είναι δυνατόν να επιτευχθεί το ίδιο με μια άλλη προσέγγιση, π.χ. απλώς απενεργοποιώντας τη ρουτίνα συμβάντος (event routine) αντί να την αφαιρέσετε.


Η κατάτμηση των απαντήσεων επιτρέπεται μόνο έως και τρεις διαδοχικές απαντήσεις. Επομένως, πρέπει να συγχωνεύσω τα παραπάνω με την τέταρτη απάντησή μου παρακάτω.

Μεδιέφερε πώς λειτουργεί το μικρό πρόγραμμα από το AA114. Αφού έκανα αποσυμβολισμό (disassembling) και το κατάλαβα, δεν έχω πειστεί πραγματικά: Θα λειτουργήσει, αλλά δημιουργεί μια άλλη ρουτίνα διακοπής (interrupt routine) για να καταπολεμήσει τη ρουτίνα του firmware (μηδενίζοντας συνεχώς έναν μετρητή). Πιστεύω ότι η απενεργοποίηση της ρουτίνας του firmware είναι ο καλύτερος τρόπος.

NOLIST
ORG #8000

KL_NEW_FRAME_FLY    EQU #BCD7
KL_DELETE_FRAME_FLY EQU #BCDD
PRIORITY            EQU #81
ROM_CONFIGURATION   EQU #FF
BLINK_COUNTER       EQU #B7F8

enable_color_change_suppression:           ;;          ;;
    LD HL,event_block                      ;; 21 17 80 ;; Ορισμός δείκτη στα δεδομένα συμβάντος.
    LD BC,PRIORITY*256 + ROM_CONFIGURATION ;; 01 FF 81 ;;
    LD DE,RESET_BLINK_COUNTER              ;; 11 12 80 ;; Ορισμός δείκτη στη ρουτίνα συμβάντος.
    JP KL_NEW_FRAME_FLY                    ;; C3 D7 BC ;; Εγκατάσταση νέας ρουτίνας συμβάντος.

disable_color_change_suppression:          ;;          ;;
    LD HL,event_block                      ;; 21 17 80 ;; Ορισμός δείκτη στα δεδομένα συμβάντος.
    JP KL_DELETE_FRAME_FLY                 ;; C3 DD BC ;; Απεγκατάσταση ρουτίνας συμβάντος.

reset_blink_counter:                       ;;          ;;
    XOR A                                  ;; AF       ;;
    LD (BLINK_COUNTER),A                   ;; 32 F8 B7 ;; Επαναφορά (μηδενισμός) του μετρητή αναβοσβήματος.
    RET                                    ;; C9       ;;

event_block:                               ;;          ;; Αποθήκευση δεδομένων συμβάντος εδώ.
    ;; DEFW next_event_block               ;;          ;;
    ;; DEFB counter                        ;;          ;;
    ;; DEFB priority                       ;;          ;;
    ;; DEFW event_routine                  ;;          ;;
    ;; DEFB rom_configuration              ;;          ;;

Εντάξει, αυτό εξηγεί γιατί η «αποκατάσταση χρώματος» παραμένει παρά τη χρήση της βασικής εντολής «DI». Ευχαριστώ για τη διευκρίνιση.

Όταν χρειάζεται να αποκτήσω πρόσβαση στους καταχωρητές του ASIC (βασικά, για την τοποθέτηση των sprite ή/και την παλέτα των sprite), χρησιμοποιώ την ακόλουθη δομή: DI:OUT &7F00,&B8:[πρόσβαση στους καταχωρητές του ASIC]:OUT &7F00,&A0:EI. Σύμφωνα με το προηγούμενο μήνυμά σας, αυτό σημαίνει ότι τα «DI» και «EI» δεν είναι απαραίτητα;

Τα DI/EI της BASIC δεν θα κάνουν τίποτα εκεί, αποτρέπουν μόνο την εκτέλεση των ρουτινών AFTER και EVERY.

Ναι! Δουλεύει! Σας ευχαριστώ πολύ!

Στην υγειά σας,

David

1 «Μου αρέσει»

Τέλεια, η επισήμανση σύνταξης λειτουργεί εξαιρετικά, αν και είναι λίγο ελλιπής!

1 «Μου αρέσει»