diff --git a/src/main/fragment/cache/fragment-cache-mos6502.asm b/src/main/fragment/cache/fragment-cache-mos6502.asm index 6adb2db75..020fd788e 100644 --- a/src/main/fragment/cache/fragment-cache-mos6502.asm +++ b/src/main/fragment/cache/fragment-cache-mos6502.asm @@ -538,3 +538,219 @@ sta {z1} bcc !+ inc {z1}+1 !: +//FRAGMENT vbuz1=vbuz2_rol_2 +lda {z2} +asl +asl +sta {z1} +//FRAGMENT pbuc1_derefidx_vbuz1=pbuc2_derefidx_vbuz2 +ldy {z2} +lda {c2},y +ldy {z1} +sta {c1},y +//FRAGMENT vbuz1=pbuc1_derefidx_vbuz2_plus_vbuc2 +lda #{c2} +ldy {z2} +clc +adc {c1},y +sta {z1} +//FRAGMENT pbuc1_derefidx_vbuz1=vbuz2 +lda {z2} +ldy {z1} +sta {c1},y +//FRAGMENT vbuz1=vbuz1_minus_vbuc1 +lda {z1} +sec +sbc #{c1} +sta {z1} +//FRAGMENT vbuaa=vbuz1_rol_2 +lda {z1} +asl +asl +//FRAGMENT vbuxx=vbuz1_rol_2 +lda {z1} +asl +asl +tax +//FRAGMENT vbuyy=vbuz1_rol_2 +lda {z1} +asl +asl +tay +//FRAGMENT vbuz1=vbuaa_rol_2 +asl +asl +sta {z1} +//FRAGMENT vbuaa=vbuaa_rol_2 +asl +asl +//FRAGMENT vbuxx=vbuaa_rol_2 +asl +asl +tax +//FRAGMENT vbuyy=vbuaa_rol_2 +asl +asl +tay +//FRAGMENT vbuz1=vbuxx_rol_2 +txa +asl +asl +sta {z1} +//FRAGMENT vbuaa=vbuxx_rol_2 +txa +asl +asl +//FRAGMENT vbuxx=vbuxx_rol_2 +txa +asl +asl +tax +//FRAGMENT vbuyy=vbuxx_rol_2 +txa +asl +asl +tay +//FRAGMENT vbuz1=vbuyy_rol_2 +tya +asl +asl +sta {z1} +//FRAGMENT vbuaa=vbuyy_rol_2 +tya +asl +asl +//FRAGMENT vbuxx=vbuyy_rol_2 +tya +asl +asl +tax +//FRAGMENT vbuyy=vbuyy_rol_2 +tya +asl +asl +tay +//FRAGMENT pbuc1_derefidx_vbuxx=pbuc2_derefidx_vbuz1 +ldy {z1} +lda {c2},y +sta {c1},x +//FRAGMENT pbuc1_derefidx_vbuyy=pbuc2_derefidx_vbuz1 +ldx {z1} +lda {c2},x +sta {c1},y +//FRAGMENT pbuc1_derefidx_vbuz1=pbuc2_derefidx_vbuxx +lda {c2},x +ldy {z1} +sta {c1},y +//FRAGMENT pbuc1_derefidx_vbuxx=pbuc2_derefidx_vbuxx +lda {c2},x +sta {c1},x +//FRAGMENT pbuc1_derefidx_vbuyy=pbuc2_derefidx_vbuxx +lda {c2},x +sta {c1},y +//FRAGMENT pbuc1_derefidx_vbuz1=pbuc2_derefidx_vbuyy +lda {c2},y +ldy {z1} +sta {c1},y +//FRAGMENT pbuc1_derefidx_vbuxx=pbuc2_derefidx_vbuyy +lda {c2},y +sta {c1},x +//FRAGMENT pbuc1_derefidx_vbuyy=pbuc2_derefidx_vbuyy +lda {c2},y +sta {c1},y +//FRAGMENT pbuc1_derefidx_vbuaa=pbuc2_derefidx_vbuz1 +ldx {z1} +tay +lda {c2},x +sta {c1},y +//FRAGMENT pbuc1_derefidx_vbuaa=pbuc2_derefidx_vbuxx +tay +lda {c2},x +sta {c1},y +//FRAGMENT pbuc1_derefidx_vbuaa=pbuc2_derefidx_vbuyy +tax +lda {c2},y +sta {c1},x +//FRAGMENT vbuaa=pbuc1_derefidx_vbuz1_plus_vbuc2 +lda #{c2} +ldy {z1} +clc +adc {c1},y +//FRAGMENT vbuxx=pbuc1_derefidx_vbuz1_plus_vbuc2 +lda #{c2} +ldx {z1} +clc +adc {c1},x +tax +//FRAGMENT vbuyy=pbuc1_derefidx_vbuz1_plus_vbuc2 +lda #{c2} +ldy {z1} +clc +adc {c1},y +tay +//FRAGMENT vbuz1=pbuc1_derefidx_vbuxx_plus_vbuc2 +lda #{c2} +clc +adc {c1},x +sta {z1} +//FRAGMENT vbuaa=pbuc1_derefidx_vbuxx_plus_vbuc2 +lda #{c2} +clc +adc {c1},x +//FRAGMENT vbuxx=pbuc1_derefidx_vbuxx_plus_vbuc2 +lda #{c2} +clc +adc {c1},x +tax +//FRAGMENT vbuyy=pbuc1_derefidx_vbuxx_plus_vbuc2 +lda #{c2} +clc +adc {c1},x +tay +//FRAGMENT vbuz1=pbuc1_derefidx_vbuyy_plus_vbuc2 +lda #{c2} +clc +adc {c1},y +sta {z1} +//FRAGMENT vbuaa=pbuc1_derefidx_vbuyy_plus_vbuc2 +lda #{c2} +clc +adc {c1},y +//FRAGMENT vbuxx=pbuc1_derefidx_vbuyy_plus_vbuc2 +lda #{c2} +clc +adc {c1},y +tax +//FRAGMENT vbuyy=pbuc1_derefidx_vbuyy_plus_vbuc2 +lda #{c2} +clc +adc {c1},y +tay +//FRAGMENT pbuc1_derefidx_vbuz1=vbuaa +ldy {z1} +sta {c1},y +//FRAGMENT pbuc1_derefidx_vbuz1=vbuxx +ldy {z1} +txa +sta {c1},y +//FRAGMENT pbuc1_derefidx_vbuz1=vbuyy +tya +ldy {z1} +sta {c1},y +//FRAGMENT pbuc1_derefidx_vbuxx=vbuz1 +lda {z1} +sta {c1},x +//FRAGMENT vbuxx=vbuxx_minus_vbuc1 +txa +sec +sbc #{c1} +tax +//FRAGMENT vbuyy=vbuyy_minus_vbuc1 +tya +sec +sbc #{c1} +tay +//FRAGMENT vbuyy=vbuz1 +ldy {z1} +//FRAGMENT pbuc1_derefidx_vbuyy=vbuaa +sta {c1},y diff --git a/src/main/kc/include/c128.h b/src/main/kc/include/c128.h new file mode 100644 index 000000000..259cd8dc1 --- /dev/null +++ b/src/main/kc/include/c128.h @@ -0,0 +1,8 @@ +// Commodore 128 Registers and Memory +// https://archive.org/details/C128_Programmers_Reference_Guide_1986_Bamtam_Books/page/n299/mode/2up +#ifndef __C128__ +#error "Target platform must be C128" +#endif +#include +#include +#include diff --git a/src/main/kc/lib/conio-nes.c b/src/main/kc/lib/conio-nes.c index 79bed588e..35aebb12b 100644 --- a/src/main/kc/lib/conio-nes.c +++ b/src/main/kc/lib/conio-nes.c @@ -117,8 +117,8 @@ void cscroll() { char* line1 = CONIO_SCREEN_TEXT; char* line2 = CONIO_SCREEN_TEXT+CONIO_WIDTH; for(char y=0;y +#include + +// RESET Called when the NES is reset, including when it is turned on. +void main() { + // Initialize NES after RESET + initNES(); + // Transfer the palette + ppuDataTransfer(PPU_PALETTE, PALETTE, sizeof(PALETTE)); + // Fill the PPU attribute table + ppuDataFill(PPU_NAME_TABLE_0, '*', 32*30); + ppuDataFill(PPU_ATTRIBUTE_TABLE_0, 0, 0x40); + // Initialize Sprite Buffer with the SPRITE data + for(char s=0;s<0x40;s++) { + SPRITE_BUFFER[s] = { 0, MESSAGE[s], 0b00000010, 0 }; + } + // Enable screen rendering and vblank + enableVideoOutput(); + // Infinite loop + while(1) { + } +} + +// Index into the Y sine +volatile char y_sin_idx = 0; +// Index into the X sine +volatile char x_sin_idx = 73; + +// NMI Called when the PPU refreshes the screen (also known as the V-Blank period) +interrupt(hardware_stack) void vblank() { + // Set scroll + PPU->PPUSCROLL = 0; + PPU->PPUSCROLL = 0; + // DMA transfer the entire sprite buffer to the PPU + ppuSpriteBufferDmaTransfer(SPRITE_BUFFER); + // Update sprite positions + char y_idx = y_sin_idx++; + char x_idx = x_sin_idx++; + for(char s=0;s<0x40;s++) { + SPRITE_BUFFER[s].y = SINTABLE[y_idx]; + SPRITE_BUFFER[s].x = SINTABLE[x_idx]+8; + y_idx += 4; + x_idx -= 7; + } +} + +// Data (in PRG ROM) +#pragma data_seg(Data) + +// The DXYCP message 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef +char MESSAGE[0x40] = "rex-of-camelot-presents-a-dxycp-on-nintendo-entertainment-system"z; + +// Color Palette +char PALETTE[0x20] = { + // Background palettes + 0x01, 0x21, 0x0f, 0x30, // C64 colors + 0x01, 0x21, 0x0f, 0x30, // C64 colors + 0x01, 0x21, 0x0f, 0x30, // C64 colors + 0x01, 0x21, 0x0f, 0x30, // C64 colors + // Sprite palettes (selected by the attribute bits 0-1 of the sprites) + 0x01, 0x0f, 0x30, 0x08, // Goomba upper colors + 0x01, 0x0f, 0x18, 0x08, // Goomba lower colors + 0x01, 0x30, 0x37, 0x1a, // Luigi-like colors + 0x0f, 0x0f, 0x0f, 0x0f // All black +}; + +// Sinus Table (0-239) +const char SINTABLE[0x100] = kickasm {{ + .fill $100, round(115.5+107.5*sin(2*PI*i/256)) +}}; + +// Tile Set (in CHR ROM) - A C64 charset from http://www.zimmers.net/anonftp/pub/cbm/firmware/computers/c64/ +#pragma data_seg(Tiles) +export char TILES[] = kickasm(resource "characters.901225-01.bin") {{ + .var filechargen = LoadBinary("characters.901225-01.bin") + .for(var c=0; c<256; c++) { + // Plane 0 + .fill 8, filechargen.get(c*8+i) + // Plane 1 + .fill 8, 0 + } +}}; + +// Sprite Buffer (in GAME RAM) +// Will be transferred to the PPU via DMA during vblank +#pragma data_seg(GameRam) +struct SpriteData align(0x100) SPRITE_BUFFER[0x100]; + +// Interrupt Vectors (in PRG ROM) +#pragma data_seg(Vectors) +export void()* const VECTORS[] = { + // NMI Called when the PPU refreshes the screen (also known as the V-Blank period) + &vblank, + // RESET Called when the NES is reset, including when it is turned on. + &main, + // IRQ Called when a BRK instruction is executed. + 0 +}; \ No newline at end of file diff --git a/src/test/ref/examples/nes-conio/nes-conio.asm b/src/test/ref/examples/nes-conio/nes-conio.asm index 5ef1fe537..9a0d0c34b 100644 --- a/src/test/ref/examples/nes-conio/nes-conio.asm +++ b/src/test/ref/examples/nes-conio/nes-conio.asm @@ -409,13 +409,13 @@ cscroll: { // } rts __b2: - // ppuDataFetch(scroll_buffer, line2, CONIO_WIDTH) + // ppuDataFetch(conio_cscroll_buffer, line2, CONIO_WIDTH) lda.z line2 sta.z ppuDataFetch.ppuData lda.z line2+1 sta.z ppuDataFetch.ppuData+1 jsr ppuDataFetch - // ppuDataTransfer(line1, scroll_buffer, CONIO_WIDTH) + // ppuDataTransfer(line1, conio_cscroll_buffer, CONIO_WIDTH) lda.z line1 sta.z ppuDataTransfer.ppuData lda.z line1+1 @@ -424,9 +424,9 @@ cscroll: { sta.z ppuDataTransfer.size lda #>$20 sta.z ppuDataTransfer.size+1 - lda #scroll_buffer + lda #>conio_cscroll_buffer sta.z ppuDataTransfer.cpuData+1 jsr ppuDataTransfer // line1 += CONIO_WIDTH @@ -509,7 +509,7 @@ ppuDataTransfer: { // ppuDataFetch(void* zp($19) ppuData) ppuDataFetch: { .const size = $20 - .label cpuData = scroll_buffer + .label cpuData = conio_cscroll_buffer // Fetch from PPU to CPU .label cpuDst = 7 .label i = 5 @@ -947,6 +947,9 @@ readJoy1: { inx jmp __b1 } +.segment GameRam + // Buffer used for scrolling the NES screen + conio_cscroll_buffer: .fill $20, 0 .segment Data // The digits used for numbers DIGITS: .text "0123456789abcdef" @@ -954,7 +957,6 @@ readJoy1: { RADIX_HEXADECIMAL_VALUES_CHAR: .byte $10 .segment GameRam num_buffer: .fill $b, 0 - scroll_buffer: .fill $20, 0 .segment Data // Color Palette PALETTE: .byte 1, $21, $f, $30, 1, $21, $f, $30, 1, $21, $f, $30, 1, $21, $f, $30, 1, $f, $30, 8, 1, $f, $18, 8, 1, $30, $37, $1a, $f, $f, $f, $f diff --git a/src/test/ref/examples/nes-conio/nes-conio.cfg b/src/test/ref/examples/nes-conio/nes-conio.cfg index 4d58ea63a..6e08e2196 100644 --- a/src/test/ref/examples/nes-conio/nes-conio.cfg +++ b/src/test/ref/examples/nes-conio/nes-conio.cfg @@ -244,7 +244,7 @@ cscroll::@5: scope:[cscroll] from cscroll::@4 (void()) ppuDataTransfer((nomodify void*) ppuDataTransfer::ppuData , (nomodify void*) ppuDataTransfer::cpuData , (word) ppuDataTransfer::size) ppuDataTransfer: scope:[ppuDataTransfer] from cscroll::@4 main::@6 [110] (word) ppuDataTransfer::size#3 ← phi( cscroll::@4/(byte) $20 main::@6/(byte) $20*(const byte) SIZEOF_BYTE ) - [110] (nomodify void*) ppuDataTransfer::cpuData#2 ← phi( cscroll::@4/(void*)(const byte*) scroll_buffer main::@6/(void*)(const byte*) PALETTE ) + [110] (nomodify void*) ppuDataTransfer::cpuData#2 ← phi( cscroll::@4/(void*)(const byte*) conio_cscroll_buffer main::@6/(void*)(const byte*) PALETTE ) [110] (nomodify void*) ppuDataTransfer::ppuDataPrepare1_ppuData#0 ← phi( cscroll::@4/(nomodify void*) ppuDataTransfer::ppuData#0 main::@6/(void*)(const nomodify byte*) PPU_PALETTE ) to:ppuDataTransfer::ppuDataPrepare1 ppuDataTransfer::ppuDataPrepare1: scope:[ppuDataTransfer] from ppuDataTransfer diff --git a/src/test/ref/examples/nes-conio/nes-conio.log b/src/test/ref/examples/nes-conio/nes-conio.log index 838ced89d..e712313e8 100644 --- a/src/test/ref/examples/nes-conio/nes-conio.log +++ b/src/test/ref/examples/nes-conio/nes-conio.log @@ -1,5 +1,3 @@ -Resolved forward reference scroll_buffer to (const byte*) scroll_buffer -Resolved forward reference scroll_buffer to (const byte*) scroll_buffer Resolved forward reference PALETTE to (const byte*) PALETTE Resolved forward reference PALETTE to (const byte*) PALETTE Resolved forward reference x_scroll to (volatile byte) x_scroll @@ -431,7 +429,7 @@ cscroll::@5: scope:[cscroll] from cscroll::@4 (byte) cscroll::y#5 ← phi( cscroll::@4/(byte) cscroll::y#2 ) (byte*) cscroll::line1#4 ← phi( cscroll::@4/(byte*) cscroll::line1#5 ) (byte*) cscroll::line2#2 ← phi( cscroll::@4/(byte*) cscroll::line2#4 ) - (nomodify void*) ppuDataFetch::cpuData#0 ← (void*)(const byte*) scroll_buffer + (nomodify void*) ppuDataFetch::cpuData#0 ← (void*)(const byte*) conio_cscroll_buffer (nomodify void*) ppuDataFetch::ppuData#0 ← (void*)(byte*) cscroll::line2#2 (word) ppuDataFetch::size#0 ← (number) $20 call ppuDataFetch @@ -441,7 +439,7 @@ cscroll::@8: scope:[cscroll] from cscroll::@5 (byte*) cscroll::line2#5 ← phi( cscroll::@5/(byte*) cscroll::line2#2 ) (byte*) cscroll::line1#2 ← phi( cscroll::@5/(byte*) cscroll::line1#4 ) (nomodify void*) ppuDataTransfer::ppuData#0 ← (void*)(byte*) cscroll::line1#2 - (nomodify void*) ppuDataTransfer::cpuData#0 ← (void*)(const byte*) scroll_buffer + (nomodify void*) ppuDataTransfer::cpuData#0 ← (void*)(const byte*) conio_cscroll_buffer (word) ppuDataTransfer::size#0 ← (number) $20 call ppuDataTransfer to:cscroll::@9 @@ -1137,6 +1135,7 @@ SYMBOL TABLE SSA (void()) clrscr() (label) clrscr::@1 (label) clrscr::@return +(const byte*) conio_cscroll_buffer[(number) $20] = { fill( $20, 0) } (byte) conio_cursor_x loadstore (byte) conio_cursor_y loadstore (byte*) conio_line_text loadstore @@ -1674,7 +1673,6 @@ SYMBOL TABLE SSA (byte) readJoy1::return#2 (byte) readJoy1::return#3 (byte) readJoy1::return#4 -(const byte*) scroll_buffer[(number) $20] = { fill( $20, 0) } (void()) uctoa((byte) uctoa::value , (byte*) uctoa::buffer , (byte) uctoa::radix) (bool~) uctoa::$0 (bool~) uctoa::$1 @@ -2443,9 +2441,9 @@ Constant (const byte*) cscroll::line2#0 = CONIO_SCREEN_TEXT+$20 Constant (const byte) cscroll::y#0 = 0 Constant (const byte) gotoxy::x#1 = 0 Constant (const byte) gotoxy::y#1 = 0 -Constant (const nomodify void*) ppuDataFetch::cpuData#0 = (void*)scroll_buffer +Constant (const nomodify void*) ppuDataFetch::cpuData#0 = (void*)conio_cscroll_buffer Constant (const word) ppuDataFetch::size#0 = $20 -Constant (const nomodify void*) ppuDataTransfer::cpuData#0 = (void*)scroll_buffer +Constant (const nomodify void*) ppuDataTransfer::cpuData#0 = (void*)conio_cscroll_buffer Constant (const word) ppuDataTransfer::size#0 = $20 Constant (const nomodify void*) ppuDataFill::ppuData#1 = (void*)CONIO_SCREEN_TEXT+(word)$1e*$20-$20 Constant (const byte) ppuDataFill::val#1 = ' ' @@ -2761,7 +2759,7 @@ Constant inlined readJoy1::joy#0 = (byte) 0 Constant inlined ppuDataTransfer::cpuData#1 = (void*)(const byte*) PALETTE Constant inlined cscroll::y#0 = (byte) 0 Constant inlined cscroll::line2#0 = (const nomodify byte*) PPU_NAME_TABLE_0+(byte) $20 -Constant inlined ppuDataTransfer::cpuData#0 = (void*)(const byte*) scroll_buffer +Constant inlined ppuDataTransfer::cpuData#0 = (void*)(const byte*) conio_cscroll_buffer Constant inlined ppuDataTransfer::ppuData#1 = (void*)(const nomodify byte*) PPU_PALETTE Constant inlined cputcxy::c#3 = (byte) 'i' Constant inlined cputcxy::c#2 = (byte) 'i' @@ -3260,7 +3258,7 @@ cscroll::@5: scope:[cscroll] from cscroll::@4 (void()) ppuDataTransfer((nomodify void*) ppuDataTransfer::ppuData , (nomodify void*) ppuDataTransfer::cpuData , (word) ppuDataTransfer::size) ppuDataTransfer: scope:[ppuDataTransfer] from cscroll::@4 main::@6 [110] (word) ppuDataTransfer::size#3 ← phi( cscroll::@4/(byte) $20 main::@6/(byte) $20*(const byte) SIZEOF_BYTE ) - [110] (nomodify void*) ppuDataTransfer::cpuData#2 ← phi( cscroll::@4/(void*)(const byte*) scroll_buffer main::@6/(void*)(const byte*) PALETTE ) + [110] (nomodify void*) ppuDataTransfer::cpuData#2 ← phi( cscroll::@4/(void*)(const byte*) conio_cscroll_buffer main::@6/(void*)(const byte*) PALETTE ) [110] (nomodify void*) ppuDataTransfer::ppuDataPrepare1_ppuData#0 ← phi( cscroll::@4/(nomodify void*) ppuDataTransfer::ppuData#0 main::@6/(void*)(const nomodify byte*) PPU_PALETTE ) to:ppuDataTransfer::ppuDataPrepare1 ppuDataTransfer::ppuDataPrepare1: scope:[ppuDataTransfer] from ppuDataTransfer @@ -4805,10 +4803,10 @@ cscroll: { sta.z ppuDataTransfer.size lda #>$20 sta.z ppuDataTransfer.size+1 - // [110] phi (nomodify void*) ppuDataTransfer::cpuData#2 = (void*)(const byte*) scroll_buffer [phi:cscroll::@4->ppuDataTransfer#1] -- pvoz1=pvoc1 - lda #ppuDataTransfer#1] -- pvoz1=pvoc1 + lda #scroll_buffer + lda #>conio_cscroll_buffer sta.z ppuDataTransfer.cpuData+1 // [110] phi (nomodify void*) ppuDataTransfer::ppuDataPrepare1_ppuData#0 = (nomodify void*) ppuDataTransfer::ppuData#0 [phi:cscroll::@4->ppuDataTransfer#2] -- register_copy jsr ppuDataTransfer @@ -4943,7 +4941,7 @@ ppuDataTransfer: { // ppuDataFetch(void* zp($3e) ppuData) ppuDataFetch: { .const size = $20 - .label cpuData = scroll_buffer + .label cpuData = conio_cscroll_buffer .label ppuDataPrepare1___0 = $43 .label ppuDataPrepare1___1 = $44 .label ppuDataRead1_return = $45 @@ -5740,6 +5738,9 @@ readJoy1: { jmp __b1 } // File Data +.segment GameRam + // Buffer used for scrolling the NES screen + conio_cscroll_buffer: .fill $20, 0 .segment Data // The digits used for numbers DIGITS: .text "0123456789abcdef" @@ -5747,7 +5748,6 @@ readJoy1: { RADIX_HEXADECIMAL_VALUES_CHAR: .byte $10 .segment GameRam num_buffer: .fill $b, 0 - scroll_buffer: .fill $20, 0 .segment Data // Color Palette PALETTE: .byte 1, $21, $f, $30, 1, $21, $f, $30, 1, $21, $f, $30, 1, $21, $f, $30, 1, $f, $30, 8, 1, $f, $18, 8, 1, $30, $37, $1a, $f, $f, $f, $f @@ -6845,10 +6845,10 @@ cscroll: { sta.z ppuDataTransfer.size lda #>$20 sta.z ppuDataTransfer.size+1 - // [110] phi (nomodify void*) ppuDataTransfer::cpuData#2 = (void*)(const byte*) scroll_buffer [phi:cscroll::@4->ppuDataTransfer#1] -- pvoz1=pvoc1 - lda #ppuDataTransfer#1] -- pvoz1=pvoc1 + lda #scroll_buffer + lda #>conio_cscroll_buffer sta.z ppuDataTransfer.cpuData+1 // [110] phi (nomodify void*) ppuDataTransfer::ppuDataPrepare1_ppuData#0 = (nomodify void*) ppuDataTransfer::ppuData#0 [phi:cscroll::@4->ppuDataTransfer#2] -- register_copy jsr ppuDataTransfer @@ -6970,7 +6970,7 @@ ppuDataTransfer: { // ppuDataFetch(void* zp($19) ppuData) ppuDataFetch: { .const size = $20 - .label cpuData = scroll_buffer + .label cpuData = conio_cscroll_buffer // Fetch from PPU to CPU .label cpuDst = 7 .label i = 5 @@ -7662,6 +7662,9 @@ readJoy1: { jmp __b1 } // File Data +.segment GameRam + // Buffer used for scrolling the NES screen + conio_cscroll_buffer: .fill $20, 0 .segment Data // The digits used for numbers DIGITS: .text "0123456789abcdef" @@ -7669,7 +7672,6 @@ readJoy1: { RADIX_HEXADECIMAL_VALUES_CHAR: .byte $10 .segment GameRam num_buffer: .fill $b, 0 - scroll_buffer: .fill $20, 0 .segment Data // Color Palette PALETTE: .byte 1, $21, $f, $30, 1, $21, $f, $30, 1, $21, $f, $30, 1, $21, $f, $30, 1, $f, $30, 8, 1, $f, $18, 8, 1, $30, $37, $1a, $f, $f, $f, $f @@ -8061,6 +8063,7 @@ FINAL SYMBOL TABLE (void()) clrscr() (label) clrscr::@1 (label) clrscr::@return +(const byte*) conio_cscroll_buffer[(number) $20] = { fill( $20, 0) } (byte) conio_cursor_x loadstore zp[1]:17 4375315.90625 (byte) conio_cursor_y loadstore zp[1]:18 6.5306328755102046E7 (byte*) conio_line_text loadstore zp[2]:19 4.9111335755555555E7 @@ -8209,7 +8212,7 @@ FINAL SYMBOL TABLE (label) ppuDataFetch::@3 (label) ppuDataFetch::@return (nomodify void*) ppuDataFetch::cpuData -(const nomodify void*) ppuDataFetch::cpuData#0 cpuData = (void*)(const byte*) scroll_buffer +(const nomodify void*) ppuDataFetch::cpuData#0 cpuData = (void*)(const byte*) conio_cscroll_buffer (byte*) ppuDataFetch::cpuDst (byte*) ppuDataFetch::cpuDst#1 cpuDst zp[2]:7 1.0E17 (byte*) ppuDataFetch::cpuDst#2 cpuDst zp[2]:7 7.5E16 @@ -8309,7 +8312,6 @@ FINAL SYMBOL TABLE (byte) readJoy1::joy#2 reg byte a 51.0 (byte) readJoy1::return (byte) readJoy1::return#2 reg byte a 4.0 -(const byte*) scroll_buffer[(number) $20] = { fill( $20, 0) } (void()) uctoa((byte) uctoa::value , (byte*) uctoa::buffer , (byte) uctoa::radix) (label) uctoa::@1 (label) uctoa::@2 @@ -9068,7 +9070,7 @@ cscroll: { rts // cscroll::@2 __b2: - // ppuDataFetch(scroll_buffer, line2, CONIO_WIDTH) + // ppuDataFetch(conio_cscroll_buffer, line2, CONIO_WIDTH) // [103] (nomodify void*) ppuDataFetch::ppuData#0 ← (void*)(byte*) cscroll::line2#2 -- pvoz1=pvoz2 lda.z line2 sta.z ppuDataFetch.ppuData @@ -9078,7 +9080,7 @@ cscroll: { // [123] phi from cscroll::@2 to ppuDataFetch [phi:cscroll::@2->ppuDataFetch] jsr ppuDataFetch // cscroll::@4 - // ppuDataTransfer(line1, scroll_buffer, CONIO_WIDTH) + // ppuDataTransfer(line1, conio_cscroll_buffer, CONIO_WIDTH) // [105] (nomodify void*) ppuDataTransfer::ppuData#0 ← (void*)(byte*) cscroll::line1#2 -- pvoz1=pvoz2 lda.z line1 sta.z ppuDataTransfer.ppuData @@ -9091,10 +9093,10 @@ cscroll: { sta.z ppuDataTransfer.size lda #>$20 sta.z ppuDataTransfer.size+1 - // [110] phi (nomodify void*) ppuDataTransfer::cpuData#2 = (void*)(const byte*) scroll_buffer [phi:cscroll::@4->ppuDataTransfer#1] -- pvoz1=pvoc1 - lda #ppuDataTransfer#1] -- pvoz1=pvoc1 + lda #scroll_buffer + lda #>conio_cscroll_buffer sta.z ppuDataTransfer.cpuData+1 // [110] phi (nomodify void*) ppuDataTransfer::ppuDataPrepare1_ppuData#0 = (nomodify void*) ppuDataTransfer::ppuData#0 [phi:cscroll::@4->ppuDataTransfer#2] -- register_copy jsr ppuDataTransfer @@ -9212,7 +9214,7 @@ ppuDataTransfer: { // ppuDataFetch(void* zp($19) ppuData) ppuDataFetch: { .const size = $20 - .label cpuData = scroll_buffer + .label cpuData = conio_cscroll_buffer // Fetch from PPU to CPU .label cpuDst = 7 .label i = 5 @@ -9882,6 +9884,9 @@ readJoy1: { jmp __b1 } // File Data +.segment GameRam + // Buffer used for scrolling the NES screen + conio_cscroll_buffer: .fill $20, 0 .segment Data // The digits used for numbers DIGITS: .text "0123456789abcdef" @@ -9889,7 +9894,6 @@ readJoy1: { RADIX_HEXADECIMAL_VALUES_CHAR: .byte $10 .segment GameRam num_buffer: .fill $b, 0 - scroll_buffer: .fill $20, 0 .segment Data // Color Palette PALETTE: .byte 1, $21, $f, $30, 1, $21, $f, $30, 1, $21, $f, $30, 1, $21, $f, $30, 1, $f, $30, 8, 1, $f, $18, 8, 1, $30, $37, $1a, $f, $f, $f, $f diff --git a/src/test/ref/examples/nes-conio/nes-conio.sym b/src/test/ref/examples/nes-conio/nes-conio.sym index c1aa53447..5e9354247 100644 --- a/src/test/ref/examples/nes-conio/nes-conio.sym +++ b/src/test/ref/examples/nes-conio/nes-conio.sym @@ -80,6 +80,7 @@ (void()) clrscr() (label) clrscr::@1 (label) clrscr::@return +(const byte*) conio_cscroll_buffer[(number) $20] = { fill( $20, 0) } (byte) conio_cursor_x loadstore zp[1]:17 4375315.90625 (byte) conio_cursor_y loadstore zp[1]:18 6.5306328755102046E7 (byte*) conio_line_text loadstore zp[2]:19 4.9111335755555555E7 @@ -228,7 +229,7 @@ (label) ppuDataFetch::@3 (label) ppuDataFetch::@return (nomodify void*) ppuDataFetch::cpuData -(const nomodify void*) ppuDataFetch::cpuData#0 cpuData = (void*)(const byte*) scroll_buffer +(const nomodify void*) ppuDataFetch::cpuData#0 cpuData = (void*)(const byte*) conio_cscroll_buffer (byte*) ppuDataFetch::cpuDst (byte*) ppuDataFetch::cpuDst#1 cpuDst zp[2]:7 1.0E17 (byte*) ppuDataFetch::cpuDst#2 cpuDst zp[2]:7 7.5E16 @@ -328,7 +329,6 @@ (byte) readJoy1::joy#2 reg byte a 51.0 (byte) readJoy1::return (byte) readJoy1::return#2 reg byte a 4.0 -(const byte*) scroll_buffer[(number) $20] = { fill( $20, 0) } (void()) uctoa((byte) uctoa::value , (byte*) uctoa::buffer , (byte) uctoa::radix) (label) uctoa::@1 (label) uctoa::@2 diff --git a/src/test/ref/examples/nes-dxycp/nes-dxycp.asm b/src/test/ref/examples/nes-dxycp/nes-dxycp.asm new file mode 100644 index 000000000..5efffdab3 --- /dev/null +++ b/src/test/ref/examples/nes-dxycp/nes-dxycp.asm @@ -0,0 +1,401 @@ +// NES DXYCP using sprites +// Nintendo Entertainment System (NES +// https://en.wikipedia.org/wiki/Nintendo_Entertainment_System_(Model_NES-101) +// https://github.com/gregkrsak/first_nes +// Ricoh 2C02 - NES Picture Processing Unit (PPU) +// Ricoh RP2C02 (NTSC version) / RP2C07 (PAL version), +// https://en.wikipedia.org/wiki/Picture_Processing_Unit +// https://wiki.nesdev.com/w/index.php/PPU_registers +// http://nesdev.com/2C02%20technical%20reference.TXT +// Based on: https://github.com/gregkrsak/first_nes written by Greg M. Krsak, 2018. + // Nintendo Entertainment System (NES) ROM +// https://sadistech.com/nesromtool/romdoc.html +// https://forums.nesdev.com/viewtopic.php?f=2&t=9896 +// https://github.com/gregkrsak/first_nes +.file [name="nes-dxycp.nes", type="bin", segments="NesRom"] +.file [name="nes-dxycp.nes_hdr", type="bin", segments="Header"] +.file [name="nes-dxycp.nes_prg", type="bin", segments="ProgramRom"] +.file [name="nes-dxycp.nes_chr", type="bin", segments="CharacterRom"] +.segmentdef Header [ start=$0000, min=$0000, max=$000f, fill ] +.segmentdef Tiles [ start=$0000, min=$0000, max=$1fff, fill ] +.segmentdef Code [ start=$c000, min=$c000, max=$fff9 ] +.segmentdef Data [ startAfter="Code", min=$c000, max=$fff9 ] +.segmentdef Vectors [ start=$fffa, min=$fffa, max=$ffff ] +.segmentdef GameRam [start=$200,max=$7ff, virtual] +.segmentdef ProgramRom [ segments="Code, Data, Vectors" ] +.segmentdef CharacterRom [ segments="Tiles" ] +.segmentdef NesRom +.segment NesRom +.segmentout [ segments="Header" ] +.segmentout [ segments="ProgramRom" ] +.segmentout [ segments="CharacterRom" ] +.segment Header +.text @"NES\$1a" +.byte $01 // 1x 16KB ROM (PRG) +.byte $01 // 1x 8KB VROM (CHR) +.byte %00000001 // Mapper nibble 0000 == No mapping (a simple 16KB PRG + 8KB CHR game) + // Mirroring nibble 0001 == Vertical mirroring only +.segment Code + + .const OFFSET_STRUCT_SPRITEDATA_TILE = 1 + .const OFFSET_STRUCT_SPRITEDATA_ATTRIBUTES = 2 + .const OFFSET_STRUCT_SPRITEDATA_X = 3 + .const OFFSET_STRUCT_RICOH_2A03_DMC_FREQ = $10 + .const OFFSET_STRUCT_RICOH_2C02_PPUMASK = 1 + .const OFFSET_STRUCT_RICOH_2C02_PPUSTATUS = 2 + .const OFFSET_STRUCT_RICOH_2C02_OAMADDR = 3 + .const OFFSET_STRUCT_RICOH_2A03_OAMDMA = $14 + .const OFFSET_STRUCT_RICOH_2C02_PPUADDR = 6 + .const OFFSET_STRUCT_RICOH_2C02_PPUDATA = 7 + .const OFFSET_STRUCT_RICOH_2C02_PPUSCROLL = 5 + .const SIZEOF_BYTE = 1 + // $2000-$23bf $03c0 Name table 0 + .label PPU_NAME_TABLE_0 = $2000 + // $23c0-$23ff $0040 Attribute table 0 + .label PPU_ATTRIBUTE_TABLE_0 = $23c0 + // $3000-$3eff $0f00 Mirrors of $2000-$2eff + // $3f00-$3f1f $0020 Palette RAM indexes + .label PPU_PALETTE = $3f00 + // PPU Status Register for reading in ASM + .label PPU_PPUSTATUS = $2002 + // APU Frame Counter + // generates low-frequency clocks for the channels and an optional 60 Hz interrupt. + // https://wiki.nesdev.com/w/index.php/APU_Frame_Counter + // ------+-----+--------------------------------------------------------------- + // $4017 | W | FR_COUNTER Frame Counter Set mode and interrupt + // ------+-----+--------------------------------------------------------------- + // | 7 | Sequencer mode: 0 selects 4-step sequence, 1 selects 5-step sequence + // | 6 | Interrupt inhibit flag. If set, the frame interrupt flag is cleared, otherwise it is unaffected. + // ------+-----+--------------------------------------------------------------- + // Side effects After 3 or 4 CPU clock cycles*, the timer is reset. + // If the mode flag is set, then both "quarter frame" and "half frame" signals are also generated. + .label FR_COUNTER = $4017 + // Pointer to the start of RAM memory + .label MEMORY = 0 + // NES Picture Processing Unit (PPU) + .label PPU = $2000 + // NES CPU and audion processing unit (APU) + .label APU = $4000 + .label y_sin_idx = $a + .label x_sin_idx = $b +__bbegin: + // y_sin_idx = 0 + // Index into the Y sine + lda #0 + sta.z y_sin_idx + // x_sin_idx = 73 + // Index into the X sine + lda #$49 + sta.z x_sin_idx + jsr main + rts +.segment Code +// RESET Called when the NES is reset, including when it is turned on. +main: { + // asm + cld + ldx #$ff + txs + // PPU->PPUCTRL = 0 + lda #0 + sta PPU + // PPU->PPUMASK = 0 + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUMASK + // *FR_COUNTER = 0b01000000 + lda #$40 + sta FR_COUNTER + // APU->DMC_FREQ = 0b01000000 + sta APU+OFFSET_STRUCT_RICOH_2A03_DMC_FREQ + // asm + lda PPU_PPUSTATUS + initNES1_waitForVBlank1: + // PPU->PPUSTATUS&0x80 + lda #$80 + and PPU+OFFSET_STRUCT_RICOH_2C02_PPUSTATUS + // while(!(PPU->PPUSTATUS&0x80)) + cmp #0 + beq initNES1_waitForVBlank1 + ldx #0 + initNES1___b1: + // (MEMORY+0x000)[i] = 0 + lda #0 + sta MEMORY,x + // (MEMORY+0x100)[i] = 0 + sta MEMORY+$100,x + // (MEMORY+0x200)[i] = 0 + sta MEMORY+$200,x + // (MEMORY+0x300)[i] = 0 + sta MEMORY+$300,x + // (MEMORY+0x400)[i] = 0 + sta MEMORY+$400,x + // (MEMORY+0x500)[i] = 0 + sta MEMORY+$500,x + // (MEMORY+0x600)[i] = 0 + sta MEMORY+$600,x + // (MEMORY+0x700)[i] = 0 + sta MEMORY+$700,x + // while (++i) + inx + cpx #0 + bne initNES1___b1 + initNES1_waitForVBlank2: + // PPU->PPUSTATUS&0x80 + lda #$80 + and PPU+OFFSET_STRUCT_RICOH_2C02_PPUSTATUS + // while(!(PPU->PPUSTATUS&0x80)) + cmp #0 + beq initNES1_waitForVBlank2 + // asm + lda PPU_PPUSTATUS + // ppuDataTransfer(PPU_PALETTE, PALETTE, sizeof(PALETTE)) + // Transfer the palette + jsr ppuDataTransfer + // ppuDataFill(PPU_NAME_TABLE_0, '*', 32*30) + // Fill the PPU attribute table + ldx #'*' + lda #<$20*$1e + sta.z ppuDataFill.size + lda #>$20*$1e + sta.z ppuDataFill.size+1 + lda #PPU_NAME_TABLE_0 + sta.z ppuDataFill.ppuDataPrepare1_ppuData+1 + jsr ppuDataFill + // ppuDataFill(PPU_ATTRIBUTE_TABLE_0, 0, 0x40) + ldx #0 + lda #<$40 + sta.z ppuDataFill.size + lda #>$40 + sta.z ppuDataFill.size+1 + lda #PPU_ATTRIBUTE_TABLE_0 + sta.z ppuDataFill.ppuDataPrepare1_ppuData+1 + jsr ppuDataFill + ldx #0 + // Initialize Sprite Buffer with the SPRITE data + __b1: + // for(char s=0;s<0x40;s++) + cpx #$40 + bcc __b2 + // PPU->PPUCTRL = 0b10000000 + lda #$80 + sta PPU + // PPU->PPUMASK = 0b00011110 + lda #$1e + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUMASK + __b3: + // Infinite loop + jmp __b3 + __b2: + // SPRITE_BUFFER[s] = { 0, MESSAGE[s], 0b00000010, 0 } + txa + asl + asl + tay + lda #0 + sta SPRITE_BUFFER,y + lda MESSAGE,x + sta SPRITE_BUFFER+OFFSET_STRUCT_SPRITEDATA_TILE,y + lda #2 + sta SPRITE_BUFFER+OFFSET_STRUCT_SPRITEDATA_ATTRIBUTES,y + lda #0 + sta SPRITE_BUFFER+OFFSET_STRUCT_SPRITEDATA_X,y + // for(char s=0;s<0x40;s++) + inx + jmp __b1 +} +// Fill a number of bytes in the PPU memory +// - ppuData : Pointer in the PPU memory +// - size : The number of bytes to transfer +// ppuDataFill(byte register(X) val, word zp(6) size) +ppuDataFill: { + .label ppuDataPrepare1_ppuData = 4 + .label i = 2 + .label size = 6 + // >ppuData + lda.z ppuDataPrepare1_ppuData+1 + // PPU->PPUADDR = >ppuData + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUADDR + // PPUADDR = PPUDATA = val + stx PPU+OFFSET_STRUCT_RICOH_2C02_PPUDATA + // for(unsigned int i=0;iPPUADDR = >ppuData + lda #>ppuData + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUADDR + // PPU->PPUADDR = cpuData + sta.z cpuSrc+1 + lda #<0 + sta.z i + sta.z i+1 + __b1: + // for(unsigned int i=0;isize + bcc __b2 + bne !+ + lda.z i + cmp #PPUDATA = val + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUDATA + // ppuDataPut(*cpuSrc++); + inc.z cpuSrc + bne !+ + inc.z cpuSrc+1 + !: + // for(unsigned int i=0;iPPUSCROLL = 0 + // Set scroll + lda #0 + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUSCROLL + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUSCROLL + // PPU->OAMADDR = 0 + sta PPU+OFFSET_STRUCT_RICOH_2C02_OAMADDR + // APU->OAMDMA = >spriteBuffer + lda #>SPRITE_BUFFER + sta APU+OFFSET_STRUCT_RICOH_2A03_OAMDMA + // y_idx = y_sin_idx++ + // Update sprite positions + lda.z y_sin_idx + sta.z y_idx + inc.z y_sin_idx + // x_idx = x_sin_idx++ + lda.z x_sin_idx + sta.z x_idx + inc.z x_sin_idx + ldx #0 + __b1: + // for(char s=0;s<0x40;s++) + cpx #$40 + bcc __b2 + // } + pla + tay + pla + tax + pla + rti + __b2: + // SPRITE_BUFFER[s].y = SINTABLE[y_idx] + txa + asl + asl + sta.z __4 + ldy.z y_idx + lda SINTABLE,y + ldy.z __4 + sta SPRITE_BUFFER,y + // SINTABLE[x_idx]+8 + lda #8 + ldy.z x_idx + clc + adc SINTABLE,y + // SPRITE_BUFFER[s].x = SINTABLE[x_idx]+8 + ldy.z __4 + sta SPRITE_BUFFER+OFFSET_STRUCT_SPRITEDATA_X,y + // y_idx += 4 + lda #4 + clc + adc.z y_idx + sta.z y_idx + // x_idx -= 7 + lda.z x_idx + sec + sbc #7 + sta.z x_idx + // for(char s=0;s<0x40;s++) + inx + jmp __b1 +} +.segment Data + // The DXYCP message 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef + MESSAGE: .text "rex-of-camelot-presents-a-dxycp-on-nintendo-entertainment-system" + // Color Palette + PALETTE: .byte 1, $21, $f, $30, 1, $21, $f, $30, 1, $21, $f, $30, 1, $21, $f, $30, 1, $f, $30, 8, 1, $f, $18, 8, 1, $30, $37, $1a, $f, $f, $f, $f + // Sinus Table (0-239) +SINTABLE: +.fill $100, round(115.5+107.5*sin(2*PI*i/256)) + +.segment Tiles +TILES: +.var filechargen = LoadBinary("characters.901225-01.bin") + .for(var c=0; c<256; c++) { + // Plane 0 + .fill 8, filechargen.get(c*8+i) + // Plane 1 + .fill 8, 0 + } + +.segment GameRam + .align $100 + SPRITE_BUFFER: .fill 4*$100, 0 +.segment Vectors + VECTORS: .word vblank, main, 0 diff --git a/src/test/ref/examples/nes-dxycp/nes-dxycp.cfg b/src/test/ref/examples/nes-dxycp/nes-dxycp.cfg new file mode 100644 index 000000000..27a207003 --- /dev/null +++ b/src/test/ref/examples/nes-dxycp/nes-dxycp.cfg @@ -0,0 +1,180 @@ +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] (volatile byte) y_sin_idx ← (byte) 0 + [2] (volatile byte) x_sin_idx ← (byte) $49 + to:@2 +@2: scope:[] from @1 + [3] phi() + [4] call main + to:@end +@end: scope:[] from @2 + [5] phi() + +(void()) main() +main: scope:[main] from @2 + [6] phi() + to:main::initNES1 +main::initNES1: scope:[main] from main + asm { cld ldx#$ff txs } + to:main::initNES1_disableVideoOutput1 +main::initNES1_disableVideoOutput1: scope:[main] from main::initNES1 + [8] *((byte*)(const struct RICOH_2C02*) PPU) ← (byte) 0 + [9] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUMASK) ← (byte) 0 + to:main::initNES1_disableAudioOutput1 +main::initNES1_disableAudioOutput1: scope:[main] from main::initNES1_disableVideoOutput1 + [10] *((const nomodify byte*) FR_COUNTER) ← (byte) $40 + [11] *((byte*)(const struct RICOH_2A03*) APU+(const byte) OFFSET_STRUCT_RICOH_2A03_DMC_FREQ) ← (byte) $40 + to:main::initNES1_clearVBlankFlag1 +main::initNES1_clearVBlankFlag1: scope:[main] from main::initNES1_disableAudioOutput1 + asm { ldaPPU_PPUSTATUS } + to:main::initNES1_waitForVBlank1 +main::initNES1_waitForVBlank1: scope:[main] from main::initNES1_clearVBlankFlag1 + [13] phi() + to:main::initNES1_waitForVBlank1_@1 +main::initNES1_waitForVBlank1_@1: scope:[main] from main::initNES1_waitForVBlank1 main::initNES1_waitForVBlank1_@1 + [14] (byte~) main::initNES1_waitForVBlank1_$0 ← *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSTATUS) & (byte) $80 + [15] if((byte) 0==(byte~) main::initNES1_waitForVBlank1_$0) goto main::initNES1_waitForVBlank1_@1 + to:main::initNES1_@1 +main::initNES1_@1: scope:[main] from main::initNES1_@1 main::initNES1_waitForVBlank1_@1 + [16] (byte) main::initNES1_i#2 ← phi( main::initNES1_@1/(byte) main::initNES1_i#1 main::initNES1_waitForVBlank1_@1/(byte) 0 ) + [17] *((const nomodify byte*) MEMORY + (byte) main::initNES1_i#2) ← (byte) 0 + [18] *((const nomodify byte*) MEMORY+(word) $100 + (byte) main::initNES1_i#2) ← (byte) 0 + [19] *((const nomodify byte*) MEMORY+(word) $200 + (byte) main::initNES1_i#2) ← (byte) 0 + [20] *((const nomodify byte*) MEMORY+(word) $300 + (byte) main::initNES1_i#2) ← (byte) 0 + [21] *((const nomodify byte*) MEMORY+(word) $400 + (byte) main::initNES1_i#2) ← (byte) 0 + [22] *((const nomodify byte*) MEMORY+(word) $500 + (byte) main::initNES1_i#2) ← (byte) 0 + [23] *((const nomodify byte*) MEMORY+(word) $600 + (byte) main::initNES1_i#2) ← (byte) 0 + [24] *((const nomodify byte*) MEMORY+(word) $700 + (byte) main::initNES1_i#2) ← (byte) 0 + [25] (byte) main::initNES1_i#1 ← ++ (byte) main::initNES1_i#2 + [26] if((byte) 0!=(byte) main::initNES1_i#1) goto main::initNES1_@1 + to:main::initNES1_waitForVBlank2 +main::initNES1_waitForVBlank2: scope:[main] from main::initNES1_@1 + [27] phi() + to:main::initNES1_waitForVBlank2_@1 +main::initNES1_waitForVBlank2_@1: scope:[main] from main::initNES1_waitForVBlank2 main::initNES1_waitForVBlank2_@1 + [28] (byte~) main::initNES1_waitForVBlank2_$0 ← *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSTATUS) & (byte) $80 + [29] if((byte) 0==(byte~) main::initNES1_waitForVBlank2_$0) goto main::initNES1_waitForVBlank2_@1 + to:main::initNES1_@7 +main::initNES1_@7: scope:[main] from main::initNES1_waitForVBlank2_@1 + asm { ldaPPU_PPUSTATUS } + to:main::@4 +main::@4: scope:[main] from main::initNES1_@7 + [31] phi() + [32] call ppuDataTransfer + to:main::@5 +main::@5: scope:[main] from main::@4 + [33] phi() + [34] call ppuDataFill + to:main::@6 +main::@6: scope:[main] from main::@5 + [35] phi() + [36] call ppuDataFill + to:main::@1 +main::@1: scope:[main] from main::@2 main::@6 + [37] (byte) main::s#2 ← phi( main::@2/(byte) main::s#1 main::@6/(byte) 0 ) + [38] if((byte) main::s#2<(byte) $40) goto main::@2 + to:main::enableVideoOutput1 +main::enableVideoOutput1: scope:[main] from main::@1 + [39] *((byte*)(const struct RICOH_2C02*) PPU) ← (byte) $80 + [40] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUMASK) ← (byte) $1e + to:main::@3 +main::@3: scope:[main] from main::@3 main::enableVideoOutput1 + [41] phi() + to:main::@3 +main::@2: scope:[main] from main::@1 + [42] (byte~) main::$7 ← (byte) main::s#2 << (byte) 2 + [43] *((byte*)(const struct SpriteData*) SPRITE_BUFFER + (byte~) main::$7) ← (byte) 0 + [44] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_TILE + (byte~) main::$7) ← *((const byte*) MESSAGE + (byte) main::s#2) + [45] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_ATTRIBUTES + (byte~) main::$7) ← (byte) 2 + [46] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_X + (byte~) main::$7) ← (byte) 0 + [47] (byte) main::s#1 ← ++ (byte) main::s#2 + to:main::@1 + +(void()) ppuDataFill((nomodify void*) ppuDataFill::ppuData , (byte) ppuDataFill::val , (word) ppuDataFill::size) +ppuDataFill: scope:[ppuDataFill] from main::@5 main::@6 + [48] (byte) ppuDataFill::val#4 ← phi( main::@5/(byte) '*' main::@6/(byte) 0 ) + [48] (word) ppuDataFill::size#3 ← phi( main::@5/(word)(number) $20*(number) $1e main::@6/(byte) $40 ) + [48] (nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0 ← phi( main::@5/(void*)(const nomodify byte*) PPU_NAME_TABLE_0 main::@6/(void*)(const nomodify byte*) PPU_ATTRIBUTE_TABLE_0 ) + to:ppuDataFill::ppuDataPrepare1 +ppuDataFill::ppuDataPrepare1: scope:[ppuDataFill] from ppuDataFill + [49] (byte~) ppuDataFill::ppuDataPrepare1_$0 ← > (nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0 + [50] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← (byte~) ppuDataFill::ppuDataPrepare1_$0 + [51] (byte~) ppuDataFill::ppuDataPrepare1_$1 ← < (nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0 + [52] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← (byte~) ppuDataFill::ppuDataPrepare1_$1 + to:ppuDataFill::@1 +ppuDataFill::@1: scope:[ppuDataFill] from ppuDataFill::@2 ppuDataFill::ppuDataPrepare1 + [53] (word) ppuDataFill::i#2 ← phi( ppuDataFill::ppuDataPrepare1/(word) 0 ppuDataFill::@2/(word) ppuDataFill::i#1 ) + [54] if((word) ppuDataFill::i#2<(word) ppuDataFill::size#3) goto ppuDataFill::ppuDataPut1 + to:ppuDataFill::@return +ppuDataFill::@return: scope:[ppuDataFill] from ppuDataFill::@1 + [55] return + to:@return +ppuDataFill::ppuDataPut1: scope:[ppuDataFill] from ppuDataFill::@1 + [56] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUDATA) ← (byte) ppuDataFill::val#4 + to:ppuDataFill::@2 +ppuDataFill::@2: scope:[ppuDataFill] from ppuDataFill::ppuDataPut1 + [57] (word) ppuDataFill::i#1 ← ++ (word) ppuDataFill::i#2 + to:ppuDataFill::@1 + +(void()) ppuDataTransfer((nomodify void*) ppuDataTransfer::ppuData , (nomodify void*) ppuDataTransfer::cpuData , (word) ppuDataTransfer::size) +ppuDataTransfer: scope:[ppuDataTransfer] from main::@4 + [58] phi() + to:ppuDataTransfer::ppuDataPrepare1 +ppuDataTransfer::ppuDataPrepare1: scope:[ppuDataTransfer] from ppuDataTransfer + [59] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← >(const nomodify void*) ppuDataTransfer::ppuData#0 + [60] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← (byte) 0 + to:ppuDataTransfer::@1 +ppuDataTransfer::@1: scope:[ppuDataTransfer] from ppuDataTransfer::@3 ppuDataTransfer::ppuDataPrepare1 + [61] (byte*) ppuDataTransfer::cpuSrc#2 ← phi( ppuDataTransfer::ppuDataPrepare1/(byte*)(const nomodify void*) ppuDataTransfer::cpuData#0 ppuDataTransfer::@3/(byte*) ppuDataTransfer::cpuSrc#1 ) + [61] (word) ppuDataTransfer::i#2 ← phi( ppuDataTransfer::ppuDataPrepare1/(word) 0 ppuDataTransfer::@3/(word) ppuDataTransfer::i#1 ) + [62] if((word) ppuDataTransfer::i#2<(const word) ppuDataTransfer::size#0) goto ppuDataTransfer::@2 + to:ppuDataTransfer::@return +ppuDataTransfer::@return: scope:[ppuDataTransfer] from ppuDataTransfer::@1 + [63] return + to:@return +ppuDataTransfer::@2: scope:[ppuDataTransfer] from ppuDataTransfer::@1 + [64] (byte) ppuDataTransfer::ppuDataPut1_val#0 ← *((byte*) ppuDataTransfer::cpuSrc#2) + to:ppuDataTransfer::ppuDataPut1 +ppuDataTransfer::ppuDataPut1: scope:[ppuDataTransfer] from ppuDataTransfer::@2 + [65] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUDATA) ← (byte) ppuDataTransfer::ppuDataPut1_val#0 + to:ppuDataTransfer::@3 +ppuDataTransfer::@3: scope:[ppuDataTransfer] from ppuDataTransfer::ppuDataPut1 + [66] (byte*) ppuDataTransfer::cpuSrc#1 ← ++ (byte*) ppuDataTransfer::cpuSrc#2 + [67] (word) ppuDataTransfer::i#1 ← ++ (word) ppuDataTransfer::i#2 + to:ppuDataTransfer::@1 + +interrupt(HARDWARE_STACK)(void()) vblank() +vblank: scope:[vblank] from + [68] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSCROLL) ← (byte) 0 + [69] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSCROLL) ← (byte) 0 + to:vblank::ppuSpriteBufferDmaTransfer1 +vblank::ppuSpriteBufferDmaTransfer1: scope:[vblank] from vblank + [70] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_OAMADDR) ← (byte) 0 + [71] *((byte*)(const struct RICOH_2A03*) APU+(const byte) OFFSET_STRUCT_RICOH_2A03_OAMDMA) ← >(const struct SpriteData*) SPRITE_BUFFER + to:vblank::@3 +vblank::@3: scope:[vblank] from vblank::ppuSpriteBufferDmaTransfer1 + [72] (byte) vblank::y_idx#0 ← (volatile byte) y_sin_idx + [73] (volatile byte) y_sin_idx ← ++ (volatile byte) y_sin_idx + [74] (byte) vblank::x_idx#0 ← (volatile byte) x_sin_idx + [75] (volatile byte) x_sin_idx ← ++ (volatile byte) x_sin_idx + to:vblank::@1 +vblank::@1: scope:[vblank] from vblank::@2 vblank::@3 + [76] (byte) vblank::x_idx#2 ← phi( vblank::@2/(byte) vblank::x_idx#1 vblank::@3/(byte) vblank::x_idx#0 ) + [76] (byte) vblank::y_idx#2 ← phi( vblank::@2/(byte) vblank::y_idx#1 vblank::@3/(byte) vblank::y_idx#0 ) + [76] (byte) vblank::s#2 ← phi( vblank::@2/(byte) vblank::s#1 vblank::@3/(byte) 0 ) + [77] if((byte) vblank::s#2<(byte) $40) goto vblank::@2 + to:vblank::@return +vblank::@return: scope:[vblank] from vblank::@1 + [78] return + to:@return +vblank::@2: scope:[vblank] from vblank::@1 + [79] (byte~) vblank::$4 ← (byte) vblank::s#2 << (byte) 2 + [80] *((byte*)(const struct SpriteData*) SPRITE_BUFFER + (byte~) vblank::$4) ← *((const to_nomodify byte*) SINTABLE + (byte) vblank::y_idx#2) + [81] (byte~) vblank::$2 ← *((const to_nomodify byte*) SINTABLE + (byte) vblank::x_idx#2) + (byte) 8 + [82] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_X + (byte~) vblank::$4) ← (byte~) vblank::$2 + [83] (byte) vblank::y_idx#1 ← (byte) vblank::y_idx#2 + (byte) 4 + [84] (byte) vblank::x_idx#1 ← (byte) vblank::x_idx#2 - (byte) 7 + [85] (byte) vblank::s#1 ← ++ (byte) vblank::s#2 + to:vblank::@1 diff --git a/src/test/ref/examples/nes-dxycp/nes-dxycp.log b/src/test/ref/examples/nes-dxycp/nes-dxycp.log new file mode 100644 index 000000000..9dad3f465 --- /dev/null +++ b/src/test/ref/examples/nes-dxycp/nes-dxycp.log @@ -0,0 +1,3643 @@ +Resolved forward reference PALETTE to (const byte*) PALETTE +Resolved forward reference PALETTE to (const byte*) PALETTE +Resolved forward reference MESSAGE to (const byte*) MESSAGE +Resolved forward reference SPRITE_BUFFER to (const struct SpriteData*) SPRITE_BUFFER +Resolved forward reference SPRITE_BUFFER to (const struct SpriteData*) SPRITE_BUFFER +Resolved forward reference SINTABLE to (const to_nomodify byte*) SINTABLE +Resolved forward reference SPRITE_BUFFER to (const struct SpriteData*) SPRITE_BUFFER +Resolved forward reference SINTABLE to (const to_nomodify byte*) SINTABLE +Resolved forward reference SPRITE_BUFFER to (const struct SpriteData*) SPRITE_BUFFER +Constantified RValue *((const struct SpriteData*) SPRITE_BUFFER + (byte~) main::$7) ← (struct SpriteData){ (byte) 0, *((const byte*) MESSAGE + (byte) main::s), (byte) 2, (byte) 0 } +Inlined call call disableVideoOutput +Inlined call call disableAudioOutput +Inlined call call clearVBlankFlag +Inlined call call waitForVBlank +Inlined call call waitForVBlank +Inlined call call ppuDataPrepare (nomodify void*) ppuDataFill::ppuData +Inlined call call ppuDataPut (byte) ppuDataFill::val +Inlined call call ppuDataPrepare (nomodify void*) ppuDataTransfer::ppuData +Inlined call call ppuDataPut *((byte*) ppuDataTransfer::cpuSrc) +Inlined call call ppuDataPrepare (nomodify void*) ppuDataFetch::ppuData +Inlined call (byte~) ppuDataFetch::$2 ← call ppuDataRead +Inlined call call ppuDataPrepare (nomodify void*) ppuDataPutTile::ppuData +Inlined call call ppuDataPut *((byte*) ppuDataPutTile::tile + (number) 0) +Inlined call call ppuDataPut *((byte*) ppuDataPutTile::tile + (number) 1) +Inlined call call ppuDataPrepare (void*)(byte*~) ppuDataPutTile::$3 +Inlined call call ppuDataPut *((byte*) ppuDataPutTile::tile + (number) 2) +Inlined call call ppuDataPut *((byte*) ppuDataPutTile::tile + (number) 3) +Inlined call call ppuDataPrepare (nomodify void*) ppuDataSet::ppuData +Inlined call call ppuDataPut (byte) ppuDataSet::val +Inlined call call ppuDataPrepare (nomodify void*) ppuDataGet::ppuData +Inlined call (byte~) ppuDataGet::$1 ← call ppuDataRead +Inlined call call initNES +Inlined call call enableVideoOutput +Inlined call call ppuSpriteBufferDmaTransfer (const struct SpriteData*) SPRITE_BUFFER + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + to:@1 + +(void()) ppuDataFill((nomodify void*) ppuDataFill::ppuData , (byte) ppuDataFill::val , (word) ppuDataFill::size) +ppuDataFill: scope:[ppuDataFill] from main::@5 main::@6 + (byte) ppuDataFill::val#8 ← phi( main::@5/(byte) ppuDataFill::val#0 main::@6/(byte) ppuDataFill::val#1 ) + (word) ppuDataFill::size#7 ← phi( main::@5/(word) ppuDataFill::size#0 main::@6/(word) ppuDataFill::size#1 ) + (nomodify void*) ppuDataFill::ppuData#2 ← phi( main::@5/(nomodify void*) ppuDataFill::ppuData#0 main::@6/(nomodify void*) ppuDataFill::ppuData#1 ) + (nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0 ← (nomodify void*) ppuDataFill::ppuData#2 + to:ppuDataFill::ppuDataPrepare1 +ppuDataFill::ppuDataPrepare1: scope:[ppuDataFill] from ppuDataFill + (byte) ppuDataFill::val#6 ← phi( ppuDataFill/(byte) ppuDataFill::val#8 ) + (word) ppuDataFill::size#5 ← phi( ppuDataFill/(word) ppuDataFill::size#7 ) + (nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#1 ← phi( ppuDataFill/(nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0 ) + (byte~) ppuDataFill::ppuDataPrepare1_$0 ← > (nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#1 + (byte*~) ppuDataFill::ppuDataPrepare1_$4 ← (byte*)(const struct RICOH_2C02*) PPU + (byte*~) ppuDataFill::ppuDataPrepare1_$2 ← (byte*~) ppuDataFill::ppuDataPrepare1_$4 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR + *((byte*~) ppuDataFill::ppuDataPrepare1_$2) ← (byte~) ppuDataFill::ppuDataPrepare1_$0 + (byte~) ppuDataFill::ppuDataPrepare1_$1 ← < (nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#1 + (byte*~) ppuDataFill::ppuDataPrepare1_$5 ← (byte*)(const struct RICOH_2C02*) PPU + (byte*~) ppuDataFill::ppuDataPrepare1_$3 ← (byte*~) ppuDataFill::ppuDataPrepare1_$5 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR + *((byte*~) ppuDataFill::ppuDataPrepare1_$3) ← (byte~) ppuDataFill::ppuDataPrepare1_$1 + to:ppuDataFill::@3 +ppuDataFill::@3: scope:[ppuDataFill] from ppuDataFill::ppuDataPrepare1 + (byte) ppuDataFill::val#4 ← phi( ppuDataFill::ppuDataPrepare1/(byte) ppuDataFill::val#6 ) + (word) ppuDataFill::size#3 ← phi( ppuDataFill::ppuDataPrepare1/(word) ppuDataFill::size#5 ) + (word) ppuDataFill::i#0 ← (word) 0 + to:ppuDataFill::@1 +ppuDataFill::@1: scope:[ppuDataFill] from ppuDataFill::@3 ppuDataFill::@4 + (byte) ppuDataFill::val#3 ← phi( ppuDataFill::@3/(byte) ppuDataFill::val#4 ppuDataFill::@4/(byte) ppuDataFill::val#5 ) + (word) ppuDataFill::size#2 ← phi( ppuDataFill::@3/(word) ppuDataFill::size#3 ppuDataFill::@4/(word) ppuDataFill::size#4 ) + (word) ppuDataFill::i#2 ← phi( ppuDataFill::@3/(word) ppuDataFill::i#0 ppuDataFill::@4/(word) ppuDataFill::i#1 ) + (bool~) ppuDataFill::$1 ← (word) ppuDataFill::i#2 < (word) ppuDataFill::size#2 + if((bool~) ppuDataFill::$1) goto ppuDataFill::@2 + to:ppuDataFill::@return +ppuDataFill::@2: scope:[ppuDataFill] from ppuDataFill::@1 + (word) ppuDataFill::size#8 ← phi( ppuDataFill::@1/(word) ppuDataFill::size#2 ) + (word) ppuDataFill::i#5 ← phi( ppuDataFill::@1/(word) ppuDataFill::i#2 ) + (byte) ppuDataFill::val#2 ← phi( ppuDataFill::@1/(byte) ppuDataFill::val#3 ) + (byte) ppuDataFill::ppuDataPut1_val#0 ← (byte) ppuDataFill::val#2 + to:ppuDataFill::ppuDataPut1 +ppuDataFill::ppuDataPut1: scope:[ppuDataFill] from ppuDataFill::@2 + (byte) ppuDataFill::val#7 ← phi( ppuDataFill::@2/(byte) ppuDataFill::val#2 ) + (word) ppuDataFill::size#6 ← phi( ppuDataFill::@2/(word) ppuDataFill::size#8 ) + (word) ppuDataFill::i#4 ← phi( ppuDataFill::@2/(word) ppuDataFill::i#5 ) + (byte) ppuDataFill::ppuDataPut1_val#1 ← phi( ppuDataFill::@2/(byte) ppuDataFill::ppuDataPut1_val#0 ) + (byte*~) ppuDataFill::ppuDataPut1_$1 ← (byte*)(const struct RICOH_2C02*) PPU + (byte*~) ppuDataFill::ppuDataPut1_$0 ← (byte*~) ppuDataFill::ppuDataPut1_$1 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUDATA + *((byte*~) ppuDataFill::ppuDataPut1_$0) ← (byte) ppuDataFill::ppuDataPut1_val#1 + to:ppuDataFill::@4 +ppuDataFill::@4: scope:[ppuDataFill] from ppuDataFill::ppuDataPut1 + (byte) ppuDataFill::val#5 ← phi( ppuDataFill::ppuDataPut1/(byte) ppuDataFill::val#7 ) + (word) ppuDataFill::size#4 ← phi( ppuDataFill::ppuDataPut1/(word) ppuDataFill::size#6 ) + (word) ppuDataFill::i#3 ← phi( ppuDataFill::ppuDataPut1/(word) ppuDataFill::i#4 ) + (word) ppuDataFill::i#1 ← ++ (word) ppuDataFill::i#3 + to:ppuDataFill::@1 +ppuDataFill::@return: scope:[ppuDataFill] from ppuDataFill::@1 + return + to:@return + +(void()) ppuDataTransfer((nomodify void*) ppuDataTransfer::ppuData , (nomodify void*) ppuDataTransfer::cpuData , (word) ppuDataTransfer::size) +ppuDataTransfer: scope:[ppuDataTransfer] from main::@4 + (word) ppuDataTransfer::size#6 ← phi( main::@4/(word) ppuDataTransfer::size#0 ) + (nomodify void*) ppuDataTransfer::cpuData#3 ← phi( main::@4/(nomodify void*) ppuDataTransfer::cpuData#0 ) + (nomodify void*) ppuDataTransfer::ppuData#1 ← phi( main::@4/(nomodify void*) ppuDataTransfer::ppuData#0 ) + (nomodify void*) ppuDataTransfer::ppuDataPrepare1_ppuData#0 ← (nomodify void*) ppuDataTransfer::ppuData#1 + to:ppuDataTransfer::ppuDataPrepare1 +ppuDataTransfer::ppuDataPrepare1: scope:[ppuDataTransfer] from ppuDataTransfer + (word) ppuDataTransfer::size#4 ← phi( ppuDataTransfer/(word) ppuDataTransfer::size#6 ) + (nomodify void*) ppuDataTransfer::cpuData#2 ← phi( ppuDataTransfer/(nomodify void*) ppuDataTransfer::cpuData#3 ) + (nomodify void*) ppuDataTransfer::ppuDataPrepare1_ppuData#1 ← phi( ppuDataTransfer/(nomodify void*) ppuDataTransfer::ppuDataPrepare1_ppuData#0 ) + (byte~) ppuDataTransfer::ppuDataPrepare1_$0 ← > (nomodify void*) ppuDataTransfer::ppuDataPrepare1_ppuData#1 + (byte*~) ppuDataTransfer::ppuDataPrepare1_$4 ← (byte*)(const struct RICOH_2C02*) PPU + (byte*~) ppuDataTransfer::ppuDataPrepare1_$2 ← (byte*~) ppuDataTransfer::ppuDataPrepare1_$4 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR + *((byte*~) ppuDataTransfer::ppuDataPrepare1_$2) ← (byte~) ppuDataTransfer::ppuDataPrepare1_$0 + (byte~) ppuDataTransfer::ppuDataPrepare1_$1 ← < (nomodify void*) ppuDataTransfer::ppuDataPrepare1_ppuData#1 + (byte*~) ppuDataTransfer::ppuDataPrepare1_$5 ← (byte*)(const struct RICOH_2C02*) PPU + (byte*~) ppuDataTransfer::ppuDataPrepare1_$3 ← (byte*~) ppuDataTransfer::ppuDataPrepare1_$5 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR + *((byte*~) ppuDataTransfer::ppuDataPrepare1_$3) ← (byte~) ppuDataTransfer::ppuDataPrepare1_$1 + to:ppuDataTransfer::@3 +ppuDataTransfer::@3: scope:[ppuDataTransfer] from ppuDataTransfer::ppuDataPrepare1 + (word) ppuDataTransfer::size#2 ← phi( ppuDataTransfer::ppuDataPrepare1/(word) ppuDataTransfer::size#4 ) + (nomodify void*) ppuDataTransfer::cpuData#1 ← phi( ppuDataTransfer::ppuDataPrepare1/(nomodify void*) ppuDataTransfer::cpuData#2 ) + (byte*) ppuDataTransfer::cpuSrc#0 ← (byte*)(nomodify void*) ppuDataTransfer::cpuData#1 + (word) ppuDataTransfer::i#0 ← (word) 0 + to:ppuDataTransfer::@1 +ppuDataTransfer::@1: scope:[ppuDataTransfer] from ppuDataTransfer::@3 ppuDataTransfer::@4 + (byte*) ppuDataTransfer::cpuSrc#4 ← phi( ppuDataTransfer::@3/(byte*) ppuDataTransfer::cpuSrc#0 ppuDataTransfer::@4/(byte*) ppuDataTransfer::cpuSrc#1 ) + (word) ppuDataTransfer::size#1 ← phi( ppuDataTransfer::@3/(word) ppuDataTransfer::size#2 ppuDataTransfer::@4/(word) ppuDataTransfer::size#3 ) + (word) ppuDataTransfer::i#2 ← phi( ppuDataTransfer::@3/(word) ppuDataTransfer::i#0 ppuDataTransfer::@4/(word) ppuDataTransfer::i#1 ) + (bool~) ppuDataTransfer::$1 ← (word) ppuDataTransfer::i#2 < (word) ppuDataTransfer::size#1 + if((bool~) ppuDataTransfer::$1) goto ppuDataTransfer::@2 + to:ppuDataTransfer::@return +ppuDataTransfer::@2: scope:[ppuDataTransfer] from ppuDataTransfer::@1 + (word) ppuDataTransfer::size#7 ← phi( ppuDataTransfer::@1/(word) ppuDataTransfer::size#1 ) + (word) ppuDataTransfer::i#5 ← phi( ppuDataTransfer::@1/(word) ppuDataTransfer::i#2 ) + (byte*) ppuDataTransfer::cpuSrc#2 ← phi( ppuDataTransfer::@1/(byte*) ppuDataTransfer::cpuSrc#4 ) + (byte) ppuDataTransfer::ppuDataPut1_val#0 ← *((byte*) ppuDataTransfer::cpuSrc#2) + to:ppuDataTransfer::ppuDataPut1 +ppuDataTransfer::ppuDataPut1: scope:[ppuDataTransfer] from ppuDataTransfer::@2 + (word) ppuDataTransfer::size#5 ← phi( ppuDataTransfer::@2/(word) ppuDataTransfer::size#7 ) + (word) ppuDataTransfer::i#4 ← phi( ppuDataTransfer::@2/(word) ppuDataTransfer::i#5 ) + (byte*) ppuDataTransfer::cpuSrc#5 ← phi( ppuDataTransfer::@2/(byte*) ppuDataTransfer::cpuSrc#2 ) + (byte) ppuDataTransfer::ppuDataPut1_val#1 ← phi( ppuDataTransfer::@2/(byte) ppuDataTransfer::ppuDataPut1_val#0 ) + (byte*~) ppuDataTransfer::ppuDataPut1_$1 ← (byte*)(const struct RICOH_2C02*) PPU + (byte*~) ppuDataTransfer::ppuDataPut1_$0 ← (byte*~) ppuDataTransfer::ppuDataPut1_$1 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUDATA + *((byte*~) ppuDataTransfer::ppuDataPut1_$0) ← (byte) ppuDataTransfer::ppuDataPut1_val#1 + to:ppuDataTransfer::@4 +ppuDataTransfer::@4: scope:[ppuDataTransfer] from ppuDataTransfer::ppuDataPut1 + (word) ppuDataTransfer::size#3 ← phi( ppuDataTransfer::ppuDataPut1/(word) ppuDataTransfer::size#5 ) + (word) ppuDataTransfer::i#3 ← phi( ppuDataTransfer::ppuDataPut1/(word) ppuDataTransfer::i#4 ) + (byte*) ppuDataTransfer::cpuSrc#3 ← phi( ppuDataTransfer::ppuDataPut1/(byte*) ppuDataTransfer::cpuSrc#5 ) + (byte*) ppuDataTransfer::cpuSrc#1 ← ++ (byte*) ppuDataTransfer::cpuSrc#3 + (word) ppuDataTransfer::i#1 ← ++ (word) ppuDataTransfer::i#3 + to:ppuDataTransfer::@1 +ppuDataTransfer::@return: scope:[ppuDataTransfer] from ppuDataTransfer::@1 + return + to:@return + +(void()) main() +main: scope:[main] from @2 + to:main::initNES1 +main::initNES1: scope:[main] from main + asm { cld ldx#$ff txs } + to:main::initNES1_disableVideoOutput1 +main::initNES1_disableVideoOutput1: scope:[main] from main::initNES1 + (byte*~) main::initNES1_disableVideoOutput1_$2 ← (byte*)(const struct RICOH_2C02*) PPU + (byte*~) main::initNES1_disableVideoOutput1_$0 ← (byte*~) main::initNES1_disableVideoOutput1_$2 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUCTRL + *((byte*~) main::initNES1_disableVideoOutput1_$0) ← (number) 0 + (byte*~) main::initNES1_disableVideoOutput1_$3 ← (byte*)(const struct RICOH_2C02*) PPU + (byte*~) main::initNES1_disableVideoOutput1_$1 ← (byte*~) main::initNES1_disableVideoOutput1_$3 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUMASK + *((byte*~) main::initNES1_disableVideoOutput1_$1) ← (number) 0 + to:main::initNES1_disableAudioOutput1 +main::initNES1_disableAudioOutput1: scope:[main] from main::initNES1_disableVideoOutput1 + *((const nomodify byte*) FR_COUNTER) ← (number) $40 + (byte*~) main::initNES1_disableAudioOutput1_$1 ← (byte*)(const struct RICOH_2A03*) APU + (byte*~) main::initNES1_disableAudioOutput1_$0 ← (byte*~) main::initNES1_disableAudioOutput1_$1 + (const byte) OFFSET_STRUCT_RICOH_2A03_DMC_FREQ + *((byte*~) main::initNES1_disableAudioOutput1_$0) ← (number) $40 + to:main::initNES1_clearVBlankFlag1 +main::initNES1_clearVBlankFlag1: scope:[main] from main::initNES1_disableAudioOutput1 + asm { ldaPPU_PPUSTATUS } + to:main::initNES1_waitForVBlank1 +main::initNES1_waitForVBlank1: scope:[main] from main::initNES1_clearVBlankFlag1 + to:main::initNES1_waitForVBlank1_@1 +main::initNES1_waitForVBlank1_@1: scope:[main] from main::initNES1_waitForVBlank1 main::initNES1_waitForVBlank1_@1 + (byte*~) main::initNES1_waitForVBlank1_$3 ← (byte*)(const struct RICOH_2C02*) PPU + (byte*~) main::initNES1_waitForVBlank1_$2 ← (byte*~) main::initNES1_waitForVBlank1_$3 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUSTATUS + (number~) main::initNES1_waitForVBlank1_$0 ← *((byte*~) main::initNES1_waitForVBlank1_$2) & (number) $80 + (bool~) main::initNES1_waitForVBlank1_$4 ← (number) 0 != (number~) main::initNES1_waitForVBlank1_$0 + (bool~) main::initNES1_waitForVBlank1_$1 ← ! (bool~) main::initNES1_waitForVBlank1_$4 + if((bool~) main::initNES1_waitForVBlank1_$1) goto main::initNES1_waitForVBlank1_@1 + to:main::initNES1_@6 +main::initNES1_@6: scope:[main] from main::initNES1_waitForVBlank1_@1 + (byte) main::initNES1_i#0 ← (byte) 0 + to:main::initNES1_@1 +main::initNES1_@1: scope:[main] from main::initNES1_@1 main::initNES1_@6 + (byte) main::initNES1_i#2 ← phi( main::initNES1_@1/(byte) main::initNES1_i#1 main::initNES1_@6/(byte) main::initNES1_i#0 ) + *((const nomodify byte*) MEMORY+(number) 0 + (byte) main::initNES1_i#2) ← (number) 0 + *((const nomodify byte*) MEMORY+(number) $100 + (byte) main::initNES1_i#2) ← (number) 0 + *((const nomodify byte*) MEMORY+(number) $200 + (byte) main::initNES1_i#2) ← (number) 0 + *((const nomodify byte*) MEMORY+(number) $300 + (byte) main::initNES1_i#2) ← (number) 0 + *((const nomodify byte*) MEMORY+(number) $400 + (byte) main::initNES1_i#2) ← (number) 0 + *((const nomodify byte*) MEMORY+(number) $500 + (byte) main::initNES1_i#2) ← (number) 0 + *((const nomodify byte*) MEMORY+(number) $600 + (byte) main::initNES1_i#2) ← (number) 0 + *((const nomodify byte*) MEMORY+(number) $700 + (byte) main::initNES1_i#2) ← (number) 0 + (byte) main::initNES1_i#1 ← ++ (byte) main::initNES1_i#2 + (bool~) main::initNES1_$5 ← (number) 0 != (byte) main::initNES1_i#1 + if((bool~) main::initNES1_$5) goto main::initNES1_@1 + to:main::initNES1_waitForVBlank2 +main::initNES1_waitForVBlank2: scope:[main] from main::initNES1_@1 + to:main::initNES1_waitForVBlank2_@1 +main::initNES1_waitForVBlank2_@1: scope:[main] from main::initNES1_waitForVBlank2 main::initNES1_waitForVBlank2_@1 + (byte*~) main::initNES1_waitForVBlank2_$3 ← (byte*)(const struct RICOH_2C02*) PPU + (byte*~) main::initNES1_waitForVBlank2_$2 ← (byte*~) main::initNES1_waitForVBlank2_$3 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUSTATUS + (number~) main::initNES1_waitForVBlank2_$0 ← *((byte*~) main::initNES1_waitForVBlank2_$2) & (number) $80 + (bool~) main::initNES1_waitForVBlank2_$4 ← (number) 0 != (number~) main::initNES1_waitForVBlank2_$0 + (bool~) main::initNES1_waitForVBlank2_$1 ← ! (bool~) main::initNES1_waitForVBlank2_$4 + if((bool~) main::initNES1_waitForVBlank2_$1) goto main::initNES1_waitForVBlank2_@1 + to:main::initNES1_@7 +main::initNES1_@7: scope:[main] from main::initNES1_waitForVBlank2_@1 + asm { ldaPPU_PPUSTATUS } + to:main::@4 +main::@4: scope:[main] from main::initNES1_@7 + (byte~) main::$1 ← sizeof (const byte*) PALETTE + (nomodify void*) ppuDataTransfer::ppuData#0 ← (void*)(const nomodify byte*) PPU_PALETTE + (nomodify void*) ppuDataTransfer::cpuData#0 ← (void*)(const byte*) PALETTE + (word) ppuDataTransfer::size#0 ← (byte~) main::$1 + call ppuDataTransfer + to:main::@5 +main::@5: scope:[main] from main::@4 + (nomodify void*) ppuDataFill::ppuData#0 ← (void*)(const nomodify byte*) PPU_NAME_TABLE_0 + (byte) ppuDataFill::val#0 ← (byte) '*' + (word) ppuDataFill::size#0 ← (number) $20*(number) $1e + call ppuDataFill + to:main::@6 +main::@6: scope:[main] from main::@5 + (nomodify void*) ppuDataFill::ppuData#1 ← (void*)(const nomodify byte*) PPU_ATTRIBUTE_TABLE_0 + (byte) ppuDataFill::val#1 ← (number) 0 + (word) ppuDataFill::size#1 ← (number) $40 + call ppuDataFill + to:main::@7 +main::@7: scope:[main] from main::@6 + (byte) main::s#0 ← (byte) 0 + to:main::@1 +main::@1: scope:[main] from main::@2 main::@7 + (byte) main::s#2 ← phi( main::@2/(byte) main::s#1 main::@7/(byte) main::s#0 ) + (bool~) main::$6 ← (byte) main::s#2 < (number) $40 + if((bool~) main::$6) goto main::@2 + to:main::enableVideoOutput1 +main::@2: scope:[main] from main::@1 + (byte) main::s#3 ← phi( main::@1/(byte) main::s#2 ) + (byte~) main::$7 ← (byte) main::s#3 * (const byte) SIZEOF_STRUCT_SPRITEDATA + *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_Y + (byte~) main::$7) ← (byte) 0 + *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_TILE + (byte~) main::$7) ← *((const byte*) MESSAGE + (byte) main::s#3) + *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_ATTRIBUTES + (byte~) main::$7) ← (byte) 2 + *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_X + (byte~) main::$7) ← (byte) 0 + (byte) main::s#1 ← ++ (byte) main::s#3 + to:main::@1 +main::enableVideoOutput1: scope:[main] from main::@1 + (byte*~) main::enableVideoOutput1_$2 ← (byte*)(const struct RICOH_2C02*) PPU + (byte*~) main::enableVideoOutput1_$0 ← (byte*~) main::enableVideoOutput1_$2 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUCTRL + *((byte*~) main::enableVideoOutput1_$0) ← (number) $80 + (byte*~) main::enableVideoOutput1_$3 ← (byte*)(const struct RICOH_2C02*) PPU + (byte*~) main::enableVideoOutput1_$1 ← (byte*~) main::enableVideoOutput1_$3 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUMASK + *((byte*~) main::enableVideoOutput1_$1) ← (number) $1e + to:main::@3 +main::@3: scope:[main] from main::@3 main::enableVideoOutput1 + (bool~) main::$8 ← (number) 0 != (number) 1 + if((bool~) main::$8) goto main::@3 + to:main::@return +main::@return: scope:[main] from main::@3 + return + to:@return +@1: scope:[] from @begin + (volatile byte) y_sin_idx ← (byte) 0 + (volatile byte) x_sin_idx ← (byte) $49 + to:@2 + +interrupt(HARDWARE_STACK)(void()) vblank() +vblank: scope:[vblank] from + (byte*~) vblank::$7 ← (byte*)(const struct RICOH_2C02*) PPU + (byte*~) vblank::$5 ← (byte*~) vblank::$7 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUSCROLL + *((byte*~) vblank::$5) ← (number) 0 + (byte*~) vblank::$8 ← (byte*)(const struct RICOH_2C02*) PPU + (byte*~) vblank::$6 ← (byte*~) vblank::$8 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUSCROLL + *((byte*~) vblank::$6) ← (number) 0 + (struct SpriteData*) vblank::ppuSpriteBufferDmaTransfer1_spriteBuffer#0 ← (const struct SpriteData*) SPRITE_BUFFER + to:vblank::ppuSpriteBufferDmaTransfer1 +vblank::ppuSpriteBufferDmaTransfer1: scope:[vblank] from vblank + (struct SpriteData*) vblank::ppuSpriteBufferDmaTransfer1_spriteBuffer#1 ← phi( vblank/(struct SpriteData*) vblank::ppuSpriteBufferDmaTransfer1_spriteBuffer#0 ) + (byte*~) vblank::ppuSpriteBufferDmaTransfer1_$3 ← (byte*)(const struct RICOH_2C02*) PPU + (byte*~) vblank::ppuSpriteBufferDmaTransfer1_$1 ← (byte*~) vblank::ppuSpriteBufferDmaTransfer1_$3 + (const byte) OFFSET_STRUCT_RICOH_2C02_OAMADDR + *((byte*~) vblank::ppuSpriteBufferDmaTransfer1_$1) ← (number) 0 + (byte~) vblank::ppuSpriteBufferDmaTransfer1_$0 ← > (struct SpriteData*) vblank::ppuSpriteBufferDmaTransfer1_spriteBuffer#1 + (byte*~) vblank::ppuSpriteBufferDmaTransfer1_$4 ← (byte*)(const struct RICOH_2A03*) APU + (byte*~) vblank::ppuSpriteBufferDmaTransfer1_$2 ← (byte*~) vblank::ppuSpriteBufferDmaTransfer1_$4 + (const byte) OFFSET_STRUCT_RICOH_2A03_OAMDMA + *((byte*~) vblank::ppuSpriteBufferDmaTransfer1_$2) ← (byte~) vblank::ppuSpriteBufferDmaTransfer1_$0 + to:vblank::@3 +vblank::@3: scope:[vblank] from vblank::ppuSpriteBufferDmaTransfer1 + (byte) vblank::y_idx#0 ← (volatile byte) y_sin_idx + (volatile byte) y_sin_idx ← ++ (volatile byte) y_sin_idx + (byte) vblank::x_idx#0 ← (volatile byte) x_sin_idx + (volatile byte) x_sin_idx ← ++ (volatile byte) x_sin_idx + (byte) vblank::s#0 ← (byte) 0 + to:vblank::@1 +vblank::@1: scope:[vblank] from vblank::@2 vblank::@3 + (byte) vblank::x_idx#3 ← phi( vblank::@2/(byte) vblank::x_idx#1 vblank::@3/(byte) vblank::x_idx#0 ) + (byte) vblank::y_idx#3 ← phi( vblank::@2/(byte) vblank::y_idx#1 vblank::@3/(byte) vblank::y_idx#0 ) + (byte) vblank::s#2 ← phi( vblank::@2/(byte) vblank::s#1 vblank::@3/(byte) vblank::s#0 ) + (bool~) vblank::$1 ← (byte) vblank::s#2 < (number) $40 + if((bool~) vblank::$1) goto vblank::@2 + to:vblank::@return +vblank::@2: scope:[vblank] from vblank::@1 + (byte) vblank::x_idx#2 ← phi( vblank::@1/(byte) vblank::x_idx#3 ) + (byte) vblank::y_idx#2 ← phi( vblank::@1/(byte) vblank::y_idx#3 ) + (byte) vblank::s#3 ← phi( vblank::@1/(byte) vblank::s#2 ) + (byte~) vblank::$3 ← (byte) vblank::s#3 * (const byte) SIZEOF_STRUCT_SPRITEDATA + *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_Y + (byte~) vblank::$3) ← *((const to_nomodify byte*) SINTABLE + (byte) vblank::y_idx#2) + (number~) vblank::$2 ← *((const to_nomodify byte*) SINTABLE + (byte) vblank::x_idx#2) + (number) 8 + (byte~) vblank::$4 ← (byte) vblank::s#3 * (const byte) SIZEOF_STRUCT_SPRITEDATA + *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_X + (byte~) vblank::$4) ← (number~) vblank::$2 + (byte) vblank::y_idx#1 ← (byte) vblank::y_idx#2 + (number) 4 + (byte) vblank::x_idx#1 ← (byte) vblank::x_idx#2 - (number) 7 + (byte) vblank::s#1 ← ++ (byte) vblank::s#3 + to:vblank::@1 +vblank::@return: scope:[vblank] from vblank::@1 + return + to:@return +@2: scope:[] from @1 + call main + to:@3 +@3: scope:[] from @2 + to:@end +@end: scope:[] from @3 + +SYMBOL TABLE SSA +(label) @1 +(label) @2 +(label) @3 +(label) @begin +(label) @end +(const struct RICOH_2A03*) APU = (struct RICOH_2A03*)(number) $4000 +(const nomodify byte*) FR_COUNTER = (byte*)(number) $4017 +(const nomodify byte*) MEMORY = (byte*)(number) 0 +(const byte*) MESSAGE[(number) $40] = (byte*) "rex-of-camelot-presents-a-dxycp-on-nintendo-entertainment-system"z +(const byte) OFFSET_STRUCT_RICOH_2A03_DMC_FREQ = (byte) $10 +(const byte) OFFSET_STRUCT_RICOH_2A03_OAMDMA = (byte) $14 +(const byte) OFFSET_STRUCT_RICOH_2C02_OAMADDR = (byte) 3 +(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR = (byte) 6 +(const byte) OFFSET_STRUCT_RICOH_2C02_PPUCTRL = (byte) 0 +(const byte) OFFSET_STRUCT_RICOH_2C02_PPUDATA = (byte) 7 +(const byte) OFFSET_STRUCT_RICOH_2C02_PPUMASK = (byte) 1 +(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSCROLL = (byte) 5 +(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSTATUS = (byte) 2 +(const byte) OFFSET_STRUCT_SPRITEDATA_ATTRIBUTES = (byte) 2 +(const byte) OFFSET_STRUCT_SPRITEDATA_TILE = (byte) 1 +(const byte) OFFSET_STRUCT_SPRITEDATA_X = (byte) 3 +(const byte) OFFSET_STRUCT_SPRITEDATA_Y = (byte) 0 +(const byte*) PALETTE[(number) $20] = { (byte) 1, (byte) $21, (byte) $f, (byte) $30, (byte) 1, (byte) $21, (byte) $f, (byte) $30, (byte) 1, (byte) $21, (byte) $f, (byte) $30, (byte) 1, (byte) $21, (byte) $f, (byte) $30, (byte) 1, (byte) $f, (byte) $30, (byte) 8, (byte) 1, (byte) $f, (byte) $18, (byte) 8, (byte) 1, (byte) $30, (byte) $37, (byte) $1a, (byte) $f, (byte) $f, (byte) $f, (byte) $f } +(const struct RICOH_2C02*) PPU = (struct RICOH_2C02*)(number) $2000 +(const nomodify byte*) PPU_ATTRIBUTE_TABLE_0 = (byte*)(number) $23c0 +(const nomodify byte*) PPU_NAME_TABLE_0 = (byte*)(number) $2000 +(const nomodify byte*) PPU_PALETTE = (byte*)(number) $3f00 +(const nomodify to_volatile byte*) PPU_PPUSTATUS = (byte*)(number) $2002 +(byte) RICOH_2A03::DMC_FREQ +(byte) RICOH_2A03::DMC_LEN +(byte) RICOH_2A03::DMC_RAW +(byte) RICOH_2A03::DMC_START +(byte) RICOH_2A03::JOY1 +(byte) RICOH_2A03::JOY2 +(byte) RICOH_2A03::NOISE_HI +(byte) RICOH_2A03::NOISE_LO +(byte) RICOH_2A03::NOISE_VOL +(byte) RICOH_2A03::OAMDMA +(byte) RICOH_2A03::SND_CHN +(byte) RICOH_2A03::SQ1_HI +(byte) RICOH_2A03::SQ1_LO +(byte) RICOH_2A03::SQ1_SWEEP +(byte) RICOH_2A03::SQ1_VOL +(byte) RICOH_2A03::SQ2_HI +(byte) RICOH_2A03::SQ2_LO +(byte) RICOH_2A03::SQ2_SWEEP +(byte) RICOH_2A03::SQ2_VOL +(byte) RICOH_2A03::TRI_HI +(byte) RICOH_2A03::TRI_LINEAR +(byte) RICOH_2A03::TRI_LO +(byte) RICOH_2A03::UNUSED1 +(byte) RICOH_2A03::UNUSED2 +(byte) RICOH_2C02::OAMADDR +(byte) RICOH_2C02::OAMDATA +(byte) RICOH_2C02::PPUADDR +(byte) RICOH_2C02::PPUCTRL +(byte) RICOH_2C02::PPUDATA +(byte) RICOH_2C02::PPUMASK +(byte) RICOH_2C02::PPUSCROLL +(volatile byte) RICOH_2C02::PPUSTATUS loadstore +(const to_nomodify byte*) SINTABLE[(number) $100] = kickasm {{ .fill $100, round(115.5+107.5*sin(2*PI*i/256)) + }} +(const byte) SIZEOF_STRUCT_SPRITEDATA = (byte) 4 +(const struct SpriteData*) SPRITE_BUFFER[(number) $100] = { fill( $100, 0) } +(byte) SpriteData::attributes +(byte) SpriteData::tile +(byte) SpriteData::x +(byte) SpriteData::y +(const byte*) TILES[] = kickasm {{ .var filechargen = LoadBinary("characters.901225-01.bin") + .for(var c=0; c<256; c++) { + // Plane 0 + .fill 8, filechargen.get(c*8+i) + // Plane 1 + .fill 8, 0 + } + }} +(const to_nomodify void()**) VECTORS[] = { &interrupt(HARDWARE_STACK)(void()) vblank(), &(void()) main(), (void()*)(number) 0 } +(void()) main() +(byte~) main::$1 +(bool~) main::$6 +(byte~) main::$7 +(bool~) main::$8 +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@4 +(label) main::@5 +(label) main::@6 +(label) main::@7 +(label) main::@return +(label) main::enableVideoOutput1 +(byte*~) main::enableVideoOutput1_$0 +(byte*~) main::enableVideoOutput1_$1 +(byte*~) main::enableVideoOutput1_$2 +(byte*~) main::enableVideoOutput1_$3 +(label) main::initNES1 +(bool~) main::initNES1_$5 +(label) main::initNES1_@1 +(label) main::initNES1_@6 +(label) main::initNES1_@7 +(label) main::initNES1_clearVBlankFlag1 +(label) main::initNES1_disableAudioOutput1 +(byte*~) main::initNES1_disableAudioOutput1_$0 +(byte*~) main::initNES1_disableAudioOutput1_$1 +(label) main::initNES1_disableVideoOutput1 +(byte*~) main::initNES1_disableVideoOutput1_$0 +(byte*~) main::initNES1_disableVideoOutput1_$1 +(byte*~) main::initNES1_disableVideoOutput1_$2 +(byte*~) main::initNES1_disableVideoOutput1_$3 +(byte) main::initNES1_i +(byte) main::initNES1_i#0 +(byte) main::initNES1_i#1 +(byte) main::initNES1_i#2 +(label) main::initNES1_waitForVBlank1 +(number~) main::initNES1_waitForVBlank1_$0 +(bool~) main::initNES1_waitForVBlank1_$1 +(byte*~) main::initNES1_waitForVBlank1_$2 +(byte*~) main::initNES1_waitForVBlank1_$3 +(bool~) main::initNES1_waitForVBlank1_$4 +(label) main::initNES1_waitForVBlank1_@1 +(label) main::initNES1_waitForVBlank2 +(number~) main::initNES1_waitForVBlank2_$0 +(bool~) main::initNES1_waitForVBlank2_$1 +(byte*~) main::initNES1_waitForVBlank2_$2 +(byte*~) main::initNES1_waitForVBlank2_$3 +(bool~) main::initNES1_waitForVBlank2_$4 +(label) main::initNES1_waitForVBlank2_@1 +(byte) main::s +(byte) main::s#0 +(byte) main::s#1 +(byte) main::s#2 +(byte) main::s#3 +(void()) ppuDataFill((nomodify void*) ppuDataFill::ppuData , (byte) ppuDataFill::val , (word) ppuDataFill::size) +(bool~) ppuDataFill::$1 +(label) ppuDataFill::@1 +(label) ppuDataFill::@2 +(label) ppuDataFill::@3 +(label) ppuDataFill::@4 +(label) ppuDataFill::@return +(word) ppuDataFill::i +(word) ppuDataFill::i#0 +(word) ppuDataFill::i#1 +(word) ppuDataFill::i#2 +(word) ppuDataFill::i#3 +(word) ppuDataFill::i#4 +(word) ppuDataFill::i#5 +(nomodify void*) ppuDataFill::ppuData +(nomodify void*) ppuDataFill::ppuData#0 +(nomodify void*) ppuDataFill::ppuData#1 +(nomodify void*) ppuDataFill::ppuData#2 +(label) ppuDataFill::ppuDataPrepare1 +(byte~) ppuDataFill::ppuDataPrepare1_$0 +(byte~) ppuDataFill::ppuDataPrepare1_$1 +(byte*~) ppuDataFill::ppuDataPrepare1_$2 +(byte*~) ppuDataFill::ppuDataPrepare1_$3 +(byte*~) ppuDataFill::ppuDataPrepare1_$4 +(byte*~) ppuDataFill::ppuDataPrepare1_$5 +(nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData +(nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0 +(nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#1 +(label) ppuDataFill::ppuDataPut1 +(byte*~) ppuDataFill::ppuDataPut1_$0 +(byte*~) ppuDataFill::ppuDataPut1_$1 +(byte) ppuDataFill::ppuDataPut1_val +(byte) ppuDataFill::ppuDataPut1_val#0 +(byte) ppuDataFill::ppuDataPut1_val#1 +(word) ppuDataFill::size +(word) ppuDataFill::size#0 +(word) ppuDataFill::size#1 +(word) ppuDataFill::size#2 +(word) ppuDataFill::size#3 +(word) ppuDataFill::size#4 +(word) ppuDataFill::size#5 +(word) ppuDataFill::size#6 +(word) ppuDataFill::size#7 +(word) ppuDataFill::size#8 +(byte) ppuDataFill::val +(byte) ppuDataFill::val#0 +(byte) ppuDataFill::val#1 +(byte) ppuDataFill::val#2 +(byte) ppuDataFill::val#3 +(byte) ppuDataFill::val#4 +(byte) ppuDataFill::val#5 +(byte) ppuDataFill::val#6 +(byte) ppuDataFill::val#7 +(byte) ppuDataFill::val#8 +(void()) ppuDataTransfer((nomodify void*) ppuDataTransfer::ppuData , (nomodify void*) ppuDataTransfer::cpuData , (word) ppuDataTransfer::size) +(bool~) ppuDataTransfer::$1 +(label) ppuDataTransfer::@1 +(label) ppuDataTransfer::@2 +(label) ppuDataTransfer::@3 +(label) ppuDataTransfer::@4 +(label) ppuDataTransfer::@return +(nomodify void*) ppuDataTransfer::cpuData +(nomodify void*) ppuDataTransfer::cpuData#0 +(nomodify void*) ppuDataTransfer::cpuData#1 +(nomodify void*) ppuDataTransfer::cpuData#2 +(nomodify void*) ppuDataTransfer::cpuData#3 +(byte*) ppuDataTransfer::cpuSrc +(byte*) ppuDataTransfer::cpuSrc#0 +(byte*) ppuDataTransfer::cpuSrc#1 +(byte*) ppuDataTransfer::cpuSrc#2 +(byte*) ppuDataTransfer::cpuSrc#3 +(byte*) ppuDataTransfer::cpuSrc#4 +(byte*) ppuDataTransfer::cpuSrc#5 +(word) ppuDataTransfer::i +(word) ppuDataTransfer::i#0 +(word) ppuDataTransfer::i#1 +(word) ppuDataTransfer::i#2 +(word) ppuDataTransfer::i#3 +(word) ppuDataTransfer::i#4 +(word) ppuDataTransfer::i#5 +(nomodify void*) ppuDataTransfer::ppuData +(nomodify void*) ppuDataTransfer::ppuData#0 +(nomodify void*) ppuDataTransfer::ppuData#1 +(label) ppuDataTransfer::ppuDataPrepare1 +(byte~) ppuDataTransfer::ppuDataPrepare1_$0 +(byte~) ppuDataTransfer::ppuDataPrepare1_$1 +(byte*~) ppuDataTransfer::ppuDataPrepare1_$2 +(byte*~) ppuDataTransfer::ppuDataPrepare1_$3 +(byte*~) ppuDataTransfer::ppuDataPrepare1_$4 +(byte*~) ppuDataTransfer::ppuDataPrepare1_$5 +(nomodify void*) ppuDataTransfer::ppuDataPrepare1_ppuData +(nomodify void*) ppuDataTransfer::ppuDataPrepare1_ppuData#0 +(nomodify void*) ppuDataTransfer::ppuDataPrepare1_ppuData#1 +(label) ppuDataTransfer::ppuDataPut1 +(byte*~) ppuDataTransfer::ppuDataPut1_$0 +(byte*~) ppuDataTransfer::ppuDataPut1_$1 +(byte) ppuDataTransfer::ppuDataPut1_val +(byte) ppuDataTransfer::ppuDataPut1_val#0 +(byte) ppuDataTransfer::ppuDataPut1_val#1 +(word) ppuDataTransfer::size +(word) ppuDataTransfer::size#0 +(word) ppuDataTransfer::size#1 +(word) ppuDataTransfer::size#2 +(word) ppuDataTransfer::size#3 +(word) ppuDataTransfer::size#4 +(word) ppuDataTransfer::size#5 +(word) ppuDataTransfer::size#6 +(word) ppuDataTransfer::size#7 +interrupt(HARDWARE_STACK)(void()) vblank() +(bool~) vblank::$1 +(number~) vblank::$2 +(byte~) vblank::$3 +(byte~) vblank::$4 +(byte*~) vblank::$5 +(byte*~) vblank::$6 +(byte*~) vblank::$7 +(byte*~) vblank::$8 +(label) vblank::@1 +(label) vblank::@2 +(label) vblank::@3 +(label) vblank::@return +(label) vblank::ppuSpriteBufferDmaTransfer1 +(byte~) vblank::ppuSpriteBufferDmaTransfer1_$0 +(byte*~) vblank::ppuSpriteBufferDmaTransfer1_$1 +(byte*~) vblank::ppuSpriteBufferDmaTransfer1_$2 +(byte*~) vblank::ppuSpriteBufferDmaTransfer1_$3 +(byte*~) vblank::ppuSpriteBufferDmaTransfer1_$4 +(struct SpriteData*) vblank::ppuSpriteBufferDmaTransfer1_spriteBuffer +(struct SpriteData*) vblank::ppuSpriteBufferDmaTransfer1_spriteBuffer#0 +(struct SpriteData*) vblank::ppuSpriteBufferDmaTransfer1_spriteBuffer#1 +(byte) vblank::s +(byte) vblank::s#0 +(byte) vblank::s#1 +(byte) vblank::s#2 +(byte) vblank::s#3 +(byte) vblank::x_idx +(byte) vblank::x_idx#0 +(byte) vblank::x_idx#1 +(byte) vblank::x_idx#2 +(byte) vblank::x_idx#3 +(byte) vblank::y_idx +(byte) vblank::y_idx#0 +(byte) vblank::y_idx#1 +(byte) vblank::y_idx#2 +(byte) vblank::y_idx#3 +(volatile byte) x_sin_idx loadstore +(volatile byte) y_sin_idx loadstore + +Adding number conversion cast (unumber) 0 in *((byte*~) main::initNES1_disableVideoOutput1_$0) ← (number) 0 +Adding number conversion cast (unumber) 0 in *((byte*~) main::initNES1_disableVideoOutput1_$1) ← (number) 0 +Adding number conversion cast (unumber) $40 in *((const nomodify byte*) FR_COUNTER) ← (number) $40 +Adding number conversion cast (unumber) $40 in *((byte*~) main::initNES1_disableAudioOutput1_$0) ← (number) $40 +Adding number conversion cast (unumber) $80 in (number~) main::initNES1_waitForVBlank1_$0 ← *((byte*~) main::initNES1_waitForVBlank1_$2) & (number) $80 +Adding number conversion cast (unumber) main::initNES1_waitForVBlank1_$0 in (number~) main::initNES1_waitForVBlank1_$0 ← *((byte*~) main::initNES1_waitForVBlank1_$2) & (unumber)(number) $80 +Adding number conversion cast (unumber) 0 in (bool~) main::initNES1_waitForVBlank1_$4 ← (number) 0 != (unumber~) main::initNES1_waitForVBlank1_$0 +Adding number conversion cast (unumber) 0 in *((const nomodify byte*) MEMORY+(number) 0 + (byte) main::initNES1_i#2) ← (number) 0 +Adding number conversion cast (unumber) 0 in *((const nomodify byte*) MEMORY+(number) 0 + (byte) main::initNES1_i#2) ← ((unumber)) (number) 0 +Adding number conversion cast (unumber) 0 in *((const nomodify byte*) MEMORY+(number) $100 + (byte) main::initNES1_i#2) ← (number) 0 +Adding number conversion cast (unumber) $100 in *((const nomodify byte*) MEMORY+(number) $100 + (byte) main::initNES1_i#2) ← ((unumber)) (number) 0 +Adding number conversion cast (unumber) 0 in *((const nomodify byte*) MEMORY+(number) $200 + (byte) main::initNES1_i#2) ← (number) 0 +Adding number conversion cast (unumber) $200 in *((const nomodify byte*) MEMORY+(number) $200 + (byte) main::initNES1_i#2) ← ((unumber)) (number) 0 +Adding number conversion cast (unumber) 0 in *((const nomodify byte*) MEMORY+(number) $300 + (byte) main::initNES1_i#2) ← (number) 0 +Adding number conversion cast (unumber) $300 in *((const nomodify byte*) MEMORY+(number) $300 + (byte) main::initNES1_i#2) ← ((unumber)) (number) 0 +Adding number conversion cast (unumber) 0 in *((const nomodify byte*) MEMORY+(number) $400 + (byte) main::initNES1_i#2) ← (number) 0 +Adding number conversion cast (unumber) $400 in *((const nomodify byte*) MEMORY+(number) $400 + (byte) main::initNES1_i#2) ← ((unumber)) (number) 0 +Adding number conversion cast (unumber) 0 in *((const nomodify byte*) MEMORY+(number) $500 + (byte) main::initNES1_i#2) ← (number) 0 +Adding number conversion cast (unumber) $500 in *((const nomodify byte*) MEMORY+(number) $500 + (byte) main::initNES1_i#2) ← ((unumber)) (number) 0 +Adding number conversion cast (unumber) 0 in *((const nomodify byte*) MEMORY+(number) $600 + (byte) main::initNES1_i#2) ← (number) 0 +Adding number conversion cast (unumber) $600 in *((const nomodify byte*) MEMORY+(number) $600 + (byte) main::initNES1_i#2) ← ((unumber)) (number) 0 +Adding number conversion cast (unumber) 0 in *((const nomodify byte*) MEMORY+(number) $700 + (byte) main::initNES1_i#2) ← (number) 0 +Adding number conversion cast (unumber) $700 in *((const nomodify byte*) MEMORY+(number) $700 + (byte) main::initNES1_i#2) ← ((unumber)) (number) 0 +Adding number conversion cast (unumber) 0 in (bool~) main::initNES1_$5 ← (number) 0 != (byte) main::initNES1_i#1 +Adding number conversion cast (unumber) $80 in (number~) main::initNES1_waitForVBlank2_$0 ← *((byte*~) main::initNES1_waitForVBlank2_$2) & (number) $80 +Adding number conversion cast (unumber) main::initNES1_waitForVBlank2_$0 in (number~) main::initNES1_waitForVBlank2_$0 ← *((byte*~) main::initNES1_waitForVBlank2_$2) & (unumber)(number) $80 +Adding number conversion cast (unumber) 0 in (bool~) main::initNES1_waitForVBlank2_$4 ← (number) 0 != (unumber~) main::initNES1_waitForVBlank2_$0 +Adding number conversion cast (unumber) $20*$1e in (word) ppuDataFill::size#0 ← (number) $20*(number) $1e +Adding number conversion cast (unumber) 0 in (byte) ppuDataFill::val#1 ← (number) 0 +Adding number conversion cast (unumber) $40 in (word) ppuDataFill::size#1 ← (number) $40 +Adding number conversion cast (unumber) $40 in (bool~) main::$6 ← (byte) main::s#2 < (number) $40 +Adding number conversion cast (unumber) $80 in *((byte*~) main::enableVideoOutput1_$0) ← (number) $80 +Adding number conversion cast (unumber) $1e in *((byte*~) main::enableVideoOutput1_$1) ← (number) $1e +Adding number conversion cast (unumber) 0 in *((byte*~) vblank::$5) ← (number) 0 +Adding number conversion cast (unumber) 0 in *((byte*~) vblank::$6) ← (number) 0 +Adding number conversion cast (unumber) 0 in *((byte*~) vblank::ppuSpriteBufferDmaTransfer1_$1) ← (number) 0 +Adding number conversion cast (unumber) $40 in (bool~) vblank::$1 ← (byte) vblank::s#2 < (number) $40 +Adding number conversion cast (unumber) 8 in (number~) vblank::$2 ← *((const to_nomodify byte*) SINTABLE + (byte) vblank::x_idx#2) + (number) 8 +Adding number conversion cast (unumber) vblank::$2 in (number~) vblank::$2 ← *((const to_nomodify byte*) SINTABLE + (byte) vblank::x_idx#2) + (unumber)(number) 8 +Adding number conversion cast (unumber) 4 in (byte) vblank::y_idx#1 ← (byte) vblank::y_idx#2 + (number) 4 +Adding number conversion cast (unumber) 7 in (byte) vblank::x_idx#1 ← (byte) vblank::x_idx#2 - (number) 7 +Successful SSA optimization PassNAddNumberTypeConversions +Inlining cast *((byte*~) main::initNES1_disableVideoOutput1_$0) ← (unumber)(number) 0 +Inlining cast *((byte*~) main::initNES1_disableVideoOutput1_$1) ← (unumber)(number) 0 +Inlining cast *((const nomodify byte*) FR_COUNTER) ← (unumber)(number) $40 +Inlining cast *((byte*~) main::initNES1_disableAudioOutput1_$0) ← (unumber)(number) $40 +Inlining cast *((const nomodify byte*) MEMORY+(unumber)(number) 0 + (byte) main::initNES1_i#2) ← (unumber)(number) 0 +Inlining cast *((const nomodify byte*) MEMORY+(unumber)(number) $100 + (byte) main::initNES1_i#2) ← (unumber)(number) 0 +Inlining cast *((const nomodify byte*) MEMORY+(unumber)(number) $200 + (byte) main::initNES1_i#2) ← (unumber)(number) 0 +Inlining cast *((const nomodify byte*) MEMORY+(unumber)(number) $300 + (byte) main::initNES1_i#2) ← (unumber)(number) 0 +Inlining cast *((const nomodify byte*) MEMORY+(unumber)(number) $400 + (byte) main::initNES1_i#2) ← (unumber)(number) 0 +Inlining cast *((const nomodify byte*) MEMORY+(unumber)(number) $500 + (byte) main::initNES1_i#2) ← (unumber)(number) 0 +Inlining cast *((const nomodify byte*) MEMORY+(unumber)(number) $600 + (byte) main::initNES1_i#2) ← (unumber)(number) 0 +Inlining cast *((const nomodify byte*) MEMORY+(unumber)(number) $700 + (byte) main::initNES1_i#2) ← (unumber)(number) 0 +Inlining cast (word) ppuDataFill::size#0 ← (unumber)(number) $20*(number) $1e +Inlining cast (byte) ppuDataFill::val#1 ← (unumber)(number) 0 +Inlining cast (word) ppuDataFill::size#1 ← (unumber)(number) $40 +Inlining cast *((byte*~) main::enableVideoOutput1_$0) ← (unumber)(number) $80 +Inlining cast *((byte*~) main::enableVideoOutput1_$1) ← (unumber)(number) $1e +Inlining cast *((byte*~) vblank::$5) ← (unumber)(number) 0 +Inlining cast *((byte*~) vblank::$6) ← (unumber)(number) 0 +Inlining cast *((byte*~) vblank::ppuSpriteBufferDmaTransfer1_$1) ← (unumber)(number) 0 +Successful SSA optimization Pass2InlineCast +Simplifying constant pointer cast (byte*) 8192 +Simplifying constant pointer cast (byte*) 9152 +Simplifying constant pointer cast (byte*) 16128 +Simplifying constant pointer cast (byte*) 8194 +Simplifying constant pointer cast (byte*) 16407 +Simplifying constant pointer cast (byte*) 0 +Simplifying constant pointer cast (void()*) 0 +Simplifying constant pointer cast (struct RICOH_2C02*) 8192 +Simplifying constant pointer cast (struct RICOH_2A03*) 16384 +Simplifying constant integer cast 0 +Simplifying constant integer cast 0 +Simplifying constant integer cast $40 +Simplifying constant integer cast $40 +Simplifying constant integer cast $80 +Simplifying constant integer cast 0 +Simplifying constant integer cast 0 +Simplifying constant integer cast 0 +Simplifying constant integer cast 0 +Simplifying constant integer cast $100 +Simplifying constant integer cast 0 +Simplifying constant integer cast $200 +Simplifying constant integer cast 0 +Simplifying constant integer cast $300 +Simplifying constant integer cast 0 +Simplifying constant integer cast $400 +Simplifying constant integer cast 0 +Simplifying constant integer cast $500 +Simplifying constant integer cast 0 +Simplifying constant integer cast $600 +Simplifying constant integer cast 0 +Simplifying constant integer cast $700 +Simplifying constant integer cast 0 +Simplifying constant integer cast $80 +Simplifying constant integer cast 0 +Simplifying constant integer cast 0 +Simplifying constant integer cast $40 +Simplifying constant integer cast $40 +Simplifying constant integer cast $80 +Simplifying constant integer cast $1e +Simplifying constant integer cast 0 +Simplifying constant integer cast 0 +Simplifying constant integer cast 0 +Simplifying constant integer cast $40 +Simplifying constant integer cast 8 +Simplifying constant integer cast 4 +Simplifying constant integer cast 7 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) $40 +Finalized unsigned number type (byte) $40 +Finalized unsigned number type (byte) $80 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (word) $100 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (word) $200 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (word) $300 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (word) $400 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (word) $500 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (word) $600 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (word) $700 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) $80 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) $40 +Finalized unsigned number type (byte) $40 +Finalized unsigned number type (byte) $80 +Finalized unsigned number type (byte) $1e +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) $40 +Finalized unsigned number type (byte) 8 +Finalized unsigned number type (byte) 4 +Finalized unsigned number type (byte) 7 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Inferred type updated to byte in (unumber~) main::initNES1_waitForVBlank1_$0 ← *((byte*~) main::initNES1_waitForVBlank1_$2) & (byte) $80 +Inferred type updated to byte in (unumber~) main::initNES1_waitForVBlank2_$0 ← *((byte*~) main::initNES1_waitForVBlank2_$2) & (byte) $80 +Inferred type updated to byte in (unumber~) vblank::$2 ← *((const to_nomodify byte*) SINTABLE + (byte) vblank::x_idx#2) + (byte) 8 +Inversing boolean not [68] (bool~) main::initNES1_waitForVBlank1_$1 ← (byte) 0 == (byte~) main::initNES1_waitForVBlank1_$0 from [67] (bool~) main::initNES1_waitForVBlank1_$4 ← (byte) 0 != (byte~) main::initNES1_waitForVBlank1_$0 +Inversing boolean not [87] (bool~) main::initNES1_waitForVBlank2_$1 ← (byte) 0 == (byte~) main::initNES1_waitForVBlank2_$0 from [86] (bool~) main::initNES1_waitForVBlank2_$4 ← (byte) 0 != (byte~) main::initNES1_waitForVBlank2_$0 +Successful SSA optimization Pass2UnaryNotSimplification +Alias ppuDataFill::ppuDataPrepare1_ppuData#0 = ppuDataFill::ppuData#2 ppuDataFill::ppuDataPrepare1_ppuData#1 +Alias ppuDataFill::size#3 = ppuDataFill::size#5 ppuDataFill::size#7 +Alias ppuDataFill::val#4 = ppuDataFill::val#6 ppuDataFill::val#8 +Alias ppuDataFill::val#2 = ppuDataFill::val#3 ppuDataFill::ppuDataPut1_val#0 ppuDataFill::ppuDataPut1_val#1 ppuDataFill::val#7 ppuDataFill::val#5 +Alias ppuDataFill::i#2 = ppuDataFill::i#5 ppuDataFill::i#4 ppuDataFill::i#3 +Alias ppuDataFill::size#2 = ppuDataFill::size#8 ppuDataFill::size#6 ppuDataFill::size#4 +Alias ppuDataTransfer::ppuDataPrepare1_ppuData#0 = ppuDataTransfer::ppuData#1 ppuDataTransfer::ppuDataPrepare1_ppuData#1 +Alias ppuDataTransfer::cpuData#1 = ppuDataTransfer::cpuData#2 ppuDataTransfer::cpuData#3 +Alias ppuDataTransfer::size#2 = ppuDataTransfer::size#4 ppuDataTransfer::size#6 +Alias ppuDataTransfer::cpuSrc#2 = ppuDataTransfer::cpuSrc#4 ppuDataTransfer::cpuSrc#5 ppuDataTransfer::cpuSrc#3 +Alias ppuDataTransfer::i#2 = ppuDataTransfer::i#5 ppuDataTransfer::i#4 ppuDataTransfer::i#3 +Alias ppuDataTransfer::size#1 = ppuDataTransfer::size#7 ppuDataTransfer::size#5 ppuDataTransfer::size#3 +Alias ppuDataTransfer::ppuDataPut1_val#0 = ppuDataTransfer::ppuDataPut1_val#1 +Alias ppuDataTransfer::size#0 = main::$1 +Alias main::s#2 = main::s#3 +Alias vblank::ppuSpriteBufferDmaTransfer1_spriteBuffer#0 = vblank::ppuSpriteBufferDmaTransfer1_spriteBuffer#1 +Alias vblank::s#2 = vblank::s#3 +Alias vblank::y_idx#2 = vblank::y_idx#3 +Alias vblank::x_idx#2 = vblank::x_idx#3 +Successful SSA optimization Pass2AliasElimination +Identical Phi Values (word) ppuDataFill::size#2 (word) ppuDataFill::size#3 +Identical Phi Values (byte) ppuDataFill::val#2 (byte) ppuDataFill::val#4 +Identical Phi Values (nomodify void*) ppuDataTransfer::ppuDataPrepare1_ppuData#0 (nomodify void*) ppuDataTransfer::ppuData#0 +Identical Phi Values (nomodify void*) ppuDataTransfer::cpuData#1 (nomodify void*) ppuDataTransfer::cpuData#0 +Identical Phi Values (word) ppuDataTransfer::size#2 (word) ppuDataTransfer::size#0 +Identical Phi Values (word) ppuDataTransfer::size#1 (word) ppuDataTransfer::size#2 +Successful SSA optimization Pass2IdenticalPhiElimination +Identified duplicate assignment right side [152] (byte~) vblank::$4 ← (byte) vblank::s#2 * (const byte) SIZEOF_STRUCT_SPRITEDATA +Successful SSA optimization Pass2DuplicateRValueIdentification +Simple Condition (bool~) ppuDataFill::$1 [12] if((word) ppuDataFill::i#2<(word) ppuDataFill::size#3) goto ppuDataFill::@2 +Simple Condition (bool~) ppuDataTransfer::$1 [31] if((word) ppuDataTransfer::i#2<(word) ppuDataTransfer::size#0) goto ppuDataTransfer::@2 +Simple Condition (bool~) main::initNES1_waitForVBlank1_$1 [55] if((byte) 0==(byte~) main::initNES1_waitForVBlank1_$0) goto main::initNES1_waitForVBlank1_@1 +Simple Condition (bool~) main::initNES1_$5 [68] if((byte) 0!=(byte) main::initNES1_i#1) goto main::initNES1_@1 +Simple Condition (bool~) main::initNES1_waitForVBlank2_$1 [73] if((byte) 0==(byte~) main::initNES1_waitForVBlank2_$0) goto main::initNES1_waitForVBlank2_@1 +Simple Condition (bool~) main::$6 [90] if((byte) main::s#2<(byte) $40) goto main::@2 +Simple Condition (bool~) main::$8 [104] if((number) 0!=(number) 1) goto main::@3 +Simple Condition (bool~) vblank::$1 [129] if((byte) vblank::s#2<(byte) $40) goto vblank::@2 +Successful SSA optimization Pass2ConditionalJumpSimplification +Constant right-side identified [2] (byte*~) ppuDataFill::ppuDataPrepare1_$4 ← (byte*)(const struct RICOH_2C02*) PPU +Constant right-side identified [6] (byte*~) ppuDataFill::ppuDataPrepare1_$5 ← (byte*)(const struct RICOH_2C02*) PPU +Constant right-side identified [13] (byte*~) ppuDataFill::ppuDataPut1_$1 ← (byte*)(const struct RICOH_2C02*) PPU +Constant right-side identified [20] (byte*~) ppuDataTransfer::ppuDataPrepare1_$4 ← (byte*)(const struct RICOH_2C02*) PPU +Constant right-side identified [24] (byte*~) ppuDataTransfer::ppuDataPrepare1_$5 ← (byte*)(const struct RICOH_2C02*) PPU +Constant right-side identified [33] (byte*~) ppuDataTransfer::ppuDataPut1_$1 ← (byte*)(const struct RICOH_2C02*) PPU +Constant right-side identified [40] (byte*~) main::initNES1_disableVideoOutput1_$2 ← (byte*)(const struct RICOH_2C02*) PPU +Constant right-side identified [43] (byte*~) main::initNES1_disableVideoOutput1_$3 ← (byte*)(const struct RICOH_2C02*) PPU +Constant right-side identified [47] (byte*~) main::initNES1_disableAudioOutput1_$1 ← (byte*)(const struct RICOH_2A03*) APU +Constant right-side identified [51] (byte*~) main::initNES1_waitForVBlank1_$3 ← (byte*)(const struct RICOH_2C02*) PPU +Constant right-side identified [69] (byte*~) main::initNES1_waitForVBlank2_$3 ← (byte*)(const struct RICOH_2C02*) PPU +Constant right-side identified [75] (word) ppuDataTransfer::size#0 ← sizeof (const byte*) PALETTE +Constant right-side identified [81] (word) ppuDataFill::size#0 ← (unumber)(number) $20*(number) $1e +Constant right-side identified [97] (byte*~) main::enableVideoOutput1_$2 ← (byte*)(const struct RICOH_2C02*) PPU +Constant right-side identified [100] (byte*~) main::enableVideoOutput1_$3 ← (byte*)(const struct RICOH_2C02*) PPU +Constant right-side identified [108] (byte*~) vblank::$7 ← (byte*)(const struct RICOH_2C02*) PPU +Constant right-side identified [111] (byte*~) vblank::$8 ← (byte*)(const struct RICOH_2C02*) PPU +Constant right-side identified [115] (byte*~) vblank::ppuSpriteBufferDmaTransfer1_$3 ← (byte*)(const struct RICOH_2C02*) PPU +Constant right-side identified [119] (byte*~) vblank::ppuSpriteBufferDmaTransfer1_$4 ← (byte*)(const struct RICOH_2A03*) APU +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte*) ppuDataFill::ppuDataPrepare1_$4 = (byte*)PPU +Constant (const byte*) ppuDataFill::ppuDataPrepare1_$5 = (byte*)PPU +Constant (const word) ppuDataFill::i#0 = 0 +Constant (const byte*) ppuDataFill::ppuDataPut1_$1 = (byte*)PPU +Constant (const byte*) ppuDataTransfer::ppuDataPrepare1_$4 = (byte*)PPU +Constant (const byte*) ppuDataTransfer::ppuDataPrepare1_$5 = (byte*)PPU +Constant (const word) ppuDataTransfer::i#0 = 0 +Constant (const byte*) ppuDataTransfer::ppuDataPut1_$1 = (byte*)PPU +Constant (const byte*) main::initNES1_disableVideoOutput1_$2 = (byte*)PPU +Constant (const byte*) main::initNES1_disableVideoOutput1_$3 = (byte*)PPU +Constant (const byte*) main::initNES1_disableAudioOutput1_$1 = (byte*)APU +Constant (const byte*) main::initNES1_waitForVBlank1_$3 = (byte*)PPU +Constant (const byte) main::initNES1_i#0 = 0 +Constant (const byte*) main::initNES1_waitForVBlank2_$3 = (byte*)PPU +Constant (const word) ppuDataTransfer::size#0 = sizeof PALETTE +Constant (const nomodify void*) ppuDataTransfer::ppuData#0 = (void*)PPU_PALETTE +Constant (const nomodify void*) ppuDataTransfer::cpuData#0 = (void*)PALETTE +Constant (const nomodify void*) ppuDataFill::ppuData#0 = (void*)PPU_NAME_TABLE_0 +Constant (const byte) ppuDataFill::val#0 = '*' +Constant (const word) ppuDataFill::size#0 = (unumber)$20*$1e +Constant (const nomodify void*) ppuDataFill::ppuData#1 = (void*)PPU_ATTRIBUTE_TABLE_0 +Constant (const byte) ppuDataFill::val#1 = 0 +Constant (const word) ppuDataFill::size#1 = $40 +Constant (const byte) main::s#0 = 0 +Constant (const byte*) main::enableVideoOutput1_$2 = (byte*)PPU +Constant (const byte*) main::enableVideoOutput1_$3 = (byte*)PPU +Constant (const byte*) vblank::$7 = (byte*)PPU +Constant (const byte*) vblank::$8 = (byte*)PPU +Constant (const struct SpriteData*) vblank::ppuSpriteBufferDmaTransfer1_spriteBuffer#0 = SPRITE_BUFFER +Constant (const byte*) vblank::ppuSpriteBufferDmaTransfer1_$3 = (byte*)PPU +Constant (const byte*) vblank::ppuSpriteBufferDmaTransfer1_$4 = (byte*)APU +Constant (const byte) vblank::s#0 = 0 +Successful SSA optimization Pass2ConstantIdentification +Constant (const byte*) ppuDataTransfer::cpuSrc#0 = (byte*)ppuDataTransfer::cpuData#0 +Successful SSA optimization Pass2ConstantIdentification +if() condition always true - replacing block destination [104] if((number) 0!=(number) 1) goto main::@3 +Successful SSA optimization Pass2ConstantIfs +Converting *(pointer+n) to pointer[n] [4] *((byte*~) ppuDataFill::ppuDataPrepare1_$2) ← (byte~) ppuDataFill::ppuDataPrepare1_$0 -- *(ppuDataFill::ppuDataPrepare1_$4 + OFFSET_STRUCT_RICOH_2C02_PPUADDR) +Converting *(pointer+n) to pointer[n] [8] *((byte*~) ppuDataFill::ppuDataPrepare1_$3) ← (byte~) ppuDataFill::ppuDataPrepare1_$1 -- *(ppuDataFill::ppuDataPrepare1_$5 + OFFSET_STRUCT_RICOH_2C02_PPUADDR) +Converting *(pointer+n) to pointer[n] [15] *((byte*~) ppuDataFill::ppuDataPut1_$0) ← (byte) ppuDataFill::val#4 -- *(ppuDataFill::ppuDataPut1_$1 + OFFSET_STRUCT_RICOH_2C02_PPUDATA) +Converting *(pointer+n) to pointer[n] [22] *((byte*~) ppuDataTransfer::ppuDataPrepare1_$2) ← (byte~) ppuDataTransfer::ppuDataPrepare1_$0 -- *(ppuDataTransfer::ppuDataPrepare1_$4 + OFFSET_STRUCT_RICOH_2C02_PPUADDR) +Converting *(pointer+n) to pointer[n] [26] *((byte*~) ppuDataTransfer::ppuDataPrepare1_$3) ← (byte~) ppuDataTransfer::ppuDataPrepare1_$1 -- *(ppuDataTransfer::ppuDataPrepare1_$5 + OFFSET_STRUCT_RICOH_2C02_PPUADDR) +Converting *(pointer+n) to pointer[n] [35] *((byte*~) ppuDataTransfer::ppuDataPut1_$0) ← (byte) ppuDataTransfer::ppuDataPut1_val#0 -- *(ppuDataTransfer::ppuDataPut1_$1 + OFFSET_STRUCT_RICOH_2C02_PPUDATA) +Converting *(pointer+n) to pointer[n] [42] *((byte*~) main::initNES1_disableVideoOutput1_$0) ← (byte) 0 -- *(main::initNES1_disableVideoOutput1_$2 + OFFSET_STRUCT_RICOH_2C02_PPUCTRL) +Converting *(pointer+n) to pointer[n] [45] *((byte*~) main::initNES1_disableVideoOutput1_$1) ← (byte) 0 -- *(main::initNES1_disableVideoOutput1_$3 + OFFSET_STRUCT_RICOH_2C02_PPUMASK) +Converting *(pointer+n) to pointer[n] [49] *((byte*~) main::initNES1_disableAudioOutput1_$0) ← (byte) $40 -- *(main::initNES1_disableAudioOutput1_$1 + OFFSET_STRUCT_RICOH_2A03_DMC_FREQ) +Converting *(pointer+n) to pointer[n] [53] (byte~) main::initNES1_waitForVBlank1_$0 ← *((byte*~) main::initNES1_waitForVBlank1_$2) & (byte) $80 -- *(main::initNES1_waitForVBlank1_$3 + OFFSET_STRUCT_RICOH_2C02_PPUSTATUS) +Converting *(pointer+n) to pointer[n] [71] (byte~) main::initNES1_waitForVBlank2_$0 ← *((byte*~) main::initNES1_waitForVBlank2_$2) & (byte) $80 -- *(main::initNES1_waitForVBlank2_$3 + OFFSET_STRUCT_RICOH_2C02_PPUSTATUS) +Converting *(pointer+n) to pointer[n] [99] *((byte*~) main::enableVideoOutput1_$0) ← (byte) $80 -- *(main::enableVideoOutput1_$2 + OFFSET_STRUCT_RICOH_2C02_PPUCTRL) +Converting *(pointer+n) to pointer[n] [102] *((byte*~) main::enableVideoOutput1_$1) ← (byte) $1e -- *(main::enableVideoOutput1_$3 + OFFSET_STRUCT_RICOH_2C02_PPUMASK) +Converting *(pointer+n) to pointer[n] [110] *((byte*~) vblank::$5) ← (byte) 0 -- *(vblank::$7 + OFFSET_STRUCT_RICOH_2C02_PPUSCROLL) +Converting *(pointer+n) to pointer[n] [113] *((byte*~) vblank::$6) ← (byte) 0 -- *(vblank::$8 + OFFSET_STRUCT_RICOH_2C02_PPUSCROLL) +Converting *(pointer+n) to pointer[n] [117] *((byte*~) vblank::ppuSpriteBufferDmaTransfer1_$1) ← (byte) 0 -- *(vblank::ppuSpriteBufferDmaTransfer1_$3 + OFFSET_STRUCT_RICOH_2C02_OAMADDR) +Converting *(pointer+n) to pointer[n] [121] *((byte*~) vblank::ppuSpriteBufferDmaTransfer1_$2) ← (byte~) vblank::ppuSpriteBufferDmaTransfer1_$0 -- *(vblank::ppuSpriteBufferDmaTransfer1_$4 + OFFSET_STRUCT_RICOH_2A03_OAMDMA) +Successful SSA optimization Pass2InlineDerefIdx +Simplifying expression containing zero main::initNES1_disableVideoOutput1_$2 in [41] (byte*~) main::initNES1_disableVideoOutput1_$0 ← (const byte*) main::initNES1_disableVideoOutput1_$2 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUCTRL +Simplifying expression containing zero main::initNES1_disableVideoOutput1_$2 in [42] *((const byte*) main::initNES1_disableVideoOutput1_$2 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUCTRL) ← (byte) 0 +Simplifying expression containing zero MEMORY in [58] *((const nomodify byte*) MEMORY+(byte) 0 + (byte) main::initNES1_i#2) ← (byte) 0 +Simplifying expression containing zero (byte*)SPRITE_BUFFER in [92] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_Y + (byte~) main::$7) ← (byte) 0 +Simplifying expression containing zero main::enableVideoOutput1_$2 in [98] (byte*~) main::enableVideoOutput1_$0 ← (const byte*) main::enableVideoOutput1_$2 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUCTRL +Simplifying expression containing zero main::enableVideoOutput1_$2 in [99] *((const byte*) main::enableVideoOutput1_$2 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUCTRL) ← (byte) $80 +Simplifying expression containing zero (byte*)SPRITE_BUFFER in [131] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_Y + (byte~) vblank::$3) ← *((const to_nomodify byte*) SINTABLE + (byte) vblank::y_idx#2) +Successful SSA optimization PassNSimplifyExpressionWithZero +Eliminating unused variable (byte*~) ppuDataFill::ppuDataPrepare1_$2 and assignment [2] (byte*~) ppuDataFill::ppuDataPrepare1_$2 ← (const byte*) ppuDataFill::ppuDataPrepare1_$4 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR +Eliminating unused variable (byte*~) ppuDataFill::ppuDataPrepare1_$3 and assignment [5] (byte*~) ppuDataFill::ppuDataPrepare1_$3 ← (const byte*) ppuDataFill::ppuDataPrepare1_$5 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR +Eliminating unused variable (byte*~) ppuDataFill::ppuDataPut1_$0 and assignment [9] (byte*~) ppuDataFill::ppuDataPut1_$0 ← (const byte*) ppuDataFill::ppuDataPut1_$1 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUDATA +Eliminating unused variable (byte*~) ppuDataTransfer::ppuDataPrepare1_$2 and assignment [14] (byte*~) ppuDataTransfer::ppuDataPrepare1_$2 ← (const byte*) ppuDataTransfer::ppuDataPrepare1_$4 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR +Eliminating unused variable (byte*~) ppuDataTransfer::ppuDataPrepare1_$3 and assignment [17] (byte*~) ppuDataTransfer::ppuDataPrepare1_$3 ← (const byte*) ppuDataTransfer::ppuDataPrepare1_$5 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR +Eliminating unused variable (byte*~) ppuDataTransfer::ppuDataPut1_$0 and assignment [22] (byte*~) ppuDataTransfer::ppuDataPut1_$0 ← (const byte*) ppuDataTransfer::ppuDataPut1_$1 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUDATA +Eliminating unused variable (byte*~) main::initNES1_disableVideoOutput1_$0 and assignment [28] (byte*~) main::initNES1_disableVideoOutput1_$0 ← (const byte*) main::initNES1_disableVideoOutput1_$2 +Eliminating unused variable (byte*~) main::initNES1_disableVideoOutput1_$1 and assignment [30] (byte*~) main::initNES1_disableVideoOutput1_$1 ← (const byte*) main::initNES1_disableVideoOutput1_$3 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUMASK +Eliminating unused variable (byte*~) main::initNES1_disableAudioOutput1_$0 and assignment [33] (byte*~) main::initNES1_disableAudioOutput1_$0 ← (const byte*) main::initNES1_disableAudioOutput1_$1 + (const byte) OFFSET_STRUCT_RICOH_2A03_DMC_FREQ +Eliminating unused variable (byte*~) main::initNES1_waitForVBlank1_$2 and assignment [36] (byte*~) main::initNES1_waitForVBlank1_$2 ← (const byte*) main::initNES1_waitForVBlank1_$3 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUSTATUS +Eliminating unused variable (byte*~) main::initNES1_waitForVBlank2_$2 and assignment [50] (byte*~) main::initNES1_waitForVBlank2_$2 ← (const byte*) main::initNES1_waitForVBlank2_$3 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUSTATUS +Eliminating unused variable (byte*~) main::enableVideoOutput1_$0 and assignment [65] (byte*~) main::enableVideoOutput1_$0 ← (const byte*) main::enableVideoOutput1_$2 +Eliminating unused variable (byte*~) main::enableVideoOutput1_$1 and assignment [67] (byte*~) main::enableVideoOutput1_$1 ← (const byte*) main::enableVideoOutput1_$3 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUMASK +Eliminating unused variable (byte*~) vblank::$5 and assignment [72] (byte*~) vblank::$5 ← (const byte*) vblank::$7 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUSCROLL +Eliminating unused variable (byte*~) vblank::$6 and assignment [74] (byte*~) vblank::$6 ← (const byte*) vblank::$8 + (const byte) OFFSET_STRUCT_RICOH_2C02_PPUSCROLL +Eliminating unused variable (byte*~) vblank::ppuSpriteBufferDmaTransfer1_$1 and assignment [76] (byte*~) vblank::ppuSpriteBufferDmaTransfer1_$1 ← (const byte*) vblank::ppuSpriteBufferDmaTransfer1_$3 + (const byte) OFFSET_STRUCT_RICOH_2C02_OAMADDR +Eliminating unused variable (byte*~) vblank::ppuSpriteBufferDmaTransfer1_$2 and assignment [79] (byte*~) vblank::ppuSpriteBufferDmaTransfer1_$2 ← (const byte*) vblank::ppuSpriteBufferDmaTransfer1_$4 + (const byte) OFFSET_STRUCT_RICOH_2A03_OAMDMA +Eliminating unused constant (const byte) OFFSET_STRUCT_SPRITEDATA_Y +Eliminating unused constant (const byte) OFFSET_STRUCT_RICOH_2C02_PPUCTRL +Successful SSA optimization PassNEliminateUnusedVars +Removing unused block main::@return +Successful SSA optimization Pass2EliminateUnusedBlocks +Resolving array sizeof() sizeof (const byte*) PALETTE +Successful SSA optimization PassNSizeOfSimplification +Alias vblank::$4 = vblank::$3 +Successful SSA optimization Pass2AliasElimination +Constant right-side identified [10] (byte~) ppuDataTransfer::ppuDataPrepare1_$0 ← > (const nomodify void*) ppuDataTransfer::ppuData#0 +Constant right-side identified [12] (byte~) ppuDataTransfer::ppuDataPrepare1_$1 ← < (const nomodify void*) ppuDataTransfer::ppuData#0 +Constant right-side identified [61] (byte~) vblank::ppuSpriteBufferDmaTransfer1_$0 ← > (const struct SpriteData*) vblank::ppuSpriteBufferDmaTransfer1_spriteBuffer#0 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) ppuDataTransfer::ppuDataPrepare1_$0 = >ppuDataTransfer::ppuData#0 +Constant (const byte) ppuDataTransfer::ppuDataPrepare1_$1 = vblank::ppuSpriteBufferDmaTransfer1_spriteBuffer#0 +Successful SSA optimization Pass2ConstantIdentification +Simplifying constant evaluating to zero <(const nomodify void*) ppuDataTransfer::ppuData#0 in +Successful SSA optimization PassNSimplifyConstantZero +Adding number conversion cast (unumber) $20 in +Successful SSA optimization PassNAddNumberTypeConversions +Simplifying constant integer cast $20 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (byte) $20 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Rewriting multiplication to use shift [46] (byte~) main::$7 ← (byte) main::s#2 * (const byte) SIZEOF_STRUCT_SPRITEDATA +Rewriting multiplication to use shift [66] (byte~) vblank::$4 ← (byte) vblank::s#2 * (const byte) SIZEOF_STRUCT_SPRITEDATA +Successful SSA optimization Pass2MultiplyToShiftRewriting +Inlining constant with var siblings (const word) ppuDataFill::i#0 +Inlining constant with different constant siblings (const nomodify void*) ppuDataFill::ppuData#0 +Inlining constant with var siblings (const byte) ppuDataFill::val#0 +Inlining constant with var siblings (const word) ppuDataFill::size#0 +Inlining constant with different constant siblings (const nomodify void*) ppuDataFill::ppuData#1 +Inlining constant with var siblings (const byte) ppuDataFill::val#1 +Inlining constant with var siblings (const word) ppuDataFill::size#1 +Inlining constant with var siblings (const word) ppuDataTransfer::i#0 +Inlining constant with var siblings (const byte*) ppuDataTransfer::cpuSrc#0 +Inlining constant with var siblings (const byte) main::initNES1_i#0 +Inlining constant with var siblings (const byte) main::s#0 +Inlining constant with var siblings (const byte) vblank::s#0 +Constant inlined ppuDataTransfer::i#0 = (word) 0 +Constant inlined ppuDataTransfer::ppuDataPrepare1_$1 = (byte) 0 +Constant inlined ppuDataTransfer::ppuDataPrepare1_$0 = >(const nomodify void*) ppuDataTransfer::ppuData#0 +Constant inlined vblank::s#0 = (byte) 0 +Constant inlined main::enableVideoOutput1_$3 = (byte*)(const struct RICOH_2C02*) PPU +Constant inlined main::enableVideoOutput1_$2 = (byte*)(const struct RICOH_2C02*) PPU +Constant inlined vblank::$7 = (byte*)(const struct RICOH_2C02*) PPU +Constant inlined ppuDataTransfer::ppuDataPut1_$1 = (byte*)(const struct RICOH_2C02*) PPU +Constant inlined vblank::$8 = (byte*)(const struct RICOH_2C02*) PPU +Constant inlined ppuDataFill::val#1 = (byte) 0 +Constant inlined ppuDataFill::ppuDataPut1_$1 = (byte*)(const struct RICOH_2C02*) PPU +Constant inlined ppuDataFill::val#0 = (byte) '*' +Constant inlined main::initNES1_waitForVBlank2_$3 = (byte*)(const struct RICOH_2C02*) PPU +Constant inlined ppuDataFill::ppuDataPrepare1_$4 = (byte*)(const struct RICOH_2C02*) PPU +Constant inlined ppuDataTransfer::ppuDataPrepare1_$5 = (byte*)(const struct RICOH_2C02*) PPU +Constant inlined ppuDataFill::ppuDataPrepare1_$5 = (byte*)(const struct RICOH_2C02*) PPU +Constant inlined ppuDataTransfer::ppuDataPrepare1_$4 = (byte*)(const struct RICOH_2C02*) PPU +Constant inlined main::initNES1_disableVideoOutput1_$3 = (byte*)(const struct RICOH_2C02*) PPU +Constant inlined main::initNES1_disableVideoOutput1_$2 = (byte*)(const struct RICOH_2C02*) PPU +Constant inlined ppuDataFill::ppuData#1 = (void*)(const nomodify byte*) PPU_ATTRIBUTE_TABLE_0 +Constant inlined ppuDataFill::ppuData#0 = (void*)(const nomodify byte*) PPU_NAME_TABLE_0 +Constant inlined main::initNES1_disableAudioOutput1_$1 = (byte*)(const struct RICOH_2A03*) APU +Constant inlined ppuDataTransfer::cpuSrc#0 = (byte*)(const nomodify void*) ppuDataTransfer::cpuData#0 +Constant inlined main::s#0 = (byte) 0 +Constant inlined main::initNES1_i#0 = (byte) 0 +Constant inlined vblank::ppuSpriteBufferDmaTransfer1_spriteBuffer#0 = (const struct SpriteData*) SPRITE_BUFFER +Constant inlined main::initNES1_waitForVBlank1_$3 = (byte*)(const struct RICOH_2C02*) PPU +Constant inlined vblank::ppuSpriteBufferDmaTransfer1_$0 = >(const struct SpriteData*) SPRITE_BUFFER +Constant inlined ppuDataFill::size#1 = (byte) $40 +Constant inlined ppuDataFill::size#0 = (word)(number) $20*(number) $1e +Constant inlined vblank::ppuSpriteBufferDmaTransfer1_$3 = (byte*)(const struct RICOH_2C02*) PPU +Constant inlined ppuDataFill::i#0 = (word) 0 +Constant inlined vblank::ppuSpriteBufferDmaTransfer1_$4 = (byte*)(const struct RICOH_2A03*) APU +Successful SSA optimization Pass2ConstantInlining +Consolidated array index constant in *((byte*)PPU+OFFSET_STRUCT_RICOH_2C02_PPUADDR) +Consolidated array index constant in *((byte*)PPU+OFFSET_STRUCT_RICOH_2C02_PPUADDR) +Consolidated array index constant in *((byte*)PPU+OFFSET_STRUCT_RICOH_2C02_PPUDATA) +Consolidated array index constant in *((byte*)PPU+OFFSET_STRUCT_RICOH_2C02_PPUADDR) +Consolidated array index constant in *((byte*)PPU+OFFSET_STRUCT_RICOH_2C02_PPUADDR) +Consolidated array index constant in *((byte*)PPU+OFFSET_STRUCT_RICOH_2C02_PPUDATA) +Consolidated array index constant in *((byte*)PPU+OFFSET_STRUCT_RICOH_2C02_PPUMASK) +Consolidated array index constant in *((byte*)APU+OFFSET_STRUCT_RICOH_2A03_DMC_FREQ) +Consolidated array index constant in *((byte*)PPU+OFFSET_STRUCT_RICOH_2C02_PPUSTATUS) +Consolidated array index constant in *((byte*)PPU+OFFSET_STRUCT_RICOH_2C02_PPUSTATUS) +Consolidated array index constant in *((byte*)PPU+OFFSET_STRUCT_RICOH_2C02_PPUMASK) +Consolidated array index constant in *((byte*)PPU+OFFSET_STRUCT_RICOH_2C02_PPUSCROLL) +Consolidated array index constant in *((byte*)PPU+OFFSET_STRUCT_RICOH_2C02_PPUSCROLL) +Consolidated array index constant in *((byte*)PPU+OFFSET_STRUCT_RICOH_2C02_OAMADDR) +Consolidated array index constant in *((byte*)APU+OFFSET_STRUCT_RICOH_2A03_OAMDMA) +Successful SSA optimization Pass2ConstantAdditionElimination +Eliminating unused constant (const byte) SIZEOF_STRUCT_SPRITEDATA +Successful SSA optimization PassNEliminateUnusedVars +Added new block during phi lifting main::@8(between main::initNES1_@1 and main::initNES1_@1) +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @2 +Adding NOP phi() at start of @3 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main +Adding NOP phi() at start of main::initNES1_waitForVBlank1 +Adding NOP phi() at start of main::initNES1_@6 +Adding NOP phi() at start of main::initNES1_waitForVBlank2 +Adding NOP phi() at start of main::@4 +Adding NOP phi() at start of main::@5 +Adding NOP phi() at start of main::@6 +Adding NOP phi() at start of main::@7 +Adding NOP phi() at start of main::@3 +Adding NOP phi() at start of ppuDataFill::@3 +Adding NOP phi() at start of ppuDataFill::@2 +Adding NOP phi() at start of ppuDataTransfer +Adding NOP phi() at start of ppuDataTransfer::@3 +CALL GRAPH +Calls in [] to main:4 +Calls in [main] to ppuDataTransfer:34 ppuDataFill:36 ppuDataFill:38 + +Created 11 initial phi equivalence classes +Coalesced [51] main::s#4 ← main::s#1 +Coalesced [52] main::initNES1_i#3 ← main::initNES1_i#1 +Coalesced [65] ppuDataFill::i#6 ← ppuDataFill::i#1 +Coalesced [77] ppuDataTransfer::i#6 ← ppuDataTransfer::i#1 +Coalesced [78] ppuDataTransfer::cpuSrc#6 ← ppuDataTransfer::cpuSrc#1 +Coalesced [87] vblank::y_idx#5 ← vblank::y_idx#0 +Coalesced [88] vblank::x_idx#5 ← vblank::x_idx#0 +Coalesced [99] vblank::s#4 ← vblank::s#1 +Coalesced [100] vblank::y_idx#4 ← vblank::y_idx#1 +Coalesced [101] vblank::x_idx#4 ← vblank::x_idx#1 +Coalesced down to 11 phi equivalence classes +Culled Empty Block (label) @3 +Culled Empty Block (label) main::initNES1_@6 +Culled Empty Block (label) main::@7 +Culled Empty Block (label) main::@8 +Culled Empty Block (label) ppuDataFill::@3 +Culled Empty Block (label) ppuDataFill::@2 +Culled Empty Block (label) ppuDataTransfer::@3 +Renumbering block ppuDataFill::@4 to ppuDataFill::@2 +Renumbering block ppuDataTransfer::@4 to ppuDataTransfer::@3 +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @2 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main +Adding NOP phi() at start of main::initNES1_waitForVBlank1 +Adding NOP phi() at start of main::initNES1_waitForVBlank2 +Adding NOP phi() at start of main::@4 +Adding NOP phi() at start of main::@5 +Adding NOP phi() at start of main::@6 +Adding NOP phi() at start of main::@3 +Adding NOP phi() at start of ppuDataTransfer + +FINAL CONTROL FLOW GRAPH +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] (volatile byte) y_sin_idx ← (byte) 0 + [2] (volatile byte) x_sin_idx ← (byte) $49 + to:@2 +@2: scope:[] from @1 + [3] phi() + [4] call main + to:@end +@end: scope:[] from @2 + [5] phi() + +(void()) main() +main: scope:[main] from @2 + [6] phi() + to:main::initNES1 +main::initNES1: scope:[main] from main + asm { cld ldx#$ff txs } + to:main::initNES1_disableVideoOutput1 +main::initNES1_disableVideoOutput1: scope:[main] from main::initNES1 + [8] *((byte*)(const struct RICOH_2C02*) PPU) ← (byte) 0 + [9] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUMASK) ← (byte) 0 + to:main::initNES1_disableAudioOutput1 +main::initNES1_disableAudioOutput1: scope:[main] from main::initNES1_disableVideoOutput1 + [10] *((const nomodify byte*) FR_COUNTER) ← (byte) $40 + [11] *((byte*)(const struct RICOH_2A03*) APU+(const byte) OFFSET_STRUCT_RICOH_2A03_DMC_FREQ) ← (byte) $40 + to:main::initNES1_clearVBlankFlag1 +main::initNES1_clearVBlankFlag1: scope:[main] from main::initNES1_disableAudioOutput1 + asm { ldaPPU_PPUSTATUS } + to:main::initNES1_waitForVBlank1 +main::initNES1_waitForVBlank1: scope:[main] from main::initNES1_clearVBlankFlag1 + [13] phi() + to:main::initNES1_waitForVBlank1_@1 +main::initNES1_waitForVBlank1_@1: scope:[main] from main::initNES1_waitForVBlank1 main::initNES1_waitForVBlank1_@1 + [14] (byte~) main::initNES1_waitForVBlank1_$0 ← *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSTATUS) & (byte) $80 + [15] if((byte) 0==(byte~) main::initNES1_waitForVBlank1_$0) goto main::initNES1_waitForVBlank1_@1 + to:main::initNES1_@1 +main::initNES1_@1: scope:[main] from main::initNES1_@1 main::initNES1_waitForVBlank1_@1 + [16] (byte) main::initNES1_i#2 ← phi( main::initNES1_@1/(byte) main::initNES1_i#1 main::initNES1_waitForVBlank1_@1/(byte) 0 ) + [17] *((const nomodify byte*) MEMORY + (byte) main::initNES1_i#2) ← (byte) 0 + [18] *((const nomodify byte*) MEMORY+(word) $100 + (byte) main::initNES1_i#2) ← (byte) 0 + [19] *((const nomodify byte*) MEMORY+(word) $200 + (byte) main::initNES1_i#2) ← (byte) 0 + [20] *((const nomodify byte*) MEMORY+(word) $300 + (byte) main::initNES1_i#2) ← (byte) 0 + [21] *((const nomodify byte*) MEMORY+(word) $400 + (byte) main::initNES1_i#2) ← (byte) 0 + [22] *((const nomodify byte*) MEMORY+(word) $500 + (byte) main::initNES1_i#2) ← (byte) 0 + [23] *((const nomodify byte*) MEMORY+(word) $600 + (byte) main::initNES1_i#2) ← (byte) 0 + [24] *((const nomodify byte*) MEMORY+(word) $700 + (byte) main::initNES1_i#2) ← (byte) 0 + [25] (byte) main::initNES1_i#1 ← ++ (byte) main::initNES1_i#2 + [26] if((byte) 0!=(byte) main::initNES1_i#1) goto main::initNES1_@1 + to:main::initNES1_waitForVBlank2 +main::initNES1_waitForVBlank2: scope:[main] from main::initNES1_@1 + [27] phi() + to:main::initNES1_waitForVBlank2_@1 +main::initNES1_waitForVBlank2_@1: scope:[main] from main::initNES1_waitForVBlank2 main::initNES1_waitForVBlank2_@1 + [28] (byte~) main::initNES1_waitForVBlank2_$0 ← *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSTATUS) & (byte) $80 + [29] if((byte) 0==(byte~) main::initNES1_waitForVBlank2_$0) goto main::initNES1_waitForVBlank2_@1 + to:main::initNES1_@7 +main::initNES1_@7: scope:[main] from main::initNES1_waitForVBlank2_@1 + asm { ldaPPU_PPUSTATUS } + to:main::@4 +main::@4: scope:[main] from main::initNES1_@7 + [31] phi() + [32] call ppuDataTransfer + to:main::@5 +main::@5: scope:[main] from main::@4 + [33] phi() + [34] call ppuDataFill + to:main::@6 +main::@6: scope:[main] from main::@5 + [35] phi() + [36] call ppuDataFill + to:main::@1 +main::@1: scope:[main] from main::@2 main::@6 + [37] (byte) main::s#2 ← phi( main::@2/(byte) main::s#1 main::@6/(byte) 0 ) + [38] if((byte) main::s#2<(byte) $40) goto main::@2 + to:main::enableVideoOutput1 +main::enableVideoOutput1: scope:[main] from main::@1 + [39] *((byte*)(const struct RICOH_2C02*) PPU) ← (byte) $80 + [40] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUMASK) ← (byte) $1e + to:main::@3 +main::@3: scope:[main] from main::@3 main::enableVideoOutput1 + [41] phi() + to:main::@3 +main::@2: scope:[main] from main::@1 + [42] (byte~) main::$7 ← (byte) main::s#2 << (byte) 2 + [43] *((byte*)(const struct SpriteData*) SPRITE_BUFFER + (byte~) main::$7) ← (byte) 0 + [44] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_TILE + (byte~) main::$7) ← *((const byte*) MESSAGE + (byte) main::s#2) + [45] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_ATTRIBUTES + (byte~) main::$7) ← (byte) 2 + [46] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_X + (byte~) main::$7) ← (byte) 0 + [47] (byte) main::s#1 ← ++ (byte) main::s#2 + to:main::@1 + +(void()) ppuDataFill((nomodify void*) ppuDataFill::ppuData , (byte) ppuDataFill::val , (word) ppuDataFill::size) +ppuDataFill: scope:[ppuDataFill] from main::@5 main::@6 + [48] (byte) ppuDataFill::val#4 ← phi( main::@5/(byte) '*' main::@6/(byte) 0 ) + [48] (word) ppuDataFill::size#3 ← phi( main::@5/(word)(number) $20*(number) $1e main::@6/(byte) $40 ) + [48] (nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0 ← phi( main::@5/(void*)(const nomodify byte*) PPU_NAME_TABLE_0 main::@6/(void*)(const nomodify byte*) PPU_ATTRIBUTE_TABLE_0 ) + to:ppuDataFill::ppuDataPrepare1 +ppuDataFill::ppuDataPrepare1: scope:[ppuDataFill] from ppuDataFill + [49] (byte~) ppuDataFill::ppuDataPrepare1_$0 ← > (nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0 + [50] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← (byte~) ppuDataFill::ppuDataPrepare1_$0 + [51] (byte~) ppuDataFill::ppuDataPrepare1_$1 ← < (nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0 + [52] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← (byte~) ppuDataFill::ppuDataPrepare1_$1 + to:ppuDataFill::@1 +ppuDataFill::@1: scope:[ppuDataFill] from ppuDataFill::@2 ppuDataFill::ppuDataPrepare1 + [53] (word) ppuDataFill::i#2 ← phi( ppuDataFill::ppuDataPrepare1/(word) 0 ppuDataFill::@2/(word) ppuDataFill::i#1 ) + [54] if((word) ppuDataFill::i#2<(word) ppuDataFill::size#3) goto ppuDataFill::ppuDataPut1 + to:ppuDataFill::@return +ppuDataFill::@return: scope:[ppuDataFill] from ppuDataFill::@1 + [55] return + to:@return +ppuDataFill::ppuDataPut1: scope:[ppuDataFill] from ppuDataFill::@1 + [56] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUDATA) ← (byte) ppuDataFill::val#4 + to:ppuDataFill::@2 +ppuDataFill::@2: scope:[ppuDataFill] from ppuDataFill::ppuDataPut1 + [57] (word) ppuDataFill::i#1 ← ++ (word) ppuDataFill::i#2 + to:ppuDataFill::@1 + +(void()) ppuDataTransfer((nomodify void*) ppuDataTransfer::ppuData , (nomodify void*) ppuDataTransfer::cpuData , (word) ppuDataTransfer::size) +ppuDataTransfer: scope:[ppuDataTransfer] from main::@4 + [58] phi() + to:ppuDataTransfer::ppuDataPrepare1 +ppuDataTransfer::ppuDataPrepare1: scope:[ppuDataTransfer] from ppuDataTransfer + [59] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← >(const nomodify void*) ppuDataTransfer::ppuData#0 + [60] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← (byte) 0 + to:ppuDataTransfer::@1 +ppuDataTransfer::@1: scope:[ppuDataTransfer] from ppuDataTransfer::@3 ppuDataTransfer::ppuDataPrepare1 + [61] (byte*) ppuDataTransfer::cpuSrc#2 ← phi( ppuDataTransfer::ppuDataPrepare1/(byte*)(const nomodify void*) ppuDataTransfer::cpuData#0 ppuDataTransfer::@3/(byte*) ppuDataTransfer::cpuSrc#1 ) + [61] (word) ppuDataTransfer::i#2 ← phi( ppuDataTransfer::ppuDataPrepare1/(word) 0 ppuDataTransfer::@3/(word) ppuDataTransfer::i#1 ) + [62] if((word) ppuDataTransfer::i#2<(const word) ppuDataTransfer::size#0) goto ppuDataTransfer::@2 + to:ppuDataTransfer::@return +ppuDataTransfer::@return: scope:[ppuDataTransfer] from ppuDataTransfer::@1 + [63] return + to:@return +ppuDataTransfer::@2: scope:[ppuDataTransfer] from ppuDataTransfer::@1 + [64] (byte) ppuDataTransfer::ppuDataPut1_val#0 ← *((byte*) ppuDataTransfer::cpuSrc#2) + to:ppuDataTransfer::ppuDataPut1 +ppuDataTransfer::ppuDataPut1: scope:[ppuDataTransfer] from ppuDataTransfer::@2 + [65] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUDATA) ← (byte) ppuDataTransfer::ppuDataPut1_val#0 + to:ppuDataTransfer::@3 +ppuDataTransfer::@3: scope:[ppuDataTransfer] from ppuDataTransfer::ppuDataPut1 + [66] (byte*) ppuDataTransfer::cpuSrc#1 ← ++ (byte*) ppuDataTransfer::cpuSrc#2 + [67] (word) ppuDataTransfer::i#1 ← ++ (word) ppuDataTransfer::i#2 + to:ppuDataTransfer::@1 + +interrupt(HARDWARE_STACK)(void()) vblank() +vblank: scope:[vblank] from + [68] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSCROLL) ← (byte) 0 + [69] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSCROLL) ← (byte) 0 + to:vblank::ppuSpriteBufferDmaTransfer1 +vblank::ppuSpriteBufferDmaTransfer1: scope:[vblank] from vblank + [70] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_OAMADDR) ← (byte) 0 + [71] *((byte*)(const struct RICOH_2A03*) APU+(const byte) OFFSET_STRUCT_RICOH_2A03_OAMDMA) ← >(const struct SpriteData*) SPRITE_BUFFER + to:vblank::@3 +vblank::@3: scope:[vblank] from vblank::ppuSpriteBufferDmaTransfer1 + [72] (byte) vblank::y_idx#0 ← (volatile byte) y_sin_idx + [73] (volatile byte) y_sin_idx ← ++ (volatile byte) y_sin_idx + [74] (byte) vblank::x_idx#0 ← (volatile byte) x_sin_idx + [75] (volatile byte) x_sin_idx ← ++ (volatile byte) x_sin_idx + to:vblank::@1 +vblank::@1: scope:[vblank] from vblank::@2 vblank::@3 + [76] (byte) vblank::x_idx#2 ← phi( vblank::@2/(byte) vblank::x_idx#1 vblank::@3/(byte) vblank::x_idx#0 ) + [76] (byte) vblank::y_idx#2 ← phi( vblank::@2/(byte) vblank::y_idx#1 vblank::@3/(byte) vblank::y_idx#0 ) + [76] (byte) vblank::s#2 ← phi( vblank::@2/(byte) vblank::s#1 vblank::@3/(byte) 0 ) + [77] if((byte) vblank::s#2<(byte) $40) goto vblank::@2 + to:vblank::@return +vblank::@return: scope:[vblank] from vblank::@1 + [78] return + to:@return +vblank::@2: scope:[vblank] from vblank::@1 + [79] (byte~) vblank::$4 ← (byte) vblank::s#2 << (byte) 2 + [80] *((byte*)(const struct SpriteData*) SPRITE_BUFFER + (byte~) vblank::$4) ← *((const to_nomodify byte*) SINTABLE + (byte) vblank::y_idx#2) + [81] (byte~) vblank::$2 ← *((const to_nomodify byte*) SINTABLE + (byte) vblank::x_idx#2) + (byte) 8 + [82] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_X + (byte~) vblank::$4) ← (byte~) vblank::$2 + [83] (byte) vblank::y_idx#1 ← (byte) vblank::y_idx#2 + (byte) 4 + [84] (byte) vblank::x_idx#1 ← (byte) vblank::x_idx#2 - (byte) 7 + [85] (byte) vblank::s#1 ← ++ (byte) vblank::s#2 + to:vblank::@1 + + +VARIABLE REGISTER WEIGHTS +(byte) RICOH_2A03::DMC_FREQ +(byte) RICOH_2A03::DMC_LEN +(byte) RICOH_2A03::DMC_RAW +(byte) RICOH_2A03::DMC_START +(byte) RICOH_2A03::JOY1 +(byte) RICOH_2A03::JOY2 +(byte) RICOH_2A03::NOISE_HI +(byte) RICOH_2A03::NOISE_LO +(byte) RICOH_2A03::NOISE_VOL +(byte) RICOH_2A03::OAMDMA +(byte) RICOH_2A03::SND_CHN +(byte) RICOH_2A03::SQ1_HI +(byte) RICOH_2A03::SQ1_LO +(byte) RICOH_2A03::SQ1_SWEEP +(byte) RICOH_2A03::SQ1_VOL +(byte) RICOH_2A03::SQ2_HI +(byte) RICOH_2A03::SQ2_LO +(byte) RICOH_2A03::SQ2_SWEEP +(byte) RICOH_2A03::SQ2_VOL +(byte) RICOH_2A03::TRI_HI +(byte) RICOH_2A03::TRI_LINEAR +(byte) RICOH_2A03::TRI_LO +(byte) RICOH_2A03::UNUSED1 +(byte) RICOH_2A03::UNUSED2 +(byte) RICOH_2C02::OAMADDR +(byte) RICOH_2C02::OAMDATA +(byte) RICOH_2C02::PPUADDR +(byte) RICOH_2C02::PPUCTRL +(byte) RICOH_2C02::PPUDATA +(byte) RICOH_2C02::PPUMASK +(byte) RICOH_2C02::PPUSCROLL +(volatile byte) RICOH_2C02::PPUSTATUS loadstore +(byte) SpriteData::attributes +(byte) SpriteData::tile +(byte) SpriteData::x +(byte) SpriteData::y +(void()) main() +(byte~) main::$7 126.25 +(byte) main::initNES1_i +(byte) main::initNES1_i#1 151.5 +(byte) main::initNES1_i#2 112.22222222222223 +(byte~) main::initNES1_waitForVBlank1_$0 202.0 +(byte~) main::initNES1_waitForVBlank2_$0 202.0 +(byte) main::s +(byte) main::s#1 202.0 +(byte) main::s#2 72.14285714285714 +(void()) ppuDataFill((nomodify void*) ppuDataFill::ppuData , (byte) ppuDataFill::val , (word) ppuDataFill::size) +(word) ppuDataFill::i +(word) ppuDataFill::i#1 2002.0 +(word) ppuDataFill::i#2 1001.0 +(nomodify void*) ppuDataFill::ppuData +(byte~) ppuDataFill::ppuDataPrepare1_$0 202.0 +(byte~) ppuDataFill::ppuDataPrepare1_$1 202.0 +(nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData +(nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0 67.33333333333333 +(byte) ppuDataFill::ppuDataPut1_val +(word) ppuDataFill::size +(word) ppuDataFill::size#3 111.22222222222223 +(byte) ppuDataFill::val +(byte) ppuDataFill::val#4 111.22222222222223 +(void()) ppuDataTransfer((nomodify void*) ppuDataTransfer::ppuData , (nomodify void*) ppuDataTransfer::cpuData , (word) ppuDataTransfer::size) +(nomodify void*) ppuDataTransfer::cpuData +(byte*) ppuDataTransfer::cpuSrc +(byte*) ppuDataTransfer::cpuSrc#1 1001.0 +(byte*) ppuDataTransfer::cpuSrc#2 750.75 +(word) ppuDataTransfer::i +(word) ppuDataTransfer::i#1 2002.0 +(word) ppuDataTransfer::i#2 600.5999999999999 +(nomodify void*) ppuDataTransfer::ppuData +(nomodify void*) ppuDataTransfer::ppuDataPrepare1_ppuData +(byte) ppuDataTransfer::ppuDataPut1_val +(byte) ppuDataTransfer::ppuDataPut1_val#0 2002.0 +(word) ppuDataTransfer::size +interrupt(HARDWARE_STACK)(void()) vblank() +(byte~) vblank::$2 22.0 +(byte~) vblank::$4 11.0 +(struct SpriteData*) vblank::ppuSpriteBufferDmaTransfer1_spriteBuffer +(byte) vblank::s +(byte) vblank::s#1 22.0 +(byte) vblank::s#2 5.5 +(byte) vblank::x_idx +(byte) vblank::x_idx#0 2.0 +(byte) vblank::x_idx#1 11.0 +(byte) vblank::x_idx#2 5.0 +(byte) vblank::y_idx +(byte) vblank::y_idx#0 1.0 +(byte) vblank::y_idx#1 7.333333333333333 +(byte) vblank::y_idx#2 5.833333333333333 +(volatile byte) x_sin_idx loadstore 1.1428571428571428 +(volatile byte) y_sin_idx loadstore 1.6 + +Initial phi equivalence classes +[ main::initNES1_i#2 main::initNES1_i#1 ] +[ main::s#2 main::s#1 ] +[ ppuDataFill::ppuDataPrepare1_ppuData#0 ] +[ ppuDataFill::size#3 ] +[ ppuDataFill::val#4 ] +[ ppuDataFill::i#2 ppuDataFill::i#1 ] +[ ppuDataTransfer::i#2 ppuDataTransfer::i#1 ] +[ ppuDataTransfer::cpuSrc#2 ppuDataTransfer::cpuSrc#1 ] +[ vblank::s#2 vblank::s#1 ] +[ vblank::y_idx#2 vblank::y_idx#1 vblank::y_idx#0 ] +[ vblank::x_idx#2 vblank::x_idx#1 vblank::x_idx#0 ] +Added variable y_sin_idx to live range equivalence class [ y_sin_idx ] +Added variable x_sin_idx to live range equivalence class [ x_sin_idx ] +Added variable main::initNES1_waitForVBlank1_$0 to live range equivalence class [ main::initNES1_waitForVBlank1_$0 ] +Added variable main::initNES1_waitForVBlank2_$0 to live range equivalence class [ main::initNES1_waitForVBlank2_$0 ] +Added variable main::$7 to live range equivalence class [ main::$7 ] +Added variable ppuDataFill::ppuDataPrepare1_$0 to live range equivalence class [ ppuDataFill::ppuDataPrepare1_$0 ] +Added variable ppuDataFill::ppuDataPrepare1_$1 to live range equivalence class [ ppuDataFill::ppuDataPrepare1_$1 ] +Added variable ppuDataTransfer::ppuDataPut1_val#0 to live range equivalence class [ ppuDataTransfer::ppuDataPut1_val#0 ] +Added variable vblank::$4 to live range equivalence class [ vblank::$4 ] +Added variable vblank::$2 to live range equivalence class [ vblank::$2 ] +Complete equivalence classes +[ main::initNES1_i#2 main::initNES1_i#1 ] +[ main::s#2 main::s#1 ] +[ ppuDataFill::ppuDataPrepare1_ppuData#0 ] +[ ppuDataFill::size#3 ] +[ ppuDataFill::val#4 ] +[ ppuDataFill::i#2 ppuDataFill::i#1 ] +[ ppuDataTransfer::i#2 ppuDataTransfer::i#1 ] +[ ppuDataTransfer::cpuSrc#2 ppuDataTransfer::cpuSrc#1 ] +[ vblank::s#2 vblank::s#1 ] +[ vblank::y_idx#2 vblank::y_idx#1 vblank::y_idx#0 ] +[ vblank::x_idx#2 vblank::x_idx#1 vblank::x_idx#0 ] +[ y_sin_idx ] +[ x_sin_idx ] +[ main::initNES1_waitForVBlank1_$0 ] +[ main::initNES1_waitForVBlank2_$0 ] +[ main::$7 ] +[ ppuDataFill::ppuDataPrepare1_$0 ] +[ ppuDataFill::ppuDataPrepare1_$1 ] +[ ppuDataTransfer::ppuDataPut1_val#0 ] +[ vblank::$4 ] +[ vblank::$2 ] +Allocated zp[1]:2 [ main::initNES1_i#2 main::initNES1_i#1 ] +Allocated zp[1]:3 [ main::s#2 main::s#1 ] +Allocated zp[2]:4 [ ppuDataFill::ppuDataPrepare1_ppuData#0 ] +Allocated zp[2]:6 [ ppuDataFill::size#3 ] +Allocated zp[1]:8 [ ppuDataFill::val#4 ] +Allocated zp[2]:9 [ ppuDataFill::i#2 ppuDataFill::i#1 ] +Allocated zp[2]:11 [ ppuDataTransfer::i#2 ppuDataTransfer::i#1 ] +Allocated zp[2]:13 [ ppuDataTransfer::cpuSrc#2 ppuDataTransfer::cpuSrc#1 ] +Allocated zp[1]:15 [ vblank::s#2 vblank::s#1 ] +Allocated zp[1]:16 [ vblank::y_idx#2 vblank::y_idx#1 vblank::y_idx#0 ] +Allocated zp[1]:17 [ vblank::x_idx#2 vblank::x_idx#1 vblank::x_idx#0 ] +Allocated zp[1]:18 [ y_sin_idx ] +Allocated zp[1]:19 [ x_sin_idx ] +Allocated zp[1]:20 [ main::initNES1_waitForVBlank1_$0 ] +Allocated zp[1]:21 [ main::initNES1_waitForVBlank2_$0 ] +Allocated zp[1]:22 [ main::$7 ] +Allocated zp[1]:23 [ ppuDataFill::ppuDataPrepare1_$0 ] +Allocated zp[1]:24 [ ppuDataFill::ppuDataPrepare1_$1 ] +Allocated zp[1]:25 [ ppuDataTransfer::ppuDataPut1_val#0 ] +Allocated zp[1]:26 [ vblank::$4 ] +Allocated zp[1]:27 [ vblank::$2 ] + +INITIAL ASM +Target platform is nes / MOS6502 + // File Comments +// NES DXYCP using sprites +// Nintendo Entertainment System (NES +// https://en.wikipedia.org/wiki/Nintendo_Entertainment_System_(Model_NES-101) +// https://github.com/gregkrsak/first_nes +// Ricoh 2C02 - NES Picture Processing Unit (PPU) +// Ricoh RP2C02 (NTSC version) / RP2C07 (PAL version), +// https://en.wikipedia.org/wiki/Picture_Processing_Unit +// https://wiki.nesdev.com/w/index.php/PPU_registers +// http://nesdev.com/2C02%20technical%20reference.TXT +// Based on: https://github.com/gregkrsak/first_nes written by Greg M. Krsak, 2018. + // Upstart + // Nintendo Entertainment System (NES) ROM +// https://sadistech.com/nesromtool/romdoc.html +// https://forums.nesdev.com/viewtopic.php?f=2&t=9896 +// https://github.com/gregkrsak/first_nes +.file [name="nes-dxycp.nes", type="bin", segments="NesRom"] +.file [name="nes-dxycp.nes_hdr", type="bin", segments="Header"] +.file [name="nes-dxycp.nes_prg", type="bin", segments="ProgramRom"] +.file [name="nes-dxycp.nes_chr", type="bin", segments="CharacterRom"] +.segmentdef Header [ start=$0000, min=$0000, max=$000f, fill ] +.segmentdef Tiles [ start=$0000, min=$0000, max=$1fff, fill ] +.segmentdef Code [ start=$c000, min=$c000, max=$fff9 ] +.segmentdef Data [ startAfter="Code", min=$c000, max=$fff9 ] +.segmentdef Vectors [ start=$fffa, min=$fffa, max=$ffff ] +.segmentdef GameRam [start=$200,max=$7ff, virtual] +.segmentdef ProgramRom [ segments="Code, Data, Vectors" ] +.segmentdef CharacterRom [ segments="Tiles" ] +.segmentdef NesRom +.segment NesRom +.segmentout [ segments="Header" ] +.segmentout [ segments="ProgramRom" ] +.segmentout [ segments="CharacterRom" ] +.segment Header +.text @"NES\$1a" +.byte $01 // 1x 16KB ROM (PRG) +.byte $01 // 1x 8KB VROM (CHR) +.byte %00000001 // Mapper nibble 0000 == No mapping (a simple 16KB PRG + 8KB CHR game) + // Mirroring nibble 0001 == Vertical mirroring only +.segment Code + + // Global Constants & labels + .const OFFSET_STRUCT_SPRITEDATA_TILE = 1 + .const OFFSET_STRUCT_SPRITEDATA_ATTRIBUTES = 2 + .const OFFSET_STRUCT_SPRITEDATA_X = 3 + .const OFFSET_STRUCT_RICOH_2A03_DMC_FREQ = $10 + .const OFFSET_STRUCT_RICOH_2C02_PPUMASK = 1 + .const OFFSET_STRUCT_RICOH_2C02_PPUSTATUS = 2 + .const OFFSET_STRUCT_RICOH_2C02_OAMADDR = 3 + .const OFFSET_STRUCT_RICOH_2A03_OAMDMA = $14 + .const OFFSET_STRUCT_RICOH_2C02_PPUADDR = 6 + .const OFFSET_STRUCT_RICOH_2C02_PPUDATA = 7 + .const OFFSET_STRUCT_RICOH_2C02_PPUSCROLL = 5 + .const SIZEOF_BYTE = 1 + // $2000-$23bf $03c0 Name table 0 + .label PPU_NAME_TABLE_0 = $2000 + // $23c0-$23ff $0040 Attribute table 0 + .label PPU_ATTRIBUTE_TABLE_0 = $23c0 + // $3000-$3eff $0f00 Mirrors of $2000-$2eff + // $3f00-$3f1f $0020 Palette RAM indexes + .label PPU_PALETTE = $3f00 + // PPU Status Register for reading in ASM + .label PPU_PPUSTATUS = $2002 + // APU Frame Counter + // generates low-frequency clocks for the channels and an optional 60 Hz interrupt. + // https://wiki.nesdev.com/w/index.php/APU_Frame_Counter + // ------+-----+--------------------------------------------------------------- + // $4017 | W | FR_COUNTER Frame Counter Set mode and interrupt + // ------+-----+--------------------------------------------------------------- + // | 7 | Sequencer mode: 0 selects 4-step sequence, 1 selects 5-step sequence + // | 6 | Interrupt inhibit flag. If set, the frame interrupt flag is cleared, otherwise it is unaffected. + // ------+-----+--------------------------------------------------------------- + // Side effects After 3 or 4 CPU clock cycles*, the timer is reset. + // If the mode flag is set, then both "quarter frame" and "half frame" signals are also generated. + .label FR_COUNTER = $4017 + // Pointer to the start of RAM memory + .label MEMORY = 0 + // NES Picture Processing Unit (PPU) + .label PPU = $2000 + // NES CPU and audion processing unit (APU) + .label APU = $4000 + .label y_sin_idx = $12 + .label x_sin_idx = $13 + // @begin +__bbegin: + jmp __b1 + // @1 +__b1: + // [1] (volatile byte) y_sin_idx ← (byte) 0 -- vbuz1=vbuc1 + // Index into the Y sine + lda #0 + sta.z y_sin_idx + // [2] (volatile byte) x_sin_idx ← (byte) $49 -- vbuz1=vbuc1 + // Index into the X sine + lda #$49 + sta.z x_sin_idx + // [3] phi from @1 to @2 [phi:@1->@2] +__b2_from___b1: + jmp __b2 + // @2 +__b2: + // [4] call main + // [6] phi from @2 to main [phi:@2->main] +main_from___b2: + jsr main + // [5] phi from @2 to @end [phi:@2->@end] +__bend_from___b2: + jmp __bend + // @end +__bend: +.segment Code + // main +// RESET Called when the NES is reset, including when it is turned on. +main: { + .label __7 = $16 + .label initNES1_waitForVBlank1___0 = $14 + .label initNES1_waitForVBlank2___0 = $15 + .label initNES1_i = 2 + .label s = 3 + jmp initNES1 + // main::initNES1 + initNES1: + // asm { cld ldx#$ff txs } + cld + ldx #$ff + txs + jmp initNES1_disableVideoOutput1 + // main::initNES1_disableVideoOutput1 + initNES1_disableVideoOutput1: + // [8] *((byte*)(const struct RICOH_2C02*) PPU) ← (byte) 0 -- _deref_pbuc1=vbuc2 + lda #0 + sta PPU + // [9] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUMASK) ← (byte) 0 -- _deref_pbuc1=vbuc2 + lda #0 + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUMASK + jmp initNES1_disableAudioOutput1 + // main::initNES1_disableAudioOutput1 + initNES1_disableAudioOutput1: + // [10] *((const nomodify byte*) FR_COUNTER) ← (byte) $40 -- _deref_pbuc1=vbuc2 + lda #$40 + sta FR_COUNTER + // [11] *((byte*)(const struct RICOH_2A03*) APU+(const byte) OFFSET_STRUCT_RICOH_2A03_DMC_FREQ) ← (byte) $40 -- _deref_pbuc1=vbuc2 + lda #$40 + sta APU+OFFSET_STRUCT_RICOH_2A03_DMC_FREQ + jmp initNES1_clearVBlankFlag1 + // main::initNES1_clearVBlankFlag1 + initNES1_clearVBlankFlag1: + // asm { ldaPPU_PPUSTATUS } + lda PPU_PPUSTATUS + // [13] phi from main::initNES1_clearVBlankFlag1 to main::initNES1_waitForVBlank1 [phi:main::initNES1_clearVBlankFlag1->main::initNES1_waitForVBlank1] + initNES1_waitForVBlank1_from_initNES1_clearVBlankFlag1: + jmp initNES1_waitForVBlank1 + // main::initNES1_waitForVBlank1 + initNES1_waitForVBlank1: + jmp initNES1_waitForVBlank1___b1 + // main::initNES1_waitForVBlank1_@1 + initNES1_waitForVBlank1___b1: + // [14] (byte~) main::initNES1_waitForVBlank1_$0 ← *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSTATUS) & (byte) $80 -- vbuz1=_deref_pbuc1_band_vbuc2 + lda #$80 + and PPU+OFFSET_STRUCT_RICOH_2C02_PPUSTATUS + sta.z initNES1_waitForVBlank1___0 + // [15] if((byte) 0==(byte~) main::initNES1_waitForVBlank1_$0) goto main::initNES1_waitForVBlank1_@1 -- vbuc1_eq_vbuz1_then_la1 + lda #0 + cmp.z initNES1_waitForVBlank1___0 + beq initNES1_waitForVBlank1___b1 + // [16] phi from main::initNES1_waitForVBlank1_@1 to main::initNES1_@1 [phi:main::initNES1_waitForVBlank1_@1->main::initNES1_@1] + initNES1___b1_from_initNES1_waitForVBlank1___b1: + // [16] phi (byte) main::initNES1_i#2 = (byte) 0 [phi:main::initNES1_waitForVBlank1_@1->main::initNES1_@1#0] -- vbuz1=vbuc1 + lda #0 + sta.z initNES1_i + jmp initNES1___b1 + // [16] phi from main::initNES1_@1 to main::initNES1_@1 [phi:main::initNES1_@1->main::initNES1_@1] + initNES1___b1_from_initNES1___b1: + // [16] phi (byte) main::initNES1_i#2 = (byte) main::initNES1_i#1 [phi:main::initNES1_@1->main::initNES1_@1#0] -- register_copy + jmp initNES1___b1 + // main::initNES1_@1 + initNES1___b1: + // [17] *((const nomodify byte*) MEMORY + (byte) main::initNES1_i#2) ← (byte) 0 -- pbuc1_derefidx_vbuz1=vbuc2 + lda #0 + ldy.z initNES1_i + sta MEMORY,y + // [18] *((const nomodify byte*) MEMORY+(word) $100 + (byte) main::initNES1_i#2) ← (byte) 0 -- pbuc1_derefidx_vbuz1=vbuc2 + lda #0 + ldy.z initNES1_i + sta MEMORY+$100,y + // [19] *((const nomodify byte*) MEMORY+(word) $200 + (byte) main::initNES1_i#2) ← (byte) 0 -- pbuc1_derefidx_vbuz1=vbuc2 + lda #0 + ldy.z initNES1_i + sta MEMORY+$200,y + // [20] *((const nomodify byte*) MEMORY+(word) $300 + (byte) main::initNES1_i#2) ← (byte) 0 -- pbuc1_derefidx_vbuz1=vbuc2 + lda #0 + ldy.z initNES1_i + sta MEMORY+$300,y + // [21] *((const nomodify byte*) MEMORY+(word) $400 + (byte) main::initNES1_i#2) ← (byte) 0 -- pbuc1_derefidx_vbuz1=vbuc2 + lda #0 + ldy.z initNES1_i + sta MEMORY+$400,y + // [22] *((const nomodify byte*) MEMORY+(word) $500 + (byte) main::initNES1_i#2) ← (byte) 0 -- pbuc1_derefidx_vbuz1=vbuc2 + lda #0 + ldy.z initNES1_i + sta MEMORY+$500,y + // [23] *((const nomodify byte*) MEMORY+(word) $600 + (byte) main::initNES1_i#2) ← (byte) 0 -- pbuc1_derefidx_vbuz1=vbuc2 + lda #0 + ldy.z initNES1_i + sta MEMORY+$600,y + // [24] *((const nomodify byte*) MEMORY+(word) $700 + (byte) main::initNES1_i#2) ← (byte) 0 -- pbuc1_derefidx_vbuz1=vbuc2 + lda #0 + ldy.z initNES1_i + sta MEMORY+$700,y + // [25] (byte) main::initNES1_i#1 ← ++ (byte) main::initNES1_i#2 -- vbuz1=_inc_vbuz1 + inc.z initNES1_i + // [26] if((byte) 0!=(byte) main::initNES1_i#1) goto main::initNES1_@1 -- vbuc1_neq_vbuz1_then_la1 + lda #0 + cmp.z initNES1_i + bne initNES1___b1_from_initNES1___b1 + // [27] phi from main::initNES1_@1 to main::initNES1_waitForVBlank2 [phi:main::initNES1_@1->main::initNES1_waitForVBlank2] + initNES1_waitForVBlank2_from_initNES1___b1: + jmp initNES1_waitForVBlank2 + // main::initNES1_waitForVBlank2 + initNES1_waitForVBlank2: + jmp initNES1_waitForVBlank2___b1 + // main::initNES1_waitForVBlank2_@1 + initNES1_waitForVBlank2___b1: + // [28] (byte~) main::initNES1_waitForVBlank2_$0 ← *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSTATUS) & (byte) $80 -- vbuz1=_deref_pbuc1_band_vbuc2 + lda #$80 + and PPU+OFFSET_STRUCT_RICOH_2C02_PPUSTATUS + sta.z initNES1_waitForVBlank2___0 + // [29] if((byte) 0==(byte~) main::initNES1_waitForVBlank2_$0) goto main::initNES1_waitForVBlank2_@1 -- vbuc1_eq_vbuz1_then_la1 + lda #0 + cmp.z initNES1_waitForVBlank2___0 + beq initNES1_waitForVBlank2___b1 + jmp initNES1___b7 + // main::initNES1_@7 + initNES1___b7: + // asm { ldaPPU_PPUSTATUS } + lda PPU_PPUSTATUS + // [31] phi from main::initNES1_@7 to main::@4 [phi:main::initNES1_@7->main::@4] + __b4_from_initNES1___b7: + jmp __b4 + // main::@4 + __b4: + // [32] call ppuDataTransfer + // Transfer the palette + // [58] phi from main::@4 to ppuDataTransfer [phi:main::@4->ppuDataTransfer] + ppuDataTransfer_from___b4: + jsr ppuDataTransfer + // [33] phi from main::@4 to main::@5 [phi:main::@4->main::@5] + __b5_from___b4: + jmp __b5 + // main::@5 + __b5: + // [34] call ppuDataFill + // Fill the PPU attribute table + // [48] phi from main::@5 to ppuDataFill [phi:main::@5->ppuDataFill] + ppuDataFill_from___b5: + // [48] phi (byte) ppuDataFill::val#4 = (byte) '*' [phi:main::@5->ppuDataFill#0] -- vbuz1=vbuc1 + lda #'*' + sta.z ppuDataFill.val + // [48] phi (word) ppuDataFill::size#3 = (word)(number) $20*(number) $1e [phi:main::@5->ppuDataFill#1] -- vwuz1=vwuc1 + lda #<$20*$1e + sta.z ppuDataFill.size + lda #>$20*$1e + sta.z ppuDataFill.size+1 + // [48] phi (nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0 = (void*)(const nomodify byte*) PPU_NAME_TABLE_0 [phi:main::@5->ppuDataFill#2] -- pvoz1=pvoc1 + lda #PPU_NAME_TABLE_0 + sta.z ppuDataFill.ppuDataPrepare1_ppuData+1 + jsr ppuDataFill + // [35] phi from main::@5 to main::@6 [phi:main::@5->main::@6] + __b6_from___b5: + jmp __b6 + // main::@6 + __b6: + // [36] call ppuDataFill + // [48] phi from main::@6 to ppuDataFill [phi:main::@6->ppuDataFill] + ppuDataFill_from___b6: + // [48] phi (byte) ppuDataFill::val#4 = (byte) 0 [phi:main::@6->ppuDataFill#0] -- vbuz1=vbuc1 + lda #0 + sta.z ppuDataFill.val + // [48] phi (word) ppuDataFill::size#3 = (byte) $40 [phi:main::@6->ppuDataFill#1] -- vwuz1=vbuc1 + lda #<$40 + sta.z ppuDataFill.size + lda #>$40 + sta.z ppuDataFill.size+1 + // [48] phi (nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0 = (void*)(const nomodify byte*) PPU_ATTRIBUTE_TABLE_0 [phi:main::@6->ppuDataFill#2] -- pvoz1=pvoc1 + lda #PPU_ATTRIBUTE_TABLE_0 + sta.z ppuDataFill.ppuDataPrepare1_ppuData+1 + jsr ppuDataFill + // [37] phi from main::@6 to main::@1 [phi:main::@6->main::@1] + __b1_from___b6: + // [37] phi (byte) main::s#2 = (byte) 0 [phi:main::@6->main::@1#0] -- vbuz1=vbuc1 + lda #0 + sta.z s + jmp __b1 + // Initialize Sprite Buffer with the SPRITE data + // main::@1 + __b1: + // [38] if((byte) main::s#2<(byte) $40) goto main::@2 -- vbuz1_lt_vbuc1_then_la1 + lda.z s + cmp #$40 + bcc __b2 + jmp enableVideoOutput1 + // main::enableVideoOutput1 + enableVideoOutput1: + // [39] *((byte*)(const struct RICOH_2C02*) PPU) ← (byte) $80 -- _deref_pbuc1=vbuc2 + lda #$80 + sta PPU + // [40] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUMASK) ← (byte) $1e -- _deref_pbuc1=vbuc2 + lda #$1e + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUMASK + // [41] phi from main::@3 main::enableVideoOutput1 to main::@3 [phi:main::@3/main::enableVideoOutput1->main::@3] + __b3_from___b3: + __b3_from_enableVideoOutput1: + jmp __b3 + // Infinite loop + // main::@3 + __b3: + jmp __b3_from___b3 + // main::@2 + __b2: + // [42] (byte~) main::$7 ← (byte) main::s#2 << (byte) 2 -- vbuz1=vbuz2_rol_2 + lda.z s + asl + asl + sta.z __7 + // [43] *((byte*)(const struct SpriteData*) SPRITE_BUFFER + (byte~) main::$7) ← (byte) 0 -- pbuc1_derefidx_vbuz1=vbuc2 + lda #0 + ldy.z __7 + sta SPRITE_BUFFER,y + // [44] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_TILE + (byte~) main::$7) ← *((const byte*) MESSAGE + (byte) main::s#2) -- pbuc1_derefidx_vbuz1=pbuc2_derefidx_vbuz2 + ldy.z s + lda MESSAGE,y + ldy.z __7 + sta SPRITE_BUFFER+OFFSET_STRUCT_SPRITEDATA_TILE,y + // [45] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_ATTRIBUTES + (byte~) main::$7) ← (byte) 2 -- pbuc1_derefidx_vbuz1=vbuc2 + lda #2 + ldy.z __7 + sta SPRITE_BUFFER+OFFSET_STRUCT_SPRITEDATA_ATTRIBUTES,y + // [46] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_X + (byte~) main::$7) ← (byte) 0 -- pbuc1_derefidx_vbuz1=vbuc2 + lda #0 + ldy.z __7 + sta SPRITE_BUFFER+OFFSET_STRUCT_SPRITEDATA_X,y + // [47] (byte) main::s#1 ← ++ (byte) main::s#2 -- vbuz1=_inc_vbuz1 + inc.z s + // [37] phi from main::@2 to main::@1 [phi:main::@2->main::@1] + __b1_from___b2: + // [37] phi (byte) main::s#2 = (byte) main::s#1 [phi:main::@2->main::@1#0] -- register_copy + jmp __b1 +} + // ppuDataFill +// Fill a number of bytes in the PPU memory +// - ppuData : Pointer in the PPU memory +// - size : The number of bytes to transfer +// ppuDataFill(byte zp(8) val, word zp(6) size) +ppuDataFill: { + .label ppuDataPrepare1___0 = $17 + .label ppuDataPrepare1___1 = $18 + .label ppuDataPrepare1_ppuData = 4 + .label i = 9 + .label size = 6 + .label val = 8 + jmp ppuDataPrepare1 + // ppuDataFill::ppuDataPrepare1 + ppuDataPrepare1: + // [49] (byte~) ppuDataFill::ppuDataPrepare1_$0 ← > (nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0 -- vbuz1=_hi_pvoz2 + lda.z ppuDataPrepare1_ppuData+1 + sta.z ppuDataPrepare1___0 + // [50] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← (byte~) ppuDataFill::ppuDataPrepare1_$0 -- _deref_pbuc1=vbuz1 + lda.z ppuDataPrepare1___0 + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUADDR + // [51] (byte~) ppuDataFill::ppuDataPrepare1_$1 ← < (nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0 -- vbuz1=_lo_pvoz2 + lda.z ppuDataPrepare1_ppuData + sta.z ppuDataPrepare1___1 + // [52] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← (byte~) ppuDataFill::ppuDataPrepare1_$1 -- _deref_pbuc1=vbuz1 + lda.z ppuDataPrepare1___1 + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUADDR + // [53] phi from ppuDataFill::ppuDataPrepare1 to ppuDataFill::@1 [phi:ppuDataFill::ppuDataPrepare1->ppuDataFill::@1] + __b1_from_ppuDataPrepare1: + // [53] phi (word) ppuDataFill::i#2 = (word) 0 [phi:ppuDataFill::ppuDataPrepare1->ppuDataFill::@1#0] -- vwuz1=vwuc1 + lda #<0 + sta.z i + lda #>0 + sta.z i+1 + jmp __b1 + // Transfer to PPU + // ppuDataFill::@1 + __b1: + // [54] if((word) ppuDataFill::i#2<(word) ppuDataFill::size#3) goto ppuDataFill::ppuDataPut1 -- vwuz1_lt_vwuz2_then_la1 + lda.z i+1 + cmp.z size+1 + bcc ppuDataPut1 + bne !+ + lda.z i + cmp.z size + bcc ppuDataPut1 + !: + jmp __breturn + // ppuDataFill::@return + __breturn: + // [55] return + rts + // ppuDataFill::ppuDataPut1 + ppuDataPut1: + // [56] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUDATA) ← (byte) ppuDataFill::val#4 -- _deref_pbuc1=vbuz1 + lda.z val + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUDATA + jmp __b2 + // ppuDataFill::@2 + __b2: + // [57] (word) ppuDataFill::i#1 ← ++ (word) ppuDataFill::i#2 -- vwuz1=_inc_vwuz1 + inc.z i + bne !+ + inc.z i+1 + !: + // [53] phi from ppuDataFill::@2 to ppuDataFill::@1 [phi:ppuDataFill::@2->ppuDataFill::@1] + __b1_from___b2: + // [53] phi (word) ppuDataFill::i#2 = (word) ppuDataFill::i#1 [phi:ppuDataFill::@2->ppuDataFill::@1#0] -- register_copy + jmp __b1 +} + // ppuDataTransfer +// Transfer a number of bytes from the CPU memory to the PPU memory +// - cpuData : Pointer to the CPU memory (RAM of ROM) +// - ppuData : Pointer in the PPU memory +// - size : The number of bytes to transfer +ppuDataTransfer: { + .const size = $20*SIZEOF_BYTE + .label ppuData = PPU_PALETTE + .label cpuData = PALETTE + .label ppuDataPut1_val = $19 + // Transfer to PPU + .label cpuSrc = $d + .label i = $b + jmp ppuDataPrepare1 + // ppuDataTransfer::ppuDataPrepare1 + ppuDataPrepare1: + // [59] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← >(const nomodify void*) ppuDataTransfer::ppuData#0 -- _deref_pbuc1=vbuc2 + lda #>ppuData + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUADDR + // [60] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← (byte) 0 -- _deref_pbuc1=vbuc2 + lda #0 + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUADDR + // [61] phi from ppuDataTransfer::ppuDataPrepare1 to ppuDataTransfer::@1 [phi:ppuDataTransfer::ppuDataPrepare1->ppuDataTransfer::@1] + __b1_from_ppuDataPrepare1: + // [61] phi (byte*) ppuDataTransfer::cpuSrc#2 = (byte*)(const nomodify void*) ppuDataTransfer::cpuData#0 [phi:ppuDataTransfer::ppuDataPrepare1->ppuDataTransfer::@1#0] -- pbuz1=pbuc1 + lda #cpuData + sta.z cpuSrc+1 + // [61] phi (word) ppuDataTransfer::i#2 = (word) 0 [phi:ppuDataTransfer::ppuDataPrepare1->ppuDataTransfer::@1#1] -- vwuz1=vwuc1 + lda #<0 + sta.z i + lda #>0 + sta.z i+1 + jmp __b1 + // ppuDataTransfer::@1 + __b1: + // [62] if((word) ppuDataTransfer::i#2<(const word) ppuDataTransfer::size#0) goto ppuDataTransfer::@2 -- vwuz1_lt_vwuc1_then_la1 + lda.z i+1 + cmp #>size + bcc __b2 + bne !+ + lda.z i + cmp #ppuDataTransfer::@1] + __b1_from___b3: + // [61] phi (byte*) ppuDataTransfer::cpuSrc#2 = (byte*) ppuDataTransfer::cpuSrc#1 [phi:ppuDataTransfer::@3->ppuDataTransfer::@1#0] -- register_copy + // [61] phi (word) ppuDataTransfer::i#2 = (word) ppuDataTransfer::i#1 [phi:ppuDataTransfer::@3->ppuDataTransfer::@1#1] -- register_copy + jmp __b1 +} + // vblank +// NMI Called when the PPU refreshes the screen (also known as the V-Blank period) +vblank: { + .label __2 = $1b + .label __4 = $1a + .label y_idx = $10 + .label x_idx = $11 + .label s = $f + // entry interrupt(HARDWARE_STACK) + pha + txa + pha + tya + pha + // [68] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSCROLL) ← (byte) 0 -- _deref_pbuc1=vbuc2 + // Set scroll + lda #0 + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUSCROLL + // [69] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSCROLL) ← (byte) 0 -- _deref_pbuc1=vbuc2 + lda #0 + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUSCROLL + jmp ppuSpriteBufferDmaTransfer1 + // vblank::ppuSpriteBufferDmaTransfer1 + ppuSpriteBufferDmaTransfer1: + // [70] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_OAMADDR) ← (byte) 0 -- _deref_pbuc1=vbuc2 + lda #0 + sta PPU+OFFSET_STRUCT_RICOH_2C02_OAMADDR + // [71] *((byte*)(const struct RICOH_2A03*) APU+(const byte) OFFSET_STRUCT_RICOH_2A03_OAMDMA) ← >(const struct SpriteData*) SPRITE_BUFFER -- _deref_pbuc1=vbuc2 + lda #>SPRITE_BUFFER + sta APU+OFFSET_STRUCT_RICOH_2A03_OAMDMA + jmp __b3 + // vblank::@3 + __b3: + // [72] (byte) vblank::y_idx#0 ← (volatile byte) y_sin_idx -- vbuz1=vbuz2 + // Update sprite positions + lda.z y_sin_idx + sta.z y_idx + // [73] (volatile byte) y_sin_idx ← ++ (volatile byte) y_sin_idx -- vbuz1=_inc_vbuz1 + inc.z y_sin_idx + // [74] (byte) vblank::x_idx#0 ← (volatile byte) x_sin_idx -- vbuz1=vbuz2 + lda.z x_sin_idx + sta.z x_idx + // [75] (volatile byte) x_sin_idx ← ++ (volatile byte) x_sin_idx -- vbuz1=_inc_vbuz1 + inc.z x_sin_idx + // [76] phi from vblank::@3 to vblank::@1 [phi:vblank::@3->vblank::@1] + __b1_from___b3: + // [76] phi (byte) vblank::x_idx#2 = (byte) vblank::x_idx#0 [phi:vblank::@3->vblank::@1#0] -- register_copy + // [76] phi (byte) vblank::y_idx#2 = (byte) vblank::y_idx#0 [phi:vblank::@3->vblank::@1#1] -- register_copy + // [76] phi (byte) vblank::s#2 = (byte) 0 [phi:vblank::@3->vblank::@1#2] -- vbuz1=vbuc1 + lda #0 + sta.z s + jmp __b1 + // vblank::@1 + __b1: + // [77] if((byte) vblank::s#2<(byte) $40) goto vblank::@2 -- vbuz1_lt_vbuc1_then_la1 + lda.z s + cmp #$40 + bcc __b2 + jmp __breturn + // vblank::@return + __breturn: + // [78] return - exit interrupt(HARDWARE_STACK) + pla + tay + pla + tax + pla + rti + // vblank::@2 + __b2: + // [79] (byte~) vblank::$4 ← (byte) vblank::s#2 << (byte) 2 -- vbuz1=vbuz2_rol_2 + lda.z s + asl + asl + sta.z __4 + // [80] *((byte*)(const struct SpriteData*) SPRITE_BUFFER + (byte~) vblank::$4) ← *((const to_nomodify byte*) SINTABLE + (byte) vblank::y_idx#2) -- pbuc1_derefidx_vbuz1=pbuc2_derefidx_vbuz2 + ldy.z y_idx + lda SINTABLE,y + ldy.z __4 + sta SPRITE_BUFFER,y + // [81] (byte~) vblank::$2 ← *((const to_nomodify byte*) SINTABLE + (byte) vblank::x_idx#2) + (byte) 8 -- vbuz1=pbuc1_derefidx_vbuz2_plus_vbuc2 + lda #8 + ldy.z x_idx + clc + adc SINTABLE,y + sta.z __2 + // [82] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_X + (byte~) vblank::$4) ← (byte~) vblank::$2 -- pbuc1_derefidx_vbuz1=vbuz2 + lda.z __2 + ldy.z __4 + sta SPRITE_BUFFER+OFFSET_STRUCT_SPRITEDATA_X,y + // [83] (byte) vblank::y_idx#1 ← (byte) vblank::y_idx#2 + (byte) 4 -- vbuz1=vbuz1_plus_vbuc1 + lda #4 + clc + adc.z y_idx + sta.z y_idx + // [84] (byte) vblank::x_idx#1 ← (byte) vblank::x_idx#2 - (byte) 7 -- vbuz1=vbuz1_minus_vbuc1 + lda.z x_idx + sec + sbc #7 + sta.z x_idx + // [85] (byte) vblank::s#1 ← ++ (byte) vblank::s#2 -- vbuz1=_inc_vbuz1 + inc.z s + // [76] phi from vblank::@2 to vblank::@1 [phi:vblank::@2->vblank::@1] + __b1_from___b2: + // [76] phi (byte) vblank::x_idx#2 = (byte) vblank::x_idx#1 [phi:vblank::@2->vblank::@1#0] -- register_copy + // [76] phi (byte) vblank::y_idx#2 = (byte) vblank::y_idx#1 [phi:vblank::@2->vblank::@1#1] -- register_copy + // [76] phi (byte) vblank::s#2 = (byte) vblank::s#1 [phi:vblank::@2->vblank::@1#2] -- register_copy + jmp __b1 +} + // File Data +.segment Data + // The DXYCP message 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef + MESSAGE: .text "rex-of-camelot-presents-a-dxycp-on-nintendo-entertainment-system" + // Color Palette + PALETTE: .byte 1, $21, $f, $30, 1, $21, $f, $30, 1, $21, $f, $30, 1, $21, $f, $30, 1, $f, $30, 8, 1, $f, $18, 8, 1, $30, $37, $1a, $f, $f, $f, $f + // Sinus Table (0-239) +SINTABLE: +.fill $100, round(115.5+107.5*sin(2*PI*i/256)) + +.segment Tiles +TILES: +.var filechargen = LoadBinary("characters.901225-01.bin") + .for(var c=0; c<256; c++) { + // Plane 0 + .fill 8, filechargen.get(c*8+i) + // Plane 1 + .fill 8, 0 + } + +.segment GameRam + .align $100 + SPRITE_BUFFER: .fill 4*$100, 0 +.segment Vectors + VECTORS: .word vblank, main, 0 + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [1] (volatile byte) y_sin_idx ← (byte) 0 [ ] ( [ ] { } ) always clobbers reg byte a +Statement [2] (volatile byte) x_sin_idx ← (byte) $49 [ ] ( [ ] { } ) always clobbers reg byte a +Statement asm { cld ldx#$ff txs } always clobbers reg byte x +Statement [8] *((byte*)(const struct RICOH_2C02*) PPU) ← (byte) 0 [ ] ( [ ] { } main:4 [ ] { } ) always clobbers reg byte a +Statement [9] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUMASK) ← (byte) 0 [ ] ( [ ] { } main:4 [ ] { } ) always clobbers reg byte a +Statement [10] *((const nomodify byte*) FR_COUNTER) ← (byte) $40 [ ] ( [ ] { } main:4 [ ] { } ) always clobbers reg byte a +Statement [11] *((byte*)(const struct RICOH_2A03*) APU+(const byte) OFFSET_STRUCT_RICOH_2A03_DMC_FREQ) ← (byte) $40 [ ] ( [ ] { } main:4 [ ] { } ) always clobbers reg byte a +Statement asm { ldaPPU_PPUSTATUS } always clobbers reg byte a +Statement [14] (byte~) main::initNES1_waitForVBlank1_$0 ← *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSTATUS) & (byte) $80 [ main::initNES1_waitForVBlank1_$0 ] ( [ main::initNES1_waitForVBlank1_$0 ] { } main:4 [ main::initNES1_waitForVBlank1_$0 ] { } ) always clobbers reg byte a +Statement [17] *((const nomodify byte*) MEMORY + (byte) main::initNES1_i#2) ← (byte) 0 [ main::initNES1_i#2 ] ( [ main::initNES1_i#2 ] { } main:4 [ main::initNES1_i#2 ] { } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::initNES1_i#2 main::initNES1_i#1 ] +Statement [18] *((const nomodify byte*) MEMORY+(word) $100 + (byte) main::initNES1_i#2) ← (byte) 0 [ main::initNES1_i#2 ] ( [ main::initNES1_i#2 ] { } main:4 [ main::initNES1_i#2 ] { } ) always clobbers reg byte a +Statement [19] *((const nomodify byte*) MEMORY+(word) $200 + (byte) main::initNES1_i#2) ← (byte) 0 [ main::initNES1_i#2 ] ( [ main::initNES1_i#2 ] { } main:4 [ main::initNES1_i#2 ] { } ) always clobbers reg byte a +Statement [20] *((const nomodify byte*) MEMORY+(word) $300 + (byte) main::initNES1_i#2) ← (byte) 0 [ main::initNES1_i#2 ] ( [ main::initNES1_i#2 ] { } main:4 [ main::initNES1_i#2 ] { } ) always clobbers reg byte a +Statement [21] *((const nomodify byte*) MEMORY+(word) $400 + (byte) main::initNES1_i#2) ← (byte) 0 [ main::initNES1_i#2 ] ( [ main::initNES1_i#2 ] { } main:4 [ main::initNES1_i#2 ] { } ) always clobbers reg byte a +Statement [22] *((const nomodify byte*) MEMORY+(word) $500 + (byte) main::initNES1_i#2) ← (byte) 0 [ main::initNES1_i#2 ] ( [ main::initNES1_i#2 ] { } main:4 [ main::initNES1_i#2 ] { } ) always clobbers reg byte a +Statement [23] *((const nomodify byte*) MEMORY+(word) $600 + (byte) main::initNES1_i#2) ← (byte) 0 [ main::initNES1_i#2 ] ( [ main::initNES1_i#2 ] { } main:4 [ main::initNES1_i#2 ] { } ) always clobbers reg byte a +Statement [24] *((const nomodify byte*) MEMORY+(word) $700 + (byte) main::initNES1_i#2) ← (byte) 0 [ main::initNES1_i#2 ] ( [ main::initNES1_i#2 ] { } main:4 [ main::initNES1_i#2 ] { } ) always clobbers reg byte a +Statement [28] (byte~) main::initNES1_waitForVBlank2_$0 ← *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSTATUS) & (byte) $80 [ main::initNES1_waitForVBlank2_$0 ] ( [ main::initNES1_waitForVBlank2_$0 ] { } main:4 [ main::initNES1_waitForVBlank2_$0 ] { } ) always clobbers reg byte a +Statement asm { ldaPPU_PPUSTATUS } always clobbers reg byte a +Statement [39] *((byte*)(const struct RICOH_2C02*) PPU) ← (byte) $80 [ ] ( [ ] { } main:4 [ ] { } ) always clobbers reg byte a +Statement [40] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUMASK) ← (byte) $1e [ ] ( [ ] { } main:4 [ ] { } ) always clobbers reg byte a +Statement [42] (byte~) main::$7 ← (byte) main::s#2 << (byte) 2 [ main::s#2 main::$7 ] ( [ main::s#2 main::$7 ] { } main:4 [ main::s#2 main::$7 ] { } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:3 [ main::s#2 main::s#1 ] +Statement [43] *((byte*)(const struct SpriteData*) SPRITE_BUFFER + (byte~) main::$7) ← (byte) 0 [ main::s#2 main::$7 ] ( [ main::s#2 main::$7 ] { } main:4 [ main::s#2 main::$7 ] { } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:22 [ main::$7 ] +Statement [44] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_TILE + (byte~) main::$7) ← *((const byte*) MESSAGE + (byte) main::s#2) [ main::s#2 main::$7 ] ( [ main::s#2 main::$7 ] { } main:4 [ main::s#2 main::$7 ] { } ) always clobbers reg byte a +Statement [45] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_ATTRIBUTES + (byte~) main::$7) ← (byte) 2 [ main::s#2 main::$7 ] ( [ main::s#2 main::$7 ] { } main:4 [ main::s#2 main::$7 ] { } ) always clobbers reg byte a +Statement [46] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_X + (byte~) main::$7) ← (byte) 0 [ main::s#2 ] ( [ main::s#2 ] { } main:4 [ main::s#2 ] { } ) always clobbers reg byte a +Statement [54] if((word) ppuDataFill::i#2<(word) ppuDataFill::size#3) goto ppuDataFill::ppuDataPut1 [ ppuDataFill::size#3 ppuDataFill::val#4 ppuDataFill::i#2 ] ( ppuDataFill:34 [ ppuDataFill::size#3 ppuDataFill::val#4 ppuDataFill::i#2 ] { } main:4::ppuDataFill:34 [ ppuDataFill::size#3 ppuDataFill::val#4 ppuDataFill::i#2 ] { } ppuDataFill:36 [ ppuDataFill::size#3 ppuDataFill::val#4 ppuDataFill::i#2 ] { } main:4::ppuDataFill:36 [ ppuDataFill::size#3 ppuDataFill::val#4 ppuDataFill::i#2 ] { } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:8 [ ppuDataFill::val#4 ] +Statement [59] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← >(const nomodify void*) ppuDataTransfer::ppuData#0 [ ] ( ppuDataTransfer:32 [ ] { } main:4::ppuDataTransfer:32 [ ] { } ) always clobbers reg byte a +Statement [60] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← (byte) 0 [ ] ( ppuDataTransfer:32 [ ] { } main:4::ppuDataTransfer:32 [ ] { } ) always clobbers reg byte a +Statement [62] if((word) ppuDataTransfer::i#2<(const word) ppuDataTransfer::size#0) goto ppuDataTransfer::@2 [ ppuDataTransfer::i#2 ppuDataTransfer::cpuSrc#2 ] ( ppuDataTransfer:32 [ ppuDataTransfer::i#2 ppuDataTransfer::cpuSrc#2 ] { } main:4::ppuDataTransfer:32 [ ppuDataTransfer::i#2 ppuDataTransfer::cpuSrc#2 ] { } ) always clobbers reg byte a +Statement [64] (byte) ppuDataTransfer::ppuDataPut1_val#0 ← *((byte*) ppuDataTransfer::cpuSrc#2) [ ppuDataTransfer::i#2 ppuDataTransfer::cpuSrc#2 ppuDataTransfer::ppuDataPut1_val#0 ] ( ppuDataTransfer:32 [ ppuDataTransfer::i#2 ppuDataTransfer::cpuSrc#2 ppuDataTransfer::ppuDataPut1_val#0 ] { } main:4::ppuDataTransfer:32 [ ppuDataTransfer::i#2 ppuDataTransfer::cpuSrc#2 ppuDataTransfer::ppuDataPut1_val#0 ] { } ) always clobbers reg byte a reg byte y +Statement [68] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSCROLL) ← (byte) 0 [ y_sin_idx x_sin_idx ] ( [ y_sin_idx x_sin_idx ] { } ) always clobbers reg byte a +Statement [69] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSCROLL) ← (byte) 0 [ y_sin_idx x_sin_idx ] ( [ y_sin_idx x_sin_idx ] { } ) always clobbers reg byte a +Statement [70] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_OAMADDR) ← (byte) 0 [ y_sin_idx x_sin_idx ] ( [ y_sin_idx x_sin_idx ] { } ) always clobbers reg byte a +Statement [71] *((byte*)(const struct RICOH_2A03*) APU+(const byte) OFFSET_STRUCT_RICOH_2A03_OAMDMA) ← >(const struct SpriteData*) SPRITE_BUFFER [ y_sin_idx x_sin_idx ] ( [ y_sin_idx x_sin_idx ] { } ) always clobbers reg byte a +Statement [78] return [ ] ( [ ] { } ) always clobbers reg byte a reg byte x reg byte y +Statement [79] (byte~) vblank::$4 ← (byte) vblank::s#2 << (byte) 2 [ vblank::s#2 vblank::y_idx#2 vblank::x_idx#2 vblank::$4 ] ( [ vblank::s#2 vblank::y_idx#2 vblank::x_idx#2 vblank::$4 ] { } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:15 [ vblank::s#2 vblank::s#1 ] +Removing always clobbered register reg byte a as potential for zp[1]:16 [ vblank::y_idx#2 vblank::y_idx#1 vblank::y_idx#0 ] +Removing always clobbered register reg byte a as potential for zp[1]:17 [ vblank::x_idx#2 vblank::x_idx#1 vblank::x_idx#0 ] +Statement [80] *((byte*)(const struct SpriteData*) SPRITE_BUFFER + (byte~) vblank::$4) ← *((const to_nomodify byte*) SINTABLE + (byte) vblank::y_idx#2) [ vblank::s#2 vblank::y_idx#2 vblank::x_idx#2 vblank::$4 ] ( [ vblank::s#2 vblank::y_idx#2 vblank::x_idx#2 vblank::$4 ] { } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:26 [ vblank::$4 ] +Statement [81] (byte~) vblank::$2 ← *((const to_nomodify byte*) SINTABLE + (byte) vblank::x_idx#2) + (byte) 8 [ vblank::s#2 vblank::y_idx#2 vblank::x_idx#2 vblank::$4 vblank::$2 ] ( [ vblank::s#2 vblank::y_idx#2 vblank::x_idx#2 vblank::$4 vblank::$2 ] { } ) always clobbers reg byte a +Statement [83] (byte) vblank::y_idx#1 ← (byte) vblank::y_idx#2 + (byte) 4 [ vblank::s#2 vblank::x_idx#2 vblank::y_idx#1 ] ( [ vblank::s#2 vblank::x_idx#2 vblank::y_idx#1 ] { } ) always clobbers reg byte a +Statement [84] (byte) vblank::x_idx#1 ← (byte) vblank::x_idx#2 - (byte) 7 [ vblank::s#2 vblank::y_idx#1 vblank::x_idx#1 ] ( [ vblank::s#2 vblank::y_idx#1 vblank::x_idx#1 ] { } ) always clobbers reg byte a +Statement [1] (volatile byte) y_sin_idx ← (byte) 0 [ ] ( [ ] { } ) always clobbers reg byte a +Statement [2] (volatile byte) x_sin_idx ← (byte) $49 [ ] ( [ ] { } ) always clobbers reg byte a +Statement asm { cld ldx#$ff txs } always clobbers reg byte x +Statement [8] *((byte*)(const struct RICOH_2C02*) PPU) ← (byte) 0 [ ] ( [ ] { } main:4 [ ] { } ) always clobbers reg byte a +Statement [9] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUMASK) ← (byte) 0 [ ] ( [ ] { } main:4 [ ] { } ) always clobbers reg byte a +Statement [10] *((const nomodify byte*) FR_COUNTER) ← (byte) $40 [ ] ( [ ] { } main:4 [ ] { } ) always clobbers reg byte a +Statement [11] *((byte*)(const struct RICOH_2A03*) APU+(const byte) OFFSET_STRUCT_RICOH_2A03_DMC_FREQ) ← (byte) $40 [ ] ( [ ] { } main:4 [ ] { } ) always clobbers reg byte a +Statement asm { ldaPPU_PPUSTATUS } always clobbers reg byte a +Statement [14] (byte~) main::initNES1_waitForVBlank1_$0 ← *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSTATUS) & (byte) $80 [ main::initNES1_waitForVBlank1_$0 ] ( [ main::initNES1_waitForVBlank1_$0 ] { } main:4 [ main::initNES1_waitForVBlank1_$0 ] { } ) always clobbers reg byte a +Statement [17] *((const nomodify byte*) MEMORY + (byte) main::initNES1_i#2) ← (byte) 0 [ main::initNES1_i#2 ] ( [ main::initNES1_i#2 ] { } main:4 [ main::initNES1_i#2 ] { } ) always clobbers reg byte a +Statement [18] *((const nomodify byte*) MEMORY+(word) $100 + (byte) main::initNES1_i#2) ← (byte) 0 [ main::initNES1_i#2 ] ( [ main::initNES1_i#2 ] { } main:4 [ main::initNES1_i#2 ] { } ) always clobbers reg byte a +Statement [19] *((const nomodify byte*) MEMORY+(word) $200 + (byte) main::initNES1_i#2) ← (byte) 0 [ main::initNES1_i#2 ] ( [ main::initNES1_i#2 ] { } main:4 [ main::initNES1_i#2 ] { } ) always clobbers reg byte a +Statement [20] *((const nomodify byte*) MEMORY+(word) $300 + (byte) main::initNES1_i#2) ← (byte) 0 [ main::initNES1_i#2 ] ( [ main::initNES1_i#2 ] { } main:4 [ main::initNES1_i#2 ] { } ) always clobbers reg byte a +Statement [21] *((const nomodify byte*) MEMORY+(word) $400 + (byte) main::initNES1_i#2) ← (byte) 0 [ main::initNES1_i#2 ] ( [ main::initNES1_i#2 ] { } main:4 [ main::initNES1_i#2 ] { } ) always clobbers reg byte a +Statement [22] *((const nomodify byte*) MEMORY+(word) $500 + (byte) main::initNES1_i#2) ← (byte) 0 [ main::initNES1_i#2 ] ( [ main::initNES1_i#2 ] { } main:4 [ main::initNES1_i#2 ] { } ) always clobbers reg byte a +Statement [23] *((const nomodify byte*) MEMORY+(word) $600 + (byte) main::initNES1_i#2) ← (byte) 0 [ main::initNES1_i#2 ] ( [ main::initNES1_i#2 ] { } main:4 [ main::initNES1_i#2 ] { } ) always clobbers reg byte a +Statement [24] *((const nomodify byte*) MEMORY+(word) $700 + (byte) main::initNES1_i#2) ← (byte) 0 [ main::initNES1_i#2 ] ( [ main::initNES1_i#2 ] { } main:4 [ main::initNES1_i#2 ] { } ) always clobbers reg byte a +Statement [28] (byte~) main::initNES1_waitForVBlank2_$0 ← *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSTATUS) & (byte) $80 [ main::initNES1_waitForVBlank2_$0 ] ( [ main::initNES1_waitForVBlank2_$0 ] { } main:4 [ main::initNES1_waitForVBlank2_$0 ] { } ) always clobbers reg byte a +Statement asm { ldaPPU_PPUSTATUS } always clobbers reg byte a +Statement [39] *((byte*)(const struct RICOH_2C02*) PPU) ← (byte) $80 [ ] ( [ ] { } main:4 [ ] { } ) always clobbers reg byte a +Statement [40] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUMASK) ← (byte) $1e [ ] ( [ ] { } main:4 [ ] { } ) always clobbers reg byte a +Statement [42] (byte~) main::$7 ← (byte) main::s#2 << (byte) 2 [ main::s#2 main::$7 ] ( [ main::s#2 main::$7 ] { } main:4 [ main::s#2 main::$7 ] { } ) always clobbers reg byte a +Statement [43] *((byte*)(const struct SpriteData*) SPRITE_BUFFER + (byte~) main::$7) ← (byte) 0 [ main::s#2 main::$7 ] ( [ main::s#2 main::$7 ] { } main:4 [ main::s#2 main::$7 ] { } ) always clobbers reg byte a +Statement [44] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_TILE + (byte~) main::$7) ← *((const byte*) MESSAGE + (byte) main::s#2) [ main::s#2 main::$7 ] ( [ main::s#2 main::$7 ] { } main:4 [ main::s#2 main::$7 ] { } ) always clobbers reg byte a +Statement [45] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_ATTRIBUTES + (byte~) main::$7) ← (byte) 2 [ main::s#2 main::$7 ] ( [ main::s#2 main::$7 ] { } main:4 [ main::s#2 main::$7 ] { } ) always clobbers reg byte a +Statement [46] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_X + (byte~) main::$7) ← (byte) 0 [ main::s#2 ] ( [ main::s#2 ] { } main:4 [ main::s#2 ] { } ) always clobbers reg byte a +Statement [54] if((word) ppuDataFill::i#2<(word) ppuDataFill::size#3) goto ppuDataFill::ppuDataPut1 [ ppuDataFill::size#3 ppuDataFill::val#4 ppuDataFill::i#2 ] ( ppuDataFill:34 [ ppuDataFill::size#3 ppuDataFill::val#4 ppuDataFill::i#2 ] { } main:4::ppuDataFill:34 [ ppuDataFill::size#3 ppuDataFill::val#4 ppuDataFill::i#2 ] { } ppuDataFill:36 [ ppuDataFill::size#3 ppuDataFill::val#4 ppuDataFill::i#2 ] { } main:4::ppuDataFill:36 [ ppuDataFill::size#3 ppuDataFill::val#4 ppuDataFill::i#2 ] { } ) always clobbers reg byte a +Statement [59] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← >(const nomodify void*) ppuDataTransfer::ppuData#0 [ ] ( ppuDataTransfer:32 [ ] { } main:4::ppuDataTransfer:32 [ ] { } ) always clobbers reg byte a +Statement [60] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← (byte) 0 [ ] ( ppuDataTransfer:32 [ ] { } main:4::ppuDataTransfer:32 [ ] { } ) always clobbers reg byte a +Statement [62] if((word) ppuDataTransfer::i#2<(const word) ppuDataTransfer::size#0) goto ppuDataTransfer::@2 [ ppuDataTransfer::i#2 ppuDataTransfer::cpuSrc#2 ] ( ppuDataTransfer:32 [ ppuDataTransfer::i#2 ppuDataTransfer::cpuSrc#2 ] { } main:4::ppuDataTransfer:32 [ ppuDataTransfer::i#2 ppuDataTransfer::cpuSrc#2 ] { } ) always clobbers reg byte a +Statement [64] (byte) ppuDataTransfer::ppuDataPut1_val#0 ← *((byte*) ppuDataTransfer::cpuSrc#2) [ ppuDataTransfer::i#2 ppuDataTransfer::cpuSrc#2 ppuDataTransfer::ppuDataPut1_val#0 ] ( ppuDataTransfer:32 [ ppuDataTransfer::i#2 ppuDataTransfer::cpuSrc#2 ppuDataTransfer::ppuDataPut1_val#0 ] { } main:4::ppuDataTransfer:32 [ ppuDataTransfer::i#2 ppuDataTransfer::cpuSrc#2 ppuDataTransfer::ppuDataPut1_val#0 ] { } ) always clobbers reg byte a reg byte y +Statement [68] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSCROLL) ← (byte) 0 [ y_sin_idx x_sin_idx ] ( [ y_sin_idx x_sin_idx ] { } ) always clobbers reg byte a +Statement [69] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSCROLL) ← (byte) 0 [ y_sin_idx x_sin_idx ] ( [ y_sin_idx x_sin_idx ] { } ) always clobbers reg byte a +Statement [70] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_OAMADDR) ← (byte) 0 [ y_sin_idx x_sin_idx ] ( [ y_sin_idx x_sin_idx ] { } ) always clobbers reg byte a +Statement [71] *((byte*)(const struct RICOH_2A03*) APU+(const byte) OFFSET_STRUCT_RICOH_2A03_OAMDMA) ← >(const struct SpriteData*) SPRITE_BUFFER [ y_sin_idx x_sin_idx ] ( [ y_sin_idx x_sin_idx ] { } ) always clobbers reg byte a +Statement [78] return [ ] ( [ ] { } ) always clobbers reg byte a reg byte x reg byte y +Statement [79] (byte~) vblank::$4 ← (byte) vblank::s#2 << (byte) 2 [ vblank::s#2 vblank::y_idx#2 vblank::x_idx#2 vblank::$4 ] ( [ vblank::s#2 vblank::y_idx#2 vblank::x_idx#2 vblank::$4 ] { } ) always clobbers reg byte a +Statement [80] *((byte*)(const struct SpriteData*) SPRITE_BUFFER + (byte~) vblank::$4) ← *((const to_nomodify byte*) SINTABLE + (byte) vblank::y_idx#2) [ vblank::s#2 vblank::y_idx#2 vblank::x_idx#2 vblank::$4 ] ( [ vblank::s#2 vblank::y_idx#2 vblank::x_idx#2 vblank::$4 ] { } ) always clobbers reg byte a +Statement [81] (byte~) vblank::$2 ← *((const to_nomodify byte*) SINTABLE + (byte) vblank::x_idx#2) + (byte) 8 [ vblank::s#2 vblank::y_idx#2 vblank::x_idx#2 vblank::$4 vblank::$2 ] ( [ vblank::s#2 vblank::y_idx#2 vblank::x_idx#2 vblank::$4 vblank::$2 ] { } ) always clobbers reg byte a +Statement [83] (byte) vblank::y_idx#1 ← (byte) vblank::y_idx#2 + (byte) 4 [ vblank::s#2 vblank::x_idx#2 vblank::y_idx#1 ] ( [ vblank::s#2 vblank::x_idx#2 vblank::y_idx#1 ] { } ) always clobbers reg byte a +Statement [84] (byte) vblank::x_idx#1 ← (byte) vblank::x_idx#2 - (byte) 7 [ vblank::s#2 vblank::y_idx#1 vblank::x_idx#1 ] ( [ vblank::s#2 vblank::y_idx#1 vblank::x_idx#1 ] { } ) always clobbers reg byte a +Potential registers zp[1]:2 [ main::initNES1_i#2 main::initNES1_i#1 ] : zp[1]:2 , reg byte x , reg byte y , +Potential registers zp[1]:3 [ main::s#2 main::s#1 ] : zp[1]:3 , reg byte x , reg byte y , +Potential registers zp[2]:4 [ ppuDataFill::ppuDataPrepare1_ppuData#0 ] : zp[2]:4 , +Potential registers zp[2]:6 [ ppuDataFill::size#3 ] : zp[2]:6 , +Potential registers zp[1]:8 [ ppuDataFill::val#4 ] : zp[1]:8 , reg byte x , reg byte y , +Potential registers zp[2]:9 [ ppuDataFill::i#2 ppuDataFill::i#1 ] : zp[2]:9 , +Potential registers zp[2]:11 [ ppuDataTransfer::i#2 ppuDataTransfer::i#1 ] : zp[2]:11 , +Potential registers zp[2]:13 [ ppuDataTransfer::cpuSrc#2 ppuDataTransfer::cpuSrc#1 ] : zp[2]:13 , +Potential registers zp[1]:15 [ vblank::s#2 vblank::s#1 ] : zp[1]:15 , reg byte x , reg byte y , +Potential registers zp[1]:16 [ vblank::y_idx#2 vblank::y_idx#1 vblank::y_idx#0 ] : zp[1]:16 , reg byte x , reg byte y , +Potential registers zp[1]:17 [ vblank::x_idx#2 vblank::x_idx#1 vblank::x_idx#0 ] : zp[1]:17 , reg byte x , reg byte y , +Potential registers zp[1]:18 [ y_sin_idx ] : zp[1]:18 , +Potential registers zp[1]:19 [ x_sin_idx ] : zp[1]:19 , +Potential registers zp[1]:20 [ main::initNES1_waitForVBlank1_$0 ] : zp[1]:20 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:21 [ main::initNES1_waitForVBlank2_$0 ] : zp[1]:21 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:22 [ main::$7 ] : zp[1]:22 , reg byte x , reg byte y , +Potential registers zp[1]:23 [ ppuDataFill::ppuDataPrepare1_$0 ] : zp[1]:23 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:24 [ ppuDataFill::ppuDataPrepare1_$1 ] : zp[1]:24 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:25 [ ppuDataTransfer::ppuDataPut1_val#0 ] : zp[1]:25 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:26 [ vblank::$4 ] : zp[1]:26 , reg byte x , reg byte y , +Potential registers zp[1]:27 [ vblank::$2 ] : zp[1]:27 , reg byte a , reg byte x , reg byte y , + +REGISTER UPLIFT SCOPES +Uplift Scope [ppuDataTransfer] 2,602.6: zp[2]:11 [ ppuDataTransfer::i#2 ppuDataTransfer::i#1 ] 2,002: zp[1]:25 [ ppuDataTransfer::ppuDataPut1_val#0 ] 1,751.75: zp[2]:13 [ ppuDataTransfer::cpuSrc#2 ppuDataTransfer::cpuSrc#1 ] +Uplift Scope [ppuDataFill] 3,003: zp[2]:9 [ ppuDataFill::i#2 ppuDataFill::i#1 ] 202: zp[1]:23 [ ppuDataFill::ppuDataPrepare1_$0 ] 202: zp[1]:24 [ ppuDataFill::ppuDataPrepare1_$1 ] 111.22: zp[2]:6 [ ppuDataFill::size#3 ] 111.22: zp[1]:8 [ ppuDataFill::val#4 ] 67.33: zp[2]:4 [ ppuDataFill::ppuDataPrepare1_ppuData#0 ] +Uplift Scope [main] 274.14: zp[1]:3 [ main::s#2 main::s#1 ] 263.72: zp[1]:2 [ main::initNES1_i#2 main::initNES1_i#1 ] 202: zp[1]:20 [ main::initNES1_waitForVBlank1_$0 ] 202: zp[1]:21 [ main::initNES1_waitForVBlank2_$0 ] 126.25: zp[1]:22 [ main::$7 ] +Uplift Scope [vblank] 27.5: zp[1]:15 [ vblank::s#2 vblank::s#1 ] 22: zp[1]:27 [ vblank::$2 ] 18: zp[1]:17 [ vblank::x_idx#2 vblank::x_idx#1 vblank::x_idx#0 ] 14.17: zp[1]:16 [ vblank::y_idx#2 vblank::y_idx#1 vblank::y_idx#0 ] 11: zp[1]:26 [ vblank::$4 ] +Uplift Scope [] 1.6: zp[1]:18 [ y_sin_idx ] 1.14: zp[1]:19 [ x_sin_idx ] +Uplift Scope [RICOH_2C02] +Uplift Scope [RICOH_2A03] +Uplift Scope [SpriteData] + +Uplifting [ppuDataTransfer] best 5348 combination zp[2]:11 [ ppuDataTransfer::i#2 ppuDataTransfer::i#1 ] reg byte a [ ppuDataTransfer::ppuDataPut1_val#0 ] zp[2]:13 [ ppuDataTransfer::cpuSrc#2 ppuDataTransfer::cpuSrc#1 ] +Uplifting [ppuDataFill] best 5300 combination zp[2]:9 [ ppuDataFill::i#2 ppuDataFill::i#1 ] reg byte a [ ppuDataFill::ppuDataPrepare1_$0 ] reg byte a [ ppuDataFill::ppuDataPrepare1_$1 ] zp[2]:6 [ ppuDataFill::size#3 ] reg byte x [ ppuDataFill::val#4 ] zp[2]:4 [ ppuDataFill::ppuDataPrepare1_ppuData#0 ] +Uplifting [main] best 4720 combination reg byte x [ main::s#2 main::s#1 ] reg byte x [ main::initNES1_i#2 main::initNES1_i#1 ] reg byte a [ main::initNES1_waitForVBlank1_$0 ] reg byte a [ main::initNES1_waitForVBlank2_$0 ] zp[1]:22 [ main::$7 ] +Limited combination testing to 100 combinations of 432 possible. +Uplifting [vblank] best 4560 combination reg byte x [ vblank::s#2 vblank::s#1 ] reg byte a [ vblank::$2 ] zp[1]:17 [ vblank::x_idx#2 vblank::x_idx#1 vblank::x_idx#0 ] zp[1]:16 [ vblank::y_idx#2 vblank::y_idx#1 vblank::y_idx#0 ] zp[1]:26 [ vblank::$4 ] +Limited combination testing to 100 combinations of 324 possible. +Uplifting [] best 4560 combination zp[1]:18 [ y_sin_idx ] zp[1]:19 [ x_sin_idx ] +Uplifting [RICOH_2C02] best 4560 combination +Uplifting [RICOH_2A03] best 4560 combination +Uplifting [SpriteData] best 4560 combination +Attempting to uplift remaining variables inzp[1]:22 [ main::$7 ] +Uplifting [main] best 4430 combination reg byte y [ main::$7 ] +Attempting to uplift remaining variables inzp[1]:17 [ vblank::x_idx#2 vblank::x_idx#1 vblank::x_idx#0 ] +Uplifting [vblank] best 4430 combination zp[1]:17 [ vblank::x_idx#2 vblank::x_idx#1 vblank::x_idx#0 ] +Attempting to uplift remaining variables inzp[1]:16 [ vblank::y_idx#2 vblank::y_idx#1 vblank::y_idx#0 ] +Uplifting [vblank] best 4430 combination zp[1]:16 [ vblank::y_idx#2 vblank::y_idx#1 vblank::y_idx#0 ] +Attempting to uplift remaining variables inzp[1]:26 [ vblank::$4 ] +Uplifting [vblank] best 4430 combination zp[1]:26 [ vblank::$4 ] +Attempting to uplift remaining variables inzp[1]:18 [ y_sin_idx ] +Uplifting [] best 4430 combination zp[1]:18 [ y_sin_idx ] +Attempting to uplift remaining variables inzp[1]:19 [ x_sin_idx ] +Uplifting [] best 4430 combination zp[1]:19 [ x_sin_idx ] +Coalescing zero page register [ zp[2]:11 [ ppuDataTransfer::i#2 ppuDataTransfer::i#1 ] ] with [ zp[2]:4 [ ppuDataFill::ppuDataPrepare1_ppuData#0 ] ] +Coalescing zero page register [ zp[2]:13 [ ppuDataTransfer::cpuSrc#2 ppuDataTransfer::cpuSrc#1 ] ] with [ zp[2]:6 [ ppuDataFill::size#3 ] ] +Allocated (was zp[2]:9) zp[2]:2 [ ppuDataFill::i#2 ppuDataFill::i#1 ] +Allocated (was zp[2]:11) zp[2]:4 [ ppuDataTransfer::i#2 ppuDataTransfer::i#1 ppuDataFill::ppuDataPrepare1_ppuData#0 ] +Allocated (was zp[2]:13) zp[2]:6 [ ppuDataTransfer::cpuSrc#2 ppuDataTransfer::cpuSrc#1 ppuDataFill::size#3 ] +Allocated (was zp[1]:16) zp[1]:8 [ vblank::y_idx#2 vblank::y_idx#1 vblank::y_idx#0 ] +Allocated (was zp[1]:17) zp[1]:9 [ vblank::x_idx#2 vblank::x_idx#1 vblank::x_idx#0 ] +Allocated (was zp[1]:18) zp[1]:10 [ y_sin_idx ] +Allocated (was zp[1]:19) zp[1]:11 [ x_sin_idx ] +Allocated (was zp[1]:26) zp[1]:12 [ vblank::$4 ] + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// NES DXYCP using sprites +// Nintendo Entertainment System (NES +// https://en.wikipedia.org/wiki/Nintendo_Entertainment_System_(Model_NES-101) +// https://github.com/gregkrsak/first_nes +// Ricoh 2C02 - NES Picture Processing Unit (PPU) +// Ricoh RP2C02 (NTSC version) / RP2C07 (PAL version), +// https://en.wikipedia.org/wiki/Picture_Processing_Unit +// https://wiki.nesdev.com/w/index.php/PPU_registers +// http://nesdev.com/2C02%20technical%20reference.TXT +// Based on: https://github.com/gregkrsak/first_nes written by Greg M. Krsak, 2018. + // Upstart + // Nintendo Entertainment System (NES) ROM +// https://sadistech.com/nesromtool/romdoc.html +// https://forums.nesdev.com/viewtopic.php?f=2&t=9896 +// https://github.com/gregkrsak/first_nes +.file [name="nes-dxycp.nes", type="bin", segments="NesRom"] +.file [name="nes-dxycp.nes_hdr", type="bin", segments="Header"] +.file [name="nes-dxycp.nes_prg", type="bin", segments="ProgramRom"] +.file [name="nes-dxycp.nes_chr", type="bin", segments="CharacterRom"] +.segmentdef Header [ start=$0000, min=$0000, max=$000f, fill ] +.segmentdef Tiles [ start=$0000, min=$0000, max=$1fff, fill ] +.segmentdef Code [ start=$c000, min=$c000, max=$fff9 ] +.segmentdef Data [ startAfter="Code", min=$c000, max=$fff9 ] +.segmentdef Vectors [ start=$fffa, min=$fffa, max=$ffff ] +.segmentdef GameRam [start=$200,max=$7ff, virtual] +.segmentdef ProgramRom [ segments="Code, Data, Vectors" ] +.segmentdef CharacterRom [ segments="Tiles" ] +.segmentdef NesRom +.segment NesRom +.segmentout [ segments="Header" ] +.segmentout [ segments="ProgramRom" ] +.segmentout [ segments="CharacterRom" ] +.segment Header +.text @"NES\$1a" +.byte $01 // 1x 16KB ROM (PRG) +.byte $01 // 1x 8KB VROM (CHR) +.byte %00000001 // Mapper nibble 0000 == No mapping (a simple 16KB PRG + 8KB CHR game) + // Mirroring nibble 0001 == Vertical mirroring only +.segment Code + + // Global Constants & labels + .const OFFSET_STRUCT_SPRITEDATA_TILE = 1 + .const OFFSET_STRUCT_SPRITEDATA_ATTRIBUTES = 2 + .const OFFSET_STRUCT_SPRITEDATA_X = 3 + .const OFFSET_STRUCT_RICOH_2A03_DMC_FREQ = $10 + .const OFFSET_STRUCT_RICOH_2C02_PPUMASK = 1 + .const OFFSET_STRUCT_RICOH_2C02_PPUSTATUS = 2 + .const OFFSET_STRUCT_RICOH_2C02_OAMADDR = 3 + .const OFFSET_STRUCT_RICOH_2A03_OAMDMA = $14 + .const OFFSET_STRUCT_RICOH_2C02_PPUADDR = 6 + .const OFFSET_STRUCT_RICOH_2C02_PPUDATA = 7 + .const OFFSET_STRUCT_RICOH_2C02_PPUSCROLL = 5 + .const SIZEOF_BYTE = 1 + // $2000-$23bf $03c0 Name table 0 + .label PPU_NAME_TABLE_0 = $2000 + // $23c0-$23ff $0040 Attribute table 0 + .label PPU_ATTRIBUTE_TABLE_0 = $23c0 + // $3000-$3eff $0f00 Mirrors of $2000-$2eff + // $3f00-$3f1f $0020 Palette RAM indexes + .label PPU_PALETTE = $3f00 + // PPU Status Register for reading in ASM + .label PPU_PPUSTATUS = $2002 + // APU Frame Counter + // generates low-frequency clocks for the channels and an optional 60 Hz interrupt. + // https://wiki.nesdev.com/w/index.php/APU_Frame_Counter + // ------+-----+--------------------------------------------------------------- + // $4017 | W | FR_COUNTER Frame Counter Set mode and interrupt + // ------+-----+--------------------------------------------------------------- + // | 7 | Sequencer mode: 0 selects 4-step sequence, 1 selects 5-step sequence + // | 6 | Interrupt inhibit flag. If set, the frame interrupt flag is cleared, otherwise it is unaffected. + // ------+-----+--------------------------------------------------------------- + // Side effects After 3 or 4 CPU clock cycles*, the timer is reset. + // If the mode flag is set, then both "quarter frame" and "half frame" signals are also generated. + .label FR_COUNTER = $4017 + // Pointer to the start of RAM memory + .label MEMORY = 0 + // NES Picture Processing Unit (PPU) + .label PPU = $2000 + // NES CPU and audion processing unit (APU) + .label APU = $4000 + .label y_sin_idx = $a + .label x_sin_idx = $b + // @begin +__bbegin: + jmp __b1 + // @1 +__b1: + // [1] (volatile byte) y_sin_idx ← (byte) 0 -- vbuz1=vbuc1 + // Index into the Y sine + lda #0 + sta.z y_sin_idx + // [2] (volatile byte) x_sin_idx ← (byte) $49 -- vbuz1=vbuc1 + // Index into the X sine + lda #$49 + sta.z x_sin_idx + // [3] phi from @1 to @2 [phi:@1->@2] +__b2_from___b1: + jmp __b2 + // @2 +__b2: + // [4] call main + // [6] phi from @2 to main [phi:@2->main] +main_from___b2: + jsr main + // [5] phi from @2 to @end [phi:@2->@end] +__bend_from___b2: + jmp __bend + // @end +__bend: +.segment Code + // main +// RESET Called when the NES is reset, including when it is turned on. +main: { + jmp initNES1 + // main::initNES1 + initNES1: + // asm { cld ldx#$ff txs } + cld + ldx #$ff + txs + jmp initNES1_disableVideoOutput1 + // main::initNES1_disableVideoOutput1 + initNES1_disableVideoOutput1: + // [8] *((byte*)(const struct RICOH_2C02*) PPU) ← (byte) 0 -- _deref_pbuc1=vbuc2 + lda #0 + sta PPU + // [9] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUMASK) ← (byte) 0 -- _deref_pbuc1=vbuc2 + lda #0 + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUMASK + jmp initNES1_disableAudioOutput1 + // main::initNES1_disableAudioOutput1 + initNES1_disableAudioOutput1: + // [10] *((const nomodify byte*) FR_COUNTER) ← (byte) $40 -- _deref_pbuc1=vbuc2 + lda #$40 + sta FR_COUNTER + // [11] *((byte*)(const struct RICOH_2A03*) APU+(const byte) OFFSET_STRUCT_RICOH_2A03_DMC_FREQ) ← (byte) $40 -- _deref_pbuc1=vbuc2 + lda #$40 + sta APU+OFFSET_STRUCT_RICOH_2A03_DMC_FREQ + jmp initNES1_clearVBlankFlag1 + // main::initNES1_clearVBlankFlag1 + initNES1_clearVBlankFlag1: + // asm { ldaPPU_PPUSTATUS } + lda PPU_PPUSTATUS + // [13] phi from main::initNES1_clearVBlankFlag1 to main::initNES1_waitForVBlank1 [phi:main::initNES1_clearVBlankFlag1->main::initNES1_waitForVBlank1] + initNES1_waitForVBlank1_from_initNES1_clearVBlankFlag1: + jmp initNES1_waitForVBlank1 + // main::initNES1_waitForVBlank1 + initNES1_waitForVBlank1: + jmp initNES1_waitForVBlank1___b1 + // main::initNES1_waitForVBlank1_@1 + initNES1_waitForVBlank1___b1: + // [14] (byte~) main::initNES1_waitForVBlank1_$0 ← *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSTATUS) & (byte) $80 -- vbuaa=_deref_pbuc1_band_vbuc2 + lda #$80 + and PPU+OFFSET_STRUCT_RICOH_2C02_PPUSTATUS + // [15] if((byte) 0==(byte~) main::initNES1_waitForVBlank1_$0) goto main::initNES1_waitForVBlank1_@1 -- vbuc1_eq_vbuaa_then_la1 + cmp #0 + beq initNES1_waitForVBlank1___b1 + // [16] phi from main::initNES1_waitForVBlank1_@1 to main::initNES1_@1 [phi:main::initNES1_waitForVBlank1_@1->main::initNES1_@1] + initNES1___b1_from_initNES1_waitForVBlank1___b1: + // [16] phi (byte) main::initNES1_i#2 = (byte) 0 [phi:main::initNES1_waitForVBlank1_@1->main::initNES1_@1#0] -- vbuxx=vbuc1 + ldx #0 + jmp initNES1___b1 + // [16] phi from main::initNES1_@1 to main::initNES1_@1 [phi:main::initNES1_@1->main::initNES1_@1] + initNES1___b1_from_initNES1___b1: + // [16] phi (byte) main::initNES1_i#2 = (byte) main::initNES1_i#1 [phi:main::initNES1_@1->main::initNES1_@1#0] -- register_copy + jmp initNES1___b1 + // main::initNES1_@1 + initNES1___b1: + // [17] *((const nomodify byte*) MEMORY + (byte) main::initNES1_i#2) ← (byte) 0 -- pbuc1_derefidx_vbuxx=vbuc2 + lda #0 + sta MEMORY,x + // [18] *((const nomodify byte*) MEMORY+(word) $100 + (byte) main::initNES1_i#2) ← (byte) 0 -- pbuc1_derefidx_vbuxx=vbuc2 + lda #0 + sta MEMORY+$100,x + // [19] *((const nomodify byte*) MEMORY+(word) $200 + (byte) main::initNES1_i#2) ← (byte) 0 -- pbuc1_derefidx_vbuxx=vbuc2 + lda #0 + sta MEMORY+$200,x + // [20] *((const nomodify byte*) MEMORY+(word) $300 + (byte) main::initNES1_i#2) ← (byte) 0 -- pbuc1_derefidx_vbuxx=vbuc2 + lda #0 + sta MEMORY+$300,x + // [21] *((const nomodify byte*) MEMORY+(word) $400 + (byte) main::initNES1_i#2) ← (byte) 0 -- pbuc1_derefidx_vbuxx=vbuc2 + lda #0 + sta MEMORY+$400,x + // [22] *((const nomodify byte*) MEMORY+(word) $500 + (byte) main::initNES1_i#2) ← (byte) 0 -- pbuc1_derefidx_vbuxx=vbuc2 + lda #0 + sta MEMORY+$500,x + // [23] *((const nomodify byte*) MEMORY+(word) $600 + (byte) main::initNES1_i#2) ← (byte) 0 -- pbuc1_derefidx_vbuxx=vbuc2 + lda #0 + sta MEMORY+$600,x + // [24] *((const nomodify byte*) MEMORY+(word) $700 + (byte) main::initNES1_i#2) ← (byte) 0 -- pbuc1_derefidx_vbuxx=vbuc2 + lda #0 + sta MEMORY+$700,x + // [25] (byte) main::initNES1_i#1 ← ++ (byte) main::initNES1_i#2 -- vbuxx=_inc_vbuxx + inx + // [26] if((byte) 0!=(byte) main::initNES1_i#1) goto main::initNES1_@1 -- vbuc1_neq_vbuxx_then_la1 + cpx #0 + bne initNES1___b1_from_initNES1___b1 + // [27] phi from main::initNES1_@1 to main::initNES1_waitForVBlank2 [phi:main::initNES1_@1->main::initNES1_waitForVBlank2] + initNES1_waitForVBlank2_from_initNES1___b1: + jmp initNES1_waitForVBlank2 + // main::initNES1_waitForVBlank2 + initNES1_waitForVBlank2: + jmp initNES1_waitForVBlank2___b1 + // main::initNES1_waitForVBlank2_@1 + initNES1_waitForVBlank2___b1: + // [28] (byte~) main::initNES1_waitForVBlank2_$0 ← *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSTATUS) & (byte) $80 -- vbuaa=_deref_pbuc1_band_vbuc2 + lda #$80 + and PPU+OFFSET_STRUCT_RICOH_2C02_PPUSTATUS + // [29] if((byte) 0==(byte~) main::initNES1_waitForVBlank2_$0) goto main::initNES1_waitForVBlank2_@1 -- vbuc1_eq_vbuaa_then_la1 + cmp #0 + beq initNES1_waitForVBlank2___b1 + jmp initNES1___b7 + // main::initNES1_@7 + initNES1___b7: + // asm { ldaPPU_PPUSTATUS } + lda PPU_PPUSTATUS + // [31] phi from main::initNES1_@7 to main::@4 [phi:main::initNES1_@7->main::@4] + __b4_from_initNES1___b7: + jmp __b4 + // main::@4 + __b4: + // [32] call ppuDataTransfer + // Transfer the palette + // [58] phi from main::@4 to ppuDataTransfer [phi:main::@4->ppuDataTransfer] + ppuDataTransfer_from___b4: + jsr ppuDataTransfer + // [33] phi from main::@4 to main::@5 [phi:main::@4->main::@5] + __b5_from___b4: + jmp __b5 + // main::@5 + __b5: + // [34] call ppuDataFill + // Fill the PPU attribute table + // [48] phi from main::@5 to ppuDataFill [phi:main::@5->ppuDataFill] + ppuDataFill_from___b5: + // [48] phi (byte) ppuDataFill::val#4 = (byte) '*' [phi:main::@5->ppuDataFill#0] -- vbuxx=vbuc1 + ldx #'*' + // [48] phi (word) ppuDataFill::size#3 = (word)(number) $20*(number) $1e [phi:main::@5->ppuDataFill#1] -- vwuz1=vwuc1 + lda #<$20*$1e + sta.z ppuDataFill.size + lda #>$20*$1e + sta.z ppuDataFill.size+1 + // [48] phi (nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0 = (void*)(const nomodify byte*) PPU_NAME_TABLE_0 [phi:main::@5->ppuDataFill#2] -- pvoz1=pvoc1 + lda #PPU_NAME_TABLE_0 + sta.z ppuDataFill.ppuDataPrepare1_ppuData+1 + jsr ppuDataFill + // [35] phi from main::@5 to main::@6 [phi:main::@5->main::@6] + __b6_from___b5: + jmp __b6 + // main::@6 + __b6: + // [36] call ppuDataFill + // [48] phi from main::@6 to ppuDataFill [phi:main::@6->ppuDataFill] + ppuDataFill_from___b6: + // [48] phi (byte) ppuDataFill::val#4 = (byte) 0 [phi:main::@6->ppuDataFill#0] -- vbuxx=vbuc1 + ldx #0 + // [48] phi (word) ppuDataFill::size#3 = (byte) $40 [phi:main::@6->ppuDataFill#1] -- vwuz1=vbuc1 + lda #<$40 + sta.z ppuDataFill.size + lda #>$40 + sta.z ppuDataFill.size+1 + // [48] phi (nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0 = (void*)(const nomodify byte*) PPU_ATTRIBUTE_TABLE_0 [phi:main::@6->ppuDataFill#2] -- pvoz1=pvoc1 + lda #PPU_ATTRIBUTE_TABLE_0 + sta.z ppuDataFill.ppuDataPrepare1_ppuData+1 + jsr ppuDataFill + // [37] phi from main::@6 to main::@1 [phi:main::@6->main::@1] + __b1_from___b6: + // [37] phi (byte) main::s#2 = (byte) 0 [phi:main::@6->main::@1#0] -- vbuxx=vbuc1 + ldx #0 + jmp __b1 + // Initialize Sprite Buffer with the SPRITE data + // main::@1 + __b1: + // [38] if((byte) main::s#2<(byte) $40) goto main::@2 -- vbuxx_lt_vbuc1_then_la1 + cpx #$40 + bcc __b2 + jmp enableVideoOutput1 + // main::enableVideoOutput1 + enableVideoOutput1: + // [39] *((byte*)(const struct RICOH_2C02*) PPU) ← (byte) $80 -- _deref_pbuc1=vbuc2 + lda #$80 + sta PPU + // [40] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUMASK) ← (byte) $1e -- _deref_pbuc1=vbuc2 + lda #$1e + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUMASK + // [41] phi from main::@3 main::enableVideoOutput1 to main::@3 [phi:main::@3/main::enableVideoOutput1->main::@3] + __b3_from___b3: + __b3_from_enableVideoOutput1: + jmp __b3 + // Infinite loop + // main::@3 + __b3: + jmp __b3_from___b3 + // main::@2 + __b2: + // [42] (byte~) main::$7 ← (byte) main::s#2 << (byte) 2 -- vbuyy=vbuxx_rol_2 + txa + asl + asl + tay + // [43] *((byte*)(const struct SpriteData*) SPRITE_BUFFER + (byte~) main::$7) ← (byte) 0 -- pbuc1_derefidx_vbuyy=vbuc2 + lda #0 + sta SPRITE_BUFFER,y + // [44] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_TILE + (byte~) main::$7) ← *((const byte*) MESSAGE + (byte) main::s#2) -- pbuc1_derefidx_vbuyy=pbuc2_derefidx_vbuxx + lda MESSAGE,x + sta SPRITE_BUFFER+OFFSET_STRUCT_SPRITEDATA_TILE,y + // [45] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_ATTRIBUTES + (byte~) main::$7) ← (byte) 2 -- pbuc1_derefidx_vbuyy=vbuc2 + lda #2 + sta SPRITE_BUFFER+OFFSET_STRUCT_SPRITEDATA_ATTRIBUTES,y + // [46] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_X + (byte~) main::$7) ← (byte) 0 -- pbuc1_derefidx_vbuyy=vbuc2 + lda #0 + sta SPRITE_BUFFER+OFFSET_STRUCT_SPRITEDATA_X,y + // [47] (byte) main::s#1 ← ++ (byte) main::s#2 -- vbuxx=_inc_vbuxx + inx + // [37] phi from main::@2 to main::@1 [phi:main::@2->main::@1] + __b1_from___b2: + // [37] phi (byte) main::s#2 = (byte) main::s#1 [phi:main::@2->main::@1#0] -- register_copy + jmp __b1 +} + // ppuDataFill +// Fill a number of bytes in the PPU memory +// - ppuData : Pointer in the PPU memory +// - size : The number of bytes to transfer +// ppuDataFill(byte register(X) val, word zp(6) size) +ppuDataFill: { + .label ppuDataPrepare1_ppuData = 4 + .label i = 2 + .label size = 6 + jmp ppuDataPrepare1 + // ppuDataFill::ppuDataPrepare1 + ppuDataPrepare1: + // [49] (byte~) ppuDataFill::ppuDataPrepare1_$0 ← > (nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0 -- vbuaa=_hi_pvoz1 + lda.z ppuDataPrepare1_ppuData+1 + // [50] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← (byte~) ppuDataFill::ppuDataPrepare1_$0 -- _deref_pbuc1=vbuaa + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUADDR + // [51] (byte~) ppuDataFill::ppuDataPrepare1_$1 ← < (nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0 -- vbuaa=_lo_pvoz1 + lda.z ppuDataPrepare1_ppuData + // [52] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← (byte~) ppuDataFill::ppuDataPrepare1_$1 -- _deref_pbuc1=vbuaa + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUADDR + // [53] phi from ppuDataFill::ppuDataPrepare1 to ppuDataFill::@1 [phi:ppuDataFill::ppuDataPrepare1->ppuDataFill::@1] + __b1_from_ppuDataPrepare1: + // [53] phi (word) ppuDataFill::i#2 = (word) 0 [phi:ppuDataFill::ppuDataPrepare1->ppuDataFill::@1#0] -- vwuz1=vwuc1 + lda #<0 + sta.z i + lda #>0 + sta.z i+1 + jmp __b1 + // Transfer to PPU + // ppuDataFill::@1 + __b1: + // [54] if((word) ppuDataFill::i#2<(word) ppuDataFill::size#3) goto ppuDataFill::ppuDataPut1 -- vwuz1_lt_vwuz2_then_la1 + lda.z i+1 + cmp.z size+1 + bcc ppuDataPut1 + bne !+ + lda.z i + cmp.z size + bcc ppuDataPut1 + !: + jmp __breturn + // ppuDataFill::@return + __breturn: + // [55] return + rts + // ppuDataFill::ppuDataPut1 + ppuDataPut1: + // [56] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUDATA) ← (byte) ppuDataFill::val#4 -- _deref_pbuc1=vbuxx + stx PPU+OFFSET_STRUCT_RICOH_2C02_PPUDATA + jmp __b2 + // ppuDataFill::@2 + __b2: + // [57] (word) ppuDataFill::i#1 ← ++ (word) ppuDataFill::i#2 -- vwuz1=_inc_vwuz1 + inc.z i + bne !+ + inc.z i+1 + !: + // [53] phi from ppuDataFill::@2 to ppuDataFill::@1 [phi:ppuDataFill::@2->ppuDataFill::@1] + __b1_from___b2: + // [53] phi (word) ppuDataFill::i#2 = (word) ppuDataFill::i#1 [phi:ppuDataFill::@2->ppuDataFill::@1#0] -- register_copy + jmp __b1 +} + // ppuDataTransfer +// Transfer a number of bytes from the CPU memory to the PPU memory +// - cpuData : Pointer to the CPU memory (RAM of ROM) +// - ppuData : Pointer in the PPU memory +// - size : The number of bytes to transfer +ppuDataTransfer: { + .const size = $20*SIZEOF_BYTE + .label ppuData = PPU_PALETTE + .label cpuData = PALETTE + // Transfer to PPU + .label cpuSrc = 6 + .label i = 4 + jmp ppuDataPrepare1 + // ppuDataTransfer::ppuDataPrepare1 + ppuDataPrepare1: + // [59] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← >(const nomodify void*) ppuDataTransfer::ppuData#0 -- _deref_pbuc1=vbuc2 + lda #>ppuData + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUADDR + // [60] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← (byte) 0 -- _deref_pbuc1=vbuc2 + lda #0 + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUADDR + // [61] phi from ppuDataTransfer::ppuDataPrepare1 to ppuDataTransfer::@1 [phi:ppuDataTransfer::ppuDataPrepare1->ppuDataTransfer::@1] + __b1_from_ppuDataPrepare1: + // [61] phi (byte*) ppuDataTransfer::cpuSrc#2 = (byte*)(const nomodify void*) ppuDataTransfer::cpuData#0 [phi:ppuDataTransfer::ppuDataPrepare1->ppuDataTransfer::@1#0] -- pbuz1=pbuc1 + lda #cpuData + sta.z cpuSrc+1 + // [61] phi (word) ppuDataTransfer::i#2 = (word) 0 [phi:ppuDataTransfer::ppuDataPrepare1->ppuDataTransfer::@1#1] -- vwuz1=vwuc1 + lda #<0 + sta.z i + lda #>0 + sta.z i+1 + jmp __b1 + // ppuDataTransfer::@1 + __b1: + // [62] if((word) ppuDataTransfer::i#2<(const word) ppuDataTransfer::size#0) goto ppuDataTransfer::@2 -- vwuz1_lt_vwuc1_then_la1 + lda.z i+1 + cmp #>size + bcc __b2 + bne !+ + lda.z i + cmp #ppuDataTransfer::@1] + __b1_from___b3: + // [61] phi (byte*) ppuDataTransfer::cpuSrc#2 = (byte*) ppuDataTransfer::cpuSrc#1 [phi:ppuDataTransfer::@3->ppuDataTransfer::@1#0] -- register_copy + // [61] phi (word) ppuDataTransfer::i#2 = (word) ppuDataTransfer::i#1 [phi:ppuDataTransfer::@3->ppuDataTransfer::@1#1] -- register_copy + jmp __b1 +} + // vblank +// NMI Called when the PPU refreshes the screen (also known as the V-Blank period) +vblank: { + .label __4 = $c + .label y_idx = 8 + .label x_idx = 9 + // entry interrupt(HARDWARE_STACK) + pha + txa + pha + tya + pha + // [68] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSCROLL) ← (byte) 0 -- _deref_pbuc1=vbuc2 + // Set scroll + lda #0 + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUSCROLL + // [69] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSCROLL) ← (byte) 0 -- _deref_pbuc1=vbuc2 + lda #0 + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUSCROLL + jmp ppuSpriteBufferDmaTransfer1 + // vblank::ppuSpriteBufferDmaTransfer1 + ppuSpriteBufferDmaTransfer1: + // [70] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_OAMADDR) ← (byte) 0 -- _deref_pbuc1=vbuc2 + lda #0 + sta PPU+OFFSET_STRUCT_RICOH_2C02_OAMADDR + // [71] *((byte*)(const struct RICOH_2A03*) APU+(const byte) OFFSET_STRUCT_RICOH_2A03_OAMDMA) ← >(const struct SpriteData*) SPRITE_BUFFER -- _deref_pbuc1=vbuc2 + lda #>SPRITE_BUFFER + sta APU+OFFSET_STRUCT_RICOH_2A03_OAMDMA + jmp __b3 + // vblank::@3 + __b3: + // [72] (byte) vblank::y_idx#0 ← (volatile byte) y_sin_idx -- vbuz1=vbuz2 + // Update sprite positions + lda.z y_sin_idx + sta.z y_idx + // [73] (volatile byte) y_sin_idx ← ++ (volatile byte) y_sin_idx -- vbuz1=_inc_vbuz1 + inc.z y_sin_idx + // [74] (byte) vblank::x_idx#0 ← (volatile byte) x_sin_idx -- vbuz1=vbuz2 + lda.z x_sin_idx + sta.z x_idx + // [75] (volatile byte) x_sin_idx ← ++ (volatile byte) x_sin_idx -- vbuz1=_inc_vbuz1 + inc.z x_sin_idx + // [76] phi from vblank::@3 to vblank::@1 [phi:vblank::@3->vblank::@1] + __b1_from___b3: + // [76] phi (byte) vblank::x_idx#2 = (byte) vblank::x_idx#0 [phi:vblank::@3->vblank::@1#0] -- register_copy + // [76] phi (byte) vblank::y_idx#2 = (byte) vblank::y_idx#0 [phi:vblank::@3->vblank::@1#1] -- register_copy + // [76] phi (byte) vblank::s#2 = (byte) 0 [phi:vblank::@3->vblank::@1#2] -- vbuxx=vbuc1 + ldx #0 + jmp __b1 + // vblank::@1 + __b1: + // [77] if((byte) vblank::s#2<(byte) $40) goto vblank::@2 -- vbuxx_lt_vbuc1_then_la1 + cpx #$40 + bcc __b2 + jmp __breturn + // vblank::@return + __breturn: + // [78] return - exit interrupt(HARDWARE_STACK) + pla + tay + pla + tax + pla + rti + // vblank::@2 + __b2: + // [79] (byte~) vblank::$4 ← (byte) vblank::s#2 << (byte) 2 -- vbuz1=vbuxx_rol_2 + txa + asl + asl + sta.z __4 + // [80] *((byte*)(const struct SpriteData*) SPRITE_BUFFER + (byte~) vblank::$4) ← *((const to_nomodify byte*) SINTABLE + (byte) vblank::y_idx#2) -- pbuc1_derefidx_vbuz1=pbuc2_derefidx_vbuz2 + ldy.z y_idx + lda SINTABLE,y + ldy.z __4 + sta SPRITE_BUFFER,y + // [81] (byte~) vblank::$2 ← *((const to_nomodify byte*) SINTABLE + (byte) vblank::x_idx#2) + (byte) 8 -- vbuaa=pbuc1_derefidx_vbuz1_plus_vbuc2 + lda #8 + ldy.z x_idx + clc + adc SINTABLE,y + // [82] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_X + (byte~) vblank::$4) ← (byte~) vblank::$2 -- pbuc1_derefidx_vbuz1=vbuaa + ldy.z __4 + sta SPRITE_BUFFER+OFFSET_STRUCT_SPRITEDATA_X,y + // [83] (byte) vblank::y_idx#1 ← (byte) vblank::y_idx#2 + (byte) 4 -- vbuz1=vbuz1_plus_vbuc1 + lda #4 + clc + adc.z y_idx + sta.z y_idx + // [84] (byte) vblank::x_idx#1 ← (byte) vblank::x_idx#2 - (byte) 7 -- vbuz1=vbuz1_minus_vbuc1 + lda.z x_idx + sec + sbc #7 + sta.z x_idx + // [85] (byte) vblank::s#1 ← ++ (byte) vblank::s#2 -- vbuxx=_inc_vbuxx + inx + // [76] phi from vblank::@2 to vblank::@1 [phi:vblank::@2->vblank::@1] + __b1_from___b2: + // [76] phi (byte) vblank::x_idx#2 = (byte) vblank::x_idx#1 [phi:vblank::@2->vblank::@1#0] -- register_copy + // [76] phi (byte) vblank::y_idx#2 = (byte) vblank::y_idx#1 [phi:vblank::@2->vblank::@1#1] -- register_copy + // [76] phi (byte) vblank::s#2 = (byte) vblank::s#1 [phi:vblank::@2->vblank::@1#2] -- register_copy + jmp __b1 +} + // File Data +.segment Data + // The DXYCP message 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef + MESSAGE: .text "rex-of-camelot-presents-a-dxycp-on-nintendo-entertainment-system" + // Color Palette + PALETTE: .byte 1, $21, $f, $30, 1, $21, $f, $30, 1, $21, $f, $30, 1, $21, $f, $30, 1, $f, $30, 8, 1, $f, $18, 8, 1, $30, $37, $1a, $f, $f, $f, $f + // Sinus Table (0-239) +SINTABLE: +.fill $100, round(115.5+107.5*sin(2*PI*i/256)) + +.segment Tiles +TILES: +.var filechargen = LoadBinary("characters.901225-01.bin") + .for(var c=0; c<256; c++) { + // Plane 0 + .fill 8, filechargen.get(c*8+i) + // Plane 1 + .fill 8, 0 + } + +.segment GameRam + .align $100 + SPRITE_BUFFER: .fill 4*$100, 0 +.segment Vectors + VECTORS: .word vblank, main, 0 + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __b1 +Removing instruction jmp __b2 +Removing instruction jmp __bend +Removing instruction jmp initNES1 +Removing instruction jmp initNES1_disableVideoOutput1 +Removing instruction jmp initNES1_disableAudioOutput1 +Removing instruction jmp initNES1_clearVBlankFlag1 +Removing instruction jmp initNES1_waitForVBlank1 +Removing instruction jmp initNES1_waitForVBlank1___b1 +Removing instruction jmp initNES1___b1 +Removing instruction jmp initNES1_waitForVBlank2 +Removing instruction jmp initNES1_waitForVBlank2___b1 +Removing instruction jmp initNES1___b7 +Removing instruction jmp __b4 +Removing instruction jmp __b5 +Removing instruction jmp __b6 +Removing instruction jmp __b1 +Removing instruction jmp enableVideoOutput1 +Removing instruction jmp __b3 +Removing instruction jmp ppuDataPrepare1 +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Removing instruction jmp __b2 +Removing instruction jmp ppuDataPrepare1 +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Removing instruction jmp ppuDataPut1 +Removing instruction jmp __b3 +Removing instruction jmp ppuSpriteBufferDmaTransfer1 +Removing instruction jmp __b3 +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction lda #0 +Removing instruction lda #$40 +Removing instruction lda #0 +Removing instruction lda #0 +Removing instruction lda #0 +Removing instruction lda #0 +Removing instruction lda #0 +Removing instruction lda #0 +Removing instruction lda #0 +Removing instruction lda #>0 +Removing instruction lda #>0 +Removing instruction lda #0 +Succesful ASM optimization Pass5UnnecesaryLoadElimination +Replacing label initNES1_waitForVBlank1___b1 with initNES1_waitForVBlank1 +Replacing label initNES1___b1_from_initNES1___b1 with initNES1___b1 +Replacing label initNES1_waitForVBlank2___b1 with initNES1_waitForVBlank2 +Removing instruction __b1: +Removing instruction __b2_from___b1: +Removing instruction main_from___b2: +Removing instruction __bend_from___b2: +Removing instruction initNES1_waitForVBlank1_from_initNES1_clearVBlankFlag1: +Removing instruction initNES1_waitForVBlank1___b1: +Removing instruction initNES1___b1_from_initNES1___b1: +Removing instruction initNES1_waitForVBlank2_from_initNES1___b1: +Removing instruction initNES1_waitForVBlank2___b1: +Removing instruction __b4_from_initNES1___b7: +Removing instruction __b5_from___b4: +Removing instruction __b6_from___b5: +Removing instruction ppuDataFill_from___b6: +Removing instruction __b3_from_enableVideoOutput1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction __b2: +Removing instruction __bend: +Removing instruction initNES1: +Removing instruction initNES1_disableVideoOutput1: +Removing instruction initNES1_disableAudioOutput1: +Removing instruction initNES1_clearVBlankFlag1: +Removing instruction initNES1___b1_from_initNES1_waitForVBlank1___b1: +Removing instruction initNES1___b7: +Removing instruction __b4: +Removing instruction ppuDataTransfer_from___b4: +Removing instruction __b5: +Removing instruction ppuDataFill_from___b5: +Removing instruction __b6: +Removing instruction __b1_from___b6: +Removing instruction enableVideoOutput1: +Removing instruction __b3: +Removing instruction __b1_from___b2: +Removing instruction ppuDataPrepare1: +Removing instruction __b1_from_ppuDataPrepare1: +Removing instruction __breturn: +Removing instruction __b2: +Removing instruction __b1_from___b2: +Removing instruction ppuDataPrepare1: +Removing instruction __b1_from_ppuDataPrepare1: +Removing instruction __breturn: +Removing instruction ppuDataPut1: +Removing instruction __b3: +Removing instruction __b1_from___b3: +Removing instruction ppuSpriteBufferDmaTransfer1: +Removing instruction __b3: +Removing instruction __b1_from___b3: +Removing instruction __breturn: +Removing instruction __b1_from___b2: +Succesful ASM optimization Pass5UnusedLabelElimination +Relabelling long label __b3_from___b3 to __b3 +Succesful ASM optimization Pass5RelabelLongLabels +Adding RTS to root block +Succesful ASM optimization Pass5AddMainRts +Removing instruction jmp initNES1___b1 +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction lda #0 +Succesful ASM optimization Pass5UnnecesaryLoadElimination + +FINAL SYMBOL TABLE +(label) @1 +(label) @2 +(label) @begin +(label) @end +(const struct RICOH_2A03*) APU = (struct RICOH_2A03*) 16384 +(const nomodify byte*) FR_COUNTER = (byte*) 16407 +(const nomodify byte*) MEMORY = (byte*) 0 +(const byte*) MESSAGE[(number) $40] = (byte*) "rex-of-camelot-presents-a-dxycp-on-nintendo-entertainment-system"z +(const byte) OFFSET_STRUCT_RICOH_2A03_DMC_FREQ = (byte) $10 +(const byte) OFFSET_STRUCT_RICOH_2A03_OAMDMA = (byte) $14 +(const byte) OFFSET_STRUCT_RICOH_2C02_OAMADDR = (byte) 3 +(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR = (byte) 6 +(const byte) OFFSET_STRUCT_RICOH_2C02_PPUDATA = (byte) 7 +(const byte) OFFSET_STRUCT_RICOH_2C02_PPUMASK = (byte) 1 +(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSCROLL = (byte) 5 +(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSTATUS = (byte) 2 +(const byte) OFFSET_STRUCT_SPRITEDATA_ATTRIBUTES = (byte) 2 +(const byte) OFFSET_STRUCT_SPRITEDATA_TILE = (byte) 1 +(const byte) OFFSET_STRUCT_SPRITEDATA_X = (byte) 3 +(const byte*) PALETTE[(number) $20] = { (byte) 1, (byte) $21, (byte) $f, (byte) $30, (byte) 1, (byte) $21, (byte) $f, (byte) $30, (byte) 1, (byte) $21, (byte) $f, (byte) $30, (byte) 1, (byte) $21, (byte) $f, (byte) $30, (byte) 1, (byte) $f, (byte) $30, (byte) 8, (byte) 1, (byte) $f, (byte) $18, (byte) 8, (byte) 1, (byte) $30, (byte) $37, (byte) $1a, (byte) $f, (byte) $f, (byte) $f, (byte) $f } +(const struct RICOH_2C02*) PPU = (struct RICOH_2C02*) 8192 +(const nomodify byte*) PPU_ATTRIBUTE_TABLE_0 = (byte*) 9152 +(const nomodify byte*) PPU_NAME_TABLE_0 = (byte*) 8192 +(const nomodify byte*) PPU_PALETTE = (byte*) 16128 +(const nomodify to_volatile byte*) PPU_PPUSTATUS = (byte*) 8194 +(byte) RICOH_2A03::DMC_FREQ +(byte) RICOH_2A03::DMC_LEN +(byte) RICOH_2A03::DMC_RAW +(byte) RICOH_2A03::DMC_START +(byte) RICOH_2A03::JOY1 +(byte) RICOH_2A03::JOY2 +(byte) RICOH_2A03::NOISE_HI +(byte) RICOH_2A03::NOISE_LO +(byte) RICOH_2A03::NOISE_VOL +(byte) RICOH_2A03::OAMDMA +(byte) RICOH_2A03::SND_CHN +(byte) RICOH_2A03::SQ1_HI +(byte) RICOH_2A03::SQ1_LO +(byte) RICOH_2A03::SQ1_SWEEP +(byte) RICOH_2A03::SQ1_VOL +(byte) RICOH_2A03::SQ2_HI +(byte) RICOH_2A03::SQ2_LO +(byte) RICOH_2A03::SQ2_SWEEP +(byte) RICOH_2A03::SQ2_VOL +(byte) RICOH_2A03::TRI_HI +(byte) RICOH_2A03::TRI_LINEAR +(byte) RICOH_2A03::TRI_LO +(byte) RICOH_2A03::UNUSED1 +(byte) RICOH_2A03::UNUSED2 +(byte) RICOH_2C02::OAMADDR +(byte) RICOH_2C02::OAMDATA +(byte) RICOH_2C02::PPUADDR +(byte) RICOH_2C02::PPUCTRL +(byte) RICOH_2C02::PPUDATA +(byte) RICOH_2C02::PPUMASK +(byte) RICOH_2C02::PPUSCROLL +(volatile byte) RICOH_2C02::PPUSTATUS loadstore +(const to_nomodify byte*) SINTABLE[(number) $100] = kickasm {{ .fill $100, round(115.5+107.5*sin(2*PI*i/256)) + }} +(const byte) SIZEOF_BYTE = (byte) 1 +(const struct SpriteData*) SPRITE_BUFFER[(number) $100] = { fill( $100, 0) } +(byte) SpriteData::attributes +(byte) SpriteData::tile +(byte) SpriteData::x +(byte) SpriteData::y +(const byte*) TILES[] = kickasm {{ .var filechargen = LoadBinary("characters.901225-01.bin") + .for(var c=0; c<256; c++) { + // Plane 0 + .fill 8, filechargen.get(c*8+i) + // Plane 1 + .fill 8, 0 + } + }} +(const to_nomodify void()**) VECTORS[] = { &interrupt(HARDWARE_STACK)(void()) vblank(), &(void()) main(), (void()*) 0 } +(void()) main() +(byte~) main::$7 reg byte y 126.25 +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@4 +(label) main::@5 +(label) main::@6 +(label) main::enableVideoOutput1 +(label) main::initNES1 +(label) main::initNES1_@1 +(label) main::initNES1_@7 +(label) main::initNES1_clearVBlankFlag1 +(label) main::initNES1_disableAudioOutput1 +(label) main::initNES1_disableVideoOutput1 +(byte) main::initNES1_i +(byte) main::initNES1_i#1 reg byte x 151.5 +(byte) main::initNES1_i#2 reg byte x 112.22222222222223 +(label) main::initNES1_waitForVBlank1 +(byte~) main::initNES1_waitForVBlank1_$0 reg byte a 202.0 +(label) main::initNES1_waitForVBlank1_@1 +(label) main::initNES1_waitForVBlank2 +(byte~) main::initNES1_waitForVBlank2_$0 reg byte a 202.0 +(label) main::initNES1_waitForVBlank2_@1 +(byte) main::s +(byte) main::s#1 reg byte x 202.0 +(byte) main::s#2 reg byte x 72.14285714285714 +(void()) ppuDataFill((nomodify void*) ppuDataFill::ppuData , (byte) ppuDataFill::val , (word) ppuDataFill::size) +(label) ppuDataFill::@1 +(label) ppuDataFill::@2 +(label) ppuDataFill::@return +(word) ppuDataFill::i +(word) ppuDataFill::i#1 i zp[2]:2 2002.0 +(word) ppuDataFill::i#2 i zp[2]:2 1001.0 +(nomodify void*) ppuDataFill::ppuData +(label) ppuDataFill::ppuDataPrepare1 +(byte~) ppuDataFill::ppuDataPrepare1_$0 reg byte a 202.0 +(byte~) ppuDataFill::ppuDataPrepare1_$1 reg byte a 202.0 +(nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData +(nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0 ppuDataPrepare1_ppuData zp[2]:4 67.33333333333333 +(label) ppuDataFill::ppuDataPut1 +(byte) ppuDataFill::ppuDataPut1_val +(word) ppuDataFill::size +(word) ppuDataFill::size#3 size zp[2]:6 111.22222222222223 +(byte) ppuDataFill::val +(byte) ppuDataFill::val#4 reg byte x 111.22222222222223 +(void()) ppuDataTransfer((nomodify void*) ppuDataTransfer::ppuData , (nomodify void*) ppuDataTransfer::cpuData , (word) ppuDataTransfer::size) +(label) ppuDataTransfer::@1 +(label) ppuDataTransfer::@2 +(label) ppuDataTransfer::@3 +(label) ppuDataTransfer::@return +(nomodify void*) ppuDataTransfer::cpuData +(const nomodify void*) ppuDataTransfer::cpuData#0 cpuData = (void*)(const byte*) PALETTE +(byte*) ppuDataTransfer::cpuSrc +(byte*) ppuDataTransfer::cpuSrc#1 cpuSrc zp[2]:6 1001.0 +(byte*) ppuDataTransfer::cpuSrc#2 cpuSrc zp[2]:6 750.75 +(word) ppuDataTransfer::i +(word) ppuDataTransfer::i#1 i zp[2]:4 2002.0 +(word) ppuDataTransfer::i#2 i zp[2]:4 600.5999999999999 +(nomodify void*) ppuDataTransfer::ppuData +(const nomodify void*) ppuDataTransfer::ppuData#0 ppuData = (void*)(const nomodify byte*) PPU_PALETTE +(label) ppuDataTransfer::ppuDataPrepare1 +(nomodify void*) ppuDataTransfer::ppuDataPrepare1_ppuData +(label) ppuDataTransfer::ppuDataPut1 +(byte) ppuDataTransfer::ppuDataPut1_val +(byte) ppuDataTransfer::ppuDataPut1_val#0 reg byte a 2002.0 +(word) ppuDataTransfer::size +(const word) ppuDataTransfer::size#0 size = (byte) $20*(const byte) SIZEOF_BYTE +interrupt(HARDWARE_STACK)(void()) vblank() +(byte~) vblank::$2 reg byte a 22.0 +(byte~) vblank::$4 zp[1]:12 11.0 +(label) vblank::@1 +(label) vblank::@2 +(label) vblank::@3 +(label) vblank::@return +(label) vblank::ppuSpriteBufferDmaTransfer1 +(struct SpriteData*) vblank::ppuSpriteBufferDmaTransfer1_spriteBuffer +(byte) vblank::s +(byte) vblank::s#1 reg byte x 22.0 +(byte) vblank::s#2 reg byte x 5.5 +(byte) vblank::x_idx +(byte) vblank::x_idx#0 x_idx zp[1]:9 2.0 +(byte) vblank::x_idx#1 x_idx zp[1]:9 11.0 +(byte) vblank::x_idx#2 x_idx zp[1]:9 5.0 +(byte) vblank::y_idx +(byte) vblank::y_idx#0 y_idx zp[1]:8 1.0 +(byte) vblank::y_idx#1 y_idx zp[1]:8 7.333333333333333 +(byte) vblank::y_idx#2 y_idx zp[1]:8 5.833333333333333 +(volatile byte) x_sin_idx loadstore zp[1]:11 1.1428571428571428 +(volatile byte) y_sin_idx loadstore zp[1]:10 1.6 + +reg byte x [ main::initNES1_i#2 main::initNES1_i#1 ] +reg byte x [ main::s#2 main::s#1 ] +reg byte x [ ppuDataFill::val#4 ] +zp[2]:2 [ ppuDataFill::i#2 ppuDataFill::i#1 ] +zp[2]:4 [ ppuDataTransfer::i#2 ppuDataTransfer::i#1 ppuDataFill::ppuDataPrepare1_ppuData#0 ] +zp[2]:6 [ ppuDataTransfer::cpuSrc#2 ppuDataTransfer::cpuSrc#1 ppuDataFill::size#3 ] +reg byte x [ vblank::s#2 vblank::s#1 ] +zp[1]:8 [ vblank::y_idx#2 vblank::y_idx#1 vblank::y_idx#0 ] +zp[1]:9 [ vblank::x_idx#2 vblank::x_idx#1 vblank::x_idx#0 ] +zp[1]:10 [ y_sin_idx ] +zp[1]:11 [ x_sin_idx ] +reg byte a [ main::initNES1_waitForVBlank1_$0 ] +reg byte a [ main::initNES1_waitForVBlank2_$0 ] +reg byte y [ main::$7 ] +reg byte a [ ppuDataFill::ppuDataPrepare1_$0 ] +reg byte a [ ppuDataFill::ppuDataPrepare1_$1 ] +reg byte a [ ppuDataTransfer::ppuDataPut1_val#0 ] +zp[1]:12 [ vblank::$4 ] +reg byte a [ vblank::$2 ] + + +FINAL ASSEMBLER +Score: 3582 + + // File Comments +// NES DXYCP using sprites +// Nintendo Entertainment System (NES +// https://en.wikipedia.org/wiki/Nintendo_Entertainment_System_(Model_NES-101) +// https://github.com/gregkrsak/first_nes +// Ricoh 2C02 - NES Picture Processing Unit (PPU) +// Ricoh RP2C02 (NTSC version) / RP2C07 (PAL version), +// https://en.wikipedia.org/wiki/Picture_Processing_Unit +// https://wiki.nesdev.com/w/index.php/PPU_registers +// http://nesdev.com/2C02%20technical%20reference.TXT +// Based on: https://github.com/gregkrsak/first_nes written by Greg M. Krsak, 2018. + // Upstart + // Nintendo Entertainment System (NES) ROM +// https://sadistech.com/nesromtool/romdoc.html +// https://forums.nesdev.com/viewtopic.php?f=2&t=9896 +// https://github.com/gregkrsak/first_nes +.file [name="nes-dxycp.nes", type="bin", segments="NesRom"] +.file [name="nes-dxycp.nes_hdr", type="bin", segments="Header"] +.file [name="nes-dxycp.nes_prg", type="bin", segments="ProgramRom"] +.file [name="nes-dxycp.nes_chr", type="bin", segments="CharacterRom"] +.segmentdef Header [ start=$0000, min=$0000, max=$000f, fill ] +.segmentdef Tiles [ start=$0000, min=$0000, max=$1fff, fill ] +.segmentdef Code [ start=$c000, min=$c000, max=$fff9 ] +.segmentdef Data [ startAfter="Code", min=$c000, max=$fff9 ] +.segmentdef Vectors [ start=$fffa, min=$fffa, max=$ffff ] +.segmentdef GameRam [start=$200,max=$7ff, virtual] +.segmentdef ProgramRom [ segments="Code, Data, Vectors" ] +.segmentdef CharacterRom [ segments="Tiles" ] +.segmentdef NesRom +.segment NesRom +.segmentout [ segments="Header" ] +.segmentout [ segments="ProgramRom" ] +.segmentout [ segments="CharacterRom" ] +.segment Header +.text @"NES\$1a" +.byte $01 // 1x 16KB ROM (PRG) +.byte $01 // 1x 8KB VROM (CHR) +.byte %00000001 // Mapper nibble 0000 == No mapping (a simple 16KB PRG + 8KB CHR game) + // Mirroring nibble 0001 == Vertical mirroring only +.segment Code + + // Global Constants & labels + .const OFFSET_STRUCT_SPRITEDATA_TILE = 1 + .const OFFSET_STRUCT_SPRITEDATA_ATTRIBUTES = 2 + .const OFFSET_STRUCT_SPRITEDATA_X = 3 + .const OFFSET_STRUCT_RICOH_2A03_DMC_FREQ = $10 + .const OFFSET_STRUCT_RICOH_2C02_PPUMASK = 1 + .const OFFSET_STRUCT_RICOH_2C02_PPUSTATUS = 2 + .const OFFSET_STRUCT_RICOH_2C02_OAMADDR = 3 + .const OFFSET_STRUCT_RICOH_2A03_OAMDMA = $14 + .const OFFSET_STRUCT_RICOH_2C02_PPUADDR = 6 + .const OFFSET_STRUCT_RICOH_2C02_PPUDATA = 7 + .const OFFSET_STRUCT_RICOH_2C02_PPUSCROLL = 5 + .const SIZEOF_BYTE = 1 + // $2000-$23bf $03c0 Name table 0 + .label PPU_NAME_TABLE_0 = $2000 + // $23c0-$23ff $0040 Attribute table 0 + .label PPU_ATTRIBUTE_TABLE_0 = $23c0 + // $3000-$3eff $0f00 Mirrors of $2000-$2eff + // $3f00-$3f1f $0020 Palette RAM indexes + .label PPU_PALETTE = $3f00 + // PPU Status Register for reading in ASM + .label PPU_PPUSTATUS = $2002 + // APU Frame Counter + // generates low-frequency clocks for the channels and an optional 60 Hz interrupt. + // https://wiki.nesdev.com/w/index.php/APU_Frame_Counter + // ------+-----+--------------------------------------------------------------- + // $4017 | W | FR_COUNTER Frame Counter Set mode and interrupt + // ------+-----+--------------------------------------------------------------- + // | 7 | Sequencer mode: 0 selects 4-step sequence, 1 selects 5-step sequence + // | 6 | Interrupt inhibit flag. If set, the frame interrupt flag is cleared, otherwise it is unaffected. + // ------+-----+--------------------------------------------------------------- + // Side effects After 3 or 4 CPU clock cycles*, the timer is reset. + // If the mode flag is set, then both "quarter frame" and "half frame" signals are also generated. + .label FR_COUNTER = $4017 + // Pointer to the start of RAM memory + .label MEMORY = 0 + // NES Picture Processing Unit (PPU) + .label PPU = $2000 + // NES CPU and audion processing unit (APU) + .label APU = $4000 + .label y_sin_idx = $a + .label x_sin_idx = $b + // @begin +__bbegin: + // @1 + // y_sin_idx = 0 + // [1] (volatile byte) y_sin_idx ← (byte) 0 -- vbuz1=vbuc1 + // Index into the Y sine + lda #0 + sta.z y_sin_idx + // x_sin_idx = 73 + // [2] (volatile byte) x_sin_idx ← (byte) $49 -- vbuz1=vbuc1 + // Index into the X sine + lda #$49 + sta.z x_sin_idx + // [3] phi from @1 to @2 [phi:@1->@2] + // @2 + // [4] call main + // [6] phi from @2 to main [phi:@2->main] + jsr main + rts + // [5] phi from @2 to @end [phi:@2->@end] + // @end +.segment Code + // main +// RESET Called when the NES is reset, including when it is turned on. +main: { + // main::initNES1 + // asm + // asm { cld ldx#$ff txs } + cld + ldx #$ff + txs + // main::initNES1_disableVideoOutput1 + // PPU->PPUCTRL = 0 + // [8] *((byte*)(const struct RICOH_2C02*) PPU) ← (byte) 0 -- _deref_pbuc1=vbuc2 + lda #0 + sta PPU + // PPU->PPUMASK = 0 + // [9] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUMASK) ← (byte) 0 -- _deref_pbuc1=vbuc2 + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUMASK + // main::initNES1_disableAudioOutput1 + // *FR_COUNTER = 0b01000000 + // [10] *((const nomodify byte*) FR_COUNTER) ← (byte) $40 -- _deref_pbuc1=vbuc2 + lda #$40 + sta FR_COUNTER + // APU->DMC_FREQ = 0b01000000 + // [11] *((byte*)(const struct RICOH_2A03*) APU+(const byte) OFFSET_STRUCT_RICOH_2A03_DMC_FREQ) ← (byte) $40 -- _deref_pbuc1=vbuc2 + sta APU+OFFSET_STRUCT_RICOH_2A03_DMC_FREQ + // main::initNES1_clearVBlankFlag1 + // asm + // asm { ldaPPU_PPUSTATUS } + lda PPU_PPUSTATUS + // [13] phi from main::initNES1_clearVBlankFlag1 to main::initNES1_waitForVBlank1 [phi:main::initNES1_clearVBlankFlag1->main::initNES1_waitForVBlank1] + // main::initNES1_waitForVBlank1 + initNES1_waitForVBlank1: + // main::initNES1_waitForVBlank1_@1 + // PPU->PPUSTATUS&0x80 + // [14] (byte~) main::initNES1_waitForVBlank1_$0 ← *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSTATUS) & (byte) $80 -- vbuaa=_deref_pbuc1_band_vbuc2 + lda #$80 + and PPU+OFFSET_STRUCT_RICOH_2C02_PPUSTATUS + // while(!(PPU->PPUSTATUS&0x80)) + // [15] if((byte) 0==(byte~) main::initNES1_waitForVBlank1_$0) goto main::initNES1_waitForVBlank1_@1 -- vbuc1_eq_vbuaa_then_la1 + cmp #0 + beq initNES1_waitForVBlank1 + // [16] phi from main::initNES1_waitForVBlank1_@1 to main::initNES1_@1 [phi:main::initNES1_waitForVBlank1_@1->main::initNES1_@1] + // [16] phi (byte) main::initNES1_i#2 = (byte) 0 [phi:main::initNES1_waitForVBlank1_@1->main::initNES1_@1#0] -- vbuxx=vbuc1 + ldx #0 + // [16] phi from main::initNES1_@1 to main::initNES1_@1 [phi:main::initNES1_@1->main::initNES1_@1] + // [16] phi (byte) main::initNES1_i#2 = (byte) main::initNES1_i#1 [phi:main::initNES1_@1->main::initNES1_@1#0] -- register_copy + // main::initNES1_@1 + initNES1___b1: + // (MEMORY+0x000)[i] = 0 + // [17] *((const nomodify byte*) MEMORY + (byte) main::initNES1_i#2) ← (byte) 0 -- pbuc1_derefidx_vbuxx=vbuc2 + lda #0 + sta MEMORY,x + // (MEMORY+0x100)[i] = 0 + // [18] *((const nomodify byte*) MEMORY+(word) $100 + (byte) main::initNES1_i#2) ← (byte) 0 -- pbuc1_derefidx_vbuxx=vbuc2 + sta MEMORY+$100,x + // (MEMORY+0x200)[i] = 0 + // [19] *((const nomodify byte*) MEMORY+(word) $200 + (byte) main::initNES1_i#2) ← (byte) 0 -- pbuc1_derefidx_vbuxx=vbuc2 + sta MEMORY+$200,x + // (MEMORY+0x300)[i] = 0 + // [20] *((const nomodify byte*) MEMORY+(word) $300 + (byte) main::initNES1_i#2) ← (byte) 0 -- pbuc1_derefidx_vbuxx=vbuc2 + sta MEMORY+$300,x + // (MEMORY+0x400)[i] = 0 + // [21] *((const nomodify byte*) MEMORY+(word) $400 + (byte) main::initNES1_i#2) ← (byte) 0 -- pbuc1_derefidx_vbuxx=vbuc2 + sta MEMORY+$400,x + // (MEMORY+0x500)[i] = 0 + // [22] *((const nomodify byte*) MEMORY+(word) $500 + (byte) main::initNES1_i#2) ← (byte) 0 -- pbuc1_derefidx_vbuxx=vbuc2 + sta MEMORY+$500,x + // (MEMORY+0x600)[i] = 0 + // [23] *((const nomodify byte*) MEMORY+(word) $600 + (byte) main::initNES1_i#2) ← (byte) 0 -- pbuc1_derefidx_vbuxx=vbuc2 + sta MEMORY+$600,x + // (MEMORY+0x700)[i] = 0 + // [24] *((const nomodify byte*) MEMORY+(word) $700 + (byte) main::initNES1_i#2) ← (byte) 0 -- pbuc1_derefidx_vbuxx=vbuc2 + sta MEMORY+$700,x + // while (++i) + // [25] (byte) main::initNES1_i#1 ← ++ (byte) main::initNES1_i#2 -- vbuxx=_inc_vbuxx + inx + // [26] if((byte) 0!=(byte) main::initNES1_i#1) goto main::initNES1_@1 -- vbuc1_neq_vbuxx_then_la1 + cpx #0 + bne initNES1___b1 + // [27] phi from main::initNES1_@1 to main::initNES1_waitForVBlank2 [phi:main::initNES1_@1->main::initNES1_waitForVBlank2] + // main::initNES1_waitForVBlank2 + initNES1_waitForVBlank2: + // main::initNES1_waitForVBlank2_@1 + // PPU->PPUSTATUS&0x80 + // [28] (byte~) main::initNES1_waitForVBlank2_$0 ← *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSTATUS) & (byte) $80 -- vbuaa=_deref_pbuc1_band_vbuc2 + lda #$80 + and PPU+OFFSET_STRUCT_RICOH_2C02_PPUSTATUS + // while(!(PPU->PPUSTATUS&0x80)) + // [29] if((byte) 0==(byte~) main::initNES1_waitForVBlank2_$0) goto main::initNES1_waitForVBlank2_@1 -- vbuc1_eq_vbuaa_then_la1 + cmp #0 + beq initNES1_waitForVBlank2 + // main::initNES1_@7 + // asm + // asm { ldaPPU_PPUSTATUS } + lda PPU_PPUSTATUS + // [31] phi from main::initNES1_@7 to main::@4 [phi:main::initNES1_@7->main::@4] + // main::@4 + // ppuDataTransfer(PPU_PALETTE, PALETTE, sizeof(PALETTE)) + // [32] call ppuDataTransfer + // Transfer the palette + // [58] phi from main::@4 to ppuDataTransfer [phi:main::@4->ppuDataTransfer] + jsr ppuDataTransfer + // [33] phi from main::@4 to main::@5 [phi:main::@4->main::@5] + // main::@5 + // ppuDataFill(PPU_NAME_TABLE_0, '*', 32*30) + // [34] call ppuDataFill + // Fill the PPU attribute table + // [48] phi from main::@5 to ppuDataFill [phi:main::@5->ppuDataFill] + // [48] phi (byte) ppuDataFill::val#4 = (byte) '*' [phi:main::@5->ppuDataFill#0] -- vbuxx=vbuc1 + ldx #'*' + // [48] phi (word) ppuDataFill::size#3 = (word)(number) $20*(number) $1e [phi:main::@5->ppuDataFill#1] -- vwuz1=vwuc1 + lda #<$20*$1e + sta.z ppuDataFill.size + lda #>$20*$1e + sta.z ppuDataFill.size+1 + // [48] phi (nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0 = (void*)(const nomodify byte*) PPU_NAME_TABLE_0 [phi:main::@5->ppuDataFill#2] -- pvoz1=pvoc1 + lda #PPU_NAME_TABLE_0 + sta.z ppuDataFill.ppuDataPrepare1_ppuData+1 + jsr ppuDataFill + // [35] phi from main::@5 to main::@6 [phi:main::@5->main::@6] + // main::@6 + // ppuDataFill(PPU_ATTRIBUTE_TABLE_0, 0, 0x40) + // [36] call ppuDataFill + // [48] phi from main::@6 to ppuDataFill [phi:main::@6->ppuDataFill] + // [48] phi (byte) ppuDataFill::val#4 = (byte) 0 [phi:main::@6->ppuDataFill#0] -- vbuxx=vbuc1 + ldx #0 + // [48] phi (word) ppuDataFill::size#3 = (byte) $40 [phi:main::@6->ppuDataFill#1] -- vwuz1=vbuc1 + lda #<$40 + sta.z ppuDataFill.size + lda #>$40 + sta.z ppuDataFill.size+1 + // [48] phi (nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0 = (void*)(const nomodify byte*) PPU_ATTRIBUTE_TABLE_0 [phi:main::@6->ppuDataFill#2] -- pvoz1=pvoc1 + lda #PPU_ATTRIBUTE_TABLE_0 + sta.z ppuDataFill.ppuDataPrepare1_ppuData+1 + jsr ppuDataFill + // [37] phi from main::@6 to main::@1 [phi:main::@6->main::@1] + // [37] phi (byte) main::s#2 = (byte) 0 [phi:main::@6->main::@1#0] -- vbuxx=vbuc1 + ldx #0 + // Initialize Sprite Buffer with the SPRITE data + // main::@1 + __b1: + // for(char s=0;s<0x40;s++) + // [38] if((byte) main::s#2<(byte) $40) goto main::@2 -- vbuxx_lt_vbuc1_then_la1 + cpx #$40 + bcc __b2 + // main::enableVideoOutput1 + // PPU->PPUCTRL = 0b10000000 + // [39] *((byte*)(const struct RICOH_2C02*) PPU) ← (byte) $80 -- _deref_pbuc1=vbuc2 + lda #$80 + sta PPU + // PPU->PPUMASK = 0b00011110 + // [40] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUMASK) ← (byte) $1e -- _deref_pbuc1=vbuc2 + lda #$1e + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUMASK + // [41] phi from main::@3 main::enableVideoOutput1 to main::@3 [phi:main::@3/main::enableVideoOutput1->main::@3] + __b3: + // Infinite loop + // main::@3 + jmp __b3 + // main::@2 + __b2: + // SPRITE_BUFFER[s] = { 0, MESSAGE[s], 0b00000010, 0 } + // [42] (byte~) main::$7 ← (byte) main::s#2 << (byte) 2 -- vbuyy=vbuxx_rol_2 + txa + asl + asl + tay + // [43] *((byte*)(const struct SpriteData*) SPRITE_BUFFER + (byte~) main::$7) ← (byte) 0 -- pbuc1_derefidx_vbuyy=vbuc2 + lda #0 + sta SPRITE_BUFFER,y + // [44] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_TILE + (byte~) main::$7) ← *((const byte*) MESSAGE + (byte) main::s#2) -- pbuc1_derefidx_vbuyy=pbuc2_derefidx_vbuxx + lda MESSAGE,x + sta SPRITE_BUFFER+OFFSET_STRUCT_SPRITEDATA_TILE,y + // [45] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_ATTRIBUTES + (byte~) main::$7) ← (byte) 2 -- pbuc1_derefidx_vbuyy=vbuc2 + lda #2 + sta SPRITE_BUFFER+OFFSET_STRUCT_SPRITEDATA_ATTRIBUTES,y + // [46] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_X + (byte~) main::$7) ← (byte) 0 -- pbuc1_derefidx_vbuyy=vbuc2 + lda #0 + sta SPRITE_BUFFER+OFFSET_STRUCT_SPRITEDATA_X,y + // for(char s=0;s<0x40;s++) + // [47] (byte) main::s#1 ← ++ (byte) main::s#2 -- vbuxx=_inc_vbuxx + inx + // [37] phi from main::@2 to main::@1 [phi:main::@2->main::@1] + // [37] phi (byte) main::s#2 = (byte) main::s#1 [phi:main::@2->main::@1#0] -- register_copy + jmp __b1 +} + // ppuDataFill +// Fill a number of bytes in the PPU memory +// - ppuData : Pointer in the PPU memory +// - size : The number of bytes to transfer +// ppuDataFill(byte register(X) val, word zp(6) size) +ppuDataFill: { + .label ppuDataPrepare1_ppuData = 4 + .label i = 2 + .label size = 6 + // ppuDataFill::ppuDataPrepare1 + // >ppuData + // [49] (byte~) ppuDataFill::ppuDataPrepare1_$0 ← > (nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0 -- vbuaa=_hi_pvoz1 + lda.z ppuDataPrepare1_ppuData+1 + // PPU->PPUADDR = >ppuData + // [50] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← (byte~) ppuDataFill::ppuDataPrepare1_$0 -- _deref_pbuc1=vbuaa + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUADDR + // PPUADDR = ppuDataFill::@1] + // [53] phi (word) ppuDataFill::i#2 = (word) 0 [phi:ppuDataFill::ppuDataPrepare1->ppuDataFill::@1#0] -- vwuz1=vwuc1 + lda #<0 + sta.z i + sta.z i+1 + // Transfer to PPU + // ppuDataFill::@1 + __b1: + // for(unsigned int i=0;iPPUDATA = val + // [56] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUDATA) ← (byte) ppuDataFill::val#4 -- _deref_pbuc1=vbuxx + stx PPU+OFFSET_STRUCT_RICOH_2C02_PPUDATA + // ppuDataFill::@2 + // for(unsigned int i=0;ippuDataFill::@1] + // [53] phi (word) ppuDataFill::i#2 = (word) ppuDataFill::i#1 [phi:ppuDataFill::@2->ppuDataFill::@1#0] -- register_copy + jmp __b1 +} + // ppuDataTransfer +// Transfer a number of bytes from the CPU memory to the PPU memory +// - cpuData : Pointer to the CPU memory (RAM of ROM) +// - ppuData : Pointer in the PPU memory +// - size : The number of bytes to transfer +ppuDataTransfer: { + .const size = $20*SIZEOF_BYTE + .label ppuData = PPU_PALETTE + .label cpuData = PALETTE + // Transfer to PPU + .label cpuSrc = 6 + .label i = 4 + // ppuDataTransfer::ppuDataPrepare1 + // PPU->PPUADDR = >ppuData + // [59] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← >(const nomodify void*) ppuDataTransfer::ppuData#0 -- _deref_pbuc1=vbuc2 + lda #>ppuData + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUADDR + // PPU->PPUADDR = ppuDataTransfer::@1] + // [61] phi (byte*) ppuDataTransfer::cpuSrc#2 = (byte*)(const nomodify void*) ppuDataTransfer::cpuData#0 [phi:ppuDataTransfer::ppuDataPrepare1->ppuDataTransfer::@1#0] -- pbuz1=pbuc1 + lda #cpuData + sta.z cpuSrc+1 + // [61] phi (word) ppuDataTransfer::i#2 = (word) 0 [phi:ppuDataTransfer::ppuDataPrepare1->ppuDataTransfer::@1#1] -- vwuz1=vwuc1 + lda #<0 + sta.z i + sta.z i+1 + // ppuDataTransfer::@1 + __b1: + // for(unsigned int i=0;isize + bcc __b2 + bne !+ + lda.z i + cmp #PPUDATA = val + // [65] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUDATA) ← (byte) ppuDataTransfer::ppuDataPut1_val#0 -- _deref_pbuc1=vbuaa + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUDATA + // ppuDataTransfer::@3 + // ppuDataPut(*cpuSrc++); + // [66] (byte*) ppuDataTransfer::cpuSrc#1 ← ++ (byte*) ppuDataTransfer::cpuSrc#2 -- pbuz1=_inc_pbuz1 + inc.z cpuSrc + bne !+ + inc.z cpuSrc+1 + !: + // for(unsigned int i=0;ippuDataTransfer::@1] + // [61] phi (byte*) ppuDataTransfer::cpuSrc#2 = (byte*) ppuDataTransfer::cpuSrc#1 [phi:ppuDataTransfer::@3->ppuDataTransfer::@1#0] -- register_copy + // [61] phi (word) ppuDataTransfer::i#2 = (word) ppuDataTransfer::i#1 [phi:ppuDataTransfer::@3->ppuDataTransfer::@1#1] -- register_copy + jmp __b1 +} + // vblank +// NMI Called when the PPU refreshes the screen (also known as the V-Blank period) +vblank: { + .label __4 = $c + .label y_idx = 8 + .label x_idx = 9 + // entry interrupt(HARDWARE_STACK) + pha + txa + pha + tya + pha + // PPU->PPUSCROLL = 0 + // [68] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSCROLL) ← (byte) 0 -- _deref_pbuc1=vbuc2 + // Set scroll + lda #0 + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUSCROLL + // [69] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSCROLL) ← (byte) 0 -- _deref_pbuc1=vbuc2 + sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUSCROLL + // vblank::ppuSpriteBufferDmaTransfer1 + // PPU->OAMADDR = 0 + // [70] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_OAMADDR) ← (byte) 0 -- _deref_pbuc1=vbuc2 + sta PPU+OFFSET_STRUCT_RICOH_2C02_OAMADDR + // APU->OAMDMA = >spriteBuffer + // [71] *((byte*)(const struct RICOH_2A03*) APU+(const byte) OFFSET_STRUCT_RICOH_2A03_OAMDMA) ← >(const struct SpriteData*) SPRITE_BUFFER -- _deref_pbuc1=vbuc2 + lda #>SPRITE_BUFFER + sta APU+OFFSET_STRUCT_RICOH_2A03_OAMDMA + // vblank::@3 + // y_idx = y_sin_idx++ + // [72] (byte) vblank::y_idx#0 ← (volatile byte) y_sin_idx -- vbuz1=vbuz2 + // Update sprite positions + lda.z y_sin_idx + sta.z y_idx + // [73] (volatile byte) y_sin_idx ← ++ (volatile byte) y_sin_idx -- vbuz1=_inc_vbuz1 + inc.z y_sin_idx + // x_idx = x_sin_idx++ + // [74] (byte) vblank::x_idx#0 ← (volatile byte) x_sin_idx -- vbuz1=vbuz2 + lda.z x_sin_idx + sta.z x_idx + // [75] (volatile byte) x_sin_idx ← ++ (volatile byte) x_sin_idx -- vbuz1=_inc_vbuz1 + inc.z x_sin_idx + // [76] phi from vblank::@3 to vblank::@1 [phi:vblank::@3->vblank::@1] + // [76] phi (byte) vblank::x_idx#2 = (byte) vblank::x_idx#0 [phi:vblank::@3->vblank::@1#0] -- register_copy + // [76] phi (byte) vblank::y_idx#2 = (byte) vblank::y_idx#0 [phi:vblank::@3->vblank::@1#1] -- register_copy + // [76] phi (byte) vblank::s#2 = (byte) 0 [phi:vblank::@3->vblank::@1#2] -- vbuxx=vbuc1 + ldx #0 + // vblank::@1 + __b1: + // for(char s=0;s<0x40;s++) + // [77] if((byte) vblank::s#2<(byte) $40) goto vblank::@2 -- vbuxx_lt_vbuc1_then_la1 + cpx #$40 + bcc __b2 + // vblank::@return + // } + // [78] return - exit interrupt(HARDWARE_STACK) + pla + tay + pla + tax + pla + rti + // vblank::@2 + __b2: + // SPRITE_BUFFER[s].y = SINTABLE[y_idx] + // [79] (byte~) vblank::$4 ← (byte) vblank::s#2 << (byte) 2 -- vbuz1=vbuxx_rol_2 + txa + asl + asl + sta.z __4 + // [80] *((byte*)(const struct SpriteData*) SPRITE_BUFFER + (byte~) vblank::$4) ← *((const to_nomodify byte*) SINTABLE + (byte) vblank::y_idx#2) -- pbuc1_derefidx_vbuz1=pbuc2_derefidx_vbuz2 + ldy.z y_idx + lda SINTABLE,y + ldy.z __4 + sta SPRITE_BUFFER,y + // SINTABLE[x_idx]+8 + // [81] (byte~) vblank::$2 ← *((const to_nomodify byte*) SINTABLE + (byte) vblank::x_idx#2) + (byte) 8 -- vbuaa=pbuc1_derefidx_vbuz1_plus_vbuc2 + lda #8 + ldy.z x_idx + clc + adc SINTABLE,y + // SPRITE_BUFFER[s].x = SINTABLE[x_idx]+8 + // [82] *((byte*)(const struct SpriteData*) SPRITE_BUFFER+(const byte) OFFSET_STRUCT_SPRITEDATA_X + (byte~) vblank::$4) ← (byte~) vblank::$2 -- pbuc1_derefidx_vbuz1=vbuaa + ldy.z __4 + sta SPRITE_BUFFER+OFFSET_STRUCT_SPRITEDATA_X,y + // y_idx += 4 + // [83] (byte) vblank::y_idx#1 ← (byte) vblank::y_idx#2 + (byte) 4 -- vbuz1=vbuz1_plus_vbuc1 + lda #4 + clc + adc.z y_idx + sta.z y_idx + // x_idx -= 7 + // [84] (byte) vblank::x_idx#1 ← (byte) vblank::x_idx#2 - (byte) 7 -- vbuz1=vbuz1_minus_vbuc1 + lda.z x_idx + sec + sbc #7 + sta.z x_idx + // for(char s=0;s<0x40;s++) + // [85] (byte) vblank::s#1 ← ++ (byte) vblank::s#2 -- vbuxx=_inc_vbuxx + inx + // [76] phi from vblank::@2 to vblank::@1 [phi:vblank::@2->vblank::@1] + // [76] phi (byte) vblank::x_idx#2 = (byte) vblank::x_idx#1 [phi:vblank::@2->vblank::@1#0] -- register_copy + // [76] phi (byte) vblank::y_idx#2 = (byte) vblank::y_idx#1 [phi:vblank::@2->vblank::@1#1] -- register_copy + // [76] phi (byte) vblank::s#2 = (byte) vblank::s#1 [phi:vblank::@2->vblank::@1#2] -- register_copy + jmp __b1 +} + // File Data +.segment Data + // The DXYCP message 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef + MESSAGE: .text "rex-of-camelot-presents-a-dxycp-on-nintendo-entertainment-system" + // Color Palette + PALETTE: .byte 1, $21, $f, $30, 1, $21, $f, $30, 1, $21, $f, $30, 1, $21, $f, $30, 1, $f, $30, 8, 1, $f, $18, 8, 1, $30, $37, $1a, $f, $f, $f, $f + // Sinus Table (0-239) +SINTABLE: +.fill $100, round(115.5+107.5*sin(2*PI*i/256)) + +.segment Tiles +TILES: +.var filechargen = LoadBinary("characters.901225-01.bin") + .for(var c=0; c<256; c++) { + // Plane 0 + .fill 8, filechargen.get(c*8+i) + // Plane 1 + .fill 8, 0 + } + +.segment GameRam + .align $100 + SPRITE_BUFFER: .fill 4*$100, 0 +.segment Vectors + VECTORS: .word vblank, main, 0 + diff --git a/src/test/ref/examples/nes-dxycp/nes-dxycp.sym b/src/test/ref/examples/nes-dxycp/nes-dxycp.sym new file mode 100644 index 000000000..fff6ac4c2 --- /dev/null +++ b/src/test/ref/examples/nes-dxycp/nes-dxycp.sym @@ -0,0 +1,184 @@ +(label) @1 +(label) @2 +(label) @begin +(label) @end +(const struct RICOH_2A03*) APU = (struct RICOH_2A03*) 16384 +(const nomodify byte*) FR_COUNTER = (byte*) 16407 +(const nomodify byte*) MEMORY = (byte*) 0 +(const byte*) MESSAGE[(number) $40] = (byte*) "rex-of-camelot-presents-a-dxycp-on-nintendo-entertainment-system"z +(const byte) OFFSET_STRUCT_RICOH_2A03_DMC_FREQ = (byte) $10 +(const byte) OFFSET_STRUCT_RICOH_2A03_OAMDMA = (byte) $14 +(const byte) OFFSET_STRUCT_RICOH_2C02_OAMADDR = (byte) 3 +(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR = (byte) 6 +(const byte) OFFSET_STRUCT_RICOH_2C02_PPUDATA = (byte) 7 +(const byte) OFFSET_STRUCT_RICOH_2C02_PPUMASK = (byte) 1 +(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSCROLL = (byte) 5 +(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSTATUS = (byte) 2 +(const byte) OFFSET_STRUCT_SPRITEDATA_ATTRIBUTES = (byte) 2 +(const byte) OFFSET_STRUCT_SPRITEDATA_TILE = (byte) 1 +(const byte) OFFSET_STRUCT_SPRITEDATA_X = (byte) 3 +(const byte*) PALETTE[(number) $20] = { (byte) 1, (byte) $21, (byte) $f, (byte) $30, (byte) 1, (byte) $21, (byte) $f, (byte) $30, (byte) 1, (byte) $21, (byte) $f, (byte) $30, (byte) 1, (byte) $21, (byte) $f, (byte) $30, (byte) 1, (byte) $f, (byte) $30, (byte) 8, (byte) 1, (byte) $f, (byte) $18, (byte) 8, (byte) 1, (byte) $30, (byte) $37, (byte) $1a, (byte) $f, (byte) $f, (byte) $f, (byte) $f } +(const struct RICOH_2C02*) PPU = (struct RICOH_2C02*) 8192 +(const nomodify byte*) PPU_ATTRIBUTE_TABLE_0 = (byte*) 9152 +(const nomodify byte*) PPU_NAME_TABLE_0 = (byte*) 8192 +(const nomodify byte*) PPU_PALETTE = (byte*) 16128 +(const nomodify to_volatile byte*) PPU_PPUSTATUS = (byte*) 8194 +(byte) RICOH_2A03::DMC_FREQ +(byte) RICOH_2A03::DMC_LEN +(byte) RICOH_2A03::DMC_RAW +(byte) RICOH_2A03::DMC_START +(byte) RICOH_2A03::JOY1 +(byte) RICOH_2A03::JOY2 +(byte) RICOH_2A03::NOISE_HI +(byte) RICOH_2A03::NOISE_LO +(byte) RICOH_2A03::NOISE_VOL +(byte) RICOH_2A03::OAMDMA +(byte) RICOH_2A03::SND_CHN +(byte) RICOH_2A03::SQ1_HI +(byte) RICOH_2A03::SQ1_LO +(byte) RICOH_2A03::SQ1_SWEEP +(byte) RICOH_2A03::SQ1_VOL +(byte) RICOH_2A03::SQ2_HI +(byte) RICOH_2A03::SQ2_LO +(byte) RICOH_2A03::SQ2_SWEEP +(byte) RICOH_2A03::SQ2_VOL +(byte) RICOH_2A03::TRI_HI +(byte) RICOH_2A03::TRI_LINEAR +(byte) RICOH_2A03::TRI_LO +(byte) RICOH_2A03::UNUSED1 +(byte) RICOH_2A03::UNUSED2 +(byte) RICOH_2C02::OAMADDR +(byte) RICOH_2C02::OAMDATA +(byte) RICOH_2C02::PPUADDR +(byte) RICOH_2C02::PPUCTRL +(byte) RICOH_2C02::PPUDATA +(byte) RICOH_2C02::PPUMASK +(byte) RICOH_2C02::PPUSCROLL +(volatile byte) RICOH_2C02::PPUSTATUS loadstore +(const to_nomodify byte*) SINTABLE[(number) $100] = kickasm {{ .fill $100, round(115.5+107.5*sin(2*PI*i/256)) + }} +(const byte) SIZEOF_BYTE = (byte) 1 +(const struct SpriteData*) SPRITE_BUFFER[(number) $100] = { fill( $100, 0) } +(byte) SpriteData::attributes +(byte) SpriteData::tile +(byte) SpriteData::x +(byte) SpriteData::y +(const byte*) TILES[] = kickasm {{ .var filechargen = LoadBinary("characters.901225-01.bin") + .for(var c=0; c<256; c++) { + // Plane 0 + .fill 8, filechargen.get(c*8+i) + // Plane 1 + .fill 8, 0 + } + }} +(const to_nomodify void()**) VECTORS[] = { &interrupt(HARDWARE_STACK)(void()) vblank(), &(void()) main(), (void()*) 0 } +(void()) main() +(byte~) main::$7 reg byte y 126.25 +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@4 +(label) main::@5 +(label) main::@6 +(label) main::enableVideoOutput1 +(label) main::initNES1 +(label) main::initNES1_@1 +(label) main::initNES1_@7 +(label) main::initNES1_clearVBlankFlag1 +(label) main::initNES1_disableAudioOutput1 +(label) main::initNES1_disableVideoOutput1 +(byte) main::initNES1_i +(byte) main::initNES1_i#1 reg byte x 151.5 +(byte) main::initNES1_i#2 reg byte x 112.22222222222223 +(label) main::initNES1_waitForVBlank1 +(byte~) main::initNES1_waitForVBlank1_$0 reg byte a 202.0 +(label) main::initNES1_waitForVBlank1_@1 +(label) main::initNES1_waitForVBlank2 +(byte~) main::initNES1_waitForVBlank2_$0 reg byte a 202.0 +(label) main::initNES1_waitForVBlank2_@1 +(byte) main::s +(byte) main::s#1 reg byte x 202.0 +(byte) main::s#2 reg byte x 72.14285714285714 +(void()) ppuDataFill((nomodify void*) ppuDataFill::ppuData , (byte) ppuDataFill::val , (word) ppuDataFill::size) +(label) ppuDataFill::@1 +(label) ppuDataFill::@2 +(label) ppuDataFill::@return +(word) ppuDataFill::i +(word) ppuDataFill::i#1 i zp[2]:2 2002.0 +(word) ppuDataFill::i#2 i zp[2]:2 1001.0 +(nomodify void*) ppuDataFill::ppuData +(label) ppuDataFill::ppuDataPrepare1 +(byte~) ppuDataFill::ppuDataPrepare1_$0 reg byte a 202.0 +(byte~) ppuDataFill::ppuDataPrepare1_$1 reg byte a 202.0 +(nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData +(nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0 ppuDataPrepare1_ppuData zp[2]:4 67.33333333333333 +(label) ppuDataFill::ppuDataPut1 +(byte) ppuDataFill::ppuDataPut1_val +(word) ppuDataFill::size +(word) ppuDataFill::size#3 size zp[2]:6 111.22222222222223 +(byte) ppuDataFill::val +(byte) ppuDataFill::val#4 reg byte x 111.22222222222223 +(void()) ppuDataTransfer((nomodify void*) ppuDataTransfer::ppuData , (nomodify void*) ppuDataTransfer::cpuData , (word) ppuDataTransfer::size) +(label) ppuDataTransfer::@1 +(label) ppuDataTransfer::@2 +(label) ppuDataTransfer::@3 +(label) ppuDataTransfer::@return +(nomodify void*) ppuDataTransfer::cpuData +(const nomodify void*) ppuDataTransfer::cpuData#0 cpuData = (void*)(const byte*) PALETTE +(byte*) ppuDataTransfer::cpuSrc +(byte*) ppuDataTransfer::cpuSrc#1 cpuSrc zp[2]:6 1001.0 +(byte*) ppuDataTransfer::cpuSrc#2 cpuSrc zp[2]:6 750.75 +(word) ppuDataTransfer::i +(word) ppuDataTransfer::i#1 i zp[2]:4 2002.0 +(word) ppuDataTransfer::i#2 i zp[2]:4 600.5999999999999 +(nomodify void*) ppuDataTransfer::ppuData +(const nomodify void*) ppuDataTransfer::ppuData#0 ppuData = (void*)(const nomodify byte*) PPU_PALETTE +(label) ppuDataTransfer::ppuDataPrepare1 +(nomodify void*) ppuDataTransfer::ppuDataPrepare1_ppuData +(label) ppuDataTransfer::ppuDataPut1 +(byte) ppuDataTransfer::ppuDataPut1_val +(byte) ppuDataTransfer::ppuDataPut1_val#0 reg byte a 2002.0 +(word) ppuDataTransfer::size +(const word) ppuDataTransfer::size#0 size = (byte) $20*(const byte) SIZEOF_BYTE +interrupt(HARDWARE_STACK)(void()) vblank() +(byte~) vblank::$2 reg byte a 22.0 +(byte~) vblank::$4 zp[1]:12 11.0 +(label) vblank::@1 +(label) vblank::@2 +(label) vblank::@3 +(label) vblank::@return +(label) vblank::ppuSpriteBufferDmaTransfer1 +(struct SpriteData*) vblank::ppuSpriteBufferDmaTransfer1_spriteBuffer +(byte) vblank::s +(byte) vblank::s#1 reg byte x 22.0 +(byte) vblank::s#2 reg byte x 5.5 +(byte) vblank::x_idx +(byte) vblank::x_idx#0 x_idx zp[1]:9 2.0 +(byte) vblank::x_idx#1 x_idx zp[1]:9 11.0 +(byte) vblank::x_idx#2 x_idx zp[1]:9 5.0 +(byte) vblank::y_idx +(byte) vblank::y_idx#0 y_idx zp[1]:8 1.0 +(byte) vblank::y_idx#1 y_idx zp[1]:8 7.333333333333333 +(byte) vblank::y_idx#2 y_idx zp[1]:8 5.833333333333333 +(volatile byte) x_sin_idx loadstore zp[1]:11 1.1428571428571428 +(volatile byte) y_sin_idx loadstore zp[1]:10 1.6 + +reg byte x [ main::initNES1_i#2 main::initNES1_i#1 ] +reg byte x [ main::s#2 main::s#1 ] +reg byte x [ ppuDataFill::val#4 ] +zp[2]:2 [ ppuDataFill::i#2 ppuDataFill::i#1 ] +zp[2]:4 [ ppuDataTransfer::i#2 ppuDataTransfer::i#1 ppuDataFill::ppuDataPrepare1_ppuData#0 ] +zp[2]:6 [ ppuDataTransfer::cpuSrc#2 ppuDataTransfer::cpuSrc#1 ppuDataFill::size#3 ] +reg byte x [ vblank::s#2 vblank::s#1 ] +zp[1]:8 [ vblank::y_idx#2 vblank::y_idx#1 vblank::y_idx#0 ] +zp[1]:9 [ vblank::x_idx#2 vblank::x_idx#1 vblank::x_idx#0 ] +zp[1]:10 [ y_sin_idx ] +zp[1]:11 [ x_sin_idx ] +reg byte a [ main::initNES1_waitForVBlank1_$0 ] +reg byte a [ main::initNES1_waitForVBlank2_$0 ] +reg byte y [ main::$7 ] +reg byte a [ ppuDataFill::ppuDataPrepare1_$0 ] +reg byte a [ ppuDataFill::ppuDataPrepare1_$1 ] +reg byte a [ ppuDataTransfer::ppuDataPut1_val#0 ] +zp[1]:12 [ vblank::$4 ] +reg byte a [ vblank::$2 ]