diff --git a/src/Actions.s b/src/Actions.s index ddc25d0..881dabe 100644 --- a/src/Actions.s +++ b/src/Actions.s @@ -7,7 +7,7 @@ MoveLeft lsr jsr SetBG1XPos - jsr Render + jsr _Render rts MoveRight @@ -23,7 +23,7 @@ MoveRight lsr jsr SetBG1XPos - jsr Render + jsr _Render pla rts @@ -46,7 +46,7 @@ MoveUp ; lsr ; jsr SetBG1YPos - jsr Render + jsr _Render rts MoveDown @@ -62,7 +62,7 @@ MoveDown ; lsr ; jsr SetBG1YPos - jsr Render + jsr _Render pla rts @@ -108,7 +108,7 @@ Demo ; jsr MoveLeft jsr UpdateBG1Rotation ; jsr DoColorCycle - jsr Render + jsr _Render inc frameCount @@ -190,7 +190,7 @@ AngleUp sbc #64 sta angle jsr _ApplyAngle - jsr Render + jsr _Render rts AngleDown @@ -201,7 +201,7 @@ AngleDown adc #64 sta angle jsr _ApplyAngle - jsr Render + jsr _Render rts angle dw 0 @@ -295,3 +295,4 @@ _DoTimers + diff --git a/src/App.Init.s b/src/App.Init.s index ea48faf..7916434 100644 --- a/src/App.Init.s +++ b/src/App.Init.s @@ -16,7 +16,7 @@ mx %00 -MemInit PushLong #0 ; space for result +InitMemory PushLong #0 ; space for result PushLong #$008000 ; size (32k) PushWord UserId PushWord #%11000000_00010111 ; Fixed location @@ -123,7 +123,7 @@ AllocOneBank PushLong #0 :bank ldal $000001,X ; recover the bank address in A=XX/00 rts -; Variation that return pointer in the X/A registers (X = low, A = high) +; Variation that returns the pointer in the X/A registers (X = low, A = high) AllocOneBank2 PushLong #0 PushLong #$10000 PushWord UserId @@ -134,75 +134,3 @@ AllocOneBank2 PushLong #0 pla ; high address 00XX of the new handle (bank) _Deref rts - -; Set up the interrupts -; -; oldOneVect = GetVector( oneSecHnd ); -; SetVector( oneSecHnd, (Pointer) ONEHANDLER ); -; IntSource( oSecEnable ); -; SetHeartBeat( VBLTASK ); -IntInit rts - - -; IntSource( oSecDisable ); /* disable one second interrupts */ -; SetVector( oneSecHnd, oldOneVect ); /* reset to the old handler */ -ShutDown rts - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/App.Main.s b/src/App.Main.s index ff807db..be8e942 100644 --- a/src/App.Main.s +++ b/src/App.Main.s @@ -1,669 +1,510 @@ ; Test driver to exercise graphics routines. -; -; The general organization of the code is -; -; 1. The blitter/ folder contains all of the low-level graphics primitives -; 2. The blitter/DirectPage.s file defines all of the DP locations -; 3. Subroutines are written to try and be stateless, but, if local -; storage is needed, it is takes from the stack and uses stack-relative -; addressing. -; Allow dynamic resizing to benchmark against different games - REL - DSK MAINSEG + REL + DSK MAINSEG - use Util.Macs.s - use Locator.Macs.s - use Mem.Macs.s - use Misc.Macs.s - put ..\macros\App.Macs.s - put ..\macros\EDS.GSOS.MACS.s - put ..\macros\Tool222.MACS.s - put .\blitter\DirectPage.s + use EDS.GSOS.MACS.s + put ./GTE.s - mx %00 - -SHADOW_REG equ $E0C035 -STATE_REG equ $E0C068 -NEW_VIDEO_REG equ $E0C029 -BORDER_REG equ $E0C034 ; 0-3 = border, 4-7 Text color -VBL_VERT_REG equ $E0C02E -VBL_HORZ_REG equ $E0C02F - -KBD_REG equ $E0C000 -KBD_STROBE_REG equ $E0C010 -VBL_STATE_REG equ $E0C019 -MOD_REG equ $E0C025 -COMMAND_KEY_REG equ $E0C061 -OPTION_KEY_REG equ $E0C062 - -SHADOW_SCREEN equ $012000 -SHR_SCREEN equ $E12000 -SHR_SCB equ $E19D00 -SHR_PALETTES equ $E19E00 + mx %00 ; External references -tiledata ext +tiledata ext ; Feature flags -NO_INTERRUPTS equ 1 ; turn off for crossrunner debugging -NO_MUSIC equ 1 ; turn music + tool loading off +NO_INTERRUPTS equ 1 ; turn off for crossrunner debugging +NO_MUSIC equ 1 ; turn music + tool loading off ; Typical init - phk - plb + phk + plb -; Tool startup + jsl EngineStartUp - _TLStartUp ; normal tool initialization - pha - _MMStartUp - _Err ; should never happen - pla - sta MasterId ; our master handle references the memory allocated to us - ora #$0100 ; set auxID = $01 (valid values $01-0f) - sta UserId ; any memory we request must use our own id + ldx #0 + jsl SetScreenMode - _MTStartUp + jsr _InitBG1 ; Initialize the second background -; Use Tool222 (NinjaTrackerPlus) for music playback - - lda #NO_MUSIC - bne :no_music - - pea $00DE - pea $0000 - _LoadOneTool - _Err - - lda UserId - pha - _NTPStartUp - - pea #^MusicFile - pea #MusicFile - _NTPLoadOneMusic - - pea $0001 ; loop - _NTPPlayMusic -:no_music - -; Install interrupt handlers. We use the VBL interrupt to keep animations -; moving at a consistent rate, regarless of the rendered frame rate. The -; one-second timer is generally just used for counters and as a handy -; frames-per-second trigger. - - lda #NO_INTERRUPTS - bne :no_interrupts - PushLong #0 - pea $0015 ; Get the existing 1-second interrupt handler and save - _GetVector - PullLong OldOneSecVec - - pea $0015 ; Set the new handler and enable interrupts - PushLong #OneSecHandler - _SetVector - - pea $0006 - _IntSource - - PushLong #VBLTASK ; Also register a Heart Beat Task - _SetHeartBeat -:no_interrupts - -; Start up the graphics engine... - - jsr MemInit ; Allocate memory - jsr BlitInit ; Initialize the memory - jsr GrafInit ; Initialize the graphics screen - - ldx #0 ; - jsr SetScreenMode - - jsr _InitBG1 ; Initialize the second background - - lda #0 - jsr _ClearBG1Buffer + lda #0 + jsr _ClearBG1Buffer ; Set up our level data - jsr BG0SetUp - jsr BG1SetUp + jsr BG0SetUp + jsr BG1SetUp ; Allocate room to load data - jsr AllocOneBank2 ; Alloc 64KB for Load/Unpack - sta BankLoad ; Store "Bank Pointer" + jsr AllocOneBank2 ; Alloc 64KB for Load/Unpack + sta BankLoad ; Store "Bank Pointer" - jsr MovePlayerToOrigin ; Put the player at the beginning of the map + jsr MovePlayerToOrigin ; Put the player at the beginning of the map - lda #DIRTY_BIT_BG0_REFRESH ; Redraw all of the tiles on the next Render - ora #DIRTY_BIT_BG1_REFRESH - tsb DirtyBits + lda #DIRTY_BIT_BG0_REFRESH ; Redraw all of the tiles on the next Render + ora #DIRTY_BIT_BG1_REFRESH + tsb DirtyBits -; jsr DoTiles -; jsr DoLoadBG1 -; jsr Demo - jsr Render + jsl Render EvtLoop - jsr ReadControl - and #$007F ; Ignore the buttons for now + jsl ReadControl + and #$007F ; Ignore the buttons for now - cmp #'q' - bne :1 - brl Exit + cmp #'q' + bne :1 + brl Exit -:1 cmp #'l' - bne :1_1 - jsr DoLoadFG - bra EvtLoop +:1 cmp #'l' + bne :1_1 + jsr DoLoadFG + bra EvtLoop -:1_1 cmp #'b' - bne :2 - jsr DoLoadBG1 - bra EvtLoop +:1_1 cmp #'b' + bne :2 + jsr DoLoadBG1 + bra EvtLoop -:2 cmp #'m' - bne :3 - jsr DumpBanks - bra EvtLoop +:2 cmp #'m' + bne :3 + jsr DumpBanks + bra EvtLoop -:3 cmp #'f' ; render a 'f'rame - bne :4 - jsr Render - bra EvtLoop +:3 cmp #'f' ; render a 'f'rame + bne :4 + jsl Render + bra EvtLoop -:4 cmp #'h' ; Show the 'h'eads up display - bne :5 - jsr DoHUP - bra EvtLoop +:4 cmp #'h' ; Show the 'h'eads up display + bne :5 + jsr DoHUP + bra EvtLoop -:5 cmp #'1' ; User selects a new screen size - bcc :6 - cmp #'9'+1 - bcs :6 - sec - sbc #'1' - tax - jsr SetScreenMode - jsr MovePlayerToOrigin - brl EvtLoop +:5 cmp #'1' ; User selects a new screen size + bcc :6 + cmp #'9'+1 + bcs :6 + sec + sbc #'1' + tax + jsr SetScreenMode + jsr MovePlayerToOrigin + brl EvtLoop -:6 cmp #'t' - bne :7 - jsr DoTiles - brl EvtLoop +:6 cmp #'t' + bne :7 + jsr DoTiles + brl EvtLoop -:7 cmp #$15 ; left = $08, right = $15, up = $0B, down = $0A - bne :8 - lda #1 - jsr MoveRight - brl EvtLoop +:7 cmp #$15 ; left = $08, right = $15, up = $0B, down = $0A + bne :8 + lda #1 + jsr MoveRight + brl EvtLoop -:8 cmp #$08 - bne :9 - lda #1 - jsr MoveLeft - brl EvtLoop +:8 cmp #$08 + bne :9 + lda #1 + jsr MoveLeft + brl EvtLoop -:9 cmp #$0B - bne :10 - lda #1 - jsr MoveUp - brl EvtLoop +:9 cmp #$0B + bne :10 + lda #1 + jsr MoveUp + brl EvtLoop -:10 cmp #$0A - bne :11 - lda #1 - jsr MoveDown - brl EvtLoop +:10 cmp #$0A + bne :11 + lda #1 + jsr MoveDown + brl EvtLoop -:11 cmp #'d' - bne :12 - lda #1 - jsr Demo - brl EvtLoop +:11 cmp #'d' + bne :12 + lda #1 + jsr Demo + brl EvtLoop -:12 cmp #'z' - bne :13 - jsr AngleUp - brl EvtLoop +:12 cmp #'z' + bne :13 + jsr AngleUp + brl EvtLoop -:13 cmp #'x' - bne :14 - jsr AngleDown - brl EvtLoop +:13 cmp #'x' + bne :14 + jsr AngleDown + brl EvtLoop -:14 brl EvtLoop +:14 brl EvtLoop ; Exit code Exit - lda #NO_INTERRUPTS - bne :no_interrupts + jsl EngineShutDown - pea $0007 ; disable 1-second interrupts - _IntSource + _QuitGS qtRec - PushLong #VBLTASK ; Remove our heartbeat task - _DelHeartBeat + bcs Fatal +Fatal brk $00 - pea $0015 - PushLong OldOneSecVec ; Reset the interrupt vector - _SetVector -:no_interrupts +StartMusic + pea #^MusicFile + pea #MusicFile + _NTPLoadOneMusic - lda #NO_MUSIC - bne :no_music - _NTPShutDown -:no_music - - PushWord UserId ; Deallocate all of our memory - _DisposeAll - - _QuitGS qtRec - - bcs Fatal -Fatal brk $00 + pea $0001 ; loop + _NTPPlayMusic + rts ; Position the screen with the botom-left corner of the tilemap visible MovePlayerToOrigin - lda #0 ; Set the player's position - jsr SetBG0XPos - lda #0 - jsr SetBG1XPos + lda #0 ; Set the player's position + jsr SetBG0XPos + lda #0 + jsr SetBG1XPos - lda TileMapHeight - asl - asl - asl - sec - sbc ScreenHeight - pha - jsr SetBG0YPos - pla - jsr SetBG1YPos + lda TileMapHeight + asl + asl + asl + sec + sbc ScreenHeight + pha + jsr SetBG0YPos + pla + jsr SetBG1YPos - rts + rts ClearBankLoad - lda BankLoad - phb - pha - plb - ldx #$FFFE -:lp sta: $0000,x - dex - dex - cpx #0 - bne :lp - plb - plb - rts + lda BankLoad + phb + pha + plb + ldx #$FFFE +:lp sta: $0000,x + dex + dex + cpx #0 + bne :lp + plb + plb + rts -; Allow the user to dynamically select one of the pre-configured screen sizes -; -; 1. Full Screen : 40 x 25 320 x 200 (32,000 bytes (100.0%)) -; 2. Sword of Sodan : 34 x 24 272 x 192 (26,112 bytes ( 81.6%)) -; 3. ~NES : 32 x 25 256 x 200 (25,600 bytes ( 80.0%)) -; 4. Task Force : 32 x 22 256 x 176 (22,528 bytes ( 70.4%)) -; 5. Defender of the World : 35 x 20 280 x 160 (22,400 bytes ( 70.0%)) -; 6. Rastan : 32 x 20 256 x 160 (20,480 bytes ( 64.0%)) -; 7. Game Boy Advanced : 30 x 20 240 x 160 (19,200 bytes ( 60.0%)) -; 8. Ancient Land of Y's : 36 x 16 288 x 128 (18,432 bytes ( 57.6%)) -; 9. Game Boy Color : 20 x 18 160 x 144 (11,520 bytes ( 36.0%)) -; 10. DEBUG : 40 x 1 320 x 1 -; X=mode number - -]ScreenModeWidth dw 320,272,256,256,280,256,240,288,160,320 -]ScreenModeHeight dw 200,192,200,176,160,160,160,128,144,1 - -SetScreenMode cpx #9 - bcc :rangeOk - ldx #9 - -:rangeOk txa - asl - tax - - lda #320 ; Calculate the screen offset - sec - sbc: ]ScreenModeWidth,x - lsr - lsr - xba - pha - - lda #200 - sec - sbc: ]ScreenModeHeight,x - lsr - ora 1,s - sta 1,s - - ldy: ]ScreenModeHeight,x - lda: ]ScreenModeWidth,x - lsr - tax - pla - jsr SetScreenRect - jsr FillScreen - rts - -SecondsStr str 'SECONDS' -TicksStr str 'TICKS' +SecondsStr str 'SECONDS' +TicksStr str 'TICKS' ; Print a bunch of messages on screen DoHUP - lda #SecondsStr - ldx #{160-12*4} - ldy #$7777 - jsr DrawString - lda OneSecondCounter ; Number of elapsed seconds - ldx #{160-4*4} ; Render the word 4 charaters from right edge - jsr DrawWord + lda #SecondsStr + ldx #{160-12*4} + ldy #$7777 + jsr DrawString + lda OneSecondCounter ; Number of elapsed seconds + ldx #{160-4*4} ; Render the word 4 charaters from right edge + jsr DrawWord - lda #TicksStr - ldx #{8*160+160-12*4} - ldy #$7777 - jsr DrawString - PushLong #0 - _GetTick - pla - plx - ldx #{8*160+160-4*4} - jsr DrawWord - rts + lda #TicksStr + ldx #{8*160+160-12*4} + ldy #$7777 + jsr DrawString + PushLong #0 + _GetTick + pla + plx + ldx #{8*160+160-4*4} + jsr DrawWord + rts ; Fill up the virtual buffer with tile data DoTiles -:row equ 1 -:column equ 3 -:tile equ 5 +:row equ 1 +:column equ 3 +:tile equ 5 - pea $0000 ; Allocate local variable space - pea $0000 - pea $0000 + pea $0000 ; Allocate local variable space + pea $0000 + pea $0000 :rowloop - lda #0 - sta :column,s - lda #$0010 - sta :tile,s + lda #0 + sta :column,s + lda #$0010 + sta :tile,s :colloop - lda :row,s - tay - lda :column,s - tax - lda :tile,s - jsr CopyTile + lda :row,s + tay + lda :column,s + tax + lda :tile,s + jsr CopyTile - lda :column,s - inc - sta :column,s - cmp #41 - bcc :colloop + lda :column,s + inc + sta :column,s + cmp #41 + bcc :colloop - lda :row,s - inc - sta :row,s - cmp #26 - bcc :rowloop + lda :row,s + inc + sta :row,s + cmp #26 + bcc :rowloop - pla ; restore the stack - pla - pla - rts + pla ; restore the stack + pla + pla + rts ; Load a binary file in the BG1 buffer DoLoadBG1 - lda BankLoad - ldx #BG1DataFile - jsr LoadFile + lda BankLoad + ldx #BG1DataFile + jsr LoadFile - ldx BankLoad - lda #0 - ldy BG1DataBank - jsr CopyBinToBG1 + ldx BankLoad + lda #0 + ldy BG1DataBank + jsr CopyBinToBG1 - lda BankLoad - ldx #BG1AltDataFile - jsr LoadFile + lda BankLoad + ldx #BG1AltDataFile + jsr LoadFile - ldx BankLoad - lda #0 - ldy BG1AltBank - jsr CopyBinToBG1 + ldx BankLoad + lda #0 + ldy BG1AltBank + jsr CopyBinToBG1 - rts + rts ; Load a raw pixture into the code buffer DoLoadFG - lda BankLoad - ldx #FGName - jsr LoadFile + lda BankLoad + ldx #FGName + jsr LoadFile - ldx BankLoad ; Copy it into the code field - lda #0 - jsr CopyBinToField - rts + ldx BankLoad ; Copy it into the code field + lda #0 + jsr CopyBinToField + rts ; Load a simple picture format onto the SHR screen DoLoadPic - lda BankLoad - ldx #ImageName ; Load+Unpack Boot Picture - jsr LoadPicture ; X=Name, A=Bank to use for loading + lda BankLoad + ldx #ImageName ; Load+Unpack Boot Picture + jsr LoadPicture ; X=Name, A=Bank to use for loading - ldx BankLoad ; Copy it into the code field - lda #0 - jsr CopyPicToField - rts + ldx BankLoad ; Copy it into the code field + lda #0 + jsr CopyPicToField + rts ; Copy a raw data file into the code field ; ; A=low word of picture address ; X=high word of pixture address CopyBinToField -:srcptr equ tmp0 -:line_cnt equ tmp2 -:dstptr equ tmp3 -:col_cnt equ tmp5 -:mask equ tmp6 -:data equ tmp7 -:mask_color equ tmp8 +:srcptr equ tmp0 +:line_cnt equ tmp2 +:dstptr equ tmp3 +:col_cnt equ tmp5 +:mask equ tmp6 +:data equ tmp7 +:mask_color equ tmp8 - sta :srcptr - stx :srcptr+2 + sta :srcptr + stx :srcptr+2 ; Check that this is a GTERAW image and save the transparent color - ldy #4 + ldy #4 :chkloop - lda [:srcptr],y - cmp :headerStr,y - beq *+3 - rts - dey - dey - bpl :chkloop + lda [:srcptr],y + cmp :headerStr,y + beq *+3 + rts + dey + dey + bpl :chkloop ; We have a valid header, now get the transparency word and load it in - ldy #6 - lda [:srcptr],y - sta :mask_color + ldy #6 + lda [:srcptr],y + sta :mask_color ; Advance over the header - lda :srcptr - clc - adc #8 - sta :srcptr + lda :srcptr + clc + adc #8 + sta :srcptr - stz :line_cnt + stz :line_cnt :rloop - lda :line_cnt ; get the pointer to the code field line - asl - tax + lda :line_cnt ; get the pointer to the code field line + asl + tax - lda BTableLow,x - sta :dstptr - lda BTableHigh,x - sta :dstptr+2 + lda BTableLow,x + sta :dstptr + lda BTableHigh,x + sta :dstptr+2 ; ldx #162 ; move backwards in the code field - ldy #0 ; move forward in the image data + ldy #0 ; move forward in the image data - lda #82 ; keep a running column count - sta :col_cnt + lda #82 ; keep a running column count + sta :col_cnt :cloop - phy - lda [:srcptr],y ; load the picture data - cmp :mask_color - beq :transparent ; a value of $0000 is transparent + phy + lda [:srcptr],y ; load the picture data + cmp :mask_color + beq :transparent ; a value of $0000 is transparent - jsr :toMask ; Infer a mask value for this. If it's $0000, then - cmp #$0000 - bne :mixed ; the data is solid, otherwise mixed + jsr :toMask ; Infer a mask value for this. If it's $0000, then + cmp #$0000 + bne :mixed ; the data is solid, otherwise mixed ; This is a solid word :solid - lda [:srcptr],y - pha ; Save the data + lda [:srcptr],y + pha ; Save the data - lda Col2CodeOffset,y ; Get the offset to the code from the line start - tay + lda Col2CodeOffset,y ; Get the offset to the code from the line start + tay - lda #$00F4 ; PEA instruction - sta [:dstptr],y - iny - pla - sta [:dstptr],y ; PEA operand - bra :next + lda #$00F4 ; PEA instruction + sta [:dstptr],y + iny + pla + sta [:dstptr],y ; PEA operand + bra :next :transparent - lda :mask_color ; Make sure we actually have to mask - cmp #$A5A5 - beq :solid + lda :mask_color ; Make sure we actually have to mask + cmp #$A5A5 + beq :solid - lda Col2CodeOffset,y ; Get the offset to the code from the line start - tay - lda #$B1 ; LDA (dp),y - sta [:dstptr],y - iny - lda 1,s ; load the saved Y-index - ora #$4800 ; put a PHA after the offset - sta [:dstptr],y - bra :next + lda Col2CodeOffset,y ; Get the offset to the code from the line start + tay + lda #$B1 ; LDA (dp),y + sta [:dstptr],y + iny + lda 1,s ; load the saved Y-index + ora #$4800 ; put a PHA after the offset + sta [:dstptr],y + bra :next :mixed - sta :mask ; Save the mask - lda [:srcptr],y ; Refetch the screen data - sta :data + sta :mask ; Save the mask + lda [:srcptr],y ; Refetch the screen data + sta :data - tyx - lda Col2CodeOffset,y ; Get the offset into the code field - tay - lda #$4C ; JMP exception - sta [:dstptr],y - iny + tyx + lda Col2CodeOffset,y ; Get the offset into the code field + tay + lda #$4C ; JMP exception + sta [:dstptr],y + iny - lda JTableOffset,x ; Get the address offset and add to the base address - clc - adc :dstptr - sta [:dstptr],y + lda JTableOffset,x ; Get the address offset and add to the base address + clc + adc :dstptr + sta [:dstptr],y - ldy JTableOffset,x ; This points to the code fragment - lda 1,s ; load the offset - xba - ora #$00B1 - sta [:dstptr],y ; write the LDA (--),y instruction - iny - iny - iny ; advance to the AND #imm operand - lda :mask - sta [:dstptr],y - iny - iny - iny ; advance to the ORA #imm operand - lda :mask - eor #$FFFF ; invert the mask to clear up the data - and :data - sta [:dstptr],y + ldy JTableOffset,x ; This points to the code fragment + lda 1,s ; load the offset + xba + ora #$00B1 + sta [:dstptr],y ; write the LDA (--),y instruction + iny + iny + iny ; advance to the AND #imm operand + lda :mask + sta [:dstptr],y + iny + iny + iny ; advance to the ORA #imm operand + lda :mask + eor #$FFFF ; invert the mask to clear up the data + and :data + sta [:dstptr],y :next - ply + ply ; dex ; dex - iny - iny + iny + iny - dec :col_cnt - bne :cloop + dec :col_cnt + bne :cloop - lda :srcptr - clc - adc #164 - sta :srcptr + lda :srcptr + clc + adc #164 + sta :srcptr - inc :line_cnt - lda :line_cnt - cmp #200 - bcs :exit - brl :rloop + inc :line_cnt + lda :line_cnt + cmp #200 + bcs :exit + brl :rloop :exit - rts + rts -:toMask pha ; save original +:toMask pha ; save original - lda 1,s - eor :mask_color ; only identical bits produce zero - and #$F000 - beq *+7 - pea #$0000 - bra *+5 - pea #$F000 + lda 1,s + eor :mask_color ; only identical bits produce zero + and #$F000 + beq *+7 + pea #$0000 + bra *+5 + pea #$F000 - lda 3,s - eor :mask_color - and #$0F00 - beq *+7 - pea #$0000 - bra *+5 - pea #$0F00 + lda 3,s + eor :mask_color + and #$0F00 + beq *+7 + pea #$0000 + bra *+5 + pea #$0F00 - lda 5,s - eor :mask_color - and #$00F0 - beq *+7 - pea #$0000 - bra *+5 - pea #$00F0 + lda 5,s + eor :mask_color + and #$00F0 + beq *+7 + pea #$0000 + bra *+5 + pea #$00F0 - lda 7,s - eor :mask_color - and #$000F - beq *+7 - lda #$0000 - bra *+5 - lda #$000F + lda 7,s + eor :mask_color + and #$000F + beq *+7 + lda #$0000 + bra *+5 + lda #$000F - ora 1,s - sta 1,s - pla - ora 1,s - sta 1,s - pla - ora 1,s - sta 1,s - pla + ora 1,s + sta 1,s + pla + ora 1,s + sta 1,s + pla + ora 1,s + sta 1,s + pla - sta 1,s ; pop the saved word - pla - rts + sta 1,s ; pop the saved word + pla + rts -:headerStr asc 'GTERAW' +:headerStr asc 'GTERAW' ; Copy a loaded SHR picture into the code field ; @@ -672,152 +513,152 @@ CopyBinToField ; ; Picture must be within one bank CopyPicToField -:srcptr equ tmp0 -:line_cnt equ tmp2 -:dstptr equ tmp3 -:col_cnt equ tmp5 -:mask equ tmp6 -:data equ tmp7 +:srcptr equ tmp0 +:line_cnt equ tmp2 +:dstptr equ tmp3 +:col_cnt equ tmp5 +:mask equ tmp6 +:data equ tmp7 - sta :srcptr - stx :srcptr+2 + sta :srcptr + stx :srcptr+2 - stz :line_cnt + stz :line_cnt :rloop - lda :line_cnt ; get the pointer to the code field line - asl - tax + lda :line_cnt ; get the pointer to the code field line + asl + tax - lda BTableLow,x - sta :dstptr - lda BTableHigh,x - sta :dstptr+2 + lda BTableLow,x + sta :dstptr + lda BTableHigh,x + sta :dstptr+2 ; ldx #162 ; move backwards in the code field - ldy #0 ; move forward in the image data + ldy #0 ; move forward in the image data - lda #80 ; keep a running column count + lda #80 ; keep a running column count ; lda #82 ; keep a running column count - sta :col_cnt + sta :col_cnt :cloop - phy - lda [:srcptr],y ; load the picture data - beq :transparent ; a value of $0000 is transparent + phy + lda [:srcptr],y ; load the picture data + beq :transparent ; a value of $0000 is transparent - jsr :toMask ; Infer a mask value for this. If it's $0000, then - bne :mixed ; the data is solid, otherwise mixed + jsr :toMask ; Infer a mask value for this. If it's $0000, then + bne :mixed ; the data is solid, otherwise mixed ; This is a solid word - lda [:srcptr],y - pha ; Save the data + lda [:srcptr],y + pha ; Save the data - lda Col2CodeOffset,y ; Get the offset to the code from the line start - tay + lda Col2CodeOffset,y ; Get the offset to the code from the line start + tay - lda #$00F4 ; PEA instruction - sta [:dstptr],y - iny - pla - sta [:dstptr],y ; PEA operand - bra :next + lda #$00F4 ; PEA instruction + sta [:dstptr],y + iny + pla + sta [:dstptr],y ; PEA operand + bra :next :transparent - lda Col2CodeOffset,y ; Get the offset to the code from the line start - tay + lda Col2CodeOffset,y ; Get the offset to the code from the line start + tay - lda #$B1 ; LDA (dp),y - sta [:dstptr],y - iny - lda 1,s ; load the saved Y-index - ora #$4800 ; put a PHA after the offset - sta [:dstptr],y - bra :next + lda #$B1 ; LDA (dp),y + sta [:dstptr],y + iny + lda 1,s ; load the saved Y-index + ora #$4800 ; put a PHA after the offset + sta [:dstptr],y + bra :next :mixed - sta :mask ; Save the mask - lda [:srcptr],y ; Refetch the screen data - sta :data + sta :mask ; Save the mask + lda [:srcptr],y ; Refetch the screen data + sta :data - tyx - lda Col2CodeOffset,y ; Get the offset into the code field - tay + tyx + lda Col2CodeOffset,y ; Get the offset into the code field + tay - lda #$4C ; JMP exception - sta [:dstptr],y - iny + lda #$4C ; JMP exception + sta [:dstptr],y + iny - lda JTableOffset,x ; Get the address offset and add to the base address - clc - adc :dstptr - sta [:dstptr],y + lda JTableOffset,x ; Get the address offset and add to the base address + clc + adc :dstptr + sta [:dstptr],y - ldy JTableOffset,x ; This points to the code fragment - lda 1,s ; load the offset - xba - ora #$00B1 - sta [:dstptr],y ; write the LDA (--),y instruction - iny - iny - iny ; advance to the AND #imm operand - lda :mask - sta [:dstptr],y - iny - iny - iny ; advance to the ORA #imm operand - lda :data - sta [:dstptr],y + ldy JTableOffset,x ; This points to the code fragment + lda 1,s ; load the offset + xba + ora #$00B1 + sta [:dstptr],y ; write the LDA (--),y instruction + iny + iny + iny ; advance to the AND #imm operand + lda :mask + sta [:dstptr],y + iny + iny + iny ; advance to the ORA #imm operand + lda :data + sta [:dstptr],y :next - ply + ply ; dex ; dex - iny - iny + iny + iny - dec :col_cnt - bne :cloop + dec :col_cnt + bne :cloop - lda :srcptr - clc + lda :srcptr + clc ; adc #164 - adc #160 - sta :srcptr + adc #160 + sta :srcptr - inc :line_cnt - lda :line_cnt + inc :line_cnt + lda :line_cnt ; cmp #208 - cmp #200 - bcs :exit - brl :rloop + cmp #200 + bcs :exit + brl :rloop :exit - rts + rts -:toMask bit #$F000 - beq *+7 - and #$0FFF - bra *+5 - ora #$F000 +:toMask bit #$F000 + beq *+7 + and #$0FFF + bra *+5 + ora #$F000 - bit #$0F00 - beq *+7 - and #$F0FF - bra *+5 - ora #$0F00 + bit #$0F00 + beq *+7 + and #$F0FF + bra *+5 + ora #$0F00 - bit #$00F0 - beq *+7 - and #$FF0F - bra *+5 - ora #$00F0 + bit #$00F0 + beq *+7 + and #$FF0F + bra *+5 + ora #$00F0 - bit #$000F - beq *+7 - and #$FFF0 - bra *+5 - ora #$000F - rts + bit #$000F + beq *+7 + and #$FFF0 + bra *+5 + ora #$000F + rts ; Copy a binary image data file into BG1. Assumes the file is the correct size. ; @@ -826,475 +667,219 @@ CopyPicToField ; Y=high word of BG1 bank CopyBinToBG1 -:srcptr equ tmp0 -:line_cnt equ tmp2 -:dstptr equ tmp3 -:col_cnt equ tmp5 +:srcptr equ tmp0 +:line_cnt equ tmp2 +:dstptr equ tmp3 +:col_cnt equ tmp5 - sta :srcptr - stx :srcptr+2 - sty :dstptr+2 ; Everything goes into this bank + sta :srcptr + stx :srcptr+2 + sty :dstptr+2 ; Everything goes into this bank - ; Advance over the header - lda :srcptr - clc - adc #8 - sta :srcptr + ; Advance over the header + lda :srcptr + clc + adc #8 + sta :srcptr - stz :line_cnt + stz :line_cnt :rloop - lda :line_cnt ; get the pointer to the code field line - asl - tax + lda :line_cnt ; get the pointer to the code field line + asl + tax - lda BG1YTable,x - sta :dstptr + lda BG1YTable,x + sta :dstptr - ldy #0 ; move forward in the image data and image data + ldy #0 ; move forward in the image data and image data :cloop - lda [:srcptr],y - sta [:dstptr],y + lda [:srcptr],y + sta [:dstptr],y - iny - iny + iny + iny - cpy #164 - bcc :cloop + cpy #164 + bcc :cloop - lda [:srcptr] ; Duplicate the last byte in the extra space at the end of the line - sta [:dstptr],y + lda [:srcptr] ; Duplicate the last byte in the extra space at the end of the line + sta [:dstptr],y - lda :srcptr - clc - adc #164 ; Each line is 328 pixels - sta :srcptr + lda :srcptr + clc + adc #164 ; Each line is 328 pixels + sta :srcptr - inc :line_cnt - lda :line_cnt - cmp #208 ; A total of 208 lines - bcc :rloop - rts - -**************************************** -* Fatal Error Handler * -**************************************** -PgmDeath tax - pla - inc - phx - phk - pha - bra ContDeath -PgmDeath0 pha - pea $0000 - pea $0000 -ContDeath ldx #$1503 - jsl $E10000 - -; Interrupt handlers. We install a heartbeat (1/60th second and a 1-second timer) -OneSecHandler mx %11 - phb - pha - phk - plb - - rep #$20 - inc OneSecondCounter - sep #$20 - - ldal $E0C032 - and #%10111111 ;clear IRQ source - stal $E0C032 - - pla - plb - clc - rtl - mx %00 -OneSecondCounter dw 0 -OldOneSecVec ds 4 - -VBLTASK hex 00000000 - dw 0 - hex 5AA5 - -; Blitter initialization -BlitInit - stz ScreenHeight - stz ScreenWidth - stz ScreenY0 - stz ScreenY1 - stz ScreenX0 - stz ScreenX1 - stz ScreenTileHeight - stz ScreenTileWidth - stz StartX - stz OldStartX - stz StartXMod164 - - stz StartY - stz OldStartY - stz StartYMod208 - - stz EngineMode - stz DirtyBits - stz LastPatchOffset - stz BG1StartX - stz BG1StartXMod164 - stz BG1StartY - stz BG1StartYMod208 - stz BG1OffsetIndex - - stz BG0TileOriginX - stz BG0TileOriginY - stz OldBG0TileOriginX - stz OldBG0TileOriginY - - stz BG1TileOriginX - stz BG1TileOriginY - stz OldBG1TileOriginX - stz OldBG1TileOriginY - - stz TileMapWidth - stz TileMapHeight - stz TileMapPtr - stz TileMapPtr+2 - -]step equ 0 - lup 13 - ldx #BlitBuff - lda #^BlitBuff - ldy #]step - jsr BuildBank -]step equ ]step+4 - --^ - rts - - -; Graphic screen initialization -GrafInit - jsr ShadowOn - jsr GrafOn - lda #$8888 - jsr ClearToColor - lda #0000 - jsr SetSCBs - ldx #DefaultPalette - lda #0 - jsr SetPalette - rts + inc :line_cnt + lda :line_cnt + cmp #208 ; A total of 208 lines + bcc :rloop + rts ;DefaultPalette dw $0000,$007F,$0090,$0FF0 ; dw $000F,$0080,$0f70,$0FFF - dw $0fa9,$0ff0,$00e0,$04DF - dw $0d00,$078f,$0ccc,$0FFF + dw $0fa9,$0ff0,$00e0,$04DF + dw $0d00,$078f,$0ccc,$0FFF ; DefaultPalette dw $09BE,$0AA6,$0DC9,$0DB7,$09AA - dw $0080,$0f70,$0FFF - dw $0fa9,$0ff0,$00e0,$04DF - dw $0d00,$078f,$0ccc,$0FFF + dw $0080,$0f70,$0FFF + dw $0fa9,$0ff0,$00e0,$04DF + dw $0d00,$078f,$0ccc,$0FFF ; Super Mario World Assets ;DefaultPalette dw $0EEF,$0342,$0C95,$0852,$0DB4,$00C0 - dw $0FDA,$0DEE,$0000,$0CC5,$09A0,$0680,$0470,$0051 + dw $0FDA,$0DEE,$0000,$0CC5,$09A0,$0680,$0470,$0051 ;DefaultPalette dw $0000,$0000,$0778,$0BCC,$0368,$00AF,$0556,$0245 - dw $0000,$0778,$0AAA,$0CFF,$0368,$00AF,$0556 + dw $0000,$0778,$0AAA,$0CFF,$0368,$00AF,$0556 ; Woz ;DefaultPalette dw $0EEF,$0342,$0C95,$0852,$0DB4,$00C0 - dw $0666,$0999,$0CCC,$0222,$09A0,$0680,$0470,$0051 + dw $0666,$0999,$0CCC,$0222,$09A0,$0680,$0470,$0051 ; Fatdog color cycling ;DefaultPalette dw $0EEF,$0342,$0C95,$0852,$0DB4,$00C0 - dw $0156,$0288,$03A8,$07B8,$0034,$0013,$0470,$0051 + dw $0156,$0288,$03A8,$07B8,$0034,$0013,$0470,$0051 ; Plant ;DefaultPalette dw $0EEF,$0342,$0C95,$0852,$0DB4,$00C0 - dw $0222,$0333,$0444,$0888,$09A0,$0680,$0470,$0051 + dw $0222,$0333,$0444,$0888,$09A0,$0680,$0470,$0051 ; SMB -DefaultPalette dw $0E51,$0EDB,$0000,$068F,$0BF1,$00A0,$0EEE,$0777,$0FA4,$0F59,$0E05,$0F30 - dw $0680,$0470,$0051 - -; Return the current border color ($0 - $F) in the accumulator -GetBorderColor lda #0000 - sep #$20 - ldal BORDER_REG - and #$0F - rep #$20 - rts - -; Set the border color to the accumulator value. -SetBorderColor sep #$20 ; ACC = $X_Y, REG = $W_Z - eorl BORDER_REG ; ACC = $(X^Y)_(Y^Z) - and #$0F ; ACC = $0_(Y^Z) - eorl BORDER_REG ; ACC = $W_(Y^Z^Z) = $W_Y - stal BORDER_REG - rep #$20 - rts - -; Clear to SHR screen to a specific color -ClearToColor ldx #$7D00 ;start at top of pixel data! ($2000-9D00) -:clearloop dex - dex - stal SHR_SCREEN,x ;screen location - bne :clearloop ;loop until we've worked our way down to 0 - rts - -; Set a palette values -; A = palette number, X = palette address -SetPalette - and #$000F ; palette values are 0 - 15 and each palette is 32 bytes - asl - asl - asl - asl - asl - txy - tax - -]idx equ 0 - lup 16 - lda: $0000+]idx,y - stal SHR_PALETTES+]idx,x -]idx equ ]idx+2 - --^ - rts - -; Initialize the SCB -SetSCBs ldx #$0100 ;set all $100 scbs to A -:scbloop dex - dex - stal SHR_SCB,x - bne :scbloop - rts - -; Turn SHR screen On/Off -GrafOn sep #$20 - lda #$81 - stal NEW_VIDEO_REG - rep #$20 - rts - -GrafOff sep #$20 - lda #$01 - stal NEW_VIDEO_REG - rep #$20 - rts - -; Enable/Disable Shadowing. -ShadowOn sep #$20 - ldal SHADOW_REG - and #$F7 - stal SHADOW_REG - rep #$20 - rts - -ShadowOff sep #$20 - ldal SHADOW_REG - ora #$08 - stal SHADOW_REG - rep #$20 - rts - -GetVBL sep #$20 - ldal VBL_HORZ_REG - asl - ldal VBL_VERT_REG - rol ; put V5 into carry bit, if needed. See TN #39 for details. - rep #$20 - and #$00FF - rts - -WaitForVBL sep #$20 -:wait1 ldal VBL_STATE_REG ; If we are already in VBL, then wait - bmi :wait1 -:wait2 ldal VBL_STATE_REG - bpl :wait2 ; spin until transition into VBL - rep #$20 - rts - -WaitForKey sep #$20 - stal KBD_STROBE_REG ; clear the strobe -:WFK ldal KBD_REG - bpl :WFK - rep #$20 - and #$007F - rts - -ClearKeyboardStrobe sep #$20 - stal KBD_STROBE_REG - rep #$20 - rts - -ReadControl - pea $0000 ; low byte = key code, high byte = %------AB - - sep #$20 - ldal OPTION_KEY_REG ; 'B' button - and #$80 - beq :BNotDown - - lda #1 - ora 1,s - sta 1,s - -:BNotDown - ldal COMMAND_KEY_REG - and #$80 - beq :ANotDown - - lda #2 - ora 1,s - sta 1,s - -:ANotDown - ldal KBD_STROBE_REG ; read the keyboard - bit #$80 - beq :KbdNotDwn ; check the key-down status - and #$7f - ora 1,s - sta 1,s - -:KbdNotDwn - rep #$20 - pla - rts +DefaultPalette dw $0E51,$0EDB,$0000,$068F,$0BF1,$00A0,$0EEE,$0777,$0FA4,$0F59,$0E05,$0F30 + dw $0680,$0470,$0051 ; Graphics helpers LoadPicture - jsr LoadFile ; X=Nom Image, A=Banc de chargement XX/00 - bcc :loadOK - rts + jsr LoadFile ; X=Nom Image, A=Banc de chargement XX/00 + bcc :loadOK + rts :loadOK - jsr UnpackPicture ; A=Packed Size - rts + jsr UnpackPicture ; A=Packed Size + rts -UnpackPicture sta UP_PackedSize ; Size of Packed Data - lda #$8000 ; Size of output Data Buffer - sta UP_UnPackedSize - lda BankLoad ; Banc de chargement / Decompression - sta UP_Packed+1 ; Packed Data - clc - adc #$0080 - stz UP_UnPacked ; On remet a zero car modifie par l'appel - stz UP_UnPacked+2 - sta UP_UnPacked+1 ; Unpacked Data buffer +UnpackPicture sta UP_PackedSize ; Size of Packed Data + lda #$8000 ; Size of output Data Buffer + sta UP_UnPackedSize + lda BankLoad ; Banc de chargement / Decompression + sta UP_Packed+1 ; Packed Data + clc + adc #$0080 + stz UP_UnPacked ; On remet a zero car modifie par l'appel + stz UP_UnPacked+2 + sta UP_UnPacked+1 ; Unpacked Data buffer - PushWord #0 ; Space for Result : Number of bytes unpacked - PushLong UP_Packed ; Pointer to buffer containing the packed data - PushWord UP_PackedSize ; Size of the Packed Data - PushLong #UP_UnPacked ; Pointer to Pointer to unpacked buffer - PushLong #UP_UnPackedSize ; Pointer to a Word containing size of unpacked data - _UnPackBytes - pla ; Number of byte unpacked - rts + PushWord #0 ; Space for Result : Number of bytes unpacked + PushLong UP_Packed ; Pointer to buffer containing the packed data + PushWord UP_PackedSize ; Size of the Packed Data + PushLong #UP_UnPacked ; Pointer to Pointer to unpacked buffer + PushLong #UP_UnPackedSize ; Pointer to a Word containing size of unpacked data + _UnPackBytes + pla ; Number of byte unpacked + rts -UP_Packed hex 00000000 ; Address of Packed Data -UP_PackedSize hex 0000 ; Size of Packed Data -UP_UnPacked hex 00000000 ; Address of Unpacked Data Buffer (modified) -UP_UnPackedSize hex 0000 ; Size of Unpacked Data Buffer (modified) +UP_Packed hex 00000000 ; Address of Packed Data +UP_PackedSize hex 0000 ; Size of Packed Data +UP_UnPacked hex 00000000 ; Address of Unpacked Data Buffer (modified) +UP_UnPackedSize hex 0000 ; Size of Unpacked Data Buffer (modified) ; Basic I/O function to load files LoadFile - stx openRec+4 ; X=File, A=Bank (high word) assumed zero for low - stz readRec+4 - sta readRec+6 - jsr ClearBankLoad + stx openRec+4 ; X=File, A=Bank (high word) assumed zero for low + stz readRec+4 + sta readRec+6 + jsr ClearBankLoad -:openFile _OpenGS openRec - bcs :openReadErr - lda openRec+2 - sta eofRec+2 - sta readRec+2 +:openFile _OpenGS openRec + bcs :openReadErr + lda openRec+2 + sta eofRec+2 + sta readRec+2 - _GetEOFGS eofRec - lda eofRec+4 - sta readRec+8 - lda eofRec+6 - sta readRec+10 + _GetEOFGS eofRec + lda eofRec+4 + sta readRec+8 + lda eofRec+6 + sta readRec+10 - _ReadGS readRec - bcs :openReadErr + _ReadGS readRec + bcs :openReadErr -:closeFile _CloseGS closeRec - clc - lda eofRec+4 ; File Size - rts +:closeFile _CloseGS closeRec + clc + lda eofRec+4 ; File Size + rts -:openReadErr jsr :closeFile - nop - nop +:openReadErr jsr :closeFile + nop + nop - PushWord #0 - PushLong #msgLine1 - PushLong #msgLine2 - PushLong #msgLine3 - PushLong #msgLine4 - _TLTextMountVolume - pla - cmp #1 - bne :loadFileErr - brl :openFile -:loadFileErr sec - rts + PushWord #0 + PushLong #msgLine1 + PushLong #msgLine2 + PushLong #msgLine3 + PushLong #msgLine4 + _TLTextMountVolume + pla + cmp #1 + bne :loadFileErr + brl :openFile +:loadFileErr sec + rts -msgLine1 str 'Unable to load File' -msgLine2 str 'Press a key :' -msgLine3 str ' -> Return to Try Again' -msgLine4 str ' -> Esc to Quit' +msgLine1 str 'Unable to load File' +msgLine2 str 'Press a key :' +msgLine3 str ' -> Return to Try Again' +msgLine4 str ' -> Esc to Quit' ; Data storage -MusicFile str '1/main.ntp' -BG1DataFile strl '1/bg1a.bin' -BG1AltDataFile strl '1/bg1b.bin' +MusicFile str '1/main.ntp' +BG1DataFile strl '1/bg1a.bin' +BG1AltDataFile strl '1/bg1b.bin' + +ImageName strl '1/test.pic' +FGName strl '1/fg1.bin' +;MasterId ds 2 +;UserId ds 2 + +openRec dw 2 ; pCount + ds 2 ; refNum + adrl FGName ; pathname + +eofRec dw 2 ; pCount + ds 2 ; refNum + ds 4 ; eof + +readRec dw 4 ; pCount + ds 2 ; refNum + ds 4 ; dataBuffer + ds 4 ; requestCount + ds 4 ; transferCount + +closeRec dw 1 ; pCount + ds 2 ; refNum + +qtRec adrl $0000 + da $00 + + PUT App.TileMapBG0.s + PUT App.TileMapBG1.s + + + + + + -ImageName strl '1/test.pic' -FGName strl '1/fg1.bin' -MasterId ds 2 -UserId ds 2 -openRec dw 2 ; pCount - ds 2 ; refNum - adrl FGName ; pathname -eofRec dw 2 ; pCount - ds 2 ; refNum - ds 4 ; eof -readRec dw 4 ; pCount - ds 2 ; refNum - ds 4 ; dataBuffer - ds 4 ; requestCount - ds 4 ; transferCount -closeRec dw 1 ; pCount - ds 2 ; refNum -qtRec adrl $0000 - da $00 - put App.Init.s - put App.Msg.s - put Actions.s - put font.s - put Render.s - put Overlay.s - put blitter/Blitter.s - put blitter/Horz.s - put blitter/PEISlammer.s - put blitter/Tables.s - put blitter/Template.s - put blitter/Tiles.s - put blitter/Vert.s - put blitter/BG1.s - PUT TileMap.s - PUT App.TileMapBG0.s - PUT App.TileMapBG1.s diff --git a/src/App.s b/src/App.s index f475c9d..3a7716f 100644 --- a/src/App.s +++ b/src/App.s @@ -20,7 +20,7 @@ ; ALI BANK SNA Tiles -;Segment #3 -- Rotation table data +; Segment #3 -- Rotation table data ASM RotData.s DS 0 @@ -28,3 +28,4 @@ ALI BANK SNA RotData + diff --git a/src/Core.s b/src/Core.s new file mode 100644 index 0000000..4d6c97a --- /dev/null +++ b/src/Core.s @@ -0,0 +1,428 @@ + use Util.Macs.s + use Locator.Macs.s + use Mem.Macs.s + use Misc.Macs.s + use Tool222.MACS.s + use Core.MACS.s + + use .\Defs.s + +; Feature flags +NO_INTERRUPTS equ 1 ; turn off for crossrunner debugging +NO_MUSIC equ 1 ; turn music + tool loading off + +; External data provided by the main program segment +tiledata EXT + +; Core engine functionality. The idea is that that source file can be PUT into +; a main source file and all of the functionality will be available. +; +; There are some constancts that must be externally defined that can affect how +; the GTE runtime works +; +; NO_MUSIC : Set to non-zero to avoid using any source +; NO_INTERRUPTS : Set to non-zero to avoid installing custom interrupt handlers + + mx %00 + +; High-Level StartUp and ShutDown functions +EngineStartUp ENT + phb + phk + plb + + jsr ToolStartUp ; Start up the toolbox tools we rely on + jsr SoundStartUp ; Start up any sound/music tools + jsr IntStartUp ; Enable certain iterrupts + + jsr InitMemory ; Allocate and initialize memory for the engine + jsr InitGraphics ; Initialize all of the graphics-related dat + jsr InitTimers ; Initialize the timee subsystem + + jsr EngineReset ; All of the resources are allocated, put the engine in a known state + + plb + rtl + +EngineShutDown ENT + jsr IntShutDown + jsr SoundShutDown + jsr ToolShutDown + rtl + +ToolStartUp + _TLStartUp ; normal tool initialization + pha + _MMStartUp + _Err ; should never happen + pla + sta MasterId ; our master handle references the memory allocated to us + ora #$0100 ; set auxID = $01 (valid values $01-0f) + sta UserId ; any memory we request must use our own id + + _MTStartUp + rts + +MasterId ds 2 +UserId ds 2 + +; Fatal error handler invoked by the _Err macro +PgmDeath tax + pla + inc + phx + phk + pha + bra ContDeath +PgmDeath0 pha + pea $0000 + pea $0000 +ContDeath ldx #$1503 + jsl $E10000 + +ToolShutDown + rts + +; Use Tool222 (NinjaTrackerPlus) for music playback +SoundStartUp + lda #NO_MUSIC + bne :no_music + + pea $00DE + pea $0000 + _LoadOneTool + _Err + + lda UserId + pha + _NTPStartUp +:no_music + rts + +SoundShutDown + lda #NO_MUSIC + bne :no_music + _NTPShutDown +:no_music + rts + +; Install interrupt handlers. We use the VBL interrupt to keep animations +; moving at a consistent rate, regarless of the rendered frame rate. The +; one-second timer is generally just used for counters and as a handy +; frames-per-second trigger. +IntStartUp + lda #NO_INTERRUPTS + bne :no_interrupts + PushLong #0 + pea $0015 ; Get the existing 1-second interrupt handler and save + _GetVector + PullLong OldOneSecVec + + pea $0015 ; Set the new handler and enable interrupts + PushLong #OneSecHandler + _SetVector + + pea $0006 + _IntSource + + PushLong #VBLTASK ; Also register a Heart Beat Task + _SetHeartBeat + +:no_interrupts + rts + +IntShutDown + lda #NO_INTERRUPTS + bne :no_interrupts + + pea $0007 ; disable 1-second interrupts + _IntSource + + PushLong #VBLTASK ; Remove our heartbeat task + _DelHeartBeat + + pea $0015 + PushLong OldOneSecVec ; Reset the interrupt vector + _SetVector + +:no_interrupts + rts + + +; Interrupt handlers. We install a heartbeat (1/60th second and a 1-second timer) +OneSecHandler mx %11 + phb + pha + phk + plb + + rep #$20 + inc OneSecondCounter + sep #$20 + + ldal $E0C032 + and #%10111111 ;clear IRQ source + stal $E0C032 + + pla + plb + clc + rtl + mx %00 + +OneSecondCounter dw 0 +OldOneSecVec ds 4 + +VBLTASK hex 00000000 + dw 0 + hex 5AA5 + +; Reset the engine to a known state +; Blitter initialization +EngineReset + stz ScreenHeight + stz ScreenWidth + stz ScreenY0 + stz ScreenY1 + stz ScreenX0 + stz ScreenX1 + stz ScreenTileHeight + stz ScreenTileWidth + stz StartX + stz OldStartX + stz StartXMod164 + + stz StartY + stz OldStartY + stz StartYMod208 + + stz EngineMode + stz DirtyBits + stz LastPatchOffset + stz BG1StartX + stz BG1StartXMod164 + stz BG1StartY + stz BG1StartYMod208 + stz BG1OffsetIndex + + stz BG0TileOriginX + stz BG0TileOriginY + stz OldBG0TileOriginX + stz OldBG0TileOriginY + + stz BG1TileOriginX + stz BG1TileOriginY + stz OldBG1TileOriginX + stz OldBG1TileOriginY + + stz TileMapWidth + stz TileMapHeight + stz TileMapPtr + stz TileMapPtr+2 + + stz OneSecondCounter + +]step equ 0 + lup 13 + ldx #BlitBuff + lda #^BlitBuff + ldy #]step + jsr BuildBank +]step equ ]step+4 + --^ + rts + +; Allow the user to dynamically select one of the pre-configured screen sizes, or pass +; in a specific width and height. The screen is automatically centered. If this is +; not desired, then SetScreenRect should be used directly +; +; 0. Full Screen : 40 x 25 320 x 200 (32,000 bytes (100.0%)) +; 1. Sword of Sodan : 34 x 24 272 x 192 (26,112 bytes ( 81.6%)) +; 2. ~NES : 32 x 25 256 x 200 (25,600 bytes ( 80.0%)) +; 3. Task Force : 32 x 22 256 x 176 (22,528 bytes ( 70.4%)) +; 4. Defender of the World : 35 x 20 280 x 160 (22,400 bytes ( 70.0%)) +; 5. Rastan : 32 x 20 256 x 160 (20,480 bytes ( 64.0%)) +; 6. Game Boy Advanced : 30 x 20 240 x 160 (19,200 bytes ( 60.0%)) +; 7. Ancient Land of Y's : 36 x 16 288 x 128 (18,432 bytes ( 57.6%)) +; 8. Game Boy Color : 20 x 18 160 x 144 (11,520 bytes ( 36.0%)) +; +; X = mode number OR width in pixels (must be multiple of 2) +; Y = hwight in pixels (if X > 8) + +ScreenModeWidth dw 320,272,256,256,280,256,240,288,160,320 +ScreenModeHeight dw 200,192,200,176,160,160,160,128,144,1 + +SetScreenMode ENT + phb + phk + plb + + cpx #9 + bcs :direct ; if x > 8, then assume X and Y are the dimensions + + txa + asl + tax + + ldy ScreenModeHeight,x + lda ScreenModeWidth,x + tax + +:direct cpy #201 + bcs :exit + + cpx #321 + bcs :exit + + txa + lsr + pha ; Save X (width / 2) and Y (height) + phy + + lda #160 ; Center the screen + sec + sbc 3,s + lsr + xba + pha ; Save half the origin coordinate + + lda #200 + sec + sbc 3,s ; This is now Y because of the PHA above + lsr + ora 1,s + + plx ; Throw-away to pop the stack + ply + plx + + jsr SetScreenRect + jsr FillScreen + +:exit + plb + rtl + +WaitForKey sep #$20 + stal KBD_STROBE_REG ; clear the strobe +:WFK ldal KBD_REG + bpl :WFK + rep #$20 + and #$007F + rts + +ClearKbdStrobe sep #$20 + stal KBD_STROBE_REG + rep #$20 + rts + +; Read the keyboard and paddle controls and return in a game-cotroller-like format +ReadControl ENT + pea $0000 ; low byte = key code, high byte = %------AB + + sep #$20 + ldal OPTION_KEY_REG ; 'B' button + and #$80 + beq :BNotDown + + lda #1 + ora 1,s + sta 1,s + +:BNotDown + ldal COMMAND_KEY_REG + and #$80 + beq :ANotDown + + lda #2 + ora 1,s + sta 1,s + +:ANotDown + ldal KBD_STROBE_REG ; read the keyboard + bit #$80 + beq :KbdNotDwn ; check the key-down status + and #$7f + ora 1,s + sta 1,s + +:KbdNotDwn + rep #$20 + pla + rtl + + put App.Init.s + put Graphics.s +; put App.Msg.s +; put Actions.s +; put font.s + put Render.s +; put Overlay.s + put blitter/Blitter.s + put blitter/Horz.s + put blitter/PEISlammer.s + put blitter/Tables.s + put blitter/Template.s + put blitter/Tiles.s + put blitter/Vert.s + put blitter/BG1.s + put TileMap.s + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/blitter/DirectPage.s b/src/Defs.s similarity index 79% rename from src/blitter/DirectPage.s rename to src/Defs.s index b998d12..c53d416 100644 --- a/src/blitter/DirectPage.s +++ b/src/Defs.s @@ -1,3 +1,23 @@ +; Global addresses and engine values +SHADOW_REG equ $E0C035 +STATE_REG equ $E0C068 +NEW_VIDEO_REG equ $E0C029 +BORDER_REG equ $E0C034 ; 0-3 = border, 4-7 Text color +VBL_VERT_REG equ $E0C02E +VBL_HORZ_REG equ $E0C02F + +KBD_REG equ $E0C000 +KBD_STROBE_REG equ $E0C010 +VBL_STATE_REG equ $E0C019 +MOD_REG equ $E0C025 +COMMAND_KEY_REG equ $E0C061 +OPTION_KEY_REG equ $E0C062 + +SHADOW_SCREEN equ $012000 +SHR_SCREEN equ $E12000 +SHR_SCB equ $E19D00 +SHR_PALETTES equ $E19E00 + ; Direct page locations used by the engine ScreenHeight equ 0 ; Height of the playfield in scan lines ScreenWidth equ 2 ; Width of the playfield in bytes @@ -59,10 +79,12 @@ Next equ 86 BankLoad equ 128 -tiletmp equ 186 ; 8 bytes of temp storage for the tile renderers -blttmp equ 192 ; 32 bytes of local cache/scratch space +AppSpace equ 160 ; 16 bytes of space reserved for application use -tmp8 equ 224 +tiletmp equ 186 ; 8 bytes of temp storage for the tile renderers +blttmp equ 192 ; 32 bytes of local cache/scratch space for blitter + +tmp8 equ 224 ; another 16 bytes of temporary space to be used as scratch tmp9 equ 226 tmp10 equ 228 tmp11 equ 230 @@ -89,3 +111,10 @@ DIRTY_BIT_BG1_REFRESH equ $0020 + + + + + + + diff --git a/src/GTE.s b/src/GTE.s new file mode 100644 index 0000000..0c66773 --- /dev/null +++ b/src/GTE.s @@ -0,0 +1,22 @@ +; Collection of the EXTernal labels exported by GTE. This is the closest thing +; we have to an API definition. + +EngineStartUp EXT +EngineShutDown EXT + +SetScreenMode EXT +ReadControl EXT +Render EXT + +AddTimer EXT +RemoveTimer EXT +DoTimers EXT + +StartScript EXT +StopScript EXT + +; Super Hires line address lookup table for convenience +ScreenAddr EXT + + + diff --git a/src/Graphics.s b/src/Graphics.s new file mode 100644 index 0000000..e63a420 --- /dev/null +++ b/src/Graphics.s @@ -0,0 +1,118 @@ + +; Graphic screen initialization +InitGraphics + jsr ShadowOn + jsr GrafOn + lda #0 + jsr ClearToColor + lda #0 + jsr SetSCBs + ldx #DefaultPalette + lda #0 + jsr SetPalette + rts + +DefaultPalette dw $0000,$007F,$0090,$0FF0 + dw $000F,$0080,$0f70,$0FFF + dw $0fa9,$0ff0,$00e0,$04DF + dw $0d00,$078f,$0ccc,$0FFF + +; Return the current border color ($0 - $F) in the accumulator +GetBorderColor lda #0000 + sep #$20 + ldal BORDER_REG + and #$0F + rep #$20 + rts + +; Set the border color to the accumulator value. +SetBorderColor sep #$20 ; ACC = $X_Y, REG = $W_Z + eorl BORDER_REG ; ACC = $(X^Y)_(Y^Z) + and #$0F ; ACC = $0_(Y^Z) + eorl BORDER_REG ; ACC = $W_(Y^Z^Z) = $W_Y + stal BORDER_REG + rep #$20 + rts + +; Clear to SHR screen to a specific color +ClearToColor ldx #$7D00 ;start at top of pixel data! ($2000-9D00) +:clearloop dex + dex + stal SHR_SCREEN,x ;screen location + bne :clearloop ;loop until we've worked our way down to 0 + rts + +; Set a palette values +; A = palette number, X = palette address +SetPalette + and #$000F ; palette values are 0 - 15 and each palette is 32 bytes + asl + asl + asl + asl + asl + txy + tax + +]idx equ 0 + lup 16 + lda: $0000+]idx,y + stal SHR_PALETTES+]idx,x +]idx equ ]idx+2 + --^ + rts + +; Initialize the SCB +SetSCBs ldx #$0100 ;set all $100 scbs to A +:scbloop dex + dex + stal SHR_SCB,x + bne :scbloop + rts + +; Turn SHR screen On/Off +GrafOn sep #$20 + lda #$81 + stal NEW_VIDEO_REG + rep #$20 + rts + +GrafOff sep #$20 + lda #$01 + stal NEW_VIDEO_REG + rep #$20 + rts + +; Enable/Disable Shadowing. +ShadowOn sep #$20 + ldal SHADOW_REG + and #$F7 + stal SHADOW_REG + rep #$20 + rts + +ShadowOff sep #$20 + ldal SHADOW_REG + ora #$08 + stal SHADOW_REG + rep #$20 + rts + +GetVBL sep #$20 + ldal VBL_HORZ_REG + asl + ldal VBL_VERT_REG + rol ; put V5 into carry bit, if needed. See TN #39 for details. + rep #$20 + and #$00FF + rts + +WaitForVBL sep #$20 +:wait1 ldal VBL_STATE_REG ; If we are already in VBL, then wait + bmi :wait1 +:wait2 ldal VBL_STATE_REG + bpl :wait2 ; spin until transition into VBL + rep #$20 + rts + + diff --git a/src/Render.s b/src/Render.s index 3ff9e90..cdde2f9 100644 --- a/src/Render.s +++ b/src/Render.s @@ -53,7 +53,13 @@ ; This function examines the dirty bits and actually performs the work to update the code field ; and internal data structure to properly render the play field. Then the update pipeline is ; executed. -Render +Render ENT + phb + phk + plb + jsr _Render + plb + rtl ; TODO -- actually check the dirty bits and be selective on what gets updated. For example, if ; only the Y position changes, then we should only need to set new values on the @@ -63,7 +69,7 @@ Render ; It's important to do _ApplyBG0YPos first because it calculates the value of StartY % 208 which is ; used in all of the other loops - +_Render jsr _ApplyBG0YPos ; Set stack addresses for the virtual lines to the physical screen jsr _ApplyBG1YPos @@ -137,6 +143,11 @@ Render + + + + + diff --git a/src/Sprite.s b/src/Sprite.s new file mode 100644 index 0000000..106d9ad --- /dev/null +++ b/src/Sprite.s @@ -0,0 +1,62 @@ +; Some sample code / utilities to help integrate compiled sprites int the GTE rendering +; pipeline. +; +; The main point of this file to to establish calling conventions and provide a framework +; for blitting a range of sprite lines, instead of always the full sprite. + +; A = address, X = scroll_mask offset, Y = HHLL, LL = first line, HH = last line +draw + sei + + cli + rts + +lines dw line0,line1,line2,line3,line4,line5,line6,line7 + +line0 + lda 0 + and #$FF00 + ora #$00DD + sta 0 + +line1 + lda 0 + and #$FF00 + ora #$00DD + sta 0 + +line2 + lda 0 + and #$FF00 + ora #$00DD + sta 0 + +line3 + lda 0 + and #$FF00 + ora #$00DD + sta 0 + +line4 + lda 0 + and #$FF00 + ora #$00DD + sta 0 + +line5 + lda 0 + and #$FF00 + ora #$00DD + sta 0 + +line6 + lda 0 + and #$FF00 + ora #$00DD + sta 0 + +line7 + lda 0 + and #$FF00 + ora #$00DD + sta 0 diff --git a/src/blitter/Tables.s b/src/blitter/Tables.s index f3aab05..65ff585 100644 --- a/src/blitter/Tables.s +++ b/src/blitter/Tables.s @@ -215,7 +215,8 @@ CodeFieldOddBRA bra *-6 ; 0 -- branch back 6 to skip the JMP even path ]step equ $2000 -ScreenAddr lup 200 +ScreenAddr ENT + lup 200 dw ]step ]step = ]step+160 --^ @@ -256,3 +257,4 @@ BG1YOffsetTable lup 26 +