diff --git a/macros/Load.Macs.s b/macros/Load.Macs.s new file mode 100644 index 0000000..9d96ddd --- /dev/null +++ b/macros/Load.Macs.s @@ -0,0 +1,113 @@ +* Load Manager macros +* by Dave Klimas +; +; Copyright Apple Computer, Inc. 1986, 1987 +; and Roger Wagner Publishing, Inc. 1988 +; All Rights Reserved +; +_LoaderInitialization MAC + Tool $111 + <<< +_LoaderStartUp MAC + Tool $211 + <<< +_LoaderShutDown MAC + Tool $311 + <<< +~LoaderVersion MAC + PHA +_LoaderVersion MAC + Tool $411 + <<< +_LoaderReset MAC + Tool $511 + <<< +~LoaderStatus MAC + PHA +_LoaderStatus MAC + Tool $611 + <<< +~InitialLoad MAC + PHS 5 + PHWL ]1;]2 + PHW ]3 +_InitialLoad MAC + Tool $911 + <<< +~InitialLoad2 MAC + PHS 5 + PHWL ]1;]2 + PxW ]3;]4 +_InitialLoad2 MAC + Tool $2011 + <<< +~Restart MAC + PHS 5 + PHW ]1 +_Restart MAC + Tool $A11 + <<< +~LoadSegNum MAC + PHS 2 + PxW ]1;]2;]3 +_LoadSegNum MAC + Tool $B11 + <<< +~UnloadSegNum MAC + PxW ]1;]2;]3 +_UnloadSegNum MAC + Tool $C11 + <<< +~LoadSegName MAC + PHS 4 + PHW ]1 + PxL ]2;]3 +_LoadSegName MAC + Tool $D11 + <<< +~UnloadSeg MAC + PHS 3 + PHL ]1 +_UnloadSeg MAC + Tool $E11 + <<< +~GetLoadSegInfo MAC + PxW ]1;]2;]3 + PHL ]4 +_GetLoadSegInfo MAC + Tool $F11 + <<< +~GetUserID MAC + P1SL ]1 +_GetUserID MAC + Tool $1011 + <<< +~GetUserID2 MAC + P1SL ]1 +_GetUserID2 MAC + Tool $2111 + <<< +~LGetPathname MAC + PHS 2 + PxW ]1;]2 +_LGetPathname MAC + Tool $1111 + <<< +~LGetPathname2 MAC + PHS 2 + PxW ]1;]2 +_LGetPathname2 MAC + Tool $2211 + <<< +~UserShutDown MAC + PHA + PxW ]1;]2 +_UserShutDown MAC + Tool $1211 + <<< +~RenamePathname MAC + PxL ]1;]2 +_RenamePathname MAC + Tool $1311 + <<< + diff --git a/macros/Util.Macs.s b/macros/Util.Macs.s index 0a685aa..ef26b6e 100644 --- a/macros/Util.Macs.s +++ b/macros/Util.Macs.s @@ -339,6 +339,11 @@ Tool MAC JSL $E10000 ; go to dispatcher <<< +UserTool MAC + LDX #]1 ; load tool call # + JSL $E10008 ; go to dispatcher + <<< + ************************************************** * Auto-menu item macros * * This is one alternative for defining a menu * diff --git a/src/Core.s b/src/Core.s index 4077e2c..84dea71 100644 --- a/src/Core.s +++ b/src/Core.s @@ -1,4 +1,5 @@ use Util.Macs.s + use Load.Macs.s use Locator.Macs.s use Mem.Macs.s use Misc.Macs.s @@ -39,6 +40,12 @@ EngineStartUp ENT plb jsr ToolStartUp ; Start up the toolbox tools we rely on + jsr _CoreStartUp + + plb + rtl + +_CoreStartUp jsr SoundStartUp ; Start up any sound/music tools jsr IntStartUp ; Enable certain iterrupts @@ -51,22 +58,24 @@ EngineStartUp ENT jsr InitTiles ; Initialize the tile subsystem jsr InitTimers ; Initialize the timer subsystem - - plb - rtl + rts EngineShutDown ENT phb phk plb - jsr IntShutDown - jsr SoundShutDown + jsr _CoreShutDown jsr ToolShutDown plb rtl +_CoreShutDown + jsr IntShutDown + jsr SoundShutDown + rts + ToolStartUp _TLStartUp ; normal tool initialization pha @@ -274,9 +283,10 @@ EngineReset ; 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%)) -; +; 9. Agony (Amiga) : 36 x 24 288 x 192 (27,648 bytes ( 86.4%)) +; ; X = mode number OR width in pixels (must be multiple of 2) -; Y = hwight in pixels (if X > 8) +; Y = height 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 @@ -285,7 +295,11 @@ SetScreenMode ENT phb phk plb + jsr _SetScreenMode + plb + rtl +_SetScreenMode cpx #9 bcs :direct ; if x > 8, then assume X and Y are the dimensions @@ -326,11 +340,10 @@ SetScreenMode ENT plx jsr SetScreenRect - jsr FillScreen - + jmp FillScreen ; tail return :exit - plb - rtl + rts + WaitForKey sep #$20 stal KBD_STROBE_REG ; clear the strobe @@ -348,6 +361,10 @@ ClearKbdStrobe sep #$20 ; Read the keyboard and paddle controls and return in a game-controller-like format LastKey db 0 ReadControl ENT + jsr _ReadControl + rtl + +_ReadControl pea $0000 ; low byte = key code, high byte = %------AB sep #$20 @@ -391,7 +408,7 @@ ReadControl ENT :KbdDown rep #$20 pla - rtl + rts put Memory.s put Graphics.s diff --git a/src/Defs.s b/src/Defs.s index 8609c53..111e272 100644 --- a/src/Defs.s +++ b/src/Defs.s @@ -78,8 +78,9 @@ BG1TileMapWidth equ 82 BG1TileMapHeight equ 84 BG1TileMapPtr equ 86 -SCBArrayPtr equ 90 ; USed for palette binding -Next equ 94 +SCBArrayPtr equ 90 ; Used for palette binding +SpriteBanks equ 94 ; Bank bytes for the sprite data and sprite mask +Next equ 96 BankLoad equ 128 diff --git a/src/GTE.s b/src/GTE.s index 74db746..030b172 100644 --- a/src/GTE.s +++ b/src/GTE.s @@ -74,3 +74,21 @@ AllocBank EXT ScreenAddr EXT OneSecondCounter EXT BlitBuff EXT + +; Helper function to load the GTE User Toolset +GTEInstall + php +; ~InitialLoad userId;localToolPath;#0 + + pea $8000 ; User tool + pea $00A5 ; Tool 165 + PushLong toolPtr + _SetTSPtr + + plp + rtl + +; Look for the tool set in the System Tools folder and then next to the application +sysToolPath strl '*:System:Tools:ToolGTE' +localToolPath strl '9:ToolGTE' +toolPtr adrl 0 \ No newline at end of file diff --git a/src/Sprite.s b/src/Sprite.s index 207a1e9..78160a6 100644 --- a/src/Sprite.s +++ b/src/Sprite.s @@ -1,4 +1,4 @@ -; Functions for sprie handling. Mostly maintains the sprite list and provides +; Functions for sprite handling. Mostly maintains the sprite list and provides ; utility functions to calculate sprite/tile intersections ; ; The sprite plane actually covers two banks so that more than 32K can be used as a virtual @@ -31,6 +31,8 @@ InitSprites dex bpl :loop3 +; Precalculate some bank values + jsr _CacheSpriteBanks rts ; Run through the list of tile store offsets that this sprite was last drawn into and mark @@ -116,23 +118,27 @@ _ClearSpriteFromTileStore ; any sprite that needs to be re-drawn has been marked as dirty. ; ; In the first phase, we run through the list of dirty sprites and erase them from their -; OLD_VBUFF_ADDR. This clears the sprite plane buffers. We also interate through the +; OLD_VBUFF_ADDR. This clears the sprite plane buffers. We also iterate through the ; TILE_STORE_ADDR_X array and mark all of the tile store location that this sprite had occupied ; as dirty, as well as removing this sprite from the TS_SPRITE_FLAG bitfield. ; -; A final aspect is that any of the sprites idicated in the TS_SPRITE_FLAG are marked to be +; A final aspect is that any of the sprites indicated in the TS_SPRITE_FLAG are marked to be ; drawn in the next phase (since a portion of their content may have been erased if they overlap) ; ; In the second phase, the sprite is re-drawn into the sprite plane buffers and the appropriate -; Tile Store locations are marked as dirty -; -; +; Tile Store locations are marked as dirty. It is important to recognize that the sprites themselves +; can be marked dirty, and the underlying tiles in the tile store are independently marked dirty. + forceSpriteFlag ds 2 _RenderSprites ; First step is to look at the StartX and StartY values. If the offsets have changed from the -; last time that the frame was redered, then we need to mark all of the sprites as dirty so that +; last time that the frame was rendered, then we need to mark all of the sprites as dirty so that ; the tiles on which they were located at the previous frame will be refreshed +; +; OPTIMIZATION NOTE: Shoud check that the sprite actually chanegs position. If the screen scrolles +; by +X, but the sprite moves by -X (so it's relative position is unchanged), then +; it does NOT need to be marked as dirty. stz forceSpriteFlag lda StartX @@ -169,7 +175,7 @@ _RenderSprites ; Second step is to scan the list of sprites. A sprite is either clean or dirty. If it's dirty, ; then its position had changed, so we need to add tiles to the dirty queue to make sure the -; playfield gets update. If it's clean, we can skip everything. +; playfield gets updated. If it's clean, we can skip everything. ldy #0 :loop lda _Sprites+SPRITE_STATUS,y ; If the status is zero, that's the sentinel value @@ -371,7 +377,7 @@ draw_8x16h adc #{8*SPRITE_PLANE_SPAN} tax tya - adc #{128*32} ; 32 tiles to the next verical one, each tile is 128 bytes + adc #{128*32} ; 32 tiles to the next vertical one, each tile is 128 bytes tay jmp _DrawTile8x8 @@ -586,8 +592,8 @@ _DrawTile8x8 ]line equ 0 lup 8 lda: tiledata+32+{]line*4},y - andl spritemask+{]line*256},x - stal spritemask+{]line*256},x + andl spritemask+{]line*SPRITE_PLANE_SPAN},x + stal spritemask+{]line*SPRITE_PLANE_SPAN},x ldal spritedata+{]line*SPRITE_PLANE_SPAN},x and: tiledata+32+{]line*4},y @@ -619,8 +625,8 @@ _DrawTile16x16 ]line equ 0 lup 8 lda: tiledata+32+{]line*4},y - andl spritemask+{]line*256},x - stal spritemask+{]line*256},x + andl spritemask+{]line*SPRITE_PLANE_SPAN},x + stal spritemask+{]line*SPRITE_PLANE_SPAN},x ldal spritedata+{]line*SPRITE_PLANE_SPAN},x and: tiledata+32+{]line*4},y @@ -663,8 +669,8 @@ SPRITE_ROW_STRIDE equ 8*SPRITE_PLANE_SPAN ]line equ 0 lup 8 lda: tiledata+TILE_ROW_STRIDE+32+{]line*4},y - andl spritemask+SPRITE_ROW_STRIDE+{]line*256},x - stal spritemask+SPRITE_ROW_STRIDE+{]line*256},x + andl spritemask+SPRITE_ROW_STRIDE+{]line*SPRITE_PLANE_SPAN},x + stal spritemask+SPRITE_ROW_STRIDE+{]line*SPRITE_PLANE_SPAN},x ldal spritedata+SPRITE_ROW_STRIDE+{]line*SPRITE_PLANE_SPAN},x and: tiledata+TILE_ROW_STRIDE+32+{]line*4},y @@ -717,8 +723,8 @@ _DrawTile8x8V ]line equ 0 lup 8 lda: tiledata+32+{{7-]line}*4},y - andl spritemask+{]line*256},x - stal spritemask+{]line*256},x + andl spritemask+{]line*SPRITE_PLANE_SPAN},x + stal spritemask+{]line*SPRITE_PLANE_SPAN},x ldal spritedata+{]line*SPRITE_PLANE_SPAN},x and: tiledata+32+{{7-]line}*4},y @@ -744,13 +750,20 @@ _DrawTile8x8V ; resgion to all $FFFF ; ; X = address is sprite plane -- erases an 8x8 region +_CacheSpriteBanks + lda #>spritemask + and #$FF00 + ora #^spritedata + sta SpriteBanks + rts + SPRITE_PLANE_SPAN equ 256 _EraseTileSprite phb ; Save the bank to switch to the sprite plane - pea #^spritedata - plb + pei SpriteBanks + plb ; pop the data bank (low byte) lda #0 sta: {0*SPRITE_PLANE_SPAN}+0,x @@ -770,8 +783,7 @@ _EraseTileSprite sta: {7*SPRITE_PLANE_SPAN}+0,x sta: {7*SPRITE_PLANE_SPAN}+2,x - pea #^spritemask - plb + plb ; pop the mask bank (high byte) lda #$FFFF sta: {0*SPRITE_PLANE_SPAN}+0,x @@ -791,7 +803,6 @@ _EraseTileSprite sta: {7*SPRITE_PLANE_SPAN}+0,x sta: {7*SPRITE_PLANE_SPAN}+2,x - pla plb rts diff --git a/src/Tool.s b/src/Tool.s new file mode 100644 index 0000000..c1ba0dd --- /dev/null +++ b/src/Tool.s @@ -0,0 +1,131 @@ +; Toolbox wrapper for the GTE library. Implemented as a user tool +; +; Ref: Toolbox Reference, Volume 2, Appendix A +; Ref: IIgs Tech Note #73 + +ToStrip equ $E10184 + +_CallTable + dw {_CTEnd-_CallTable}/4,0 + adrl _TSBootInit-1 + adrl _TSStartUp-1 + adrl _TSShutDown-1 + adrl _TSVersion-1 + adrl _TSReset-1 + adrl _TSStatus-1 + adrl _TSReserved-1 + adrl _TSReserved-1 + + adrl _TSSetScreenMode +_CTEnd + +; Do nothing when the tool set is installed +_TSBootInit + lda #0 + clc + rtl + +; Call the regular GTE startup function after setting the Work Area Point (WAP). The caller much provide +; one page of Bank 0 memory for the tool set's private use +; +; X = +_TSStartUp +:zpToUse equ 7 + + pea #$8000 + txa + and #$00FF + pha + + pea $0000 + lda :zpToUse+6,s + pha + _SetWAP + + jsr _CoreStartUp + +_TSShutDown + cmp #0 ; Acc is low word of the WAP (direct page) + beq :inactive + + phd + pha + pld ; Set the direct page for the toolset + + phx ; Preserve the X register + jsr _CoreShutDown ; Shut down GTE + pla + + pea $8000 + and #$00FF + pha + pea $0000 ; Set WAP to null + pea $0000 + _SetWAP + + pld ; Restore the direct page + +:inactive + lda #0 + clc + rtl + +_TSVersion + lda #$0100 ; Version 1 + sta 7,s + + lda #0 + clc + rtl + +_TSReset + lda #0 + clc + rtl + +; Check the WAP values in the A, Y registers +_TSStatus + sta 1,s + tya + ora 1,s + sta 1,s ; 0 if WAP is null, non-zero if WAP is set + + lda #0 + clc + rtl + +_TSReserved + txa + xba + ora #$00FF ; Put error code $FF in the accumulator + sec + rtl + +_TSSetScreenMode + phd ; Preserve the direct page + pha + pld + + lda 9,s + tay + lda 9,s + tax + jsr _SetScreenMode + pld + + ldx #0 ; No error + ldy #4 ; Remove the 4 input bytes + jml ToStrip + +_TSReadControl + phd ; Preserve the direct page + pha + pld + + jsr _ReadControl + sta 9,s + + pld + ldx #0 ; No error + ldy #0 ; Remove zero input bytes + jml ToStrip diff --git a/src/blitter/Template.s b/src/blitter/Template.s index cdb36b4..8dea8d2 100644 --- a/src/blitter/Template.s +++ b/src/blitter/Template.s @@ -526,11 +526,11 @@ BuildBank ; to cover the full screen vertical scrolling. ; ; The 'base' location is always assumed to be on a 4kb ($1000) boundary. We make sure that -; the code is assembled on a page boundary to help will alignment +; the code is assembled on a page boundary to help with alignment ds \,$00 ; pad to the next page boundary base -entry_1 ldx #0000 ; Used for LDA 00,x addressing -entry_2 ldy #0000 ; Used for LDA (00),y addressing +entry_1 ldx #0000 ; Used for LDA 00,x addressing (Dynamic Tiles) +entry_2 ldy #0000 ; Used for LDA (00),y addressing (Second Layer; BG1) entry_3 lda #0000 ; Sets screen address (right edge) tcs @@ -691,22 +691,17 @@ epilogue_1 tsc ; Standard Two-level Mix (23 bytes) ; ; Optimal = 18 cycles (LDA/AND/ORA/PHA/JMP) -; 16-bit write = 21 cycles -; 8-bit low = 30 cycles -; 8-bit high = 29 cycles +; 16-bit write = 20 cycles +; 8-bit low = 28 cycles +; 8-bit high = 27 cycles ; ; start lda (00),y ; 6 ; and #MASK ; 3 ; ora #DATA ; 3 = 12 cycles to load the data ; bcs alt_exit ; 2/3 ; pha ; 4 -; out brl next ; 4 Fast-path completes in 5 additional cycles -; -; alt_exit bvs r_edge ; 2/3 -; clc ; 2 -; brl l_jmp_rtn ; 3 -; r_edge rep #$41 -; brl r_jmp_rtn ; 3 +; out jmp next ; 3 Fast-path completes in 5 additional cycles +; alt_exit jmp jmp_rtn ; 3 ; ; ; For dynamic masked tiles, we re-write bytes 2 - 8 as this, which mostly @@ -716,7 +711,6 @@ epilogue_1 tsc ; start lda (00),y ; 6 ; and $80,x ; 5 ; ora $00,x ; 5 = 16 cycles to load the data -; bcc *+4 ; ; bcs alt_exit ; 2/3 ; pha ; ...