News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu

asic unlock/lock sequence

Started by arnoldemu, 15:06, 04 September 12

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

arnoldemu

I am running some tests concerning the asic unlock/lock sequence.

It says that to lock the features again, send all the data except the last &ee. Instead send another value and then the asic will be locked.

However, on my 464plus at least, it doesn't seem to work. Once the asic has been unlocked, the asic ram can be paged in and out, I can try to lock it, but the ram can still be paged in/out.

Anyone have any success with *locking* the asic features again?


My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Grim

The answer can be found in the "Controlling access to computer system features" patent.

The locking sequence is composed as follow:
NZB, &00, &FF, &77, &B3, &51, &A8, &D4, &62, &39, &9C, &46, &2B, &15, &8A, LOCK, EOK

- The first two bytes, NZB and &00 correspond to the sync sequence (telling the ASIC a key sequence is coming). NZB means Non Zero Byte (NZB>0).
- The next 13 bytes correspond to the activation key. If it's valid, then the ASIC will allow access to it's locking status.
- LOCK is the value to use to lock or unlock the ASIC. If LOCK=205, access to the RMR2 register will be allowed. For any other value, access to RMR2 is disabled.
- EOK is a dummy byte. It's value doesn't matter but it must be sent to tell the ASIC that the (un)locking request is completed.

IIRC, access to the RMR2 is automatically locked as soon as the sync+key sequences are sent but the ASIC will wait for the next bytes to permanently change the lock status.

Devilmarkus

Thanks, Grim, for explaining.

So I embedded this ASIC_Sequence code to my emulator (Based on Kev's Arnold source):
    protected final int SEQUENCE_SYNCHRONISE_FIRST_BYTE = 0;
    protected final int SEQUENCE_SYNCHRONISE_SECOND_BYTE = 1;
    protected final int SEQUENCE_RECOGNISE = 2;
    protected final int SEQUENCE_GET_LOCK_STATUS = 3;
    protected final int SEQUENCE_SYNCHRONISE_THIRD_BYTE = 4;
    protected int CurrentSequencePos;
    protected int RecogniseSequenceState;
    protected int lockvalue = -1;

    public void ASIC_EnableDisable(int value) {
        value &= 0x0ff;
        switch (RecogniseSequenceState) {
            case SEQUENCE_SYNCHRONISE_FIRST_BYTE: {
                /*
                 * we are waiting for the first byte of synchronisation
                 */
                if (value != 0) {
                    RecogniseSequenceState = SEQUENCE_SYNCHRONISE_SECOND_BYTE;
                }
            }
            break;

            case SEQUENCE_SYNCHRONISE_SECOND_BYTE: {
                /*
                 * at this point we already have a non-zero byte to start the
                 * synchronisation.
                 *
                 * we are waiting for the second byte of synchronisation
                 *
                 * this byte must be zero for synchronisation. If it is
                 * non-zero, then it can still count as part of the
                 * synchronisation.
                 */

                if (value == 0x00) {
                    /*
                     * got zero. We are now waiting for the first byte of the
                     * sequence
                     */
                    RecogniseSequenceState = SEQUENCE_SYNCHRONISE_THIRD_BYTE;
                }
            }
            break;

            case SEQUENCE_SYNCHRONISE_THIRD_BYTE: {
                /*
                 * we are waiting for the first data byte of the sequence. To
                 * get here we must have had a non-zero byte followed by a zero
                 * byte
                 */

                /*
                 * have we got the first byte of the sequence?
                 */
                if (value == 0x0ff) {
                    /*
                     * first byte of sequence, get ready to recognise the
                     * sequence.
                     */
                    RecogniseSequenceState = SEQUENCE_RECOGNISE;
                    CurrentSequencePos = 1;
                } else {
                    if (value != 0) {
                        /*
                         * we got a non-zero byte, and it wasn't the first part
                         * of the sequence. / this could act as the first byte
                         * of synchronisation ready for a zero / to follow.
                         */
                        RecogniseSequenceState = SEQUENCE_SYNCHRONISE_SECOND_BYTE;
                    }

                    /*
                     * if we got a zero, we are still synchronised. We are still
                     * waiting for the first byte of sequence.
                     */
                }

            }
            break;

            case SEQUENCE_RECOGNISE: {
                /*
                 * we want to recognise the sequence. We already recognise the
                 * first byte.
                 */

                if (value == 0x000) {
                    RecogniseSequenceState = SEQUENCE_SYNCHRONISE_THIRD_BYTE;
                } else {
                    if (value == ASIC_EnableSequence[CurrentSequencePos]) {
                        /*
                         * data byte the same as sequence
                         */

                        /*
                         * ready for next char in sequence
                         */
                        CurrentSequencePos++;

                        if (CurrentSequencePos == ASIC_EnableSequence.length) {
                            /*
                             * store value to lockvalue
                             */
                            asicLocked = true;
                            lockvalue = value;

                            /*
                             * sequence is almost complete. If next byte is sent
                             * then the asic will be enabled / disabled depending on lockvalue.
                             */
                            RecogniseSequenceState = SEQUENCE_GET_LOCK_STATUS;
                            break;
                        }
                    } else {
                        CurrentSequencePos = 0;
                        RecogniseSequenceState = SEQUENCE_SYNCHRONISE_SECOND_BYTE;
                    }
                }
            }
            break;

            case SEQUENCE_GET_LOCK_STATUS: {
                /*
                 * the sequence has been correct up to this point, therefore we
                 * want to lock or un-lock the ASIC
                 */
                {
                    asicLocked = lockvalue != 0x0cd;
                    System.out.println("ASIC " + (asicLocked ? "L" : "Unl") + "ocked!!!");
                    cpc.memory.asiclocked = asicLocked;
                    setModeAndROMEnable();
                    cpc.memory.remap();
                }

                if (value != 0) {
                    RecogniseSequenceState = SEQUENCE_SYNCHRONISE_SECOND_BYTE;
                } else {
                    RecogniseSequenceState = SEQUENCE_SYNCHRONISE_FIRST_BYTE;
                }
            }
            break;
        }
    }
When you put your ear on a hot stove, you can smell how stupid you are ...

Amstrad CPC games in your webbrowser

JavaCPC Desktop Full Release

arnoldemu

@Grim: Thanks. The EOK byte was the missing part of the puzzle.
The Arnold5 specification doesn't state this.

My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

arnoldemu

#4
All the asic locking code I've seen (csd, test cart), turns off the asic ram page then does an unlock.
Then checks the ram.

I think this is not correct.

Why?

If asic features are unlocked then turning off the register page will work. writing to the area will be like any other ram.
Then it does the lock and writes to the ram to check. But, this will only fail, if the ram failed to page out. It will not check if the lock has actually worked.

My code unlocks the asic, keeps the asic ram enabled, then locks it again to see what happens. All indications point to that it is still enabled.
This seems logical, because the lock (and this is something I am testing), may not turn off features once you have unlocked them and used them for the first time, all it should do is stop the register page from being enabled.

So perhaps it *is* working. Ok, so i should then try to use the i/o after the unlock to see if it makes any difference. In theory if it's blocked, it should remain in the state it was either enabled or not.

My theory is seeing what happens if you unlock, write some asic stuff (e.g. to setup a tv style logo in the top left ;) ), then re-lock asic.

But in practice, so far I can't get it to relock correctly.
No sequence seems to work.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

arnoldemu

#5
Ok, this is what I can confirm according to my tests:

- asic is locked after hard reset (e.g. reset switch) or power on/off
- asic unlock sequence is:

<not zero> <zero>
&ff,&77,&b3,&51,&a8,&d4,&62,&39,&9c,&46,&2b,&15,&8a,&cd
<any value>

- asic lock sequence is:
<not zero> <zero>
&ff,&77,&b3,&51,&a8,&d4,&62,&39,&9c,&46,&2b,&15,&8a
<any value - but not &cd>

Here the last value acts as the EOK as well as indicating the lock was not done.

- asic lock/unlock sequence blocks the I/O port for enabling the ram ONLY

- asic lock remains in it's current state until the sequence completes

- asic lock doesn't disable the ram. So if you did unlock, enable ram, lock, you can still write to the ram. it is stuck in place now and you can't disable it unless you unlock the asic and disable it. ;)

- asic raster interrupt remains active after lock

- asic screen split remains active after lock

- asic sprites remain active after lock (tested by unlock, setting sprites, then lock/unlock in sequence. No visible change, sprite remains on screen).

- asic palette remains active after lock

It seems to confirm the statement in arnold 5 docs that say the lock is there for access to the I/O for the ram page in/out.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

arnoldemu

Quote from: Devilmarkus on 20:45, 04 September 12
Thanks, Grim, for explaining.

So I embedded this ASIC_Sequence code to my emulator (Based on Kev's Arnold source):
Yes it's not correct.
I modified a few other things too now to make the result correct.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Devilmarkus

We need a test program, which unlocks/locks asic and also does some + stuff... ;)
When you put your ear on a hot stove, you can smell how stupid you are ...

Amstrad CPC games in your webbrowser

JavaCPC Desktop Full Release

MacDeath


arnoldemu

#9
Quote from: Devilmarkus on 15:32, 05 September 12
We need a test program, which unlocks/locks asic and also does some + stuff... ;)
Yes I wrote some new ones ;)

so far my new tests check raster interrupts, split screen, lock/unlock.
I am trying to test every detail.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

arnoldemu

#10
Quote from: MacDeath on 16:56, 05 September 12
like the test cartridge ?
it doesn't test the lock/unlock sequence correctly.
the correct test should be:

locked with ram disabled:
enable ram, check, disable ram, check
(no difference)

unlocked, ram enabled, locked:
enable ram, check, disable ram, check
should always act like ram is enabled.

well this is what my tests show.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Powered by SMFPacks Menu Editor Mod