HNHacker News
TopNewBestAskShowJobs

TapamN

468 karma · joined April 8, 2015

submissionscomments
TapamN··on The Framework is the most exciting laptop I've used
>when was the last time you used the right shift key?

I generally use the shift key closest to the key I'm typing. For keys near the center, I favor the right shift key.

The keyboard would absolutely be the show stopper for me, if I didn't just get a new laptop last year. The lack of dedicated Page Up and Page Down keys is unacceptable.

TapamN··on Apple testing new external display with A13 chip
Regular LCD displays last a long time, but OLED displays definitely wear out.

https://www.eevblog.com/forum/chat/oled-lifespan/

TapamN··on 12 Months, 850 Languages, 63 Fonts, No Waiting Or: Thank God for Google Noto
It's bad on desktop, too.

If I hit page down, it scrolls the size of the frame, and not my screen. The frame is taller than my screen, so page down scrolls more than a screen full. I would have to use arrow keys or the mouse wheel to read it.

I tried scaling the page down so that the frame fits on screen, but page down still scrolls too far, somehow?

TapamN··on PCG32: The Perfect PRNG for Roguelikes (2018)
That's true. I did think about mentioning this possibility, but decided not to.

Another good example of predicting RNG, after a large amount of gameplay, for a non-turn-based game:

https://www.youtube.com/watch?v=1hs451PfFzQ

I think in certain Pokemon games, people figured out how to predict and manipulate random encounters based on an animation in the load screen.

TapamN··on PCG32: The Perfect PRNG for Roguelikes (2018)
Does it need to pass them? A stronger algorithm wouldn't hurt, but it's not being used for cryptography or scientific simulations. It's just for games.

With the goal of having sharable seeds, the smaller space could be considered beneficial. The right tool for the job is more important. Even an 8-bit LFSR is good for certain tasks, like randomizing particle effects for an NES game.

TapamN··on Graphic Designers Have Always Loved Minimalism. But at What Cost?
Workaround:

View -> Page Style -> No Style

TapamN··on Sectorforth: A 16-bit x86 Forth that fits in a boot sector
That's actually been done. It's called StrongForth.

http://www.arestlessmind.org/2009/02/03/intro.html

TapamN··on C implementation of Tic-Tac-Toe in a single call to printf
That's not too unusual for IOCCC entries. Of the top of my head, there's a flight simulator shaped like an airplane, and an addition routine shaped like a full-adder.

A more subtle touch is that the #defines spell out NOUGHTs AnD CRoSSES.

TapamN··on No cookie consent walls, scrolling isn’t consent, says EU data protection body
This used to be a feature of Firefox. You could get a pop-up asking if you wanted to allow, allow for session, or disallow cookies from a domain the first time it tried to create a cookie. This was removed for some reason.
TapamN··on Ask HN: Smallest laptop that is decent for coding?
The Gemini might be better for dedicated programming. It's cheaper, and the Cosmo Communicator has terrible stand-by battery life (although usage doesn't significantly affect life). You would miss out on the light-up keyboard, though.
TapamN··on Obscure Features of JPEG (2011)
You would still have to read the entire JPEG in though, wouldn't you?

I'm not an expert on JPEG, but I think that if you want the macro blocks at the bottom of the image, you still need to un-Huffman the all the blocks before it to find where the macro blocks start (since AFAIK there isn't a table indicating where each block starts). That means you have to read the entire JPEG from storage, only to through away the vast majority of it.

Even if there was a way to magically predict where the low frequency values of the image are stored, you'd still have to do tens of thousands of random reads to just get to them. Reading the whole file would be faster.

So if you have 500 photos and you want to go though them and need some thumbnails, for non-progressive image thumbnail generation, you have to read 10 MB x 500 images = 5 GB of data, but with a progressive thumbnail you only need the first 100 KB x 500 images = 50 MB of data.

TapamN··on Obscure Features of JPEG (2011)
If you have time and space to pre-generate thumbnails, it's probably not a significant win, but I think it could work well for displaying local thumbnails of JPEGs, like from a camera.

If you're browsing a directory of hundreds of large (e.g. 10+ MB) JPEG photographs, generating the thumbnails by fully decompressing all of them would take while. "Progressive thumbnails" that only decompress the first ~100 KB would be much faster.

TapamN··on Super Mario World Memory Map
One thing that's interesting about this memory map is how much is crammed into the first 8KB of the SNES's 128 KB main RAM, while the rest is mainly used to store large blocks of uncompressed data. This is probably a remnant of how the SNES was originally designed have just 8KB of RAM. (http://www.chrismcovell.com/secret/SFC_1988Q4.html)
TapamN··on Almost everything on computers is perceptually slower than it was in 1983 (2017)
Not really. Here's what an 70's/80's PC and OS had to do to print a single character in response to user input (simpified):

Poll the keyboard matrix for a key press. Convert the key press coordinate to ASCII. Read the location of the cursor. Write one byte to RAM. Results will be visible next screen refresh.

A modern PC and OS would do something more like this:

The keyboard's microcontroller will poll the keyboard matrix for a key press. Convert the key press location to a event code. Signal to the host USB controller that you have data to send. Wait for the host to accept. Transfer the data to the USB host. Have the USB controller validate that the data was correctly received. Begin DMA from the USB controller to a RAM buffer. Wait the RAM to be ready. Transfer the data to RAM. Raise an interrupt to the CPU. Wait for the CPU to receive the interrupt. Task switch to the interrupt handler. Decode the USB packet. Pass it to the USB keyboard driver. Convert the USB keyboard event to an OS event. Determine what processes get to see the key press event. Add the event to the process's event queue. Task switch to the process. Read the new event. Filter the key press through all the libraries wrapping the OS's native event system. Read the location of the cursor. Ask the toolkit library to draw a character. Tell the windowing system to draw a character. Figure out what font glyph corresponds to that character. See if it's been cached, rasterize glyph if it's not. Draw the character to the window texture. Signal to the compositor that a region of the screen needs to be redrawn. Create a GPU command list. Have GPU execute command list. Page flip. Results will be visible next screen refresh.

I could drag this out longer and go into more detail, but I don't really feel like it.

I'm sure people who actually work on implementing these things can find inaccuracies with this, but it should give an idea how much more work and handshaking between components is being done now than in the 70's/80's. Switching to gaming hardware isn't enough to get down to ye olde latencies.

TapamN··on Coding for the World's Trickiest Chip – SEGA's Saturn DSP [video]
Well, not many DC emulators will run my code anymore, and eventually none will. :P On the DC, I used to use serial port with a USB adapter that manages 384k baud, but upgraded to a BBA several years ago.

I really, really, don't like the idea of doing a bunch of development on an emulator, then finding out it doesn't work right on real hardware (either not at all or with unexpectedly terrible performance) and having to figure out what all is going wrong. Doing it all on a real console means you find out immediately where any problems arise.

The Dreamcast tries to pretend to be like a PC, but treating it like one will seriously limit performance. The SH-4's terrible cache needs to be babied to get the most out of it, and there's a lot of unusual things you can do with the 3D hardware since it works very differently than other GPUs.

You can definitely do assembly on the DC, and it's really important for performance critical code. GCC can't use the SH-4's SIMD instructions effectively, so you have to use at least inline asm or true assembly. I'm not totally sure what you mean by "in very logical ways". I guess optimal SH-4 code doesn't look logical! Rendering-type code is harder on the SH-4 than the SH-2/3 because it's superscalar and FPU instructions have longer latency than ALU instructions. You have to spend more time figuring out how to hide latencies, and software pipelining becomes more important for performance. Optimal SH-4 assembler code ends up much messer looking than optimal SH-2/3 code.

For example, normalizing an array of 3D vectors in C, using inline assembly to use the inner product (FIPR) and square root reciprocal (FSRRA) instructions, you'd be lucky to get around 24-28 cycles per vector (it'd be even worse if you used pure vanilla C). But with software pipelined assembly, I can manage 8 cycles per vector.

But it's much more complex, not just because it's in assembler. The optimized main loop juggles normalizing 4 vectors at the same time (The loop is 32 cycles, with 4 vectors it averages 8 cycles per vector), and there's code to prepare the loop and exit the loop, and special case code for if there are fewer than 4 vectors to transform. The resulting machine code for the entire asm version is probably around 10 times the simple version.

Another example would be transforming a bunch of 4D vectors by a 4x4 matrix. C with inline asm will take about 16 cycles per vector, but optimized pure asm can do 4 cycles.

A 3D rendering engine I'm working on for the DC does software vertex shaders by basically copy & pasting optimized assembly loops into a single function and adding a bit of glue code between them.

TapamN··on Coding for the World's Trickiest Chip – SEGA's Saturn DSP [video]
I do Dreamcast homebrew (https://www.youtube.com/watch?v=2uZP9iOQc6E) (https://www.youtube.com/watch?v=MlFu-y1LDbs) and I've thought about trying Saturn homebrew, but getting code to run on a Saturn has been more difficult than running it on a Dreamcast.

With a DC, I just connect it to a computer through serial or ethernet, pop in a CD-R with a loader program, and I can easily upload and run code on it.

On the Saturn, getting a loader to run it much more difficult since it requires some kind of console modification (like disabling the disc-door state detection in order to allow disc swapping, or getting hold of a sold-out disc drive replacement) or an ISA-only PC Comms Link card and a Pro Action Replay. (I do happen to own a PAR, but not a Comms Link card and would rather avoid setting up ISA compatible hardware just for one purpose.) Testing on an emulator is a terrible idea, because you have no idea if it will work on real hardware, and I like trying to come up with ways to break emulators anyways, so that option's no good.

And... I was going to ask if you had any ideas for how to upload code in my situation, but I decided to search for "pc comms link saturn" while typing this and found a Bluetooth adapter for the PAR's comms port, so... I guess I just ordered one.

Actually, I've been working on an SH-2/3 assembly blitting library to run on the HP Jornada 690, a palmtop computer which has a 133 MHz SH3-DSP as the CPU. One of my goals for the library is for it to run on a 32X (which I actually don't own), and a Saturn is much closer to a 32X than the Jornada, so I'll be able to get a better idea of it's actual 32X performance this way.

And the Jornada really does use the DSP variant of the SH-3. I was disassembling the hardware initialization code of the boot ROM to figure out what it's memory timings were (to compare them to the 32X) and found it executing DSP instructions. I wrote a test program to double check, and it passed. The Jornada has a software modem, so the DSP capabilities are probably used for that.

TapamN··on Overturned polygons: shapes with less than two sides
I remember playing with LOGO (MicroWorlds, specifically) in 2nd or 3rd grade, and I was given code that would draw a n-sided polygon. I got the idea to draw polygons with weird numbers of sides (like a 0-sized polygon, or a polygon with a non-integer number of sides) and at one point I got a circle made with a dashed line (I'm pretty sure this was the 0-sided polygon).

It was (and still is) super confusing since it had no pen up commands at all, so everything should have been connected. I guess it couldn't handle the weird angles and distances it was being asked to draw.

TapamN··on GDPR for lazy people: Block all European users with Cloudflare Workers
It's pretty much trivial to reverse a hash when there are only 2^32 possible inputs.
TapamN··on OpenSC2K – An Open Source Remake of SimCity 2000
Terrain height just changes the Y position when where you draw. Draw order is still the same. The formula for tile map space to screen space is:

scrx = mapy16 - mapx16;

scry = mapx8 + mapy8 - GetSurfaceHeight(mapx,mapy)*12;

IIRC, this assumes origin is in top most tile, with increasing Y going down. So each step the terrain increases, you move the tile you draw up 12 pixels higher from the lowest point.

TapamN··on OpenSC2K – An Open Source Remake of SimCity 2000
I'm also actually working on an unreleased to-be-open-source SimCity 2000 clone in C++ (which I am planning to call 21st Century Micropolis, after the existing, official open-source SimCity Classic release called Micropolis), so I've looked into how SC2K renders the screen. I'll describe it for drawing the whole map, since it's simpler, but you'd want to modify it to draw only the visible parts in an actual game.

Directions are relative to the screen, not the grid.

10 Clear the screen and set a pointer to the top corner of the map

20 If the pointed tile belongs to terrain or the leftmost tile of a building, draw it on top of what we already have on screen. (Note that for tiles that belong to a building, but aren't the leftmost tile, we do nothing) (1x1 buildings always count as a leftmost tile)

30 If we are at the last row, exit

40 If we are at the end of the row, go to the leftmost tile of the row below, and jump to 20

50 Otherwise step one tile to the right, and jump to 20

That's it.

One wrinkle in getting the exact same output as the original has to do with the magic eraser tool, which basically hacks the map and forcibly resets a tile to it's blank state, even if it's supposed to belong to a building. If the leftmost tile of a 2x2, 3x3, or 4x4 building has been magically erased, the entire building disappears. If you magic erase a tile below the leftmost tile, or to the right of it, you will draw ground tiles over the building. Erasing tiles above the leftmost tile's waterline has no visible effect. Magically erased tiles can also have things built onto them. This algorithm gets these cases correct.

TapamN··on System76 ME Firmware Updates Plan
To compile to the same bit pattern binary, you'd need the same optimization settings (easy) with the same compiler (harder).

Intel can just give the source, but you can't trust Intel to just give you the same compiler they used, because the compiler might insert a backdoor. You'd need the compiler source, audit it for backdoors, then compile that with a trustworthy compiler. Then use the resulting compiler to compile the ME source.

(Compiler compiler compiler)

TapamN··on Seiko 80s Computer Watches (2005)
The page doesn't make it clear, but the watch doesn't run BASIC, the keyboard does. The watch just works as a screen. On it's own, the watch just has some basic databank (with 2K of RAM) and timekeeping features. It supposedly supports small programs running from RAM when disconnected from the keyboard, like the Timex Data Link's WristApps, but I can't find any real details on it.

A somewhat more detailed explanation of the watch is here: http://cdecas.free.fr/computers/pocket/uc2000.php

TapamN··on A Lighter and Smaller Laptop
These have been made (with the trackpoint replaced with a touchscreen + stylus), although you don't see them much nowadays. A examples would be the NEC MobilePro 900 (on the not-far-from-full-sized-keyboard end of the scale) and HP Jornada 6xx/7xx series (on the technically-pocket-sized-but-really-slightly-too-big scale).

I regularly use a Jornada 690, with Linux installed, which I use to do some programming on when doing things like taking my mom to her doctors appointments. I don't keep mine in my pocket, but have a small bag, intended to be attached the front handlebars of a bicycle, that I attach to my belt, to keep it in.

TapamN··on Resurrecting Duckhunt
Even the Sega Master System used that technique.
TapamN··on Adobe CEO desperately tries to avoid answering a simple question (2013)
No, he asks why digital downloads of Cloud-free products are more expensive, and specifically not boxed copies.

Here's a transcript of the first half of the video. Hopefully, I have not made any errors in the transcription. I have tried to remove "um"s and other filler to make it read better.

Interviewer: Mr. Narayen, just a question which I know my readers are universally asking me to ask you. How can Adobe possibility justify charging up to $1,400 dollars more for the exact same software delivered in Australia, delivered over the internet with no boxed copies, compared to US prices?

Narayen: When we look at the Creative Cloud, and where the future of Creative Cloud is that is--

I: [interrupting] We're not talking about Creative Cloud...

N: [continues talking, ignoring interruption] [portion unintelligible due to interruption] --with the company. And we think that's the best offering for customers. We really believe that if you look at what we've done to pricing there, it's actually a great value to our customers, and we think that's the future of the company, and I think it's a very attractive opportunity right now in terms of pricing.

I: There's a lot of companies, a lot of individuals, who don't want to buy Creative Cloud. They want to by Creative Suite, and the Creative Suite Master Collection is $1,400 more in Australia, but how can you possibly justify that when it's delivered over the internet?

N: I think it's important to remember that the Creative Cloud is not just for individuals, we just recently announced a Creative Cloud for teams. We think that the collaboration features that you have for Creative Cloud for teams is a better opportunity even for teams and for enterprises. When you think of the combination of what we're doing with the Creative Cloud and the marketing clout [not sure]... I think the message I'm trying to send all of you is that the Creative Cloud is the future of Creative. And when you look at the value that individuals all the way to large enterprises are getting through the Creative Cloud, we think that's phenomenal value for our customers.

I: What about the versions for customers who want to buy traditional versions of Creative Suite, which is still the majority of Adobe's business. I know you're talking a little bit about Creative Cloud being the future, but if that's that case, why not harmonize the prices of your traditional software?

N: When Adobe wants to make sure we attract the next generation... I, again, the future of Creative is the Creative Cloud.

I: I'm sorry, sir. You're really not answering the question.

TapamN··on Resurrecting the SuperH architecture
Compilers did use the shifter. I don't know if this is exactly what he was referring to, but one oddity with the SH4's dynamic shift instruction is that it only shifts to the left (there are also a limited number of shift-by-small constant (1,2,8,16) amount instructions). To shift to the right, you have to first negate the shift amount, then preform a left shift. So if use did a right shift by a non-constant, you would always see a negation of the shift amount before the shift. My guess as to why it was implemented like this was that since the SH4 had a fixed length, 2-byte instruction set, running out of possible instructions for future expansion was a real hazard, and not encoding both directions was done to save space.

On the original SH4 implementation, under certain conditions, there had to be one cycle in-between when a shift-amount was generated and when it was used, otherwise there would be a one-cycle CPU stall. A real right shift would avoid the need to schedule around this stall. This isn't necessarily something that needs an extra instruction to fix, the implementation could be designed to not need the stall, but it might difficult to work around. I don't to circuit design, but dynamic shift instructions typically look at as few bits in the shift amount to simplify and speed up the design of the shifter. The reason for the delay in the original SH4 is probably because it analysis and tags each register with information for the correct shift direction and amount, and certain units won't have this information ready for the shifter in time, hence the stall if the shift is too close the shift amount generation. (I've read this certain CPU implementations have done similar work in tagging if a register is zero or not, in order to help keep branch-on-zero/not-zero instructions quick.) If the instruction talked about is a dedicated right shift, it could be defined in a way that doesn't need a negation and extra tagging, would be much more compiler friendly, and faster.

← PreviousPage 4 of 4