3DO ZONE Forums

The Only R.E.A.L. 3DO Experience.
It is currently Thu Mar 23, 2017 3:18 am

All times are UTC [ DST ]

Post new topic Reply to topic  [ 1 post ] 
Author Message
PostPosted: Sun Jun 21, 2015 5:01 pm 
Jaguar MOD
User avatar

Joined: Mon Apr 01, 2013 7:09 am
Posts: 816
VladR has been nice enough to share his working through the startup.s file. This for those who don't know this is the file (or one like it with the same name) that bootstraps the Jaguar every time a program is run.

First I will start with posting the actual startup.s code from 'Hello Jag users!

Thanks to VladR for this. Reprinted with permission.

   .include    "jaguar.inc"

; Begin STARTUP PICTURE CONFIGURATION -- Edit this to change startup picture

PPP        .equ    8               ; Pixels per Phrase (1-bit)
BMP_WIDTH      .equ    320            ; Width in Pixels
BMP_HEIGHT     .equ    200             ; Height in Pixels


; Globals
      .globl   gSetOLP
      .globl   olp2set
      .globl   ticks

      .globl  a_vdb
      .globl  a_vde
      .globl  a_hdb
      .globl  a_hde
      .globl  width
      .globl  height
                .globl  _vidmem
; Externals
      .extern   ___main
                .extern _SetPallete

BMP_PHRASES    .equ    (BMP_WIDTH/PPP)    ; Width in Phrases
BMP_LINES      .equ    (BMP_HEIGHT*2)     ; Height in Half Scanlines
BITMAP_OFF     .equ    (2*8)             ; Two Phrases
LISTSIZE       .equ    5             ; List length (in phrases)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Program Entry Point Follows...


      move.l  #$70007,G_END      ; big-endian mode
      move.l  #$70007,D_END
      move.w  #$FFFF,VI          ; disable video interrupts

      move.l  #INITSTACK,a7      ; Setup a stack
      jsr    InitVideo            ; Setup our video registers.
      jsr    InitLister           ; Initialize Object Display List
      jsr    InitVBint            ; Initialize our VBLANK routine

;;; Sneaky trick to cause display to popup at first VB

      move.l   #$0,listbuf+BITMAP_OFF
      move.l   #$C,listbuf+BITMAP_OFF+4

      move.l  d0,olp2set         ; D0 is swapped OLP from InitLister
      move.l  #gSetOLP,G_PC      ; Set GPU PC
      move.l  #RISCGO,G_CTRL     ; Go!
      move.l  G_CTRL,d0         ; Wait for write.
      andi.l  #$1,d0
      bne    waitforset

      move.w  #$6C7,VMODE        ; Configure Video

       jmp    ___main         ; Jump to main code

; Procedure: gSetOLP
;            Use the GPU to set the OLP and quit.
;    Inputs: olp2set - Variable contains pre-swapped value to stuff OLP with.
; NOTE!!!: This code can run in DRAM only because it contains no JUMP's or
;          JR's. It will generate a warning with current versions of MADMAC
;          because it doesn't '.ORG'.
      movei   #olp2set,r0         ; Read value to write
      load    (r0),r1

      movei   #OLP,r0             ; Store it
      store   r1,(r0)

      moveq   #0,r0               ; Stop GPU
      movei   #G_CTRL,r1
      store   r0,(r1)
      nop                   ; Two "feet" on the brake pedal


olp2set:       .ds.l   1                 ; GPU Code Parameter


; Procedure: InitVBint
; Install our vertical blank handler and enable interrupts

      move.l  d0,-(sp)

      move.l  #UpdateList,LEVEL0   ; Install 68K LEVEL0 handler

      move.w  a_vde,d0           ; Must be ODD
      ori.w   #1,d0
      move.w  d0,VI

      move.w  #C_VIDENA,INT1            ; Enable video interrupts

      move.w  sr,d0
      and.w   #$F8FF,d0          ; Lower 68k IPL to allow
      move.w  d0,sr              ; interrupts

      move.l  (sp)+,d0
; Procedure: InitVideo (same as in vidinit.s)
;            Build values for hdb, hde, vdb, and vde and store them.
      movem.l d0-d6,-(sp)
      move.w  CONFIG,d0             ; Also is joystick register
      andi.w  #VIDTYPE,d0           ; 0 = PAL, 1 = NTSC
      beq    palvals

      move.w  #NTSC_HMID,d2
      move.w  #NTSC_WIDTH,d0

      move.w  #NTSC_VMID,d6
      move.w  #NTSC_HEIGHT,d4

      bra    calc_vals
      move.w  #PAL_HMID,d2
      move.w  #PAL_WIDTH,d0

      move.w  #PAL_VMID,d6
      move.w  #PAL_HEIGHT,d4

      move.w  d0,width
      move.w  d4,height

      move.w  d0,d1
      asr    #1,d1                ; Width/2

      sub.w   d1,d2                 ; Mid - Width/2
      add.w   #4,d2                 ; (Mid - Width/2)+4

      sub.w   #1,d1                 ; Width/2 - 1
      ori.w   #$400,d1              ; (Width/2 - 1)|$400
      move.w  d1,a_hde
      move.w  d1,HDE

      move.w  d2,a_hdb
      move.w  d2,HDB1
      move.w  d2,HDB2

      move.w  d6,d5
      sub.w   d4,d5
      move.w  d5,a_vdb

      add.w   d4,d6
      move.w  d6,a_vde
      move.w  a_vdb,VDB
      move.w  #$FFFF,VDE
      move.l  #0,BORD1           ; Black border
      move.w  #0,BG              ; Init line buffer to black
      movem.l (sp)+,d0-d6

; InitLister: Initialize Object List Processor List
;    Returns: Pre-word-swapped address of current object list in d0.l
;  Registers: d0.l/d1.l - Phrase being built
;             d2.l/d3.l - Link address overlays
;             d4.l      - Work register
;             a0.l      - Roving object list pointer
      movem.l d1-d4/a0,-(sp)      ; Save registers
      lea     listbuf,a0
      move.l  a0,d2              ; Copy

      add.l   #(LISTSIZE-1)*8,d2     ; Address of STOP object
      move.l   d2,d3         ; Copy for low half

      lsr.l   #8,d2         ; Shift high half into place
      lsr.l   #3,d2
      swap   d3         ; Place low half correctly
      clr.w   d3
      lsl.l   #5,d3

; Write first BRANCH object (branch if YPOS > a_vde )

      clr.l   d0
      move.l  #(BRANCHOBJ|O_BRLT),d1  ; $4000 = VC < YPOS
      or.l   d2,d0         ; Do LINK overlay
      or.l   d3,d1
      move.w  a_vde,d4                ; for YPOS
      lsl.w   #3,d4                   ; Make it bits 13-3
      or.w    d4,d1

      move.l   d0,(a0)+
      move.l   d1,(a0)+

; Write second branch object (branch if YPOS < a_vdb)
; Note: LINK address is the same so preserve it

      andi.l  #$FF000007,d1           ; Mask off CC and YPOS
      ori.l   #O_BRGT,d1         ; $8000 = VC > YPOS
      move.w  a_vdb,d4                ; for YPOS
      lsl.w   #3,d4                   ; Make it bits 13-3
      or.w    d4,d1

      move.l   d0,(a0)+
      move.l   d1,(a0)+

; Write a standard BITMAP object
      move.l   d2,d0
      move.l   d3,d1

      ori.l  #BMP_HEIGHT<<14,d1       ; Height of image

      move.w  height,d4              ; Center bitmap vertically
      sub.w   #BMP_HEIGHT,d4
      add.w   a_vdb,d4
      andi.w  #$FFFE,d4               ; Must be even
      lsl.w   #3,d4
      or.w    d4,d1                   ; Stuff YPOS in low phrase

      move.l   #_vidmem,d4
      lsl.l   #8,d4
      or.l   d4,d0

      move.l   d0,(a0)+
      move.l   d1,(a0)+
      movem.l   d0-d1,bmpupdate

; Second Phrase of Bitmap
      move.l   #BMP_PHRASES>>4,d0   ; Only part of top LONG is IWIDTH
      move.l  #O_DEPTH8|O_NOGAP,d1   ; Bit Depth = 16-bit, Contiguous data

      move.w  width,d4               ; Get width in clocks
      lsr.w   #2,d4                  ; /4 Pixel Divisor
      sub.w   #BMP_WIDTH,d4
      lsr.w   #1,d4
      or.w    d4,d1

      ori.l   #(BMP_PHRASES<<18)|(BMP_PHRASES<<28),d1   ; DWIDTH|IWIDTH

      move.l   d0,(a0)+
      move.l   d1,(a0)+

; Write a STOP object at end of list
      clr.l   (a0)+
      move.l  #(STOPOBJ|O_STOPINTS),(a0)+

; Now return swapped list pointer in D0

      move.l  #listbuf,d0
      swap    d0

      movem.l (sp)+,d1-d4/a0

; Procedure: UpdateList
;        Handle Video Interrupt and update object list fields
;        destroyed by the object processor.

      move.l  a0,-(sp)

      move.l  #listbuf+BITMAP_OFF,a0

      move.l  bmpupdate,(a0)         ; Phrase = d1.l/d0.l
      move.l  bmpupdate+4,4(a0)

      add.l   #1,ticks      ; Increment ticks semaphore

      move.w  #$101,INT1         ; Signal we're done
      move.w  #$0,INT2

      move.l  (sp)+,a0




listbuf:       .ds.l   LISTSIZE*2        ; Object List
bmpupdate:     .ds.l   2             ; One Phrase of Bitmap for Refresh
ticks:      .ds.l   1         ; Incrementing # of ticks
a_hdb:     .ds.w   1
a_hde:         .ds.w   1
a_vdb:         .ds.w   1
a_vde:         .ds.w   1
width:         .ds.w   1
height:        .ds.w   1
                .ds.b   64000

VladR wrote:
I spent some time in Assembler, going over the initialization of the video mode and object processor in file startup.s.

I finally forced myself to crosscheck the docs against several of the registers used in initialization of the video mode, as I mentioned last week that I'd like to do some experiments with the CRY mode (soon-ish), which required breaking down some constants (hence postponing for later).

In the statup.s, in the section waitforoffset, there is this line:
      move.w  #$6C7,VMODE        ; Configure Video:

That is not helpful. At all.

VMODE is register F00028 (described in detail in docs page 12)

The value $6C7 (hex) is 0000 0110 1100 0111 (binary)
Checking against JAGUAR.H, the above value can be rewritten as:

Now that is infinitely mode readable as $6C7. Here's the description copied from the docs:
bit 0: VIDEN: Enable Video Interrupts
bit 6: CSYNC: Enables composite sync on the vertical sync output
bit 7: BGEN: Clears the line buffer to the colour in the background register after displaying the contents. This only has effect in CRY and RGB16 modes
bits 1-3: MODE = 3 RGB16: 16-bit RGB. Each 32-bit entry in the line buffer is treated as two 16-bit RGB pixels
bits 9-11: PWIDTH =3 PWIDTH4: This field determines the width of pixels in video clock cycles. The width is one more than the value in this field.

Of interest are the bits for MODE and PWIDTH. Checking JAGUAR.H reveals the following for MODE:
#define CRY16      0x0000      /* 16-bit CRY mode */
#define RGB24      0x0002      /* 24-bit RGB mode */
#define DIRECT16   0x0004      /* 16-bit Direct mode */
#define RGB16      0x0006      /* 16-bit RGB mode */

Changing RGB16 to CRY16 should change the video mode to CRY. Changing it to RGB24 should change it to 24-bit.

I suspect the OP would have to be instructed to use O_DEPTH16 instead of O_DEPTH8 (and maybe a pitch would have to be adjusted too) in its second phrase - but I'll leave that exercise for later, when I'll play with CRY mode, as I will for sure have to reread the section on Object processor's bitmap definitions.

Now, let's get back to bits of PWIDTH:
#define PWIDTH1   0x0000      /* Pixel Dividers */
#define PWIDTH2   0x0200
#define PWIDTH3   0x0400
#define PWIDTH4   0x0600
#define PWIDTH5   0x0800
#define PWIDTH6   0x0A00
#define PWIDTH7   0x0C00
#define PWIDTH8   0x0E00 

From docs:
PWIDTH: This field determines the width of pixels in video clock cycles. The width is one more than the value in this field.

So, this is where the actual horizontal resolution is being set. This must be sync'ed with the contents of the second phrase for OP:
      move.w  width,d4               ; Get width in clocks
      lsr.w   #2,d4         ; /4 Pixel Divisor

Backtracking the ASM code few pages above reveals that width = NTSC_WIDTH, which according to JAGUAR.H is 1409.

Hence the code above can be rewritten as equation: d4 = NTSC_WIDTH / (2 ^ 2) = 1409 / 4 = 352

As vertical resolutions are only few and between (240p vs 480i), the default startup.s creates the resolution 352x240.

Experimenting with different values for the divisor should result in different horizontal resolutions. This could be a useful feature for VRBasic.

What came after the Jaguar was the PS1 which for all it's greatness, ushered in corporate development and with it the bleached, repetitive, bland titles which for the most part we're still playing today. - David Wightman

Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 1 post ] 

All times are UTC [ DST ]

Who is online

Users browsing this forum: No registered users and 1 guest

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group