Secret sauce

This commit is contained in:
Lucas Scharenbroich 2023-05-16 12:34:18 -05:00
parent aaf70af236
commit cb13c2ae2d
15 changed files with 2199 additions and 172 deletions

View File

@ -1 +1,4 @@
SMBStart EXT ; Base address of the ROM. Should be XX/8000 in the bank the ROM is loaded into
SMBStart EXT ; Base address of the ROM. Should be XX/8000 in the bank the ROM is loaded into
NonMaskableInterrupt EXT ; Called every VBL
ExtIn EXT
ROMBase EXT

View File

@ -9,43 +9,735 @@
use GTE.Macs
use Externals.s
; Keycodes
LEFT_ARROW equ $08
RIGHT_ARROW equ $15
UP_ARROW equ $0B
DOWN_ARROW equ $0A
mx %00
; Direct page space
MyUserId equ 0
ROMStk equ 2
ROMZeroPg equ 4
LastScroll equ 6
Tmp0 equ 240
Tmp1 equ 242
Tmp2 equ 244
Tmp3 equ 246
phk
plb
sta MyUserId ; GS/OS passes the memory manager user ID for the application into the program
_MTStartUp ; GTE requires the miscellaneous toolset to be running
pea $00A0 ; Load from System:Tools
pea $0100 ; Tool160, version 1.0
_LoadOneTool
stz LastScroll
clc ; Give GTE a page of direct page memory
; The next two direct pages will be used by GTE, so get another 2 pages beyond that for the ROM. We get
; 4K of DP/Stack space by default, so there is plenty to share
tdc
adc #$0100
pha
pea $0000 ; Default fast mode
lda MyUserId ; Pass the userId for memory allocation
pha
_GTEStartUp
clc
adc #$300
sta ROMZeroPg
clc
adc #$1FF ; Stack starts at the top of the page
sta ROMStk
* ldx #SMBStart
* jsr romxfer
* ; Call the main loop 23 times
* lda #23
* :pre pha
* jsr triggerNMI
* pla
* dec
* bne :pre
* :gloop
* jsr triggerNMI
* bra :gloop
* brl Quit
lda #ENGINE_MODE_USER_TOOL ; Engine in Fast Mode as a User Tool
jsr GTEStartUp ; Load and install the GTE User Tool
; Install a VBL callback task that we will use to invoke the NMI routine in the ROM
pea vblCallback
pea #^nmiTask
pea #nmiTask
_GTESetAddress
; Install a custom sprite renderer that will read directly off of the OAM table
pea extSpriteRenderer
pea #^drawOAMSprites
pea #drawOAMSprites
_GTESetAddress
; Get the address of a low-level routine that can be used to draw a tile directly to the graphics screen
pea rawDrawTile
_GTEGetAddress
lda 1,s
sta drawTilePatch+1
lda 2,s
sta drawTilePatch+2
pla
plx
; Initialize the graphics screen playfield (256x160). The NES is 240 lines high, so 160
; is a reasonable compromise.
pea #160
pea #128
pea #200
_GTESetScreenMode
pea $0000
pea #^Greyscale
pea #Greyscale
_GTESetPalette
; Convert the CHR ROM from the cart into GTE tiles
; jsr LoadTilesFromROM
ldx #0
ldy #0
:tloop
phx
phy
lda #TileBuff
jsr ConvertROMTile
lda 1,s
pha
inc
pha
pea #^TileBuff
pea #TileBuff
_GTELoadTileSet
ply
iny
pla
clc
adc #16 ; NES tiles are 16 bytes
tax
cpx #512*16
bcc :tloop
; Put the tile set on the screen
* lda #0
* stz Tmp1
* :yloop stz Tmp0
* :xloop
* pha
* pei Tmp0
* pei Tmp1
* pha
* _GTESetTile
* pla
* inc
* inc Tmp0
* ldx Tmp0
* cpx #32
* bcc :xloop
* inc Tmp1
* ldx Tmp1
* cpx #20
* bcc :yloop
* ; Render and wait for the user to continue
* pea $0000
* _GTERender
* :wait1
* pha
* _GTEReadControl
* pla
* and #$007F
* cmp #' '
* bne :wait1
; Set an internal flag to tell the VBL interrupt handler that it is
; ok to start invoking the game logic. The ROM code has to be run
; at 60 Hz because it controls the audio. Bad audio is way worse
; than a choppy refresh rate.
;
; Call the boot code in the ROM
ldx #SMBStart
jsr romxfer
EvtLoop
:spin lda ppustatus ; Set the bit that the VBL has started
bit #$80
beq :spin
and #$FF7F
sta ppustatus
jsr triggerNMI
lda #$2000
jsr CopyNametable
lda ppuscroll+1
and #$00FF
lsr
pha
sta LastScroll
lda ppuscroll
and #$00FF
pha
_GTESetBG0Origin
pea $FFFF ; NES mode
_GTERender
pha
_GTEReadControl
pla
; Map the GTE field to the NES controller format: A-B-Select-Start-Up-Down-Left-Right
pha
and #PAD_BUTTON_A+PAD_BUTTON_B ; bits 0x200 and 0x100
lsr
lsr
sta native_joy
lda 1,s
and #$00FF
cmp #'n'
bne *+7
lda #$0020
bra :nes_merge
cmp #'m'
bne *+7
lda #$0010
bra :nes_merge
cmp #UP_ARROW
bne *+7
lda #$0008
bra :nes_merge
cmp #DOWN_ARROW
bne *+7
lda #$0004
bra :nes_merge
cmp #LEFT_ARROW
bne *+7
lda #$0002
bra :nes_merge
cmp #RIGHT_ARROW
bne :nes_done
lda #$0001
:nes_merge ora native_joy
sta native_joy
:nes_done
pla
; bit #PAD_KEY_DOWN
; bne *+5
; brl EvtLoop
and #$007F
cmp #'1' ; Copy nametable 1
bne :not_1
lda #$2000
jsr CopyNametable
brl EvtLoop
:not_1
cmp #'2'
bne :not_2
lda #$2400
jsr CopyNametable
:not_2
cmp #'s' ; next step
bne :not_n
jsr triggerNMI
:not_n
cmp #'q'
beq Exit
brl EvtLoop
Exit
_GTEShutDown
Quit
_QuitGS qtRec
qtRec adrl $0000
da $00
da $00
Greyscale dw $0000,$5555,$AAAA,$FFFF
dw $0000,$5555,$AAAA,$FFFF
dw $0000,$5555,$AAAA,$FFFF
dw $0000,$5555,$AAAA,$FFFF
; Copy the tile and attribute bytes into the GTE buffer
;
; A = Nametable address ($2000, $2400, $2800, or $2C00)
CopyNametable
lda ppuctrl
and #$0003 ; nametable select bits
xba
asl
asl
clc
adc #2*32
sta Tmp0 ; base address offset into nametable memory
; ora #$2000
; clc
; adc #PPU_MEM
; clc
; adc #2*32
; sta Tmp0 ; base address
; NES RAM $6D = page, $86 = player_x_in_page can be used to get a global position in the level, then subtracting the
; player's x coordinate will give us the global coordinate of the left edge of the screen and allow us to map between
; the GTE tile buffer and the PPU nametables
lda ppuscroll+1
lsr
lsr
lsr
and #$001F
sta Tmp1 ; starting offset
; Copy the first two rows from $2400 because they don't scroll
ldy #0
:yloop
ldx #0
cpy #2
bcs :offset
tya
clc
adc #2
asl
asl
asl
asl
asl
; lda #$0000+{2*32}
sta Tmp2
lda #0
sta Tmp3
bra :xloop
:offset
lda Tmp0 ; Get the base address for this line
ora Tmp1 ; Move over to the first horizontal tile
sta Tmp2 ; coarse x-scroll
lda Tmp1
sta Tmp3 ; Keep a separate count for the GTE tile position
:xloop
phx ; Save X and Y
phy
pei Tmp3 ; Wrap-around tile column
phy ; No vertical scroll, so screen_y = tile_y
ldx Tmp2 ; Nametable address
lda PPU_MEM+$2000,x
and #$00FF
ora #$0100
pha
; Advance to the next tile (handle nametable wrapping)
lda #$001F
and Tmp2
cmp #$001F
bne :inc_x
txa
and #$FFE0
eor #$0400
sta Tmp2
bra :x_hop
:inc_x inx
stx Tmp2
:x_hop
_GTESetTile
ply
plx
lda Tmp3
inc
cmp #41
bcc *+5
lda #0
sta Tmp3
inx
cpx #33
bcc :xloop
lda Tmp0
clc
adc #32
sta Tmp0
iny
cpy #25
bcc :yloop
rts
; Trigger an NMI in the ROM
triggerNMI
ldal ppuctrl ; If the ROM has not enabled VBL NMI, also skip
bit #$80
beq :skip
lda ppustatus ; Set the bit that the VBL has started
ora #$80
sta ppustatus
ldx #NonMaskableInterrupt
jmp romxfer
:skip rts
; Expose joypad bits from GTE to the ROM: A-B-Select-Start-Up-Down-Left-Right
native_joy ENT
db 0,0
; X = address in the rom file
; A = address to write
ConvertROMTile
DPtr equ Tmp1
MPtr equ Tmp2
sta DPtr
clc
adc #32 ; Move to the mask
sta MPtr
lda #0 ; Clear A and B
sep #$20 ; 8-bit mode
ldy #0
:loop
lda CHR_ROM,x ; Load the high bits
rol
rol
rol
rol
and #$06
sta Tmp0
lda CHR_ROM+8,x
and #$C0
lsr
lsr
lsr
ora Tmp0 ; Combine the two and create a lookup value
phx
tax
lda DLUT,x ; Look up the two, 4-bit pixel values for this quad of bits
sta (DPtr),y
lda MLUT,x
sta (MPtr),y
iny
plx
; Repeat for bits 4 & 5
ldal CHR_ROM,x ; Load the high bits
and #$30
lsr
lsr
lsr
sta Tmp0
ldal CHR_ROM+8,x
and #$30
lsr
ora Tmp0 ; Combine the two and create a lookup value
phx
tax
lda DLUT,x
sta (DPtr),y
lda MLUT,x
sta (MPtr),y
iny
plx
; Repeat for bits 2 & 3
ldal CHR_ROM,x ; Load the high bits
and #$0C
lsr
sta Tmp0
ldal CHR_ROM+8,x
and #$0C
asl
ora Tmp0 ; Combine the two and create a lookup value
phx
tax
lda DLUT,x
sta (DPtr),y
lda MLUT,x
sta (MPtr),y
iny
plx
; Repeat for bits 0 & 1
ldal CHR_ROM,x ; Load the high bits
and #$03
asl
sta Tmp0
ldal CHR_ROM+8,x
and #$03
asl
asl
asl
ora Tmp0 ; Combine the two and create a lookup value
phx
tax
lda DLUT,x
sta (DPtr),y
lda MLUT,x
sta (MPtr),y
iny
plx
inx
cpy #32
bcs :done
brl :loop
:done
rep #$20
; Flip the tile before returning
ldy #16
ldx DPtr
:rloop
lda: 0,x
jsr reverse
sta: 66,x
lda: 2,x
jsr reverse
sta: 64,x
inx
inx
inx
inx
dey
bne :rloop
rts
reverse
xba
sta Tmp0
and #$0F0F
asl
asl
asl
asl
sta Tmp1
lda Tmp0
and #$F0F0
lsr
lsr
lsr
lsr
ora Tmp1
rts
DLUT dw $00,$01,$10,$11 ; CHR_ROM[0] = xx, CHR_ROM[8] = 00
dw $02,$03,$12,$13 ; CHR_ROM[0] = xx, CHR_ROM[8] = 01
dw $20,$21,$30,$31 ; CHR_ROM[0] = xx, CHR_ROM[8] = 10
dw $22,$23,$32,$33 ; CHR_ROM[0] = xx, CHR_ROM[8] = 11
MLUT dw $FF,$F0,$0F,$00
dw $F0,$F0,$00,$00
dw $0F,$00,$0F,$00
dw $00,$00,$00,$00
; Extracted tiles
TileBuff ds 128
GTEStartUp
pha ; Save engine mode
pea $0000
_LoaderStatus
pla
pea $0000
pea $0000
pea $0000
pea $0000
pea $0000 ; result space
lda MyUserId
pha
pea #^ToolPath
pea #ToolPath
pea $0001 ; do not load into special memory
_InitialLoad
bcc *+4
brk $01
ply
pla ; Address of the loaded tool
plx
ply
ply
pea $8000 ; User toolset
pea $00A0 ; Set the tool set number
phx
pha ; Address of function pointer table
_SetTSPtr
bcc *+4
brk $02
plx ; Pop the Engine Mode value
clc ; Give GTE two pages of direct page memory
tdc
adc #$0100
pha
phx
lda MyUserId ; Pass the userId for memory allocation
pha
_GTEStartUp
bcc *+4
brk $03
rts
ToolPath str '1/Tool160'
* ; Store sprite and tile data as 0000000w wxxyyzz0 to facilitate swizzle loads
* ; sprite high priority (8-bit acc, compiled)
* ldy #PPU_DATA
* lda screen
* andl tilemask,x
* ora (palptr),y ; 512 byte lookup table per palette
* sta screen
* ; sprite low (this is just slow) ....
* lda screen
* beq empty
* ; do 4 bits to figure out a mask and then
* bit #$FF00
* ...
* ...
* ldy #PPU_DATA
* lda (palptr),y
* eor screen
* andl tilemask,x
* and bgmask
* eor screen
* sta screen
* ; tile
* ldy tiledata,x
* lda (palptr),y
* ldy tmp
* sta abs,y
* ; Custom tile renderer that swizzles the tile data based on the PPU attribute tables. This
* ; is more complicate than just combining the palette select bits with the tile index bits
* ; because the NES can have >16 colors on screen at once, we remap the possible colors
* ; onto a smaller set of indices.
* SwizzleTile
* tax
* ]line equ 0
* lup 8
* ldal tiledata+{]line*4},x ; Tile data is 00ww00xx 00yy00zz
* ora metatile ; Pre-calculated metatile mask
* and tilemask+{]line*4},x ; Set any zero indices to actual zero
* sta: $0004+{]line*$1000},y
* ldal tiledata+{]line*4}+2,x
* sta: $0001+{]line*$1000},y
* ]line equ ]line+1
* --^
* plb
* rts
; Transfer control to the ROM. This function is trampoline that is responsible for
; setting up the direct page and stack for the ROM and then passing control into
; the ROM wrapped in a JSL/RTL vector stashed in the ROM space.
;
; X = ROM Address
romxfer phb ; Save the bank and direct page
phd
tsc
sta StkSave+1 ; Save the current stack in the main program
pea #^ExtIn ; Set the bank to the ROM
plb
lda ROMStk ; Set the ROM stack address
tcs
lda ROMZeroPg ; Set the ROM zero page
tcd
jml ExtIn
ExtRtn ENT
tsx ; Copy the stack address returned by the emulator
StkSave lda #$0000
tcs
pld
plb
stx ROMStk ; Keep an updated copy of the stack address
rts
; VBL Interrupt task (called in native 8-bit mode)
mx %11
nmiTask
ldal ppustatus ; Set the bit that the VBL has started
ora #$80
stal ppustatus
ldal ppuctrl
bit #$80 ; Should an NMI be generated with the VBL?
beq :skip
php
; jsr triggerNMI
plp
:skip
rtl
mx %00
put palette.s
put ppu.s
ds \,$00 ; pad to the next page boundary
PPU_MEM
CHR_ROM put chr2.s ; 8K of CHR-ROM at PPU memory $0000 - $2000
PPU_NT ds $2000 ; Nametable memory from $2000 - $3000, $3F00 - $3F14 is palette RAM
PPU_OAM ds 256 ; 256 bytes of separate OAM RAM

View File

@ -14,3 +14,4 @@ REM Cadius does not overwrite files, so clear the root folder first
REM Now copy files and folders as needed
%CADIUS% ADDFILE %IMAGE% %FOLDER% .\SuperMarioGS
%CADIUS% ADDFILE %IMAGE% %FOLDER% ..\..\src\Tool160

512
demos/smb/chr2.s Normal file
View File

@ -0,0 +1,512 @@
db $03,$0F,$1F,$1F,$1C,$24,$26,$66,$00,$00,$00,$00,$1F,$3F,$3F,$7F
db $E0,$C0,$80,$FC,$80,$C0,$00,$20,$00,$20,$60,$00,$F0,$FC,$FE,$FE
db $60,$70,$18,$07,$0F,$1F,$3F,$7F,$7F,$7F,$1F,$07,$00,$1E,$3F,$7F
db $FC,$7C,$00,$00,$E0,$F0,$F8,$F8,$FC,$FC,$F8,$C0,$C2,$67,$2F,$37
db $7F,$7F,$FF,$FF,$07,$07,$0F,$0F,$7F,$7E,$FC,$F0,$F8,$F8,$F0,$70
db $FD,$FE,$B4,$F8,$F8,$F9,$FB,$FF,$37,$36,$5C,$00,$00,$01,$03,$1F
db $1F,$3F,$FF,$FF,$FC,$70,$70,$38,$08,$24,$E3,$F0,$F8,$70,$70,$38
db $FF,$FF,$FF,$1F,$00,$00,$00,$00,$1F,$1F,$1F,$1F,$00,$00,$00,$00
db $00,$00,$01,$07,$0F,$0F,$0E,$12,$00,$00,$00,$00,$00,$00,$0F,$1F
db $00,$00,$F0,$E0,$C0,$FE,$40,$60,$00,$00,$00,$10,$30,$00,$F8,$FE
db $13,$33,$30,$18,$04,$0F,$1F,$1F,$1F,$3F,$3F,$1F,$07,$08,$17,$17
db $00,$10,$7E,$3E,$00,$00,$C0,$E0,$FF,$FF,$FE,$FE,$FC,$E0,$40,$A0
db $3F,$3F,$3F,$1F,$1F,$1F,$1F,$1F,$37,$27,$23,$03,$01,$00,$00,$00
db $F0,$F0,$F0,$F8,$F8,$F8,$F8,$F8,$CC,$FF,$FF,$FF,$FF,$70,$00,$08
db $FF,$FF,$FF,$FE,$F0,$C0,$80,$00,$F0,$F0,$F0,$F0,$F0,$C0,$80,$00
db $FC,$FC,$F8,$78,$78,$78,$7E,$7E,$10,$60,$80,$00,$78,$78,$7E,$7E
db $00,$03,$0F,$1F,$1F,$1C,$24,$26,$00,$00,$00,$00,$00,$1F,$3F,$3F
db $00,$E0,$C0,$80,$FC,$80,$C0,$00,$00,$00,$20,$60,$00,$F0,$FC,$FE
db $66,$60,$30,$18,$0F,$1F,$3F,$3F,$7F,$7F,$3F,$1F,$00,$16,$2F,$2F
db $20,$FC,$7C,$00,$00,$E0,$E0,$F0,$FE,$FC,$FC,$F8,$C0,$60,$20,$30
db $3F,$3F,$3F,$3F,$3F,$3F,$3F,$1F,$2F,$2F,$2F,$0F,$07,$03,$00,$00
db $F0,$90,$00,$08,$0C,$1C,$FC,$F8,$10,$F0,$F0,$F0,$F0,$E0,$C0,$E0
db $0F,$0F,$07,$07,$07,$0F,$0F,$03,$01,$03,$01,$04,$07,$0F,$0F,$03
db $F8,$F0,$E0,$F0,$B0,$80,$E0,$E0,$F8,$F0,$E0,$70,$B0,$80,$E0,$E0
db $03,$3F,$7F,$19,$09,$09,$28,$5C,$00,$30,$70,$7F,$FF,$FF,$F7,$F3
db $F8,$E0,$E0,$FC,$26,$30,$80,$10,$00,$18,$10,$00,$F8,$F8,$FE,$FF
db $3E,$1E,$3F,$38,$30,$30,$00,$3A,$E7,$0F,$0F,$1F,$1F,$1F,$0F,$07
db $78,$1E,$80,$FE,$7E,$7E,$7F,$7F,$FF,$FE,$FC,$C6,$8E,$EE,$FF,$FF
db $3C,$3F,$1F,$0F,$07,$3F,$21,$20,$03,$00,$00,$0E,$07,$3F,$3F,$3F
db $FF,$FF,$FF,$FE,$FE,$FE,$FC,$70,$FF,$7F,$3F,$0E,$C0,$C0,$E0,$E0
db $0F,$9F,$CF,$FF,$7F,$3F,$1E,$0E,$00,$80,$C8,$FE,$7F,$3F,$1E,$0E
db $20,$C0,$80,$80,$00,$00,$00,$00,$E0,$00,$00,$00,$00,$00,$00,$00
db $00,$00,$03,$0F,$1F,$1F,$1C,$24,$00,$00,$00,$00,$00,$00,$1F,$3F
db $00,$04,$E6,$E0,$FF,$FF,$8F,$83,$0E,$1F,$1F,$1F,$1F,$03,$FF,$FF
db $26,$26,$60,$78,$18,$0F,$7F,$FF,$3F,$3F,$7F,$7F,$1F,$00,$7E,$FF
db $01,$21,$FE,$7A,$06,$FE,$FC,$FC,$FF,$FF,$FE,$FE,$FE,$DE,$5C,$6C
db $FF,$CF,$87,$07,$07,$0F,$1F,$1F,$FF,$FF,$FE,$FC,$F8,$B0,$60,$00
db $F8,$F8,$F0,$B8,$F8,$F9,$FB,$FF,$28,$30,$18,$40,$00,$01,$03,$0F
db $1F,$FF,$FF,$FF,$FF,$FE,$C0,$80,$10,$EC,$E3,$E0,$E0,$E0,$C0,$80
db $FF,$FF,$FF,$3F,$00,$00,$00,$00,$0F,$0F,$0F,$0F,$00,$00,$00,$00
db $13,$33,$30,$18,$04,$0F,$1F,$1F,$1F,$3F,$3F,$1F,$07,$09,$13,$17
db $00,$10,$7E,$30,$E0,$F0,$F0,$E0,$FF,$FF,$FE,$FF,$FE,$FC,$F8,$E0
db $1F,$1F,$0F,$0F,$0F,$1F,$1F,$1F,$17,$17,$03,$00,$00,$00,$00,$00
db $F0,$F0,$F8,$F8,$B8,$F8,$F8,$F8,$D0,$90,$18,$08,$40,$00,$00,$00
db $3F,$FF,$FF,$FF,$F6,$C6,$84,$00,$30,$F0,$F0,$F1,$F6,$C6,$84,$00
db $F0,$E0,$80,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $1F,$1F,$3F,$3F,$1F,$0F,$0F,$1F,$1F,$1F,$3F,$3E,$7C,$78,$F0,$E0
db $F0,$F0,$F8,$F8,$B8,$F8,$F8,$F0,$B0,$90,$18,$08,$40,$00,$00,$00
db $E0,$F0,$F0,$F0,$F0,$F0,$F8,$F0,$C0,$E0,$FC,$FE,$FF,$7F,$03,$00
db $1F,$1F,$1F,$3F,$3E,$3C,$38,$18,$00,$00,$10,$38,$3E,$3C,$38,$18
db $00,$03,$07,$07,$0A,$0B,$0C,$00,$00,$00,$00,$07,$0F,$0F,$0F,$03
db $00,$E0,$FC,$20,$20,$10,$3C,$00,$00,$00,$00,$F0,$FC,$FE,$FC,$F8
db $07,$07,$07,$1F,$1F,$3E,$21,$01,$07,$0F,$1B,$18,$10,$30,$21,$01
db $E0,$E0,$E0,$F0,$F0,$E0,$C0,$E0,$A8,$FC,$F8,$00,$00,$00,$C0,$E0
db $07,$0F,$0E,$14,$16,$18,$00,$3F,$00,$00,$0F,$1F,$1F,$1F,$07,$3C
db $C0,$F8,$40,$40,$20,$78,$00,$C0,$00,$00,$E0,$F8,$FC,$F8,$F0,$C0
db $3F,$0E,$0F,$1F,$3F,$7C,$70,$38,$FC,$ED,$C0,$00,$00,$60,$70,$38
db $F0,$F8,$E4,$FC,$FC,$7C,$00,$00,$7E,$1E,$04,$0C,$0C,$0C,$00,$00
db $07,$0F,$0E,$14,$16,$18,$00,$0F,$00,$00,$0F,$1F,$1F,$1F,$07,$0D
db $1F,$1F,$1F,$1C,$0C,$07,$07,$07,$1E,$1C,$1E,$0F,$07,$00,$07,$07
db $E0,$60,$F0,$70,$E0,$E0,$F0,$80,$60,$90,$00,$80,$00,$E0,$F0,$80
db $07,$1F,$3F,$12,$13,$08,$1F,$31,$00,$10,$3F,$7F,$7F,$3F,$03,$0F
db $C0,$F0,$40,$00,$30,$18,$C0,$F8,$00,$00,$E0,$F8,$FC,$F8,$B0,$38
db $31,$39,$1F,$1F,$0F,$5F,$7E,$3C,$1F,$07,$00,$0E,$0F,$53,$7C,$3C
db $F8,$F8,$F0,$E0,$E0,$C0,$00,$00,$F8,$F8,$F0,$00,$00,$80,$00,$00
db $00,$E0,$FC,$27,$27,$11,$3E,$04,$07,$07,$03,$F7,$FF,$FF,$FE,$FC
db $3F,$7F,$3F,$0F,$1F,$3F,$7F,$4F,$3E,$7F,$FF,$E2,$50,$38,$70,$40
db $F8,$F9,$F9,$B7,$FF,$FF,$E0,$00,$E8,$71,$01,$4B,$03,$03,$00,$00
db $07,$07,$0F,$3F,$3F,$3F,$26,$04,$05,$03,$01,$30,$30,$30,$26,$04
db $F0,$F0,$F0,$E0,$C0,$00,$00,$00,$FE,$FC,$E0,$00,$00,$00,$00,$00
db $07,$07,$0F,$1F,$3F,$0F,$1C,$18,$05,$03,$01,$10,$30,$0C,$1C,$18
db $E0,$E0,$E0,$E0,$C0,$80,$00,$00,$C0,$E0,$F0,$78,$18,$08,$00,$00
db $07,$0F,$1F,$0F,$3F,$0F,$1C,$18,$07,$0F,$3E,$7C,$30,$0C,$1C,$18
db $E0,$E0,$E0,$40,$C0,$80,$00,$00,$60,$60,$60,$80,$00,$00,$00,$00
db $7F,$FF,$FF,$FB,$0F,$0F,$0F,$1F,$73,$F3,$F0,$F4,$F0,$F0,$70,$60
db $3F,$7E,$7C,$7C,$3C,$3C,$FC,$FC,$00,$00,$00,$00,$3C,$3C,$FC,$FC
db $60,$70,$18,$08,$0F,$1F,$3F,$7F,$7F,$7F,$1F,$07,$0B,$1B,$3B,$7B
db $FC,$7C,$00,$20,$F0,$F8,$FC,$FE,$FC,$FC,$F8,$E0,$D0,$D8,$DC,$DE
db $0B,$0F,$1F,$1E,$3C,$3C,$3C,$7C,$C4,$E0,$E0,$40,$00,$3C,$3C,$7C
db $1F,$3F,$0D,$07,$0F,$0E,$1C,$3C,$1D,$3C,$3A,$38,$30,$00,$1C,$3C
db $00,$00,$00,$00,$00,$00,$00,$00,$22,$55,$55,$55,$55,$55,$77,$22
db $00,$07,$1F,$FF,$07,$1F,$0F,$06,$00,$00,$00,$00,$00,$00,$00,$00
db $3F,$FF,$FF,$FF,$FF,$FF,$FB,$76,$00,$00,$CF,$07,$7F,$00,$00,$00
db $20,$F8,$FF,$C3,$FD,$FE,$F0,$40,$00,$00,$3C,$FC,$FE,$E0,$00,$00
db $40,$E0,$40,$40,$41,$41,$4F,$47,$40,$E0,$40,$3F,$3E,$3E,$30,$38
db $00,$00,$00,$00,$00,$00,$E0,$C0,$00,$00,$00,$F8,$F8,$F8,$18,$38
db $43,$46,$44,$40,$40,$40,$40,$40,$3C,$39,$3B,$3F,$00,$00,$00,$00
db $80,$C0,$40,$00,$00,$00,$00,$00,$78,$38,$B8,$F8,$00,$00,$00,$00
db $31,$30,$38,$7C,$7F,$FF,$FF,$FB,$3F,$3F,$0F,$77,$77,$F7,$F7,$F7
db $10,$7E,$3E,$00,$1E,$FE,$FF,$FF,$FF,$FE,$FE,$FE,$FA,$FA,$F3,$E7
db $FF,$FF,$E3,$C3,$87,$48,$3C,$FC,$F0,$F8,$FC,$7C,$78,$38,$3C,$FC
db $00,$FF,$C3,$83,$83,$FF,$FF,$FF,$FF,$00,$C3,$81,$81,$C3,$FF,$00
db $1F,$1F,$0F,$07,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $F0,$FB,$FF,$FF,$FE,$3E,$0C,$04,$00,$0B,$1F,$1F,$1E,$3E,$0C,$04
db $1F,$1F,$0F,$0F,$07,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $FB,$FF,$FF,$FF,$FF,$00,$00,$00,$03,$0F,$0F,$0F,$0F,$00,$00,$00
db $00,$18,$3C,$7E,$6E,$DF,$DF,$DF,$00,$18,$3C,$7E,$76,$FB,$FB,$FB
db $00,$18,$18,$3C,$3C,$3C,$3C,$1C,$00,$10,$10,$20,$20,$20,$20,$20
db $00,$08,$08,$08,$08,$08,$08,$00,$00,$08,$08,$08,$08,$08,$08,$08
db $00,$08,$08,$04,$04,$04,$04,$04,$00,$10,$10,$38,$38,$38,$38,$38
db $3C,$7E,$77,$FB,$9F,$5F,$8E,$20,$00,$18,$3C,$0E,$0E,$04,$00,$00
db $5C,$2E,$8F,$3F,$7B,$77,$7E,$3C,$00,$00,$04,$06,$1E,$3C,$18,$00
db $13,$4F,$3F,$BF,$3F,$7A,$F8,$F8,$00,$00,$01,$0A,$17,$0F,$2F,$1F
db $00,$08,$05,$0F,$2F,$1D,$1C,$3C,$00,$00,$00,$00,$05,$07,$0F,$07
db $00,$00,$00,$00,$02,$0B,$07,$0F,$00,$00,$00,$00,$00,$00,$01,$03
db $00,$00,$00,$00,$00,$08,$04,$04,$00,$60,$F0,$F8,$7C,$3E,$7E,$7F
db $02,$02,$02,$05,$71,$7F,$7F,$7F,$3F,$5F,$7F,$3E,$0E,$0A,$51,$20
db $00,$00,$00,$00,$00,$00,$00,$04,$00,$00,$00,$00,$00,$00,$0E,$1F
db $02,$02,$00,$01,$13,$3F,$7F,$7F,$3F,$7F,$7F,$FE,$EC,$CA,$51,$20
db $00,$40,$60,$70,$73,$27,$0F,$1F,$00,$40,$63,$77,$7C,$38,$F8,$E4
db $00,$00,$00,$00,$03,$07,$0F,$1F,$00,$00,$03,$07,$0C,$18,$F8,$E4
db $7F,$7F,$3F,$3F,$1F,$1F,$0F,$07,$03,$44,$28,$10,$08,$04,$03,$04
db $03,$07,$0F,$1F,$3F,$77,$77,$F5,$03,$07,$0F,$1F,$27,$7B,$78,$FB
db $C0,$E0,$F0,$F8,$FC,$EE,$EE,$AF,$C0,$E0,$F0,$F8,$E4,$DE,$1E,$DF
db $F1,$FF,$78,$00,$00,$18,$1C,$0E,$FF,$FF,$7F,$0F,$0F,$07,$03,$00
db $8F,$FF,$1E,$00,$0C,$3E,$7E,$7C,$FF,$FF,$FE,$F0,$F0,$C0,$80,$00
db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$18,$24,$24,$18,$00,$00
db $00,$02,$41,$41,$61,$33,$06,$3C,$3C,$7E,$FF,$FF,$FF,$FF,$7E,$3C
db $03,$07,$0F,$1F,$3F,$7F,$7F,$FF,$03,$07,$0F,$1F,$3F,$63,$41,$C1
db $C0,$E0,$F0,$F8,$FC,$FE,$FE,$FF,$C0,$80,$00,$00,$8C,$FE,$FE,$F3
db $FF,$FF,$FF,$78,$00,$00,$00,$00,$C1,$E3,$FF,$47,$0F,$0F,$0F,$07
db $FF,$FF,$FF,$1E,$00,$20,$20,$40,$F1,$F9,$FF,$E2,$F0,$F0,$F0,$E0
db $16,$1F,$3F,$7F,$3D,$1D,$3F,$1F,$16,$1F,$00,$00,$05,$0D,$3F,$1F
db $80,$80,$C0,$E0,$F0,$F0,$F0,$F8,$80,$80,$00,$00,$00,$A0,$A0,$E0
db $3C,$FA,$B1,$72,$F2,$DB,$DF,$5F,$00,$04,$4E,$8C,$0C,$7F,$FF,$FF
db $00,$00,$00,$01,$01,$01,$06,$1E,$00,$00,$00,$00,$00,$00,$01,$01
db $00,$00,$00,$00,$00,$00,$00,$00,$FF,$7F,$3F,$1F,$0F,$07,$03,$01
db $00,$7C,$D6,$92,$BA,$EE,$FE,$38,$FF,$83,$29,$6D,$45,$11,$01,$C7
db $00,$15,$3F,$62,$5F,$FF,$9F,$7D,$08,$08,$02,$1F,$22,$02,$02,$00
db $00,$00,$00,$00,$00,$00,$00,$00,$08,$08,$08,$08,$08,$08,$08,$08
db $2F,$1E,$2F,$2F,$2F,$15,$0D,$0E,$10,$1E,$10,$50,$10,$08,$00,$00
db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FE,$00,$00,$00,$00
db $1C,$3E,$7F,$FF,$FF,$FE,$7C,$38,$1C,$2A,$77,$EE,$DD,$AA,$74,$28
db $00,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FE,$FE,$00,$EF,$EF,$EF,$00
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FE,$FE,$FE,$00,$EF,$EF,$EF,$00
db $7F,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$00,$7F,$5F,$7F,$7F,$7F,$7F,$7F
db $68,$4E,$E0,$E0,$E0,$F0,$F8,$FC,$B8,$9E,$80,$C0,$E0,$F0,$F8,$7C
db $3F,$5C,$39,$3B,$BB,$F9,$FC,$FE,$00,$23,$57,$4F,$57,$27,$C3,$21
db $C0,$F0,$F0,$F0,$F0,$E0,$C0,$00,$00,$30,$70,$70,$F0,$E0,$C0,$00
db $FE,$FC,$61,$0F,$FF,$FE,$F0,$E0,$13,$0F,$1E,$F0,$FC,$F8,$F0,$E0
db $6E,$40,$E0,$E0,$E0,$E0,$E0,$C0,$BE,$90,$80,$C0,$C0,$80,$00,$00
db $01,$01,$03,$03,$07,$7F,$7F,$3F,$01,$01,$03,$03,$07,$7F,$7D,$3D
db $06,$07,$3F,$3C,$19,$7B,$7F,$3F,$06,$04,$30,$23,$06,$64,$60,$00
db $3F,$7F,$7F,$1F,$3F,$3F,$07,$06,$00,$60,$60,$00,$20,$30,$04,$06
db $03,$07,$0F,$0F,$0F,$0F,$07,$03,$00,$01,$01,$00,$00,$00,$00,$00
db $F8,$F8,$F8,$A0,$E1,$FF,$FF,$FF,$FE,$FF,$FF,$40,$01,$03,$03,$03
db $0F,$0F,$0F,$1F,$1F,$1F,$0F,$07,$01,$01,$00,$00,$00,$00,$00,$00
db $E0,$F8,$F8,$F8,$FF,$FE,$F0,$C0,$E0,$FE,$FF,$7F,$03,$02,$00,$00
db $01,$0F,$0F,$1F,$39,$33,$37,$7F,$01,$0D,$08,$00,$36,$2C,$08,$60
db $7F,$3F,$3F,$3F,$1F,$0F,$0F,$01,$60,$00,$20,$30,$00,$08,$0D,$01
db $00,$00,$03,$03,$47,$67,$77,$77,$01,$01,$03,$43,$67,$77,$7B,$78
db $00,$00,$00,$00,$88,$98,$F8,$F0,$00,$00,$80,$84,$CC,$DC,$BC,$3C
db $7E,$7F,$FF,$1F,$07,$30,$1C,$0C,$33,$07,$07,$E3,$38,$3F,$1C,$0C
db $7E,$38,$F6,$ED,$DF,$38,$70,$60,$98,$C7,$C8,$92,$30,$F8,$70,$60
db $00,$00,$00,$03,$03,$47,$67,$77,$00,$01,$01,$03,$43,$67,$77,$7B
db $00,$00,$00,$00,$00,$88,$98,$F8,$00,$00,$00,$80,$84,$CC,$DC,$BC
db $77,$7E,$7F,$FF,$1F,$07,$70,$F0,$78,$33,$07,$07,$E3,$38,$7F,$F0
db $F0,$7E,$38,$F6,$ED,$DF,$38,$3C,$3C,$98,$C7,$C8,$92,$30,$F8,$3C
db $03,$07,$0A,$1A,$1C,$1E,$0B,$08,$00,$10,$7F,$7F,$7F,$1F,$0F,$0F
db $1C,$3F,$3F,$3D,$3F,$1F,$00,$00,$03,$33,$39,$3A,$38,$18,$00,$00
db $00,$00,$04,$4C,$4E,$4E,$46,$6F,$10,$38,$3C,$74,$76,$76,$7E,$7D
db $00,$1F,$3F,$3F,$4F,$5F,$7F,$7F,$00,$00,$11,$0A,$34,$2A,$51,$20
db $7F,$67,$A3,$B0,$D8,$DE,$DC,$C8,$7F,$67,$63,$70,$38,$3E,$7C,$B8
db $7F,$7F,$7F,$1F,$47,$70,$70,$39,$51,$0A,$04,$EA,$79,$7F,$70,$39
db $E8,$E8,$E0,$C0,$10,$70,$E0,$C0,$58,$38,$10,$30,$F0,$F0,$E0,$C0
db $00,$00,$00,$20,$66,$66,$66,$62,$00,$08,$1C,$3C,$7A,$7A,$7A,$7E
db $00,$00,$1F,$3F,$7F,$4F,$5F,$7F,$00,$00,$00,$11,$0A,$34,$2A,$51
db $77,$7F,$3F,$B7,$B3,$DB,$DA,$D8,$7F,$7D,$3F,$37,$33,$3B,$3A,$78
db $7F,$7F,$7F,$7F,$1F,$07,$70,$F0,$20,$51,$0A,$04,$EA,$39,$7F,$F0
db $CC,$E8,$E8,$E0,$C0,$18,$7C,$3E,$BC,$58,$38,$10,$30,$F8,$FC,$3E
db $03,$0F,$1F,$3F,$3B,$3F,$7F,$7F,$00,$00,$00,$06,$0E,$0C,$00,$00
db $80,$F0,$F8,$FC,$FE,$FE,$FF,$FE,$00,$00,$00,$00,$00,$00,$0F,$18
db $7F,$7F,$7F,$7F,$FF,$0F,$03,$00,$00,$00,$00,$00,$F8,$3E,$3B,$18
db $FE,$FB,$FF,$FF,$F6,$E0,$C0,$00,$10,$14,$10,$10,$38,$78,$F8,$30
db $00,$03,$0F,$1F,$3F,$3B,$3F,$7F,$00,$00,$00,$00,$06,$0E,$0C,$00
db $00,$C0,$F0,$F8,$FC,$FE,$FE,$FF,$00,$00,$00,$00,$00,$00,$00,$0F
db $7F,$7F,$7F,$7F,$7F,$FF,$0F,$03,$00,$00,$00,$00,$00,$F8,$7E,$F3
db $FE,$FE,$FB,$FF,$FF,$F6,$E0,$C0,$18,$10,$14,$10,$10,$38,$7C,$DE
db $00,$01,$01,$01,$01,$00,$00,$08,$00,$0D,$1E,$1E,$1E,$1F,$0F,$07
db $78,$F0,$F8,$E4,$C0,$CA,$CA,$C0,$78,$F0,$00,$1A,$3F,$35,$35,$3F
db $0F,$1F,$9F,$FF,$FF,$7F,$74,$20,$00,$00,$80,$E0,$E0,$70,$73,$21
db $E4,$FF,$FE,$FC,$9C,$1E,$00,$00,$1A,$07,$0C,$18,$78,$FE,$FC,$F0
db $00,$01,$03,$03,$07,$03,$01,$00,$00,$01,$02,$00,$38,$7C,$7E,$3F
db $00,$5F,$7F,$7F,$3F,$3F,$14,$00,$3F,$40,$60,$60,$20,$30,$13,$01
db $C0,$E0,$F0,$30,$38,$3C,$3C,$FC,$C0,$E0,$30,$D0,$D0,$D0,$D0,$00
db $07,$0F,$1F,$22,$20,$25,$25,$1F,$07,$0F,$02,$1D,$1F,$1A,$1A,$02
db $FE,$FE,$7E,$3A,$02,$01,$41,$41,$38,$7C,$FC,$FC,$FC,$FE,$BE,$BE
db $1F,$3F,$7E,$5C,$40,$80,$82,$82,$1C,$3E,$3F,$3F,$3F,$7F,$7D,$7D
db $82,$80,$A0,$44,$43,$40,$21,$1E,$7D,$7F,$5F,$3B,$3C,$3F,$1E,$00
db $1C,$3F,$3E,$3C,$40,$80,$82,$82,$1C,$3E,$3F,$1F,$3F,$7F,$7D,$7D
db $00,$00,$80,$80,$92,$9D,$C7,$EF,$00,$00,$00,$60,$62,$65,$3F,$1F
db $00,$23,$33,$3F,$3F,$7F,$7F,$7F,$70,$3C,$3C,$18,$00,$00,$02,$07
db $FE,$F8,$A0,$00,$00,$00,$80,$80,$CF,$7A,$5A,$10,$00,$00,$C0,$80
db $7E,$7F,$7D,$3F,$1E,$8F,$8F,$19,$85,$84,$86,$C6,$E7,$73,$73,$E1
db $E0,$0E,$73,$F3,$F9,$F9,$F8,$70,$80,$4E,$77,$F3,$FB,$F9,$FA,$78
db $0E,$66,$E2,$F6,$FF,$FF,$1F,$98,$11,$39,$7D,$39,$00,$00,$E0,$E7
db $00,$00,$00,$04,$0F,$0F,$1F,$07,$00,$00,$07,$07,$16,$10,$00,$38
db $F3,$E7,$EE,$EC,$CD,$CF,$CF,$DF,$CF,$1F,$17,$10,$33,$30,$30,$20
db $27,$3F,$3F,$78,$3C,$1F,$1F,$73,$38,$30,$40,$C7,$07,$66,$E0,$6C
db $9F,$3E,$7C,$FC,$F8,$F8,$C0,$40,$60,$C0,$80,$04,$9E,$FF,$F0,$F8
db $7F,$7E,$78,$01,$07,$1F,$3C,$7C,$24,$01,$07,$FE,$FF,$7F,$3F,$7F
db $FC,$F8,$A0,$FE,$FC,$F0,$80,$00,$CF,$7A,$0A,$FE,$FC,$00,$00,$00
db $7E,$7F,$7F,$3F,$1F,$8F,$8F,$18,$85,$86,$83,$C3,$E1,$70,$70,$E0
db $9F,$3E,$7C,$F8,$F8,$3C,$18,$F8,$60,$C0,$80,$00,$98,$FC,$FE,$FF
db $7F,$7F,$78,$01,$07,$13,$F1,$03,$24,$00,$07,$FE,$FF,$7F,$FF,$03
db $00,$00,$1C,$1D,$1B,$C3,$E3,$E1,$03,$0F,$23,$62,$64,$3C,$1C,$1E
db $E0,$CD,$1D,$4F,$EE,$FF,$3F,$3F,$1F,$3D,$6D,$4F,$EE,$F3,$20,$03
db $3F,$3F,$00,$00,$70,$B8,$FC,$FC,$07,$07,$1F,$3F,$0F,$47,$03,$00
db $07,$0F,$1F,$3F,$3E,$7C,$78,$78,$00,$00,$03,$07,$0F,$0F,$1F,$1F
db $3F,$5C,$39,$3B,$BF,$FF,$FE,$FE,$00,$23,$57,$4F,$57,$2F,$DF,$21
db $C0,$C0,$80,$80,$80,$80,$00,$00,$00,$00,$00,$00,$80,$80,$00,$00
db $FE,$FC,$61,$0F,$7F,$3F,$1F,$1E,$23,$0F,$1E,$F0,$1C,$3F,$1F,$1E
db $F0,$78,$E4,$C8,$CC,$BE,$BE,$3E,$00,$80,$18,$30,$34,$FE,$FE,$FE
db $00,$01,$00,$07,$07,$07,$07,$1F,$00,$00,$01,$04,$06,$06,$07,$07
db $00,$00,$0F,$3F,$3F,$0F,$00,$00,$0F,$3F,$7F,$F8,$F8,$7F,$3F,$0F
db $78,$7C,$7E,$7F,$3F,$3F,$1B,$09,$1F,$1F,$1F,$0B,$01,$01,$00,$00
db $0C,$00,$00,$00,$07,$7F,$7C,$00,$03,$1F,$3F,$3F,$78,$00,$03,$FF
db $01,$E1,$71,$79,$3D,$3D,$1F,$03,$00,$00,$00,$00,$00,$00,$00,$00
db $3F,$3F,$1F,$1B,$36,$30,$7F,$3F,$23,$27,$1F,$07,$0F,$1F,$7F,$3F
db $F8,$F8,$F8,$B8,$18,$D8,$D8,$B8,$E0,$80,$80,$40,$E0,$E0,$E0,$C0
db $01,$02,$04,$04,$08,$08,$10,$10,$03,$07,$0F,$1F,$3F,$7F,$FF,$1F
db $00,$0F,$13,$0D,$0D,$13,$0C,$20,$1F,$10,$0C,$12,$12,$2C,$3F,$3F
db $00,$24,$00,$24,$00,$04,$00,$00,$37,$36,$36,$36,$16,$16,$12,$02
db $0F,$41,$00,$88,$00,$44,$00,$00,$10,$7E,$FF,$FF,$F6,$76,$3A,$1A
db $38,$7C,$FE,$FE,$3B,$03,$03,$03,$00,$00,$38,$04,$00,$00,$00,$00
db $03,$33,$7B,$7F,$FF,$FB,$03,$03,$00,$00,$00,$38,$40,$00,$00,$00
db $DC,$C0,$E0,$E0,$E0,$E0,$E0,$C0,$FC,$A0,$80,$80,$00,$00,$00,$00
db $3F,$5F,$3F,$3F,$BB,$F8,$FE,$FE,$07,$27,$57,$4F,$57,$27,$C1,$21
db $1F,$0F,$0F,$1F,$1F,$1E,$38,$30,$1D,$0F,$0F,$1F,$1F,$1E,$38,$30
db $00,$20,$60,$60,$70,$F0,$F8,$F8,$00,$00,$38,$10,$4C,$18,$86,$24
db $F8,$FC,$FC,$7E,$7E,$3E,$1F,$07,$00,$42,$0A,$40,$10,$02,$08,$02
db $00,$C0,$70,$B8,$F4,$F2,$F5,$7B,$00,$00,$80,$40,$08,$0C,$0A,$84
db $00,$DF,$10,$FF,$DF,$FF,$FF,$F9,$00,$00,$CF,$20,$20,$20,$26,$2E
db $1F,$1F,$3E,$FC,$F8,$F0,$C0,$00,$E0,$E0,$C0,$00,$00,$00,$00,$00
db $F8,$FC,$FE,$FF,$FF,$DF,$DF,$00,$2F,$23,$21,$20,$20,$00,$00,$00
db $C1,$F1,$79,$7D,$3D,$3F,$1F,$03,$C1,$B1,$59,$6D,$35,$3B,$1F,$03
db $02,$06,$0E,$0E,$1E,$1E,$3E,$3E,$00,$02,$00,$08,$02,$00,$28,$00
db $3E,$3E,$3E,$3E,$1E,$1E,$0E,$02,$04,$10,$02,$10,$04,$00,$0A,$00
db $C1,$F1,$79,$7D,$3D,$3F,$1F,$03,$C1,$B1,$59,$6D,$35,$3B,$1F,$03
db $7C,$00,$00,$FF,$C3,$7F,$1F,$03,$00,$0F,$1F,$FF,$FC,$63,$1F,$03
db $FF,$FF,$7C,$00,$00,$7C,$FF,$FF,$00,$00,$FE,$C6,$C6,$FE,$00,$00
db $FF,$FF,$00,$04,$0C,$18,$30,$00,$00,$00,$06,$06,$0C,$18,$70,$60
db $FF,$FF,$00,$04,$04,$04,$08,$08,$00,$00,$06,$06,$04,$04,$08,$08
db $08,$10,$10,$00,$00,$10,$10,$08,$08,$10,$30,$30,$30,$30,$10,$08
db $7F,$3F,$3F,$3E,$1F,$0F,$03,$00,$00,$00,$01,$03,$01,$00,$00,$00
db $03,$0F,$FF,$7F,$7F,$7F,$7F,$7F,$03,$0E,$F8,$00,$00,$00,$00,$00
db $00,$00,$00,$00,$00,$00,$00,$00,$22,$65,$25,$25,$25,$25,$77,$72
db $00,$00,$00,$00,$00,$00,$00,$00,$62,$95,$15,$25,$45,$85,$F7,$F2
db $00,$00,$00,$00,$00,$00,$00,$00,$A2,$A5,$A5,$A5,$F5,$F5,$27,$22
db $00,$00,$00,$00,$00,$00,$00,$00,$F2,$85,$85,$E5,$15,$15,$F7,$E2
db $00,$00,$00,$00,$00,$00,$00,$00,$62,$95,$55,$65,$B5,$95,$97,$62
db $00,$00,$00,$00,$00,$00,$00,$00,$20,$50,$50,$50,$50,$50,$70,$20
db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $00,$00,$00,$00,$00,$00,$00,$00,$66,$E6,$66,$66,$66,$67,$F3,$00
db $00,$00,$00,$00,$00,$00,$00,$00,$5E,$59,$59,$59,$5E,$D8,$98,$00
db $00,$00,$00,$00,$00,$7C,$38,$00,$00,$00,$00,$00,$00,$04,$08,$00
db $38,$4C,$C6,$C6,$C6,$64,$38,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $18,$38,$18,$18,$18,$18,$7E,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $7C,$C6,$0E,$3C,$78,$E0,$FE,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $7E,$0C,$18,$3C,$06,$C6,$7C,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $1C,$3C,$6C,$CC,$FE,$0C,$0C,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $FC,$C0,$FC,$06,$06,$C6,$7C,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $3C,$60,$C0,$FC,$C6,$C6,$7C,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $FE,$C6,$0C,$18,$30,$30,$30,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $7C,$C6,$C6,$7C,$C6,$C6,$7C,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $7C,$C6,$C6,$7E,$06,$0C,$78,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $38,$6C,$C6,$C6,$FE,$C6,$C6,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $FC,$C6,$C6,$FC,$C6,$C6,$FC,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $3C,$66,$C0,$C0,$C0,$66,$3C,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $F8,$CC,$C6,$C6,$C6,$CC,$F8,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $FE,$C0,$C0,$FC,$C0,$C0,$FE,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $FE,$C0,$C0,$FC,$C0,$C0,$C0,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $3E,$60,$C0,$CE,$C6,$66,$3E,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $C6,$C6,$C6,$FE,$C6,$C6,$C6,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $7E,$18,$18,$18,$18,$18,$7E,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $1E,$06,$06,$06,$C6,$C6,$7C,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $C6,$CC,$D8,$F0,$F8,$DC,$CE,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $60,$60,$60,$60,$60,$60,$7E,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $C6,$EE,$FE,$FE,$D6,$C6,$C6,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $C6,$E6,$F6,$FE,$DE,$CE,$C6,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $7C,$C6,$C6,$C6,$C6,$C6,$7C,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $FC,$C6,$C6,$C6,$FC,$C0,$C0,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $7C,$C6,$C6,$C6,$DE,$CC,$7A,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $FC,$C6,$C6,$CE,$F8,$DC,$CE,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $78,$CC,$C0,$7C,$06,$C6,$7C,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $7E,$18,$18,$18,$18,$18,$18,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $C6,$C6,$C6,$C6,$C6,$C6,$7C,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $C6,$C6,$C6,$EE,$7C,$38,$10,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $C6,$C6,$D6,$FE,$FE,$EE,$C6,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $C6,$EE,$7C,$38,$7C,$EE,$C6,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $66,$66,$66,$3C,$18,$18,$18,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $FE,$0E,$1C,$38,$70,$E0,$FE,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$00,$00,$00,$00,$00,$00,$00,$00
db $00,$00,$00,$00,$00,$00,$00,$00,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $00,$00,$00,$7E,$7E,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $00,$00,$44,$28,$10,$28,$44,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F
db $18,$3C,$3C,$3C,$18,$18,$00,$18,$00,$00,$00,$00,$00,$00,$00,$00
db $FF,$7F,$7F,$7F,$7F,$FF,$E3,$C1,$FF,$80,$80,$80,$80,$00,$1C,$3E
db $80,$80,$80,$C1,$E3,$FF,$FF,$FF,$7F,$7F,$7F,$3E,$1C,$00,$00,$FF
db $38,$7C,$7C,$7C,$7C,$7C,$38,$00,$08,$04,$04,$04,$04,$04,$08,$00
db $03,$06,$0C,$0C,$08,$08,$04,$03,$03,$05,$0B,$0B,$0F,$0F,$07,$03
db $01,$02,$04,$08,$10,$20,$40,$80,$01,$03,$07,$0F,$1F,$3F,$7F,$FF
db $00,$00,$00,$00,$00,$07,$38,$C0,$00,$00,$00,$00,$00,$07,$3F,$FF
db $00,$00,$00,$00,$00,$E0,$1C,$03,$00,$00,$00,$00,$00,$E0,$FC,$FF
db $80,$40,$20,$10,$08,$04,$02,$01,$80,$C0,$E0,$F0,$F8,$FC,$FE,$FF
db $04,$0E,$0E,$0E,$6E,$64,$60,$60,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $07,$0F,$1F,$1F,$7F,$FF,$FF,$7F,$07,$08,$10,$00,$60,$80,$80,$40
db $03,$07,$1F,$3F,$3F,$3F,$79,$F7,$03,$04,$18,$20,$20,$20,$46,$88
db $C0,$E0,$F0,$F4,$FE,$BF,$DF,$FF,$C0,$20,$10,$14,$0A,$41,$21,$01
db $90,$B8,$F8,$FA,$FF,$FF,$FF,$FE,$90,$A8,$48,$0A,$05,$01,$01,$02
db $3B,$1D,$0E,$0F,$07,$00,$00,$00,$24,$12,$09,$08,$07,$00,$00,$00
db $FF,$BF,$1C,$C0,$F3,$FF,$7E,$1C,$00,$40,$E3,$3F,$0C,$81,$62,$1C
db $BF,$7F,$3D,$83,$C7,$FF,$FF,$3C,$40,$80,$C2,$7C,$38,$00,$C3,$3C
db $FC,$FE,$FF,$FE,$FE,$F8,$60,$00,$04,$02,$01,$00,$06,$98,$60,$00
db $C0,$20,$10,$10,$10,$10,$20,$C0,$C0,$E0,$F0,$F0,$F0,$F0,$E0,$C0
db $00,$00,$00,$00,$3F,$7F,$E0,$C0,$00,$00,$00,$00,$00,$00,$1C,$3E
db $88,$9C,$88,$80,$80,$80,$80,$80,$7F,$7F,$7F,$3E,$1C,$00,$00,$00
db $FE,$FE,$FE,$FE,$FE,$FE,$FE,$FE,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $08,$14,$24,$C4,$03,$40,$A1,$26,$00,$08,$18,$38,$FC,$BF,$5E,$D9
db $FF,$FF,$FF,$FF,$7F,$7F,$7F,$7F,$81,$81,$81,$81,$81,$81,$81,$81
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$01,$01,$01,$01,$01,$01,$01,$01
db $7F,$80,$80,$98,$9C,$8C,$80,$80,$00,$7F,$7F,$67,$67,$7F,$7F,$7F
db $FF,$01,$01,$FF,$10,$10,$10,$FF,$00,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $80,$80,$80,$80,$80,$80,$80,$80,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F
db $01,$01,$01,$FF,$10,$10,$10,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $FF,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $FE,$01,$01,$19,$1D,$0D,$01,$01,$00,$FF,$FF,$E7,$E7,$FF,$FF,$FF
db $01,$01,$01,$01,$01,$01,$01,$01,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $3F,$7F,$7F,$FF,$FF,$FF,$FF,$FF,$3F,$60,$40,$C0,$80,$80,$80,$80
db $FF,$FF,$FF,$FF,$FF,$FF,$7E,$3C,$80,$80,$80,$80,$80,$81,$42,$3C
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$00,$00,$00,$00,$00,$00,$00
db $FF,$FF,$FF,$FF,$FF,$FF,$FE,$7C,$00,$00,$00,$00,$00,$01,$82,$7C
db $FF,$FF,$FF,$FF,$FF,$FF,$FE,$7C,$00,$00,$00,$00,$00,$01,$83,$FF
db $F8,$FC,$FE,$FE,$FF,$FF,$FF,$FF,$F8,$04,$02,$02,$01,$01,$01,$01
db $FF,$FF,$FF,$FF,$FF,$FF,$7E,$3C,$01,$01,$01,$01,$01,$81,$42,$3C
db $00,$08,$08,$08,$10,$10,$10,$00,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $00,$7F,$7F,$78,$73,$73,$73,$7F,$7F,$80,$A0,$87,$8F,$8E,$8E,$86
db $00,$FF,$FF,$3F,$9F,$9F,$9F,$1F,$FE,$01,$05,$C1,$E1,$71,$71,$F1
db $7E,$7E,$7F,$7E,$7E,$7F,$7F,$FF,$81,$81,$80,$81,$81,$A0,$80,$FF
db $7F,$7F,$FF,$7F,$7F,$FF,$FF,$FF,$F1,$C1,$C1,$81,$C1,$C5,$01,$FF
db $7F,$80,$A0,$80,$80,$80,$80,$80,$7F,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $FE,$01,$05,$01,$01,$01,$01,$01,$FE,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $80,$80,$80,$80,$80,$A0,$80,$7F,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$7F
db $01,$01,$01,$01,$01,$05,$01,$FE,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FE
db $00,$00,$00,$00,$FC,$FE,$07,$03,$00,$00,$00,$00,$00,$00,$38,$7C
db $11,$39,$11,$01,$01,$01,$01,$01,$FE,$FE,$FE,$7C,$38,$00,$00,$00
db $EF,$28,$28,$28,$28,$28,$EF,$00,$20,$E7,$E7,$E7,$E7,$E7,$EF,$00
db $FE,$82,$82,$82,$82,$82,$FE,$00,$02,$7E,$7E,$7E,$7E,$7E,$FE,$00
db $80,$80,$80,$98,$9C,$8C,$80,$7F,$7F,$7F,$7F,$67,$67,$7F,$7F,$7F
db $FF,$FF,$83,$F3,$F3,$F3,$F3,$F3,$FF,$80,$FC,$8C,$8C,$8C,$8C,$8C
db $FF,$FF,$F0,$F6,$F6,$F6,$F6,$F6,$FF,$00,$0F,$09,$09,$09,$09,$09
db $FF,$FF,$00,$00,$00,$00,$00,$00,$FF,$00,$FF,$FF,$FF,$FF,$FF,$FF
db $FF,$FF,$01,$57,$2F,$57,$2F,$57,$FF,$01,$FF,$A9,$D1,$A9,$D1,$A9
db $F3,$F3,$F3,$F3,$F3,$F3,$FF,$3F,$8C,$8C,$8C,$8C,$8C,$8C,$FF,$3F
db $F6,$F6,$F6,$F6,$F6,$F6,$FF,$FF,$09,$09,$09,$09,$09,$09,$FF,$FF
db $00,$00,$00,$00,$00,$00,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $2F,$57,$2F,$57,$2F,$57,$FF,$FC,$D1,$A9,$D1,$A9,$D1,$A9,$FF,$FC
db $3C,$3C,$3C,$3C,$3C,$3C,$3C,$3C,$23,$23,$23,$23,$23,$23,$23,$23
db $FB,$FB,$FB,$FB,$FB,$FB,$FB,$FB,$04,$04,$04,$04,$04,$04,$04,$04
db $BC,$5C,$BC,$5C,$BC,$5C,$BC,$5C,$44,$A4,$44,$A4,$44,$A4,$44,$A4
db $1F,$20,$40,$40,$80,$80,$80,$81,$1F,$3F,$7F,$7F,$FF,$FF,$FF,$FE
db $FF,$80,$80,$C0,$FF,$FF,$FE,$FE,$FF,$7F,$7F,$3F,$00,$00,$01,$01
db $FF,$7F,$7F,$FF,$FF,$07,$03,$03,$FF,$80,$80,$00,$00,$F8,$FC,$FC
db $FF,$00,$00,$00,$00,$81,$C3,$FF,$FF,$FF,$FF,$FF,$FF,$7E,$3C,$00
db $F8,$FC,$FE,$FE,$E3,$C1,$81,$81,$F8,$04,$02,$02,$1D,$3F,$7F,$7F
db $83,$FF,$FF,$FF,$FF,$FF,$7F,$1F,$FC,$80,$80,$80,$80,$80,$60,$1F
db $FC,$FC,$FC,$FC,$FE,$FE,$FF,$FF,$03,$03,$03,$03,$01,$01,$00,$FF
db $01,$01,$01,$01,$03,$03,$07,$FF,$FE,$FE,$FE,$FE,$FC,$FC,$F8,$FF
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$00,$00,$00,$00,$00,$00,$00,$FF
db $81,$C1,$E3,$FF,$FF,$FF,$FF,$FE,$7F,$3F,$1D,$01,$01,$01,$03,$FE
db $FF,$FF,$FF,$FF,$FF,$FB,$B5,$CE,$80,$80,$80,$80,$80,$84,$CA,$B1
db $FF,$FF,$FF,$FF,$FF,$DF,$AD,$73,$01,$01,$01,$01,$01,$21,$53,$8D
db $77,$77,$77,$77,$77,$77,$77,$77,$00,$00,$00,$00,$77,$FF,$FF,$FF
db $00,$00,$00,$00,$00,$00,$00,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $77,$77,$77,$77,$00,$00,$00,$00,$FF,$FF,$FF,$77,$77,$77,$77,$77
db $01,$01,$01,$19,$1D,$0D,$01,$FE,$FF,$FF,$FF,$E7,$E7,$FF,$FF,$FE
db $20,$78,$7F,$FE,$FE,$FE,$FE,$FE,$00,$21,$21,$41,$41,$41,$41,$41
db $04,$9A,$FA,$FD,$FD,$FD,$FD,$FD,$00,$80,$80,$80,$80,$80,$80,$80
db $7E,$38,$21,$00,$01,$00,$01,$00,$21,$21,$01,$01,$01,$01,$01,$01
db $FA,$8A,$84,$80,$80,$80,$80,$80,$80,$80,$80,$80,$80,$80,$80,$80
db $02,$04,$00,$10,$00,$40,$80,$00,$01,$01,$06,$08,$18,$20,$20,$C0
db $0B,$0B,$3B,$0B,$FB,$0B,$0B,$0A,$04,$04,$C4,$F4,$F4,$04,$04,$05
db $90,$10,$1F,$10,$1F,$10,$10,$90,$70,$F0,$F0,$FF,$FF,$F0,$F0,$70
db $3F,$78,$E7,$CF,$58,$58,$50,$90,$C0,$87,$18,$B0,$E7,$E7,$EF,$EF
db $B0,$FC,$E2,$C1,$C1,$83,$8F,$7E,$6F,$43,$5D,$3F,$3F,$7F,$7F,$FF
db $FE,$03,$0F,$91,$70,$60,$20,$31,$03,$FF,$F1,$6E,$CF,$DF,$FF,$FF
db $3F,$3F,$1D,$39,$7B,$F3,$86,$FE,$FD,$FB,$FB,$F7,$F7,$0F,$7F,$FF
db $FF,$FF,$FF,$FF,$FF,$80,$80,$FF,$FF,$80,$80,$80,$80,$FF,$FF,$80
db $FE,$FF,$FF,$FF,$FF,$03,$03,$FF,$FE,$03,$03,$03,$03,$FF,$FF,$03
db $00,$FF,$FF,$FF,$FF,$FF,$00,$00,$00,$FF,$00,$00,$00,$00,$FF,$FF
db $3C,$FC,$FC,$FC,$FC,$FC,$04,$04,$23,$F3,$0B,$0B,$0B,$07,$FF,$FF
db $FF,$FF,$FF,$FF,$80,$FF,$FF,$FF,$80,$80,$80,$80,$FF,$80,$80,$80
db $FF,$FF,$FF,$FF,$03,$FF,$FF,$FF,$03,$03,$03,$03,$FF,$03,$03,$03
db $FF,$FF,$FF,$FF,$FF,$00,$FF,$FF,$00,$00,$00,$00,$00,$FF,$00,$00
db $FC,$FC,$FE,$FE,$FE,$02,$FE,$FE,$07,$07,$03,$03,$03,$FF,$03,$03
db $FF,$80,$80,$80,$80,$80,$80,$80,$80,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $FF,$03,$03,$03,$03,$03,$03,$03,$03,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $02,$02,$02,$02,$02,$02,$04,$04,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $80,$80,$AA,$D5,$AA,$FF,$FF,$FF,$FF,$FF,$D5,$AA,$D5,$80,$80,$FF
db $03,$03,$AB,$57,$AB,$FF,$FF,$FE,$FF,$FF,$57,$AB,$57,$03,$03,$FE
db $00,$55,$AA,$55,$FF,$FF,$FF,$00,$FF,$AA,$55,$AA,$00,$00,$FF,$00
db $04,$54,$AC,$5C,$FC,$FC,$FC,$3C,$FF,$AF,$57,$AB,$0B,$0B,$F3,$23
db $3F,$3F,$3F,$3F,$00,$00,$00,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $7E,$7C,$7C,$78,$00,$00,$00,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $1F,$0F,$0F,$07,$00,$00,$00,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $FE,$FC,$FC,$F8,$00,$00,$00,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $00,$00,$00,$00,$FF,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $18,$18,$18,$18,$18,$18,$18,$18,$00,$00,$00,$00,$00,$00,$00,$00
db $07,$1F,$3F,$FF,$7F,$7F,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $E1,$F9,$FD,$FF,$FE,$FE,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $F0,$10,$10,$10,$10,$10,$10,$FF,$00,$E0,$E0,$E0,$E0,$E0,$E0,$E0
db $1F,$10,$10,$10,$10,$10,$10,$FF,$00,$0F,$0F,$0F,$0F,$0F,$0F,$0F
db $92,$92,$92,$FE,$FE,$00,$00,$00,$48,$48,$6C,$00,$00,$00,$FE,$00
db $0A,$0A,$3A,$0A,$FB,$0B,$0B,$0B,$05,$05,$C5,$F5,$F4,$04,$04,$04
db $90,$90,$9F,$90,$9F,$90,$90,$90,$70,$70,$70,$7F,$7F,$70,$70,$70
db $01,$01,$01,$01,$01,$01,$01,$01,$00,$00,$00,$00,$00,$00,$00,$00
db $80,$80,$80,$80,$80,$80,$80,$80,$00,$00,$00,$00,$00,$00,$00,$00
db $08,$88,$91,$D1,$53,$53,$73,$3F,$FF,$FF,$FF,$FF,$FF,$FE,$BE,$CE
db $00,$00,$07,$0F,$0C,$1B,$1B,$1B,$00,$00,$00,$00,$03,$04,$04,$04
db $00,$00,$E0,$F0,$F0,$F8,$F8,$F8,$00,$00,$60,$30,$30,$98,$98,$98
db $1B,$1B,$1B,$1B,$1B,$0F,$0F,$07,$04,$04,$04,$04,$04,$03,$00,$00
db $F8,$F8,$F8,$F8,$F8,$F0,$F0,$E0,$98,$98,$98,$98,$98,$30,$30,$60
db $F1,$11,$11,$1F,$10,$10,$10,$FF,$0F,$EF,$EF,$EF,$EF,$EF,$EF,$E0
db $1F,$10,$10,$F0,$10,$10,$10,$FF,$E0,$EF,$EF,$EF,$EF,$EF,$EF,$0F
db $7F,$BF,$DF,$EF,$F0,$F0,$F0,$F0,$80,$40,$20,$10,$0F,$0F,$0F,$0F
db $F0,$F0,$F0,$F0,$FF,$FF,$FF,$FF,$0F,$0F,$0F,$0F,$1F,$3F,$7F,$FF
db $FF,$FF,$FF,$FF,$0F,$0F,$0F,$0F,$01,$03,$07,$0F,$FF,$FF,$FF,$FF
db $0F,$0F,$0F,$0F,$F7,$FB,$FD,$FE,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $00,$00,$00,$00,$00,$00,$18,$18,$00,$00,$00,$00,$00,$00,$00,$00
db $1F,$3F,$7F,$7F,$7F,$FF,$FF,$FF,$1F,$20,$40,$40,$40,$80,$82,$82
db $FF,$FF,$FF,$7F,$7F,$7F,$3F,$1E,$82,$80,$A0,$44,$43,$40,$21,$1E
db $F8,$FC,$FE,$FE,$FE,$FF,$FF,$FF,$F8,$04,$02,$02,$02,$01,$41,$41
db $FF,$FF,$FF,$FE,$FE,$FE,$FC,$78,$41,$01,$05,$22,$C2,$02,$84,$78
db $7F,$80,$80,$80,$80,$80,$80,$80,$80,$7F,$7F,$7F,$7F,$7F,$7F,$7F
db $DE,$61,$61,$61,$71,$5E,$7F,$61,$61,$DF,$DF,$DF,$DF,$FF,$C1,$DF
db $80,$80,$C0,$F0,$BF,$8F,$81,$7E,$7F,$7F,$FF,$3F,$4F,$71,$7F,$FF
db $61,$61,$C1,$C1,$81,$81,$83,$FE,$DF,$DF,$BF,$BF,$7F,$7F,$7F,$7F
db $00,$00,$03,$0F,$1F,$3F,$7F,$7F,$00,$00,$03,$0C,$10,$20,$40,$40
db $00,$00,$C0,$F0,$F8,$FC,$FE,$FE,$00,$00,$C0,$30,$08,$04,$02,$02
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$80,$80,$80,$80,$80,$80,$80,$80
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$01,$01,$01,$01,$01,$01,$01,$01
db $7F,$7F,$7F,$3F,$3F,$1F,$0F,$07,$40,$40,$40,$20,$30,$1C,$0F,$07
db $FE,$FE,$FE,$FC,$FC,$F8,$F0,$F0,$02,$02,$02,$04,$0C,$38,$F0,$F0
db $0F,$0F,$0F,$0F,$0F,$0F,$07,$0F,$08,$08,$08,$08,$08,$0C,$05,$0A
db $F0,$F0,$F0,$F0,$F0,$F0,$E0,$F0,$10,$50,$50,$50,$50,$30,$A0,$50
db $81,$C1,$A3,$A3,$9D,$81,$81,$81,$00,$41,$22,$22,$1C,$00,$00,$00
db $E3,$F7,$C1,$C1,$C1,$C1,$F7,$E3,$E3,$14,$3E,$3E,$3E,$3E,$14,$E3
db $00,$00,$07,$0F,$0C,$1B,$1B,$1B,$FF,$FF,$F8,$F0,$F0,$E0,$E0,$E0
db $00,$00,$E0,$F0,$F0,$F8,$F8,$F8,$FF,$FF,$7F,$3F,$3F,$9F,$9F,$9F
db $1B,$1B,$1B,$1B,$1B,$0F,$0F,$07,$E0,$E0,$E0,$E0,$E0,$F3,$F0,$F8
db $F8,$F8,$F8,$F8,$F8,$F0,$F0,$E0,$9F,$9F,$9F,$9F,$9F,$3F,$3F,$7F
db $E0,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$00,$70,$1F,$10,$70,$7F,$7F,$7F
db $07,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$00,$03,$F8,$00,$03,$FB,$FB,$FB
db $FF,$FF,$FF,$FF,$FF,$FE,$FF,$EF,$7C,$7B,$76,$75,$75,$77,$17,$67
db $FF,$DF,$EF,$AF,$AF,$6F,$EF,$E7,$3B,$FB,$7B,$FB,$FB,$F3,$F8,$F3
db $1F,$1F,$3F,$3F,$70,$63,$E7,$E5,$0F,$0F,$1F,$1F,$3F,$3C,$78,$7A
db $F0,$F0,$F8,$F8,$0C,$C4,$E4,$A6,$F8,$F8,$FC,$FC,$FE,$3E,$1E,$5F
db $E9,$E9,$E9,$EF,$E2,$E3,$F0,$FF,$76,$76,$76,$70,$7D,$7C,$7F,$7F
db $96,$96,$96,$F6,$46,$C6,$0E,$FE,$6F,$6F,$6F,$0F,$BF,$3F,$FF,$FF
db $00,$00,$00,$00,$00,$00,$7E,$3C,$3C,$7E,$7E,$FF,$FF,$FF,$42,$00
db $3C,$42,$99,$A1,$A1,$99,$42,$3C,$00,$00,$00,$00,$00,$00,$00,$00
db $0F,$1F,$1F,$3F,$3F,$7F,$7F,$7F,$F0,$E0,$E0,$C0,$C0,$80,$80,$80
db $F0,$F8,$F8,$FC,$FC,$FE,$FE,$FE,$0F,$07,$07,$03,$03,$01,$01,$01
db $7F,$7F,$3F,$3F,$3F,$3F,$1F,$1F,$80,$80,$C0,$C0,$E0,$F8,$FE,$FF
db $FE,$FF,$FF,$FF,$FC,$FC,$FE,$FE,$FF,$7F,$1F,$07,$03,$03,$01,$81
db $7F,$7F,$7F,$3F,$3F,$3F,$3F,$1F,$80,$80,$80,$C0,$C0,$E0,$E0,$F0
db $FE,$FE,$FF,$FF,$FF,$FF,$FF,$FE,$01,$01,$01,$03,$03,$07,$07,$0F
db $1F,$0F,$0F,$07,$00,$00,$00,$00,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $FE,$FC,$FC,$F8,$00,$00,$00,$00,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $7E,$7E,$7E,$7E,$7F,$7F,$7F,$7F,$81,$81,$81,$81,$81,$81,$81,$81
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FE,$01,$01,$01,$03,$03,$07,$07,$0F
db $FE,$FE,$FE,$FE,$FF,$FF,$FF,$FF,$01,$01,$01,$01,$01,$01,$01,$01
db $7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$81,$81,$81,$81,$81,$81,$81,$81
db $FF,$FF,$FF,$FF,$FC,$FE,$FE,$7E,$FF,$03,$03,$03,$03,$03,$03,$FF
db $FF,$FF,$FF,$FF,$00,$00,$00,$00,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $7F,$7F,$7F,$7F,$7F,$7F,$7F,$7F,$80,$80,$80,$80,$80,$80,$80,$80
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FE,$01,$01,$01,$03,$07,$03,$01,$01
db $7E,$7E,$7F,$7F,$7F,$7F,$7F,$7F,$81,$81,$81,$81,$81,$81,$81,$81
db $3F,$3F,$3F,$3F,$00,$00,$00,$00,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $7E,$7C,$7C,$78,$00,$00,$00,$00,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
db $FE,$FE,$FF,$FF,$7F,$7F,$7F,$7F,$81,$81,$81,$81,$81,$81,$81,$81
db $7F,$7F,$3F,$3F,$3F,$3F,$1F,$1F,$80,$80,$C0,$C0,$E0,$F8,$FE,$FF
db $3F,$BF,$FF,$FF,$FC,$FC,$FE,$FE,$FF,$7F,$1F,$07,$03,$03,$01,$81
db $7F,$7F,$7E,$7E,$7F,$7F,$7F,$7F,$81,$81,$81,$81,$81,$81,$81,$81
db $7E,$7E,$7E,$7E,$7F,$7F,$7F,$7F,$81,$81,$81,$81,$81,$81,$81,$81
db $81,$C3,$C3,$E7,$E7,$FF,$FF,$FF,$7E,$3C,$3C,$18,$18,$00,$00,$00
db $0F,$43,$5B,$53,$31,$19,$0F,$07,$F2,$FE,$FE,$FF,$FF,$EF,$F7,$F8
db $C1,$C3,$C6,$84,$FC,$FC,$0E,$02,$BF,$BE,$BD,$7B,$7B,$07,$F3,$FD
db $10,$20,$22,$BA,$E6,$E1,$C0,$C0,$FF,$FF,$FF,$67,$59,$9E,$BF,$BF
db $20,$A6,$54,$26,$20,$C6,$54,$26,$20,$E6,$54,$26,$21,$06,$54,$26
db $20,$85,$01,$44,$20,$86,$54,$48,$20,$9A,$01,$49,$20,$A5,$C9,$46
db $20,$BA,$C9,$4A,$20,$A6,$0A,$D0,$D1,$D8,$D8,$DE,$D1,$D0,$DA,$DE
db $D1,$20,$C6,$0A,$D2,$D3,$DB,$DB,$DB,$D9,$DB,$DC,$DB,$DF,$20,$E6
db $0A,$D4,$D5,$D4,$D9,$DB,$E2,$D4,$DA,$DB,$E0,$21,$06,$0A,$D6,$D7
db $D6,$D7,$E1,$26,$D6,$DD,$E1,$E1,$21,$26,$14,$D0,$E8,$D1,$D0,$D1
db $DE,$D1,$D8,$D0,$D1,$26,$DE,$D1,$DE,$D1,$D0,$D1,$D0,$D1,$26,$21
db $46,$14,$DB,$42,$42,$DB,$42,$DB,$42,$DB,$DB,$42,$26,$DB,$42,$DB
db $42,$DB,$42,$DB,$42,$26,$21,$66,$46,$DB,$21,$6C,$0E,$DF,$DB,$DB
db $DB,$26,$DB,$DF,$DB,$DF,$DB,$DB,$E4,$E5,$26,$21,$86,$14,$DB,$DB
db $DB,$DE,$43,$DB,$E0,$DB,$DB,$DB,$26,$DB,$E3,$DB,$E0,$DB,$DB,$E6
db $E3,$26,$21,$A6,$14,$DB,$DB,$DB,$DB,$42,$DB,$DB,$DB,$D4,$D9,$26
db $DB,$D9,$DB,$DB,$D4,$D9,$D4,$D9,$E7,$21,$C5,$16,$5F,$95,$95,$95
db $95,$95,$95,$95,$95,$97,$98,$78,$95,$96,$95,$95,$97,$98,$97,$98
db $95,$7A,$21,$ED,$0E,$CF,$01,$09,$08,$05,$24,$17,$12,$17,$1D,$0E
db $17,$0D,$18,$22,$4B,$0D,$01,$24,$19,$15,$0A,$22,$0E,$1B,$24,$10
db $0A,$16,$0E,$22,$8B,$0D,$02,$24,$19,$15,$0A,$22,$0E,$1B,$24,$10
db $0A,$16,$0E,$22,$EC,$04,$1D,$18,$19,$28,$22,$F6,$01,$00,$23,$C9
db $56,$55,$23,$E2,$04,$99,$AA,$AA,$AA,$23,$EA,$04,$99,$AA,$AA,$AA
db $00,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF

View File

@ -8,13 +8,17 @@
"cadius": "C:\\Programs\\IIgsXDev\\bin\\Cadius.exe",
"gsport": "C:\\Programs\\gsport\\gsport_0.31\\GSPort.exe",
"macros": "../../macros",
"crossrunner": "C:\\Programs\\Crossrunner\\Crossrunner.exe"
"crossrunner": "C:\\Program Files\\Crossrunner\\Crossrunner.exe"
},
"scripts": {
"test": "npm run build && npm run build:image && npm run gsport",
"gsport": "%npm_package_config_gsport%",
"build": "%npm_package_config_merlin32% -V %npm_package_config_macros% App.s",
"build:image": "build-image.bat %npm_package_config_cadius%"
"build:sys16": "%npm_package_config_merlin32% -V %npm_package_config_macros% App.s",
"build": "npm run build:tool && npm run build:sys16",
"build:tool": "%npm_package_config_merlin32% -V %npm_package_config_macros% ../../src/Master.s",
"build:image": "build-image.bat %npm_package_config_cadius%",
"debug": "\"%npm_package_config_crossrunner%\" SuperMarioGS -Source SuperMarioGS_S02__Output.txt -Source SuperMarioGS_S03__Output.txt -Debug -CompatibilityLayer"
},
"repository": {
"type": "git",

69
demos/smb/palette.s Normal file
View File

@ -0,0 +1,69 @@
; NES Palette (52 entries)
nesPalette
dw $0888
dw $004A
dw $001B
dw $0409
dw $0A06
dw $0C02
dw $0C10
dw $0910
dw $0630
dw $0140
dw $0050
dw $0043
dw $0046
dw $0000
dw $0111
dw $0111
dw $0CCC
dw $007F
dw $025F
dw $083F
dw $0F3B
dw $0F35
dw $0F20
dw $0D30
dw $0C60
dw $0380
dw $0190
dw $0095
dw $00AD
dw $0222
dw $0111
dw $0111
dw $0FFF
dw $01DF
dw $07AF
dw $0D8F
dw $0F4F
dw $0F69
dw $0F93
dw $0F91
dw $0FC2
dw $0AE1
dw $03F3
dw $01FA
dw $00FF
dw $0666
dw $0111
dw $0111
dw $0FFF
dw $0AFF
dw $0BEF
dw $0DAF
dw $0FBF
dw $0FAB
dw $0FDB
dw $0FEA
dw $0FF9
dw $0DE9
dw $0AEB
dw $0AFD
dw $09FF
dw $0EEE
dw $0111
dw $0111

521
demos/smb/ppu.s Normal file
View File

@ -0,0 +1,521 @@
; PPU simulator
;
; Any read/write to the PPU registers in the ROM is intercepted and passed here.
mx %11
dw $a5a5 ; marker to find in memory
ppuaddr ds 2 ; 16-bit ppu address
w_bit dw 1 ; currently writing to high or low to the address latch
vram_buff dw 0 ; latched data when reading VRAM ($0000 - $3EFF)
ppuincr dw 1 ; 1 or 32 depending on bit 2 of PPUCTRL
spadr dw $0000 ; Sprite pattern table ($0000 or $1000) depending on bit 3 of PPUCTRL
ntaddr dw $2000 ; Base nametable address ($2000, $2400, $2800, $2C00), bits 0 and 1 of PPUCTRL
bgadr dw $0000 ; Background pattern table address
ppuctrl dw 0 ; Copy of the ppu ctrl byte
ppumask dw 0 ; Copy of the ppu mask byte
ppustatus dw 0
oamaddr dw 0 ; Typically this will always be 0
ppuscroll dw 0 ; Y X coordinates
ntbase db $20,$24,$28,$2c
assert_lt mac
cmp ]1
bcc ok
brk ]2
ok
<<<
assert_x_lt mac
cpx ]1
bcc ok
brk ]2
ok
<<<
cond mac
bit ]1
beq cond_0
lda ]3
bra cond_s
cond_0 lda ]2
cond_s sta ]4
<<<
; $2000 - PPUCTRL (Write only)
PPUCTRL_WRITE ENT
php
phb
phk
plb
sta ppuctrl
phx
; Set the pattern table base address
and #$03
tax
lda ntbase,x
sta ntaddr+1
; Set the vram increment
lda ppuctrl
cond #$04;#$01;#$20;ppuincr
; Set the sprite table address
lda ppuctrl
cond #$08;#$00;#$10;spadr+1
; Set the background table address
lda ppuctrl
cond #$10;#$00;#$10;bgadr+1
plx
lda ppuctrl
plb
plp
rtl
; $2001 - PPUMASK (Write only)
PPUMASK_WRITE ENT
stal ppumask
rtl
; $2002 - PPUSTATUS For "ldx ppustatus"
PPUSTATUS_READ_X ENT
php
pha
lda #1
stal w_bit ; Reset the address latch used by PPUSCROLL and PPUADDR
ldal ppustatus
tax
and #$7F ; Clear the VBL flag
stal ppustatus
pla ; Restore the accumulator (return value in X)
plp
phx ; re-read x to set any relevant flags
plx
rtl
PPUSTATUS_READ ENT
php
lda #1
stal w_bit ; Reset the address latch used by PPUSCROLL and PPUADDR
ldal ppustatus
pha
and #$7F ; Clear the VBL flag
stal ppustatus
pla ; pop the return value
plp
pha ; re-read accumulator to set any relevant flags
pla
rtl
; $2003
OAMADDR_WRITE ENT
stal oamaddr
rtl
; $2005 - PPU SCROLL
PPUSCROLL_WRITE ENT
php
phb
phk
plb
phx
pha
ldx w_bit
sta ppuscroll,x
txa
eor #$01
sta w_bit
pla
plx
plb
plp
rtl
; $2006 - PPUADDR
PPUADDR_WRITE ENT
php
phb
phk
plb
phx
pha
ldx w_bit
sta ppuaddr,x
; assert_lt #$40;$D0
txa
eor #$01
sta w_bit
pla
plx
plb
plp
rtl
; 2007 - PPUDATA (Read/Write)
;
; If reading from the $0000 - $3EFF range, the value from vram_buff is returned and the actual data is loaded
; post-fetch.
PPUDATA_READ ENT
php
phb
phk
plb
phx
rep #$30 ; do a 16-bit update of the address
ldx ppuaddr
txa
; assert_lt #$4000;$d1
clc
adc ppuincr
sta ppuaddr
sep #$20 ; back to 8-bit acc for the read itself
cpx #$3F00 ; check which range of memory we are accessing?
bcc :buff_read
lda PPU_MEM,x
bra :out
:buff_read
lda vram_buff ; read from the buffer
pha
lda PPU_MEM,x ; put the data in the buffer for the next read
sta vram_buff
pla ; pop the return value
:out
sep #$10
plx
plb
plp
pha
pla
rtl
PPUDATA_WRITE ENT
php
phb
phk
plb
pha
phx
rep #$10
ldx ppuaddr
sta PPU_MEM,x
rep #$30
txa
clc
adc ppuincr
sta ppuaddr
cpx #$3F00
bcs :extra
sep #$30
plx
pla
plb
plp
rtl
; Do some extra work to keep palette data in sync
;
; Based on the palette data that SMB uses, we map the NES palette entries as
;
; NES Description IIgs Palette
; ----------------------------------------
; BG0 Background color 0
; BG0,1 Light Green 1
; BG0,2 Dark Green 2
; BG0,3 Black 3
; BG1,1 Peach 4
; BG1,2 Brown 5
; BG1,3 Black 3
; BG2,1 White 6
; BG2,2 Light Blue 7
; BG2,3 Black 3
; BG3,1 Cycle 8 ; Coins / Blocks
; BG3,2 Brown 5
; BG3,3 Black 3
; SP0 0
; SP0,1 Red 9
; SP0,2 Orange 10
; SP0,3 Olive 11
; SP1,1 Dark Green 2
; SP1,2 White 6
; SP1,3 Orange 10
; SP2,1 Red 9
; SP2,2 White 6
; SP2,3 Orange 10
; SP3,1 Black 3
; SP3,2 Peach 4
; SP3,3 Brown 5
;
; There are 4 color to spare in case we need to add more entries. This mapping table is important because
; we have to have a custom tile rendering function and custom sprite rendering function that will dynamically
; map the 2-bit tile data into the proper palette range. This will likely be implemented with an 8-bit
; swizzle table. Possible optimization later on is to pre-swizzle certain tiles assuming that the palette
; assignments never change.
;
; BG Palette 2 can probably be ignored because it's just for the top of the screen and we can use a separate
; SCB palette for that line
mx %00
:extra
txa
and #$001F
asl
tax
jmp (palTbl,x)
palTbl dw ppu_3F00,ppu_3F01,ppu_3F02,ppu_3F03
dw ppu_3F04,ppu_3F05,ppu_3F06,ppu_3F07
dw ppu_3F08,ppu_3F09,ppu_3F0A,ppu_3F0B
dw ppu_3F0C,ppu_3F0D,ppu_3F0E,ppu_3F0F
dw ppu_3F10,ppu_3F11,ppu_3F12,ppu_3F13
dw ppu_3F14,ppu_3F15,ppu_3F16,ppu_3F17
dw ppu_3F18,ppu_3F19,ppu_3F1A,ppu_3F1B
dw ppu_3F1C,ppu_3F1D,ppu_3F1E,ppu_3F1F
ppu_3F00
lda PPU_MEM+$3F00
ldx #0
brl extra_out
ppu_3F01
lda PPU_MEM+$3F01
ldx #2
brl extra_out
ppu_3F02
lda PPU_MEM+$3F02
ldx #4
brl extra_out
ppu_3F03
lda PPU_MEM+$3F03
ldx #6
brl extra_out
ppu_3F05
lda PPU_MEM+$3F05
ldx #8
brl extra_out
ppu_3F06
lda PPU_MEM+$3F06
ldx #10
brl extra_out
ppu_3F07
lda PPU_MEM+$3F07
ldx #12
brl extra_out
ppu_3F09
lda PPU_MEM+$3F05
ldx #14
brl extra_out
ppu_3F0A
lda PPU_MEM+$3F06
ldx #16
brl extra_out
ppu_3F0B
lda PPU_MEM+$3F07
ldx #18
brl extra_out
ppu_3F0D
lda PPU_MEM+$3F05
ldx #20
brl extra_out
ppu_3F0E
lda PPU_MEM+$3F06
ldx #22
brl extra_out
ppu_3F0F
lda PPU_MEM+$3F07
ldx #24
brl extra_out
ppu_3F10
lda PPU_MEM+$3F10
ldx #0
brl extra_out
ppu_3F04
ppu_3F08
ppu_3F0C
ppu_3F11
ppu_3F12
ppu_3F13
ppu_3F14
ppu_3F15
ppu_3F16
ppu_3F17
ppu_3F18
ppu_3F19
ppu_3F1A
ppu_3F1B
ppu_3F1C
ppu_3F1D
ppu_3F1E
ppu_3F1F
; Exit code to set a IIgs palette entry from the PPU memory
;
; A = NES palette value
; X = IIgs Palette index
extra_out
phy
and #$00FF
asl
tay
lda nesPalette,y
ply
stal $E19E00,x
sep #$30
plx
pla
plb
plp
rtl
; Trigger a copy from a page of memory to OAM. Since this is a DMA operation, we can cheat and do a 16-bit copy
PPUDMA_WRITE ENT
php
phb
phk
plb
phx
pha
rep #$30
xba
and #$FF00
tax
]n equ 0
lup 128
ldal ROMBase+]n,x
sta PPU_OAM+]n
]n = ]n+2
--^
sep #$30
pla
plx
plb
plp
rtl
y_offset equ 16
x_offset equ 16
drawOAMSprites
:tmp equ 238
phb
php
phk
plb
sep #$30 ; 8-bit cpu
ldx #4 ; Ok to always skip sprite 0
:oam_loop
lda PPU_OAM+3,x ; remove this test once we can clip sprites
cmp #241
bcs :hidden
lda PPU_OAM,x ; Y-coordinate
cmp #200+y_offset-9
bcs :hidden
phx
inc ; Compensate for PPU delayed scanline
rep #$30
and #$00FF
asl
asl
asl
asl
asl
sta :tmp
asl
asl
clc
adc :tmp
clc
adc #$2000-{y_offset*160}+x_offset
sta :tmp
lda PPU_OAM+3,x
lsr
and #$007F
clc
adc :tmp
tay
lda PPU_OAM+2,x
bit #$0040 ; horizontal flip
bne :hflip
lda PPU_OAM,x ; Load the tile index into the high byte (x256)
and #$FF00
lsr ; multiple by 128
tax
bra drawTilePatch
:hflip
lda PPU_OAM,x ; Loda the tile index into the high byte (x256)
and #$FF00
lsr ; multiple by 128
adc #64 ; horizontal flip
tax
drawTilePatch
jsl $000000 ; Draw the tile on the graphics screen
:hop
sep #$30
plx
:hidden
inx
inx
inx
inx
bne :oam_loop
plp
plb
rtl

View File

@ -668,23 +668,79 @@ GameOverModeValue = 3
; .mem 8
;-------------------------------------------------------------------------------------
mx %11
; External wrapper is responsible for setting the stack
put chr.s
ds $6000
; External wrapper is responsible for setting the stack
PPUCTRL_WRITE EXT
PPUMASK_WRITE EXT
PPUSTATUS_READ EXT
PPUSTATUS_READ_X EXT
OAMADDR_WRITE EXT
PPUSCROLL_WRITE EXT
PPUADDR_WRITE EXT
PPUDATA_READ EXT
PPUDATA_WRITE EXT
PPUDMA_WRITE EXT
ROMBase ENT
ds $8000-14-50
; Hooks to call back to the GTE harness for PPU memory-mapped accesses
mx %11
PPU_CTRL_W
jsl PPUCTRL_WRITE
rts
PPU_MASK_W
jsl PPUMASK_WRITE
rts
PPU_STATUS_R
jsl PPUSTATUS_READ
rts
PPU_STATUS_RX
jsl PPUSTATUS_READ_X
rts
OAM_ADDR_W
jsl OAMADDR_WRITE
rts
PPU_SCROLL_W
jsl PPUSCROLL_WRITE
rts
PPU_ADDRESS_W
jsl PPUADDR_WRITE
rts
PPU_DATA_R
jsl PPUDATA_READ
rts
PPU_DATA_W
jsl PPUDATA_WRITE
rts
SPR_DMA_W
jsl PPUDMA_WRITE
rts
; Enter via a JML. X = target address, Stack and Direct page set up properly. B = ROM bank. Called in 16-bit native mode
mx %00
ExtRtn EXT
ExtIn ENT
stx :patch+1
sep #$30
:patch jsr $0000
rep #$30
jml ExtRtn
mx %11
SMBStart ENT
Start
; sei ;pretty standard 6502 type init here
; cld
lda #%00010000 ;init PPU control register 1
sta PPU_CTRL_REG1
jsr PPU_CTRL_W
; ldx #$ff ;reset stack pointer
; txs
VBlank1 lda PPU_STATUS ;wait two frames
bpl VBlank1
VBlank2 lda PPU_STATUS
bpl VBlank2
;VBlank1 jsr PPU_STATUS_R ;wait two frames
; bpl VBlank1
;VBlank2 jsr PPU_STATUS_R
; bpl VBlank2
ldy #ColdBootOffset ;load default cold boot pointer
ldx #$05 ;this is where we check for a warm boot
WBootCheck lda TopScoreDisplay,x ;check each score digit in the top score
@ -696,7 +752,8 @@ WBootCheck lda TopScoreDisplay,x ;check each score d
cmp #$a5 ;another location has a specific value
bne ColdBoot
ldy #WarmBootOffset ;if passed both, load warm boot pointer
ColdBoot jsr InitializeMemory ;clear memory using pointer in Y
ColdBoot
jsr InitializeMemory ;clear memory using pointer in Y
sta SND_DELTA_REG+1 ;reset delta counter load register
sta OperMode ;reset primary mode of operation
lda #$a5 ;set warm boot flag
@ -705,7 +762,7 @@ ColdBoot jsr InitializeMemory ;clear memory using
lda #%00001111
sta SND_MASTERCTRL_REG ;enable all sound channels except dmc
lda #%00000110
sta PPU_CTRL_REG2 ;turn off clipping for OAM and background
jsr PPU_MASK_W ;turn off clipping for OAM and background
jsr MoveAllSpritesOffscreen
jsr InitializeNameTables ;initialize both name tables
inc DisableScreenFlag ;set flag to disable screen output
@ -713,41 +770,41 @@ ColdBoot jsr InitializeMemory ;clear memory using
ora #%10000000 ;enable NMIs
jsr WritePPUReg1
; EndlessLoop jmp EndlessLoop ;endless loop, need I say more?
rtl ; GTE - Return to caller
InternalRts rts ; GTE - Return to caller
ds 17 ; Add back inthe bytes we commented out
;-------------------------------------------------------------------------------------
;$00 - vram buffer address table low, also used for pseudorandom bit
;$01 - vram buffer address table high
VRAM_AddrTable_Low
db <VRAM_Buffer1,<WaterPaletteData,
db <UndergroundPaletteData,<CastlePaletteData,
db <VRAM_Buffer2,<VRAM_Buffer2,
db <DaySnowPaletteData,<NightSnowPaletteData,
db <MarioThanksMessage,<LuigiThanksMessage,
db <PrincessSaved1,<PrincessSaved2,
db <WorldSelectMessage2
db <VRAM_Buffer1, <WaterPaletteData, <GroundPaletteData
db <UndergroundPaletteData, <CastlePaletteData, <VRAM_Buffer1_Offset
db <VRAM_Buffer2, <VRAM_Buffer2, <BowserPaletteData
db <DaySnowPaletteData, <NightSnowPaletteData, <MushroomPaletteData
db <MarioThanksMessage, <LuigiThanksMessage, <MushroomRetainerSaved
db <PrincessSaved1, <PrincessSaved2, <WorldSelectMessage1
db <WorldSelectMessage2
VRAM_AddrTable_High
db >VRAM_Buffer1,>WaterPaletteData,
db >UndergroundPaletteData,>CastlePaletteData,
db >VRAM_Buffer2,>VRAM_Buffer2,
db >DaySnowPaletteData,>NightSnowPaletteData,
db >MarioThanksMessage,>LuigiThanksMessage,
db >PrincessSaved1,>PrincessSaved2,
db >WorldSelectMessage2
db >VRAM_Buffer1, >WaterPaletteData, >GroundPaletteData
db >UndergroundPaletteData, >CastlePaletteData, >VRAM_Buffer1_Offset
db >VRAM_Buffer2, >VRAM_Buffer2, >BowserPaletteData
db >DaySnowPaletteData, >NightSnowPaletteData, >MushroomPaletteData
db >MarioThanksMessage, >LuigiThanksMessage, >MushroomRetainerSaved
db >PrincessSaved1, >PrincessSaved2, >WorldSelectMessage1
db >WorldSelectMessage2
VRAM_Buffer_Offset
db <VRAM_Buffer1_Offset,<VRAM_Buffer2_Offset
; This is the actual entry point (60 times per second to keep speeed). Uncomment hardware
; stuff that doesn't need to be communicated to the GTE wrapper
NonMaskableInterrupt
NonMaskableInterrupt ENT
lda Mirror_PPU_CTRL_REG1 ;disable NMIs in mirror reg
and #%01111111 ;save all other bits
sta Mirror_PPU_CTRL_REG1
and #%01111110 ;alter name table address to be $2800
sta PPU_CTRL_REG1 ;(essentially $2000) but save other bits
jsr PPU_CTRL_W ;(essentially $2000) but save other bits
lda Mirror_PPU_CTRL_REG2 ;disable OAM and background display by default
and #%11100110
ldy DisableScreenFlag ;get screen disable flag
@ -756,13 +813,13 @@ NonMaskableInterrupt
ora #%00011110
ScreenOff sta Mirror_PPU_CTRL_REG2 ;save bits for later but not in register at the moment
and #%11100111 ;disable screen for now
sta PPU_CTRL_REG2
ldx PPU_STATUS ;reset flip-flop and reset scroll registers to zero
jsr PPU_MASK_W
jsr PPU_STATUS_RX ;reset flip-flop and reset scroll registers to zero
lda #$00
jsr InitScroll
sta PPU_SPR_ADDR ;reset spr-ram address register
jsr OAM_ADDR_W ;reset spr-ram address register
lda #$02 ;perform spr-ram DMA access on $0200-$02ff
sta SPR_DMA
jsr SPR_DMA_W
ldx VRAM_Buffer_AddrCtrl ;load control for pointer to buffer contents
lda VRAM_AddrTable_Low,x ;set indirect at $00 to pointer
sta $00
@ -780,8 +837,12 @@ InitBuffer ldx VRAM_Buffer_Offset,y
sta VRAM_Buffer1,x
sta VRAM_Buffer_AddrCtrl ;reinit address control to $0301
lda Mirror_PPU_CTRL_REG2 ;copy mirror of $2001 to register
sta PPU_CTRL_REG2
jsr SoundEngine ;play sound
jsr PPU_MASK_W
; jsr SoundEngine ;play sound
bra *+3
ds 1
jsr ReadJoypads ;read joypads
jsr PauseRoutine ;handle pause
jsr UpdateTopScore
@ -821,37 +882,49 @@ RotPRandomBit ror PseudoRandomBitReg,x ;rotate carry into
bne RotPRandomBit
lda Sprite0HitDetectFlag ;check for flag here
beq SkipSprite0
Sprite0Clr lda PPU_STATUS ;wait for sprite 0 flag to clear, which will
and #%01000000 ;not happen until vblank has ended
bne Sprite0Clr
; With the GTE wrapper we render the status screen directly from the NES RAM area
; into a native output, so no need to busy-wait on Sprite 0 hit detection since
; there is no split-screen
;Sprite0Clr lda PPU_STATUS ;wait for sprite 0 flag to clear, which will
; and #%01000000 ;not happen until vblank has ended
; bne Sprite0Clr
bra *+7
ds 5
lda GamePauseStatus ;if in pause mode, do not bother with sprites at all
lsr
bcs Sprite0Hit
jsr MoveSpritesOffscreen
jsr SpriteShuffler
Sprite0Hit lda PPU_STATUS ;do sprite #0 hit detection
and #%01000000
beq Sprite0Hit
ldy #$14 ;small delay, to wait until we hit horizontal blank time
HBlankDelay dey
bne HBlankDelay
Sprite0Hit
; lda PPU_STATUS ;do sprite #0 hit detection
; and #%01000000
; beq Sprite0Hit
; ldy #$14 ;small delay, to wait until we hit horizontal blank time
;HBlankDelay dey
; bne HBlankDelay
bra *+12
ds 10
SkipSprite0 lda HorizontalScroll ;set scroll registers from variables
sta PPU_SCROLL_REG
jsr PPU_SCROLL_W
lda VerticalScroll
sta PPU_SCROLL_REG
jsr PPU_SCROLL_W
lda Mirror_PPU_CTRL_REG1 ;load saved mirror of $2000
pha
sta PPU_CTRL_REG1
jsr PPU_CTRL_W
lda GamePauseStatus ;if in pause mode, do not perform operation mode stuff
lsr
bcs SkipMainOper
jsr OperModeExecutionTree ;otherwise do one of many, many possible subroutines
SkipMainOper lda PPU_STATUS ;reset flip-flop
SkipMainOper jsr PPU_STATUS_R ;reset flip-flop
pla
ora #%10000000 ;reactivate NMIs
sta PPU_CTRL_REG1
jsr PPU_CTRL_W
; rti ;we are done until the next frame!
rtl
rts
;-------------------------------------------------------------------------------------
@ -1595,15 +1668,15 @@ DrawTitleScreen
lda OperMode ;are we in title screen mode?
bne IncModeTask_B ;if not, exit
lda #>TitleScreenDataOffset ;load address $1ec0 into
sta PPU_ADDRESS ;the vram address register
jsr PPU_ADDRESS_W ;the vram address register
lda #<TitleScreenDataOffset
sta PPU_ADDRESS
jsr PPU_ADDRESS_W
lda #$03 ;put address $0300 into
sta $01 ;the indirect at $00
ldy #$00
sty $00
lda PPU_DATA ;do one garbage read
OutputTScr lda PPU_DATA ;get title screen from chr-rom
jsr PPU_DATA_R ;do one garbage read
OutputTScr jsr PPU_DATA_R ;get title screen from chr-rom
sta ($00),y ;store 256 bytes into buffer
iny
bne ChkHiByte ;if not past 256 bytes, do not increment
@ -2125,10 +2198,10 @@ RemBridge lda BlockGfxData,x ;write top left and
;METATILE GRAPHICS TABLE
MetatileGraphics_Low
db <Palette0_MTiles,<Palette1_MTiles,
db <Palette0_MTiles, <Palette1_MTiles, <Palette2_MTiles, <Palette3_MTiles
MetatileGraphics_High
db >Palette0_MTiles,>Palette1_MTiles,
db >Palette0_MTiles, >Palette1_MTiles, >Palette2_MTiles, >Palette3_MTiles
Palette0_MTiles
db $24,$24,$24,$24 ;blank
@ -2384,15 +2457,21 @@ JumpEngine
iny
lda ($04),y ;load pointer from indirect
sta $06 ;note that if an RTS is performed in next routine
sta :je_patch+1
iny ;it will return to the execution before the sub
lda ($04),y ;that called this routine
sta $07
jmp ($06) ;jump to the address we loaded
sta :je_patch+2
; jmp ($06) ;jump to the address we loaded
; GTE Note: We run in a different bank with a direct page != 0, so jmp (abs) cannot work, but we're in RAM now
; so self-modifying code to the rescue
:je_patch jmp $0000
;-------------------------------------------------------------------------------------
InitializeNameTables
lda PPU_STATUS ;reset flip-flop
jsr PPU_STATUS_R ;reset flip-flop
lda Mirror_PPU_CTRL_REG1 ;load mirror of ppu reg $2000
ora #%00010000 ;set sprites for first 4k and background for second 4k
and #%11110000 ;clear rest of lower nybble, leave higher alone
@ -2400,13 +2479,13 @@ InitializeNameTables
lda #$24 ;set vram address to start of name table 1
jsr WriteNTAddr
lda #$20 ;and then set it to name table 0
WriteNTAddr sta PPU_ADDRESS
WriteNTAddr jsr PPU_ADDRESS_W
lda #$00
sta PPU_ADDRESS
jsr PPU_ADDRESS_W
ldx #$04 ;clear name table with blank tile #24
ldy #$c0
lda #$24
InitNTLoop sta PPU_DATA ;count out exactly 768 tiles
InitNTLoop jsr PPU_DATA_W ;count out exactly 768 tiles
dey
bne InitNTLoop
dex
@ -2415,7 +2494,7 @@ InitNTLoop sta PPU_DATA ;count out exactly
txa
sta VRAM_Buffer1_Offset ;init vram buffer 1 offset
sta VRAM_Buffer1 ;init vram buffer 1
InitATLoop sta PPU_DATA
InitATLoop jsr PPU_DATA_W
dey
bne InitATLoop
sta HorizontalScroll ;reset scroll variables
@ -2424,7 +2503,7 @@ InitATLoop sta PPU_DATA
;-------------------------------------------------------------------------------------
;$00 - temp joypad bit
native_joy EXT
ReadJoypads
lda #$01 ;reset and clear strobe of joypad ports
sta JOYPAD_PORT
@ -2433,17 +2512,20 @@ ReadJoypads
sta JOYPAD_PORT
jsr ReadPortBits
inx ;increment for joypad 2's port
ReadPortBits ldy #$08
PortLoop pha ;push previous bit onto stack
lda JOYPAD_PORT,x ;read current bit on joypad port
sta $00 ;check d1 and d0 of port output
lsr ;this is necessary on the old
ora $00 ;famicom systems in japan
lsr
pla ;read bits from stack
rol ;rotate bit from carry flag
dey
bne PortLoop ;count down bits left
ReadPortBits
; ldy #$08
;PortLoop pha ;push previous bit onto stack
; lda JOYPAD_PORT,x ;read current bit on joypad port
; sta $00 ;check d1 and d0 of port output
; lsr ;this is necessary on the old
; ora $00 ;famicom systems in japan
; lsr
; pla ;read bits from stack
; rol ;rotate bit from carry flag
; dey
; bne PortLoop ;count down bits left
ldal native_joy,x
sta SavedJoypadBits,x ;save controller status here always
pha
and #%00110000 ;check for select or start
@ -2462,10 +2544,10 @@ Save8Bits pla
;$01 - vram buffer address table high
WriteBufferToScreen
sta PPU_ADDRESS ;store high byte of vram address
jsr PPU_ADDRESS_W ;store high byte of vram address
iny
lda ($00),y ;load next byte (second)
sta PPU_ADDRESS ;store low byte of vram address
jsr PPU_ADDRESS_W ;store low byte of vram address
iny
lda ($00),y ;load next byte (third)
asl ;shift to left and save in stack
@ -2486,7 +2568,7 @@ GetLength lsr ;shift back to the
OutputToVRAM bcs RepeatByte ;if carry set, repeat loading the same byte
iny ;otherwise increment Y to load next byte
RepeatByte lda ($00),y ;load more data from buffer and write to vram
sta PPU_DATA
jsr PPU_DATA_W
dex ;done writing?
bne OutputToVRAM
sec
@ -2497,23 +2579,23 @@ RepeatByte lda ($00),y ;load more data fro
adc $01
sta $01
lda #$3f ;sets vram address to $3f00
sta PPU_ADDRESS
jsr PPU_ADDRESS_W
lda #$00
sta PPU_ADDRESS
sta PPU_ADDRESS ;then reinitializes it for some reason
sta PPU_ADDRESS
UpdateScreen ldx PPU_STATUS ;reset flip-flop
jsr PPU_ADDRESS_W
jsr PPU_ADDRESS_W ;then reinitializes it for some reason
jsr PPU_ADDRESS_W
UpdateScreen jsr PPU_STATUS_RX ;reset flip-flop
ldy #$00 ;load first byte from indirect as a pointer
lda ($00),y
bne WriteBufferToScreen ;if byte is zero we have no further updates to make here
InitScroll sta PPU_SCROLL_REG ;store contents of A into scroll registers
sta PPU_SCROLL_REG ;and end whatever subroutine led us here
InitScroll jsr PPU_SCROLL_W ;store contents of A into scroll registers
jsr PPU_SCROLL_W ;and end whatever subroutine led us here
rts
;-------------------------------------------------------------------------------------
WritePPUReg1
sta PPU_CTRL_REG1 ;write contents of A to PPU register 1
jsr PPU_CTRL_W ;write contents of A to PPU register 1
sta Mirror_PPU_CTRL_REG1 ;and its mirror
rts
@ -2763,8 +2845,8 @@ ISpr0Loop lda Sprite0Data,y
sta Sprite_Data,y
dey
bpl ISpr0Loop
jsr DoNothing2 ;these jsrs doesn't do anything useful
jsr DoNothing1
; jsr DoNothing2 ;these jsrs doesn't do anything useful
; jsr DoNothing1
inc Sprite0HitDetectFlag ;set sprite #0 check flag
inc OperMode_Task ;increment to next task
rts
@ -4329,8 +4411,8 @@ GetAreaObjYPosition
;$06-$07 - used to store block buffer address used as indirect
BlockBufferAddr
db <Block_Buffer_1, <Block_Buffer_2
db >Block_Buffer_1, >Block_Buffer_2
db <Block_Buffer_1, <Block_Buffer_2
db >Block_Buffer_1, >Block_Buffer_2
GetBlockBufferAddr
pha ;take value of A, save
@ -4492,39 +4574,39 @@ EnemyAddrHOffsets
db $1f,$06,$1c,$00
EnemyDataAddrLow
db <E_CastleArea1, <E_CastleArea2,
db <E_GroundArea1, <E_GroundArea2,
db <E_GroundArea7, <E_GroundArea8,
db <E_GroundArea13, <E_GroundArea14,
db <E_GroundArea19, <E_GroundArea20,
db <E_UndergroundArea2, <E_UndergroundArea3,
db <E_CastleArea1, <E_CastleArea2, <E_CastleArea3, <E_CastleArea4, <E_CastleArea5, <E_CastleArea6
db <E_GroundArea1, <E_GroundArea2, <E_GroundArea3, <E_GroundArea4, <E_GroundArea5, <E_GroundArea6
db <E_GroundArea7, <E_GroundArea8, <E_GroundArea9, <E_GroundArea10, <E_GroundArea11, <E_GroundArea12
db <E_GroundArea13, <E_GroundArea14, <E_GroundArea15, <E_GroundArea16, <E_GroundArea17, <E_GroundArea18
db <E_GroundArea19, <E_GroundArea20, <E_GroundArea21, <E_GroundArea22, <E_UndergroundArea1
db <E_UndergroundArea2, <E_UndergroundArea3, <E_WaterArea1, <E_WaterArea2, <E_WaterArea3
EnemyDataAddrHigh
db >E_CastleArea1, >E_CastleArea2,
db >E_GroundArea1, >E_GroundArea2,
db >E_GroundArea7, >E_GroundArea8,
db >E_GroundArea13, >E_GroundArea14,
db >E_GroundArea19, >E_GroundArea20,
db >E_UndergroundArea2, >E_UndergroundArea3,
db >E_CastleArea1, >E_CastleArea2, >E_CastleArea3, >E_CastleArea4, >E_CastleArea5, >E_CastleArea6
db >E_GroundArea1, >E_GroundArea2, >E_GroundArea3, >E_GroundArea4, >E_GroundArea5, >E_GroundArea6
db >E_GroundArea7, >E_GroundArea8, >E_GroundArea9, >E_GroundArea10, >E_GroundArea11, >E_GroundArea12
db >E_GroundArea13, >E_GroundArea14, >E_GroundArea15, >E_GroundArea16, >E_GroundArea17, >E_GroundArea18
db >E_GroundArea19, >E_GroundArea20, >E_GroundArea21, >E_GroundArea22, >E_UndergroundArea1
db >E_UndergroundArea2, >E_UndergroundArea3, >E_WaterArea1, >E_WaterArea2, >E_WaterArea3
AreaDataHOffsets
db $00,$03,$19,$1c
AreaDataAddrLow
db <L_WaterArea1, <L_WaterArea2,
db <L_GroundArea4, <L_GroundArea5,
db <L_GroundArea10, <L_GroundArea11,
db <L_GroundArea16, <L_GroundArea17,
db <L_GroundArea22, <L_UndergroundArea1,
db <L_CastleArea2, <L_CastleArea3,
db <L_WaterArea1, <L_WaterArea2, <L_WaterArea3, <L_GroundArea1, <L_GroundArea2, <L_GroundArea3
db <L_GroundArea4, <L_GroundArea5, <L_GroundArea6, <L_GroundArea7, <L_GroundArea8, <L_GroundArea9
db <L_GroundArea10, <L_GroundArea11, <L_GroundArea12, <L_GroundArea13, <L_GroundArea14, <L_GroundArea15
db <L_GroundArea16, <L_GroundArea17, <L_GroundArea18, <L_GroundArea19, <L_GroundArea20, <L_GroundArea21
db <L_GroundArea22, <L_UndergroundArea1, <L_UndergroundArea2, <L_UndergroundArea3, <L_CastleArea1
db <L_CastleArea2, <L_CastleArea3, <L_CastleArea4, <L_CastleArea5, <L_CastleArea6
AreaDataAddrHigh
db >L_WaterArea1, >L_WaterArea2,
db >L_GroundArea4, >L_GroundArea5,
db >L_GroundArea10, >L_GroundArea11,
db >L_GroundArea16, >L_GroundArea17,
db >L_GroundArea22, >L_UndergroundArea1,
db >L_CastleArea2, >L_CastleArea3,
db >L_WaterArea1, >L_WaterArea2, >L_WaterArea3, >L_GroundArea1, >L_GroundArea2, >L_GroundArea3
db >L_GroundArea4, >L_GroundArea5, >L_GroundArea6, >L_GroundArea7, >L_GroundArea8, >L_GroundArea9
db >L_GroundArea10, >L_GroundArea11, >L_GroundArea12, >L_GroundArea13, >L_GroundArea14, >L_GroundArea15
db >L_GroundArea16, >L_GroundArea17, >L_GroundArea18, >L_GroundArea19, >L_GroundArea20, >L_GroundArea21
db >L_GroundArea22, >L_UndergroundArea1, >L_UndergroundArea2, >L_UndergroundArea3, >L_CastleArea1
db >L_CastleArea2, >L_CastleArea3, >L_CastleArea4, >L_CastleArea5, >L_CastleArea6
;ENEMY OBJECT DATA
@ -15987,16 +16069,16 @@ MusicHeaderData
db Star_CloudHdr-MHD
db SilenceHdr-MHD
db GroundLevelLeadInHdr-MHD ;ground level music layout
db GroundLevelPart1Hdr-MHD, GroundLevelPart1Hdr-MHD
db GroundLevelPart2AHdr-MHD, GroundLevelPart2BHdr-MHD,
db GroundLevelPart2AHdr-MHD, GroundLevelPart2BHdr-MHD,
db GroundLevelPart3AHdr-MHD, GroundLevelPart3BHdr-MHD,
db GroundLevelPart1Hdr-MHD, GroundLevelPart1Hdr-MHD
db GroundLevelPart4AHdr-MHD, GroundLevelPart4BHdr-MHD,
db GroundLevelPart4AHdr-MHD, GroundLevelPart4BHdr-MHD,
db GroundLevelPart3AHdr-MHD, GroundLevelPart3BHdr-MHD,
db GroundLevelPart4AHdr-MHD, GroundLevelPart4BHdr-MHD,
db GroundLevelLeadInHdr-MHD ;ground level music layout
db GroundLevelPart1Hdr-MHD, GroundLevelPart1Hdr-MHD
db GroundLevelPart2AHdr-MHD, GroundLevelPart2BHdr-MHD, GroundLevelPart2AHdr-MHD, GroundLevelPart2CHdr-MHD
db GroundLevelPart2AHdr-MHD, GroundLevelPart2BHdr-MHD, GroundLevelPart2AHdr-MHD, GroundLevelPart2CHdr-MHD
db GroundLevelPart3AHdr-MHD, GroundLevelPart3BHdr-MHD, GroundLevelPart3AHdr-MHD, GroundLevelLeadInHdr-MHD
db GroundLevelPart1Hdr-MHD, GroundLevelPart1Hdr-MHD
db GroundLevelPart4AHdr-MHD, GroundLevelPart4BHdr-MHD, GroundLevelPart4AHdr-MHD, GroundLevelPart4CHdr-MHD
db GroundLevelPart4AHdr-MHD, GroundLevelPart4BHdr-MHD, GroundLevelPart4AHdr-MHD, GroundLevelPart4CHdr-MHD
db GroundLevelPart3AHdr-MHD, GroundLevelPart3BHdr-MHD, GroundLevelPart3AHdr-MHD, GroundLevelLeadInHdr-MHD
db GroundLevelPart4AHdr-MHD, GroundLevelPart4BHdr-MHD, GroundLevelPart4AHdr-MHD, GroundLevelPart4CHdr-MHD
;music headers
;header format is as follows
@ -16006,28 +16088,28 @@ MusicHeaderData
;1 byte - square 1 data offset
;1 byte - noise data offset (not used by secondary music)
TimeRunningOutHdr db $08, <TimeRunOutMusData,
Star_CloudHdr db $20, <Star_CloudMData,
EndOfLevelMusHdr db $20, <WinLevelMusData,
ResidualHeaderData db $20,$c4,$fc,$3f,$1d
UndergroundMusHdr db $18, <UndergroundMusData,
SilenceHdr db $08, <SilenceData,
CastleMusHdr db $00, <CastleMusData,
VictoryMusHdr db $10, <VictoryMusData,
GameOverMusHdr db $18, <GameOverMusData,
WaterMusHdr db $08, <WaterMusData,
WinCastleMusHdr db $08, <EndOfCastleMusData,
GroundLevelPart1Hdr db $18, <GroundM_P1Data,
GroundLevelPart2AHdr db $18, <GroundM_P2AData,
GroundLevelPart2BHdr db $18, <GroundM_P2BData,
GroundLevelPart2CHdr db $18, <GroundM_P2CData,
GroundLevelPart3AHdr db $18, <GroundM_P3AData,
GroundLevelPart3BHdr db $18, <GroundM_P3BData,
GroundLevelLeadInHdr db $18, <GroundMLdInData,
GroundLevelPart4AHdr db $18, <GroundM_P4AData,
GroundLevelPart4BHdr db $18, <GroundM_P4BData,
GroundLevelPart4CHdr db $18, <GroundM_P4CData,
DeathMusHdr db $18, <DeathMusData,
TimeRunningOutHdr db $08, <TimeRunOutMusData, >TimeRunOutMusData, $27, $18
Star_CloudHdr db $20, <Star_CloudMData, >Star_CloudMData, $2e, $1a, $40
EndOfLevelMusHdr db $20, <WinLevelMusData, >WinLevelMusData, $3d, $21
ResidualHeaderData db $20, $c4, $fc, $3f, $1d
UndergroundMusHdr db $18, <UndergroundMusData, >UndergroundMusData, $00, $00
SilenceHdr db $08, <SilenceData, >SilenceData, $00
CastleMusHdr db $00, <CastleMusData, >CastleMusData, $93, $62
VictoryMusHdr db $10, <VictoryMusData, >VictoryMusData, $24, $14
GameOverMusHdr db $18, <GameOverMusData, >GameOverMusData, $1e, $14
WaterMusHdr db $08, <WaterMusData, >WaterMusData, $a0, $70, $68
WinCastleMusHdr db $08, <EndOfCastleMusData, >EndOfCastleMusData, $4c, $24
GroundLevelPart1Hdr db $18, <GroundM_P1Data, >GroundM_P1Data, $2d, $1c, $b8
GroundLevelPart2AHdr db $18, <GroundM_P2AData, >GroundM_P2AData, $20, $12, $70
GroundLevelPart2BHdr db $18, <GroundM_P2BData, >GroundM_P2BData, $1b, $10, $44
GroundLevelPart2CHdr db $18, <GroundM_P2CData, >GroundM_P2CData, $11, $0a, $1c
GroundLevelPart3AHdr db $18, <GroundM_P3AData, >GroundM_P3AData, $2d, $10, $58
GroundLevelPart3BHdr db $18, <GroundM_P3BData, >GroundM_P3BData, $14, $0d, $3f
GroundLevelLeadInHdr db $18, <GroundMLdInData, >GroundMLdInData, $15, $0d, $21
GroundLevelPart4AHdr db $18, <GroundM_P4AData, >GroundM_P4AData, $18, $10, $7a
GroundLevelPart4BHdr db $18, <GroundM_P4BData, >GroundM_P4BData, $19, $0f, $54
GroundLevelPart4CHdr db $18, <GroundM_P4CData, >GroundM_P4CData, $1e, $12, $2b
DeathMusHdr db $18, <DeathMusData, >DeathMusData, $1e, $0f, $2d
;--------------------------------

View File

@ -180,6 +180,8 @@ scanlineHorzOffset equ $0001
scanlineHorzOffset2 equ $0002
tileStore equ $0003
vblCallback equ $0004
extSpriteRenderer equ $0005
rawDrawTile equ $0006
; CopyPicToBG1 flags
COPY_PIC_NORMAL equ $0000 ; Copy into BG1 buffer in "normal mode"

View File

@ -193,6 +193,8 @@ scanlineHorzOffset equ $0001 ; Table of 416 words, a double-array o
scanlineHorzOffset2 equ $0002 ; Table of 416 words, a double-array of scanline offset values. Values must be in range [0, 163]
tileStore equ $0003
vblCallback equ $0004 ; User routine to be called by VBL interrupt. Set to $000000 to disconnect
extSpriteRenderer equ $0005
rawDrawTile equ $0006
; CopyPicToBG1 flags
COPY_PIC_NORMAL equ $0000 ; Copy into BG1 buffer in "normal mode" treating the buffer as a 164x208 pixmap with stride of 256
@ -307,6 +309,7 @@ ObjectList EXT
StartXMod164Tbl EXT
LastOffsetTbl EXT
BG1StartXMod164Tbl EXT
ExtSpriteRenderer EXT
; Tool error codes
NO_TIMERS_AVAILABLE equ 10

View File

@ -60,7 +60,7 @@ _Render
jsr _ApplyTiles ; This function actually draws the new tiles into the code field
jsr _ApplyBG0XPos ; Patch the code field instructions with exit BRA opcode
jsr _ApplyBG0XPos ; Patch the code field instructions with exit BRA opcode
lda #RENDER_BG1_ROTATION
bit RenderFlags
@ -153,6 +153,87 @@ _DoOverlay
:disp jsl $000000
rts
; Special NES renderer that externalizes the sprite rendreing in order to exceed the internal limit of 16 sprites
_RenderNES
jsr _ApplyBG0YPos
jsr _ApplyBG0XPosPre
jsr _ApplyTiles ; This function actually draws the new tiles into the code field
; jsr _ApplyBG0XPos ; Patch the code field instructions with exit BRA opcode
stz tmp1 ; virt_line_x2
lda #16*2
sta tmp2 ; lines_left_x2
lda #0 ; Xmod164
jsr _ApplyBG0XPosAlt
lda tmp4 ; :exit_offset
stal nesTopOffset
lda #16*2
sta tmp1 ; virt_line_x2
lda ScreenHeight
sec
sbc #16
asl
sta tmp2 ; lines_left_x2
lda StartXMod164 ; Xmod164
jsr _ApplyBG0XPosAlt
lda tmp4
stal nesBottomOffset
ldx #0 ; Blit the full virtual buffer to the screen
ldy ScreenHeight
jsr _BltRange
lda ExtSpriteRenderer
ora ExtSpriteRenderer+2
beq :no_sprite
lda ExtSpriteRenderer
stal :patch+1
lda ExtSpriteRenderer+1
stal :patch+2
:patch jsl $000000
:no_sprite
stz tmp1 ; :virt_line_x2
lda #16*2
sta tmp2 ; :lines_left_x2
ldal nesTopOffset
sta tmp4 ; :exit_offset
jsr _RestoreBG0OpcodesAlt
lda #16*2
sta tmp1 ; :virt_line_x2
lda ScreenHeight
sec
sbc #16
asl
sta tmp2 ; lines_left_x2
ldal nesBottomOffset
sta tmp4 ; :exit_offset
jsr _RestoreBG0OpcodesAlt
; lda StartYMod208 ; Restore the fields back to their original state
; ldx ScreenHeight
; jsr _RestoreBG0Opcodes
lda StartY
sta OldStartY
lda StartX
sta OldStartX
lda BG1StartY
sta OldBG1StartY
lda BG1StartX
sta OldBG1StartX
stz DirtyBits
stz LastRender ; Mark that a full render was just performed
rts
nesTopOffset ds 2
nesBottomOffset ds 2
; Use the per-scanline tables to set the screen. This is really meant to be used without the built-in tilemap
; support and is more of a low-level way to control the background rendering

View File

@ -137,6 +137,33 @@ RTL_OPCODE equ $6B
lda :rtnval ; Address in the compile memory
rts
; Draw a tile directly to the graphics screen as a sprite
;
; Y = screen address
; X = tile address
; A = $0001 = ignore mask
_DrawTileToScreen
phb
pea $0101
plb
plb
]line equ 0
lup 8
lda: {]line*SHR_LINE_WIDTH}+2,y
andl tiledata+{]line*4}+32+2,x
oral tiledata+{]line*4}+2,x
sta: {]line*SHR_LINE_WIDTH}+2,y
lda: {]line*SHR_LINE_WIDTH},y
andl tiledata+{]line*4}+32,x
oral tiledata+{]line*4},x
sta: {]line*SHR_LINE_WIDTH},y
]line equ ]line+1
--^
plb
rtl ; special exit
; Draw a sprite directly to the graphics screen. If sprite is clipped at all, do not draw.
;
; X = sprite record index

View File

@ -298,6 +298,9 @@ _TSRender
_TSEntry
lda :flags,s
cmp #$FFFF ; Hack! Special mode...
beq :nes
bit #RENDER_WITH_SHADOWING
beq :no_shadowing
jsr _RenderWithShadowing
@ -311,6 +314,10 @@ _TSRender
:no_scanline
jsr _Render
bra :done
:nes
jsr _RenderNES
:done
_TSExit #0;#2
@ -915,7 +922,16 @@ _TSGetAddress
lda BG1StartXMod164Tbl+2
sta :output+2,s
bra :out
:next_2
:next_2 cmp #rawDrawTile
bne :next_3
lda #_DrawTileToScreen
sta :output,s
lda #^_DrawTileToScreen
sta :output+2,s
bra :out
:next_3
:out
_TSExit #0;#2
@ -933,7 +949,7 @@ _TSSetAddress
sta StartXMod164Tbl
lda :ptr+2,s
sta StartXMod164Tbl+2
bra :out
brl :out
:next_1
cmp #scanlineHorzOffset2
@ -943,7 +959,7 @@ _TSSetAddress
sta BG1StartXMod164Tbl
lda :ptr+2,s
sta BG1StartXMod164Tbl+2
bra :out
brl :out
:next_2 cmp #vblCallback
bne :next_3
@ -956,15 +972,25 @@ _TSSetAddress
stal _VblTaskPatch+1 ; long addressing because we're patching code in the K bank
lda :ptr+1,s
stal _VblTaskPatch+2
bra :out
brl :out
:vbl_restore
lda #_TaskStub
stal _VblTaskPatch+1
lda #>_TaskStub
stal _VblTaskPatch+2
brl :out
:next_3 cmp #extSpriteRenderer
bne :next_4
lda :ptr,s
sta ExtSpriteRenderer
lda :ptr+2,s
sta ExtSpriteRenderer+2
bra :out
:next_3
:next_4
:out
_TSExit #0;#6

View File

@ -153,11 +153,11 @@ _ApplyBG0XPos
; If there are saved opcodes that have not been restored, do not run this routine
lda LastPatchOffset
beq :ok
beq *+3
rts
; This code is fairly succinct. See the corresponding code in Vert.s for more detailed comments.
:ok
lda StartYMod208 ; This is the base line of the virtual screen
asl
sta :virt_line_x2 ; Keep track of it
@ -228,7 +228,8 @@ _ApplyBG0XPos
lda StartXMod164
; Alternate entry point if the virt_line_x2 and lines_left_x2 and XMod164 values are passed in externally
_ApplyBG0XPosAlt
_RestoreBG0OpcodesAlt
:stk_save equ tmp0
:virt_line_x2 equ tmp1
:lines_left_x2 equ tmp2

View File

@ -560,6 +560,9 @@ _stamp_step ENT
BG1YCache ENT
ds 32
ExtSpriteRenderer ENT
dw 0,0
; Scaling tables for the BG1 rotation tables.
ScalingTables ENT
dw Scale0,Scale1,Scale2,Scale3