Skip to content

Commit da45d35

Browse files
Forgot to push some changes lol
UxROM and AxROM, plus some bug fixes, plus some features
1 parent 32aed82 commit da45d35

10 files changed

Lines changed: 110 additions & 40 deletions

File tree

README.md

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,38 @@
11
<p align='center'><img src='https://github.com/nectarboy/nes/blob/main/src/img/pooptendo.png?raw=true'></p>
22
<h1 align='center'>Pooptendo</h1>
33

4-
This is Pooptendo, a Nintendo Entertainment System but stuffed inside with horse manure.
4+
This is Pooptendo, a Nintendo Entertainment System but stuffed inside with horse manure (emulator).
55
Games may or may not work when you plug them into this Pooptendo.
66

7-
Its a big WIP as you can prolly tell ... but some games work !<br>
7+
Pooptendo is mostly complete i think, most games i've tried work with few issues.<br>
88
[you can try it online :)](https://nectarboy.github.io/nes)
99

10-
## what about it ?
11-
Pooptendo kinda aims for cycle accuracy; i want most well known (and the fun) games to work, and the final boss is that difficult-to-emulate froggy game >:D
10+
## Features
11+
Pooptendo aims for accuracy but also makes some sacrifices for speed; i want most well known (and the fun) games to work, and the final boss is the froggy game Battle-Toads >:D (it runs! but it is a bit broken)
1212

13-
The CPU is cycle accurate, but there might be a few bugs lying around.<br>
14-
The PPU is emulated to the pixel level, though i sometimes make small sacrifices for speed, and there are still some missing stuff.<br>
13+
If your computer is new enough, most games should run at full speed, but stuttering does occur sometimes; if that happens, turn off frame-skip.
14+
15+
The CPU is cycle accurate, but there might be a few timing bugs lying around.<br>
16+
The PPU is emulated to the pixel level, though i sometimes make small sacrifices for speed, and there are still some missing features.<br>
1517
If issues show up though, (or if i manage to make it fast enough), i'll do my best to make it as accurate as i can :)
1618

17-
![super fuckin mario](https://github.com/nectarboy/nes/blob/main/docs/pics/Super_Mario_Bros/title.png?raw=true)
18-
![red panda <3](https://github.com/nectarboy/nes/blob/main/docs/pics/Homebrew/redpanda.png?raw=true)
19-
![donkey fuck](https://github.com/nectarboy/nes/blob/main/docs/pics/Mega_Man_2/title.png?raw=true)
19+
![super mario :)](https://github.com/nectarboy/nes/blob/main/docs/pics/Super_Mario_Bros/title.png?raw=true)
20+
![red panda :)](https://github.com/nectarboy/nes/blob/main/docs/pics/Homebrew/redpanda.png?raw=true)
21+
![mega man :)](https://github.com/nectarboy/nes/blob/main/docs/pics/Mega_Man_2/title.png?raw=true)
2022

21-
![super fuckin mario](https://github.com/nectarboy/nes/blob/main/docs/pics/Tetris/stack.png?raw=true)
22-
![red panda <3](https://github.com/nectarboy/nes/blob/main/docs/pics/Kirbys_Adventure/crane.png?raw=true)
23-
![donkey fuck](https://github.com/nectarboy/nes/blob/main/docs/pics/River_City_Ransom/sushi.png?raw=true)
23+
![tetris](https://github.com/nectarboy/nes/blob/main/docs/pics/Tetris/stack.png?raw=true)
24+
![kirby :)](https://github.com/nectarboy/nes/blob/main/docs/pics/Kirbys_Adventure/crane.png?raw=true)
25+
![sushi](https://github.com/nectarboy/nes/blob/main/docs/pics/River_City_Ransom/sushi.png?raw=true)
2426

2527
---
2628

27-
## functionality
29+
## Functionality
2830
```
29-
POOPTENDO STATUS :: horse manure is beginning to clear out
31+
POOPTENDO STATUS :: horse manure is clearing out
3032
```
3133

32-
Pooptendo is being written in JS atm, however, i wanna remake it in C sometime !
33-
(i hope i dont give up on that TwT)
34+
Pooptendo is written in JS atm, however I had plans to remake it in C.
35+
(This probably won't happen, I might start a new emulator in a language like C++)
3436

3537
### how to use
3638
Click <kbd>Choose File</kbd>to insert a ROM.
@@ -55,10 +57,10 @@ These are the default keybinds, they cannot be changed atm soz lol :3
5557

5658
### compatibility
5759
```
58-
- cpu (%95)
60+
- cpu (%95)
5961
- ppu (%90)
60-
- cartridge (%20)
61-
- apu (%25)
62+
- cartridge (%25)
63+
- apu (%80)
6264
- joypad (%90)
6365
- extra stuff (%0)
6466
- cool emu shit (%10)
@@ -67,7 +69,10 @@ These are the default keybinds, they cannot be changed atm soz lol :3
6769
Current mappers supported:
6870
- NROM
6971
- MMC1
72+
- MMC2
7073
- MMC3 (WIP)
74+
- UxROM
75+
- AxROM
7176

7277
### importing
7378
if you want to import Pooptendo to your site or something, first of all pls credit me :3, second of all:
@@ -76,7 +81,7 @@ import NES from './core/nes.js'; // Pooptendo is modular
7681

7782
var nes = new NES();
7883
nes.attachCanvas(canvas);
79-
nes.loadRomBuff(romBuff); // A Uint8Array buffer
84+
nes.loadRomBuff(romBuff); // A Uint8Array buffer with the ROM data
8085
nes.start();
8186
```
8287
By default, Pooptendo's default settings are:
@@ -89,6 +94,8 @@ Refer to `nes.js` in the core to figure out how to set it up to your liking :3
8994
---
9095

9196
### goodbye
97+
having more experience after my Game Boy emulator, this emulator is a little more refined and the codebase is cleaner. i probably won't update it much anymore, but overall it was very fun :)
98+
9299
thanks for checking out Pooptendo !
93100

94-
nectarboy | 2021-2022
101+
nectarboy | 2021-2023

docs/pics/Castlevania/castle.png

11.5 KB
Loading

index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ <h1>
4444
<input id='pitchshift' class='Range' type='range' max='30' min='-30' step='1' title='(NOTE: This alters actual APU timers)'>
4545

4646
<span id='frameskip' class='Button' title='(Turn this off if bad freezing or stuttering)'>Frameskip</span>
47+
<span id='antialias' class='Button' title='Toggle anti-aliasing'>Anti-Alias</span>
4748
<span id='fullscreen' class='Button' title='Toggle fullscreen'>Fullscreen</span>
4849
</div>
4950
<span id='minimize' class='SmallButton'><</span>

src/core/apu/apu.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ function Apu(nes) {
3232
const buffNumber = 5;
3333
this.buffNumber = buffNumber;
3434

35+
this.buffStep = 0;
3536
this.buffLength = length;
3637
this.sampleRate = sampleRate;
3738
for (i = 0; i < buffNumber; i++) {

src/core/mem/cartridge.js

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,47 @@ const Cartridge = function(nes, mem) {
263263
}
264264
};
265265

266+
// UxROM
267+
this.mappers[2] = {
268+
rombankaddr: new Array(2),
269+
270+
read(addr) {
271+
if (addr < 0x8000) {
272+
return 0; // (OPENBUS)
273+
}
274+
else {
275+
return mem.rom[((addr & 0x3fff) + this.rombankaddr[(addr & 0x7fff) >> 14]) & mem.romSizeMask]; // rom
276+
}
277+
// # # # amogus
278+
// # #
279+
// # # # #
280+
// # #
281+
},
282+
write(addr, val) {
283+
if (addr < 0x8000) {
284+
return 0; // (OPENBUS)
285+
}
286+
else {
287+
this.rombankaddr[0] = val << 14;
288+
}
289+
},
290+
readChr(addr) {
291+
return mem.chr[addr & mem.chrSizeMask];
292+
},
293+
writeChr(addr, val) {
294+
if (mem.hasChrRam) {
295+
mem.chr[addr & mem.chrSizeMask] = val; // 16KB CHR RAM
296+
}
297+
},
298+
299+
feedAddr(addr) {},
300+
301+
reset() {
302+
this.rombankaddr[0] = 0;
303+
this.rombankaddr[1] = mem.romSize - 0x4000;
304+
}
305+
};
306+
266307
// MMC3
267308
this.mappers[4] = {
268309
bankselected: 0,
@@ -538,7 +579,7 @@ const Cartridge = function(nes, mem) {
538579
}
539580
};
540581

541-
//this.mappers[4] = this.mappers[0]; // debug hehe
582+
this.mappers[90] = this.mappers[4]; // JY Company mapper
542583

543584
// AxROM
544585
this.mappers[7] = {

src/core/mem/mem.js

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -460,30 +460,36 @@ const Mem = function(nes) {
460460
this.cartramSizeMask = 0;
461461

462462
// Loading cart
463-
this.loadRomBuff = function(romBuff) {
464-
if (typeof romBuff !== 'object') {
463+
this.loadRomBuff = function(rombuff) {
464+
if (typeof rombuff !== 'object') {
465465
throw 'This is not a ROM!';
466466
return;
467467
}
468468

469-
var rom = new Uint8Array(romBuff);
470-
this.loadRomProps(rom);
469+
rombuff = new Uint8Array(rombuff);
470+
this.loadRomProps(rombuff);
471471
};
472472

473473
this.loadSaveBuff = function(savebuff) {
474+
if (typeof savebuff !== 'object') {
475+
throw 'This is not a SAVE!';
476+
return;
477+
}
478+
474479
if (!this.hasExtraRam) {
475-
throw 'ROM doesn\'t have save files!';
480+
throw 'This ROM doesn\'t have save files!';
476481
return false;
477482
}
478483

479484
savebuff = new Uint8Array(savebuff);
480485
var length = Math.min(savebuff.length, this.cartram.length);
486+
487+
this.cartram.fill(0);
481488
for (var i = 0; i < length; i++) {
482489
this.cartram[i] = savebuff[i];
483490
}
484491

485-
console.log('Loaded save file', savebuff);
486-
492+
console.log('Loaded save file');
487493
return true;
488494
};
489495

src/core/ppu/ppu.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,7 @@ const Ppu = function(nes) {
441441

442442
// Sprite rendering
443443
this.getSpritePixel = function(lx, px) {
444+
var lyMul256 = this.ly << 8;
444445
for (var i = 0; i < this.spritesThisLine; i++) {
445446
const oami = i << 2;
446447

@@ -457,15 +458,17 @@ const Ppu = function(nes) {
457458
var bit = (((this.sData[sdatai+1] >> shift) & 1) << 1) | ((this.sData[sdatai] >> shift) & 1);
458459

459460
if (bit) {
461+
var bgBitOpaque = this.bgMap[lyMul256 + lx] !== 0;
462+
460463
// Sprite 0 check
461464
if (!this.sprite0Atm && this.sNums[i] === 0) {
462465
this.sprite0Atm = true;
463466
this.sprite0Happened = true;
464467
}
465468

466469
// Priority check
467-
if (this.sAttr[i].priority && this.bgMap[this.ly * 256 + lx])
468-
continue;
470+
if (this.sAttr[i].priority && bgBitOpaque)
471+
return px;
469472

470473
var palMemAddr = 0x3f10 | (this.sAttr[i].pallete << 2) | bit;
471474

src/css/index.css

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ html, body {
3838
/* Settings */
3939
.FileButton, .Button, .SmallButton {
4040
font-family: arial;
41-
font-size: 13px;
41+
font-size: 12px;
4242

4343
position: relative;
4444
display: inline-block;
4545

46-
height: 28px;
47-
line-height: 28px;
46+
height: 24px;
47+
line-height: 24px;
4848
text-align: center;
4949

5050
user-select: none;
@@ -62,16 +62,13 @@ html, body {
6262

6363
.FileButton {
6464
display: ;
65-
width: 100px;
66-
height: 28px;
65+
width: 90px;
6766
}
6867
.Button {
69-
width: 80px;
70-
height: 28px;
68+
width: 70px;
7169
}
7270
.SmallButton {
73-
width: 28px;
74-
height: 28px;
71+
width: 24px;
7572
}
7673
.Range {
7774
user-select: none;

src/img/logo48.png

12 Bytes
Loading

src/index.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const saveinput = document.getElementById('saveinput');
1111
const settingsdiv = document.getElementById('settingsdiv');
1212
const minimize = document.getElementById('minimize');
1313
const fullscreen = document.getElementById('fullscreen');
14+
const antialias = document.getElementById('antialias');
1415
const frameskip = document.getElementById('frameskip');
1516
const pitchshift = document.getElementById('pitchshift');
1617
const pitchshiftreset = document.getElementById('pitchshiftreset');
@@ -78,6 +79,19 @@ fullscreen.onclick = function() {
7879
}
7980
};
8081

82+
// Anti-Alias
83+
var isantialias = false;
84+
antialias.onclick = function() {
85+
if (isantialias) {
86+
isantialias = false;
87+
canvas.style.imageRendering = 'pixelated';
88+
}
89+
else {
90+
isantialias = true;
91+
canvas.style.imageRendering = 'auto';
92+
}
93+
};
94+
8195
// Frameskip
8296
var isframeskip = nes.frameskip;
8397
frameskip.onclick = function() {

0 commit comments

Comments
 (0)