GAMEX game launcher code source with comments

* Starglider  Gamex  launcher
* Compatible on all ST(E) , any TOS.
* Here we use special GEMDOS in RAM
* It fixes copmatibility problems, but runs not on Falcon


 * Atari ST gaming system GAMEX
* Features:  it needs min 1MB RAM for games working with 512KB normally
* Game may be exited to Desktop. In that case gamestate is preserved in area 512KB-1MB
* User may after exit to Desktop to continue playing or to save gamestate on disk

* This will be open source
* Created by Pera Putnik, May 2009.



* Example of Single part, little TOS dependent game launcher
* with special GEMDOS in RAM - modded GEMDOS 0.15 of TOS 1.04

* Game : Starglider


* Starglider  gamex  launcher
* Compatible on all ST(E) because using
* TOS 1.04 GEMDOS part:   V.015

* AUTO run without reset of ST !
* running from hard drive
* Game exit to Desktop, pos saving
* 1MB RAM needed...

*Concept:

* Installing GEMDOS 0.15 in high RAM
* leave place for original TOS save
* some 150-180KB (with drivers)
* and fast init it (no floppy boot ...)
*

* in this, first version just depack executable
* and run under GEMDOS 0.15


* Starglider 1  is for  specific location !





* Launcher stage 1:  reserving TOP RAM - lovering memtop, phystop.

* Values for this game:
GameScrB       equ  $78000    *For games working with 512KB
AltRamPos    equ  $80000
MainInb        equ  $FFF40
SwapLen        equ  $7FCF8   * in fact save len

GameRest    equ   $7FD20


SysStor    equ    $FFF80     *Place for storing TOS system - 128 bytes



begin        *Beginning of program

* Adding low RAM usage check and exit if too much is used...

    lea    hwpal(pc),a1
    cmp.l    #FreeMem-DeskCopy-48,a1  *Place available to store TOS
    bcs.s    lowRamOK

    lea    lowRamTM(pc),a0
toPMex    bsr    pmess

    move.w    #1,-(sp)
    trap    #1
    addq.l    #2,sp

    clr.w    -(sp)
    trap    #1    *Exit

incomp    lea    incoTM(pc),a0
    bra.s    toPMex

noENR    lea    RAMne(pc),a0
    bra.s    toPMex


lowRamOK

NewPhyst     equ  $80000    *For 512K games

* First test HW, if only 512KB phys. then skip whole Gamex stuff

    pea    hwdet(pc)
    move.w    #38,-(sp)
    trap    #14
    addq.l    #6,sp


    lea    machin(pc),a1
    cmp.b    #3,(a1)  *TT TOS vers.
    beq.s    incomp
    cmp.b    #4,(a1)  *Falcon TOS vers.
    beq.s    incomp

* Check Physical RAM
    cmp.b    #1,7(a1)  * Is only 512K ?
    beq.s    noENR



    move.l      4(sp),a2   *basepage adr.
    lea    $77FE0,sp
    clr.l    (sp)
    move.l    a2,4(sp)


get_bp   
    move.b    #1,machin+2    * 'Set' TOS RAM size
    move.l      a2,basep
    move.l    4(a2),d2   *memtop

    move.l    d2,memt
    move.l     #NewPhyst,d1
    sub.l    #$8000,d1   *This is new memtop

    move.l     d1,4(a2)     * Correct in basepage

* Conditional settings in subrutine following :
    pea     lowmsuv(pc)
    move.w     #38,-(sp)
    trap    #14
    addq.l    #6,sp

   

 * Now TOP RAM is reserved, TOS sees only 512KB of RAM !

stage2



* Get current screen resolution:

    move.w    #4,-(sp)
    trap    #14
    addq.l    #2,sp
   
* Falcon patch:
    cmp.w    #3,d0   *Allow only  0-2 !
    bcs.s    store_res
    clr.w    d0

store_res     move.w    d0,DeskRes


    dc.w     $A00A       * Hide mouse
    clr.w     -(sp)   *set low res
    pea     GameScrB
    pea    GameScrB
     move.w    #5,-(sp)
    trap    #14
    lea    12(sp),sp




* Preparing some IKBD storage:

    move.w    #34,-(sp)   *Kbdvbase
    trap    #14
     addq.l      #2,sp   
 
    move.l     d0,a1
    lea              32(a1),a1   * IKBD system vector
    move.l    a1,ikbdsysv
    move.l    (a1),orgikbds




*   relative pos,   what

*     0    USP
*      4    Desktop screen resolution at prg start !
*    6    SSP
*    10    Palette, 32 bytes
*    42    MFP state, 24 bytes
*    66    ?

mfpof    equ  42


   

* Must following in Supervisor mode

    clr.l    -(sp)
    move.w    #32,-(sp)
    trap    #1
    addq.l    #6,sp
    move.l    d0,uspstor

    lea    SysStor+10,a6   *palette store pos

* Save desktop palette:

    lea    $FFFF8240.w,a1
    moveq    #15,d1
.palc    move.w    (a1)+,(a6)+
    dbf    d1,.palc


* Saving MFP state.....


* Save MFP registers :

    lea    $FFFFFA01.w,a1
    moveq    #23,d2   *24 registers, up to $FFFA2F
.mfpsl    move.b    (a1),(a6)+
    addq.l    #2,a1
    dbf    d2,.mfpsl


*Timer B and C needs accurate reading:
* Other 2 is off in TOS....

*So we read them some time and take
*Max value:

   * To speed it up we can test both in same time !

    lea    $FFFFFA21.w,a1
    lea    $FFFFFA23.w,a2
    move.w    #3777,d7   *Determines time for read
    clr.b    d2
    clr.b    d4

retimbl    move.b    (a1),d1
    cmp.b    d1,d2
    bcc.s    renotbb

rebiggerb    move.b    d1,d2
renotbb    move.b    (a2),d3
    cmp.b    d3,d4
    bcc.s    renotbc

rebiggerc    move.b    d3,d4
renotbc    dbf    d7,retimbl

    move.b    d2,-8(a6)      * Timer B Data reg
    move.b    d4,-7(a6)      * Timer C Data reg.

* TOS values are normally:  Timer B: $41 (PAL mode), Timer C:  $C0  !



* Launcher stage 3:   storing TOS, desktop, this prg active part in * Upper RAM for later restore


* First show HW, option select by need ...

show_hw
    bsr    clearkb

    move.l    #GameScrB,screnb   *screen pos. for pic show

   
    pea    hwpal(pc)
    move.w #6,-(sp)
    trap  #14
    addq.l    #6,sp
   
    move.w  #37,-(sp)
    trap  #14
    addq.l  #2,sp

    bsr    machipr    *HW detect. print

   
*Little pause to see it:
    move.w    #1177,d7

dell1    move.w  #37,-(sp)
    trap  #14
    addq.l  #2,sp

* Allow abort with keypress:
    pea    $600ff
    trap    #1
    addq.l    #4,sp
    tst.b    d0
    beq.s    wait_k
   
    cmp.b    #"M",d0  * Optional MSTE settings
    beq    megastes
    cmp.b    #"m",d0
    beq    megastes

    bra.s    toPicsh
wait_k    dbf    d7,dell1

toPicsh

steph         bsr    photoc    *Call Photochrome pic show rut., on (M)ST(E)
   

loadg    *now set stack pointers in picshow area

    lea    hwpal(pc),sp
    lea    -200(sp),a1
    move.l    a1,usp


    lea    SysStor,a6  
    move.l    a1,(a6)+     *Store USP
    move.w    DeskRes(pc),(a6)+

    move.l    sp,(a6)   *SSP






* Header build support #2 :

    lea    MainInb,a2
    lea    64(a2),a1

    move.l    #SwapLen,(a2)+
    move.l    #FreeMem,(a2)+   
    move.l    #SysStor,(a2)+
    move.l    #GameRest,(a2)+
    move.l    #GameStat,(a2)+
*    move.l    #GameJmp,(a2)
    move.l    #$A000+backingam-gamex,(a2)+
    move.w    #$C3C2,(a2)+   *Keys
    clr.w    (a2)+
    clr.l    (a2)+   *Forced Timer regs
    clr.l    (a2)+
    move.w    #1,(a2)+     *Flag for COS 1.00 at $C0100
*  GXUTIL must install GOS 1.00 when loading saved gamestate !


clr_maininb    clr.w    (a2)+
    cmp.l    a2,a1
    bne.s    clr_maininb   *Clear rest for future good



   


* Now  set  GEMDOS 0.15
variant to loc  $C0100  :

* Must little higher than $C0000 because of PRG header !
* $C0020  not good, must be round by $100 from some reason !!!
* so using $C0100  !




* Usually  need new SP to avoid overlap !
    lea    $77F80,sp

* Yet to add load from common DIR C:\GAMEX ...

* Load  it
    clr.w    -(a7)
    pea    d15n(pc)
    move.w    #$3D,-(a7)
    trap        #1
    addq.l    #8,a7
    move.w    d0,d7
    bmi    exitu

d15loc    equ    $C0100
   
*    Loading packed:
    pea    hwpal+8(pc)
    pea    68000    *len ++
    move.w    d7,-(a7)
    move.w    #$3F,-(a7)
    trap    #1
    lea    12(sp),sp

    move.w    d7,-(a7)
    move.w    #$3E,-(a7)
    trap    #1
    addq.l    #4,a7

* Depack :

    lea    d15loc-28,a4   *28 bytes lover due header
    lea    hwpal+40(pc),a1
    bsr    depak3



* Relocate,  here no basepage !

    lea    d15loc-28,a3
   
    move.l    2(A3),A0
    add.l    6(A3),A0
    add.l    14(A3),A0   *symbol tabl len
    lea    28(A0),A0   *by header length
    add.l    A3,A0
* No data segement here
    lea     28(a3),a1 *text begin
    move.l     a1,d0
          move.l    a0,a2 * reloc table begin

    tst.l    (A0)
    beq.s    corrbp2

    add.l    (A0)+,A1
    clr.l    d1
relol2    add.l    D0,(A1)
bigd2   
    MOVE.B    (A0)+,D1
    beq.s    corrbp2
    CMP.B    #1,D1
    bne.s    nmd2
    lea    $FE(A1),A1
    BRA.S    bigd2
nmd2    ADDA.L    D1,A1
    BRA.S    relol2
corrbp2
    * GEMDOS 0.15 now ready
* called GOS  from now - Gemdos or Gaming OS .
* this is with GOS 1.00  -  no disk support - for games not loading/saving





* Saving  area from adr 8 to  hwpal  in  high RAM
* that's enough for successful return to Desktop by exit

DeskCopy    equ    $D7008   * 167000 bytes available
* what must be enough for TOS 2.06 with hard ddriver, buffers
      lea    8.w,a5
    lea    DeskCopy,a6   * We have enough place...
   
    lea    hwpal(pc),a1
    move.l    a1,d0
    divu    #48,d0     *get loop count
    move.w    d0,swapln+2    *Set same len for TOS restore *swap part


.cod    movem.l      (a5)+,d1-d7/a0-a4   *48 bytes at once
     movem.l    d1-d7/a0-a4,(a6)   
    lea    48(a6),a6
    dbf    d0,.cod   
* Little overshot, no problems...




Stage 4:  preparing setting Exit to Desktop in stored mem.  :

* We need only  regular exit TOS call at certain point...
* Copy code in free area $FFD00 - $FFFFF

FreeMem    equ    $FFD20       *For 512KB games, 1MB total RAM



    lea    GamexCtrl(pc),a1
    lea    FreeMem,a2
    move.w    #127,d2      *There is 768 bytes place !
* But top is reserved for storing state, palette etc....
* so copying only 512 bytes ....

.cou    move.l    (a1)+,(a2)+
    dbf    d2,.cou






* Now load game

    clr.w    -(a7)
    pea    exen(pc)
    move.w    #$3D,-(a7)
    trap    #1
    addq.l    #8,a7
    move.w    d0,d7
    bmi    exitu

gamela    equ    $30E00   

    pea    gamela
    pea    290006   * Packed len, singleparted
    move.w    d7,-(a7)
    move.w    #$3F,-(a7)
    trap    #1
    lea    12(sp),sp

    move.w    d7,-(a7)
    move.w    #$3E,-(a7)
    trap    #1
    addq.l    #4,a7


* Must move up:
    lea     $77B80,a4 
    move.l    a4,a3 *save adr.
    lea       coup(pc),a1
    moveq    #116,d2 *whole mc len/4-1
mouc    move.l    (a1)+,(a4)+
      dbf     d2,mouc 
 
      jmp (a3)


   
   
exitu     clr.w -(sp)
    trap #1


game_dest     equ    $AA56   * For Starglider  1
* address fixed in fact !
* so reloc is unnecessary

coup           move    #$2700,sr
    lea    game_dest,a4    *depack here ...
    lea    gamela+32,a1
    bsr    depak3

   
* Anti-load patch:

    move.l    #$60000080,$DD54
*skips TRA file loads and building ...


* Setting some informations for game starting:

procee   
    move.l    #game_dest,$5F0.w   * Write start address for 0.15
    clr.w    $5F4.w      *Flag that user mode start needed


* Inject  game  exit activation :

*   To pos  $A000
* Warning !  Area up to OS_end will be cleared ( adr $61C2 ! )


     lea    gamex(pc),a1
    lea    $A000,a2
    moveq    #100,d2
.gac    move.l    (a1)+,(a2)+
    dbf    d2,.gac

* Link to :
    lea    $B694,a2   * ingame IKBD receive code
    move.w    #$4EF9,(a2)+
    move.l    #$A000,(a2)





* Must clear RAM above - game specific !

    move.w    #7904,d2
.clr    clr.l    (a4)+
    dbf    d2,.clr   


* Now jump in 0.15 start:

    jmp    d15loc   * This will run game after setting GEMDOS




depak3    clr.l d0
    moveq    #6,d4
    moveq    #$3f,d5   *for masking bits 5-0

* Bit meaning:  7 - if set it's back referrer , if 0 then bits
* 6-0 give count of literals to copy
* if all bits are 0 it is terminator

* When bit 7 set, bit 6: if 1 then long distance back given by 2 following byte
*  bit 6: when 0  then short distance given by following 1 byte
*  bits 5-0  count of bytes referred.
*  By short refer.  0 means 3, 1 means 4, etc  up to 66 .
*  By long refer.  0 means 4, 1 means 5, etc  up to 67 .


main3     clr.w d0 *prep for dbf
    move.b (a1)+,d0
    bmi.s back3
    beq.s nom3 *end
    subq.w #1,d0 *compens dbf
litc     move.b (a1)+,(a4)+
    dbf d0,litc
    bra.s main3

nom3    rts

back3    move.b d0,d2
    and.w d5,d2 *d5=$3f
* Test is long or short referrer:
    btst    d4,d0   *test bit 6
    bne.s  longr
   
    addq.w #2,d2 *compens   
displl    move.b (a1)+,d0 * displac
calcadr    move.l a4,a2
    sub.l d0,a2
baksl    move.b (a2)+,(a4)+
    dbf d2,baksl
    bra.s main3

longr    addq.w #3,d2 *compens
    move.b (a1)+,d0 * displac
    lsl.w  #8,d0   *MSB
    bra.s   displl

* End of C3 depak


exen      dc.b  "SG1W.FIC",0   * Packed game, whole with title pic
d15n    dc.b  "D15R_NG1.FIC",0   * Packed GEMDOS, GOS 1.00
    even


*uspstor    dc.l    0



*Game exit code:  *

gamex      cmp.b   #$C3,d0   * For F9
    beq.s  gamex_w

backingam   
gamnoex      cmp.w    #$F8,d0
    bpl.s    toB6CE
    jmp          $B69A   * 6 bytes after game exit inj. pos.
toB6CE    jmp    $B6CE

gamex_w   *Exiting game with storing state

* Code for game state store when exit is requested:


GameStat    equ    $A180   *Set for particular game always


GameStoPl    equ      $A000   *Where to place code for gamestate save



GameSto    * The code itself. Must be PC relative !!!

* Presumable we are in supervisor mode....
* For games not running in SV need some switch, workaround...
* will see later....


*     0    USP
*      4    Cur screen resolution - almost always 0 !
*    6    SSP
*    10    Palette, 32 bytes
*    42    MFP state, 24 bytes
*    66    Screen base
*    70    IKBD joy status, 8 bytes
*    80    SR,  2 bytes
*     84    PSG status, 14 bytes
*    100    IKBD mouse status, 8 bytes
*    108    Next thing worth to store  :-)



ikbdof      equ    70
ikbdm_of    equ      100
srofs      equ    80
psgofs       equ    84
   

* Store CPU regs, SR, stack pointers
   
   
    movem.l    d0-d7/a0-a6,-(sp)
    lea    GameStat,a6
    move.w    sr,80(a6)


    move.l    usp,a1
    move.l    a1,(a6)+     *Store USP
    move.b    $FFFF8260.w,d1
    and.w    #$3,d1
    move.w    d1,(a6)+   * Res. Usually 0

    move.l    sp,(a6)+  *SSP


* Saving PSG state:
    lea    $FFFF8800.w,a1
    lea    GameStat+psgofs,a2
    moveq    #0,d2
.psgl    move.b    d2,(a1)
    move.b    (a1),(a2)+
    addq.b    #1,d2
    cmp.b    #14,d2
    bne.s    .psgl




* Save palette:

    lea    $FFFF8240.w,a1
    moveq    #15,d1
.palc    move.w    (a1)+,(a6)+
    dbf    d1,.palc


* Saving MFP state.....


* Save MFP registers :

    lea    $FFFFFA01.w,a1
    moveq    #23,d2   *24 registers, up to $FFFA2F
.mfpsl    move.b    (a1),(a6)+
    addq.l    #2,a1
    dbf    d2,.mfpsl


*Timer A, C and D need accurate reading:
* we presume that timer B is intact (for now)

*So we read them some time and take
*Max value:

   * To speed it up we can test all 3 in same time !

    lea    $FFFFFA1F.w,a1   *Timer A data
    lea    $FFFFFA23.w,a2   *Timer C data
    lea    $FFFFFA25.w,a3   *Timer D data


* Trying with longer test: worked not

    move.w    #6777,d7   *Determines time for read
    clr.b    d2
    clr.b    d4
    clr.b    d6

gatimbl    move.b    (a1),d1
    cmp.b    d1,d2
    bcc.s    ganotba
    move.b    d1,d2

ganotba    move.b    (a2),d3
    cmp.b    d3,d4
    bcc.s    ganotbc
    move.b    d3,d4

ganotbc    move.b    (a3),d5
    cmp.b    d5,d6
    bcc.s    ganotbd
    move.b    d5,d6

ganotbd   
    dbf    d7,gatimbl

    move.b    d2,-9(a6)      * Timer A Data reg
    move.b    d4,-7(a6)      * Timer C Data reg.
    move.b    d6,-6(a6)    * Timer D Data reg.

* Screen Base:
    move.b    $FFFF8201.w,(a6)+   * High byte
    move.b    $FFFF8203.w,(a6)+   * Mid byte


*  IKBD status  will store  after  setting  TOS workable - in restoring it....




* so, may  jump to  TOS restore:

* Clear abort flag in game   !!!!
* If needed !   


* Above will be present in savegames too always !!!

    jmp    FreeMem













 
lowmsuv     *Supervisor mode needed for set some sysvars...

       
    move.l    $42E.w,d5   *Old Phystop
    move.l    #NewPhyst,$42E.w
   
* See is Memtop sysvar $8000 bytes below Phystop :
* By Falcon is usually $7E00 bytes below

    move.l    $436.w,d3
    move.l    d5,d4
    sub.l    d3,d4
    move.l    #$8000,d3
    sub.l    d4,d3    * add diff

    sub.l    #NewPhyst,d5    *Get diff.
    sub.l     d5,$436.w    *Correct Memtop sysvar

    sub.l    d3,$436.w    * By Falcon if....



*    Get os_end :

    move.l     $4F2.w,a1
    move.l      12(a1),a1   *seek until this addr
    lea      $800,a2     *from here seek


* Seek basepage value, followed by free RAM for... :

    move.l    basep(pc),d1
    move.l    memt(pc),d2
    sub.l    d1,d2   *free RAM for

bvseekl     cmp.l    (a2),d1
          bne.s    bvseendt

* if found test freeram value matching :

    cmp.l    4(a2),d2
    beq.s    bvgotit

bvseendt    addq.l    #2,a2
        cmp.l    a2,a1
    bgt.s    bvseekl

bvgotit   * decrease  free RAM value by diff. :

    sub.l     d5,4(a2)
* Dirty hack, but works !

    * By stoopid Falcon it is $200 bytes higher !!!!
*    cmp.b    #4,machin+3
*    bne.s    corr_2
    sub.l    d3,4(a2)


corr_2

* If no RAM for GX skip Signature writing :

*    tst.b    gxf
*    beq.s    fin_lowm


* Header build support  #1:
    move.l    $42E.w,a2
    move.l    #"PPGX",(a2)+
    move.l    #MainInb,(a2)
   
fin_lowm    rts

 
DeskRes    dc.w    0
basep    dc.l      0
memt    dc.l      $78000    *preset for case...
uspstor    dc.l    0



GamexCtrl     *Code for controlling game exit ....
* and return to Ddesktop
   * Must be PC relative !!





RamSwap     *This swaps  2 RAM halves

* Areas   are     8-$7FD00  and   $80008 - $FFD00
* If game uses RAM $7FD00-$7FFFF we need some
* space to store that 768 bytes .....   problem ???

    move.w    #$2700,sr  
   

* MFP restoring flow:

* disable all MFP interrups
* allow little time that CPU finish


* Clear IE registers
    clr.b    $FFFFFA07.w
    clr.b    $FFFFFA09.w
* Clear Pending  regs
    clr.b    $FFFFFA0B.w
    clr.b    $FFFFFA0D.w
*Clear  in Service regs :
    clr.b    $FFFFFA0F.w
    clr.b    $FFFFFA11.w


 

*Some little delay
* Until find not better solution ... ?
     move.l   #3984,d1
.del    subq.l    #1,d1
    bne.s   .del



* Swapping only  used Sys area, after it just copy left game area
* to top RAM !!!

* no need for swap, in fact .....

* First copy game up, then TOS down, then rest of game up
* 256KB max at once






ramswp    lea     8.w,a5
    lea    $80008,a6
    move.w    #5460,d0    

ramswl    
    movem.l      (a5)+,d1-d7/a0-a4   *48 bytes at once
     movem.l    d1-d7/a0-a4,(a6)   
    lea    48(a6),a6
     *48 bytes in one cycle

    tst.b    d0
    bne.s    ramsw_loop
 *Little fade/flash :
    move.w    $FFFF8240.w,d1
    addq.w    #1,d1
    cmp.w    #$0FFF,d1
    bcs.s    .colup
    clr.w    d1
.colup    move.w    d1,$FFFF8240.w

ramsw_loop    dbf    d0,ramswl

* game up to $3FFF8  copied

    lea    8.w,a6
    lea    DeskCopy,a5
swapln    move.w    #0,d0

.cod2    movem.l      (a5)+,d1-d7/a0-a4   *48 bytes at once
     movem.l    d1-d7/a0-a4,(a6)   
    lea    48(a6),a6
    dbf    d0,.cod2   


* Now only copy remaining of game in high RAM
    lea    $3FFF8,a5   *src
    lea    $BFFF8,a6   *dest

    move.w    #5445,d0      *for rest, to $7FD00 !
.cou    movem.l      (a5)+,d1-d7/a0-a4   *48 bytes at once
     movem.l    d1-d7/a0-a4,(a6)   
    lea    48(a6),a6
    dbf    d0,.cou   

* May be little overshot, so set locations min 24 bytes over !


   


* Now need to restore stack pointers, screen, MFP, PSG ....


*   relative pos,      what  in SysStor

*     0    USP
*      4    Desktop screen resolution at prg start !
*    6    SSP
*    10    Palette, 32 bytes
*    42    MFP state....



    lea    SysStor,a1
    move.l    (a1)+,a4
    move.l    a4,usp
    move.w    (a1)+,d7   *Resolution
    move.l    (a1)+,sp

*Set palette pointer Sysvar: 
    move.l    a1,$45A.w   *Colorptr - will set palette in first Vblank


* Here deal with MFP....


    lea    $FFFFFA01.w,a1
    lea    SysStor+mfpof,a2
    moveq    #23,d2   *24 registers
mfprl    move.b    (a2)+,(a1)
    addq.l    #2,a1
    dbf    d2,mfprl

    move.w    #$2300,sr



*Signal and silencing possible tone
    lea forvs(pc),a6
    lea $ffff8800.w,a0
    moveq #0,d0
sounl    move.b d0,(a0)
    move.b (a6)+,2(a0)
    addq.b #1,d0
    cmp.b #14,d0
    blt.s sounl



* Flush IKBD ACIA buffer - may be blocked
aciafl        btst    #0,$FFFFFC00.w
    beq.s    aciaempt
    tst.b     $FFFFFC02.w
    bra.s     aciafl
aciaempt     
 

* Here need IKBD mode test and store too !!!!!

* Now save IKBD status (mode set)
* Requesting mouse vertical mode:
* by other games it may be different !!!

* Prepare fetching code:
    lea    GameStat+ikbdof+AltRamPos,a4
*GameStap    lea    0,a4    *will be prepared
    lea    ikbstoc+2(pc),a2
    move.l    a4,(a2)

* Need to receive status packet:

       move.l    ikbdsysv(pc),a1
    lea    my_ikbds(pc),a2
    move.l    a2,(a1)


* Now for Mouse button eml. state:


* Prepare fetching code:
*    lea    GameStat+ikbdm_of+AltRamPos,a4
*GameStap2    lea    0,a4    *will be prepared
*    lea    ikbstoc+2(pc),a2
*    move.l    a4,(a2)

     pea  mousta(pc)   
    move.w  #0,-(sp)   *1 byte only to send
    move.w  #25,-(sp)
    trap  #14
    addq.l  #8,sp


*Some delay   * Or solve with counting receives.... 
     move.l   #6984,d1
.del2    subq.l    #1,d1
    bne.s   .del2


    cmp.b  #$00,1(a4)  * Normal value
    bne.s    go_mor3
    clr.b    (a4)

go_mor3
* Back org ikbdsys vector:
    move.l    ikbdsysv(pc),a1
    lea    orgikbds(pc),a2
    move.l    (a2),(a1)







*
    pea  ikbdres(pc)    *Back regular IKBD mode
    move.w  #1,-(sp)
    move.w  #25,-(sp)
    trap  #14
    addq.l  #8,sp


* Set screen
    move.w    d7,-(sp)
    pea     GameScrB
    pea    GameScrB
     move.w    #5,-(sp)
    trap    #14
    lea    12(sp),sp

* Write for sure :
    lea    NewPhyst,a2
    move.l    #"PPGX",(a2)+
    move.l    #MainInb,(a2)




ToDesktop    clr.w    -(sp)
    trap    #1    *Regular exit


* Reading 8-byte packet from IKBD:

my_ikbds
*    btst    #0,$FFFFFC00.w
*    beq.s    ikbdpac

    movem.l    a3-a4,-(sp)

    tst.b    $FFFFFC00.w
ikbstoc    lea    0,a4     *****

    lea    ikbstoc+2(pc),a3
    move.b     $FFFFFC02.w,(a4)+
    move.l    a4,(a3)
    movem.l    (sp)+,a3-a4
    rts    *Not rte !
   
*  It was last part of saving gamestate !





ikbdsysv    dc.l    0
orgikbds    dc.l    0
ikbdres      dc.b     $80,1
*joysta      dc.b     $90,0   
mousta      dc.b    $87,0

   even

forvs   *Sound pattern, simple
  dc.b 66,2
  dc.b 125,2,80,2
  dc.b 1 *Noise perlen -here not used
  dc.b %11111000 *Mixer control
  dc.b 16,16,16
  dc.b 0,22,0









 * Detecting HW, RAM
hwdet
 *Check TOS version - may be not built inm, but running in RAM !
       move.l    $4F2.w,d1
   *      clr.b    d1  *on round address always
       move.l    d1,a1
      move.b    2(a1),d0  *TOS ver major
      move.b    3(a1),d1  *TOS ver minor

* Writing TOS version for later outprint
    lea  machin(pc),a2
    move.b   d0,(a2)+   *TOS V
    move.b   d1,(a2)+   *TOS v
    move.b   29(a1),4(a2)   *Lang code

*Detecting RAM size, just by $42E

    move.l     $42E,d2
    swap     d2
    lsr.w    #3,d2   *shift so that 512KB will be 1
    move.b     d2,(a2)+



*If TOS is 4, skip next tests...

    cmp.b    #4,d0
    beq.s   isfalc
    cmp.b     #3,d0
    beq.s   istt


* Physical RAM size by MemCTRL sysvar, or by Chip read ...

    clr.l    d3
*Instead orgphystop look MMU control register shadow $424
    move.b     $424.w,d3
    move.l        d3,d2
    and.b         #1,d2
    move.l        d3,d1
    and.b         #4,d1
    lsr.b           #2,d1
    add.b         d1,d2  *512K multiplier - 1 or 2 or 0

    move.l         d3,d4
    and.b          #2,d4
    move.l        d3,d1
     and.b          #8,d1
    lsr.b            #2,d1
    add.b          d1,d4  *2M mult.  2 or 4 or 0
    lsr.b    #1,d4  *now 1 or 2

    clr.l    d3
    tst.b    d2
    beq.s    seem2
    move.l    #$40000,d3  *256KB
    lsl.l    d2,d3  *mult by 2 or 4 
 
seem2    clr.l    d2
    tst.b    d4
    beq.s    keepms
    move.l    #$100000,d2  *1MB
    lsl.l    d4,d2
    add.l    d2,d3

keepms    swap     d3
    lsr.w    #3,d3   *shift so that 512KB will be 1
    move.b     d3,4(a2)



*Detecting machine HW - is STE, MSTE ?


*Is MSTE ?
    move.l    sp,a3
    lea    buser1(pc),a1
    move.l    8.w,backorb-buser1+2(a1)
    move.l    a1,8.w
    move.b    $FFFF8E21.w,d1   *  read from HW reg
*Will do bus error if not Mega STE
    move.b   #3,(a2)+   *Code for MSTE

* d1  -  bit 0 = cache on/off   ,  bit 1 (?) = 8/16MHz   
     btst    #1,d1
    sne    (a2)
   

* After this may set 16MHz by need, or even back to 8...
    addq.l   #1,a2
    move.b  #$FF,$FFFF8E21.w
    st    (a2)
    bra.s    backorb
   
buser1    lea    buser2(pc),a1
    move.l    a1,8.w
    tst.b    $FFFF8924.w  *Microwire for STE detect
    move.b   #2,(a2)   *Code for STE
    bra.s    restosp

buser2    move.b    #1,(a2)

restosp    move.l  a3,sp
backorb    move.l    #0,8.w    *here comes original buserror vector
    rts

machin    dc.b  0,0,0,0,0,0,0,0   *TOS V Major, TOS v minor, RAM size, HW
    * MSTE clock at start,  MSTE clock set... Lang code

istt     move.b   #5,(a2)   *HW code
        rts

* Not Falcon compatible !
isfalc    move.b   #4,(a2)   *HW code
    rts



  

machipr  *Outprints machine parameters

    lea hwpos(pc),a0
    bsr  pmess
    lea mait(pc),a0
    bsr  pmess


    lea  machin+3(pc),a1
    cmp.b  #1,(a1)
    bne.s   isstem
    lea   hwst(pc),a0
    bra.s  hwoup

isstem    cmp.b  #2,(a1)
    bne.s   ismstem
    lea   hwste(pc),a0
    bra.s  hwoup

ismstem    cmp.b  #3,(a1)
    bne.s   isfalcm
    lea   hwmste(pc),a0
    bsr    pmess

    *Outprint CPU clock too if MSTE:
    lea  machin+4(pc),a1
    tst.b    (a1)
    bne.s   sho16   *if begin clock 16 then print 16 only
    addq.l   #1,a1
    tst.b   (a1)
    beq.s   sho8   *if begin and end is 8 show 8 only
* Show 8>16
    lea   hwm816m(pc),a0
    bra.s  hwoup
sho16    lea   hwm16m(pc),a0
    bra.s  hwoup
sho8    lea   hwm8m(pc),a0
    bra.s  hwoup


isfalcm    cmp.b  #4,(a1)
    bne.s   seetv
    lea   hwfalc(pc),a0

hwoup     bsr     pmess


seetv    *TOS version outprint

    lea tosvit(pc),a0
    bsr  pmess

    lea   tosvp+1(pc),a2
    lea  machin(pc),a1
    move.b  (a1)+,d0   *Major
    add.b #"0",d0
    move.b   d0,(a2)

    move.b  (a1),d1   *Minor
    cmp.b  #$62,d1    *is TOS 1.62 ?
    beq.s  t162s

    add.b  #"0",d1
    moveq #"0",d0
    bra.s   tosvpri

t162s    moveq #"6",d0
    moveq  #"2",d1

tosvpri    addq.l  #2,a2
    move.b  d0,(a2)+
    move.b  d1,(a2)
    lea   tosvp(pc),a0
    bsr  pmess

*TOS RAM size outprint
    lea ramit(pc),a0
    bsr  pmess   
   
    lea  machin+2(pc),a1
    cmp.b  #1,(a1)
    bne.s   not512
    lea   rams512(pc),a0
    bra.s  ramsoup

not512   *needs some calc...
    moveq   #0,d1
    move.b (a1),d1
    lsr.b #1,d1
    scs   d6   *Flag for half MB at end
        
    lea  ramsiu+1(pc),a1  *Some aligning...
    tst.b   d6
    beq.s   bratoa
    lea  ramsiu(pc),a1
bratoa    bsr  toasc

    tst.b  d6
    beq.s  ramsta
    move.b #".",(a1)+
    move.b #"5",(a1)
ramsta    lea  ramsiu(pc),a0

ramsoup  bsr.s  pmess

* ST RAM size outprint
    lea  machin+3(pc),a1
    cmp.b       #5,(a1)
    beq.s    end_hwpr
    cmp.b      #4,(a1)
    beq.s    end_hwpr

    lea ramst(pc),a0
    bsr  pmess   
   
    lea  machin+7(pc),a1
    cmp.b    #1,(a1)
    bne.s    not512rs
    lea         rams512(pc),a0
    bra.s     ramsouprs

not512rs   *needs some calc...
    moveq   #0,d1
    move.b (a1),d1
    lsr.b #1,d1
    scs   d6   *Flag for half MB at end
        
    lea       ramsiu+1(pc),a1  *Some aligning...
    tst.b     d6
    beq.s   bratoars
    lea       ramsiu(pc),a1
bratoars    bsr       toasc

    tst.b    d6
    beq.s  ramstars
    move.b #".",(a1)+
    move.b #"5",(a1)
ramstars    lea  ramsiu(pc),a0

ramsouprs  bsr.s  pmess




end_hwpr       
*    lea   noGXp(pc),a0
*    tst.b    gxf
*    beq.s    skip_gxki
    lea   gamext(pc),a0
skip_gxki         bsr  pmess

    rts


pmess      pea  (a0)
    move.w  #9,-(sp)
    trap   #1
    addq.l  #6,sp
    rts

toasc    *cover values from 1 to 14

    divu #10,d1
    move.b d1,d2
    swap  d1
    add.b #"0",d2   *10s of MB
    cmp.b #"0",d2
    bne.s   putdig1
    move.b #" ",d2
putdig1    move.b d2,(a1)+
    add.b #"0",d1   *1s of MB
    move.b d1,(a1)+

     rts


hwst dc.b  "   ST",0
hwste  dc.b "  STE",0
hwmste dc.b "Mega STE",0
hwfalc   dc.b " Falcon",0

hwm8m  dc.b 13,10," 8 MHz",0
hwm16m  dc.b 13,10," 16 MHz",0
hwm816m  dc.b 13,10,"8>16 MHz",0

tosvp  dc.b  " 1.00",0

rams512 dc.b " 512 KB",0     *  ,27,"H",0

ramsiu  dc.b  "    MB",0 

hwpos  dc.b   27,"E",27,"Y",48,32,0

homec  dc.b  27,"H",0   *Cursor back to top left


* Info texts:


mait  dc.b  "Machine: ",0
ramit  dc.b  13,10,"TOS RAM:",0
ramst  dc.b  ", ST RAM:",0
tosvit  dc.b  13,10,"TOS ver: ",0

gamext  dc.b   13,10,13,10,"GAMEX: key F9",27,"H",0



lowRamTM   dc.b  13,10,"Too much low RAM occupied !",0
RAMne   dc.b  13,10,"Min RAM: 1MB !",0
*noGXp    dc.b  13,10,13,10,"For Gamex min 1MB RAM !",27,"H",0
incoTM     dc.b  13,10,"Only ST or STE ! But any TOS.",0
  even


* Adding Mega STE machine settings as option :


megastes    *see machine

    lea    machin+3(pc),a2
    cmp.b    #3,(a2)
    beq.s    itsMSTE

*    cmp.b    #4,(a2)
*    beq    itsFalc

    bra    show_hw



itsMSTE
* Mega STE
 * Only setting 8/16MHz, together with cache off/on

    bsr    clearkb     * Clear ikbd buffer for sure

    lea    mstest(pc),a0
    bsr    pmess

    tst.b    machin+5   * Clock ?
    bne.s    its16m1
    lea    mste8mt(pc),a0   * Change txt on screen
    bsr    pmess
    clr.b    mstetems

its16m1    move.w    #7,-(sp)
    trap    #1
    addq.l    #2,sp

    cmp.b    #"1",d0
    beq.s    msteset8
    cmp.b    #"2",d0
    beq.s    msteset16

    cmp.b    #" ",d0
    beq.s    msteexit

    cmp.b    #13,d0
    beq.s    mstesetexit
    bra.s    its16m1

msteset8    lea    mste8mt(pc),a0   * Change txt on screen
    bsr    pmess
    moveq    #0,d1
mstecls    move.b    d1,mstetems   
    bra.s    its16m1

msteset16    lea    mste16mt(pc),a0   * Change txt on screen
    bsr    pmess
    st    d1
    bra.s    mstecls

mstesetexit   * We are in supervisor mode
    move.b    #$FC,d1
    tst.b    mstetems   
    beq.s    set8caoff
    move.b    #$FF,d1
set8caoff        move.b    d1,$FFFF8E21.w
    addq.b    #1,d1
    seq    machin+5

msteexit        bra    show_hw

mstetems        dc.b    255,0   *Must preset to on !


mstest     dc.b   27,"E","     Mega STE CPU clock setting",13,10
    dc.b  13,10,"Press:   1 for 8 MHz,   2 for 16 MHz",13,10
    dc.b  "Enter  for  set and exit",13,10
    dc.b   "Space exits without change",13,10

    dc.b   13,10,13,10,"CPU clock: 16 MHz",0

mste8mt    dc.b    27,"Y",39,43," 8",0       
mste16mt    dc.b    27,"Y",39,43,"16",0
      even
 

clearkb    pea    $10002   *Keyboard, Bconstat
    trap    #13
    addq.l    #4,sp
    tst.b    d0
    beq.s    nocha

    pea    $20002   *Keyboard, Bconin
    trap    #13
    addq.l    #4,sp
    bra.s    clearkb

nocha    rts


 



hwpal   *Palette with white 0 and all other as blue
   *because of medres/lowres switch bug

   dc.w   $666,$116,$116,$116,$116,$116,$116,$116
   dc.w   $116,$116,$116,$116,$116,$116,$116,$116

screnb  ds.l 1

picfn    dc.b    "STARGL.PCH",0
  even

* Not Falcon compatible dude !!!!
* falcpic   
*   include  "PCHTOF3.S"


photoc
  include  "PHOTUS.S"


 section data

 
  section  bss
head   ds.b  6   *PCH header here...
stbitm  ds.b  32000
stpal    ds.b  $4B20
stbm2    ds.b 32000
stpal2    ds.b  $4B20
convtbl  ds.b  8192