diff --git a/assets/gba-cloud-bgnd-8-color.png b/assets/gba-cloud-bgnd-8-color.png new file mode 100644 index 0000000..efaa328 Binary files /dev/null and b/assets/gba-cloud-bgnd-8-color.png differ diff --git a/assets/gba-cloud-bgnd.png b/assets/gba-cloud-bgnd.png new file mode 100644 index 0000000..e8ee06b Binary files /dev/null and b/assets/gba-cloud-bgnd.png differ diff --git a/assets/smb-2bit-328x208-shift.png b/assets/smb-2bit-328x208-shift.png new file mode 100644 index 0000000..91a66de Binary files /dev/null and b/assets/smb-2bit-328x208-shift.png differ diff --git a/assets/smb-2bit-328x208.png b/assets/smb-2bit-328x208.png new file mode 100644 index 0000000..56b58de Binary files /dev/null and b/assets/smb-2bit-328x208.png differ diff --git a/assets/smb-2bit-512x223.png b/assets/smb-2bit-512x223.png new file mode 100644 index 0000000..a8965bd Binary files /dev/null and b/assets/smb-2bit-512x223.png differ diff --git a/build-image.bat b/build-image.bat index f526bd4..be18e14 100644 --- a/build-image.bat +++ b/build-image.bat @@ -15,4 +15,5 @@ REM Cadius does not overwrite files, so clear the root folder first REM Now copy files and folders as needed %CADIUS% ADDFILE %IMAGE% %FOLDER% src\\GTETestApp %CADIUS% ADDFILE %IMAGE% %FOLDER% emu\\test.pic -%CADIUS% ADDFILE %IMAGE% %FOLDER% emu\\bg1.bin +%CADIUS% ADDFILE %IMAGE% %FOLDER% emu\\bg1a.bin +%CADIUS% ADDFILE %IMAGE% %FOLDER% emu\\bg1b.bin diff --git a/package.json b/package.json index 925551d..f9f67e6 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "debug": "%npm_package_config_crossrunner% src\\GTETestApp -Source src\\GTETestApp_S02_MAINSEG_Output.txt -Debug -CompatibilityLayer", "build": "%npm_package_config_merlin32% -V %npm_package_config_macros% src\\App.s", "build:watch": "watch \"npm run build\" src", - "build:assets": "node ./tools/pngtoiigs.js ./assets/gba-cloud-bgnd-8-color.png ./emu/bg1.bin" + "build:assets": "node ./tools/pngtoiigs.js ./assets/smb-2bit-328x208.png ./emu/bg1a.bin && node ./tools/pngtoiigs.js ./assets/smb-2bit-328x208-shift.png ./emu/bg1b.bin" }, "repository": { "type": "git", diff --git a/src/Actions.s b/src/Actions.s index f27536a..6a40663 100644 --- a/src/Actions.s +++ b/src/Actions.s @@ -1,10 +1,12 @@ MoveLeft clc adc StartX ; Increment the virtual X-position - cmp #164 - bcc *+5 - lda #0 jsr SetBG0XPos + + lda StartX + lsr + jsr SetBG1XPos + jsr DoFrame rts @@ -84,3 +86,4 @@ Demo FPSStr str 'FPS' + diff --git a/src/App.Init.s b/src/App.Init.s index dc51b72..ea48faf 100644 --- a/src/App.Init.s +++ b/src/App.Init.s @@ -51,10 +51,13 @@ MemInit PushLong #0 ; space for result _Deref stx BlitterDP -; Allocate a bank of memory for BG1 +; Allocate banks of memory for BG1 jsr AllocOneBank2 sta BG1DataBank + jsr AllocOneBank2 + sta BG1AltBank + ; Allocate the 13 banks of memory we need and store in double-length array ]step equ 0 lup 13 @@ -200,5 +203,6 @@ ShutDown rts + diff --git a/src/App.Main.s b/src/App.Main.s index 64caf5b..4a503be 100644 --- a/src/App.Main.s +++ b/src/App.Main.s @@ -102,6 +102,9 @@ NO_INTERRUPTS equ 0 ; turn off for crossrunner jsr _InitBG1 ; Initialize the second background + lda #0 + jsr _ClearBG1Buffer + ; Load a picture and copy it into Bank $E1. Then turn on the screen. jsr AllocOneBank ; Alloc 64KB for Load/Unpack @@ -303,7 +306,7 @@ DoTiles :rowloop lda #0 sta :column,s - lda #$0015 + lda #$0010 sta :tile,s :colloop @@ -314,9 +317,9 @@ DoTiles lda :tile,s jsr CopyTile - lda :tile,s - eor #$0003 - sta :tile,s +; lda :tile,s +; eor #$0003 +; sta :tile,s lda :column,s inc @@ -344,12 +347,34 @@ DoFrame ; Load a binary file in the BG1 buffer DoLoadBG1 - lda BG1DataBank - xba - and #$FF00 - ora #$0001 ; Load directly into the BG1 buffer bank on Page 1 + lda BankLoad ldx #BG1DataFile jsr LoadFile + + lda BankLoad + xba + pha + and #$00FF + tax + pla + and #$FF00 + ldy BG1DataBank + jsr CopyBinToBG1 + + lda BankLoad + ldx #BG1AltDataFile + jsr LoadFile + + lda BankLoad + xba + pha + and #$00FF + tax + pla + and #$FF00 + ldy BG1AltBank + jsr CopyBinToBG1 + rts ; Load a simple picture format onto the SHR screen @@ -448,6 +473,56 @@ CopyPicToField rts +; Copy a binary image data file into BG1. Assumes the file is the correct size. +; +; A=low word of picture address +; X=high word of pixture address +; Y=high word of BG1 bank + +CopyBinToBG1 +:srcptr equ tmp0 +:line_cnt equ tmp2 +:dstptr equ tmp3 +:col_cnt equ tmp5 + + sta :srcptr + stx :srcptr+2 + sty :dstptr+2 ; Everything goes into this bank + + stz :line_cnt +:rloop + lda :line_cnt ; get the pointer to the code field line + asl + tax + + lda BG1YTable,x + sta :dstptr + + ldy #0 ; move forward in the image data and image data +:cloop + lda [:srcptr],y + sta [:dstptr],y + + iny + iny + + cpy #164 + bcc :cloop + + lda [:srcptr] ; Duplicate the last byte in the extra space at the end of the line + sta [:dstptr],y + + lda :srcptr + clc + adc #164 ; Each line is 328 pixels + sta :srcptr + + inc :line_cnt + lda :line_cnt + cmp #208 ; A total of 208 lines + bcc :rloop + rts + **************************************** * Fatal Error Handler * **************************************** @@ -536,7 +611,8 @@ GrafInit dw $0fa9,$0ff0,$00e0,$04DF dw $0d00,$078f,$0ccc,$0FFF -DefaultPalette dw $0ADF,$0FF8,$0CD6,$09CF,$0AC6,$08A5,$0FFF,$0694 +DefaultPalette dw $09BE,$0AA6,$0DC9,$0DB7,$09AA + dw $0080,$0f70,$0FFF dw $0fa9,$0ff0,$00e0,$04DF dw $0d00,$078f,$0ccc,$0FFF @@ -735,7 +811,9 @@ msgLine3 str ' -> Return to Try Again' msgLine4 str ' -> Esc to Quit' ; Data storage -BG1DataFile strl '1/bg1.bin' +BG1DataFile strl '1/bg1a.bin' +BG1AltDataFile strl '1/bg1b.bin' + ImageName strl '1/test.pic' MasterId ds 2 UserId ds 2 @@ -785,4 +863,23 @@ qtRec adrl $0000 + + + + + + + + + + + + + + + + + + + diff --git a/src/Render.s b/src/Render.s index 83e0df6..10d4e0c 100644 --- a/src/Render.s +++ b/src/Render.s @@ -67,6 +67,7 @@ Render jsr _ApplyBG0XPos ; Patch the PEA instructions with exit BRA opcode jsr _ApplyBG0YPos ; Set stack addresses for the virtual lines to the physical screen jsr _ApplyBG1XPos ; Adjust the direct page pointers to the BG1 bank + jsr _ApplyBG1YPos ldx #0 ; Blit the full virtual buffer to the screen ldy ScreenHeight @@ -88,3 +89,4 @@ Render + diff --git a/src/blitter/BG1.s b/src/blitter/BG1.s index 022fcf1..4c49872 100644 --- a/src/blitter/BG1.s +++ b/src/blitter/BG1.s @@ -4,6 +4,10 @@ _InitBG1 jsr _ApplyBG1YPos rts +SetBG1XPos + sta BG1StartX + rts + ; Everytime either BG1 or BG0 X-position changes, we have to update the direct page values. We ; *could* do this by adjusting the since address offset, but we have to change up to 200 values ; when the vertical position changes, and only 41 when the horizontal value changes. Plus @@ -11,12 +15,21 @@ _InitBG1 ; ; Note: This routine can be optimized as an unrolled loop of PEI instructions _ApplyBG1XPos + lda BG1StartX + jsr Mod164 + sta BG1StartXMod164 + lda #162 sec sbc StartXMod164 bpl *+6 clc adc #164 + clc + adc BG1StartXMod164 + cmp #164 + bcc *+5 + sbc #164 tay phd ; save the direct page because we are going to switch to the @@ -39,6 +52,28 @@ _ApplyBG1XPos pld rts +_ClearBG1Buffer + phb + pha + sep #$20 + lda BG1DataBank + pha + plb + rep #$20 + + pla + ldx #0 +:loop + sta: $0000,x + inc + inx + inx + cpx #0 + bne :loop + + plb + rts + ; Everytime either BG1 or BG0 Y-position changes, we have to update the Y-register ; value in all of the code fields (within the visible screen) _ApplyBG1YPos @@ -47,7 +82,7 @@ _ApplyBG1YPos :draw_count equ tmp2 :ytbl_idx equ tmp3 - stz :rtbl_idx ; Start copying from the first entry in the table + stz :ytbl_idx ; Start copying from the first entry in the table lda StartY ; This is the base line of the virtual screen sta :virt_line ; Keep track of it @@ -194,6 +229,18 @@ CopyBG1YTableToBG1Addr + + + + + + + + + + + + diff --git a/src/blitter/Blitter.s b/src/blitter/Blitter.s index 30c83b2..ea7846b 100644 --- a/src/blitter/Blitter.s +++ b/src/blitter/Blitter.s @@ -54,7 +54,13 @@ _BltRange ; Now we need to set up the Bank, Stack Pointer and Direct Page registers for calling into ; the code field - lda BG1DataBank ; Set the data bank for BG1 data + lda StartX + bit #$01 + beq :primary + lda BG1AltBank + bra :alt +:primary lda BG1DataBank +:alt pha plb rep #$20 @@ -84,3 +90,4 @@ stk_save lda #0000 ; load the stack plb ; restore the bank rts + diff --git a/src/blitter/DirectPage.s b/src/blitter/DirectPage.s index ac331a3..b4bdc82 100644 --- a/src/blitter/DirectPage.s +++ b/src/blitter/DirectPage.s @@ -15,13 +15,18 @@ EngineMode equ 20 ; Defined the mode/capabilities that are ena DirtyBits equ 22 ; Identify values that have changed between frames BG1DataBank equ 24 ; Data bank that holds BG1 layer data -BlitterDP equ 26 ; Direct page address the holder blitter data +BG1AltBank equ 26 ; Alternate BG1 bank -OldStartX equ 28 -OldStartY equ 30 +BlitterDP equ 28 ; Direct page address the holder blitter data -LastPatchOffset equ 32 ; Offset into code field that was patched with BRA instructions -StartXMod164 equ 34 +OldStartX equ 30 +OldStartY equ 32 + +LastPatchOffset equ 34 ; Offset into code field that was patched with BRA instructions +StartXMod164 equ 36 + +BG1StartX equ 38 ; Logical offset of the second background +BG1StartXMod164 equ 40 bstk equ 208 ; 16-byte stack to push bank addresses @@ -59,3 +64,6 @@ DIRTY_BIT_BG1_Y equ $0008 + + + diff --git a/src/blitter/Tiles.s b/src/blitter/Tiles.s index c4e9783..a4d5afe 100644 --- a/src/blitter/Tiles.s +++ b/src/blitter/Tiles.s @@ -16,41 +16,42 @@ ; X = Tile column (0 - 40) ; Y = Tile row (0 - 25) CopyTile - phb ; save the current bank - pha ; save the tile ID + phb ; save the current bank + phx ; save the original x-value + pha ; save the tile ID - tya ; lookup the address of the virtual line (y * 8) - asl - asl - asl - asl - tay + tya ; lookup the address of the virtual line (y * 8) + asl + asl + asl + asl + tay - sep #$20 ; set the bank register - lda BTableHigh,y - pha ; save for a few instruction - rep #$20 + sep #$20 ; set the bank register + lda BTableHigh,y + pha ; save for a few instruction + rep #$20 - phx ; Reverse the tile index since x = 0 is at the end - lda #40 - sec - sbc 1,s - plx + phx ; Reverse the tile index since x = 0 is at the end + lda #40 + sec + sbc 1,s + plx - asl ; there are two columns per tile, so multiple by 4 - asl ; asl will clear the carry bit - tax - lda Col2CodeOffset,x - adc BTableLow,y - tay - iny ; +1 to move past to opcode to the operand + asl ; there are two columns per tile, so multiple by 4 + asl ; asl will clear the carry bit + tax + lda Col2CodeOffset,x + adc BTableLow,y + tay - plb ; set the bank - pla ; pop the tile ID - jsr _CopyTile + plb ; set the bank + pla ; pop the tile ID + jsr :ClearTile ; :_CopyTile - plb ; restore the data bank and return - rts + plx ; pop the x-register + plb ; restore the data bank and return + rts ; _CopyTile ; @@ -60,90 +61,130 @@ CopyTile ; A = Tile ID (0 - 1023) ; Y = Base Adddress in the code field -_CopyTile cmp #$0010 - bcc :FillWord - cmp #$0400 - bcc :CopyTileMem - rts ; Tile number is too large - -:TilePatterns dw $0000,$1111,$2222,$3333 - dw $4444,$5555,$6666,$7777 - dw $8888,$9999,$AAAA,$BBBB - dw $CCCC,$DDDD,$EEEE,$FFFF - -:FillWord asl - tax - ldal :TilePatterns,x - -CopyTileConst sta: $0000,y - sta: $0003,y - sta $1000,y - sta $1003,y - sta $2000,y - sta $2003,y - sta $3000,y - sta $3003,y - sta $4000,y - sta $4003,y - sta $5000,y - sta $5003,y - sta $6000,y - sta $6003,y - sta $7000,y - sta $7003,y - rts - -:CopyTileMem sec - sbc #$0010 - - asl - asl - asl - asl - asl - tax - -CopyTileLinear ldal tiledata+0,x ; The low word goes in the *next* instruction - sta: $0003,y - ldal tiledata+2,x - sta: $0000,y - ldal tiledata+4,x - sta $1003,y - ldal tiledata+6,x - sta $1000,y - ldal tiledata+8,x - sta $2003,y - ldal tiledata+10,x - sta $2000,y - ldal tiledata+12,x - sta $3003,y - ldal tiledata+14,x - sta $3000,y - ldal tiledata+16,x - sta $4003,y - ldal tiledata+18,x - sta $4000,y - ldal tiledata+20,x - sta $5003,y - ldal tiledata+22,x - sta $5000,y - ldal tiledata+24,x - sta $6003,y - ldal tiledata+26,x - sta $6000,y - ldal tiledata+28,x - sta $7003,y - ldal tiledata+30,x - sta $7000,y - rts - - +:_CopyTile cmp #$0010 + bcs *+5 + brl :FillWord + cmp #$0400 + bcs *+5 + brl :CopyTileMem + rts ; Tile number is too large +:TilePatterns dw $0000,$1111,$2222,$3333 + dw $4444,$5555,$6666,$7777 + dw $8888,$9999,$AAAA,$BBBB + dw $CCCC,$DDDD,$EEEE,$FFFF +:ClearTile sep #$20 + lda #$B1 + sta: $0000,y + sta: $0003,y + sta $1000,y + sta $1003,y + sta $2000,y + sta $2003,y + sta $3000,y + sta $3003,y + sta $4000,y + sta $4003,y + sta $5000,y + sta $5003,y + sta $6000,y + sta $6003,y + sta $7000,y + sta $7003,y + rep #$20 + lda 3,s + asl + asl + and #$00FF + ora #$4800 + sta: $0004,y + sta $1004,y + sta $2004,y + sta $3004,y + sta $4004,y + sta $5004,y + sta $6004,y + sta $7004,y + inc + inc + sta: $0001,y + sta $1001,y + sta $2001,y + sta $3001,y + sta $4001,y + sta $5001,y + sta $6001,y + sta $7001,y + rts +:FillWord asl + tax + ldal :TilePatterns,x + sta: $0001,y + sta: $0004,y + sta $1001,y + sta $1004,y + sta $2001,y + sta $2004,y + sta $3001,y + sta $3004,y + sta $4001,y + sta $4004,y + sta $5001,y + sta $5004,y + sta $6001,y + sta $6004,y + sta $7001,y + sta $7004,y + rts + +:CopyTileMem sec + sbc #$0010 + + asl + asl + asl + asl + asl + tax + + ldal tiledata+0,x ; The low word goes in the *next* instruction + sta: $0004,y + ldal tiledata+2,x + sta: $0001,y + ldal tiledata+4,x + sta $1004,y + ldal tiledata+6,x + sta $1001,y + ldal tiledata+8,x + sta $2004,y + ldal tiledata+10,x + sta $2001,y + ldal tiledata+12,x + sta $3004,y + ldal tiledata+14,x + sta $3001,y + ldal tiledata+16,x + sta $4004,y + ldal tiledata+18,x + sta $4001,y + ldal tiledata+20,x + sta $5004,y + ldal tiledata+22,x + sta $5001,y + ldal tiledata+24,x + sta $6004,y + ldal tiledata+26,x + sta $6001,y + ldal tiledata+28,x + sta $7004,y + ldal tiledata+30,x + sta $7001,y + rts diff --git a/tools/pngtoiigs.js b/tools/pngtoiigs.js index 6913c62..9898b10 100644 --- a/tools/pngtoiigs.js +++ b/tools/pngtoiigs.js @@ -29,13 +29,18 @@ function pngToIIgsBuff(png) { for (let x = 0; x < png.width; x += 1, i += 4) { const pixel = png.data.slice(i, i + 4); const index = findColorIndex(png, pixel); - const j = i / 8; + const j = y * (png.width / 2) + Math.floor(x / 2); + + if (index > 15) { + console.warn('Pixel index greater than 15. Skipping...'); + continue; + } if (x % 2 === 0) { - buff[j] = buff[j] + (16 * index); + buff[j] = 16 * index; } else { - buff[j] = buff[j] + index + buff[j] = buff[j] | index; } } } @@ -43,6 +48,16 @@ function pngToIIgsBuff(png) { return buff; } +function shiftImage(src) { + const { width, height, colorType, bitDepth } = src; + const dst = new PNG({ width, height, colorType, bitDepth }); + + PNG.bitblt(src, dst, 1, 0, width - 1, height, 0, 0); + PNG.bitblt(src, dst, 0, 0, 1, height, width - 1, 0); + + return dst; +} + function pngToIIgsBuffRepeat(png) { let i = 0; const buff = Buffer.alloc(png.height * png.width, 0);