HN2new | past | comments | ask | show | jobs | submitlogin
cat mario.nes | nc play-nes.org 4444 (github.com/henrikpersson)
265 points by coderpersson on March 12, 2023 | hide | past | favorite | 73 comments


> let cart = Cartridge::blow_dust("path/to/rom.nes")?;

I chuckled.


That's like those objected-oriented programming examples you get in college, from professors who learned in the 90s and literally think in terms of "modelling" real objects with OOP.


Nothing wrong with modelling your real world business objects with OOP. Thats essentially what Domain Driven Design(https://en.wikipedia.org/wiki/Domain-driven_design) is. It's difficult to pull off sometimes but this is the ideal usage of OOP.


That's still how most OOP tutorials do it tho. It's an industry-wide disease


To be fair they may actually know there stuff but from a didactic point-of-view it is very difficult introduce a `FactoryProvider` (or to a lesser extent even an `HTTPClient`) alongside basic OOP concepts.


Use real useful code example

Have Logger with StdoutLogger as basic example of it

Then FileLogger that extends it with few functions related to files

Then DBLogger with few functions related to logging to database

Then TestLogger for integrating with test framework


The title misquotes the link:

> stty -icanon && cat mario.nes - | nc play-nes.org 4444

stty makes the keyboard work, and "-" is needed after .nes.


Save you a couple characters of typing

    < mario.nes nc play-nes.org 4444


I saw this too, but both the title and your command don't work to play the game.

The actual command is "cat mario.nes - | nc ...”

The trailing dash allows you to actually control the game after the rom has been loaded.


I was sincerely hoping I wouldn't be the first person to notice the useless use of cat. https://en.m.wikipedia.org/wiki/Cat_(Unix)#Useless_use_of_ca...


I’ve run across comments regarding useless use of cat twice today. However, after reading the linked Wikipedia entry, it feels more like a way to give someone an ego trip than a truly more useful alternative.

The Wikipedia article even concedes that cat might be better:

> A cat written with UUOC might still be preferred for readability reasons, as reading a piped stream left-to-right might be easier to conceptualize.[10] Also, one wrong use of the redirection symbol ">" instead of "<" (often adjacent on keyboards) may permanently delete the content of a file, in other words clobbering, and one way to avoid this is to use cat with pipes.

I‘ll happily continue to “abuse cat” going forward and sleep perfectly well.


Yeah, I read the wiki article to learn a new trick and when reading that paragraph, I've gained more confidence in continuing to use cat :)


I often write cat as a first element of a pipeline, then replace it with head/tail, or grep when I need to narrow it down.

"oh but you can save one character" (one coz <> requires shift) yeah fuck that, if I was bothered with it I'd alias cat to c


Or pv


Hopefully this[0] should be the last word on "useless" uses of cat

> When I offer a pipeline as a solution I expect it to be reusable. It is quite likely that a pipeline would be added at the end of or spliced into another pipeline. In that case having a file argument to grep screws up reusability, and quite possibly do so silently without an error message if the file argument exists. I. e. `grep foo xyz | grep bar xyz | wc` will give you how many lines in xyz contain bar while you are expecting the number of lines that contain both foo and bar. Having to change arguments to a command in a pipeline before using it is prone to errors. Add to it the possibility of silent failures and it becomes a particularly insidious practice.

[0] https://stackoverflow.com/a/16619430/1040915


No such thing as "last word" :)

See Jonathan Leffler's comment on SO (also demonstrated by the the top-level parent comment here):

> As noted in the answer by kojiro, it is perfectly possible and legal to start the pipeline with `< file command1 ...`. Although the conventional position for the I/O redirection operators is after the command name and its arguments, that is only the convention and not a mandatory placement. The `<` does have to precede the file name. So, there's a close to perfect symmetry between `>output` and `<input` redirections: `<input command1 -opt 1 | command2 -o | command3 >output`.


Sure, and as another answerer of that SO question points out[0]:

> We are used to read from left to right, so a command like

> `cat infile | process1 | process2 > outfile`

> is trivial to understand.

> `process1 < infile | process2 > outfile`

> has to jump over process1, and then read left to right. This can be healed by:

> `< infile process1 | process2 > outfile`

> looks somehow, as if there were an arrow pointing to the left, where nothing is.

Sure, you can have the inputfile precede the process, but then you have to precede _that_ with a glyph which appears to suggest "send this data to the preceding command". You know and I know that that's not what `<infile` really means, but I claim (and others are free to subjectively disagree) that, in the context of an exploratory gradually-incrementing bash query, the extra brain cycles to remember what `<infile` really means are not worth the extra compute cycles of the extra process of a "useless" cat.

To someone who's fully internalized the workings of the shell, then sure, using `<infile` is _technically_ more efficient, at the expense of being less readable to less-experienced engineers. The tradeoff between readability and performance is always a case-by-case decision.

[0] https://stackoverflow.com/a/49254166/1040915


It’s not useless because it’s able to accomplish the same without having to memorize yet another syntax trick.

- Someone who knows the trick


It's a basic shell feature that every terminal user should know from day 1. Hardly a "trick".


There is room for other interpretations, but I'd say if it's super common for people to not know something, which appears to describe this, it doesn't meet the definition of basic.

I'd say "basic" shell knowledge is that commands or programs produce output which is where many stop and why it's common to use cat this way.

In general I tend to err less on the side of "you're holding it wrong" gatekeeping in tech and when there's a common issue with something, blame the tech rather than the users. Maybe the way shell handles input, output, and redirection isn't intuitive and poorly designed. For those that already know there's an ego thing going on condescending to users who haven't learned as much that prevent honest or productive conversations on these topics.


> In general I tend to err less on the side of "you're holding it wrong" gatekeeping in tech

That's not gatekeeping. I'm pretty sure anyone that points out `<` would like anyone that doesn't know it to become familiar with it. That's precisely why they mention it. To gatekeep would be for someone to say that people that aren't familiar with it shouldn't have access to the shell. No one is saying that.

> There is room for other interpretations, but I'd say if it's super common for people to not know something, which appears to describe this, it doesn't meet the definition of basic. I'd say "basic" shell knowledge is that commands or programs produce output which is where many stop and why it's common to use cat this way.

I feel that's the same bar as saying that knowing how to use a keyboard and mouse is not basic because most people just learn to use their phone's touch interface, given how there's now a lot of people that have a smartphone but not a computer. I don't mean in our circles, but in general.

What's probably going on is that the boundary between basic and intermediate probably moves depending on increased adoption with different proportions of motivations. That is, most learners of the shell before were probably motivated to use it as their main interface, later one of their main interfaces, and now maybe there's a lot of people that need to run a command or 2 but don't really want to use it as an interface at all, so they never bother to learn beyond the most absolute minimum they need to.

> Maybe the way shell handles input, output, and redirection isn't intuitive and poorly designed.

I don't think being intuitive is always the most important criteria to something being well designed. Many things imply trade-offs, and for example if the average potential user values versatility over intuitiveness, and there's a tradeoff to be made between the 2, it's ok to not go for the intuitive option.

That said, the redirection operators seem as intuitive as they can be. Arrow from file to command for input, arrow from command to file for output. What's a better alternative? To just remove file redirection features and leave piping?

Processes will have inheritable file descriptors. Right now, the easiest and quickest way to make ad-hoc arbitrary arrangements of file descriptors is with the shell's file redirection features. Doing it on anything else (Python, C, whatever) requires more code. That seems like successful design to me.


> It's a basic shell feature that every terminal user should know from day 1. Hardly a "trick".

> That's not gatekeeping. I'm pretty sure anyone that points out `<` would like anyone that doesn't know it to become familiar with it.

Can't see it being pointed out here. No snark intended.


I'm not that person, so I don't know how they meant themselves to be interpreted. I interpret their comment as correcting the fact that file redirection is not a trick but a basic/core feature and emphasize that with their hyperbole of everyone knowing it from day one. I don't think they mean to dissuade people from using the shell. I don't think they mean their statement in the way of "if you didn't know this, you're not a real terminal user. Get out of here". Maybe I'm wrong and that was their motivation. I don't know.

I was also interpreting user3939382's use of gatekeeping in the context of other similar comments not just the one they were directly replying to. That's probably my mistake.


Hardly "basic", natural assumption after knowing what say

    date > file
does is assuming "there needs to be data source on left side, and target file on the right side

Similiar with

   wc < file
"There needs to be receiver program on the left side, and file on the right"

The assumption from seeing it is "program on left, data on right"

   < file wc
breaks that assumption completely.

Honestly I don't think that in 15+ years I ever saw that in the wild in any shell script


> Honestly I don't think that in 15+ years I ever saw that in the wild in any shell script

I've done it in shell scripts, very rarely interactively. In scripts, it sometimes just looks better defining that part first.

Wait until you see the redirect in the middle of program arguments. That's where it gets confusing. At least the redirect at the very beginning or very end of the line is easy. :)


"from day one", there's a lot of more important stuff to learn on day 1 than one "weird trick" that literally has no tangible benefits other than nerd sniping

I have more important things to worry about than making the line less readable and less maintainable


I have been aware of this feature for 20 year. I have also 20 years of muscle memory that makes me type the redundant cat. If you are used to it, it is hard to avoid and the benefit as minuscule. Also sometimes it makes it easer to extend the pipeline


It requires forethought in many cases. Cat-initiated pipelines can be built iteratively in a natural fashion.


What's natural about cat on only one file?

> Briefly, here's the collected wisdom on using cat:

> The purpose of cat is to concatenate (or "catenate") files. If it's only one file, concatenating it with nothing at all is a waste of time, and costs you a process. The fact that the same thread ("but but but, I think it's cleaner / nicer / not that much of a waste / my privelege to waste processes!") springs up virtually every time the Award is posted is also Ancient Usenet Tradition.

https://porkmail.org/era/unix/award


> What's natural about cat on only one file?

It's about building the query, really. Here is example:

    cat file.log
"Oh, it's too big, I only care about these messages"

    cat file.log |grep error_name
"don't care about old stuff, show me the new one"

    cat file.log |grep error_name | tail
"hmm, show me when it started, and let's ignore monitoring checks"

    cat file.log |grep error_name | grep -v 'user: mon'| head
"okay, but maybe log was rotated ? Let's see last week"

    zcat file.log.1 |grep error_name | grep -v 'user: mon'| head
"hmm, it's some old error, let's search some more logs"

    zcat file.log.{10..1} |grep error_name | grep -v 'user: mon'| head
(zcat will auto add .gz if not passed)

You can't for example do

    < file.log.{1..10} zcat


That's a lot of extra processes!

There's also zgrep: https://man.openbsd.org/OpenBSD-5.9/grep.1


And if you're in a situation where you care about the overhead of extra processes, you wouldn't be exploratively and iteratively constructing a query on the command-line - you'd have already done the exploration in order to understand exactly what query you needed, and then would be converting the query into a non-bash programming language for optimization.


> What's natural about cat on only one file?

What's natural about using tar to create .tar.gz files instead of using them to archive files to tape?

"cat is to catenate" sounds like an argument from people that need to get out and smell the flowers once in a while

From 'man cat'

> cat – concatenate and print files

So if I want to print a file to stdout, I'll use cat, thanks.


Of course it's reasonable to use cat on one file. Why should it work for all 𝑛≥2 files, but suddenly fail at 𝑛=1?

Despite the dismissive tone of the article you linked, if the overhead of one single process was remotely relevant, shell wouldn't be a good fit.


Yes, it should and does work for 1. That doesn't mean it's a good use of cat.


Catenating a file with the output stream is quite useful in many circumstances. Paged data isn't always wanted, and it's not generally known if filters are needed before the file is seen. Cat is the standard way to print to stdout.


It's not a trick by any means.


There is no such thing as useless use of cat in interactive shell. The rule (barely) matters in scripting.


Alas, another confidently incorrect comment on HN.


"Cloud gaming is the next big thing." --Links to Stadia shutdown notice

OP, I appreciated that bit


It's a funny joke, but imo Stadia shutting down has very little to do with the viability of cloud gaming as a business and a lot more to do with how google (mis)managed it.


Isn't this the regular story of Google though?

"Let me give a half effort on X product. Oh, see, nobody likes it. Well, guess I'll go ahead and shutter it."

It's a shame that products with so much potential have all the resources put into them wasted with their behavior.


I've seen it mentioned on here a lot that promotions/career stability inside google are heavily based around launching new products, and maintaining existing ones is kind of a dead end. Seems like the outcome reflects the incentives.


I could very well see that being the case. I could see it being somewhat of a reminant of their old start-up days.


I don't think it's because they're not putting enough effort into it.

Like most large organisation they tend to approximate a small government and they're inherently incapable of using their resources efficiently. Every once and then they will acquire a start-up that works to give new blood to the behemot.


> more to do with how google (mis)managed it.

Definitely this. The service itself was great, was ahead of the competition gameplay-wise. Google just did what Google does.


It's so frustrating to me from the perspective of a consumer because all someone needs to do is ship "Netflix, but for games" and they'll fucking kill. Charge a reasonable subscription fee but make the games free, and make sure everyone is aware of what it is and what it does.

Stuff like GEForce Now is already great for that "core" gamer market that wants to be able to use their existing steam library but play them on their phone on the go or whatever, but that's a pretty small market because most "core" gamers would never use a streaming service as their primary system so the market is fairly small (latency, resolution, quality etc is poor compared to native).

But nobody has properly targeted that more general "I want to play games with zero up front effort or knowledge" case yet. And I suspect that's a pretty big market.


Xbox Game Pass is close to that.

I think part of the problem is the game studios and publishers have enjoyed immense profits, that have continued to grow. Nintendo just upped their base price to $70. I don't think they will let that level of profit go easily.


Love it, but in my experience geforce now makes it so I don't need a GPU anymore. I can play any (supported) game on my macbook air with a controller connected to it, with VERY little lag. It blows my mind every time.


i'm just getting regular mario, how do i get cat mario?



You need to wait for the terminal WiiU emulator.


You need a Switch emulator for that


ApplePy experimented with providing a client-server model years ago for the 6502: https://github.com/jtauber/applepy

It's great to see somebody picking up the idea again and extending it.

It's a cool idea. Lots of possibilities for fun RPC projects with distributed processing.

Remotely accessible 80-column cards and custom mappers FTW, eh?

Good reminder that projects are meant to be implemented.


The Commodore 64 had a client-server model for the 6502: The 1541 disk drive was attached by a serial port and ran on a 6502, and provided a "command" to write to the 1541 RAM so you could run code on it.

(Yes, this isn't entirely serious, but people could and did make use of it)


Doesn't seem to work on Gnome terminal Version 3.44.0 The rom loaded to the site UI in nc no problem, and I selected Sixel (option 1), but nothing is happening


That would be because GNOME Terminal doesn't support sixel graphics.

https://www.arewesixelyet.com/#gnome-terminal

Looks like if you build the latest libvte from master and make sure to explicitly enable sixel support via the appropriate build time flag, you can then build GNOME Terminal against that and you'll have sixel support:

https://gitlab.gnome.org/GNOME/vte/-/issues/253


Ah, thanks. I made the mistake of assuming any modern terminal would/should by default.


Yep! It's surprising to me, too, how recently (within the past 4 years, by my estimation) there has been an intense, renewed interest in sixel.

It has coincided with the creation of a lot of new terminal emulators (some of the youngest have the most support for sixel and similar features), and with the trend of using GPU acceleration in terminal emulators.

I couldn't exactly say 'why now', but one guess is that macOS' explosion in popularity among developers and the relatively high popularity of desktop Linux within the developer community in particular have produced a generation of developers who appreciate the power and flexibility of the Unix command line but have also grown up with rich graphics on their computers from the start.

There's clearly a strong contemporary desire for a more IDE-like terminal experience, and for graphically enriched tools that are still decidedly text-centric. Efforts to establish new standards and protocols for this have mostly withered or seen little uptake, so resurrecting support for (today) rarely-used features of old physical terminals has emerged as a viable approach for adding graphics to our CLI environments.

Maybe some day we'll escape from the 80s, but for now it seems that we are still returning to them to find 'new' material, for various practical reasons.


> I couldn't exactly say 'why now', but one guess is that macOS' explosion in popularity among developers and the relatively high popularity of desktop Linux within the developer community in particular have produced a generation of developers who appreciate the power and flexibility of the Unix command line but have also grown up with rich graphics on their computers from the start

This so much!

I mostly have 2 apps running: Edge and a terminal. On windows, this terminal is mintty (wonderful!) or Windows Terminal (no sixel support yet).

On wayland, I use foot or wezterm. I need plots, and it's much faster to use gnuplot without leaving the terminal

When I need more, I open excel or rstudio. Excel cells are very text centric, and likewise for Rstudio chunks.

> Maybe some day we'll escape from the 80s, but for now it seems that we are still returning to them to find 'new' material, for various practical reasons.

I use notebooks for literate programming. It seems new? (as in, I don't think it was done in the 80s)

I wouldn't say embedding graphical content is a return to the 80s, but more like making a new mashup taking the best of the old (command line interface= minimalist yet powerful) and the recent (graphics= high information density) to go beyond the limitations of each.


> I use notebooks for literate programming. It seems new? (as in, I don't think it was done in the 80s)

I've done a bit of the same with Emacs via Org-mode and Babel, and I want to do more! Literate programming (and even literate DevOps!) is great.

If it's picking up these days, I think that's wonderful. But the idea is indeed from 1984 (via Knuth)! So in that way, the resurgence of literate programming is the result of mining the ancient computing past for great ideas we've not yet done enough justice as an industry/practice/science. :)

> I wouldn't say embedding graphical content is a return to the 80s, but more like making a new mashup taking the best of the old (command line interface= minimalist yet powerful) and the recent (graphics= high information density) to go beyond the limitations of each.

I wrote what I wrote without any real pessimism. I think there's a lot that's still great about old technology, like Unix or Lisp.

In terms of really 'escaping from the 80s' I had something narrower in mind, like the actual implementation details of retaining compatibility with old terminals and implementing new features via escape sequences and stuff like that. I think some day more of a clean slate could be more flexible or easier to hack on. (Which is, for me, just a hunch— I've never worked on a terminal emulator myself.) But even then, I think that 'escape' would still be as much about doing justice to old ideas as being able to let go of old implementation details.


> But the idea is indeed from 1984 (via Knuth)

Today I Learned :)

> I think some day more of a clean slate could be more flexible or easier to hack on. (Which is, for me, just a hunch— I've never worked on a terminal emulator myself.)

Not really. Please understand the old protocols (ex: sixels) as making you handle a required subset of the problems the new protocols (ex: kitty, etc) will also require you to handle (like storing the bitmap, invalidation, scrollback)

> But even then, I think that 'escape' would still be as much about doing justice to old ideas as being able to let go of old implementation details.

As long as I can get videos and plots along text in my terminal, I don't care if it's old or new: it just enables me to do more :)


Give any sixel-less terminal the sixel-tmux googles and you'll see an ascii rendition of the sixel images: https://github.com/csdvrx/sixel-tmux

It's not ideal unless you use a very small font, but it's better than nothing.

BTW some people recompile libvte to get proper sixel support in their favorite terminal: https://github.com/mate-desktop/mate-terminal/issues/410 and then get results like: https://www.youtube.com/watch?v=mLQbAYJGZMA


I tried option 2 and it didn't seem to do anything either.


I can't seem to select a render mode. It never gives me a chance to enter a number, I see the prompt ">" and then it immediately tells me I gave invalid input.


Adding the dash fixed it for me: cat mario.nes - | nc play-nes.org 4444

However, while i got the game to render, I couldn't get the game to respond to controls after that, so YMMV


Thanks, that did fix it! (Controls working fine too!)


Not sure what cat is supposed to do in this case. All I get is mario.nes: No such file or directory


.nes is the extension for a NES ROM.

Given you have a NES ROM named “mario.nes” in your current folder, you will play that ROM by executing the full command.

It literally reads the ROM file, what cat normally does.


cat is a command that reads one (or more) files from disk and outputs them either to the terminal or to a subsequent command if the pipe | is used.


I guess it wouldn't be capable of keeping saves for games such as Zelda. Would it?


Haven’t tried this, but sounds super cool I must say


I love this so much! rust is such a beautiful language!!!!




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: