mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-09-09 08:54:40 +00:00
Added NES conio initial support. (scrolling not working atm.)
This commit is contained in:
parent
709039de87
commit
ba90f9ea65
@ -1,11 +1,11 @@
|
|||||||
// Commodore 64 Registers and Constants
|
// Commodore 64 Registers and Constants
|
||||||
|
#ifndef __C64__
|
||||||
|
#error "Target platform must be C64"
|
||||||
|
#endif
|
||||||
#include <mos6526.h>
|
#include <mos6526.h>
|
||||||
#include <mos6569.h>
|
#include <mos6569.h>
|
||||||
#include <mos6581.h>
|
#include <mos6581.h>
|
||||||
|
|
||||||
#ifndef __C64__
|
|
||||||
#error "Target platform must be C64"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Processor port data direction register
|
// Processor port data direction register
|
||||||
char* const PROCPORT_DDR = 0x00;
|
char* const PROCPORT_DDR = 0x00;
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
// Nintendo Entertainment System (NES
|
// Nintendo Entertainment System (NES
|
||||||
// https://en.wikipedia.org/wiki/Nintendo_Entertainment_System_(Model_NES-101)
|
// https://en.wikipedia.org/wiki/Nintendo_Entertainment_System_(Model_NES-101)
|
||||||
// https://github.com/gregkrsak/first_nes
|
// https://github.com/gregkrsak/first_nes
|
||||||
|
#ifndef __NES__
|
||||||
|
#error "Target platform must be NES"
|
||||||
|
#endif
|
||||||
#include <ricoh_2c02.h>
|
#include <ricoh_2c02.h>
|
||||||
#include <ricoh_2a03.h>
|
#include <ricoh_2a03.h>
|
||||||
|
|
||||||
@ -83,6 +86,10 @@ void ppuDataPrepare(void* const ppuData);
|
|||||||
// The byte is put into the current PPU address pointed to by the (autoincrementing) PPU->PPUADDR
|
// The byte is put into the current PPU address pointed to by the (autoincrementing) PPU->PPUADDR
|
||||||
void ppuDataPut(char val);
|
void ppuDataPut(char val);
|
||||||
|
|
||||||
|
// Read one byte from PPU memory
|
||||||
|
// The byte is read from the current PPU address pointed to by the (autoincrementing) PPU->PPUADDR
|
||||||
|
char ppuDataRead();
|
||||||
|
|
||||||
// Fill a number of bytes in the PPU memory
|
// Fill a number of bytes in the PPU memory
|
||||||
// - ppuData : Pointer in the PPU memory
|
// - ppuData : Pointer in the PPU memory
|
||||||
// - size : The number of bytes to transfer
|
// - size : The number of bytes to transfer
|
||||||
@ -99,8 +106,11 @@ void ppuDataTransfer(void* const ppuData, void* const cpuData, unsigned int size
|
|||||||
// - tile : The tile to transfer
|
// - tile : The tile to transfer
|
||||||
void ppuDataPutTile(void* const ppuData, char* tile);
|
void ppuDataPutTile(void* const ppuData, char* tile);
|
||||||
|
|
||||||
|
|
||||||
// Set one byte in PPU memory
|
// Set one byte in PPU memory
|
||||||
// - ppuData : Pointer in the PPU memory
|
// - ppuData : Pointer in the PPU memory
|
||||||
// - val : The value to set
|
// - val : The value to set
|
||||||
void ppuDataSet(void* const ppuData, char val);
|
void ppuDataSet(void* const ppuData, char val);
|
||||||
|
|
||||||
|
// Get one byte from PPU memory
|
||||||
|
// - ppuData : Pointer in the PPU memory
|
||||||
|
char ppuDataGet(void* const ppuData);
|
||||||
|
173
src/main/kc/lib/conio-nes.c
Normal file
173
src/main/kc/lib/conio-nes.c
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
// Conio.h implementation for NES
|
||||||
|
// No support for colors so far
|
||||||
|
// Scrolling is done by moving all chars in the PPU memory - very slowly!
|
||||||
|
#include <conio.h>
|
||||||
|
#include <nes.h>
|
||||||
|
|
||||||
|
// The screen width
|
||||||
|
#define CONIO_WIDTH 32
|
||||||
|
// The screen height
|
||||||
|
#define CONIO_HEIGHT 30
|
||||||
|
// The number of bytes on the screen
|
||||||
|
#define CONIO_BYTES CONIO_HEIGHT*CONIO_WIDTH
|
||||||
|
// The text screen address
|
||||||
|
char * const CONIO_SCREEN_TEXT = PPU_NAME_TABLE_0;
|
||||||
|
|
||||||
|
// Return true if there's any key pressed, return false if not
|
||||||
|
unsigned char kbhit (void) {
|
||||||
|
return ~readJoy1();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the color for the background. The old color setting is returned.
|
||||||
|
unsigned char bgcolor(unsigned char color) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the color for the border. The old color setting is returned.
|
||||||
|
unsigned char bordercolor(unsigned char color) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The current cursor x-position
|
||||||
|
__ma char conio_cursor_x = 0;
|
||||||
|
// The current cursor y-position
|
||||||
|
__ma char conio_cursor_y = 0;
|
||||||
|
// The current text cursor line start
|
||||||
|
__ma char *conio_line_text = CONIO_SCREEN_TEXT;
|
||||||
|
// Is a cursor shown when waiting for input (0: no, other: yes)
|
||||||
|
__ma char conio_display_cursor = 0;
|
||||||
|
// Is scrolling enabled when outputting beyond the end of the screen (1: yes, 0: no).
|
||||||
|
// If disabled the cursor just moves back to (0,0) instead
|
||||||
|
__ma char conio_scroll_enable = 1;
|
||||||
|
|
||||||
|
// clears the screen and moves the cursor to the upper left-hand corner of the screen.
|
||||||
|
void clrscr(void) {
|
||||||
|
ppuDataFill(CONIO_SCREEN_TEXT, ' ', 0x3c0);
|
||||||
|
conio_cursor_x = 0;
|
||||||
|
conio_cursor_y = 0;
|
||||||
|
conio_line_text = CONIO_SCREEN_TEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the cursor to the specified position
|
||||||
|
void gotoxy(unsigned char x, unsigned char y) {
|
||||||
|
if(y>CONIO_HEIGHT) y = 0;
|
||||||
|
if(x>=CONIO_WIDTH) x = 0;
|
||||||
|
conio_cursor_x = x;
|
||||||
|
conio_cursor_y = y;
|
||||||
|
unsigned int line_offset = (unsigned int)y*CONIO_WIDTH;
|
||||||
|
conio_line_text = CONIO_SCREEN_TEXT + line_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the current screen size.
|
||||||
|
void screensize(unsigned char* x, unsigned char* y) {
|
||||||
|
*x = CONIO_WIDTH;
|
||||||
|
*y = CONIO_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the current screen size X width.
|
||||||
|
inline char screensizex() {
|
||||||
|
return CONIO_WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the current screen size Y height.
|
||||||
|
inline char screensizey() {
|
||||||
|
return CONIO_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the X position of the cursor
|
||||||
|
inline unsigned char wherex(void) {
|
||||||
|
return conio_cursor_x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the Y position of the cursor
|
||||||
|
inline unsigned char wherey(void) {
|
||||||
|
return conio_cursor_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output one character at the current cursor position
|
||||||
|
// Moves the cursor forward. Scrolls the entire screen if needed
|
||||||
|
void cputc(char c) {
|
||||||
|
if(c=='\n') {
|
||||||
|
cputln();
|
||||||
|
} else {
|
||||||
|
ppuDataSet(conio_line_text+conio_cursor_x, c);
|
||||||
|
if(++conio_cursor_x==CONIO_WIDTH)
|
||||||
|
cputln();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print a newline
|
||||||
|
void cputln() {
|
||||||
|
conio_line_text += CONIO_WIDTH;
|
||||||
|
conio_cursor_x = 0;
|
||||||
|
conio_cursor_y++;
|
||||||
|
cscroll();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scroll the entire screen if the cursor is beyond the last line
|
||||||
|
void cscroll() {
|
||||||
|
if(conio_cursor_y==CONIO_HEIGHT) {
|
||||||
|
if(conio_scroll_enable) {
|
||||||
|
// Scroll lines up
|
||||||
|
char* line1 = CONIO_SCREEN_TEXT;
|
||||||
|
char* line2 = CONIO_SCREEN_TEXT+CONIO_WIDTH;
|
||||||
|
for(char y=0;y<CONIO_HEIGHT-1;y++) {
|
||||||
|
for(char x=0;x<CONIO_WIDTH;x++) {
|
||||||
|
char ch = ppuDataGet(line2++);
|
||||||
|
ppuDataSet(line1++, ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Fill last line with space
|
||||||
|
ppuDataFill(CONIO_SCREEN_TEXT+CONIO_BYTES-CONIO_WIDTH, ' ', CONIO_WIDTH);
|
||||||
|
conio_line_text -= CONIO_WIDTH;
|
||||||
|
conio_cursor_y--;
|
||||||
|
} else {
|
||||||
|
gotoxy(0,0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Output a NUL-terminated string at the current cursor position
|
||||||
|
void cputs(const char* s) {
|
||||||
|
char c;
|
||||||
|
while(c=*s++)
|
||||||
|
cputc(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move cursor and output one character
|
||||||
|
// Same as "gotoxy (x, y); cputc (c);"
|
||||||
|
void cputcxy(unsigned char x, unsigned char y, char c) {
|
||||||
|
gotoxy(x, y);
|
||||||
|
cputc(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move cursor and output a NUL-terminated string
|
||||||
|
// Same as "gotoxy (x, y); puts (s);"
|
||||||
|
void cputsxy(unsigned char x, unsigned char y, const char* s) {
|
||||||
|
gotoxy(x, y);
|
||||||
|
cputs(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the color for text output. The old color setting is returned.
|
||||||
|
unsigned char textcolor(unsigned char color) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If onoff is 1, a cursor is displayed when waiting for keyboard input.
|
||||||
|
// If onoff is 0, the cursor is hidden when waiting for keyboard input.
|
||||||
|
// The function returns the old cursor setting.
|
||||||
|
unsigned char cursor(unsigned char onoff) {
|
||||||
|
char old = conio_display_cursor;
|
||||||
|
conio_display_cursor = onoff;
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If onoff is 1, scrolling is enabled when outputting past the end of the screen
|
||||||
|
// If onoff is 1, scrolling is disabled and the cursor instead moves to (0,0)
|
||||||
|
// The function returns the old scroll setting.
|
||||||
|
unsigned char scroll(unsigned char onoff) {
|
||||||
|
char old = conio_scroll_enable;
|
||||||
|
conio_scroll_enable = onoff;
|
||||||
|
return old;
|
||||||
|
}
|
@ -11,6 +11,8 @@
|
|||||||
#include "conio-plus4.c"
|
#include "conio-plus4.c"
|
||||||
#elif defined(__VIC20__)
|
#elif defined(__VIC20__)
|
||||||
#include "conio-vic20.c"
|
#include "conio-vic20.c"
|
||||||
|
#elif defined(__NES__)
|
||||||
|
#include "conio-nes.c"
|
||||||
#else
|
#else
|
||||||
#error "Target platform does not support conio.h"
|
#error "Target platform does not support conio.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -120,6 +120,13 @@ inline void ppuDataPut(char val) {
|
|||||||
PPU->PPUDATA = val;
|
PPU->PPUDATA = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read one byte from PPU memory
|
||||||
|
// The byte is read from the current PPU address pointed to by the (autoincrementing) PPU->PPUADDR
|
||||||
|
inline char ppuDataRead() {
|
||||||
|
// Transfer from PPU
|
||||||
|
return PPU->PPUDATA;
|
||||||
|
}
|
||||||
|
|
||||||
// Fill a number of bytes in the PPU memory
|
// Fill a number of bytes in the PPU memory
|
||||||
// - ppuData : Pointer in the PPU memory
|
// - ppuData : Pointer in the PPU memory
|
||||||
// - size : The number of bytes to transfer
|
// - size : The number of bytes to transfer
|
||||||
@ -161,4 +168,11 @@ void ppuDataPutTile(void* const ppuData, char* tile) {
|
|||||||
void ppuDataSet(void* const ppuData, char val) {
|
void ppuDataSet(void* const ppuData, char val) {
|
||||||
ppuDataPrepare(ppuData);
|
ppuDataPrepare(ppuData);
|
||||||
ppuDataPut(val);
|
ppuDataPut(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get one byte from PPU memory
|
||||||
|
// - ppuData : Pointer in the PPU memory
|
||||||
|
char ppuDataGet(void* const ppuData) {
|
||||||
|
ppuDataPrepare(ppuData);
|
||||||
|
return ppuDataRead();
|
||||||
}
|
}
|
@ -57,6 +57,10 @@ public class TestPrograms {
|
|||||||
compileAndCompare("minus-precedence-problem.c");
|
compileAndCompare("minus-precedence-problem.c");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNesConio() throws IOException, URISyntaxException {
|
||||||
|
compileAndCompare("examples/nes-conio/nes-conio.c");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNesDemo() throws IOException, URISyntaxException {
|
public void testNesDemo() throws IOException, URISyntaxException {
|
||||||
|
189
src/test/kc/.vscode/tasks.json
vendored
189
src/test/kc/.vscode/tasks.json
vendored
@ -4,119 +4,74 @@
|
|||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"tasks": [
|
"tasks": [
|
||||||
{
|
{
|
||||||
"label": "KickAssembler",
|
"label": "KickAsm Build & Run",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "java",
|
"group": {
|
||||||
"args": [
|
"kind": "build",
|
||||||
"-jar",
|
"isDefault": true
|
||||||
"${config:kickassembler.kickAssPath}",
|
},
|
||||||
"${file}",
|
"problemMatcher": [],
|
||||||
"-odir",
|
"windows": {
|
||||||
"build",
|
"command": "java",
|
||||||
"-showmem",
|
"args": [
|
||||||
"-execute",
|
"-jar",
|
||||||
"${workspaceFolder}\\tools\\exomize.bat"
|
"KickAss.jar",
|
||||||
],
|
"${file}",
|
||||||
"group": "build",
|
"-showmem",
|
||||||
"problemMatcher": []
|
"-vicesymbols",
|
||||||
|
"-execute",
|
||||||
|
"x64sc"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"osx": {
|
||||||
|
"command": "java",
|
||||||
|
"args": [
|
||||||
|
"-jar",
|
||||||
|
"/Applications/KickAssembler/KickAss.jar",
|
||||||
|
"${file}",
|
||||||
|
"-showmem",
|
||||||
|
"-vicesymbols",
|
||||||
|
"-execute",
|
||||||
|
"open -a x64sc"
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "KickAsm Vice",
|
"label": "KickAsm Build & Debug",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "java",
|
"group": {
|
||||||
"args": [
|
"kind": "build",
|
||||||
"-jar",
|
"isDefault": true
|
||||||
"${config:kickassembler.kickAssPath}",
|
},
|
||||||
"${file}",
|
"problemMatcher": [],
|
||||||
"-define",
|
"windows": {
|
||||||
"AUTORUN",
|
"command": "java",
|
||||||
"-showmem",
|
"args": [
|
||||||
"-vicesymbols",
|
"-jar",
|
||||||
"-execute",
|
"KickAss.jar",
|
||||||
"\"${config:vice.vicePath}\" -moncommands ${fileBasenameNoExtension}.vs"
|
"${file}",
|
||||||
],
|
"-showmem",
|
||||||
"group": "build"
|
"-vicesymbols",
|
||||||
},
|
"-execute",
|
||||||
{
|
"C64Debugger"
|
||||||
"label": "KickAsm Vice Debug",
|
]
|
||||||
"type": "shell",
|
},
|
||||||
"command": "java",
|
"osx": {
|
||||||
"args": [
|
"command": "java",
|
||||||
"-jar",
|
"args": [
|
||||||
"${config:kickassembler.kickAssPath}",
|
"-jar",
|
||||||
"${file}",
|
"/Applications/KickAssembler/KickAss.jar",
|
||||||
"-odir",
|
"${file}",
|
||||||
"debug",
|
"-showmem",
|
||||||
"-define",
|
"-vicesymbols",
|
||||||
"AUTORUN",
|
"-execute",
|
||||||
"-define",
|
"open -a C64Debugger"
|
||||||
"DEBUG",
|
]
|
||||||
"-showmem",
|
}
|
||||||
"-vicesymbols",
|
},
|
||||||
":debug=true",
|
|
||||||
"-execute",
|
|
||||||
"\"${config:vice.vicePath}\" -moncommands ${fileBasenameNoExtension}.vs"
|
|
||||||
],
|
|
||||||
"group": "build"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "KickAsm C64Debugger",
|
|
||||||
"type": "shell",
|
|
||||||
"command": "java",
|
|
||||||
"args": [
|
|
||||||
"-jar",
|
|
||||||
"${config:kickassembler.kickAssPath}",
|
|
||||||
"${file}",
|
|
||||||
"-odir",
|
|
||||||
"bin",
|
|
||||||
"-define",
|
|
||||||
"AUTORUN",
|
|
||||||
"-showmem",
|
|
||||||
"-debugdump",
|
|
||||||
"-execute",
|
|
||||||
"\"${config:c64debugger.c64debuggerPath}\""
|
|
||||||
],
|
|
||||||
"group": "build"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "KickAsm C64Debugger Debug",
|
|
||||||
"type": "shell",
|
|
||||||
"command": "java",
|
|
||||||
"args": [
|
|
||||||
"-jar",
|
|
||||||
"${config:kickassembler.kickAssPath}",
|
|
||||||
"${file}",
|
|
||||||
"-odir",
|
|
||||||
"debug",
|
|
||||||
"-define",
|
|
||||||
"AUTORUN",
|
|
||||||
"-define",
|
|
||||||
"DEBUG",
|
|
||||||
"-showmem",
|
|
||||||
"-debugdump",
|
|
||||||
":debug=true",
|
|
||||||
"-execute",
|
|
||||||
"\"${config:c64debugger.c64debuggerPath}\""
|
|
||||||
],
|
|
||||||
"group": "build"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "KickAsm Build",
|
|
||||||
"command": "java",
|
|
||||||
"args": [
|
|
||||||
"-jar",
|
|
||||||
"${config:kickassembler.kickAssPath}",
|
|
||||||
"${file}",
|
|
||||||
"-odir",
|
|
||||||
"build",
|
|
||||||
"-showmem"
|
|
||||||
],
|
|
||||||
"group": "build"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"label": "KickC Build & Run",
|
"label": "KickC Build & Run",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"cwd": "${workspaceFolder}",
|
|
||||||
"group": {
|
"group": {
|
||||||
"kind": "build",
|
"kind": "build",
|
||||||
"isDefault": true
|
"isDefault": true
|
||||||
@ -130,7 +85,8 @@
|
|||||||
"c:/c64/tmp/",
|
"c:/c64/tmp/",
|
||||||
"-e",
|
"-e",
|
||||||
"${relativeFile}"
|
"${relativeFile}"
|
||||||
] },
|
]
|
||||||
|
},
|
||||||
"osx": {
|
"osx": {
|
||||||
"command": "~/c64/kickc_local/bin/kickc.sh",
|
"command": "~/c64/kickc_local/bin/kickc.sh",
|
||||||
"args": [
|
"args": [
|
||||||
@ -141,18 +97,9 @@
|
|||||||
"${relativeFile}"
|
"${relativeFile}"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
{
|
|
||||||
"label": "Exomize Build",
|
|
||||||
"command": "${workspaceFolder}\\tools\\exomize.bat",
|
|
||||||
"args": [
|
|
||||||
"${config:exomizer.exomizerPath}",
|
|
||||||
"${file}"
|
|
||||||
],
|
|
||||||
"dependsOn": [
|
|
||||||
"KickAsm Build"
|
|
||||||
],
|
|
||||||
"group": "build"
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BIN
src/test/kc/examples/nes-conio/characters.901225-01.bin
Normal file
BIN
src/test/kc/examples/nes-conio/characters.901225-01.bin
Normal file
Binary file not shown.
96
src/test/kc/examples/nes-conio/nes-conio.c
Normal file
96
src/test/kc/examples/nes-conio/nes-conio.c
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
// NES conio printing
|
||||||
|
#pragma target(nes)
|
||||||
|
#include <nes.h>
|
||||||
|
#include <conio.h>
|
||||||
|
|
||||||
|
// 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_ATTRIBUTE_TABLE_0, 0, 0x40);
|
||||||
|
ppuDataFill(PPU_ATTRIBUTE_TABLE_1, 0, 0x40);
|
||||||
|
// Print a string
|
||||||
|
clrscr();
|
||||||
|
cputs("hello world!\ni am nes\n look at me \n\n");
|
||||||
|
|
||||||
|
x_scroll = 0;
|
||||||
|
y_scroll = -8;
|
||||||
|
|
||||||
|
|
||||||
|
// Enable screen rendering and vblank
|
||||||
|
enableVideoOutput();
|
||||||
|
// Infinite loop
|
||||||
|
while(1) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
volatile char x_scroll;
|
||||||
|
volatile char y_scroll;
|
||||||
|
|
||||||
|
// NMI Called when the PPU refreshes the screen (also known as the V-Blank period)
|
||||||
|
interrupt(hardware_stack) void vblank() {
|
||||||
|
// Read controller 1
|
||||||
|
char joy = readJoy1();
|
||||||
|
if(joy&JOY_DOWN) {
|
||||||
|
if(++y_scroll==240)
|
||||||
|
y_scroll=0;
|
||||||
|
}
|
||||||
|
if(joy&JOY_UP) {
|
||||||
|
if(--y_scroll==255)
|
||||||
|
y_scroll=239;
|
||||||
|
}
|
||||||
|
if(joy&JOY_LEFT) {
|
||||||
|
x_scroll++;
|
||||||
|
}
|
||||||
|
if(joy&JOY_RIGHT) {
|
||||||
|
x_scroll--;
|
||||||
|
}
|
||||||
|
|
||||||
|
PPU->PPUSCROLL = x_scroll;
|
||||||
|
PPU->PPUSCROLL = y_scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Data (in PRG ROM)
|
||||||
|
#pragma data_seg(Data)
|
||||||
|
|
||||||
|
char MESSAGE[] = "hello world!";
|
||||||
|
|
||||||
|
// 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
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
||||||
|
// 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
|
||||||
|
};
|
674
src/test/ref/examples/nes-conio/nes-conio.asm
Normal file
674
src/test/ref/examples/nes-conio/nes-conio.asm
Normal file
@ -0,0 +1,674 @@
|
|||||||
|
// NES conio printing
|
||||||
|
// 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-conio.nes", type="bin", segments="NesRom"]
|
||||||
|
.file [name="nes-conio.nes_hdr", type="bin", segments="Header"]
|
||||||
|
.file [name="nes-conio.nes_prg", type="bin", segments="ProgramRom"]
|
||||||
|
.file [name="nes-conio.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
|
||||||
|
|
||||||
|
// Standard Controller Right Button
|
||||||
|
.const JOY_RIGHT = 1
|
||||||
|
// Standard Controller Left Button
|
||||||
|
.const JOY_LEFT = 2
|
||||||
|
// Standard Controller Down Button
|
||||||
|
.const JOY_DOWN = 4
|
||||||
|
// Standard Controller Up Button
|
||||||
|
.const JOY_UP = 8
|
||||||
|
.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_2A03_JOY1 = $16
|
||||||
|
.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
|
||||||
|
// $27c0-$27ff $0040 Attribute table 1
|
||||||
|
.label PPU_ATTRIBUTE_TABLE_1 = $27c0
|
||||||
|
// $3000-$3eff $0f00 Mirrors of $2000-$2eff
|
||||||
|
// $3f00-$3f1f $0020 Palette RAM indexes
|
||||||
|
.label PPU_PALETTE = $3f00
|
||||||
|
// 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
|
||||||
|
// PPU Status Register for reading in ASM
|
||||||
|
.label PPU_PPUSTATUS = $2002
|
||||||
|
// NES Picture Processing Unit (PPU)
|
||||||
|
.label PPU = $2000
|
||||||
|
// NES CPU and audion processing unit (APU)
|
||||||
|
.label APU = $4000
|
||||||
|
.label conio_cursor_x = $b
|
||||||
|
.label conio_cursor_y = $c
|
||||||
|
.label conio_line_text = $d
|
||||||
|
.label x_scroll = $f
|
||||||
|
.label y_scroll = $10
|
||||||
|
__bbegin:
|
||||||
|
// conio_cursor_x = 0
|
||||||
|
// The current cursor x-position
|
||||||
|
lda #0
|
||||||
|
sta.z conio_cursor_x
|
||||||
|
// conio_cursor_y = 0
|
||||||
|
// The current cursor y-position
|
||||||
|
sta.z conio_cursor_y
|
||||||
|
// conio_line_text = CONIO_SCREEN_TEXT
|
||||||
|
// The current text cursor line start
|
||||||
|
lda #<PPU_NAME_TABLE_0
|
||||||
|
sta.z conio_line_text
|
||||||
|
lda #>PPU_NAME_TABLE_0
|
||||||
|
sta.z conio_line_text+1
|
||||||
|
// x_scroll
|
||||||
|
lda #0
|
||||||
|
sta.z x_scroll
|
||||||
|
// y_scroll
|
||||||
|
sta.z y_scroll
|
||||||
|
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_ATTRIBUTE_TABLE_0, 0, 0x40)
|
||||||
|
// Fill the PPU attribute table
|
||||||
|
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
|
||||||
|
lda #>PPU_ATTRIBUTE_TABLE_0
|
||||||
|
sta.z ppuDataFill.ppuDataPrepare1_ppuData+1
|
||||||
|
jsr ppuDataFill
|
||||||
|
// ppuDataFill(PPU_ATTRIBUTE_TABLE_1, 0, 0x40)
|
||||||
|
ldx #0
|
||||||
|
lda #<$40
|
||||||
|
sta.z ppuDataFill.size
|
||||||
|
lda #>$40
|
||||||
|
sta.z ppuDataFill.size+1
|
||||||
|
lda #<PPU_ATTRIBUTE_TABLE_1
|
||||||
|
sta.z ppuDataFill.ppuDataPrepare1_ppuData
|
||||||
|
lda #>PPU_ATTRIBUTE_TABLE_1
|
||||||
|
sta.z ppuDataFill.ppuDataPrepare1_ppuData+1
|
||||||
|
jsr ppuDataFill
|
||||||
|
// clrscr()
|
||||||
|
// Print a string
|
||||||
|
jsr clrscr
|
||||||
|
// cputs("hello world!\ni am nes\n look at me \n\n")
|
||||||
|
jsr cputs
|
||||||
|
// x_scroll = 0
|
||||||
|
lda #0
|
||||||
|
sta.z x_scroll
|
||||||
|
// y_scroll = -8
|
||||||
|
lda #-8
|
||||||
|
sta.z y_scroll
|
||||||
|
// PPU->PPUCTRL = 0b10000000
|
||||||
|
lda #$80
|
||||||
|
sta PPU
|
||||||
|
// PPU->PPUMASK = 0b00011110
|
||||||
|
lda #$1e
|
||||||
|
sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUMASK
|
||||||
|
__b1:
|
||||||
|
// Infinite loop
|
||||||
|
jmp __b1
|
||||||
|
.segment Data
|
||||||
|
s: .text @"hello world!\ni am nes\n look at me \n\n"
|
||||||
|
.byte 0
|
||||||
|
}
|
||||||
|
.segment Code
|
||||||
|
// Output a NUL-terminated string at the current cursor position
|
||||||
|
// cputs(byte* zp(7) s)
|
||||||
|
cputs: {
|
||||||
|
.label s = 7
|
||||||
|
lda #<main.s
|
||||||
|
sta.z s
|
||||||
|
lda #>main.s
|
||||||
|
sta.z s+1
|
||||||
|
__b1:
|
||||||
|
// c=*s++
|
||||||
|
ldy #0
|
||||||
|
lda (s),y
|
||||||
|
// while(c=*s++)
|
||||||
|
inc.z s
|
||||||
|
bne !+
|
||||||
|
inc.z s+1
|
||||||
|
!:
|
||||||
|
cmp #0
|
||||||
|
bne __b2
|
||||||
|
// }
|
||||||
|
rts
|
||||||
|
__b2:
|
||||||
|
// cputc(c)
|
||||||
|
tax
|
||||||
|
jsr cputc
|
||||||
|
jmp __b1
|
||||||
|
}
|
||||||
|
// Output one character at the current cursor position
|
||||||
|
// Moves the cursor forward. Scrolls the entire screen if needed
|
||||||
|
// cputc(byte register(X) c)
|
||||||
|
cputc: {
|
||||||
|
// if(c=='\n')
|
||||||
|
cpx #'\n'
|
||||||
|
beq __b1
|
||||||
|
// conio_line_text+conio_cursor_x
|
||||||
|
lda.z conio_cursor_x
|
||||||
|
clc
|
||||||
|
adc.z conio_line_text
|
||||||
|
sta.z ppuDataSet.ppuData
|
||||||
|
lda #0
|
||||||
|
adc.z conio_line_text+1
|
||||||
|
sta.z ppuDataSet.ppuData+1
|
||||||
|
// ppuDataSet(conio_line_text+conio_cursor_x, c)
|
||||||
|
// ppuDataSet(conio_line_text+conio_cursor_x, c)
|
||||||
|
jsr ppuDataSet
|
||||||
|
// if(++conio_cursor_x==CONIO_WIDTH)
|
||||||
|
inc.z conio_cursor_x
|
||||||
|
lda #$20
|
||||||
|
cmp.z conio_cursor_x
|
||||||
|
bne __breturn
|
||||||
|
// cputln()
|
||||||
|
jsr cputln
|
||||||
|
__breturn:
|
||||||
|
// }
|
||||||
|
rts
|
||||||
|
__b1:
|
||||||
|
// cputln()
|
||||||
|
jsr cputln
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// Print a newline
|
||||||
|
cputln: {
|
||||||
|
// conio_line_text += CONIO_WIDTH
|
||||||
|
lda #$20
|
||||||
|
clc
|
||||||
|
adc.z conio_line_text
|
||||||
|
sta.z conio_line_text
|
||||||
|
bcc !+
|
||||||
|
inc.z conio_line_text+1
|
||||||
|
!:
|
||||||
|
// conio_cursor_x = 0
|
||||||
|
lda #0
|
||||||
|
sta.z conio_cursor_x
|
||||||
|
// conio_cursor_y++;
|
||||||
|
inc.z conio_cursor_y
|
||||||
|
// cscroll()
|
||||||
|
jsr cscroll
|
||||||
|
// }
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// Scroll the entire screen if the cursor is beyond the last line
|
||||||
|
cscroll: {
|
||||||
|
.label line2 = 9
|
||||||
|
// Scroll lines up
|
||||||
|
.label line1 = 3
|
||||||
|
.label y = 2
|
||||||
|
// if(conio_cursor_y==CONIO_HEIGHT)
|
||||||
|
lda #$1e
|
||||||
|
cmp.z conio_cursor_y
|
||||||
|
bne __breturn
|
||||||
|
lda #<PPU_NAME_TABLE_0
|
||||||
|
sta.z line1
|
||||||
|
lda #>PPU_NAME_TABLE_0
|
||||||
|
sta.z line1+1
|
||||||
|
lda #<PPU_NAME_TABLE_0+$20
|
||||||
|
sta.z line2
|
||||||
|
lda #>PPU_NAME_TABLE_0+$20
|
||||||
|
sta.z line2+1
|
||||||
|
lda #0
|
||||||
|
sta.z y
|
||||||
|
__b1:
|
||||||
|
// for(char y=0;y<CONIO_HEIGHT-1;y++)
|
||||||
|
lda.z y
|
||||||
|
cmp #$1e-1
|
||||||
|
bcc __b2
|
||||||
|
// ppuDataFill(CONIO_SCREEN_TEXT+CONIO_BYTES-CONIO_WIDTH, ' ', CONIO_WIDTH)
|
||||||
|
// Fill last line with space
|
||||||
|
ldx #' '
|
||||||
|
lda #<$20
|
||||||
|
sta.z ppuDataFill.size
|
||||||
|
lda #>$20
|
||||||
|
sta.z ppuDataFill.size+1
|
||||||
|
lda #<PPU_NAME_TABLE_0+$1e*$20-$20
|
||||||
|
sta.z ppuDataFill.ppuDataPrepare1_ppuData
|
||||||
|
lda #>PPU_NAME_TABLE_0+$1e*$20-$20
|
||||||
|
sta.z ppuDataFill.ppuDataPrepare1_ppuData+1
|
||||||
|
jsr ppuDataFill
|
||||||
|
// conio_line_text -= CONIO_WIDTH
|
||||||
|
sec
|
||||||
|
lda.z conio_line_text
|
||||||
|
sbc #$20
|
||||||
|
sta.z conio_line_text
|
||||||
|
lda.z conio_line_text+1
|
||||||
|
sbc #0
|
||||||
|
sta.z conio_line_text+1
|
||||||
|
// conio_cursor_y--;
|
||||||
|
dec.z conio_cursor_y
|
||||||
|
__breturn:
|
||||||
|
// }
|
||||||
|
rts
|
||||||
|
__b2:
|
||||||
|
ldy #0
|
||||||
|
__b3:
|
||||||
|
// for(char x=0;x<CONIO_WIDTH;x++)
|
||||||
|
cpy #$20
|
||||||
|
bcc __b4
|
||||||
|
// for(char y=0;y<CONIO_HEIGHT-1;y++)
|
||||||
|
inc.z y
|
||||||
|
jmp __b1
|
||||||
|
__b4:
|
||||||
|
// ppuDataGet(line2++)
|
||||||
|
lda.z line2
|
||||||
|
sta.z ppuDataGet.ppuData
|
||||||
|
lda.z line2+1
|
||||||
|
sta.z ppuDataGet.ppuData+1
|
||||||
|
jsr ppuDataGet
|
||||||
|
// ppuDataGet(line2++)
|
||||||
|
// ch = ppuDataGet(line2++)
|
||||||
|
tax
|
||||||
|
inc.z line2
|
||||||
|
bne !+
|
||||||
|
inc.z line2+1
|
||||||
|
!:
|
||||||
|
// ppuDataSet(line1++, ch)
|
||||||
|
lda.z line1
|
||||||
|
sta.z ppuDataSet.ppuData
|
||||||
|
lda.z line1+1
|
||||||
|
sta.z ppuDataSet.ppuData+1
|
||||||
|
jsr ppuDataSet
|
||||||
|
// ppuDataSet(line1++, ch);
|
||||||
|
inc.z line1
|
||||||
|
bne !+
|
||||||
|
inc.z line1+1
|
||||||
|
!:
|
||||||
|
// for(char x=0;x<CONIO_WIDTH;x++)
|
||||||
|
iny
|
||||||
|
jmp __b3
|
||||||
|
}
|
||||||
|
// Set one byte in PPU memory
|
||||||
|
// - ppuData : Pointer in the PPU memory
|
||||||
|
// - val : The value to set
|
||||||
|
// ppuDataSet(byte* zp(5) ppuData, byte register(X) val)
|
||||||
|
ppuDataSet: {
|
||||||
|
.label ppuDataPrepare1_ppuData = 5
|
||||||
|
.label ppuData = 5
|
||||||
|
// >ppuData
|
||||||
|
lda.z ppuDataPrepare1_ppuData+1
|
||||||
|
// PPU->PPUADDR = >ppuData
|
||||||
|
sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUADDR
|
||||||
|
// <ppuData
|
||||||
|
lda.z ppuDataPrepare1_ppuData
|
||||||
|
// PPU->PPUADDR = <ppuData
|
||||||
|
sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUADDR
|
||||||
|
// PPU->PPUDATA = val
|
||||||
|
stx PPU+OFFSET_STRUCT_RICOH_2C02_PPUDATA
|
||||||
|
// }
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// Get one byte from PPU memory
|
||||||
|
// - ppuData : Pointer in the PPU memory
|
||||||
|
// ppuDataGet(void* zp($11) ppuData)
|
||||||
|
ppuDataGet: {
|
||||||
|
.label ppuData = $11
|
||||||
|
// >ppuData
|
||||||
|
lda.z ppuData+1
|
||||||
|
// PPU->PPUADDR = >ppuData
|
||||||
|
sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUADDR
|
||||||
|
// <ppuData
|
||||||
|
lda.z ppuData
|
||||||
|
// PPU->PPUADDR = <ppuData
|
||||||
|
sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUADDR
|
||||||
|
// return PPU->PPUDATA;
|
||||||
|
lda PPU+OFFSET_STRUCT_RICOH_2C02_PPUDATA
|
||||||
|
// }
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// 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($11) size)
|
||||||
|
ppuDataFill: {
|
||||||
|
.label ppuDataPrepare1_ppuData = 5
|
||||||
|
.label i = 9
|
||||||
|
.label size = $11
|
||||||
|
// >ppuData
|
||||||
|
lda.z ppuDataPrepare1_ppuData+1
|
||||||
|
// PPU->PPUADDR = >ppuData
|
||||||
|
sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUADDR
|
||||||
|
// <ppuData
|
||||||
|
lda.z ppuDataPrepare1_ppuData
|
||||||
|
// PPU->PPUADDR = <ppuData
|
||||||
|
sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUADDR
|
||||||
|
lda #<0
|
||||||
|
sta.z i
|
||||||
|
sta.z i+1
|
||||||
|
// Transfer to PPU
|
||||||
|
__b1:
|
||||||
|
// for(unsigned int i=0;i<size;i++)
|
||||||
|
lda.z i+1
|
||||||
|
cmp.z size+1
|
||||||
|
bcc ppuDataPut1
|
||||||
|
bne !+
|
||||||
|
lda.z i
|
||||||
|
cmp.z size
|
||||||
|
bcc ppuDataPut1
|
||||||
|
!:
|
||||||
|
// }
|
||||||
|
rts
|
||||||
|
ppuDataPut1:
|
||||||
|
// PPU->PPUDATA = val
|
||||||
|
stx PPU+OFFSET_STRUCT_RICOH_2C02_PPUDATA
|
||||||
|
// for(unsigned int i=0;i<size;i++)
|
||||||
|
inc.z i
|
||||||
|
bne !+
|
||||||
|
inc.z i+1
|
||||||
|
!:
|
||||||
|
jmp __b1
|
||||||
|
}
|
||||||
|
// clears the screen and moves the cursor to the upper left-hand corner of the screen.
|
||||||
|
clrscr: {
|
||||||
|
// ppuDataFill(CONIO_SCREEN_TEXT, ' ', 0x3c0)
|
||||||
|
ldx #' '
|
||||||
|
lda #<$3c0
|
||||||
|
sta.z ppuDataFill.size
|
||||||
|
lda #>$3c0
|
||||||
|
sta.z ppuDataFill.size+1
|
||||||
|
lda #<PPU_NAME_TABLE_0
|
||||||
|
sta.z ppuDataFill.ppuDataPrepare1_ppuData
|
||||||
|
lda #>PPU_NAME_TABLE_0
|
||||||
|
sta.z ppuDataFill.ppuDataPrepare1_ppuData+1
|
||||||
|
jsr ppuDataFill
|
||||||
|
// conio_cursor_x = 0
|
||||||
|
lda #0
|
||||||
|
sta.z conio_cursor_x
|
||||||
|
// conio_cursor_y = 0
|
||||||
|
sta.z conio_cursor_y
|
||||||
|
// conio_line_text = CONIO_SCREEN_TEXT
|
||||||
|
lda #<PPU_NAME_TABLE_0
|
||||||
|
sta.z conio_line_text
|
||||||
|
lda #>PPU_NAME_TABLE_0
|
||||||
|
sta.z conio_line_text+1
|
||||||
|
// }
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// 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 = 9
|
||||||
|
.label i = 7
|
||||||
|
// PPU->PPUADDR = >ppuData
|
||||||
|
lda #>ppuData
|
||||||
|
sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUADDR
|
||||||
|
// PPU->PPUADDR = <ppuData
|
||||||
|
lda #0
|
||||||
|
sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUADDR
|
||||||
|
lda #<cpuData
|
||||||
|
sta.z cpuSrc
|
||||||
|
lda #>cpuData
|
||||||
|
sta.z cpuSrc+1
|
||||||
|
lda #<0
|
||||||
|
sta.z i
|
||||||
|
sta.z i+1
|
||||||
|
__b1:
|
||||||
|
// for(unsigned int i=0;i<size;i++)
|
||||||
|
lda.z i+1
|
||||||
|
cmp #>size
|
||||||
|
bcc __b2
|
||||||
|
bne !+
|
||||||
|
lda.z i
|
||||||
|
cmp #<size
|
||||||
|
bcc __b2
|
||||||
|
!:
|
||||||
|
// }
|
||||||
|
rts
|
||||||
|
__b2:
|
||||||
|
// ppuDataPut(*cpuSrc++)
|
||||||
|
ldy #0
|
||||||
|
lda (cpuSrc),y
|
||||||
|
// PPU->PPUDATA = val
|
||||||
|
sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUDATA
|
||||||
|
// ppuDataPut(*cpuSrc++);
|
||||||
|
inc.z cpuSrc
|
||||||
|
bne !+
|
||||||
|
inc.z cpuSrc+1
|
||||||
|
!:
|
||||||
|
// for(unsigned int i=0;i<size;i++)
|
||||||
|
inc.z i
|
||||||
|
bne !+
|
||||||
|
inc.z i+1
|
||||||
|
!:
|
||||||
|
jmp __b1
|
||||||
|
}
|
||||||
|
// NMI Called when the PPU refreshes the screen (also known as the V-Blank period)
|
||||||
|
vblank: {
|
||||||
|
pha
|
||||||
|
txa
|
||||||
|
pha
|
||||||
|
tya
|
||||||
|
pha
|
||||||
|
// readJoy1()
|
||||||
|
jsr readJoy1
|
||||||
|
// joy = readJoy1()
|
||||||
|
tax
|
||||||
|
// joy&JOY_DOWN
|
||||||
|
txa
|
||||||
|
and #JOY_DOWN
|
||||||
|
// if(joy&JOY_DOWN)
|
||||||
|
cmp #0
|
||||||
|
beq __b1
|
||||||
|
// if(++y_scroll==240)
|
||||||
|
inc.z y_scroll
|
||||||
|
lda #$f0
|
||||||
|
cmp.z y_scroll
|
||||||
|
bne __b1
|
||||||
|
// y_scroll=0
|
||||||
|
lda #0
|
||||||
|
sta.z y_scroll
|
||||||
|
__b1:
|
||||||
|
// joy&JOY_UP
|
||||||
|
txa
|
||||||
|
and #JOY_UP
|
||||||
|
// if(joy&JOY_UP)
|
||||||
|
cmp #0
|
||||||
|
beq __b2
|
||||||
|
// if(--y_scroll==255)
|
||||||
|
dec.z y_scroll
|
||||||
|
lda #$ff
|
||||||
|
cmp.z y_scroll
|
||||||
|
bne __b2
|
||||||
|
// y_scroll=239
|
||||||
|
lda #$ef
|
||||||
|
sta.z y_scroll
|
||||||
|
__b2:
|
||||||
|
// joy&JOY_LEFT
|
||||||
|
txa
|
||||||
|
and #JOY_LEFT
|
||||||
|
// if(joy&JOY_LEFT)
|
||||||
|
cmp #0
|
||||||
|
beq __b3
|
||||||
|
// x_scroll++;
|
||||||
|
inc.z x_scroll
|
||||||
|
__b3:
|
||||||
|
// joy&JOY_RIGHT
|
||||||
|
txa
|
||||||
|
and #JOY_RIGHT
|
||||||
|
// if(joy&JOY_RIGHT)
|
||||||
|
cmp #0
|
||||||
|
beq __b4
|
||||||
|
// x_scroll--;
|
||||||
|
dec.z x_scroll
|
||||||
|
__b4:
|
||||||
|
// PPU->PPUSCROLL = x_scroll
|
||||||
|
lda.z x_scroll
|
||||||
|
sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUSCROLL
|
||||||
|
// PPU->PPUSCROLL = y_scroll
|
||||||
|
lda.z y_scroll
|
||||||
|
sta PPU+OFFSET_STRUCT_RICOH_2C02_PPUSCROLL
|
||||||
|
// }
|
||||||
|
pla
|
||||||
|
tay
|
||||||
|
pla
|
||||||
|
tax
|
||||||
|
pla
|
||||||
|
rti
|
||||||
|
}
|
||||||
|
// Read Standard Controller #1
|
||||||
|
// Returns a byte representing the pushed buttons
|
||||||
|
// - bit 0: right
|
||||||
|
// - bit 1: left
|
||||||
|
// - bit 2: down
|
||||||
|
// - bit 3: up
|
||||||
|
// - bit 4: start
|
||||||
|
// - bit 5: select
|
||||||
|
// - bit 6: B
|
||||||
|
// - bit 7: A
|
||||||
|
readJoy1: {
|
||||||
|
.label __1 = $13
|
||||||
|
// APU->JOY1 = 1
|
||||||
|
// Latch the controller buttons
|
||||||
|
lda #1
|
||||||
|
sta APU+OFFSET_STRUCT_RICOH_2A03_JOY1
|
||||||
|
// APU->JOY1 = 0
|
||||||
|
lda #0
|
||||||
|
sta APU+OFFSET_STRUCT_RICOH_2A03_JOY1
|
||||||
|
tax
|
||||||
|
__b1:
|
||||||
|
// for(char i=0;i<8;i++)
|
||||||
|
cpx #8
|
||||||
|
bcc __b2
|
||||||
|
// }
|
||||||
|
rts
|
||||||
|
__b2:
|
||||||
|
// joy<<1
|
||||||
|
asl
|
||||||
|
sta.z __1
|
||||||
|
// APU->JOY1&1
|
||||||
|
lda #1
|
||||||
|
and APU+OFFSET_STRUCT_RICOH_2A03_JOY1
|
||||||
|
// joy = joy<<1 | APU->JOY1&1
|
||||||
|
ora.z __1
|
||||||
|
// for(char i=0;i<8;i++)
|
||||||
|
inx
|
||||||
|
jmp __b1
|
||||||
|
}
|
||||||
|
.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
|
||||||
|
.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 Vectors
|
||||||
|
VECTORS: .word vblank, main, 0
|
374
src/test/ref/examples/nes-conio/nes-conio.cfg
Normal file
374
src/test/ref/examples/nes-conio/nes-conio.cfg
Normal file
@ -0,0 +1,374 @@
|
|||||||
|
@begin: scope:[] from
|
||||||
|
[0] phi()
|
||||||
|
to:@1
|
||||||
|
@1: scope:[] from @begin
|
||||||
|
[1] (byte) conio_cursor_x ← (byte) 0
|
||||||
|
[2] (byte) conio_cursor_y ← (byte) 0
|
||||||
|
[3] (byte*) conio_line_text ← (const nomodify byte*) PPU_NAME_TABLE_0
|
||||||
|
to:@2
|
||||||
|
@2: scope:[] from @1
|
||||||
|
[4] (volatile byte) x_scroll ← (byte) 0
|
||||||
|
[5] (volatile byte) y_scroll ← (byte) 0
|
||||||
|
to:@3
|
||||||
|
@3: scope:[] from @2
|
||||||
|
[6] phi()
|
||||||
|
[7] call main
|
||||||
|
to:@end
|
||||||
|
@end: scope:[] from @3
|
||||||
|
[8] phi()
|
||||||
|
|
||||||
|
(void()) main()
|
||||||
|
main: scope:[main] from @3
|
||||||
|
[9] 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
|
||||||
|
[11] *((byte*)(const struct RICOH_2C02*) PPU) ← (byte) 0
|
||||||
|
[12] *((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
|
||||||
|
[13] *((const nomodify byte*) FR_COUNTER) ← (byte) $40
|
||||||
|
[14] *((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
|
||||||
|
[16] phi()
|
||||||
|
to:main::initNES1_waitForVBlank1_@1
|
||||||
|
main::initNES1_waitForVBlank1_@1: scope:[main] from main::initNES1_waitForVBlank1 main::initNES1_waitForVBlank1_@1
|
||||||
|
[17] (byte~) main::initNES1_waitForVBlank1_$0 ← *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSTATUS) & (byte) $80
|
||||||
|
[18] 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
|
||||||
|
[19] (byte) main::initNES1_i#2 ← phi( main::initNES1_@1/(byte) main::initNES1_i#1 main::initNES1_waitForVBlank1_@1/(byte) 0 )
|
||||||
|
[20] *((const nomodify byte*) MEMORY + (byte) main::initNES1_i#2) ← (byte) 0
|
||||||
|
[21] *((const nomodify byte*) MEMORY+(word) $100 + (byte) main::initNES1_i#2) ← (byte) 0
|
||||||
|
[22] *((const nomodify byte*) MEMORY+(word) $200 + (byte) main::initNES1_i#2) ← (byte) 0
|
||||||
|
[23] *((const nomodify byte*) MEMORY+(word) $300 + (byte) main::initNES1_i#2) ← (byte) 0
|
||||||
|
[24] *((const nomodify byte*) MEMORY+(word) $400 + (byte) main::initNES1_i#2) ← (byte) 0
|
||||||
|
[25] *((const nomodify byte*) MEMORY+(word) $500 + (byte) main::initNES1_i#2) ← (byte) 0
|
||||||
|
[26] *((const nomodify byte*) MEMORY+(word) $600 + (byte) main::initNES1_i#2) ← (byte) 0
|
||||||
|
[27] *((const nomodify byte*) MEMORY+(word) $700 + (byte) main::initNES1_i#2) ← (byte) 0
|
||||||
|
[28] (byte) main::initNES1_i#1 ← ++ (byte) main::initNES1_i#2
|
||||||
|
[29] 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
|
||||||
|
[30] phi()
|
||||||
|
to:main::initNES1_waitForVBlank2_@1
|
||||||
|
main::initNES1_waitForVBlank2_@1: scope:[main] from main::initNES1_waitForVBlank2 main::initNES1_waitForVBlank2_@1
|
||||||
|
[31] (byte~) main::initNES1_waitForVBlank2_$0 ← *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSTATUS) & (byte) $80
|
||||||
|
[32] 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::@2
|
||||||
|
main::@2: scope:[main] from main::initNES1_@7
|
||||||
|
[34] phi()
|
||||||
|
[35] call ppuDataTransfer
|
||||||
|
to:main::@3
|
||||||
|
main::@3: scope:[main] from main::@2
|
||||||
|
[36] phi()
|
||||||
|
[37] call ppuDataFill
|
||||||
|
to:main::@4
|
||||||
|
main::@4: scope:[main] from main::@3
|
||||||
|
[38] phi()
|
||||||
|
[39] call ppuDataFill
|
||||||
|
to:main::@5
|
||||||
|
main::@5: scope:[main] from main::@4
|
||||||
|
[40] phi()
|
||||||
|
[41] call clrscr
|
||||||
|
to:main::@6
|
||||||
|
main::@6: scope:[main] from main::@5
|
||||||
|
[42] phi()
|
||||||
|
[43] call cputs
|
||||||
|
to:main::@7
|
||||||
|
main::@7: scope:[main] from main::@6
|
||||||
|
[44] (volatile byte) x_scroll ← (byte) 0
|
||||||
|
[45] (volatile byte) y_scroll ← (byte) -8
|
||||||
|
to:main::enableVideoOutput1
|
||||||
|
main::enableVideoOutput1: scope:[main] from main::@7
|
||||||
|
[46] *((byte*)(const struct RICOH_2C02*) PPU) ← (byte) $80
|
||||||
|
[47] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUMASK) ← (byte) $1e
|
||||||
|
to:main::@1
|
||||||
|
main::@1: scope:[main] from main::@1 main::enableVideoOutput1
|
||||||
|
[48] phi()
|
||||||
|
to:main::@1
|
||||||
|
|
||||||
|
(void()) cputs((to_nomodify byte*) cputs::s)
|
||||||
|
cputs: scope:[cputs] from main::@6
|
||||||
|
[49] phi()
|
||||||
|
to:cputs::@1
|
||||||
|
cputs::@1: scope:[cputs] from cputs cputs::@2
|
||||||
|
[50] (to_nomodify byte*) cputs::s#2 ← phi( cputs/(const byte*) main::s cputs::@2/(to_nomodify byte*) cputs::s#0 )
|
||||||
|
[51] (byte) cputs::c#1 ← *((to_nomodify byte*) cputs::s#2)
|
||||||
|
[52] (to_nomodify byte*) cputs::s#0 ← ++ (to_nomodify byte*) cputs::s#2
|
||||||
|
[53] if((byte) 0!=(byte) cputs::c#1) goto cputs::@2
|
||||||
|
to:cputs::@return
|
||||||
|
cputs::@return: scope:[cputs] from cputs::@1
|
||||||
|
[54] return
|
||||||
|
to:@return
|
||||||
|
cputs::@2: scope:[cputs] from cputs::@1
|
||||||
|
[55] (byte) cputc::c#0 ← (byte) cputs::c#1
|
||||||
|
[56] call cputc
|
||||||
|
to:cputs::@1
|
||||||
|
|
||||||
|
(void()) cputc((byte) cputc::c)
|
||||||
|
cputc: scope:[cputc] from cputs::@2
|
||||||
|
[57] if((byte) cputc::c#0==(byte) '
|
||||||
|
') goto cputc::@1
|
||||||
|
to:cputc::@2
|
||||||
|
cputc::@2: scope:[cputc] from cputc
|
||||||
|
[58] (nomodify byte*) ppuDataSet::ppuData#0 ← (byte*) conio_line_text + (byte) conio_cursor_x
|
||||||
|
[59] (byte) ppuDataSet::val#0 ← (byte) cputc::c#0
|
||||||
|
[60] (nomodify void*) ppuDataSet::ppuDataPrepare1_ppuData#2 ← (void*)(nomodify byte*) ppuDataSet::ppuData#0
|
||||||
|
[61] call ppuDataSet
|
||||||
|
to:cputc::@4
|
||||||
|
cputc::@4: scope:[cputc] from cputc::@2
|
||||||
|
[62] (byte) conio_cursor_x ← ++ (byte) conio_cursor_x
|
||||||
|
[63] if((byte) conio_cursor_x!=(byte) $20) goto cputc::@return
|
||||||
|
to:cputc::@3
|
||||||
|
cputc::@3: scope:[cputc] from cputc::@4
|
||||||
|
[64] phi()
|
||||||
|
[65] call cputln
|
||||||
|
to:cputc::@return
|
||||||
|
cputc::@return: scope:[cputc] from cputc::@1 cputc::@3 cputc::@4
|
||||||
|
[66] return
|
||||||
|
to:@return
|
||||||
|
cputc::@1: scope:[cputc] from cputc
|
||||||
|
[67] phi()
|
||||||
|
[68] call cputln
|
||||||
|
to:cputc::@return
|
||||||
|
|
||||||
|
(void()) cputln()
|
||||||
|
cputln: scope:[cputln] from cputc::@1 cputc::@3
|
||||||
|
[69] (byte*) conio_line_text ← (byte*) conio_line_text + (byte) $20
|
||||||
|
[70] (byte) conio_cursor_x ← (byte) 0
|
||||||
|
[71] (byte) conio_cursor_y ← ++ (byte) conio_cursor_y
|
||||||
|
[72] call cscroll
|
||||||
|
to:cputln::@return
|
||||||
|
cputln::@return: scope:[cputln] from cputln
|
||||||
|
[73] return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
(void()) cscroll()
|
||||||
|
cscroll: scope:[cscroll] from cputln
|
||||||
|
[74] if((byte) conio_cursor_y!=(byte) $1e) goto cscroll::@return
|
||||||
|
to:cscroll::@1
|
||||||
|
cscroll::@1: scope:[cscroll] from cscroll cscroll::@5
|
||||||
|
[75] (byte*) cscroll::line1#6 ← phi( cscroll/(const nomodify byte*) PPU_NAME_TABLE_0 cscroll::@5/(byte*) cscroll::line1#2 )
|
||||||
|
[75] (byte*) cscroll::line2#6 ← phi( cscroll/(const nomodify byte*) PPU_NAME_TABLE_0+(byte) $20 cscroll::@5/(byte*) cscroll::line2#2 )
|
||||||
|
[75] (byte) cscroll::y#2 ← phi( cscroll/(byte) 0 cscroll::@5/(byte) cscroll::y#1 )
|
||||||
|
[76] if((byte) cscroll::y#2<(byte)(number) $1e-(number) 1) goto cscroll::@3
|
||||||
|
to:cscroll::@2
|
||||||
|
cscroll::@2: scope:[cscroll] from cscroll::@1
|
||||||
|
[77] phi()
|
||||||
|
[78] call ppuDataFill
|
||||||
|
to:cscroll::@6
|
||||||
|
cscroll::@6: scope:[cscroll] from cscroll::@2
|
||||||
|
[79] (byte*) conio_line_text ← (byte*) conio_line_text - (byte) $20
|
||||||
|
[80] (byte) conio_cursor_y ← -- (byte) conio_cursor_y
|
||||||
|
to:cscroll::@return
|
||||||
|
cscroll::@return: scope:[cscroll] from cscroll cscroll::@6
|
||||||
|
[81] return
|
||||||
|
to:@return
|
||||||
|
cscroll::@3: scope:[cscroll] from cscroll::@1 cscroll::@8
|
||||||
|
[82] (byte*) cscroll::line1#2 ← phi( cscroll::@8/(byte*) cscroll::line1#1 cscroll::@1/(byte*) cscroll::line1#6 )
|
||||||
|
[82] (byte*) cscroll::line2#2 ← phi( cscroll::@8/(byte*) cscroll::line2#1 cscroll::@1/(byte*) cscroll::line2#6 )
|
||||||
|
[82] (byte) cscroll::x#2 ← phi( cscroll::@8/(byte) cscroll::x#1 cscroll::@1/(byte) 0 )
|
||||||
|
[83] if((byte) cscroll::x#2<(byte) $20) goto cscroll::@4
|
||||||
|
to:cscroll::@5
|
||||||
|
cscroll::@5: scope:[cscroll] from cscroll::@3
|
||||||
|
[84] (byte) cscroll::y#1 ← ++ (byte) cscroll::y#2
|
||||||
|
to:cscroll::@1
|
||||||
|
cscroll::@4: scope:[cscroll] from cscroll::@3
|
||||||
|
[85] (nomodify void*) ppuDataGet::ppuData#0 ← (void*)(byte*) cscroll::line2#2
|
||||||
|
[86] call ppuDataGet
|
||||||
|
[87] (byte) ppuDataGet::return#2 ← (byte) ppuDataGet::ppuDataRead1_return#0
|
||||||
|
to:cscroll::@7
|
||||||
|
cscroll::@7: scope:[cscroll] from cscroll::@4
|
||||||
|
[88] (byte) cscroll::ch#0 ← (byte) ppuDataGet::return#2
|
||||||
|
[89] (byte*) cscroll::line2#1 ← ++ (byte*) cscroll::line2#2
|
||||||
|
[90] (nomodify void*) ppuDataSet::ppuData#1 ← (void*)(byte*) cscroll::line1#2
|
||||||
|
[91] (byte) ppuDataSet::val#1 ← (byte) cscroll::ch#0
|
||||||
|
[92] call ppuDataSet
|
||||||
|
to:cscroll::@8
|
||||||
|
cscroll::@8: scope:[cscroll] from cscroll::@7
|
||||||
|
[93] (byte*) cscroll::line1#1 ← ++ (byte*) cscroll::line1#2
|
||||||
|
[94] (byte) cscroll::x#1 ← ++ (byte) cscroll::x#2
|
||||||
|
to:cscroll::@3
|
||||||
|
|
||||||
|
(void()) ppuDataSet((nomodify void*) ppuDataSet::ppuData , (byte) ppuDataSet::val)
|
||||||
|
ppuDataSet: scope:[ppuDataSet] from cputc::@2 cscroll::@7
|
||||||
|
[95] (byte) ppuDataSet::val#2 ← phi( cputc::@2/(byte) ppuDataSet::val#0 cscroll::@7/(byte) ppuDataSet::val#1 )
|
||||||
|
[95] (nomodify void*) ppuDataSet::ppuDataPrepare1_ppuData#0 ← phi( cputc::@2/(nomodify void*) ppuDataSet::ppuDataPrepare1_ppuData#2 cscroll::@7/(nomodify void*) ppuDataSet::ppuData#1 )
|
||||||
|
to:ppuDataSet::ppuDataPrepare1
|
||||||
|
ppuDataSet::ppuDataPrepare1: scope:[ppuDataSet] from ppuDataSet
|
||||||
|
[96] (byte~) ppuDataSet::ppuDataPrepare1_$0 ← > (nomodify void*) ppuDataSet::ppuDataPrepare1_ppuData#0
|
||||||
|
[97] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← (byte~) ppuDataSet::ppuDataPrepare1_$0
|
||||||
|
[98] (byte~) ppuDataSet::ppuDataPrepare1_$1 ← < (nomodify void*) ppuDataSet::ppuDataPrepare1_ppuData#0
|
||||||
|
[99] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← (byte~) ppuDataSet::ppuDataPrepare1_$1
|
||||||
|
to:ppuDataSet::ppuDataPut1
|
||||||
|
ppuDataSet::ppuDataPut1: scope:[ppuDataSet] from ppuDataSet::ppuDataPrepare1
|
||||||
|
[100] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUDATA) ← (byte) ppuDataSet::val#2
|
||||||
|
to:ppuDataSet::@return
|
||||||
|
ppuDataSet::@return: scope:[ppuDataSet] from ppuDataSet::ppuDataPut1
|
||||||
|
[101] return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
(byte()) ppuDataGet((nomodify void*) ppuDataGet::ppuData)
|
||||||
|
ppuDataGet: scope:[ppuDataGet] from cscroll::@4
|
||||||
|
[102] phi()
|
||||||
|
to:ppuDataGet::ppuDataPrepare1
|
||||||
|
ppuDataGet::ppuDataPrepare1: scope:[ppuDataGet] from ppuDataGet
|
||||||
|
[103] (byte~) ppuDataGet::ppuDataPrepare1_$0 ← > (nomodify void*) ppuDataGet::ppuData#0
|
||||||
|
[104] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← (byte~) ppuDataGet::ppuDataPrepare1_$0
|
||||||
|
[105] (byte~) ppuDataGet::ppuDataPrepare1_$1 ← < (nomodify void*) ppuDataGet::ppuData#0
|
||||||
|
[106] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← (byte~) ppuDataGet::ppuDataPrepare1_$1
|
||||||
|
to:ppuDataGet::ppuDataRead1
|
||||||
|
ppuDataGet::ppuDataRead1: scope:[ppuDataGet] from ppuDataGet::ppuDataPrepare1
|
||||||
|
[107] (byte) ppuDataGet::ppuDataRead1_return#0 ← *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUDATA)
|
||||||
|
to:ppuDataGet::@return
|
||||||
|
ppuDataGet::@return: scope:[ppuDataGet] from ppuDataGet::ppuDataRead1
|
||||||
|
[108] return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
(void()) ppuDataFill((nomodify void*) ppuDataFill::ppuData , (byte) ppuDataFill::val , (word) ppuDataFill::size)
|
||||||
|
ppuDataFill: scope:[ppuDataFill] from clrscr cscroll::@2 main::@3 main::@4
|
||||||
|
[109] (byte) ppuDataFill::val#10 ← phi( clrscr/(byte) ' ' cscroll::@2/(byte) ' ' main::@3/(byte) 0 main::@4/(byte) 0 )
|
||||||
|
[109] (word) ppuDataFill::size#5 ← phi( clrscr/(word) $3c0 cscroll::@2/(byte) $20 main::@3/(byte) $40 main::@4/(byte) $40 )
|
||||||
|
[109] (nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0 ← phi( clrscr/(void*)(const nomodify byte*) PPU_NAME_TABLE_0 cscroll::@2/(void*)(const nomodify byte*) PPU_NAME_TABLE_0+(word)(number) $1e*(number) $20-(byte) $20 main::@3/(void*)(const nomodify byte*) PPU_ATTRIBUTE_TABLE_0 main::@4/(void*)(const nomodify byte*) PPU_ATTRIBUTE_TABLE_1 )
|
||||||
|
to:ppuDataFill::ppuDataPrepare1
|
||||||
|
ppuDataFill::ppuDataPrepare1: scope:[ppuDataFill] from ppuDataFill
|
||||||
|
[110] (byte~) ppuDataFill::ppuDataPrepare1_$0 ← > (nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0
|
||||||
|
[111] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← (byte~) ppuDataFill::ppuDataPrepare1_$0
|
||||||
|
[112] (byte~) ppuDataFill::ppuDataPrepare1_$1 ← < (nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0
|
||||||
|
[113] *((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
|
||||||
|
[114] (word) ppuDataFill::i#2 ← phi( ppuDataFill::ppuDataPrepare1/(word) 0 ppuDataFill::@2/(word) ppuDataFill::i#1 )
|
||||||
|
[115] if((word) ppuDataFill::i#2<(word) ppuDataFill::size#5) goto ppuDataFill::ppuDataPut1
|
||||||
|
to:ppuDataFill::@return
|
||||||
|
ppuDataFill::@return: scope:[ppuDataFill] from ppuDataFill::@1
|
||||||
|
[116] return
|
||||||
|
to:@return
|
||||||
|
ppuDataFill::ppuDataPut1: scope:[ppuDataFill] from ppuDataFill::@1
|
||||||
|
[117] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUDATA) ← (byte) ppuDataFill::val#10
|
||||||
|
to:ppuDataFill::@2
|
||||||
|
ppuDataFill::@2: scope:[ppuDataFill] from ppuDataFill::ppuDataPut1
|
||||||
|
[118] (word) ppuDataFill::i#1 ← ++ (word) ppuDataFill::i#2
|
||||||
|
to:ppuDataFill::@1
|
||||||
|
|
||||||
|
(void()) clrscr()
|
||||||
|
clrscr: scope:[clrscr] from main::@5
|
||||||
|
[119] phi()
|
||||||
|
[120] call ppuDataFill
|
||||||
|
to:clrscr::@1
|
||||||
|
clrscr::@1: scope:[clrscr] from clrscr
|
||||||
|
[121] (byte) conio_cursor_x ← (byte) 0
|
||||||
|
[122] (byte) conio_cursor_y ← (byte) 0
|
||||||
|
[123] (byte*) conio_line_text ← (const nomodify byte*) PPU_NAME_TABLE_0
|
||||||
|
to:clrscr::@return
|
||||||
|
clrscr::@return: scope:[clrscr] from clrscr::@1
|
||||||
|
[124] return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
(void()) ppuDataTransfer((nomodify void*) ppuDataTransfer::ppuData , (nomodify void*) ppuDataTransfer::cpuData , (word) ppuDataTransfer::size)
|
||||||
|
ppuDataTransfer: scope:[ppuDataTransfer] from main::@2
|
||||||
|
[125] phi()
|
||||||
|
to:ppuDataTransfer::ppuDataPrepare1
|
||||||
|
ppuDataTransfer::ppuDataPrepare1: scope:[ppuDataTransfer] from ppuDataTransfer
|
||||||
|
[126] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUADDR) ← >(const nomodify void*) ppuDataTransfer::ppuData#0
|
||||||
|
[127] *((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
|
||||||
|
[128] (byte*) ppuDataTransfer::cpuSrc#2 ← phi( ppuDataTransfer::ppuDataPrepare1/(byte*)(const nomodify void*) ppuDataTransfer::cpuData#0 ppuDataTransfer::@3/(byte*) ppuDataTransfer::cpuSrc#1 )
|
||||||
|
[128] (word) ppuDataTransfer::i#2 ← phi( ppuDataTransfer::ppuDataPrepare1/(word) 0 ppuDataTransfer::@3/(word) ppuDataTransfer::i#1 )
|
||||||
|
[129] if((word) ppuDataTransfer::i#2<(const word) ppuDataTransfer::size#0) goto ppuDataTransfer::@2
|
||||||
|
to:ppuDataTransfer::@return
|
||||||
|
ppuDataTransfer::@return: scope:[ppuDataTransfer] from ppuDataTransfer::@1
|
||||||
|
[130] return
|
||||||
|
to:@return
|
||||||
|
ppuDataTransfer::@2: scope:[ppuDataTransfer] from ppuDataTransfer::@1
|
||||||
|
[131] (byte) ppuDataTransfer::ppuDataPut1_val#0 ← *((byte*) ppuDataTransfer::cpuSrc#2)
|
||||||
|
to:ppuDataTransfer::ppuDataPut1
|
||||||
|
ppuDataTransfer::ppuDataPut1: scope:[ppuDataTransfer] from ppuDataTransfer::@2
|
||||||
|
[132] *((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
|
||||||
|
[133] (byte*) ppuDataTransfer::cpuSrc#1 ← ++ (byte*) ppuDataTransfer::cpuSrc#2
|
||||||
|
[134] (word) ppuDataTransfer::i#1 ← ++ (word) ppuDataTransfer::i#2
|
||||||
|
to:ppuDataTransfer::@1
|
||||||
|
|
||||||
|
interrupt(HARDWARE_STACK)(void()) vblank()
|
||||||
|
vblank: scope:[vblank] from
|
||||||
|
[135] phi()
|
||||||
|
[136] call readJoy1
|
||||||
|
[137] (byte) readJoy1::return#2 ← (byte) readJoy1::joy#2
|
||||||
|
to:vblank::@11
|
||||||
|
vblank::@11: scope:[vblank] from vblank
|
||||||
|
[138] (byte) vblank::joy#0 ← (byte) readJoy1::return#2
|
||||||
|
[139] (byte~) vblank::$1 ← (byte) vblank::joy#0 & (const nomodify byte) JOY_DOWN
|
||||||
|
[140] if((byte) 0==(byte~) vblank::$1) goto vblank::@1
|
||||||
|
to:vblank::@5
|
||||||
|
vblank::@5: scope:[vblank] from vblank::@11
|
||||||
|
[141] (volatile byte) y_scroll ← ++ (volatile byte) y_scroll
|
||||||
|
[142] if((volatile byte) y_scroll!=(byte) $f0) goto vblank::@1
|
||||||
|
to:vblank::@6
|
||||||
|
vblank::@6: scope:[vblank] from vblank::@5
|
||||||
|
[143] (volatile byte) y_scroll ← (byte) 0
|
||||||
|
to:vblank::@1
|
||||||
|
vblank::@1: scope:[vblank] from vblank::@11 vblank::@5 vblank::@6
|
||||||
|
[144] (byte~) vblank::$3 ← (byte) vblank::joy#0 & (const nomodify byte) JOY_UP
|
||||||
|
[145] if((byte) 0==(byte~) vblank::$3) goto vblank::@2
|
||||||
|
to:vblank::@7
|
||||||
|
vblank::@7: scope:[vblank] from vblank::@1
|
||||||
|
[146] (volatile byte) y_scroll ← -- (volatile byte) y_scroll
|
||||||
|
[147] if((volatile byte) y_scroll!=(byte) $ff) goto vblank::@2
|
||||||
|
to:vblank::@8
|
||||||
|
vblank::@8: scope:[vblank] from vblank::@7
|
||||||
|
[148] (volatile byte) y_scroll ← (byte) $ef
|
||||||
|
to:vblank::@2
|
||||||
|
vblank::@2: scope:[vblank] from vblank::@1 vblank::@7 vblank::@8
|
||||||
|
[149] (byte~) vblank::$5 ← (byte) vblank::joy#0 & (const nomodify byte) JOY_LEFT
|
||||||
|
[150] if((byte) 0==(byte~) vblank::$5) goto vblank::@3
|
||||||
|
to:vblank::@9
|
||||||
|
vblank::@9: scope:[vblank] from vblank::@2
|
||||||
|
[151] (volatile byte) x_scroll ← ++ (volatile byte) x_scroll
|
||||||
|
to:vblank::@3
|
||||||
|
vblank::@3: scope:[vblank] from vblank::@2 vblank::@9
|
||||||
|
[152] (byte~) vblank::$7 ← (byte) vblank::joy#0 & (const nomodify byte) JOY_RIGHT
|
||||||
|
[153] if((byte) 0==(byte~) vblank::$7) goto vblank::@4
|
||||||
|
to:vblank::@10
|
||||||
|
vblank::@10: scope:[vblank] from vblank::@3
|
||||||
|
[154] (volatile byte) x_scroll ← -- (volatile byte) x_scroll
|
||||||
|
to:vblank::@4
|
||||||
|
vblank::@4: scope:[vblank] from vblank::@10 vblank::@3
|
||||||
|
[155] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSCROLL) ← (volatile byte) x_scroll
|
||||||
|
[156] *((byte*)(const struct RICOH_2C02*) PPU+(const byte) OFFSET_STRUCT_RICOH_2C02_PPUSCROLL) ← (volatile byte) y_scroll
|
||||||
|
to:vblank::@return
|
||||||
|
vblank::@return: scope:[vblank] from vblank::@4
|
||||||
|
[157] return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
(byte()) readJoy1()
|
||||||
|
readJoy1: scope:[readJoy1] from vblank
|
||||||
|
[158] *((byte*)(const struct RICOH_2A03*) APU+(const byte) OFFSET_STRUCT_RICOH_2A03_JOY1) ← (byte) 1
|
||||||
|
[159] *((byte*)(const struct RICOH_2A03*) APU+(const byte) OFFSET_STRUCT_RICOH_2A03_JOY1) ← (byte) 0
|
||||||
|
to:readJoy1::@1
|
||||||
|
readJoy1::@1: scope:[readJoy1] from readJoy1 readJoy1::@2
|
||||||
|
[160] (byte) readJoy1::joy#2 ← phi( readJoy1/(byte) 0 readJoy1::@2/(byte) readJoy1::joy#1 )
|
||||||
|
[160] (byte) readJoy1::i#2 ← phi( readJoy1/(byte) 0 readJoy1::@2/(byte) readJoy1::i#1 )
|
||||||
|
[161] if((byte) readJoy1::i#2<(byte) 8) goto readJoy1::@2
|
||||||
|
to:readJoy1::@return
|
||||||
|
readJoy1::@return: scope:[readJoy1] from readJoy1::@1
|
||||||
|
[162] return
|
||||||
|
to:@return
|
||||||
|
readJoy1::@2: scope:[readJoy1] from readJoy1::@1
|
||||||
|
[163] (byte~) readJoy1::$1 ← (byte) readJoy1::joy#2 << (byte) 1
|
||||||
|
[164] (byte~) readJoy1::$2 ← *((byte*)(const struct RICOH_2A03*) APU+(const byte) OFFSET_STRUCT_RICOH_2A03_JOY1) & (byte) 1
|
||||||
|
[165] (byte) readJoy1::joy#1 ← (byte~) readJoy1::$1 | (byte~) readJoy1::$2
|
||||||
|
[166] (byte) readJoy1::i#1 ← ++ (byte) readJoy1::i#2
|
||||||
|
to:readJoy1::@1
|
6505
src/test/ref/examples/nes-conio/nes-conio.log
Normal file
6505
src/test/ref/examples/nes-conio/nes-conio.log
Normal file
File diff suppressed because it is too large
Load Diff
298
src/test/ref/examples/nes-conio/nes-conio.sym
Normal file
298
src/test/ref/examples/nes-conio/nes-conio.sym
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
(label) @1
|
||||||
|
(label) @2
|
||||||
|
(label) @3
|
||||||
|
(label) @begin
|
||||||
|
(label) @end
|
||||||
|
(const struct RICOH_2A03*) APU = (struct RICOH_2A03*) 16384
|
||||||
|
(const nomodify byte*) FR_COUNTER = (byte*) 16407
|
||||||
|
(const nomodify byte) JOY_DOWN = (byte) 4
|
||||||
|
(const nomodify byte) JOY_LEFT = (byte) 2
|
||||||
|
(const nomodify byte) JOY_RIGHT = (byte) 1
|
||||||
|
(const nomodify byte) JOY_UP = (byte) 8
|
||||||
|
(const nomodify byte*) MEMORY = (byte*) 0
|
||||||
|
(const byte) OFFSET_STRUCT_RICOH_2A03_DMC_FREQ = (byte) $10
|
||||||
|
(const byte) OFFSET_STRUCT_RICOH_2A03_JOY1 = (byte) $16
|
||||||
|
(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*) 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_ATTRIBUTE_TABLE_1 = (byte*) 10176
|
||||||
|
(const nomodify byte*) PPU_NAME_TABLE_0 = (byte*) 8192
|
||||||
|
(const nomodify byte*) PPU_PALETTE = (byte*) 16128
|
||||||
|
(const 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 byte) SIZEOF_BYTE = (byte) 1
|
||||||
|
(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()) clrscr()
|
||||||
|
(label) clrscr::@1
|
||||||
|
(label) clrscr::@return
|
||||||
|
(byte) conio_cursor_x loadstore zp[1]:11 5189.185185185185
|
||||||
|
(byte) conio_cursor_y loadstore zp[1]:12 64002.159999999996
|
||||||
|
(byte*) conio_line_text loadstore zp[2]:13 45104.24489795918
|
||||||
|
(void()) cputc((byte) cputc::c)
|
||||||
|
(label) cputc::@1
|
||||||
|
(label) cputc::@2
|
||||||
|
(label) cputc::@3
|
||||||
|
(label) cputc::@4
|
||||||
|
(label) cputc::@return
|
||||||
|
(byte) cputc::c
|
||||||
|
(byte) cputc::c#0 reg byte x 7001.0
|
||||||
|
(void()) cputln()
|
||||||
|
(label) cputln::@return
|
||||||
|
(void()) cputs((to_nomodify byte*) cputs::s)
|
||||||
|
(label) cputs::@1
|
||||||
|
(label) cputs::@2
|
||||||
|
(label) cputs::@return
|
||||||
|
(byte) cputs::c
|
||||||
|
(byte) cputs::c#1 reg byte a 1001.0
|
||||||
|
(to_nomodify byte*) cputs::s
|
||||||
|
(to_nomodify byte*) cputs::s#0 s zp[2]:7 500.5
|
||||||
|
(to_nomodify byte*) cputs::s#2 s zp[2]:7 1501.5
|
||||||
|
(void()) cscroll()
|
||||||
|
(label) cscroll::@1
|
||||||
|
(label) cscroll::@2
|
||||||
|
(label) cscroll::@3
|
||||||
|
(label) cscroll::@4
|
||||||
|
(label) cscroll::@5
|
||||||
|
(label) cscroll::@6
|
||||||
|
(label) cscroll::@7
|
||||||
|
(label) cscroll::@8
|
||||||
|
(label) cscroll::@return
|
||||||
|
(byte) cscroll::ch
|
||||||
|
(byte) cscroll::ch#0 reg byte x 6.666666673333334E8
|
||||||
|
(byte*) cscroll::line1
|
||||||
|
(byte*) cscroll::line1#1 line1 zp[2]:3 1.000000001E9
|
||||||
|
(byte*) cscroll::line1#2 line1 zp[2]:3 2.0000000036363637E8
|
||||||
|
(byte*) cscroll::line1#6 line1 zp[2]:3 1.00000001E8
|
||||||
|
(byte*) cscroll::line2
|
||||||
|
(byte*) cscroll::line2#1 line2 zp[2]:9 3.333333336666667E8
|
||||||
|
(byte*) cscroll::line2#2 line2 zp[2]:9 3.1428571485714287E8
|
||||||
|
(byte*) cscroll::line2#6 line2 zp[2]:9 1.00000001E8
|
||||||
|
(byte) cscroll::x
|
||||||
|
(byte) cscroll::x#1 reg byte y 2.000000002E9
|
||||||
|
(byte) cscroll::x#2 reg byte y 2.72727273E8
|
||||||
|
(byte) cscroll::y
|
||||||
|
(byte) cscroll::y#1 y zp[1]:2 2.00000002E8
|
||||||
|
(byte) cscroll::y#2 y zp[1]:2 2.142857164285714E7
|
||||||
|
(void()) main()
|
||||||
|
(label) main::@1
|
||||||
|
(label) main::@2
|
||||||
|
(label) main::@3
|
||||||
|
(label) main::@4
|
||||||
|
(label) main::@5
|
||||||
|
(label) main::@6
|
||||||
|
(label) main::@7
|
||||||
|
(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
|
||||||
|
(const byte*) main::s[(byte) $25] = (byte*) "hello world!
|
||||||
|
i am nes
|
||||||
|
look at me
|
||||||
|
|
||||||
|
"
|
||||||
|
(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]:9 2.00000002E8
|
||||||
|
(word) ppuDataFill::i#2 i zp[2]:9 1.00000001E8
|
||||||
|
(nomodify void*) ppuDataFill::ppuData
|
||||||
|
(label) ppuDataFill::ppuDataPrepare1
|
||||||
|
(byte~) ppuDataFill::ppuDataPrepare1_$0 reg byte a 2.0000002E7
|
||||||
|
(byte~) ppuDataFill::ppuDataPrepare1_$1 reg byte a 2.0000002E7
|
||||||
|
(nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData
|
||||||
|
(nomodify void*) ppuDataFill::ppuDataPrepare1_ppuData#0 ppuDataPrepare1_ppuData zp[2]:5 6666667.333333333
|
||||||
|
(label) ppuDataFill::ppuDataPut1
|
||||||
|
(byte) ppuDataFill::ppuDataPut1_val
|
||||||
|
(word) ppuDataFill::size
|
||||||
|
(word) ppuDataFill::size#5 size zp[2]:17 1.1111111222222222E7
|
||||||
|
(byte) ppuDataFill::val
|
||||||
|
(byte) ppuDataFill::val#10 reg byte x 1.1111111222222222E7
|
||||||
|
(byte()) ppuDataGet((nomodify void*) ppuDataGet::ppuData)
|
||||||
|
(label) ppuDataGet::@return
|
||||||
|
(nomodify void*) ppuDataGet::ppuData
|
||||||
|
(nomodify void*) ppuDataGet::ppuData#0 ppuData zp[2]:17 5.25000000075E9
|
||||||
|
(label) ppuDataGet::ppuDataPrepare1
|
||||||
|
(byte~) ppuDataGet::ppuDataPrepare1_$0 reg byte a 2.0000000002E10
|
||||||
|
(byte~) ppuDataGet::ppuDataPrepare1_$1 reg byte a 2.0000000002E10
|
||||||
|
(nomodify void*) ppuDataGet::ppuDataPrepare1_ppuData
|
||||||
|
(label) ppuDataGet::ppuDataRead1
|
||||||
|
(byte) ppuDataGet::ppuDataRead1_return
|
||||||
|
(byte) ppuDataGet::ppuDataRead1_return#0 reg byte a 3.666666667333333E9
|
||||||
|
(byte) ppuDataGet::return
|
||||||
|
(byte) ppuDataGet::return#2 reg byte a 2.000000002E9
|
||||||
|
(void()) ppuDataSet((nomodify void*) ppuDataSet::ppuData , (byte) ppuDataSet::val)
|
||||||
|
(label) ppuDataSet::@return
|
||||||
|
(nomodify void*) ppuDataSet::ppuData
|
||||||
|
(nomodify byte*) ppuDataSet::ppuData#0 ppuData zp[2]:5 5000.5
|
||||||
|
(nomodify void*) ppuDataSet::ppuData#1 ppuData zp[2]:5 1.000000001E9
|
||||||
|
(label) ppuDataSet::ppuDataPrepare1
|
||||||
|
(byte~) ppuDataSet::ppuDataPrepare1_$0 reg byte a 2.0000000002E10
|
||||||
|
(byte~) ppuDataSet::ppuDataPrepare1_$1 reg byte a 2.0000000002E10
|
||||||
|
(nomodify void*) ppuDataSet::ppuDataPrepare1_ppuData
|
||||||
|
(nomodify void*) ppuDataSet::ppuDataPrepare1_ppuData#0 ppuDataPrepare1_ppuData zp[2]:5 7.000003334666666E9
|
||||||
|
(nomodify void*) ppuDataSet::ppuDataPrepare1_ppuData#2 ppuDataPrepare1_ppuData zp[2]:5 20002.0
|
||||||
|
(label) ppuDataSet::ppuDataPut1
|
||||||
|
(byte) ppuDataSet::ppuDataPut1_val
|
||||||
|
(byte) ppuDataSet::val
|
||||||
|
(byte) ppuDataSet::val#0 reg byte x 10001.0
|
||||||
|
(byte) ppuDataSet::val#1 reg byte x 2.000000002E9
|
||||||
|
(byte) ppuDataSet::val#2 reg byte x 2.2000020006E9
|
||||||
|
(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]:9 1001.0
|
||||||
|
(byte*) ppuDataTransfer::cpuSrc#2 cpuSrc zp[2]:9 750.75
|
||||||
|
(word) ppuDataTransfer::i
|
||||||
|
(word) ppuDataTransfer::i#1 i zp[2]:7 2002.0
|
||||||
|
(word) ppuDataTransfer::i#2 i zp[2]:7 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
|
||||||
|
(byte()) readJoy1()
|
||||||
|
(byte~) readJoy1::$1 zp[1]:19 101.0
|
||||||
|
(byte~) readJoy1::$2 reg byte a 202.0
|
||||||
|
(label) readJoy1::@1
|
||||||
|
(label) readJoy1::@2
|
||||||
|
(label) readJoy1::@return
|
||||||
|
(byte) readJoy1::i
|
||||||
|
(byte) readJoy1::i#1 reg byte x 202.0
|
||||||
|
(byte) readJoy1::i#2 reg byte x 60.599999999999994
|
||||||
|
(byte) readJoy1::joy
|
||||||
|
(byte) readJoy1::joy#1 reg byte a 101.0
|
||||||
|
(byte) readJoy1::joy#2 reg byte a 51.0
|
||||||
|
(byte) readJoy1::return
|
||||||
|
(byte) readJoy1::return#2 reg byte a 4.0
|
||||||
|
interrupt(HARDWARE_STACK)(void()) vblank()
|
||||||
|
(byte~) vblank::$1 reg byte a 4.0
|
||||||
|
(byte~) vblank::$3 reg byte a 4.0
|
||||||
|
(byte~) vblank::$5 reg byte a 4.0
|
||||||
|
(byte~) vblank::$7 reg byte a 4.0
|
||||||
|
(label) vblank::@1
|
||||||
|
(label) vblank::@10
|
||||||
|
(label) vblank::@11
|
||||||
|
(label) vblank::@2
|
||||||
|
(label) vblank::@3
|
||||||
|
(label) vblank::@4
|
||||||
|
(label) vblank::@5
|
||||||
|
(label) vblank::@6
|
||||||
|
(label) vblank::@7
|
||||||
|
(label) vblank::@8
|
||||||
|
(label) vblank::@9
|
||||||
|
(label) vblank::@return
|
||||||
|
(byte) vblank::joy
|
||||||
|
(byte) vblank::joy#0 reg byte x 0.7142857142857142
|
||||||
|
(volatile byte) x_scroll loadstore zp[1]:15 1.1500000000000001
|
||||||
|
(volatile byte) y_scroll loadstore zp[1]:16 1.4761904761904767
|
||||||
|
|
||||||
|
reg byte x [ main::initNES1_i#2 main::initNES1_i#1 ]
|
||||||
|
zp[1]:2 [ cscroll::y#2 cscroll::y#1 ]
|
||||||
|
zp[2]:3 [ cscroll::line1#6 cscroll::line1#2 cscroll::line1#1 ]
|
||||||
|
reg byte y [ cscroll::x#2 cscroll::x#1 ]
|
||||||
|
reg byte x [ ppuDataSet::val#2 ppuDataSet::val#0 ppuDataSet::val#1 ]
|
||||||
|
zp[2]:5 [ ppuDataFill::ppuDataPrepare1_ppuData#0 ppuDataSet::ppuDataPrepare1_ppuData#0 ppuDataSet::ppuDataPrepare1_ppuData#2 ppuDataSet::ppuData#1 ppuDataSet::ppuData#0 ]
|
||||||
|
reg byte x [ ppuDataFill::val#10 ]
|
||||||
|
zp[2]:7 [ ppuDataTransfer::i#2 ppuDataTransfer::i#1 cputs::s#2 cputs::s#0 ]
|
||||||
|
zp[2]:9 [ ppuDataTransfer::cpuSrc#2 ppuDataTransfer::cpuSrc#1 cscroll::line2#6 cscroll::line2#2 cscroll::line2#1 ppuDataFill::i#2 ppuDataFill::i#1 ]
|
||||||
|
reg byte x [ readJoy1::i#2 readJoy1::i#1 ]
|
||||||
|
reg byte a [ readJoy1::joy#2 readJoy1::joy#1 ]
|
||||||
|
zp[1]:11 [ conio_cursor_x ]
|
||||||
|
zp[1]:12 [ conio_cursor_y ]
|
||||||
|
zp[2]:13 [ conio_line_text ]
|
||||||
|
zp[1]:15 [ x_scroll ]
|
||||||
|
zp[1]:16 [ y_scroll ]
|
||||||
|
reg byte a [ main::initNES1_waitForVBlank1_$0 ]
|
||||||
|
reg byte a [ main::initNES1_waitForVBlank2_$0 ]
|
||||||
|
reg byte a [ cputs::c#1 ]
|
||||||
|
reg byte x [ cputc::c#0 ]
|
||||||
|
zp[2]:17 [ ppuDataGet::ppuData#0 ppuDataFill::size#5 ]
|
||||||
|
reg byte a [ ppuDataGet::return#2 ]
|
||||||
|
reg byte x [ cscroll::ch#0 ]
|
||||||
|
reg byte a [ ppuDataSet::ppuDataPrepare1_$0 ]
|
||||||
|
reg byte a [ ppuDataSet::ppuDataPrepare1_$1 ]
|
||||||
|
reg byte a [ ppuDataGet::ppuDataPrepare1_$0 ]
|
||||||
|
reg byte a [ ppuDataGet::ppuDataPrepare1_$1 ]
|
||||||
|
reg byte a [ ppuDataGet::ppuDataRead1_return#0 ]
|
||||||
|
reg byte a [ ppuDataFill::ppuDataPrepare1_$0 ]
|
||||||
|
reg byte a [ ppuDataFill::ppuDataPrepare1_$1 ]
|
||||||
|
reg byte a [ ppuDataTransfer::ppuDataPut1_val#0 ]
|
||||||
|
reg byte a [ readJoy1::return#2 ]
|
||||||
|
reg byte x [ vblank::joy#0 ]
|
||||||
|
reg byte a [ vblank::$1 ]
|
||||||
|
reg byte a [ vblank::$3 ]
|
||||||
|
reg byte a [ vblank::$5 ]
|
||||||
|
reg byte a [ vblank::$7 ]
|
||||||
|
zp[1]:19 [ readJoy1::$1 ]
|
||||||
|
reg byte a [ readJoy1::$2 ]
|
@ -71,6 +71,8 @@ Inlined call call ppuDataPut *((byte*) ppuDataPutTile::tile + (number) 2)
|
|||||||
Inlined call call ppuDataPut *((byte*) ppuDataPutTile::tile + (number) 3)
|
Inlined call call ppuDataPut *((byte*) ppuDataPutTile::tile + (number) 3)
|
||||||
Inlined call call ppuDataPrepare (nomodify void*) ppuDataSet::ppuData
|
Inlined call call ppuDataPrepare (nomodify void*) ppuDataSet::ppuData
|
||||||
Inlined call call ppuDataPut (byte) ppuDataSet::val
|
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 initNES
|
||||||
Inlined call call enableVideoOutput
|
Inlined call call enableVideoOutput
|
||||||
Inlined call call ppuSpriteBufferDmaTransfer (const struct SpriteData*) SPRITE_BUFFER
|
Inlined call call ppuSpriteBufferDmaTransfer (const struct SpriteData*) SPRITE_BUFFER
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
"print.h": "c",
|
"print.h": "c",
|
||||||
"printf.h": "c",
|
"printf.h": "c",
|
||||||
"c64.h": "c"
|
"c64.h": "c"
|
||||||
}
|
},
|
||||||
|
"kickassembler.assemblerJar": "/Applications/KickAssembler/KickAss.jar"
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user